Decompiled source of MatchHistory v2.1.2

Mods/MatchHistory.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Il2CppRUMBLE.Interactions.InteractionBase;
using Il2CppRUMBLE.Managers;
using Il2CppRUMBLE.Networking.MatchFlow;
using Il2CppRUMBLE.Players;
using Il2CppRUMBLE.Utilities;
using Il2CppSystem.Collections.Generic;
using MatchHistory;
using MelonLoader;
using RumbleModUI;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(global::MatchHistory.MatchHistory), "MatchHistory", "2.1.2", "Baumritter", null)]
[assembly: MelonGame("Buckethead Entertainment", "RUMBLE")]
[assembly: VerifyLoaderVersion(0, 6, 4, true)]
[assembly: MelonColor(200, 0, 200, 0)]
[assembly: MelonAuthorColor(200, 0, 200, 0)]
[assembly: AssemblyTitle("MatchHistory")]
[assembly: AssemblyDescription("Tracks matches and makes stats available")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MatchHistory")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8f661a7c-3b10-46a8-b2b1-ff3b3eed3a32")]
[assembly: AssemblyFileVersion("2.1.2")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("2.1.2.0")]
namespace MatchHistory;

internal class General
{
	internal class Delay
	{
		private readonly bool debug = false;

		private DateTime debugTime;

		private object CRObj;

		public string name = "Delay";

		private bool Running = false;

		public bool Done = false;

		private DateTime StartTime;

		private double Wait;

		public void Delay_Start(double WaitTime, bool AllowRetrigger = false)
		{
			if (!Running || AllowRetrigger)
			{
				if (Running)
				{
					MelonCoroutines.Stop(CRObj);
				}
				Done = false;
				Wait = WaitTime;
				StartTime = DateTime.Now;
				debugTime = DateTime.Now;
				CRObj = MelonCoroutines.Start(WaitLoop());
				if (debug)
				{
					MelonLogger.Msg(name + " - Started");
				}
			}
		}

		public void Delay_Stop(bool Done = false)
		{
			if (Done)
			{
				this.Done = true;
			}
			if (Running)
			{
				MelonCoroutines.Stop(CRObj);
			}
			Running = false;
			if (debug && Done)
			{
				MelonLogger.Msg(name + " - Done");
			}
			if (debug && !Done)
			{
				MelonLogger.Msg(name + " - Stopped");
			}
			TimeSpan timeSpan = DateTime.Now - debugTime;
			if (debug && Done)
			{
				MelonLogger.Msg(name + " - " + timeSpan.TotalMilliseconds);
			}
		}

		private IEnumerator WaitLoop()
		{
			WaitForFixedUpdate waitForFixedUpdate = new WaitForFixedUpdate();
			Running = true;
			while (true)
			{
				if (DateTime.Now >= StartTime.AddSeconds(Wait))
				{
					Delay_Stop(Done: true);
					yield return null;
				}
				yield return waitForFixedUpdate;
			}
		}
	}

	internal class Folders
	{
		private readonly bool debug = false;

		private string UserData = "UserData";

		private string ModFolder;

		private List<string> SubFolders = new List<string>();

		public void SetModFolderCustom(string ModName)
		{
			ModFolder = ModName;
			if (debug)
			{
				MelonLogger.Msg("Set ModFolder to " + ModFolder);
			}
		}

		public void SetModFolderNamespace()
		{
			ModFolder = GetType().Namespace;
			if (debug)
			{
				MelonLogger.Msg("Set ModFolder to " + ModFolder);
			}
		}

		public void AddSubFolder(string FolderName)
		{
			SubFolders.Add(FolderName);
			if (debug)
			{
				MelonLogger.Msg("Added Subfolder " + FolderName);
			}
		}

		public void RemoveSubFolder(string FolderName)
		{
			SubFolders.Remove(FolderName);
			if (debug)
			{
				MelonLogger.Msg("Removed Subfolder " + FolderName);
			}
		}

		public void CheckAllFoldersExist()
		{
			CreateFolderIfNotExisting(GetFolderString());
			if (SubFolders.Count <= 0)
			{
				return;
			}
			foreach (string subFolder in SubFolders)
			{
				CreateFolderIfNotExisting(GetFolderString(subFolder));
			}
		}

