Decompiled source of CrimsonBanned v1.2.0

CrimsonBanned.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
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.Json.Serialization;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using CrimsonBanned.Commands;
using CrimsonBanned.Services;
using CrimsonBanned.Structs;
using CrimsonBanned.Utilities;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Microsoft.CodeAnalysis;
using ProjectM;
using ProjectM.Gameplay.Systems;
using ProjectM.Network;
using ProjectM.Physics;
using ProjectM.Scripting;
using ProjectM.Shared.Systems;
using Stunlock.Core;
using Stunlock.Network;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Scenes;
using UnityEngine;
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("CrimsonBanned")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Created with VRising.ModTemplate, you should edit this.")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+Branch.master.Sha.df056e8bb567652ccdeb5bf2d9fdcae755aa2320.df056e8bb567652ccdeb5bf2d9fdcae755aa2320")]
[assembly: AssemblyProduct("CrimsonBanned")]
[assembly: AssemblyTitle("CrimsonBanned")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[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 struct MessagePair
{
	public string Key { get; set; }

	public string Value { get; set; }

	public MessagePair(string key, string value)
	{
		Key = key;
		Value = value;
	}

	public string ToString(Ban ban, BanDetails details = null)
	{
		string value = Value;
		value = ((!string.IsNullOrEmpty(ban.PlayerName)) ? value.Replace("{player}", ban.PlayerName) : value.Replace("{player}", "<i>Unknown</i>"));
		value = value.Replace("{id}", ban.PlayerID.ToString());
		value = value.Replace("{issued}", ban.Issued.ToLocalTime().ToString("MM/dd/yy HH:mm"));
		value = ((!(ban.Reason == "") && !string.IsNullOrEmpty(ban.Reason)) ? value.Replace("{reason}", ban.Reason) : value.Replace("{reason}", "(None Provided)"));
		value = value.Replace("{by}", ban.IssuedBy);
		value = value.Replace("{local}", ban.LocalBan.ToString());
		value = ((details == null) ? value.Replace("{type}", "") : value.Replace("{type}", details.BanType));
		if (TimeUtility.IsPermanent(ban.TimeUntil))
		{
			value = value.Replace("{until}", "Permanent");
			return value.Replace("{remainder}", "Permanent");
		}
		value = value.Replace("{until}", ban.TimeUntil.ToLocalTime().ToString("MM/dd/yy HH:mm"));
		return value.Replace("{remainder}", TimeUtility.FormatRemainder(ban.TimeUntil.ToLocalTime()));
	}
}
namespace CrimsonBanned
{
	internal static class Core
	{
		public static Database Database;

		public static PlayerService PlayerService;

		private static MonoBehaviour MonoBehaviour;

		public static bool hasInitialized = false;

		public static World Server { get; } = GetServerWorld() ?? throw new Exception("There is no Server world (yet)...");


		public static EntityManager EntityManager => Server.EntityManager;

		public static ServerGameManager ServerGameManager => SystemService.ServerScriptMapper.GetServerGameManager();

		public static SystemService SystemService { get; } = new SystemService(Server);


		public static double ServerTime => ServerGameManager.ServerTime;

		public static ManualLogSource Log => Plugin.LogInstance;

		public static void Initialize()
		{
			if (!hasInitialized)
			{
				PlayerService = new PlayerService();
				Database = new Database();
				hasInitialized = true;
			}
		}

		private static World GetServerWorld()
		{
			return ((IEnumerable<World>)World.s_AllWorlds.ToArray()).FirstOrDefault((Func<World, bool>)((World world) => world.Name == "Server"));
		}

		public static void StartCoroutine(IEnumerator routine)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)MonoBehaviour == (Object)null)
			{
				MonoBehaviour = (MonoBehaviour)(object)new GameObject("CrimsonBanned").AddComponent<IgnorePhysicsDebugSystem>();
				Object.DontDestroyOnLoad((Object)(object)((Component)MonoBehaviour).gameObject);
			}
			MonoBehaviour.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(routine));
		}
	}
	internal static class Extensions
	{
		public delegate void ActionRef<T>(ref T item);

		private static EntityManager EntityManager => Core.EntityManager;

		private static ServerGameManager ServerGameManager => Core.ServerGameManager;

		private static SystemService SystemService => Core.SystemService;

		private static PrefabCollectionSystem PrefabCollectionSystem => SystemService.PrefabCollectionSystem;

		public 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_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)
			T item = entity.ReadRW<T>();
			action(ref item);
			EntityManager entityManager = EntityManager;
			((EntityManager)(ref entityManager)).SetComponentData<T>(entity, item);
		}

		public unsafe static void Write<T>(this Entity entity, T componentData) where T : struct
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			ComponentType val = default(ComponentType);
			((ComponentType)(ref val))..ctor(Il2CppType.Of<T>(), (AccessMode)0);
			byte[] array = StructureToByteArray(componentData);
			int num = Marshal.SizeOf<T>();
			fixed (byte* ptr = array)
			{
				EntityManager entityManager = EntityManager;
				((EntityManager)(ref entityManager)).SetComponentDataRaw(entity, val.TypeIndex, (void*)ptr, num);
			}
		}

		public static byte[] StructureToByteArray<T>(T structure) where T : struct
		{
			int num = Marshal.SizeOf(structure);
			byte[] array = new byte[num];
			IntPtr intPtr = Marshal.AllocHGlobal(num);
			Marshal.StructureToPtr(structure, intPtr, fDeleteOld: true);
			Marshal.Copy(intPtr, array, 0, num);
			Marshal.FreeHGlobal(intPtr);
			return array;
		}

		public unsafe static T ReadRW<T>(this Entity entity) where T : struct
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			ComponentType val = default(ComponentType);
			((ComponentType)(ref val))..ctor(Il2CppType.Of<T>(), (AccessMode)0);
			EntityManager entityManager = EntityManager;
			return Marshal.PtrToStructure<T>(new IntPtr(((EntityManager)(ref entityManager)).GetComponentDataRawRW(entity, val.TypeIndex)));
		}

		public unsafe static T Read<T>(this Entity entity) where T : struct
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			ComponentType val = default(ComponentType);
			((ComponentType)(ref val))..ctor(Il2CppType.Of<T>(), (AccessMode)0);
			EntityManager entityManager = EntityManager;
			return Marshal.PtrToStructure<T>(new IntPtr(((EntityManager)(ref entityManager)).GetComponentDataRawRO(entity, val.TypeIndex)));
		}

		public static DynamicBuffer<T> ReadBuffer<T>(this Entity entity) where T : struct
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			EntityManager entityManager = EntityManager;
			return ((EntityManager)(ref entityManager)).GetBuffer<T>(entity, false);
		}

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

		public static bool Has<T>(this Entity entity)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			ComponentType val = default(ComponentType);
			((ComponentType)(ref val))..ctor(Il2CppType.Of<T>(), (AccessMode)0);
			EntityManager entityManager = EntityManager;
			return ((EntityManager)(ref entityManager)).HasComponent(entity, val);
		}

		public static string LookupName(this PrefabGUID prefabGUID)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (!PrefabCollectionSystem.PrefabGuidToNameDictionary.ContainsKey(prefabGUID))
			{
				obj = "Guid Not Found";
			}
			else
			{
				string text = PrefabCollectionSystem.PrefabGuidToNameDictionary[prefabGUID];
				PrefabGUID val = prefabGUID;
				obj = text + " " + ((object)(PrefabGUID)(ref val)).ToString();
			}
			return obj.ToString();
		}

		public static void LogComponentTypes(this Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0041: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			EntityManager entityManager = EntityManager;
			Enumerator<ComponentType> enumerator = ((EntityManager)(ref entityManager)).GetComponentTypes(entity, (Allocator)2).GetEnumerator();
			Core.Log.LogInfo((object)"===");
			bool flag = default(bool);
			while (enumerator.MoveNext())
			{
				ComponentType current = enumerator.Current;
				ManualLogSource log = Core.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(0, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ComponentType>(current);
				}
				log.LogInfo(val);
			}
			Core.Log.LogInfo((object)"===");
		}

		public static void Add<T>(this Entity entity)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			ComponentType val = default(ComponentType);
			((ComponentType)(ref val))..ctor(Il2CppType.Of<T>(), (AccessMode)0);
			EntityManager entityManager = EntityManager;
			((EntityManager)(ref entityManager)).AddComponent(entity, val);
		}

		public static void Remove<T>(this Entity entity)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			ComponentType val = default(ComponentType);
			((ComponentType)(ref val))..ctor(Il2CppType.Of<T>(), (AccessMode)0);
			EntityManager entityManager = EntityManager;
			((EntityManager)(ref entityManager)).RemoveComponent(entity, val);
		}

		public static Entity GetOwner(this Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			ServerGameManager serverGameManager = ServerGameManager;
			return ((ServerGameManager)(ref serverGameManager)).GetOwner(entity);
		}

		public static bool TryGetFollowedPlayer(this Entity entity, out Entity player)
		{
			//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_0013: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			player = Entity.Null;
			if (entity.Has<Follower>())
			{
				Entity value = entity.Read<Follower>().Followed._Value;
				if (value.IsPlayer())
				{
					player = value;
					return true;
				}
			}
			return false;
		}

		public static bool TryGetPlayer(this Entity entity, out Entity player)
		{
			//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_0014: 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)
			player = Entity.Null;
			if (entity.Has<PlayerCharacter>())
			{
				player = entity;
				return true;
			}
			return false;
		}

		public static bool IsPlayer(this Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (entity.Has<VampireTag>())
			{
				return true;
			}
			return false;
		}

		public static bool IsFollowingPlayer(this Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (entity.Has<Follower>() && entity.Read<Follower>().Followed._Value.IsPlayer())
			{
				return true;
			}
			return false;
		}

		public static Entity GetBuffTarget(this Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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)
			return CreateGameplayEventServerUtility.GetBuffTarget(EntityManager, entity);
		}

		public static Entity GetPrefabEntity(this Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			ServerGameManager serverGameManager = ServerGameManager;
			return ((ServerGameManager)(ref serverGameManager)).GetPrefabEntity(entity.Read<PrefabGUID>());
		}

		public static Entity GetSpellTarget(this Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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)
			return CreateGameplayEventServerUtility.GetSpellTarget(EntityManager, entity);
		}

		public static Entity GetTeamEntity(this Entity entity)
		{
			//IL_0000: 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_0008: 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)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (entity.Has<TeamReference>())
			{
				return entity.Read<TeamReference>().Value._Value;
			}
			return Entity.Null;
		}

		public static bool Exists(this Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			EntityManager entityManager = EntityManager;
			return ((EntityManager)(ref entityManager)).Exists(entity);
		}

		public static bool Disabled(this Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return entity.Has<Disabled>();
		}

		public static ulong GetSteamId(this Entity entity)
		{
			//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)
			return entity.Read<PlayerCharacter>().UserEntity.Read<User>().PlatformId;
		}

		public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
		{
			foreach (T item in source)
			{
				action(item);
			}
		}

		public static bool TryGetPlayerInfo(this ulong steamId, out PlayerService.PlayerInfo playerInfo)
		{
			if (PlayerService.PlayerCache.TryGetValue(steamId.ToString(), out playerInfo))
			{
				return true;
			}
			return false;
		}

		public static bool TryGetPlayerInfo(this string playerName, out PlayerService.PlayerInfo playerInfo)
		{
			if (PlayerService.PlayerCache.TryGetValue(playerName, out playerInfo))
			{
				return true;
			}
			return false;
		}
	}
	[BepInPlugin("CrimsonBanned", "CrimsonBanned", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BasePlugin
	{
		private Harmony _harmony;

		public static Settings Settings;

		public static bool LogLoaded;

		internal static Plugin Instance { get; private set; }

		public static Harmony Harmony => Instance._harmony;

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

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

		public override void Load()
		{
			Instance = this;
			Settings = default(Settings);
			Settings.InitConfig();
			_harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
			CommandRegistry.RegisterAll();
			foreach (KeyValuePair<string, PluginInfo> plugin in ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins)
			{
				if (plugin.Value.Metadata.GUID.Equals("CrimsonLog"))
				{
					LogLoaded = true;
					break;
				}
			}
		}

		public override bool Unload()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			return true;
		}

		public static void LogMessage(string message, bool console = false)
		{
			if (LogLoaded && !console)
			{
				Type type = Type.GetType("CrimsonLog.Systems.Logger, CrimsonLog");
				if (type != null)
				{
					type.GetMethod("Record").Invoke(null, new object[3]
					{
						"Banned",
						"bans",
						message + "\n"
					});
					return;
				}
			}
			LogInstance.LogInfo((object)message);
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "CrimsonBanned";

		public const string PLUGIN_NAME = "CrimsonBanned";

		public const string PLUGIN_VERSION = "1.2.0";
	}
}
namespace CrimsonBanned.Utilities
{
	internal static class EntityUtilities
	{
		private static EntityManager EntityManager => Core.EntityManager;

		public static IEnumerable<Entity> GetEntitiesEnumerable(EntityQuery entityQuery)
		{
			//IL_0008: 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)
			NativeArray<Entity> entities;
			JobHandle entities2 = GetEntities(entityQuery, out entities, (Allocator)3);
			((JobHandle)(ref entities2)).Complete();
			try
			{
				Enumerator<Entity> enumerator = entities.GetEnumerator();
				while (enumerator.MoveNext())
				{
					Entity current = enumerator.Current;
					EntityManager entityManager = EntityManager;
					if (((EntityManager)(ref entityManager)).Exists(current))
					{
						yield return current;
					}
				}
			}
			finally
			{
				entities.Dispose();
			}
		}

		private static JobHandle GetEntities(EntityQuery entityQuery, out NativeArray<Entity> entities, Allocator allocator = 3)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: 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)
			//IL_000e: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			entities = ((EntityQuery)(ref entityQuery)).ToEntityArray(AllocatorHandle.op_Implicit(allocator));
			return default(JobHandle);
		}
	}
	public static class SQLConflict
	{
		public static async Task ResolveOfflines(List<Ban> list)
		{
			List<Ban> list2 = list.FindAll((Ban x) => x.DatabaseId == -1);
			foreach (Ban item in list2)
			{
				int num = SQLlink.AddBan(item, list);
				if (num >= 0)
				{
					item.DatabaseId = num;
				}
				else
				{
					await ResolveConflict(item, list);
				}
			}
		}

		public static async Task<int> ResolveConflict(Ban ban, List<Ban> list)
		{
			Ban ban2 = SQLlink.GetBan(ban.PlayerID, list);
			if (ban2 == null)
			{
				ManualLogSource logInstance = Plugin.LogInstance;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(40, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not find ban for ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ulong>(ban.PlayerID);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" in the database.");
				}
				logInstance.LogError(val);
				return -1000;
			}
			if (ban.DatabaseId != -1 && ban2.DatabaseId != -1 && ban.DatabaseId == ban2.DatabaseId)
			{
				list.Remove(ban);
				return 4;
			}
			if (ban.TimeUntil == ban2.TimeUntil)
			{
				list.Remove(ban);
				Database.AddBan(ban2, list);
				if (TimeUtility.IsPermanent(ban2.TimeUntil) && TimeUtility.IsPermanent(ban.TimeUntil))
				{
					return 0;
				}
				return 4;
			}
			if (TimeUtility.IsPermanent(ban2.TimeUntil))
			{
				list.Remove(ban);
				Database.AddBan(ban2, list);
				return 0;
			}
			if (IsExpiredBan(ban2))
			{
				return await ReplaceExistingBan(ban2, ban, list);
			}
			if (!TimeUtility.IsPermanent(ban2.TimeUntil) && TimeUtility.IsPermanent(ban.TimeUntil))
			{
				return await ReplaceExistingBan(ban2, ban, list);
			}
			if (ban.TimeUntil > ban2.TimeUntil)
			{
				return await ReplaceExistingBan(ban2, ban, list);
			}
			list.Remove(ban);
			Database.AddBan(ban2, list);
			return 1;
		}

		private static bool IsExpiredBan(Ban ban)
		{
			if (ban.TimeUntil < DateTime.UtcNow)
			{
				return !TimeUtility.IsPermanent(ban.TimeUntil);
			}
			return false;
		}

		private static async Task<int> ReplaceExistingBan(Ban oldBan, Ban newBan, List<Ban> list)
		{
			SQLlink.DeleteBan(oldBan, list);
			int databaseId = SQLlink.AddBan(newBan, list);
			newBan.DatabaseId = databaseId;
			Database.AddBan(newBan, list);
			return 2;
		}
	}
	public static class SQLUtility
	{
		private static bool IsSyncing;

		public static bool TrySQL()
		{
			return Database.SQL != null && Settings.UseSQL.Value && SQLlink.Connect();
		}

		public static async void SyncDB()
		{
			if (!TrySQL() || !SQLlink.Connect() || IsSyncing)
			{
				return;
			}
			IsSyncing = true;
			foreach (DeleteLater delete in Database.Deletes)
			{
				SQLlink.DeleteBan(delete.ID, delete.TableName);
			}
			Database.Deletes.Clear();
			if (File.Exists(Database.DeleteFile))
			{
				File.Delete(Database.DeleteFile);
			}
			await SyncTable(Database.ChatBans, "ChatBans");
			await SyncTable(Database.VoiceBans, "VoiceBans");
			await SyncTable(Database.Banned, "ServerBans");
			Database.SaveDatabases();
			IsSyncing = false;
		}

		private static async Task SyncTable(List<Ban> list, string tableName)
		{
			if (ValidateSync(list, tableName))
			{
				await SQLConflict.ResolveOfflines(list);
				DataTable sortedTableFromDatabase = GetSortedTableFromDatabase(tableName);
				HandleRemovedBans(list, sortedTableFromDatabase);
				RemoveExpiredBans(sortedTableFromDatabase, tableName);
				SyncMissingBans(list, sortedTableFromDatabase);
			}
		}

		private static DataTable GetSortedTableFromDatabase(string tableName)
		{
			DataView defaultView = ((DataTable)Database.SQL.Select(tableName)).DefaultView;
			defaultView.Sort = "Id ASC";
			return defaultView.ToTable();
		}

		private static void HandleRemovedBans(List<Ban> list, DataTable sortedTable)
		{
			HashSet<int> bansByID = new HashSet<int>(from DataRow row in sortedTable.Rows
				select Convert.ToInt32(row["Id"]));
			list.RemoveAll((Ban ban) => !bansByID.Contains(ban.DatabaseId) && ban.DatabaseId != -1);
			if (list == Database.Banned)
			{
				Database.BanListFix(list.Where((Ban ban) => !bansByID.Contains(ban.DatabaseId) && ban.DatabaseId != -1).ToList());
			}
		}

		private static void RemoveExpiredBans(DataTable sortedTable, string tableName)
		{
			foreach (DataRow row in sortedTable.Rows)
			{
				DateTime dateTime = Convert.ToDateTime(row["TimeUntil"]);
				if (dateTime < DateTime.UtcNow && !TimeUtility.IsPermanent(dateTime))
				{
					SQLlink.DeleteBan(Convert.ToInt32(row["Id"]), tableName);
				}
			}
		}

		private static void SyncMissingBans(List<Ban> list, DataTable sortedTable)
		{
			foreach (DataRow row in sortedTable.Rows)
			{
				Ban ban = CreateBanFromRow(row);
				if (list.Any((Ban x) => x.DatabaseId == ban.DatabaseId))
				{
					continue;
				}
				if (IsPlayerAlreadyBanned(ban, list, out var existingBan))
				{
					if (TimeUtility.IsPermanent(ban.TimeUntil))
					{
						list.Remove(existingBan);
						AddBanToList(list, ban);
						continue;
					}
					if (TimeUtility.IsPermanent(existingBan.TimeUntil))
					{
						SQLlink.DeleteBan(ban, list);
						AddBanToList(list, existingBan);
						break;
					}
					if (ban.TimeUntil > existingBan.TimeUntil)
					{
						list.Remove(existingBan);
						AddBanToList(list, ban);
					}
					else
					{
						SQLlink.DeleteBan(ban, list);
						AddBanToList(list, existingBan);
					}
				}
				else
				{
					AddBanToList(list, ban);
				}
			}
		}

		private static bool IsPlayerAlreadyBanned(Ban ban, List<Ban> list, out Ban existingBan)
		{
			existingBan = list.Find((Ban x) => x.PlayerID == ban.PlayerID || (x.DatabaseId != -1 && x.DatabaseId == ban.DatabaseId));
			return existingBan != null;
		}

		private static Ban CreateBanFromRow(DataRow row)
		{
			return new Ban(row["PlayerName"].ToString(), Convert.ToUInt64(row["PlayerID"]), Convert.ToDateTime(row["TimeUntil"]), row["Reason"].ToString(), row["IssuedBy"].ToString())
			{
				Issued = Convert.ToDateTime(row["Issued"]),
				DatabaseId = Convert.ToInt32(row["Id"])
			};
		}

		private static void AddBanToList(List<Ban> list, Ban ban)
		{
			list.Add(ban);
			if (list == Database.Banned)
			{
				HandleServerBan(ban);
			}
		}

		private static void HandleServerBan(Ban ban)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (ban.PlayerID.TryGetPlayerInfo(out var playerInfo) && playerInfo.User.IsConnected)
			{
				Core.StartCoroutine(BanCommands.DelayKick(playerInfo));
			}
			if (File.Exists(Settings.BanFilePath.Value))
			{
				UpdateBanFile(ban);
			}
		}

		private static void UpdateBanFile(Ban ban)
		{
			if (!File.ReadAllLines(Settings.BanFilePath.Value).Contains(ban.PlayerID.ToString()))
			{
				File.AppendAllText(Settings.BanFilePath.Value, ban.PlayerID + Environment.NewLine);
			}
		}

		private static bool ValidateSync(List<Ban> list, string tableName)
		{
			if (Database.SQL == null)
			{
				return false;
			}
			if (!SQLlink.Connect())
			{
				return false;
			}
			if (list == null)
			{
				return false;
			}
			if (string.IsNullOrEmpty(tableName))
			{
				return false;
			}
			return true;
		}
	}
	public static class TimeUtility
	{
		public static readonly DateTime MinValueUtc = new DateTime(0L, DateTimeKind.Utc);

		public static string FormatRemainder(DateTime date)
		{
			return FormatRemainder(date - DateTime.Now);
		}

		public static string FormatRemainder(TimeSpan remainder)
		{
			string text = string.Empty;
			if (remainder.Days > 0)
			{
				text += $"{remainder.Days} day{((remainder.Days > 1) ? "s" : "")}, ";
			}
			if (remainder.Hours > 0)
			{
				text += $"{remainder.Hours} hour{((remainder.Hours > 1) ? "s" : "")}, ";
			}
			if (remainder.Minutes > 0)
			{
				text += $"{remainder.Minutes} minute{((remainder.Minutes > 1) ? "s" : "")}";
			}
			if (text.EndsWith(", "))
			{
				text = text.Substring(0, text.Length - 2);
			}
			return text;
		}

		public static TimeSpan LengthParse(int length, string denomination)
		{
			denomination = denomination.ToLower();
			string[] source = new string[5] { "minute", "minutes", "min", "mins", "m" };
			string[] source2 = new string[5] { "hour", "hours", "hrs", "hr", "h" };
			string[] source3 = new string[3] { "day", "days", "d" };
			denomination = (source.Contains(denomination) ? "m" : (source2.Contains(denomination) ? "h" : ((!source3.Contains(denomination)) ? "m" : "d")));
			return denomination switch
			{
				"m" => TimeSpan.FromMinutes(length), 
				"h" => TimeSpan.FromHours(length), 
				"d" => TimeSpan.FromDays(length), 
				_ => TimeSpan.FromMinutes(length), 
			};
		}

		public static bool IsPermanent(DateTime date)
		{
			if (date == DateTime.MinValue)
			{
				return true;
			}
			if (date == DateTime.MinValue.ToUniversalTime())
			{
				return true;
			}
			if (date == DateTime.MinValue.ToLocalTime())
			{
				return true;
			}
			if (date == MinValueUtc)
			{
				return true;
			}
			return false;
		}
	}
}
namespace CrimsonBanned.Structs
{
	public class Ban
	{
		public string PlayerName { get; set; }