		public void RemoveOtherFolders()
		{
			if (debug)
			{
				MelonLogger.Msg("Folder Removal: Start");
			}
			string[] directories = Directory.GetDirectories(GetFolderString("", IgnoreList: true));
			string[] array = directories;
			foreach (string text in array)
			{
				if (debug)
				{
					MelonLogger.Msg(text);
				}
				string text2 = text.Split(new char[1] { '\\' })[^1];
				if (CheckIfFolderInList(text2))
				{
					Directory.Delete(GetFolderString(text2, IgnoreList: true), recursive: true);
					if (debug)
					{
						MelonLogger.Msg("Deleted: " + GetFolderString(text2, IgnoreList: true));
					}
				}
			}
			if (debug)
			{
				MelonLogger.Msg("Folder Removal: End");
			}
		}

		public string GetFolderString(string SubFolder = "", bool IgnoreList = false)
		{
			string text = UserData + "\\" + ModFolder;
			if (SubFolder != "" && (SubFolders.Contains(SubFolder) || IgnoreList))
			{
				text = ((!IgnoreList) ? (text + "\\" + SubFolders.FirstOrDefault((string x) => x.Contains(SubFolder))) : (text + "\\" + SubFolder));
				if (debug)
				{
					MelonLogger.Msg("Generated Path: " + text);
				}
			}
			else if (debug)
			{
				MelonLogger.Msg("Generated Path with no SubFolder: " + text);
			}
			return text;
		}

		private void CreateFolderIfNotExisting(string Path)
		{
			if (debug && !Directory.Exists(Path))
			{
				MelonLogger.Msg("Path doesn't exist: " + Path);
			}
			else if (debug && Directory.Exists(Path))
			{
				MelonLogger.Msg("Path does exist: " + Path);
			}
			if (!Directory.Exists(Path))
			{
				Directory.CreateDirectory(Path);
			}
		}

		private bool CheckIfFolderInList(string FolderName)
		{
			bool flag = false;
			string folderString = GetFolderString(FolderName, IgnoreList: true);
			if (!SubFolders.Contains(FolderName) && Directory.Exists(folderString))
			{
				flag = true;
			}
			if (debug && flag)
			{
				MelonLogger.Msg("Folder not in List " + folderString);
			}
			else if (debug && !flag)
			{
				MelonLogger.Msg("Folder in List " + folderString);
			}
			return flag;
		}
	}

	internal class Button
	{
		private GameObject ButtonTemplate;

		public List<GameObject> Buttons = new List<GameObject>();

		public void GetTemplateButton()
		{
			if ((Object)(object)ButtonTemplate == (Object)null)
			{
				GameObject val = GameObject.Find("------------TUTORIAL------------/Static tutorials/RUMBLE Starter Guide/Next Page Button/InteractionButton");
				ButtonTemplate = Object.Instantiate<GameObject>(val);
				((UnityEventBase)((Component)ButtonTemplate.transform.GetChild(0)).GetComponent<InteractionButton>().OnPressed).m_PersistentCalls.Clear();
				((Object)ButtonTemplate).name = "ButtonTemplate";
				ButtonTemplate.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)ButtonTemplate);
			}
		}

		public void AddButton(string name)
		{
			GameObject val = Object.Instantiate<GameObject>(ButtonTemplate);
			((Object)val).name = name;
			Buttons.Add(val);
		}

		public void RemoveButton(string name)
		{
			Enumerator<GameObject> enumerator = Buttons.GetEnumerator();
			while (enumerator.MoveNext())
			{
				GameObject current = enumerator.Current;
				if (((Object)current).name == name)
				{
					GameObject val = current;
					Buttons.Remove(val);
					break;
				}
			}
		}

		public UnityEvent OnPressed(string name = "", int index = -1)
		{
			if (name != "")
			{
				int num = SearchButtonList(name);
				if (num != -1)
				{
					return ((Component)Buttons[num].transform.GetChild(0)).GetComponent<InteractionButton>().OnPressed;
				}
				return ((Component)Buttons[0].transform.GetChild(0)).GetComponent<InteractionButton>().OnPressed;
			}
			if (index != -1)
			{
				return ((Component)Buttons[index].transform.GetChild(0)).GetComponent<InteractionButton>().OnPressed;
			}
			return ((Component)Buttons[0].transform.GetChild(0)).GetComponent<InteractionButton>().OnPressed;
		}

		private int SearchButtonList(string name)
		{
			for (int i = 0; i < Buttons.Count; i++)
			{
				if (((Object)Buttons[i]).name == name)
				{
					return i;
				}
			}
			return -1;
		}
	}

	internal class StringExtension
	{
		public enum Colors
		{
			Red,
			Yellow,
			Green,
			Blue
		}

		public static string ApplyColor(string Input, Colors color)
		{
			return color switch
			{
				Colors.Red => "<color=red>" + Input + "</color>", 
				Colors.Yellow => "<color=yellow>" + Input + "</color>", 
				Colors.Green => "<color=green>" + Input + "</color>", 
				Colors.Blue => "<color=blue>" + Input + "</color>", 
				_ => "<color=black>" + Input + "</color>", 
			};
		}
	}
}
internal class Data
{
	public class PlayerData
	{
		public string UserID { get; set; }

		public string Name { get; set; }

		public int BP { get; set; }

		public PlayerData()
		{
			Init();
		}

		public PlayerData(Player player)
		{
			SetDataFromPlayer(player);
		}

		public void SetDataFromPlayer(Player player)
		{
			GeneralData generalData = player.Data.GeneralData;
			UserID = generalData.InternalUsername;
			Name = SanitizeName(generalData.PublicUsername);
			BP = generalData.BattlePoints;
		}

		public override string ToString()
		{
			return UserID + " " + Name + " : " + BP;
		}

		private string SanitizeName(string Input)
		{
			bool flag = false;
			char[] array = Input.ToCharArray();
			string text = "";
			if (Input.Contains("<u>"))
			{
				Input.Replace("<u>", "");
			}
			if (Input.Contains(","))
			{
				Input.Replace(",", "");
			}
			for (int i = 0; i < Input.Length; i++)
			{
				if (array[i] == '<' && i != Input.Length && (array[i + 1] == '#' || array[i + 1] == 'c'))
				{
					flag = true;
				}
				if (!flag)
				{
					text += array[i];
				}
				if (array[i] == '>')
				{
					flag = false;
				}
			}
			return text;
		}

		private void Init()
		{
			UserID = "0";
			Name = "Player";
			BP = 0;
		}
	}

	public class RoundData
	{
		public enum RoundResult
		{
			P1Win,
			P2Win,
			Undefined
		}

		public int Index { get; set; }

		public int P1_HP { get; set; }

		public int P2_HP { get; set; }

		public TimeSpan RoundTime { get; set; }

		public RoundResult Result { get; set; }

		public RoundData()
		{
			Init();
		}

		public RoundData(int Index, int P1_HP, int P2_HP, RoundResult result)
		{
			SetData(Index, P1_HP, P2_HP, result);
		}

		public void SetData(int Index, int P1_HP, int P2_HP, RoundResult result)
		{
			this.Index = Index;
			this.P1_HP = P1_HP;
			this.P2_HP = P2_HP;
			Result = result;
		}

		public void SetRoundTime(DateTime From, DateTime To)
		{
			RoundTime = From - To;
		}

		public override string ToString()
		{
			return Index + " " + P1_HP + " " + P2_HP + " " + Result;
		}

		private void Init()
		{
			Index = -1;
			P1_HP = -1;
			P2_HP = -1;
			Result = RoundResult.Undefined;
			RoundTime = TimeSpan.Zero;
		}
	}

	public class MatchData
	{
		public enum MatchResult
		{
			P1Win,
			P2Win,
			Tie,
			P1Dc,
			P2Dc,
			Undefined
		}

		private int CurrentRound { get; set; }

		public PlayerData P1 { get; set; }

		public PlayerData P2 { get; set; }

		public RoundData[] Rounds { get; set; }

		public MatchResult Result { get; set; }