		public ulong PlayerID { get; set; }

		[JsonConverter(typeof(JsonDateTimeConverter))]
		public DateTime TimeUntil { get; set; }

		public string Reason { get; set; }

		public string IssuedBy { get; set; }

		[JsonConverter(typeof(JsonDateTimeConverter))]
		public DateTime Issued { get; set; }

		public int DatabaseId { get; set; }

		public bool LocalBan { get; set; }

		public Ban(string playerName, ulong playerID, DateTime timeUntil, string reason, string issuedBy)
		{
			PlayerName = playerName;
			PlayerID = playerID;
			TimeUntil = new DateTime(timeUntil.Year, timeUntil.Month, timeUntil.Day, timeUntil.Hour, timeUntil.Minute, timeUntil.Second, DateTimeKind.Utc);
			Reason = reason;
			DateTime utcNow = DateTime.UtcNow;
			Issued = new DateTime(utcNow.Year, utcNow.Month, utcNow.Day, utcNow.Hour, utcNow.Minute, utcNow.Second);
			IssuedBy = issuedBy;
		}
	}
	public class JsonDateTimeConverter : JsonConverter<DateTime>
	{
		public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			DateTime dateTime = new DateTime(reader.GetDateTime().Ticks / 10000000 * 10000000);
			if (dateTime.Kind != DateTimeKind.Utc)
			{
				return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
			}
			return dateTime;
		}