		public MatchData()
		{
			Rounds = new RoundData[3];
			for (int i = 0; i < Rounds.Length; i++)
			{
				Rounds[i] = new RoundData();
			}
			Result = MatchResult.Undefined;
			P1 = new PlayerData();
			P2 = new PlayerData();
			CurrentRound = 1;
		}

		public string GetHash()
		{
			return P1.Name + P1.BP + P2.Name + P2.BP;
		}

		public void InitPlayers(Player P1Data, Player P2Data)
		{
			P1.SetDataFromPlayer(P1Data);
			P2.SetDataFromPlayer(P2Data);
		}

		public void SetRoundTime(DateTime From, DateTime To)
		{
			Rounds[CurrentRound - 1].SetRoundTime(From, To);
		}

		public void SetRound(int P1_HP, int P2_HP, RoundData.RoundResult result)
		{
			Rounds[CurrentRound - 1].SetData(CurrentRound, P1_HP, P2_HP, result);
			CurrentRound++;
		}

		public int GetRoundNr()
		{
			return CurrentRound;
		}

		public void CalculateMatchResult()
		{
			int num = 0;
			int num2 = 0;
			RoundData[] rounds = Rounds;
			foreach (RoundData roundData in rounds)
			{
				if (roundData.Result == RoundData.RoundResult.P1Win)
				{
					num++;
				}
				else if (roundData.Result == RoundData.RoundResult.P2Win)
				{
					num2++;
				}
			}
			if (num > num2)
			{
				Result = MatchResult.P1Win;
			}
			else if (num < num2)
			{
				Result = MatchResult.P2Win;
			}
			else if (num == num2)
			{
				Result = MatchResult.Tie;
			}
		}

		public string GetStatusString(bool FileOutput)
		{
			string text = ((!FileOutput) ? "" : (P1.Name + " vs " + P2.Name + Environment.NewLine + Environment.NewLine));
			RoundData[] rounds = Rounds;
			foreach (RoundData roundData in rounds)
			{
				if (roundData.Index != -1)
				{
					text = text + "Round " + roundData.Index + " : " + roundData.RoundTime.ToString("mm\\:ss") + " : ";
					text = (FileOutput ? ((roundData.Result == RoundData.RoundResult.P1Win) ? (text + "You won" + Environment.NewLine) : ((roundData.Result != RoundData.RoundResult.P2Win) ? (text + "No Result" + Environment.NewLine) : (text + "Opponent won" + Environment.NewLine))) : ((roundData.Result == RoundData.RoundResult.P1Win) ? (text + General.StringExtension.ApplyColor("You won", General.StringExtension.Colors.Green) + Environment.NewLine) : ((roundData.Result != RoundData.RoundResult.P2Win) ? (text + General.StringExtension.ApplyColor("No Result", General.StringExtension.Colors.Yellow) + Environment.NewLine) : (text + General.StringExtension.ApplyColor("Opponent won", General.StringExtension.Colors.Red) + Environment.NewLine))));
					text = text + "Your HP: " + roundData.P1_HP + "  ---  Enemy HP: " + roundData.P2_HP + Environment.NewLine + Environment.NewLine;
				}
			}
			text = text + "Match Result:" + Environment.NewLine;
			if (FileOutput)
			{
				switch (Result)
				{
				case MatchResult.P1Win:
					text += "You won";
					break;
				case MatchResult.P2Win:
					text += "Opponent won";
					break;
				case MatchResult.P1Dc:
					text += "You left";
					break;
				case MatchResult.P2Dc:
					text += "Opponent left";
					break;
				case MatchResult.Undefined:
					text += "No Result";
					break;
				}
			}
			else
			{
				switch (Result)
				{
				case MatchResult.P1Win:
					text += General.StringExtension.ApplyColor("You won", General.StringExtension.Colors.Green);
					break;
				case MatchResult.P2Win:
					text += General.StringExtension.ApplyColor("Opponent won", General.StringExtension.Colors.Red);
					break;
				case MatchResult.P1Dc:
					text += General.StringExtension.ApplyColor("You left", General.StringExtension.Colors.Red);
					break;
				case MatchResult.P2Dc:
					text += General.StringExtension.ApplyColor("Opponent left", General.StringExtension.Colors.Red);
					break;
				case MatchResult.Undefined:
					text += General.StringExtension.ApplyColor("No Result", General.StringExtension.Colors.Yellow);
					break;
				}
			}
			return text;
		}
	}
}
public static class BuildInfo
{
	public const string ModName = "MatchHistory";

	public const string ModVersion = "2.1.2";

	public const string Description = "Tracks matches and makes stats available";

	public const string Author = "Baumritter";

	public const string Company = "";
}
public class MatchHistory : MelonMod
{
	private string currentscene;

	private string LastMatch;

	private bool debug = false;

	private bool MatchRunning = false;

	private int MHL = 20;

	private DateTime Start;

	private DateTime End;

	private Data.MatchData CurrentMatch;

	private Data.MatchData PreviousMatch;

	private Player P1;

	private Player P2;

	private GameObject EndofMatchObject;

	private UI UI = UI.instance;

	private Mod Mod = new Mod();

	private ModSetting<int> MatchHistoryLength = new ModSetting<int>();

	private General.Folders Folders = new General.Folders();

	private object C_Match;

	private object C_RoundEnd;

	private object C_RoundStart;

	public override void OnLateInitializeMelon()
	{
		((MelonBase)this).OnLateInitializeMelon();
		UI.UI_Initialized += OnUIInit;
		Folders.SetModFolderNamespace();
		Folders.AddSubFolder("Logs");
		Folders.CheckAllFoldersExist();
	}

	public override void OnSceneWasLoaded(int buildIndex, string sceneName)
	{
		((MelonMod)this).OnSceneWasLoaded(buildIndex, sceneName);
		currentscene = sceneName;
		if ((currentscene == "Map0" || currentscene == "Map1") && C_Match == null)
		{
			C_Match = MelonCoroutines.Start(WaitForMatchStart());
		}
	}

	public override void OnApplicationQuit()
	{
		((MelonBase)this).OnApplicationQuit();
		if (MatchRunning)
		{
			OnMatchEnd(Data.MatchData.MatchResult.P1Dc);
			KillMatchFlow("Game closed.");
			if (debug)
			{
				MelonLogger.Msg(LastMatch);
			}
		}
	}