		public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
		{
			writer.WriteStringValue(value.ToString("yyyy-MM-ddTHH:mm:ssZ"));
		}
	}
	internal class Database
	{
		public static readonly JsonSerializerOptions prettyJsonOptions = new JsonSerializerOptions
		{
			WriteIndented = true,
			IncludeFields = true
		};

		public static string BannedFile = Path.Combine(Plugin.ConfigFiles, "bans_server.json");

		public static string ChatBanFile = Path.Combine(Plugin.ConfigFiles, "bans_chat.json");

		public static string VoiceBanFile = Path.Combine(Plugin.ConfigFiles, "bans_voice.json");

		public static string MessageFile = Path.Combine(Plugin.ConfigFiles, "messages.json");

		public static string DeleteFile = Path.Combine(Plugin.ConfigFiles, "ignore.json");

		public static List<Ban> Banned;

		public static List<Ban> ChatBans;

		public static List<Ban> VoiceBans;

		public static List<MessagePair> Messages;

		public static List<DeleteLater> Deletes;

		public static dynamic SQL
		{
			get
			{
				if (!((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("CrimsonSQL", out var value))
				{
					return null;
				}
				return value.Instance.GetType().GetProperty("SQLService").GetValue(value.Instance);
			}
		}

		public Database()
		{
			LoadDatabases();
		}

		private static void LoadDatabases()
		{
			if (!Directory.Exists(Plugin.ConfigFiles))
			{
				Directory.CreateDirectory(Plugin.ConfigFiles);
			}
			if (File.Exists(ChatBanFile))
			{
				ChatBans = JsonSerializer.Deserialize<List<Ban>>(File.ReadAllText(ChatBanFile), prettyJsonOptions);
			}
			else
			{
				ChatBans = new List<Ban>();
			}
			if (File.Exists(VoiceBanFile))
			{
				VoiceBans = JsonSerializer.Deserialize<List<Ban>>(File.ReadAllText(VoiceBanFile), prettyJsonOptions);
			}
			else
			{
				VoiceBans = new List<Ban>();
			}
			if (File.Exists(BannedFile))
			{
				Banned = JsonSerializer.Deserialize<List<Ban>>(File.ReadAllText(BannedFile), prettyJsonOptions);
			}
			else
			{
				Banned = new List<Ban>();
			}
			if (File.Exists(DeleteFile))
			{
				Deletes = JsonSerializer.Deserialize<List<DeleteLater>>(File.ReadAllText(DeleteFile), prettyJsonOptions);
			}
			else
			{
				Deletes = new List<DeleteLater>();
			}
			if (File.Exists(MessageFile))
			{
				Messages = JsonSerializer.Deserialize<List<MessagePair>>(File.ReadAllText(MessageFile), prettyJsonOptions);
			}
			else
			{
				Messages = new List<MessagePair>(3)
				{
					new MessagePair("CheckHeader", "\n{player}'s ({id}) Bans:"),
					new MessagePair("CheckBanLine", "\n{type} Ban\nIssued: {issued}\nRemaining: {remainder}\nReason: {reason}"),
					new MessagePair("ListBan", "\n{player} ({id}) - {remainder}")
				};
				string contents = JsonSerializer.Serialize(Messages, prettyJsonOptions);
				File.WriteAllText(MessageFile, contents);
			}
			if (SQL != null && Settings.UseSQL.Value && SQLlink.Connect())
			{
				StartSQLConnection();
			}
			Core.StartCoroutine(Clean());
		}

		private static async void StartSQLConnection()
		{
			SQLlink.InitializeBanTables();
			await Task.Yield();
			SQLUtility.SyncDB();
			Core.StartCoroutine(SyncLoop());
		}

		public static void AddBan(Ban ban, List<Ban> list)
		{
			if (list.Exists((Ban x) => x.DatabaseId == ban.DatabaseId))
			{
				return;
			}
			string empty = string.Empty;
			if (list == ChatBans)
			{
				empty = "Chat";
				ChatBans.Add(ban);
			}
			else if (list == VoiceBans)
			{
				empty = "Voice";
				VoiceBans.Add(ban);
			}
			else
			{
				empty = "Server";
				Banned.Add(ban);
				if (File.Exists(Settings.BanFilePath.Value) && !File.ReadAllLines(Settings.BanFilePath.Value).Contains(ban.PlayerID.ToString()))
				{
					File.AppendAllText(Settings.BanFilePath.Value, ban.PlayerID + Environment.NewLine);
				}
			}
			string empty2 = string.Empty;
			string value = TimeUtility.FormatRemainder(ban.TimeUntil.ToLocalTime());
			empty2 = ((!ban.LocalBan) ? $"A player with ID: {ban.PlayerID} has had their {empty} ban synced from SQL. Originally issued by {ban.IssuedBy} with {value} remaining." : $"{ban.PlayerName} with ID: {ban.PlayerID} has been {empty} banned. Issued by {ban.IssuedBy} for {value}.");
			Plugin.LogMessage(empty2);
			SaveDatabases();
		}

		public static void DeleteBan(Ban ban, List<Ban> list)
		{
			string empty = string.Empty;
			if (list == ChatBans)
			{
				empty = "Chat";
				ChatBans.Remove(ban);
			}
			else if (list == VoiceBans)
			{
				empty = "Voice";
				VoiceBans.Remove(ban);
			}
			else
			{
				empty = "Server";
				Banned.Remove(ban);
				if (File.Exists(Settings.BanFilePath.Value))
				{
					List<string> list2 = File.ReadAllLines(Settings.BanFilePath.Value).ToList();
					list2.RemoveAll((string line) => line.Trim() == ban.PlayerID.ToString());
					File.WriteAllLines(Settings.BanFilePath.Value, list2);
				}
			}
			string empty2 = string.Empty;
			empty2 = ((!ban.LocalBan) ? $"{empty} ban has ended for synced player ID: {ban.PlayerID}." : (empty + " ban has ended for " + ban.PlayerName + "."));
			Plugin.LogMessage(empty2);
			if (SQLUtility.TrySQL())
			{
				SQLlink.DeleteBan(ban, list);
			}
			else if (SQL != null)
			{
				Deletes.Add(new DeleteLater(ban.DatabaseId, empty + "Bans"));
			}
			SaveDatabases();
		}

		public static void SaveDatabases()
		{
			if (ChatBans.Count > 0 || File.Exists(ChatBanFile))
			{
				string contents = JsonSerializer.Serialize(ChatBans, prettyJsonOptions);
				File.WriteAllText(ChatBanFile, contents);
			}
			if (VoiceBans.Count > 0 || File.Exists(VoiceBanFile))
			{
				string contents2 = JsonSerializer.Serialize(VoiceBans, prettyJsonOptions);
				File.WriteAllText(VoiceBanFile, contents2);
			}
			if (Banned.Count > 0 || File.Exists(BannedFile))
			{
				string contents3 = JsonSerializer.Serialize(Banned, prettyJsonOptions);
				File.WriteAllText(BannedFile, contents3);
			}
			if (Deletes.Count > 0 || File.Exists(DeleteFile))
			{
				string contents4 = JsonSerializer.Serialize(Deletes, prettyJsonOptions);
				File.WriteAllText(DeleteFile, contents4);
			}
		}

		private static IEnumerator SyncLoop()
		{
			while (true)
			{
				BanListFix();
				yield return (object)new WaitForSeconds((float)(Settings.SyncInterval.Value * 60 + Random.Range(-10, 20)));
				SQLUtility.SyncDB();
			}
		}

		public static void BanListFix(List<Ban> additional = null)
		{
			List<Ban> list = Banned.Where((Ban ban) => !TimeUtility.IsPermanent(ban.TimeUntil) && ban.TimeUntil < DateTime.UtcNow).ToList();
			if (additional != null)
			{
				list = list.Concat(additional).ToList();
			}
			foreach (Ban ban2 in list)
			{
				DeleteBan(ban2, Banned);
				if (File.Exists(Settings.BanFilePath.Value))
				{
					List<string> list2 = File.ReadAllLines(Settings.BanFilePath.Value).ToList();
					list2.RemoveAll((string line) => line.Trim() == ban2.PlayerID.ToString());
					File.WriteAllLines(Settings.BanFilePath.Value, list2);
				}
			}
		}

		private static IEnumerator Clean()
		{
			while (true)
			{
				yield return (object)new WaitForSeconds(60f);
				List<Ban> list = Banned.Where((Ban ban) => !TimeUtility.IsPermanent(ban.TimeUntil) && ban.TimeUntil < DateTime.UtcNow).ToList();
				List<Ban> list2 = ChatBans.Where((Ban ban) => !TimeUtility.IsPermanent(ban.TimeUntil) && ban.TimeUntil < DateTime.UtcNow).ToList();
				List<Ban> list3 = VoiceBans.Where((Ban ban) => !TimeUtility.IsPermanent(ban.TimeUntil) && ban.TimeUntil < DateTime.UtcNow).ToList();
				foreach (Ban item in list)
				{
					DeleteBan(item, Banned);
				}
				foreach (Ban item2 in list2)
				{
					DeleteBan(item2, ChatBans);
				}
				foreach (Ban item3 in list3)
				{
					DeleteBan(item3, VoiceBans);
				}
			}
		}
	}
	public struct DeleteLater
	{
		public int ID { get; set; }

		public string TableName { get; set; }

		public DeleteLater(int id, string tableName)
		{
			ID = id;
			TableName = tableName;
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public readonly struct Settings
	{
		private const string ConfigHeader = "_Config";

		private const string ServerHeader = "ServerConnection";

		private static readonly List<string> directoryPaths = new List<string>(1) { Plugin.ConfigFiles };

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

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

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

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

		public static void InitConfig()
		{
			foreach (string directoryPath in directoryPaths)
			{
				CreateDirectories(directoryPath);
			}
			ShadowBan = InitConfigEntry("_Config", "ShadowBan", defaultValue: false, "If this is set to true, the player will never be notified when chat or voice banned.");
			BanFilePath = InitConfigEntry("_Config", "BanFilePath", "save-data/Settings/banlist.txt", "The path from root to the banlist.txt file");
			if (Database.SQL != null)
			{
				UseSQL = InitConfigEntry("ServerConnection", "UseSQL", defaultValue: false, "If this is set to true, the plugin will use CrimsonSQL to store bans.");
				SyncInterval = InitConfigEntry("ServerConnection", "SyncInterval", 60, "The interval in minutes to sync the database.");
			}
		}

		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, "CrimsonBanned.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 CreateDirectories(string path)
		{
			if (!Directory.Exists(path))
			{
				Directory.CreateDirectory(path);
			}
		}
	}
	public static class SQLlink
	{
		public static void InitializeBanTables()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>
			{
				["Id"] = "INT AUTO_INCREMENT PRIMARY KEY",
				["PlayerName"] = "VARCHAR(255)",
				["PlayerID"] = "BIGINT UNSIGNED NOT NULL UNIQUE",
				["TimeUntil"] = "DATETIME NOT NULL",
				["Reason"] = "TEXT",
				["Issued"] = "DATETIME NOT NULL",
				["IssuedBy"] = "VARCHAR(255)"
			};
			Database.SQL.CreateTable("ServerBans", dictionary);
			Database.SQL.CreateTable("ChatBans", dictionary);
			Database.SQL.CreateTable("VoiceBans", dictionary);
		}

		public static int AddBan(Ban ban, List<Ban> list)
		{
			Dictionary<string, object> dictionary = new Dictionary<string, object>
			{
				["PlayerName"] = ban.PlayerName,
				["PlayerID"] = ban.PlayerID,
				["TimeUntil"] = ban.TimeUntil,
				["Reason"] = ban.Reason,
				["Issued"] = ban.Issued,
				["IssuedBy"] = ban.IssuedBy
			};
			string text = ((list == Database.ChatBans) ? "ChatBans" : ((list == Database.VoiceBans) ? "VoiceBans" : "ServerBans"));
			List<int> list2 = new List<int> { -1062, -1042 };
			int num = Database.SQL.Insert(text, dictionary, list2);
			if (num == -1042)
			{
				num = -1;
			}
			return num;
		}

		public static void DeleteBan(Ban ban, List<Ban> list)
		{
			Dictionary<string, object> dictionary = new Dictionary<string, object> { ["Id"] = ban.DatabaseId };
			string text = ((list == Database.ChatBans) ? "ChatBans" : ((list == Database.VoiceBans) ? "VoiceBans" : "ServerBans"));
			Database.SQL.Delete(text, dictionary);
		}

		public static void DeleteBan(int id, string tableName)
		{
			Dictionary<string, object> dictionary = new Dictionary<string, object> { ["Id"] = id };
			Database.SQL.Delete(tableName, dictionary);
		}

		public static Ban GetBan(ulong playerID, List<Ban> list)
		{
			Dictionary<string, object> dictionary = new Dictionary<string, object> { ["PlayerID"] = playerID };
			string text = ((list == Database.ChatBans) ? "ChatBans" : ((list == Database.VoiceBans) ? "VoiceBans" : "ServerBans"));
			dynamic val = Database.SQL.Select(text, new string[1] { "*" }, dictionary);
			if (val != null && val.Rows.Count > 0)
			{
				dynamic val2 = val.Rows[0];
				Ban ban = new Ban(val2["PlayerName"].ToString(), Convert.ToUInt64(val2["PlayerID"]), Convert.ToDateTime(val2["TimeUntil"]), val2["Reason"].ToString(), val2["IssuedBy"].ToString());
				ban.DatabaseId = Convert.ToInt32(val2["Id"]);
				ban.Issued = Convert.ToDateTime(val2["Issued"]);
				return ban;
			}
			return null;
		}

		public static bool Connect()
		{
			if (Database.SQL == null)
			{
				return false;
			}
			return Database.SQL.Connect();
		}
	}
}
namespace CrimsonBanned.Services
{
	internal class PlayerService
	{
		public class PlayerInfo
		{
			public User User { get; set; }

			public Entity UserEntity { get; set; }

			public Entity CharEntity { get; set; }

			public PlayerInfo(Entity userEntity = default(Entity), Entity charEntity = default(Entity), User user = default(User))
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: 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)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				User = user;
				UserEntity = userEntity;
				CharEntity = charEntity;
				base..ctor();
			}
		}

		private static readonly WaitForSeconds Delay = new WaitForSeconds(60f);

		private static readonly ComponentType[] UserComponent = (ComponentType[])(object)new ComponentType[1] { ComponentType.ReadOnly(Il2CppType.Of<User>()) };

		private static EntityQuery UserQuery;

		public static readonly Dictionary<string, PlayerInfo> PlayerCache = new Dictionary<string, PlayerInfo>();

		public static readonly Dictionary<string, PlayerInfo> OnlineCache = new Dictionary<string, PlayerInfo>();

		private static EntityManager EntityManager => Core.EntityManager;

		public PlayerService()
		{
			//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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			EntityManager entityManager = EntityManager;
			UserQuery = ((EntityManager)(ref entityManager)).CreateEntityQuery(UserComponent);
			Core.StartCoroutine(PlayerUpdateLoop());
		}

		private static IEnumerator PlayerUpdateLoop()
		{
			while (true)
			{
				PlayerCache.Clear();
				OnlineCache.Clear();
				(from entry in EntityUtilities.GetEntitiesEnumerable(UserQuery).Select(delegate(Entity userEntity)
					{
						//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_0020: 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_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_002c: Unknown result type (might be due to invalid IL or missing references)
						//IL_002d: Unknown result type (might be due to invalid IL or missing references)
						//IL_002e: Unknown result type (might be due to invalid IL or missing references)
						User val = userEntity.Read<User>();
						string value = ((FixedString64Bytes)(ref val.CharacterName)).Value;
						val.PlatformId.ToString();
						Entity entity = val.LocalCharacter._Entity;
						return new
						{
							PlayerNameEntry = new KeyValuePair<string, PlayerInfo>(value, new PlayerInfo(userEntity, entity, val))
						};
					}).SelectMany(entry => new KeyValuePair<string, PlayerInfo>[1] { entry.PlayerNameEntry })
					group entry by entry.Key).ToDictionary((IGrouping<string, KeyValuePair<string, PlayerInfo>> group) => group.Key, (IGrouping<string, KeyValuePair<string, PlayerInfo>> group) => group.First().Value).ForEach(delegate(KeyValuePair<string, PlayerInfo> kvp)
				{
					//IL_001f: Unknown result type (might be due to invalid IL or missing references)
					PlayerCache[kvp.Key] = kvp.Value;
					if (kvp.Value.User.IsConnected)
					{
						OnlineCache[kvp.Key] = kvp.Value;
					}
				});
				yield return Delay;
			}
		}
	}
	public class SystemService
	{
		private readonly World _world = world ?? throw new ArgumentNullException("world");

		private DebugEventsSystem _debugEventsSystem;

		private PrefabCollectionSystem _prefabCollectionSystem;

		private ServerGameSettingsSystem _serverGameSettingsSystem;

		private ServerScriptMapper _serverScriptMapper;

		private ModifyUnitStatBuffSystem_Spawn _modifyUnitStatBuffSystem_Spawn;

		private ModifyUnitStatBuffSystem_Destroy _modifyUnitStatBuffSystem_Destroy;

		private EntityCommandBufferSystem _entityCommandBufferSystem;

		private ClaimAchievementSystem _claimAchievementSystem;

		private GameDataSystem _gameDataSystem;

		private ScriptSpawnServer _scriptSpawnServer;

		private CombatMusicSystem_Server _combatMusicSystem_Server;

		private NameableInteractableSystem _nameableInteractableSystem;

		private ActivateVBloodAbilitySystem _activateVBloodAbilitySystem;

		private EndSimulationEntityCommandBufferSystem _endSimulationEntityCommandBufferSystem;

		private ReplaceAbilityOnSlotSystem _replaceAbilityOnSlotSystem;

		private UnEquipItemSystem _unEquipItemSystem;

		private EquipItemSystem _equipItemSystem;

		private Singleton _networkIdSystem_Singleton;

		public DebugEventsSystem DebugEventsSystem => _debugEventsSystem ?? (_debugEventsSystem = GetSystem<DebugEventsSystem>());

		public PrefabCollectionSystem PrefabCollectionSystem => _prefabCollectionSystem ?? (_prefabCollectionSystem = GetSystem<PrefabCollectionSystem>());

		public ServerGameSettingsSystem ServerGameSettingsSystem => _serverGameSettingsSystem ?? (_serverGameSettingsSystem = GetSystem<ServerGameSettingsSystem>());

		public ServerScriptMapper ServerScriptMapper => _serverScriptMapper ?? (_serverScriptMapper = GetSystem<ServerScriptMapper>());

		public ModifyUnitStatBuffSystem_Spawn ModifyUnitStatBuffSystem_Spawn => _modifyUnitStatBuffSystem_Spawn ?? (_modifyUnitStatBuffSystem_Spawn = GetSystem<ModifyUnitStatBuffSystem_Spawn>());

		public ModifyUnitStatBuffSystem_Destroy ModifyUnitStatBuffSystem_Destroy => _modifyUnitStatBuffSystem_Destroy ?? (_modifyUnitStatBuffSystem_Destroy = GetSystem<ModifyUnitStatBuffSystem_Destroy>());

		public EntityCommandBufferSystem EntityCommandBufferSystem => _entityCommandBufferSystem ?? (_entityCommandBufferSystem = GetSystem<EntityCommandBufferSystem>());

		public ClaimAchievementSystem ClaimAchievementSystem => _claimAchievementSystem ?? (_claimAchievementSystem = GetSystem<ClaimAchievementSystem>());

		public GameDataSystem GameDataSystem => _gameDataSystem ?? (_gameDataSystem = GetSystem<GameDataSystem>());

		public ScriptSpawnServer ScriptSpawnServer => _scriptSpawnServer ?? (_scriptSpawnServer = GetSystem<ScriptSpawnServer>());

		public CombatMusicSystem_Server CombatMusicSystem_Server => _combatMusicSystem_Server ?? (_combatMusicSystem_Server = GetSystem<CombatMusicSystem_Server>());

		public NameableInteractableSystem NameableInteractableSystem => _nameableInteractableSystem ?? (_nameableInteractableSystem = GetSystem<NameableInteractableSystem>());

		public ActivateVBloodAbilitySystem ActivateVBloodAbilitySystem => _activateVBloodAbilitySystem ?? (_activateVBloodAbilitySystem = GetSystem<ActivateVBloodAbilitySystem>());

		public EndSimulationEntityCommandBufferSystem EndSimulationEntityCommandBufferSystem => _endSimulationEntityCommandBufferSystem ?? (_endSimulationEntityCommandBufferSystem = GetSystem<EndSimulationEntityCommandBufferSystem>());

		public ReplaceAbilityOnSlotSystem ReplaceAbilityOnSlotSystem => _replaceAbilityOnSlotSystem ?? (_replaceAbilityOnSlotSystem = GetSystem<ReplaceAbilityOnSlotSystem>());

		public UnEquipItemSystem UnEquipItemSystem => _unEquipItemSystem ?? (_unEquipItemSystem = GetSystem<UnEquipItemSystem>());

		public EquipItemSystem EquipItemSystem => _equipItemSystem ?? (_equipItemSystem = GetSystem<EquipItemSystem>());

		public Singleton NetworkIdSystem => _networkIdSystem_Singleton = ((ComponentSystemBase)ServerScriptMapper).GetSingleton<Singleton>();

		public SystemService(World world)
		{
		}

		private T GetSystem<T>() where T : ComponentSystemBase
		{
			return _world.GetExistingSystemManaged<T>() ?? throw new InvalidOperationException("Failed to get " + Il2CppType.Of<T>().FullName + " from the Server...");
		}
	}
}
namespace CrimsonBanned.Patches
{
	[HarmonyPatch]
	public static class ChatMessagePatch
	{
		[HarmonyPatch(typeof(ChatMessageSystem), "OnUpdate")]
		public static bool Prefix(ChatMessageSystem __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Invalid comparison between Unknown and I4
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			_ = __instance.__query_661171423_0;
			EntityQuery _query_661171423_ = __instance.__query_661171423_0;
			Enumerator<Entity> enumerator = ((EntityQuery)(ref _query_661171423_)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)).GetEnumerator();
			while (enumerator.MoveNext())
			{
				Entity current = enumerator.Current;
				EntityManager entityManager = ((ComponentSystemBase)__instance).EntityManager;
				FromCharacter componentData = ((EntityManager)(ref entityManager)).GetComponentData<FromCharacter>(current);
				entityManager = ((ComponentSystemBase)__instance).EntityManager;
				User userData = ((EntityManager)(ref entityManager)).GetComponentData<User>(componentData.User);
				entityManager = ((ComponentSystemBase)__instance).EntityManager;
				ChatMessageEvent componentData2 = ((EntityManager)(ref entityManager)).GetComponentData<ChatMessageEvent>(current);
				((object)(FixedString512Bytes)(ref componentData2.MessageText)).ToString();
				if ((int)componentData2.MessageType == 5)
				{
					continue;
				}
				if (Database.Banned.Exists((Ban x) => x.PlayerID == userData.PlatformId))
				{
					entityManager = Core.Server.EntityManager;
					((EntityManager)(ref entityManager)).DestroyEntity(current);
				}
				else if (Database.ChatBans.Exists((Ban x) => x.PlayerID == userData.PlatformId))
				{
					Ban ban = Database.ChatBans.First((Ban x) => x.PlayerID == userData.PlatformId);
					if (DateTime.UtcNow > ban.TimeUntil && !TimeUtility.IsPermanent(ban.TimeUntil))
					{
						Database.ChatBans.Remove(ban);
						ServerChatUtils.SendSystemMessageToClient(Core.EntityManager, userData, "Your chat ban has ended.");
					}
					else
					{
						entityManager = Core.Server.EntityManager;
						((EntityManager)(ref entityManager)).DestroyEntity(current);
					}
				}
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class InitializationPatch
	{
		[HarmonyPatch(typeof(SceneSystem), "ShutdownStreamingSupport")]
		[HarmonyPostfix]
		private static void ShutdownStreamingSupportPostfix()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Core.Initialize();
			if (Core.hasInitialized)
			{
				ManualLogSource log = Core.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(16, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("|");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("CrimsonBanned");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.2.0");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] initialized|");
				}
				log.LogInfo(val);
				Plugin.Harmony.Unpatch((MethodBase)typeof(SceneSystem).GetMethod("ShutdownStreamingSupport"), typeof(InitializationPatch).GetMethod("OneShot_AfterLoad_InitializationPatch"));
			}
		}
	}
	[HarmonyPatch(typeof(ServerBootstrapSystem), "OnUserConnected")]
	public static class OnUserConnectedPatcch
	{
		public static void Postfix(ServerBootstrapSystem __instance, NetConnectionId netConnectionId)
		{
			//IL_0007: 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_002e: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: 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_0148: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_ = ((ComponentSystemBase)__instance).EntityManager;
				int num = __instance._NetEndPointToApprovedUserIndex[netConnectionId];
				Entity userEntity = ((Il2CppArrayBase<ServerClient>)(object)__instance._ApprovedUsersLookup)[num].UserEntity;
				EntityManager entityManager = ((ComponentSystemBase)__instance).EntityManager;
				User userData = ((EntityManager)(ref entityManager)).GetComponentData<User>(userEntity);
				_ = ((FixedString64Bytes)(ref userData.CharacterName)).IsEmpty;
				if (Database.Banned.Exists((Ban x) => x.PlayerID == userData.PlatformId))
				{
					Ban ban = Database.Banned.First((Ban x) => x.PlayerID == userData.PlatformId);
					if (DateTime.UtcNow > ban.TimeUntil)
					{
						Database.DeleteBan(ban, Database.Banned);
						return;
					}
					entityManager = Core.EntityManager;
					Entity entity = ((EntityManager)(ref entityManager)).CreateEntity((ComponentType[])(object)new ComponentType[3]
					{
						ComponentType.ReadOnly<NetworkEventType>(),
						ComponentType.ReadOnly<SendEventToUser>(),
						ComponentType.ReadOnly<KickEvent>()
					});
					entity.Write<KickEvent>(new KickEvent
					{
						PlatformId = userData.PlatformId
					});
					entity.Write<SendEventToUser>(new SendEventToUser
					{
						UserIndex = userData.Index
					});
					entity.Write<NetworkEventType>(new NetworkEventType
					{
						EventId = NetworkEvents.EventId_KickEvent,
						IsAdminEvent = false,
						IsDebugEvent = false
					});
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Core.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(51, 5, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failure in ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("OnUserConnected");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\nMessage: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" Inner:");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.InnerException?.Message);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\n\nStack: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.StackTrace);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\nInner Stack: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.InnerException?.StackTrace);
				}
				log.LogError(val);
			}
		}
	}
	[HarmonyPatch]
	public static class VivoxPatch
	{
		[HarmonyPatch(typeof(VivoxConnectionSystem), "OnUpdate")]
		public static void Prefix(VivoxConnectionSystem __instance)
		{
			//IL_0001: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			ProcessEntities(__instance.__query_337126773_0);
			ProcessEntities(__instance.__query_337126773_1);
			ProcessEntities(__instance.__query_337126773_2);
			ProcessEntities(__instance.__query_337126773_3);
		}

		private static void ProcessEntities(EntityQuery query)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_002e: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			NativeArray<Entity> val = ((EntityQuery)(ref query)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2));
			Enumerator<Entity> enumerator = val.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Entity current = enumerator.Current;
				if (current.Has<FromCharacter>())
				{
					User user = current.Read<FromCharacter>().User.Read<User>();
					HandleUser(current, user);
				}
			}
			val.Dispose();
		}

		private static void HandleUser(Entity entity, User user)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00c2: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			EntityManager entityManager;
			if (Database.VoiceBans.Exists((Ban x) => x.PlayerID == user.PlatformId))
			{
				Ban ban = Database.VoiceBans.First((Ban x) => x.PlayerID == user.PlatformId);
				if (!(DateTime.UtcNow > ban.TimeUntil) || TimeUtility.IsPermanent(ban.TimeUntil))
				{
					if (entity.Has<ClientEvent>())
					{
						ClientEvent componentData = entity.Read<ClientEvent>();
						componentData.Type = (VivoxRequestType)0;
						entity.Write<ClientEvent>(componentData);
					}
					if (entity.Has<ClientStateEvent>())
					{
						ClientStateEvent componentData2 = entity.Read<ClientStateEvent>();
						componentData2.IsSpeaking = false;
						entity.Write<ClientStateEvent>(componentData2);
					}
					entityManager = Core.Server.EntityManager;
					((EntityManager)(ref entityManager)).DestroyEntity(entity);
					return;
				}
				Database.DeleteBan(ban, Database.VoiceBans);
				if (!Settings.ShadowBan.Value)
				{
					ServerChatUtils.SendSystemMessageToClient(Core.EntityManager, user, "Your voice ban has expired. Please verify in your social settings that Voice Proximity is re-enabled.");
				}
			}
			if (Database.Banned.Exists((Ban x) => x.PlayerID == user.PlatformId))
			{
				entityManager = Core.Server.EntityManager;
				((EntityManager)(ref entityManager)).DestroyEntity(entity);
			}
		}
	}
}
namespace CrimsonBanned.Commands
{
	[CommandGroup("ban", null)]
	internal static class BanCommands
	{
		[Command("server", "s", null, null, null, true)]
		public static void Ban(ChatCommandContext ctx, string name, int length = 0, string timeunit = "day", string reason = "")
		{
			Task<(bool, PlayerService.PlayerInfo)> task = HandleBanOperation(ctx, name, length, timeunit, Database.Banned, "banned from the server", isGameBan: true, reason);
			if (task.Result.Item1)
			{
				Core.StartCoroutine(DelayKick(task.Result.Item2));
			}
		}