	private void OnUIInit()
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Expected O, but got Unknown
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Expected O, but got Unknown
		Mod.ModName = "MatchHistory";
		Mod.ModVersion = "2.1.2";
		Mod.SetFolder("MatchHistory");
		Mod.AddDescription("Description", "", "Settings for the Match History", new Tags
		{
			IsSummary = true
		});
		Mod.AddToList("Match History Length", 20, "Defines how many Matches should be kept in the record." + Environment.NewLine + "Default: 20", new Tags());
		Mod.GetFromFile();
		AddLogFileToSettings();
		UI.AddMod(Mod);
		MelonLoggerExtension.Log("Added Mod.");
	}

	private IEnumerator WaitForMatchStart()
	{
		WaitForFixedUpdate waitForFixedUpdate = new WaitForFixedUpdate();
		bool GymDelayTrigger = false;
		DateTime GymDelay = DateTime.Now;
		if (debug)
		{
			MelonLogger.Msg("Matchflow - Waiting for Match Start");
		}
		while (true)
		{
			if (currentscene != "Gym")
			{
				GymDelayTrigger = false;
			}
			if (!GymDelayTrigger && currentscene == "Gym")
			{
				GymDelay = DateTime.Now;
				GymDelayTrigger = true;
			}
			if (GymDelayTrigger && GymDelay.AddSeconds(2.0) < DateTime.Now)
			{
				KillMatchFlow("Gym loaded for more than 2 seconds.");
			}
			if ((int)Singleton<MatchHandler>.instance.CurrentMatchPhase == 2)
			{
				OnMatchStart();
				yield return null;
			}
			yield return waitForFixedUpdate;
		}
	}

	private void OnMatchStart()
	{
		if (C_Match != null)
		{
			MelonCoroutines.Stop(C_Match);
		}
		if (debug)
		{
			MelonLogger.Msg("Matchflow - Match started");
		}
		CurrentMatch = new Data.MatchData();
		P1 = Singleton<PlayerManager>.instance.LocalPlayer;
		if (Singleton<PlayerManager>.instance.AllPlayers.Count == 1)
		{
			CurrentMatch.P1.SetDataFromPlayer(P1);
			OnMatchEnd(Data.MatchData.MatchResult.P2Dc);
			return;
		}
		P2 = Singleton<PlayerManager>.instance.AllPlayers[1];
		if (debug)
		{
			MelonLogger.Msg("Matchflow - Data got");
		}
		CurrentMatch.InitPlayers(P1, P2);
		MatchRunning = true;
		Start = DateTime.Now;
		EndofMatchObject = ((Component)GameObject.Find("Logic/MatchSlabOne").transform.GetChild(2).GetChild(0).GetChild(0)).gameObject;
		C_RoundEnd = MelonCoroutines.Start(WaitForRoundEnd());
	}

	private IEnumerator WaitForRoundEnd()
	{
		WaitForFixedUpdate waitForFixedUpdate = new WaitForFixedUpdate();
		if (debug)
		{
			MelonLogger.Msg("Matchflow - Waiting for Round End");
		}
		while (true)
		{
			if (Singleton<PlayerManager>.instance.AllPlayers.Count == 1)
			{
				OnMatchEnd(Data.MatchData.MatchResult.P2Dc);
				yield return null;
			}
			else if ((int)Singleton<MatchHandler>.instance.CurrentMatchPhase == 4)
			{
				OnRoundEnd();
				yield return null;
			}
			yield return waitForFixedUpdate;
		}
	}

	private void OnRoundEnd()
	{
		if (C_RoundEnd != null)
		{
			MelonCoroutines.Stop(C_RoundEnd);
		}
		End = DateTime.Now;
		int healthPoints = P1.Data.HealthPoints;
		int healthPoints2 = P2.Data.HealthPoints;
		Data.RoundData.RoundResult result = ((healthPoints <= healthPoints2) ? Data.RoundData.RoundResult.P2Win : Data.RoundData.RoundResult.P1Win);
		CurrentMatch.SetRoundTime(Start, End);
		CurrentMatch.SetRound(healthPoints, healthPoints2, result);
		if (debug)
		{
			MelonLogger.Msg("Matchflow - Round ended");
		}
		C_RoundStart = MelonCoroutines.Start(WaitForRoundStart());
	}

	private IEnumerator WaitForRoundStart()
	{
		WaitForFixedUpdate waitForFixedUpdate = new WaitForFixedUpdate();
		if (debug)
		{
			MelonLogger.Msg("Matchflow - Waiting for Round Start");
		}
		while (true)
		{
			if (EndofMatchObject.active)
			{
				if (debug)
				{
					MelonLogger.Msg("Matchflow - End of Match Object found");
				}
				OnMatchEnd();
				yield return null;
			}
			else if ((int)Singleton<MatchHandler>.instance.CurrentMatchPhase == 2)
			{
				OnRoundStart();
				yield return null;
			}
			yield return waitForFixedUpdate;
		}
	}

	private void OnRoundStart()
	{
		if (C_RoundStart != null)
		{
			MelonCoroutines.Stop(C_RoundStart);
		}
		Start = DateTime.Now;
		if (debug)
		{
			MelonLogger.Msg("Matchflow - Round started");
		}
		C_RoundEnd = MelonCoroutines.Start(WaitForRoundEnd());
	}

	private void OnMatchEnd(Data.MatchData.MatchResult ForceResult = Data.MatchData.MatchResult.Undefined)
	{
		if (C_RoundEnd != null)
		{
			MelonCoroutines.Stop(C_RoundEnd);
		}
		if (C_RoundStart != null)
		{
			MelonCoroutines.Stop(C_RoundStart);
		}
		MatchRunning = false;
		if (PreviousMatch != null && PreviousMatch.GetHash() == CurrentMatch.GetHash())
		{
			if (debug)
			{
				MelonLogger.Msg("Tried to log same match again");
			}
			return;
		}
		if (ForceResult != Data.MatchData.MatchResult.Undefined)
		{
			CurrentMatch.Result = ForceResult;
		}
		else
		{
			CurrentMatch.CalculateMatchResult();
		}
		if (debug)
		{
			MelonLogger.Msg("Matchflow - Match stopped");
		}
		LastMatch = CurrentMatch.GetStatusString(FileOutput: true);
		AddCurrentLogToSettings();
		LogMatchHistory(LastMatch);
		PreviousMatch = CurrentMatch;
		MelonLogger.Msg("Match logged");
		if (debug)
		{
			MelonLogger.Msg(LastMatch);
		}
		C_Match = MelonCoroutines.Start(WaitForMatchStart());
	}

	private void KillMatchFlow(string Reason)
	{
		if (C_Match != null)
		{
			MelonCoroutines.Stop(C_Match);
		}
		if (C_RoundEnd != null)
		{
			MelonCoroutines.Stop(C_RoundEnd);
		}
		if (C_RoundStart != null)
		{
			MelonCoroutines.Stop(C_RoundStart);
		}
		if (debug)
		{
			MelonLogger.Msg("Matchflow - Terminated: " + Reason);
		}
	}

	private void LogMatchHistory(string Output)
	{
		string path = Folders.GetFolderString("Logs") + "\\Match_" + DateTime.Now.ToString("yyyyMMdd_HHmm") + ".txt";
		MHL = (int)((ModSetting)MatchHistoryLength).SavedValue;
		if (Directory.GetFiles(Folders.GetFolderString("Logs")).Length > 20)
		{
			foreach (FileInfo item in (from x in new DirectoryInfo(Folders.GetFolderString("Logs")).GetFiles()
				orderby x.LastWriteTime descending
				select x).Skip(MHL))
			{
				item.Delete();
			}
		}
		File.WriteAllText(path, Output);
		if (debug)
		{
			MelonLogger.Msg("Log Written");
		}
	}

	private void AddCurrentLogToSettings()
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected O, but got Unknown
		string text = CurrentMatch.P2.Name + " - " + DateTime.Now.ToString("HH:mm");
		Mod.AddDescription(text, "", CurrentMatch.GetStatusString(FileOutput: false), new Tags
		{
			IsEmpty = true
		});
		UI.ForceRefresh();
	}

	private void AddLogFileToSettings()
	{
		//IL_024a: Unknown result type (might be due to invalid IL or missing references)
		//IL_024f: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Expected O, but got Unknown
		string folderString = Folders.GetFolderString("Logs");
		string[] files = Directory.GetFiles(folderString);
		foreach (string text in files)
		{
			string[] array = File.ReadAllLines(text);
			string text2 = "";
			string text3 = array[0].Substring(array[0].IndexOf(" vs ") + 4).Replace(Environment.NewLine, "");
			string text4 = text.Split(new char[1] { '_' })[2].Replace(".txt", "");
			string text5 = text4.Substring(0, 2);
			string text6 = text4.Substring(2);
			text4 = text5 + ":" + text6;
			string text7 = text3 + " - " + text4;
			for (int j = 2; j < array.Length; j++)
			{
				text2 = ((!array[j].Contains("You won")) ? ((!array[j].Contains("Opponent won")) ? ((!array[j].Contains("No Result")) ? ((!array[j].Contains("You left")) ? ((!array[j].Contains("Opponent left")) ? (text2 + array[j] + Environment.NewLine) : (text2 + array[j].Replace("Opponent left", General.StringExtension.ApplyColor("Opponent left", General.StringExtension.Colors.Red)) + Environment.NewLine)) : (text2 + array[j].Replace("You left", General.StringExtension.ApplyColor("You left", General.StringExtension.Colors.Red)) + Environment.NewLine)) : (text2 + array[j].Replace("No Result", General.StringExtension.ApplyColor("No Result", General.StringExtension.Colors.Yellow)) + Environment.NewLine)) : (text2 + array[j].Replace("Opponent won", General.StringExtension.ApplyColor("Opponent won", General.StringExtension.Colors.Red)) + Environment.NewLine)) : (text2 + array[j].Replace("You won", General.StringExtension.ApplyColor("You won", General.StringExtension.Colors.Green)) + Environment.NewLine));
			}
			Mod.AddDescription(text7, "", text2, new Tags
			{
				IsEmpty = true
			});
		}
	}
}