		[Command("chat", "c", null, null, null, true)]
		public static void BanFromChat(ChatCommandContext ctx, string name, int length = 30, string timeunit = "min", string reason = "")
		{
			HandleBanOperation(ctx, name, length, timeunit, Database.ChatBans, "banned from chat", isGameBan: false, reason);
		}

		[Command("voice", "v", null, null, null, true)]
		public static void BanFromVoice(ChatCommandContext ctx, string name, int length = 30, string timeunit = "min", string reason = "")
		{
			HandleBanOperation(ctx, name, length, timeunit, Database.VoiceBans, "banned from voice chat", isGameBan: false, reason);
		}

		[Command("mute", "m", null, null, null, true)]
		public static void Mute(ChatCommandContext ctx, string name, int length = 30, string timeunit = "min", string reason = "")
		{
			BanFromChat(ctx, name, length, timeunit, reason);
			BanFromVoice(ctx, name, length, timeunit, reason);
		}

		[Command("kick", "k", null, null, null, true)]
		public static void KickPlayer(ChatCommandContext ctx, string name)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!name.TryGetPlayerInfo(out var playerInfo))
			{
				ctx.Reply("Could not find player with the name " + name + ".");
			}
			else if (playerInfo.User == ctx.User)
			{
				ctx.Reply("You cannot kick yourself.");
			}
			else
			{
				Kick(playerInfo);
			}
		}

		private static async Task<(bool Success, PlayerService.PlayerInfo PlayerInfo)> HandleBanOperation(ChatCommandContext ctx, string name, int length, string timeunit, List<Ban> banList, string banType, bool isGameBan = false, string reason = "")
		{
			if (!name.TryGetPlayerInfo(out var playerInfo))
			{
				ctx.Reply("Could not find player with the name " + name + ".");
				return (false, null);
			}
			if (playerInfo.User.IsAdmin)
			{
				ctx.Reply("You cannot ban an admin.");
				return (false, null);
			}
			if (playerInfo.User == ctx.User)
			{
				ctx.Reply("You cannot ban yourself.");
				return (false, null);
			}
			if (length < 0)
			{
				ctx.Reply("Please input a valid length of time.");
				return (false, null);
			}
			TimeSpan timeSpan = TimeUtility.LengthParse(length, timeunit);
			DateTime dateTime = DateTime.UtcNow + timeSpan;
			if (reason == "")
			{
				reason = "";
			}
			if (length == 0)
			{
				dateTime = TimeUtility.MinValueUtc;
			}
			if (banList.Exists((Ban x) => x.PlayerID == playerInfo.User.PlatformId))
			{
				Ban ban2 = banList.First((Ban x) => x.PlayerID == playerInfo.User.PlatformId);
				if (TimeUtility.IsPermanent(ban2.TimeUntil))
				{
					ctx.Reply(name + " is already permanently " + banType + ".");
					return (false, null);
				}
				if (ban2.TimeUntil > dateTime)
				{
					ctx.Reply(name + " is already " + banType + ".");
					return (false, null);
				}
				Database.DeleteBan(ban2, banList);
			}
			User user = playerInfo.User;
			string? playerName = ((object)(FixedString64Bytes)(ref user.CharacterName)).ToString();
			ulong platformId = playerInfo.User.PlatformId;
			DateTime timeUntil = dateTime;
			string reason2 = reason;
			user = ctx.User;
			Ban ban = new Ban(playerName, platformId, timeUntil, reason2, ((object)(FixedString64Bytes)(ref user.CharacterName)).ToString())
			{
				LocalBan = true
			};
			if (Database.SQL != null && Settings.UseSQL.Value)
			{
				if (SQLlink.Connect())
				{
					int num = SQLlink.AddBan(ban, banList);
					if (num >= 0 || num == -1)
					{
						ban.DatabaseId = num;
					}
					else
					{
						switch (await SQLConflict.ResolveConflict(ban, banList))
						{
						case 0:
							ctx.Reply(name + " is already permanently " + banType + ".");
							return (false, null);
						case 1:
							ctx.Reply(name + " already has an active ban with a longer length.");
							return (true, playerInfo);
						case 2:
							ctx.Reply($"{name} has been {banType} {((length == 0) ? "permanent" : ("for " + TimeUtility.FormatRemainder(timeSpan)))}");
							return (true, playerInfo);
						case 4:
							ctx.Reply(name + " is already " + banType + ".");
							return (false, null);
						}
					}
				}
				else
				{
					ban.DatabaseId = -1;
				}
			}
			else
			{
				ban.DatabaseId = -1;
			}
			Database.AddBan(ban, banList);
			ctx.Reply($"{name} has been {banType} {((length == 0) ? "permanently." : ("for " + TimeUtility.FormatRemainder(timeSpan) + "."))}");
			if (!Settings.ShadowBan.Value || isGameBan)
			{
				string text = (isGameBan ? $"You have been {banType} {((length == 0) ? "permanently." : ("for " + TimeUtility.FormatRemainder(timeSpan)))}. You will be kicked in 5 seconds." : $"You have been {banType} {((length == 0) ? "permanently." : ("for " + TimeUtility.FormatRemainder(timeSpan)))}.");
				ServerChatUtils.SendSystemMessageToClient(Core.EntityManager, playerInfo.User, text);
			}
			return (true, playerInfo);
		}

		public static IEnumerator DelayKick(PlayerService.PlayerInfo player)
		{
			yield return (object)new WaitForSeconds(5f);
			Kick(player);
		}

		private static void Kick(PlayerService.PlayerInfo player)
		{
			//IL_0005: 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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0025: 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_0031: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			EntityManager entityManager = Core.Server.EntityManager;
			User user = player.User;
			if (user.PlatformId != 0L)
			{
				Entity entity = ((EntityManager)(ref entityManager)).CreateEntity((ComponentType[])(object)new ComponentType[3]
				{
					ComponentType.ReadOnly<NetworkEventType>(),
					ComponentType.ReadOnly<SendEventToUser>(),
					ComponentType.ReadOnly<KickEvent>()
				});
				entity.Write<KickEvent>(new KickEvent
				{
					PlatformId = user.PlatformId
				});
				entity.Write<SendEventToUser>(new SendEventToUser
				{
					UserIndex = user.Index
				});
				entity.Write<NetworkEventType>(new NetworkEventType
				{
					EventId = NetworkEvents.EventId_KickEvent,
					IsAdminEvent = false,
					IsDebugEvent = false
				});
			}
		}
	}
	[CommandGroup("banid", null)]
	internal static class BanIDCommands
	{
		[Command("server", "s", null, null, null, true)]
		public static void Ban(ChatCommandContext ctx, ulong id, int length = 0, string timeunit = "day", string reason = "")
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!id.TryGetPlayerInfo(out var playerInfo))
			{
				HandleBanOperation(ctx, id, length, timeunit, Database.Banned, "banned from the server", isServerBan: true, reason);
				return;
			}
			User user = playerInfo.User;
			BanCommands.Ban(ctx, ((object)(FixedString64Bytes)(ref user.CharacterName)).ToString(), length, timeunit, reason);
		}

		[Command("chat", "c", null, null, null, true)]
		public static void BanFromChat(ChatCommandContext ctx, ulong id, int length = 30, string timeunit = "min", string reason = "")
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!id.TryGetPlayerInfo(out var playerInfo))
			{
				HandleBanOperation(ctx, id, length, timeunit, Database.ChatBans, "banned from chat", isServerBan: false, reason);
				return;
			}
			User user = playerInfo.User;
			BanCommands.BanFromChat(ctx, ((object)(FixedString64Bytes)(ref user.CharacterName)).ToString(), length, timeunit, reason);
		}

		[Command("voice", "v", null, null, null, true)]
		public static void BanFromVoice(ChatCommandContext ctx, ulong id, int length = 30, string timeunit = "min", string reason = "")
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!id.TryGetPlayerInfo(out var playerInfo))
			{
				HandleBanOperation(ctx, id, length, timeunit, Database.VoiceBans, "banned from voice chat", isServerBan: false, reason);
				return;
			}
			User user = playerInfo.User;
			BanCommands.BanFromVoice(ctx, ((object)(FixedString64Bytes)(ref user.CharacterName)).ToString(), length, timeunit, reason);
		}

		[Command("mute", "m", null, null, null, true)]
		public static void Mute(ChatCommandContext ctx, ulong id, int length = 30, string timeunit = "min", string reason = "")
		{
			BanFromChat(ctx, id, length, timeunit, reason);
			BanFromVoice(ctx, id, length, timeunit, reason);
		}

		private static async void HandleBanOperation(ChatCommandContext ctx, ulong id, int length, string timeunit, List<Ban> list, string banType, bool isServerBan, string reason)
		{
			TimeSpan timeSpan = TimeUtility.LengthParse(length, timeunit);
			DateTime dateTime = DateTime.UtcNow + timeSpan;
			if (list.Exists((Ban x) => x.PlayerID == id))
			{
				ctx.Reply($"Player {id} is already {banType}.");
				return;
			}
			if (length < 0)
			{
				ctx.Reply("Please input a valid length of time.");
				return;
			}
			if (length == 0)
			{
				dateTime = TimeUtility.MinValueUtc;
			}
			if (reason == "")
			{
				reason = "";
			}
			string empty = string.Empty;
			ulong playerID = id;
			DateTime timeUntil = dateTime;
			string reason2 = reason;
			User user = ctx.User;
			Ban ban = new Ban(empty, playerID, timeUntil, reason2, ((object)(FixedString64Bytes)(ref user.CharacterName)).ToString())
			{
				LocalBan = true
			};
			if (Database.SQL != null && Settings.UseSQL.Value)
			{
				if (SQLlink.Connect())
				{
					int num = SQLlink.AddBan(ban, list);
					if (num >= 0)
					{
						ban.DatabaseId = num;
					}
					else
					{
						switch (await SQLConflict.ResolveConflict(ban, list))
						{
						case 0:
							ctx.Reply($"{id} is already permanently {banType}.");
							return;
						case 1:
							ctx.Reply($"{id} has had their previous ban imported from SQL with a longer duration.");
							return;
						case 2:
							ctx.Reply($"{id} has been {banType} {((length == 0) ? "permanently." : ("for " + TimeUtility.FormatRemainder(timeSpan) + "."))}");
							return;
						}
					}
				}
				else
				{
					ban.DatabaseId = -1;
				}
			}
			else
			{
				ban.DatabaseId = -1;
			}
			Database.AddBan(ban, list);
			ctx.Reply($"Player {id} has been {banType}.");
		}
	}
	[CommandGroup("banned", null)]
	internal static class BannedCommands
	{
		private const int MESSAGE_LIMIT = 460;

		private const int MESSAGES_PER_PAGE = 2;

		[Command("list", "l", null, null, null, true)]
		public static void List(ChatCommandContext ctx, string banType = "server", string show = "perma/temp", int page = 1)
		{
			banType = banType.ToLower() switch
			{
				"server" => "Server", 
				"s" => "Server", 
				"chat" => "Chat", 
				"c" => "Chat", 
				"voice" => "Voice", 
				"v" => "Voice", 
				_ => "Server", 
			};
			List<Ban> list = banType switch
			{
				"Server" => Database.Banned, 
				"Chat" => Database.ChatBans, 
				"Voice" => Database.VoiceBans, 
				_ => new List<Ban>(), 
			};
			show = show switch
			{
				"perma" => "perma", 
				"temp" => "temp", 
				"p" => "perma", 
				"t" => "temp", 
				_ => "perma/temp", 
			};
			if (show == "temp")
			{
				list = list.FindAll((Ban x) => !TimeUtility.IsPermanent(x.TimeUntil));
			}
			else if (show == "perma")
			{
				list = list.FindAll((Ban x) => TimeUtility.IsPermanent(x.TimeUntil));
			}
			if (list.Count == 0)
			{
				ctx.Reply("No players in this ban list.");
				return;
			}
			list.Sort((Ban x, Ban y) => y.Issued.CompareTo(x.Issued));
			string item = "\n" + banType + " Bans:\n";
			List<string> list2 = new List<string> { item };
			int num = 0;
			foreach (Ban item2 in list)
			{
				string text = Database.Messages[2].ToString(item2);
				if (list2[num].Length + text.Length > 460)
				{
					num++;
					list2.Add(text);
				}
				else
				{
					list2[num] += text;
				}
			}
			int num2 = (int)Math.Ceiling((double)list2.Count / 2.0);
			if (page < 1 || page > num2)
			{
				page = 1;
			}
			int num3 = (page - 1) * 2;
			int num4 = Math.Min(num3 + 2, list2.Count);
			if (num2 > 1)
			{
				ctx.Reply($"Page {page} of {num2}:");
			}
			for (int i = num3; i < num4; i++)
			{
				ctx.Reply(list2[i]);
			}
		}

		[Command("loaduntracked", null, null, null, null, true)]
		public static void Backlog(ChatCommandContext ctx)
		{
			SQLUtility.SyncDB();
			if (File.Exists(Settings.BanFilePath.Value))
			{
				string[] array = File.ReadAllLines(Settings.BanFilePath.Value);
				foreach (string line in array)
				{
					if (!Database.Banned.Exists((Ban x) => x.PlayerID == Convert.ToUInt64(line)))
					{
						Database.AddBan(new Ban(string.Empty, Convert.ToUInt64(line), TimeUtility.MinValueUtc, "", "banlist.txt")
						{
							LocalBan = true,
							DatabaseId = -1
						}, Database.Banned);
					}
				}
				ctx.Reply("Untracked server bans in banlist.txt imported and added to tracking.");
			}
			else
			{
				ctx.Reply("Local banlist.txt not found. Please specify the file path.");
			}
		}

		[Command("sync", null, null, null, null, true)]
		public static void Sync(ChatCommandContext ctx)
		{
			if (Database.SQL == null)
			{
				ctx.Reply("MySQL is not configured. Please configure MySQL using CrimsonSQL.");
				return;
			}
			if (!Settings.UseSQL.Value)
			{
				ctx.Reply("You are not using CrimsonSQL. Ensure it is installed and the setting is set to true.");
				return;
			}
			if (!SQLlink.Connect())
			{
				ctx.Reply("Connection could not be established with the SQL database.");
				return;
			}
			SQLUtility.SyncDB();
			ctx.Reply("Bans have been synced with SQL Database.");
		}

		[Command("checkid", null, null, null, null, true)]
		public static void CheckID(ChatCommandContext ctx, string id)
		{
			//IL_0255: 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)
			ulong ID = Convert.ToUInt64(id);
			List<(Ban, BanDetails)> list = new List<(Ban, BanDetails)>();
			List<Ban> list2 = new List<Ban>();
			Ban ban = Database.Banned?.Find((Ban x) => x.PlayerID == ID);
			if (ban != null)
			{
				list2.Add(ban);
			}
			Ban ban2 = Database.ChatBans?.Find((Ban x) => x.PlayerID == ID);
			if (ban2 != null)
			{
				list2.Add(ban2);
			}
			Ban ban3 = Database.VoiceBans?.Find((Ban x) => x.PlayerID == ID);
			if (ban3 != null)
			{
				list2.Add(ban3);
			}
			if (list2.Count == 0)
			{
				ctx.Reply($"No bans found for ID {ID}.");
				return;
			}
			bool flag = false;
			foreach (Ban item3 in list2)
			{
				if (item3 == null)
				{
					continue;
				}
				if (!item3.LocalBan)
				{
					flag = true;
				}
				Ban ban4 = item3;
				List<Ban> list3;
				if (Database.Banned.Contains(ban4))
				{
					list3 = Database.Banned;
				}
				else
				{
					Ban item = ban4;
					if (Database.ChatBans.Contains(item))
					{
						list3 = Database.ChatBans;
					}
					else
					{
						Ban item2 = ban4;
						list3 = ((!Database.VoiceBans.Contains(item2)) ? null : Database.VoiceBans);
					}
				}
				List<Ban> list4 = list3;
				if (list4 != null && GetBanDetails(item3, list4, out var details))
				{
					list.Add((item3, details));
				}
			}
			if (list.Count == 0)
			{
				ctx.Reply($"No bans found for ID {ID}.");
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine(Database.Messages[0].ToString(list[0].Item1, list[0].Item2));
			if (ID.TryGetPlayerInfo(out var playerInfo) && flag)
			{
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(19, 1, stringBuilder2);
				handler.AppendLiteral("Local server name: ");
				User user = playerInfo.User;
				handler.AppendFormatted(((object)(FixedString64Bytes)(ref user.CharacterName)).ToString());
				stringBuilder2.AppendLine(ref handler);
			}
			foreach (var item4 in list)
			{
				stringBuilder.AppendLine(Database.Messages[1].ToString(item4.Item1, item4.Item2));
			}
			ctx.Reply(stringBuilder.ToString());
		}

		[Command("check", null, null, null, null, true)]
		public static void Check(ChatCommandContext ctx, string name)
		{
			if (!name.TryGetPlayerInfo(out var playerInfo))
			{
				ctx.Reply("Could not find player with the name " + name + ".");
				return;
			}
			List<(Ban, BanDetails)> list = new List<(Ban, BanDetails)>();
			foreach (Ban item3 in new List<Ban>
			{
				Database.ChatBans.Find((Ban x) => x.PlayerID == playerInfo.User.PlatformId),
				Database.VoiceBans.Find((Ban x) => x.PlayerID == playerInfo.User.PlatformId),
				Database.Banned.Find((Ban x) => x.PlayerID == playerInfo.User.PlatformId)
			})
			{
				if (item3 == null)
				{
					continue;
				}
				Ban ban = item3;
				List<Ban> list2;
				if (Database.Banned.Contains(ban))
				{
					list2 = Database.Banned;
				}
				else
				{
					Ban item = ban;
					if (Database.ChatBans.Contains(item))
					{
						list2 = Database.ChatBans;
					}
					else
					{
						Ban item2 = ban;
						list2 = ((!Database.VoiceBans.Contains(item2)) ? null : Database.VoiceBans);
					}
				}
				List<Ban> list3 = list2;
				if (list3 != null && GetBanDetails(item3, list3, out var details))
				{
					list.Add((item3, details));
				}
			}
			if (list.Count == 0)
			{
				ctx.Reply(name + " is not banned.");
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine(Database.Messages[0].ToString(list[0].Item1, list[0].Item2));
			foreach (var item4 in list)
			{
				stringBuilder.AppendLine(Database.Messages[1].ToString(item4.Item1, item4.Item2));
			}
			ctx.Reply(stringBuilder.ToString());
		}

		internal static bool GetBanDetails(Ban ban, List<Ban> list, out BanDetails details)
		{
			if (!TimeUtility.IsPermanent(ban.TimeUntil) && DateTime.UtcNow > ban.TimeUntil)
			{
				details = null;
				Database.DeleteBan(ban, list);
				return false;
			}
			details = new BanDetails();
			details.Ban = ban;
			details.IssuedOn = ban.Issued.ToLocalTime().ToString("MM/dd/yy HH:mm");
			if (list == Database.Banned)
			{
				details.BanType = "Server";
			}
			else if (list == Database.ChatBans)
			{
				details.BanType = "Chat";
			}
			else if (list == Database.VoiceBans)
			{
				details.BanType = "Voice";
			}
			if (TimeUtility.IsPermanent(ban.TimeUntil))
			{
				details.RemainingTime = "Permanent";
			}
			else
			{
				details.RemainingTime = $"Expires in {ban.TimeUntil - DateTime.UtcNow}";
			}
			return true;
		}
	}
	public class BanDetails
	{
		public Ban Ban { get; set; }

		public string BanType { get; set; }

		public string IssuedOn { get; set; }

		public string RemainingTime { get; set; }
	}
	[CommandGroup("unban", null)]
	internal static class UnbanCommands
	{
		[Command("server", "s", null, null, null, true)]
		public static void Unban(ChatCommandContext ctx, string name)
		{
			HandleUnbanOperation(ctx, name, Database.Banned, "unbanned from the server", "the server");
		}

		[Command("chat", "c", null, null, null, true)]
		public static void UnbanFromChat(ChatCommandContext ctx, string name)
		{
			HandleUnbanOperation(ctx, name, Database.ChatBans, "unbanned from chat", "chat");
		}

		[Command("voice", "v", null, null, null, true)]
		public static void UnbanFromVoice(ChatCommandContext ctx, string name)
		{
			HandleUnbanOperation(ctx, name, Database.VoiceBans, "unbanned from voice chat", "voice chat");
		}

		[Command("mute", "m", null, null, null, true)]
		public static void Unmute(ChatCommandContext ctx, string name)
		{
			UnbanFromChat(ctx, name);
			UnbanFromVoice(ctx, name);
		}

		private static void HandleUnbanOperation(ChatCommandContext ctx, string name, List<Ban> banList, string unbanType, string noneFound)
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if (!name.TryGetPlayerInfo(out var playerInfo))
			{
				ctx.Reply("Could not find player with the name " + name + ".");
				return;
			}
			if (!banList.Exists((Ban x) => x.PlayerID == playerInfo.User.PlatformId))
			{
				ctx.Reply(name + " is not banned from " + noneFound + ".");
				return;
			}
			Ban ban = banList.First((Ban x) => x.PlayerID == playerInfo.User.PlatformId);
			Database.DeleteBan(ban, banList);
			ctx.Reply(name + " has been " + unbanType + ".");
			if (!unbanType.Contains("server") && !Settings.ShadowBan.Value)
			{
				ServerChatUtils.SendSystemMessageToClient(Core.EntityManager, playerInfo.User, "You have been " + unbanType + ".");
			}
			if (unbanType.Contains("server") && File.Exists(Settings.BanFilePath.Value))
			{
				List<string> list = File.ReadAllLines(Settings.BanFilePath.Value).ToList();
				list.RemoveAll((string line) => line.Trim() == ban.PlayerID.ToString());
				File.WriteAllLines(Settings.BanFilePath.Value, list);
			}
		}
	}
	[CommandGroup("unbanid", null)]
	internal static class UnbanIDCommands
	{
		[Command("server", "s", null, null, null, true)]
		public static void Unban(ChatCommandContext ctx, ulong id)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!id.TryGetPlayerInfo(out var playerInfo))
			{
				HandleUnbanOperation(ctx, id, Database.Banned, "unbanned from the server", "the server");
				return;
			}
			User user = playerInfo.User;
			UnbanCommands.Unban(ctx, ((object)(FixedString64Bytes)(ref user.CharacterName)).ToString());
		}

		[Command("chat", "c", null, null, null, true)]
		public static void UnbanFromChat(ChatCommandContext ctx, ulong id)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!id.TryGetPlayerInfo(out var playerInfo))
			{
				HandleUnbanOperation(ctx, id, Database.ChatBans, "unbanned from chat", "chat");
				return;
			}
			User user = playerInfo.User;
			UnbanCommands.UnbanFromChat(ctx, ((object)(FixedString64Bytes)(ref user.CharacterName)).ToString());
		}

		[Command("voice", "v", null, null, null, true)]
		public static void UnbanFromVoice(ChatCommandContext ctx, ulong id)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!id.TryGetPlayerInfo(out var playerInfo))
			{
				HandleUnbanOperation(ctx, id, Database.VoiceBans, "unbanned from voice chat", "voice chat");
				return;
			}
			User user = playerInfo.User;
			UnbanCommands.UnbanFromVoice(ctx, ((object)(FixedString64Bytes)(ref user.CharacterName)).ToString());
		}

		[Command("mute", "m", null, null, null, true)]
		public static void Unmute(ChatCommandContext ctx, ulong id)
		{
			UnbanFromChat(ctx, id);
			UnbanFromVoice(ctx, id);
		}

		private static void HandleUnbanOperation(ChatCommandContext ctx, ulong id, List<Ban> banList, string unbanType, string noneFound)
		{
			if (!banList.Exists((Ban x) => x.PlayerID == id))
			{
				ctx.Reply($"{id} is not banned from {noneFound}.");
				return;
			}
			Ban ban = banList.First((Ban x) => x.PlayerID == id);
			Database.DeleteBan(ban, banList);
			ctx.Reply($"{id} has been {unbanType}.");
			if (unbanType.Contains("server") && File.Exists(Settings.BanFilePath.Value))
			{
				List<string> list = File.ReadAllLines(Settings.BanFilePath.Value).ToList();
				list.RemoveAll((string line) => line.Trim() == ban.PlayerID.ToString());
				File.WriteAllLines(Settings.BanFilePath.Value, list);
			}
		}
	}
}