Decompiled source of LD CrewBoom v4.2.0

CrewBoom.dll

Decompiled a month ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CommonAPI;
using CrewBoom.Behaviours;
using CrewBoom.Compatibility;
using CrewBoom.Data;
using CrewBoom.Database;
using CrewBoom.Mono;
using CrewBoom.Properties;
using CrewBoom.Utility;
using CrewBoomAPI;
using CrewBoomMono;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Reptile;
using Reptile.Phone;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Events;
using UnityEngine.Playables;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("CrewBoom")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A plugin to load custom skins and characters for Bomb Rush Cyberfunk.")]
[assembly: AssemblyFileVersion("4.2.0.0")]
[assembly: AssemblyInformationalVersion("4.2.0+dabe070583f8c672c6e79d8343dd7bc3c6980984")]
[assembly: AssemblyProduct("CrewBoom")]
[assembly: AssemblyTitle("CrewBoom")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("4.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CrewBoom
{
	public static class CharacterDatabase
	{
		private static readonly string ASSET_PATH = Path.Combine(Paths.ConfigPath, "CrewBoom");

		private static readonly string NO_CYPHER_PATH = Path.Combine(ASSET_PATH, "no_cypher");

		private static Dictionary<Guid, string> _characterBundlePaths;

		private static Dictionary<Guid, CustomCharacter> _customCharacters;

		private static Dictionary<Guid, bool> _cypherMapping;

		private static Dictionary<Characters, List<Guid>> _characterIds;

		public static Shader GraffitiShader = null;

		private static ManualLogSource DebugLog = Logger.CreateLogSource("CrewBoom Database");

		private static bool _appliedGrafShaders = false;

		public static int NewCharacterCount { get; private set; } = 0;


		public static bool HasCharacterOverride { get; private set; }

		public static Guid CharacterOverride { get; private set; }

		public static bool Initialize()
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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)
			//IL_00aa: Invalid comparison between Unknown and I4
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Invalid comparison between Unknown and I4
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if (!Directory.Exists(ASSET_PATH))
			{
				DebugLog.LogWarning((object)("Could not find character bundle directory \"" + ASSET_PATH + "\".\nIt was created instead."));
				Directory.CreateDirectory(ASSET_PATH);
				return false;
			}
			if (!Directory.Exists(NO_CYPHER_PATH))
			{
				DebugLog.LogMessage((object)"No cypher bundle path was not found. It was created instead.");
				Directory.CreateDirectory(NO_CYPHER_PATH);
			}
			_characterBundlePaths = new Dictionary<Guid, string>();
			_customCharacters = new Dictionary<Guid, CustomCharacter>();
			_cypherMapping = new Dictionary<Guid, bool>();
			_characterIds = new Dictionary<Characters, List<Guid>>();
			foreach (Characters value in Enum.GetValues(typeof(Characters)))
			{
				if ((int)value == -1 || (int)value == 26)
				{
					_characterIds.Add(value, null);
				}
				else
				{
					_characterIds.Add(value, new List<Guid>());
				}
			}
			if (!LoadAllCharacterData())
			{
				DebugLog.LogWarning((object)("There were no valid characters found in " + ASSET_PATH + ".\nMake sure your character bundles (.cbb) are in the CONFIG folder, NOT the PLUGIN folder."));
				return false;
			}
			InitializeAPI();
			return true;
		}

		private static bool LoadAllCharacterData()
		{
			int num = 0;
			bool result = false;
			string[] files = Directory.GetFiles(ASSET_PATH, "*.cbb");
			for (int i = 0; i < files.Length; i++)
			{
				if (LoadCharacterBundle(files[i], enableCypher: true, out var generatedStream))
				{
					result = true;
					if (generatedStream)
					{
						num++;
					}
				}
			}
			files = Directory.GetFiles(NO_CYPHER_PATH, "*.cbb");
			for (int i = 0; i < files.Length; i++)
			{
				if (LoadCharacterBundle(files[i], enableCypher: false, out var generatedStream2))
				{
					result = true;
					if (generatedStream2)
					{
						num++;
					}
				}
			}
			files = Directory.GetFiles(Paths.PluginPath, "*.cbb", SearchOption.AllDirectories);
			for (int i = 0; i < files.Length; i++)
			{
				if (LoadCharacterBundle(files[i], enableCypher: true, out var generatedStream3))
				{
					result = true;
					if (generatedStream3)
					{
						num++;
					}
				}
			}
			if (num > 0)
			{
				if (CrewBoomSettings.UpdateCBBs)
				{
					DebugLog.LogInfo((object)$"Updated {num} .cbb files with stream data!");
				}
				else
				{
					DebugLog.LogInfo((object)$"Created stream files (.ldcs) for {num} .cbb files!");
				}
			}
			return result;
		}

		private static bool LoadCharacterBundle(string filePath, bool enableCypher)
		{
			bool generatedStream;
			return LoadCharacterBundle(filePath, enableCypher, out generatedStream);
		}

		private static bool SafelyAppendEmbedded(string filePath, EmbeddedBundle embedded, CharacterStreamData streamData)
		{
			string text = filePath + ".bak";
			if (File.Exists(text))
			{
				File.Delete(text);
			}
			File.Copy(filePath, text);
			try
			{
				embedded.OpenWrite();
				embedded.AppendStreamData(streamData);
			}
			catch (Exception arg)
			{
				embedded.Close();
				File.Replace(text, filePath, null);
				DebugLog.LogError((object)("Failed to update CBB for \"" + filePath + "\""));
				DebugLog.LogError((object)$"{arg}");
				return false;
			}
			File.Delete(text);
			return true;
		}

		private static bool LoadCharacterBundle(string filePath, bool enableCypher, out bool generatedStream)
		{
			//IL_0043: 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_00dd: Expected O, but got Unknown
			//IL_0070: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Invalid comparison between Unknown and I4
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Expected O, but got Unknown
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Invalid comparison between Unknown and I4
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			generatedStream = false;
			string fileName = Path.GetFileName(filePath);
			string path = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath) + ".json");
			string path2 = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath) + ".ldcs");
			BrcCharacter val = (BrcCharacter)(-1);
			if (File.Exists(path))
			{
				string text = File.ReadAllText(path);
				try
				{
					CharacterConfig val2 = JsonUtility.FromJson<CharacterConfig>(text);
					if (Enum.TryParse<BrcCharacter>(val2.CharacterToReplace, out BrcCharacter result))
					{
						val = result;
					}
					else
					{
						DebugLog.LogWarning((object)("The configured replacement character for the bundle " + fileName + " (\"" + val2.CharacterToReplace + "\") is not a valid character!"));
					}
				}
				catch (Exception)
				{
					DebugLog.LogError((object)("Failed to read JSON config for \"" + fileName + "\""));
				}
			}
			CharacterDefinition val3 = null;
			CharacterStreamData val4 = null;
			try
			{
				EmbeddedBundle val5 = new EmbeddedBundle(filePath);
				try
				{
					val5.OpenRead();
					if (!val5.TryRetrieveStreamData(ref val4))
					{
						if (File.Exists(path2))
						{
							val4 = new CharacterStreamData();
							using (FileStream input = new FileStream(path2, FileMode.Open, FileAccess.Read))
							{
								using BinaryReader binaryReader = new BinaryReader(input);
								val4.Read(binaryReader, CrewBoomSettings.UpdateCBBs);
							}
							if (CrewBoomSettings.UpdateCBBs)
							{
								generatedStream = SafelyAppendEmbedded(filePath, val5, val4);
							}
						}
						else
						{
							AssetBundle val6 = val5.LoadAssetBundle();
							GameObject[] array = val6.LoadAllAssets<GameObject>();
							for (int i = 0; i < array.Length; i++)
							{
								val3 = array[i].GetComponent<CharacterDefinition>();
								if (!((Object)(object)val3 != (Object)null))
								{
									continue;
								}
								val4 = new CharacterStreamData();
								val4.FromCharacter(val3);
								if (CrewBoomSettings.UpdateCBBs)
								{
									generatedStream = SafelyAppendEmbedded(filePath, val5, val4);
									break;
								}
								using (FileStream output = new FileStream(path2, FileMode.Create, FileAccess.Write))
								{
									using BinaryWriter binaryWriter = new BinaryWriter(output);
									val4.Write(binaryWriter);
								}
								generatedStream = true;
								break;
							}
							val6.Unload(true);
						}
					}
				}
				finally
				{
					((IDisposable)val5)?.Dispose();
				}
			}
			catch (Exception arg)
			{
				DebugLog.LogError((object)("Failed to load bundle for \"" + fileName + "\""));
				DebugLog.LogError((object)$"{arg}");
				if (val4 != null)
				{
					val4.Release();
				}
				return false;
			}
			if (val4 == null)
			{
				return false;
			}
			Guid guid = Guid.Parse(val4.Id);
			if (_characterBundlePaths.ContainsKey(guid))
			{
				DebugLog.LogError((object)$"Failed to load  \"{fileName}\" - there already is a character with the same GUID ({guid})");
				val4.Release();
				return false;
			}
			_characterBundlePaths[guid] = filePath;
			SfxCollectionID sfxID = (SfxCollectionID)(-1);
			if ((int)val != -1)
			{
				_characterIds[(Characters)val].Add(guid);
			}
			else
			{
				NewCharacterCount++;
				Characters key = (Characters)(26 + NewCharacterCount);
				sfxID = (SfxCollectionID)(67 + NewCharacterCount);
				if (_characterIds.ContainsKey(key))
				{
					_characterIds[key].Add(guid);
				}
				else
				{
					_characterIds.Add(key, new List<Guid> { guid });
				}
				_cypherMapping.Add(guid, enableCypher);
			}
			bool replacement = (int)val != -1;
			bool forceLoad = false;
			if (!CrewBoomSettings.StreamCharacters)
			{
				forceLoad = true;
			}
			CustomCharacter value = new CustomCharacter(val4, sfxID, filePath, replacement, forceLoad);
			_customCharacters.Add(guid, value);
			return true;
		}

		public static void RefreshShaders()
		{
			_appliedGrafShaders = false;
			foreach (CustomCharacter value in _customCharacters.Values)
			{
				if (value.Loaded)
				{
					value.FixCharacterShader();
				}
			}
		}

		public static void SetGraffitiShader(Shader shader)
		{
			if (_appliedGrafShaders || (Object)(object)shader == (Object)null)
			{
				return;
			}
			foreach (CustomCharacter value in _customCharacters.Values)
			{
				value.ApplyShaderToGraffiti(shader);
			}
			_appliedGrafShaders = true;
		}

		private static void InitializeAPI()
		{
			Dictionary<int, Guid> dictionary = new Dictionary<int, Guid>();
			int num = 26;
			for (int i = num + 1; i <= num + NewCharacterCount; i++)
			{
				if (GetFirstOrConfigCharacterId((Characters)i, out var guid))
				{
					dictionary.Add(i, guid);
				}
			}
			CrewBoomAPIDatabase.Initialize(dictionary);
			CrewBoomAPIDatabase.OnOverride += SetCharacterOverride;
		}

		private static void SetCharacterOverride(Guid id)
		{
			HasCharacterOverride = true;
			CharacterOverride = id;
			DebugLog.LogInfo((object)$"Received override for next character {id}");
		}

		public static void SetCharacterOverrideDone()
		{
			HasCharacterOverride = false;
			DebugLog.LogInfo((object)"Finished override");
		}

		public static void InitializeMissingSfxCollections(Characters character, SfxCollection collection)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (!_characterIds.TryGetValue(character, out var value) || value == null || value.Count <= 0)
			{
				return;
			}
			foreach (Guid item in value)
			{
				if (GetCharacter(item, out var characterObject))
				{
					characterObject.ApplySfxCollection(collection);
				}
			}
		}

		public static bool GetCharacterNameWithId(int localizationId, out string name)
		{
			name = string.Empty;
			switch (localizationId)
			{
			case 0:
				return false;
			case 6:
				return GetCharacterName((Characters)0, out name);
			case 10:
				return GetCharacterName((Characters)1, out name);
			case 24:
				return GetCharacterName((Characters)2, out name);
			case 4:
				return GetCharacterName((Characters)3, out name);
			case 3:
				return GetCharacterName((Characters)4, out name);
			case 5:
				return GetCharacterName((Characters)5, out name);
			case 26:
				return GetCharacterName((Characters)6, out name);
			case 12:
				if (GetCharacterName((Characters)7, out name))
				{
					return true;
				}
				return GetCharacterName((Characters)24, out name);
			case 15:
				return GetCharacterName((Characters)8, out name);
			case 7:
				return GetCharacterName((Characters)9, out name);
			case 11:
				return GetCharacterName((Characters)10, out name);
			case 13:
				return GetCharacterName((Characters)11, out name);
			case 2:
				if (GetCharacterName((Characters)12, out name))
				{
					return true;
				}
				return GetCharacterName((Characters)23, out name);
			case 8:
				return GetCharacterName((Characters)13, out name);
			case 16:
				return GetCharacterName((Characters)14, out name);
			case 21:
				return GetCharacterName((Characters)15, out name);
			case 20:
				return GetCharacterName((Characters)16, out name);
			case 30:
				return GetCharacterName((Characters)17, out name);
			case 31:
				return GetCharacterName((Characters)18, out name);
			case 28:
				return GetCharacterName((Characters)19, out name);
			case 14:
				return GetCharacterName((Characters)20, out name);
			case 25:
				return GetCharacterName((Characters)21, out name);
			case 27:
				return GetCharacterName((Characters)22, out name);
			case 22:
				return GetCharacterName((Characters)25, out name);
			default:
				return false;
			}
		}

		private static bool GetCharacterName(Characters character, out string name)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			name = string.Empty;
			if (GetCharacter(character, out var characterObject))
			{
				name = characterObject.StreamData.Name;
				return true;
			}
			return false;
		}

		public static bool GetFirstOrConfigCharacterId(Characters character, out Guid guid)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			guid = Guid.Empty;
			if (HasCharacterOverride)
			{
				DebugLog.LogInfo((object)$"Getting override for {character} with ID {CharacterOverride}");
				if (_characterBundlePaths.ContainsKey(CharacterOverride) && _customCharacters.ContainsKey(CharacterOverride))
				{
					DebugLog.LogInfo((object)"Override was found locally.");
					guid = CharacterOverride;
					return true;
				}
			}
			if (!_characterIds.TryGetValue(character, out var value) || value == null || value.Count == 0)
			{
				return false;
			}
			if (CharacterDatabaseConfig.GetCharacterOverride(character, out var id, out var isDisabled))
			{
				if (_characterBundlePaths.ContainsKey(id) && _customCharacters.ContainsKey(id))
				{
					guid = id;
					return true;
				}
			}
			else if (isDisabled)
			{
				return false;
			}
			guid = value[0];
			return true;
		}

		public static bool GetCharacter(Guid id, out CustomCharacter characterObject)
		{
			if (!_customCharacters.TryGetValue(id, out characterObject))
			{
				return false;
			}
			return true;
		}

		public static bool GetCharacter(Characters character, out CustomCharacter characterObject)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			characterObject = null;
			if (GetFirstOrConfigCharacterId(character, out var guid))
			{
				GetCharacter(guid, out characterObject);
			}
			return characterObject != null;
		}

		public static bool GetCharacterWithGraffitiTitle(string title, out CustomCharacter characterObject)
		{
			characterObject = null;
			foreach (CustomCharacter value in _customCharacters.Values)
			{
				if (value.Graffiti != null && value.Graffiti.title == title)
				{
					characterObject = value;
					return true;
				}
			}
			return false;
		}

		public static bool HasCharacter(Characters character)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (!_characterIds.TryGetValue(character, out var value))
			{
				return false;
			}
			if (value != null)
			{
				return value.Count > 0;
			}
			return false;
		}

		public static bool HasCypherEnabledForCharacter(Characters character)
		{
			//IL_0000: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			if (!GetFirstOrConfigCharacterId(character, out var guid))
			{
				return false;
			}
			if (GetCharacter(character, out var characterObject))
			{
				if ((int)characterObject.StreamData.UnlockType == 2)
				{
					return false;
				}
				if ((int)characterObject.StreamData.UnlockType == 1 && CharacterSaveSlots.GetCharacterData(guid, out var progress))
				{
					return progress.unlocked;
				}
			}
			if (_cypherMapping.TryGetValue(guid, out var value))
			{
				return value;
			}
			return false;
		}

		public static bool GetCharacterValueFromGuid(Guid guid, out Characters character)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected I4, but got Unknown
			character = (Characters)(-1);
			foreach (KeyValuePair<Characters, List<Guid>> characterId in _characterIds)
			{
				if (characterId.Value != null && characterId.Value.Contains(guid))
				{
					character = (Characters)(int)characterId.Key;
					return true;
				}
			}
			return false;
		}
	}
	public static class CharacterDatabaseConfig
	{
		private const string CONFIG_DESCRIPTION = "Enter a GUID of a character bundle to always load for {0} (Blank = Auto-detect, \"OFF\" = Default character for you)";

		private static ConfigEntry<string>[] _characterIdOverrides;

		public static void Initialize(ConfigFile config)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0037: Invalid comparison between Unknown and I4
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			Array values = Enum.GetValues(typeof(Characters));
			_characterIdOverrides = new ConfigEntry<string>[values.Length - 2];
			foreach (Characters item in values)
			{
				if ((int)item != -1 && (int)item != 26)
				{
					BrcCharacter val2 = (BrcCharacter)item;
					_characterIdOverrides[item] = config.Bind<string>("Replacement IDs", ((object)(BrcCharacter)(ref val2)).ToString(), (string)null, $"Enter a GUID of a character bundle to always load for {val2} (Blank = Auto-detect, \"OFF\" = Default character for you)");
				}
			}
		}

		public static bool GetCharacterOverride(Characters character, out Guid id, out bool isDisabled)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			id = Guid.Empty;
			isDisabled = false;
			if ((int)character > 26)
			{
				return false;
			}
			string value = _characterIdOverrides[character].Value;
			if (value == string.Empty)
			{
				return false;
			}
			if (value == "OFF")
			{
				isDisabled = true;
				return false;
			}
			if (Guid.TryParse(value, out id))
			{
				return true;
			}
			return false;
		}
	}
	public class CharacterSaveSlots
	{
		public const int SAVE_SLOT_COUNT = 4;

		public const string SLOT_FILE_EXTENSION = ".cbs";

		public const string SAVE_FILE_EXTENSION = ".cbc";

		public static readonly string SAVE_PATH = Path.Combine(Paths.ConfigPath, "CrewBoom", "saves");

		public static CharacterSaveSlot CurrentSaveSlot;

		private static Dictionary<Guid, CharacterProgress> _progressLookup = new Dictionary<Guid, CharacterProgress>();

		public static ManualLogSource DebugLog = Logger.CreateLogSource("CrewBoom Saves");

		public static int CurrentSaveSlotId { get; private set; } = -1;


		public static void LoadSlot(int slot)
		{
			if (!Directory.Exists(SAVE_PATH))
			{
				Directory.CreateDirectory(SAVE_PATH);
				return;
			}
			string path = Path.Combine(SAVE_PATH, slot + ".cbs");
			if (File.Exists(path))
			{
				try
				{
					using FileStream input = File.OpenRead(path);
					using BinaryReader reader = new BinaryReader(input);
					CurrentSaveSlot.Read(reader);
				}
				catch (Exception)
				{
					DebugLog.LogWarning((object)$"Failed to read slot data for slot {slot}");
				}
				DebugLog.LogMessage((object)$"Loaded custom character save slot {slot}");
			}
			CurrentSaveSlotId = slot;
		}

		public static void SaveSlot()
		{
			if (CurrentSaveSlotId == -1)
			{
				return;
			}
			if (!Directory.Exists(SAVE_PATH))
			{
				Directory.CreateDirectory(SAVE_PATH);
			}
			string path = Path.Combine(SAVE_PATH, CurrentSaveSlotId + ".cbs");
			try
			{
				using FileStream output = File.OpenWrite(path);
				using BinaryWriter writer = new BinaryWriter(output);
				CurrentSaveSlot.Write(writer);
			}
			catch (Exception)
			{
				DebugLog.LogError((object)$"Failed to write slot data for slot {CurrentSaveSlotId}");
			}
		}

		public static bool GetCharacterData(Guid guid, out CharacterProgress progress)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_0079: Expected O, but got Unknown
			if (_progressLookup.TryGetValue(guid, out progress))
			{
				return true;
			}
			progress = new CharacterProgress();
			progress.unlocked = false;
			if (CurrentSaveSlotId == -1)
			{
				LogUninitialized();
				return false;
			}
			if (!EnsureSlotDirectory(out var slotPath))
			{
				return false;
			}
			string path = CharacterFilePath(slotPath, guid);
			if (!File.Exists(path))
			{
				if (CharacterDatabase.GetCharacter(guid, out var characterObject))
				{
					progress = new CharacterProgress
					{
						outfit = 0,
						moveStyle = (MoveStyle)characterObject.StreamData.DefaultMoveStyle,
						moveStyleSkin = 0
					};
					_progressLookup.Add(guid, progress);
					return true;
				}
				return false;
			}
			try
			{
				using (FileStream input = File.OpenRead(path))
				{
					using BinaryReader binaryReader = new BinaryReader(input);
					progress.Read(binaryReader);
				}
				_progressLookup.Add(guid, progress);
				return true;
			}
			catch (Exception)
			{
				DebugLog.LogError((object)$"Could not load character save data for character with GUID \"{guid}\".");
			}
			return false;
		}

		public static void SaveCharacterData(Guid guid)
		{
			if (CurrentSaveSlotId == -1)
			{
				LogUninitialized();
				return;
			}
			EnsureSlotDirectory(out var slotPath);
			if (!_progressLookup.TryGetValue(guid, out var value))
			{
				DebugLog.LogError((object)$"No save data made for character with GUID \"{guid}\".");
				return;
			}
			string path = CharacterFilePath(slotPath, guid);
			try
			{
				using FileStream output = File.OpenWrite(path);
				using BinaryWriter binaryWriter = new BinaryWriter(output);
				value.Write(binaryWriter);
			}
			catch (Exception)
			{
				DebugLog.LogError((object)$"Could not write character save data for character with GUID \"{guid}\".");
			}
		}

		private static bool EnsureSlotDirectory(out string slotPath)
		{
			bool result = true;
			if (!Directory.Exists(SAVE_PATH))
			{
				Directory.CreateDirectory(SAVE_PATH);
				result = false;
			}
			slotPath = Path.Combine(SAVE_PATH, CurrentSaveSlotId.ToString());
			if (!Directory.Exists(slotPath))
			{
				Directory.CreateDirectory(slotPath);
				result = false;
			}
			return result;
		}

		private static string CharacterFilePath(string slotPath, Guid guid)
		{
			return Path.Combine(slotPath, guid.ToString() + ".cbc");
		}

		private static void LogUninitialized()
		{
			DebugLog.LogWarning((object)"Can't read or write character data before slot was initialized!");
		}
	}
	public struct CharacterSaveSlot
	{
		public Guid LastPlayedCharacter;

		public void Write(BinaryWriter writer)
		{
			writer.Write(LastPlayedCharacter.ToString());
		}

		public void Read(BinaryReader reader)
		{
			Guid.TryParse(reader.ReadString(), out LastPlayedCharacter);
		}
	}
	[BepInPlugin("CrewBoom", "CrewBoom", "4.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string CharacterAPIGuid = "com.Viliger.CharacterAPI";

		private void Awake()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			if (Chainloader.PluginInfos.ContainsKey("com.Viliger.CharacterAPI"))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"LD CrewBoom is incompatible with CharacterAPI (viliger) and will not load!\nUninstall CharacterAPI and restart the game if you want to use LD CrewBoom.");
				return;
			}
			((BaseUnityPlugin)this).Logger.LogMessage((object)"LD CrewBoom v4.2.0 starting...");
			CrewBoomSettings.Initialize(((BaseUnityPlugin)this).Config);
			CharacterDatabaseConfig.Initialize(((BaseUnityPlugin)this).Config);
			if (CharacterDatabase.Initialize())
			{
				new Harmony("softGoat.crewBoom").PatchAll();
				((BaseUnityPlugin)this).Logger.LogMessage((object)"Loaded all available characters!");
			}
			if (Chainloader.PluginInfos.ContainsKey("com.Dragsun.BunchOfEmotes"))
			{
				BunchOfEmotesSupport.Initialize();
				StageManager.OnStagePostInitialization += new OnStageInitializedDelegate(BoE_StageManager_OnStagePostInitialization);
			}
			StageManager.OnStagePostInitialization += new OnStageInitializedDelegate(StageManager_OnStagePostInitialization);
		}

		private void Update()
		{
			CharacterStreamer.Update(Time.deltaTime);
		}

		private void BoE_StageManager_OnStagePostInitialization()
		{
			BunchOfEmotesSupport.CacheAnimations();
		}

		private void StageManager_OnStagePostInitialization()
		{
			CharacterDatabase.RefreshShaders();
			Player currentPlayer = WorldHandler.instance.GetCurrentPlayer();
			if ((Object)(object)currentPlayer != (Object)null)
			{
				PlayerStreamingComponent.GetOrCreate(currentPlayer).WaitForLoadSync();
			}
		}
	}
	public static class CharUtil
	{
		public const string CHARACTER_BUNDLE = "characters";

		public const string ADD_CHARACTER_METHOD = "AddCharacterFBX";

		public const string ADD_MATERIAL_METHOD = "AddCharacterMaterial";

		public const string MATERIAL_FORMAT = "{0}Mat{1}";

		public const string SKATE_OFFSET_L = "skateOffsetL";

		public const string SKATE_OFFSET_R = "skateOffsetR";

		public const string GRAFFITI_ASSET = "charGraffiti";

		private static readonly string[] PropBones = new string[7] { "propl", "propr", "footl", "footr", "handl", "handr", "jetpackPos" };

		public static string GetOutfitMaterialName(Characters character, int outfitIndex)
		{
			return $"{((object)(Characters)(ref character)).ToString()}Mat{outfitIndex.ToString()}";
		}

		public static void ReparentAllProps(Transform originalRoot, Transform targetRoot)
		{
			string[] propBones = PropBones;
			foreach (string text in propBones)
			{
				Transform val = TransformExtentions.FindRecursive(originalRoot, text);
				Transform val2 = TransformExtentions.FindRecursive(targetRoot, text);
				if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2))
				{
					ReparentChildren(val, val2);
				}
			}
		}

		private static void ReparentChildren(Transform source, Transform target)
		{
			//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)
			Transform[] componentsInChildren = ((Component)source).GetComponentsInChildren<Transform>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (!((Object)(object)componentsInChildren[i] == (Object)null))
				{
					componentsInChildren[i].SetParent(target, false);
					componentsInChildren[i].SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
				}
			}
		}

		public static bool TrySetCustomOutfit(Component source, int outfit, out SkinnedMeshRenderer firstActiveRenderer)
		{
			firstActiveRenderer = null;
			CharacterDefinition componentInChildren = source.GetComponentInChildren<CharacterDefinition>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.SetOutfit(outfit, out firstActiveRenderer);
				return true;
			}
			return false;
		}

		public static int GetSavedCharacterOutfit(Characters character)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Invalid comparison between Unknown and I4
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			int result = 0;
			if ((int)character > 26 && CharacterDatabase.GetFirstOrConfigCharacterId(character, out var guid))
			{
				if (CharacterSaveSlots.GetCharacterData(guid, out var progress))
				{
					result = progress.outfit;
				}
			}
			else
			{
				result = Core.Instance.SaveManager.CurrentSaveSlot.GetCharacterProgress(character).outfit;
			}
			return result;
		}
	}
	public static class VoiceUtility
	{
		public static SfxCollectionID VoiceCollectionFromCharacter(Characters character)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected I4, but got Unknown
			return (SfxCollectionID)((int)character switch
			{
				0 => 40, 
				1 => 38, 
				2 => 47, 
				3 => 44, 
				4 => 31, 
				5 => 48, 
				6 => 30, 
				7 => 36, 
				8 => 35, 
				9 => 34, 
				10 => 43, 
				11 => 32, 
				12 => 50, 
				13 => 45, 
				14 => 41, 
				15 => 42, 
				16 => -1, 
				17 => 63, 
				18 => 64, 
				19 => 49, 
				20 => 39, 
				21 => 46, 
				22 => 33, 
				23 => 51, 
				24 => 37, 
				25 => 44, 
				_ => -1, 
			});
		}

		public static Characters CharacterFromVoiceCollection(SfxCollectionID collectionID)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected I4, but got Unknown
			return (Characters)((collectionID - 30) switch
			{
				0 => 6, 
				1 => 4, 
				2 => 11, 
				3 => 22, 
				4 => 9, 
				5 => 8, 
				6 => 7, 
				7 => 24, 
				8 => 1, 
				9 => 20, 
				10 => 0, 
				20 => 12, 
				21 => 23, 
				11 => 14, 
				12 => 15, 
				13 => 10, 
				14 => 3, 
				15 => 13, 
				16 => 21, 
				17 => 2, 
				18 => 5, 
				19 => 19, 
				33 => 17, 
				34 => 18, 
				_ => -1, 
			});
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "CrewBoom";

		public const string PLUGIN_NAME = "CrewBoom";

		public const string PLUGIN_VERSION = "4.2.0";
	}
}
namespace CrewBoom.Utility
{
	public static class CharacterDefinitionExtensions
	{
		public static bool HasVoices(this CharacterDefinition characterDefinition)
		{
			if (characterDefinition.VoiceDie.Length == 0 && characterDefinition.VoiceDieFall.Length == 0 && characterDefinition.VoiceTalk.Length == 0 && characterDefinition.VoiceBoostTrick.Length == 0 && characterDefinition.VoiceCombo.Length == 0 && characterDefinition.VoiceGetHit.Length == 0)
			{
				return characterDefinition.VoiceJump.Length != 0;
			}
			return true;
		}

		public static bool SetOutfit(this CharacterDefinition characterDefinition, int outfit, out SkinnedMeshRenderer firstActiveRenderer)
		{
			firstActiveRenderer = null;
			for (int i = 0; i < characterDefinition.Renderers.Length; i++)
			{
				SkinnedMeshRenderer val = characterDefinition.Renderers[i];
				((Renderer)val).sharedMaterials = characterDefinition.Outfits[outfit].MaterialContainers[i].Materials;
				((Component)val).gameObject.SetActive(characterDefinition.Outfits[outfit].EnabledRenderers[i]);
				if ((Object)(object)firstActiveRenderer == (Object)null && characterDefinition.Outfits[outfit].EnabledRenderers[i])
				{
					firstActiveRenderer = val;
				}
			}
			StoryBlinkAnimation component = ((Component)characterDefinition).GetComponent<StoryBlinkAnimation>();
			if ((Object)(object)component != (Object)null && (Object)(object)firstActiveRenderer != (Object)null)
			{
				component.mainRenderer = firstActiveRenderer;
				component.characterMesh = firstActiveRenderer.sharedMesh;
			}
			return (Object)(object)firstActiveRenderer != (Object)null;
		}
	}
	public static class ReflectionUtility
	{
		public static Type GetTypeByName(string name)
		{
			foreach (Assembly item in AppDomain.CurrentDomain.GetAssemblies().Reverse())
			{
				Type type = item.GetType(name);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}
	}
	public class TextureUtil
	{
		public static Texture2D GetTextureFromBitmap(Bitmap bitmap, FilterMode filterMode = 1)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0027: 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_0033: Expected O, but got Unknown
			//IL_0034: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			byte[] array = (byte[])((TypeConverter)new ImageConverter()).ConvertTo((object?)bitmap, typeof(byte[]));
			Texture2D val = new Texture2D(((Image)bitmap).Width, ((Image)bitmap).Height);
			ImageConversion.LoadImage(val, array);
			((Texture)val).filterMode = filterMode;
			val.Apply();
			return val;
		}
	}
}
namespace CrewBoom.Properties
{
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	public class Resources
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		public static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					resourceMan = new ResourceManager("CrewBoom.Properties.Resources", typeof(Resources).Assembly);
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		public static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		public static Bitmap default_graffiti => (Bitmap)ResourceManager.GetObject("default_graffiti", resourceCulture);

		public static Bitmap logo_background => (Bitmap)ResourceManager.GetObject("logo_background", resourceCulture);

		internal Resources()
		{
		}
	}
}
namespace CrewBoom.Patches
{
	[HarmonyPatch(typeof(CharacterLoader), "GetCharacterFbx")]
	public class GetFbxPatch
	{
		public static void Postfix(Characters character, ref GameObject __result, CharacterLoader __instance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (CharacterDatabase.GetCharacter(character, out var characterObject))
			{
				if (characterObject.Loaded)
				{
					__result = ((Component)characterObject.Definition).gameObject;
				}
				else
				{
					__result = __instance.loadedCharacterFbxAssets[3];
				}
			}
		}
	}
	[HarmonyPatch(typeof(CharacterVisual), "Init")]
	public class BlinkPatch
	{
		public static void Postfix(Characters character, ref bool ___canBlink)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (CharacterDatabase.GetCharacter(character, out var characterObject))
			{
				if (characterObject.Loaded)
				{
					___canBlink = characterObject.Definition.CanBlink;
				}
				else
				{
					___canBlink = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(CharacterVisual), "SetInlineSkatesPropsMode")]
	public class InlineSkatesTransformPatch
	{
		private static void Postfix(MoveStylePropMode mode, Transform ___footL, Transform ___footR, PlayerMoveStyleProps ___moveStyleProps, CharacterVisual __instance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			if ((int)mode != 1)
			{
				return;
			}
			Player componentInParent = ((Component)__instance).GetComponentInParent<Player>(true);
			if (!((Object)(object)componentInParent == (Object)null) && CharacterDatabase.HasCharacter(componentInParent.character))
			{
				Transform val = ___footL.Find("skateOffsetL");
				Transform val2 = ___footR.Find("skateOffsetR");
				if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
				{
					___moveStyleProps.skateL.transform.SetLocalPositionAndRotation(val.localPosition, val.localRotation);
					___moveStyleProps.skateL.transform.localScale = val.localScale;
					___moveStyleProps.skateR.transform.SetLocalPositionAndRotation(val2.localPosition, val2.localRotation);
					___moveStyleProps.skateR.transform.localScale = val2.localScale;
				}
			}
		}
	}
	[HarmonyPatch(typeof(CharacterSelectCharacter), "Init")]
	public class CharacterSelectCharacterInitPatch
	{
		public static void Postfix(CharacterVisual ___visual, Characters setCharacter)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			CharUtil.TrySetCustomOutfit((Component)(object)___visual, CharUtil.GetSavedCharacterOutfit(setCharacter), out var _);
		}
	}
	[HarmonyPatch(typeof(CharacterSelectCharacter), "SetState")]
	public class CharacterSelectCharacterSetStatePatch
	{
		public static void Prefix(CharacterSelectCharacter __instance, CharSelectCharState setState)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			if (BunchOfEmotesSupport.Installed && BunchOfEmotesSupport.IsCustomAnimation(__instance.visual.bounceAnimHash) && ((int)setState == 5 || (int)setState == 1))
			{
				__instance.visual.anim.runtimeAnimatorController = BunchOfEmotesSupport.AnimatorController;
			}
		}
	}
	[HarmonyPatch(typeof(CharacterSelect), "PopulateListOfSelectableCharacters")]
	public class CharacterSelectPopulateListPatch
	{
		public static void Postfix(Player player, List<Characters> ___selectableCharacters, CharacterSelect __instance)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (CharacterDatabase.NewCharacterCount == 0)
			{
				return;
			}
			int num = 26;
			for (int i = num + 1; i <= num + CharacterDatabase.NewCharacterCount; i++)
			{
				Characters val = (Characters)i;
				if (player.character != val && CharacterDatabase.HasCypherEnabledForCharacter(val))
				{
					___selectableCharacters.Add(val);
				}
			}
			__instance.Shuffle(___selectableCharacters);
		}
	}
	[HarmonyPatch(typeof(CharacterSelect), "SetPlayerToCharacter")]
	public class CharacterSelectSetPlayerPatch
	{
		public static bool Prefix(int index, out Characters __state, CharacterSelect __instance, CharacterSelectCharacter[] ___charactersInCircle, Player ___player)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected I4, but got Unknown
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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)
			CharacterSelectCharacter val = ___charactersInCircle[index];
			__state = (Characters)(int)val.character;
			if ((int)__state > 26)
			{
				Characters character = ___player.character;
				Characters character2 = val.character;
				___player.SetCharacter(character2, 0);
				___player.InitVisual();
				CharacterVisual characterVisual = ___player.characterVisual;
				___player.PlayAnim(characterVisual.bounceAnimHash, false, false, -1f);
				___player.SetCurrentMoveStyleEquipped(Core.Instance.SaveManager.CurrentSaveSlot.GetCharacterProgress(character2).moveStyle, true, true);
				CharacterVisual visual = val.visual;
				___player.SetRotHard(visual.tf.forward);
				Object.Destroy((Object)(object)((Component)val).gameObject);
				__instance.CreateCharacterSelectCharacter(character, index, (CharSelectCharState)1);
				return false;
			}
			return true;
		}

		public static void Postfix(Player ___player, Characters __state)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			int savedCharacterOutfit = CharUtil.GetSavedCharacterOutfit(__state);
			CharUtil.TrySetCustomOutfit((Component)(object)___player.characterVisual, savedCharacterOutfit, out var _);
		}
	}
	[HarmonyPatch(typeof(CharacterSelect), "CreateCharacterSelectCharacter")]
	public class CharacterSelectCreateCharacterPatch
	{
		public static bool Prefix(Characters character, int numInCircle, CharSelectCharState startState, CharacterSelect __instance, Player ___player, CharacterSelectCharacter[] ___charactersInCircle, List<Vector3> ___characterPositions, List<Vector3> ___characterDirections, Transform ___tf, GameObject ___charCollision, GameObject ___charTrigger, GameObject ___swapSequence)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_000a: 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_005c: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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)
			if ((int)character > 26)
			{
				CustomCharacter characterObject = null;
				if (CharacterDatabase.GetCharacter(character, out characterObject))
				{
					characterObject.WaitForLoadSync();
				}
				CharacterVisual val = ___player.CharacterConstructor.CreateNewCharacterVisual(character, ___player.animatorController, true, ___player.motor.groundDetection.groundLimit);
				___charactersInCircle[numInCircle] = ((Component)val).gameObject.AddComponent<CharacterSelectCharacter>();
				((Component)___charactersInCircle[numInCircle]).transform.position = ___characterPositions[numInCircle];
				((Component)___charactersInCircle[numInCircle]).transform.rotation = Quaternion.LookRotation(___characterDirections[numInCircle] * -1f);
				((Component)___charactersInCircle[numInCircle]).transform.parent = ___tf;
				___charactersInCircle[numInCircle].Init(__instance, character, ___charCollision, ___charTrigger, ___tf.position, Object.Instantiate<GameObject>(___swapSequence, ((Component)___charactersInCircle[numInCircle]).transform).GetComponent<PlayableDirector>());
				___charactersInCircle[numInCircle].SetState(startState);
				if (characterObject != null)
				{
					GenericCharacterStreamer.Create(((Component)val).gameObject, characterObject);
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(CharacterSelect), "GetSelectSequenceAnim")]
	public class CharacterSelectSequencePatch
	{
		public static void Prefix(ref Characters c)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected I4, but got Unknown
			if (CharacterDatabase.GetCharacter(c, out var characterObject))
			{
				if (characterObject.Loaded)
				{
					c = (Characters)(int)characterObject.Definition.FreestyleAnimation;
				}
				else
				{
					c = (Characters)3;
				}
			}
		}
	}
	[HarmonyPatch(typeof(CharacterSelectUI), "SetCharacterInformation")]
	public class CharacterSelectUIInfoPatch
	{
		public static bool Prefix(Characters character, TextMeshProUGUI ___characterNameLabel, TextMeshProUGUI ___characterUnlockedOutfitCountLabel, CharacterSelectUI __instance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if ((int)character > 26 && CharacterDatabase.GetCharacter(character, out var characterObject))
			{
				((TMP_Text)___characterNameLabel).text = characterObject.StreamData.Name;
				((TMP_Text)___characterUnlockedOutfitCountLabel).text = "4/4";
				if (CharacterSaveSlots.GetCharacterData(Guid.Parse(characterObject.StreamData.Id), out var progress))
				{
					__instance.SetCharacterSelectUIMoveStyle(progress.moveStyle);
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(CharacterVisual), "GetCharacterFreestyleAnim")]
	public class CharacterFreestylePatch
	{
		public static void Prefix(ref Characters c)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected I4, but got Unknown
			if (CharacterDatabase.GetCharacter(c, out var characterObject))
			{
				if (characterObject.Loaded)
				{
					c = (Characters)(int)characterObject.Definition.FreestyleAnimation;
				}
				else
				{
					c = (Characters)3;
				}
			}
		}
	}
	[HarmonyPatch(typeof(CharacterVisual), "GetCharacterBounceAnim")]
	public class CharacterBouncePatch
	{
		public static bool Prefix(ref Characters c, ref int __result)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected I4, but got Unknown
			if (CharacterDatabase.GetCharacter(c, out var characterObject))
			{
				if (!string.IsNullOrWhiteSpace(characterObject.StreamData.BoEIdleDance))
				{
					if (!characterObject.StreamData.BoEIdleDanceVanilla && BunchOfEmotesSupport.Installed)
					{
						if (BunchOfEmotesSupport.TryGetGameAnimationForCustomAnimationName(characterObject.StreamData.BoEIdleDance, out var gameAnim))
						{
							__result = gameAnim;
							return false;
						}
					}
					else if (characterObject.StreamData.BoEIdleDanceVanilla)
					{
						__result = Animator.StringToHash(characterObject.StreamData.BoEIdleDance);
						return false;
					}
				}
				c = (Characters)(int)characterObject.StreamData.IdleDance;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(CharacterConstructor), "CreateNewCharacterVisual")]
	public class ConstructorCreateVisualPatch
	{
		public static bool Prefix(Characters character, RuntimeAnimatorController controller, bool IK, float setGroundAngleLimit, CharacterConstructor __instance, ref CharacterVisual __result)
		{
			//IL_0000: 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)
			if (CharacterDatabase.GetCharacter(character, out var characterObject))
			{
				CharacterVisual val = null;
				val = ((!characterObject.Loaded) ? Object.Instantiate<GameObject>(CharacterStreamer.StreamingVisuals).AddComponent<CharacterVisual>() : Object.Instantiate<GameObject>(characterObject.Visual).AddComponent<CharacterVisual>());
				val.Init(character, controller, IK, setGroundAngleLimit);
				((Component)val).gameObject.SetActive(true);
				__result = val;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(GraffitiLoader), "LoadGraffitiArtInfoAsync")]
	public class GraffitiLoadAsyncPatch
	{
		[CompilerGenerated]
		private sealed class <Postfix>d__0 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Assets assets;

			public GraffitiLoader __instance;

			private AssetBundleRequest <graffitiArtInfoRequest>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <Postfix>d__0(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<graffitiArtInfoRequest>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: Expected O, but got Unknown
				//IL_009d: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<graffitiArtInfoRequest>5__2 = assets.LoadAssetFromBundleASync<GraffitiArtInfo>("graffiti", "graffitiartinfo");
					<>2__current = <graffitiArtInfoRequest>5__2;
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					GraffitiArtInfo val = (GraffitiArtInfo)<graffitiArtInfoRequest>5__2.asset;
					CharacterDatabase.SetGraffitiShader(val.graffitiArt.Find((GraffitiArt g) => g.title == "Red").graffitiMaterial.shader);
					for (int i = 0; i < Enum.GetValues(typeof(Characters)).Length - 1; i++)
					{
						Characters val2 = (Characters)i;
						if (CharacterDatabase.GetCharacter(val2, out var characterObject) && characterObject.StreamData.HasGraffiti)
						{
							GraffitiArt obj = val.FindByCharacter(val2);
							Texture2D graffitiTexture = characterObject.StreamData.GraffitiTexture;
							obj.graffitiMaterial.mainTexture = (Texture)(object)graffitiTexture;
						}
					}
					ref GraffitiArtInfo graffitiArtInfo = ref __instance.graffitiArtInfo;
					Object asset = <graffitiArtInfoRequest>5__2.asset;
					graffitiArtInfo = (GraffitiArtInfo)(object)((asset is GraffitiArtInfo) ? asset : null);
					return false;
				}
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[IteratorStateMachine(typeof(<Postfix>d__0))]
		private static IEnumerator Postfix(IEnumerator __result, Assets assets, GraffitiLoader __instance)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Postfix>d__0(0)
			{
				assets = assets,
				__instance = __instance
			};
		}
	}
	[HarmonyPatch(typeof(GraffitiArtInfo), "FindByCharacter")]
	public class GraffitiFindCharacterPatch
	{
		public static bool Prefix(ref Characters character, ref GraffitiArt __result)
		{
			if ((int)character > 26)
			{
				if (CharacterDatabase.GetCharacter(character, out var characterObject))
				{
					__result = characterObject.Graffiti;
					return false;
				}
				character = (Characters)3;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(GraffitiArtInfo), "FindByTitle")]
	public class GraffitiFindTitlePatch
	{
		public static void Postfix(ref GraffitiArt __result, string grafTitle)
		{
			if ((__result != null || !string.IsNullOrEmpty(grafTitle)) && CharacterDatabase.GetCharacterWithGraffitiTitle(grafTitle, out var characterObject))
			{
				__result = characterObject.Graffiti;
			}
		}
	}
	[HarmonyPatch(typeof(GraffitiGame), "SetStateVisual")]
	public class GraffitiVisualPatch
	{
		public static void Postfix(GraffitiGameState setState, Player ___player, GraffitiArt ___grafArt, GraffitiArtInfo ___graffitiArtInfo)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0005: 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)
			if ((int)setState == 2 && CharacterDatabase.GetCharacter(___player.character, out var characterObject) && characterObject.Graffiti != null && ___grafArt == ___graffitiArtInfo.FindByCharacter(___player.character))
			{
				((TMP_Text)___player.ui.graffitiTitle).text = "'" + characterObject.Graffiti.title + "'";
			}
		}
	}
	[HarmonyPatch(typeof(MainMenuManager), "Init")]
	public class MainMenuPatch
	{
		public static void Postfix(MainMenuManager __instance)
		{
			//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_0028: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			Texture2D textureFromBitmap = TextureUtil.GetTextureFromBitmap(Resources.logo_background, (FilterMode)1);
			GameObject val = new GameObject("CrewBoom Logo");
			val.transform.SetParent(((Component)__instance).transform, false);
			val.AddComponent<Image>().sprite = Sprite.Create(textureFromBitmap, new Rect(0f, 0f, (float)((Texture)textureFromBitmap).width, (float)((Texture)textureFromBitmap).height), new Vector2(0.5f, 0.5f), 100f);
			RectTransform obj = GameObjectExtensions.RectTransform(val);
			obj.sizeDelta = new Vector2((float)((Texture)textureFromBitmap).width, (float)((Texture)textureFromBitmap).height);
			obj.anchorMin = new Vector2(0f, 1f);
			obj.anchorMax = obj.anchorMin;
			obj.pivot = obj.anchorMin;
			obj.anchoredPosition = Vector2.one * 32f;
		}
	}
	[HarmonyPatch(typeof(TextMeshProGameTextLocalizer), "GetCharacterName", new Type[] { typeof(Characters) })]
	public class CharacterNamePatch
	{
		public static void Postfix(Characters character, ref string __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (CharacterDatabase.GetCharacter(character, out var characterObject))
			{
				__result = characterObject.StreamData.Name;
			}
		}
	}
	[HarmonyPatch(typeof(TextMeshProGameTextLocalizer), "GetCharacterName", new Type[] { typeof(int) })]
	public class CharacterKeyNamePatch
	{
		public static void Postfix(int localizationKeyID, ref string __result)
		{
			if (CharacterDatabase.GetCharacterNameWithId(localizationKeyID, out var name))
			{
				__result = name;
			}
		}
	}
	[HarmonyPatch(typeof(TextMeshProGameTextLocalizer), "GetSkinText")]
	public class SkinTextPatch
	{
		public static Characters Character;

		public const string SPRING_OUTFIT = "U_SKIN_SPRING";

		public const string SUMMER_OUTFIT = "U_SKIN_SUMMER";

		public const string AUTUMN_OUTFIT = "U_SKIN_AUTUMN";

		public const string WINTER_OUTFIT = "U_SKIN_WINTER";

		public static readonly string[] OUTFIT_NAMES = new string[4] { "U_SKIN_SPRING", "U_SKIN_SUMMER", "U_SKIN_AUTUMN", "U_SKIN_WINTER" };

		public static void Postfix(string localizationKey, ref string __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (CharacterDatabase.GetCharacter(Character, out var characterObject))
			{
				int num;
				switch (localizationKey)
				{
				default:
					return;
				case "U_SKIN_SPRING":
					num = 0;
					break;
				case "U_SKIN_SUMMER":
					num = 1;
					break;
				case "U_SKIN_AUTUMN":
					num = 2;
					break;
				case "U_SKIN_WINTER":
					num = 3;
					break;
				}
				characterObject.WaitForLoadSync();
				string name = characterObject.Definition.Outfits[num].Name;
				if (name != null && name != string.Empty)
				{
					__result = name;
				}
			}
		}
	}
	[HarmonyPatch(typeof(NPC), "InitSceneObject")]
	public class NPCInitPatch
	{
		public static void Prefix(NPC __instance, Characters ___character)
		{
			//IL_01b5: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			OutfitSwappableCharacter[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<OutfitSwappableCharacter>(true);
			if (componentsInChildren != null && componentsInChildren.Length != 0)
			{
				OutfitSwappableCharacter[] array = componentsInChildren;
				foreach (OutfitSwappableCharacter val in array)
				{
					if (CharacterDatabase.GetCharacter(val.Character, out var characterObject))
					{
						characterObject.WaitForLoadSync();
						DynamicBone[] components = ((Component)val).GetComponents<DynamicBone>();
						for (int j = 0; j < components.Length; j++)
						{
							((Behaviour)components[j]).enabled = false;
						}
						CharacterDefinition val2 = Object.Instantiate<CharacterDefinition>(characterObject.Definition, ((Component)val).transform);
						Animator componentInChildren = ((Component)val).GetComponentInChildren<Animator>(true);
						Animator component = ((Component)val2).GetComponent<Animator>();
						component.runtimeAnimatorController = componentInChildren.runtimeAnimatorController;
						Transform val3 = ((Component)componentInChildren).transform.Find("root");
						if ((Object)(object)val3 != (Object)null)
						{
							CharUtil.ReparentAllProps(val3, ((Component)component).transform.Find("root"));
						}
						((Component)val2).transform.SetLocalPositionAndRotation(((Component)componentInChildren).transform.localPosition, ((Component)componentInChildren).transform.localRotation);
						SkinnedMeshRenderer val4 = (val.mainRenderer = val2.Renderers[0]);
						((Component)val2).gameObject.AddComponent<LookAtIKComponent>();
						((Component)val2).gameObject.AddComponent<DummyAnimationEventRelay>();
						if (characterObject.Definition.CanBlink)
						{
							StoryBlinkAnimation obj = ((Component)val2).gameObject.AddComponent<StoryBlinkAnimation>();
							obj.mainRenderer = val4;
							obj.characterMesh = val4.sharedMesh;
						}
						MeshCollider component2 = ((Component)componentInChildren).GetComponent<MeshCollider>();
						if (Object.op_Implicit((Object)(object)component2))
						{
							MeshCollider obj2 = ((Component)val2).gameObject.AddComponent<MeshCollider>();
							obj2.sharedMesh = component2.sharedMesh;
							((Collider)obj2).sharedMaterial = ((Collider)component2).sharedMaterial;
							obj2.convex = component2.convex;
							((Collider)obj2).isTrigger = ((Collider)component2).isTrigger;
						}
						Object.DestroyImmediate((Object)(object)((Component)componentInChildren).gameObject);
					}
				}
			}
			else
			{
				ReplaceNonSwappableCharacter(__instance, ___character);
			}
		}

		private static void ReplaceNonSwappableCharacter(NPC __instance, Characters ___character)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			if (!CharacterDatabase.GetCharacter(___character, out var characterObject))
			{
				return;
			}
			DummyAnimationEventRelay componentInChildren = ((Component)__instance).GetComponentInChildren<DummyAnimationEventRelay>(true);
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				characterObject.WaitForLoadSync();
				DynamicBone[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<DynamicBone>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Behaviour)componentsInChildren[i]).enabled = false;
				}
				Animator component = ((Component)componentInChildren).GetComponent<Animator>();
				GameObject gameObject = Object.Instantiate<GameObject>(((Component)characterObject.Definition).gameObject, ((Component)component).transform.parent).gameObject;
				Animator component2 = gameObject.GetComponent<Animator>();
				component2.runtimeAnimatorController = component.runtimeAnimatorController;
				Transform val = ((Component)component).transform.Find("root");
				if ((Object)(object)val != (Object)null)
				{
					CharUtil.ReparentAllProps(val, ((Component)component2).transform.Find("root"));
				}
				gameObject.transform.SetLocalPositionAndRotation(((Component)component).transform.localPosition, ((Component)component).transform.localRotation);
				gameObject.AddComponent<LookAtIKComponent>();
				gameObject.AddComponent<DummyAnimationEventRelay>();
				MeshCollider component3 = ((Component)component).GetComponent<MeshCollider>();
				if (Object.op_Implicit((Object)(object)component3))
				{
					MeshCollider obj = gameObject.AddComponent<MeshCollider>();
					obj.sharedMesh = component3.sharedMesh;
					((Collider)obj).sharedMaterial = ((Collider)component3).sharedMaterial;
					obj.convex = component3.convex;
					((Collider)obj).isTrigger = ((Collider)component3).isTrigger;
				}
				Object.DestroyImmediate((Object)(object)((Component)component).gameObject);
			}
		}
	}
	[HarmonyPatch(typeof(OutfitSwappableCharacter), "SetMaterialAndOutfit")]
	public class OutfitSwappablePatches
	{
		public static bool Prefix(OutfitSwappableCharacter __instance, ref SkinnedMeshRenderer ___mainRenderer, int outfitIndex)
		{
			if (CharUtil.TrySetCustomOutfit((Component)(object)__instance, outfitIndex, out var firstActiveRenderer))
			{
				___mainRenderer = firstActiveRenderer;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(OutfitSwitchMenu), "SkinButtonSelected")]
	public class OutfitSwitchSelectPatch
	{
		public static bool Prefix(OutfitSwitchMenu __instance, MenuTimelineButton ___buttonClicked, CharacterVisual ___previewCharacterVisual, int skinIndex)
		{
			if (__instance.IsTransitioning || (Object)(object)___buttonClicked != (Object)null)
			{
				return false;
			}
			if (CharUtil.TrySetCustomOutfit((Component)(object)___previewCharacterVisual, skinIndex, out var _))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(OutfitSwitchMenu), "SkinButtonClicked")]
	public class OutfitSwitchClickPatch
	{
		public static bool Prefix(OutfitSwitchMenu __instance, MenuTimelineButton clickedButton, int skinIndex, ref MenuTimelineButton ___buttonClicked, Player ___player)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000d: 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_007f: Expected O, but got Unknown
			if ((int)___player.character > 26)
			{
				if (CharacterDatabase.GetCharacter(___player.character, out var _))
				{
					if (__instance.IsTransitioning || (Object)(object)___buttonClicked != (Object)null)
					{
						return false;
					}
					___buttonClicked = clickedButton;
					Core.Instance.AudioManager.PlaySfxUI((SfxCollectionID)23, (AudioClipID)547, 0f);
					___player.SetOutfit(skinIndex);
					WantedManager.instance.StopPlayerWantedStatus(true, true);
					((MonoBehaviour)__instance).StartCoroutine(((BaseMenuTimelineBehaviour)__instance.clipBehaviour).FlickerDelayedButtonPress(clickedButton, new UnityAction(((BaseMenuTimelineBehaviour)__instance.clipBehaviour).ExitMenu)));
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(OutfitSwitchMenu), "Activate")]
	public class OutfitSwitchActivatePatch
	{
		private static OutfitSwitchMenu _lastMenu;

		public static bool Prefix(OutfitSwitchMenu __instance, Player ___player, MenuTimelineButton[] ___buttons, TMProLocalizationAddOn[] ___texts, GameFontType ___normalGameFontType, GameFontType ___selectedGameFontType, float ___nonSelectableAlphaValue)
		{
			//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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			//IL_0031: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			_lastMenu = __instance;
			SkinTextPatch.Character = ___player.character;
			if ((int)___player.character > 26)
			{
				if (CharacterDatabase.GetCharacter(___player.character, out var _))
				{
					CharacterProgress characterProgress = Core.Instance.SaveManager.CurrentSaveSlot.GetCharacterProgress(___player.character);
					_ = ___player.CharacterConstructor;
					MenuTimelineButton val = null;
					for (int i = 0; i < 4; i++)
					{
						string text = null;
						if (characterProgress.outfit == i)
						{
							text = "<u>";
						}
						___texts[i].AssignAndUpdateTextWithTags(SkinTextPatch.OUTFIT_NAMES[i], (GroupOptions)5, text, (string)null, Array.Empty<string>());
						MenuTimelineButton val2 = null;
						if (i < 3)
						{
							val2 = ___buttons[i + 1];
						}
						MenuTimelineButton button = ___buttons[i];
						int skinIndex = i;
						button.SetButtonVariables((OnSelectButtonAction)delegate
						{
							__instance.SkinButtonSelected(button, skinIndex);
						}, true, (Button)(object)val, (Button)(object)val2, ___normalGameFontType, ___selectedGameFontType, ___nonSelectableAlphaValue);
						((Selectable)button).interactable = true;
						((UnityEventBase)((Button)button).onClick).RemoveAllListeners();
						((UnityEvent)((Button)button).onClick).AddListener((UnityAction)delegate
						{
							__instance.SkinButtonClicked(button, skinIndex);
						});
						((Component)button).gameObject.SetActive(true);
						val = button;
					}
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Player), "SetCharacter")]
	public class PlayerInitOverridePatch
	{
		public static void Prefix(Player __instance, ref Characters setChar, int setOutfit)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected I4, but got Unknown
			if (CharacterDatabase.HasCharacterOverride && CharacterDatabase.GetCharacterValueFromGuid(CharacterDatabase.CharacterOverride, out var character) && (int)character > 26)
			{
				setChar = (Characters)(int)character;
			}
			bool preloaded = false;
			if (CharacterDatabase.GetCharacter(setChar, out var characterObject))
			{
				if (characterObject.Loaded)
				{
					preloaded = true;
				}
				else if (!CrewBoomSettings.LoadCharactersAsync)
				{
					characterObject.WaitForLoadSync();
					preloaded = true;
				}
			}
			PlayerStreamingComponent.GetOrCreate(__instance).SetCharacter(setChar, setOutfit, preloaded);
		}

		public static void Postfix(Player __instance, Characters setChar)
		{
			//IL_001e: 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_0058: Expected O, but got Unknown
			if (CharacterDatabase.HasCharacterOverride)
			{
				CharacterDatabase.SetCharacterOverrideDone();
			}
			if (!((Object)(object)__instance == (Object)(object)WorldHandler.instance.GetCurrentPlayer()))
			{
				return;
			}
			if (CharacterDatabase.GetCharacter(setChar, out var characterObject))
			{
				string text = "";
				if (characterObject.Graffiti != null)
				{
					text = characterObject.Graffiti.title;
				}
				CrewBoomAPIDatabase.UpdatePlayerCharacter(new CharacterInfo(characterObject.StreamData.Name, text));
			}
			else
			{
				CrewBoomAPIDatabase.UpdatePlayerCharacter((CharacterInfo)null);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "SetOutfit")]
	public class PlayerSetOutfitPatch
	{
		public static bool Prefix(int setOutfit, Player __instance, CharacterVisual ___characterVisual, Characters ___character)
		{
			//IL_000c: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			PlayerStreamingComponent.GetOrCreate(__instance).SetOutfit(setOutfit);
			if (!CharacterDatabase.HasCharacter(___character))
			{
				return true;
			}
			if (!__instance.isAI)
			{
				Core.Instance.SaveManager.CurrentSaveSlot.GetCharacterProgress(___character).outfit = setOutfit;
				if ((int)___character > 26 && CharacterDatabase.GetFirstOrConfigCharacterId(___character, out var guid))
				{
					CharacterSaveSlots.SaveCharacterData(guid);
				}
			}
			if (CharUtil.TrySetCustomOutfit((Component)(object)___characterVisual, setOutfit, out var firstActiveRenderer))
			{
				___characterVisual.mainRenderer = firstActiveRenderer;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "SetCurrentMoveStyleEquipped")]
	public class PlayerSetMovestyleEquipped
	{
		public static void Postfix(Player __instance, MoveStyle setMoveStyleEquipped)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0013: 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)
			if (!__instance.isAI && (int)__instance.character > 26 && CharacterDatabase.GetFirstOrConfigCharacterId(__instance.character, out var guid) && CharacterSaveSlots.GetCharacterData(guid, out var progress))
			{
				progress.moveStyle = setMoveStyleEquipped;
				CharacterSaveSlots.SaveCharacterData(guid);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "SaveSelectedCharacter")]
	public class PlayerSaveCharacterPatch
	{
		public static bool Prefix(Player __instance, ref Characters selectedCharacter)
		{
			bool result = true;
			bool flag = (int)selectedCharacter > 26;
			if (!__instance.isAI)
			{
				CharacterSaveSlots.CurrentSaveSlot.LastPlayedCharacter = Guid.Empty;
				if (flag)
				{
					if (CharacterDatabase.GetFirstOrConfigCharacterId(selectedCharacter, out var guid))
					{
						CharacterSaveSlots.CurrentSaveSlot.LastPlayedCharacter = guid;
					}
					result = false;
				}
				CharacterSaveSlots.SaveSlot();
			}
			else if ((int)selectedCharacter > 26)
			{
				result = false;
			}
			return result;
		}
	}
	public struct UpdateAnimState
	{
		public int originalAnim;

		public int newAnim;

		public bool doingBoEDance;
	}
	[HarmonyPatch(typeof(Player), "UpdateAnim")]
	public class PlayerUpdateAnimPatch
	{
		public static void Prefix(Player __instance, ref UpdateAnimState __state)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			__state.originalAnim = __instance.curAnim;
			__state.doingBoEDance = false;
			if (CharacterDatabase.GetCharacter(__instance.character, out var characterObject))
			{
				if (characterObject.StreamData.BoEIdleDanceVanilla && __instance.curAnim == __instance.characterVisual.bounceAnimHash)
				{
					__state.doingBoEDance = true;
				}
				else if (!characterObject.StreamData.BoEIdleDanceVanilla && BunchOfEmotesSupport.Installed && BunchOfEmotesSupport.IsCustomAnimation(__instance.curAnim) && __instance.curAnim == __instance.characterVisual.bounceAnimHash)
				{
					__state.doingBoEDance = true;
				}
			}
			if (__state.doingBoEDance)
			{
				__state.newAnim = __instance.softBounce1Hash;
				__instance.curAnim = __state.newAnim;
			}
		}

		public static void Postfix(Player __instance, UpdateAnimState __state)
		{
			if (__state.doingBoEDance && __state.newAnim == __instance.curAnim)
			{
				__instance.curAnim = __state.originalAnim;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "PlayVoice")]
	public class PlayerVoicePatch
	{
		public static bool Prefix(AudioClipID audioClipID, VoicePriority voicePriority, bool fromPlayer, AudioManager ___audioManager, ref VoicePriority ___currentVoicePriority, Characters ___character, AudioSource ___playerGameplayVoicesAudioSource)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			//IL_0006: 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)
			if ((int)___character > 26 && CharacterDatabase.GetCharacter(___character, out var characterObject) && !fromPlayer)
			{
				___audioManager.PlaySfxGameplay(characterObject.SfxID, audioClipID, 0f);
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PublicToilet), "DoSequence")]
	public class PublicToiletDoSequencePatch
	{
		public static void Prefix()
		{
			Player currentPlayer = WorldHandler.instance.GetCurrentPlayer();
			if ((Object)(object)currentPlayer != (Object)null)
			{
				PlayerStreamingComponent.GetOrCreate(currentPlayer).WaitForLoadSync();
			}
		}
	}
	[HarmonyPatch(typeof(SaveSlotData), "GetCharacterProgress")]
	public class SaveSlotGetProgressPatch
	{
		public static bool Prefix(Characters character, ref CharacterProgress __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if ((int)character > 26)
			{
				if (CharacterDatabase.GetFirstOrConfigCharacterId(character, out var guid) && CharacterSaveSlots.GetCharacterData(guid, out var progress))
				{
					__result = progress;
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(SaveSlotHandler), "SetCurrentSaveSlotDataBySlotId")]
	public class SaveSlotHandlerLoadPatch
	{
		public static void Postfix(int saveSlotId)
		{
			CharacterSaveSlots.LoadSlot(saveSlotId);
		}
	}
	[HarmonyPatch(typeof(SequenceHandler), "ReplaceMaterialsOnCharactersInCutscene")]
	public class SequenceCharacterModelPatch
	{
		private static Dictionary<string, Characters> CutsceneOnlyCharacters = new Dictionary<string, Characters>
		{
			{
				"FauxNoJetpackStory",
				(Characters)23
			},
			{
				"FauxStory",
				(Characters)12
			},
			{
				"SolaceStory",
				(Characters)8
			},
			{
				"IreneStory",
				(Characters)14
			},
			{
				"DJMaskedStory",
				(Characters)9
			},
			{
				"DJNoMaskStory",
				(Characters)9
			},
			{
				"FuturismStory",
				(Characters)20
			},
			{
				"FuturismBStory",
				(Characters)20
			},
			{
				"FuturismCStory",
				(Characters)20
			},
			{
				"FuturismDStory",
				(Characters)20
			},
			{
				"EclipseAStory",
				(Characters)10
			},
			{
				"EclipseBStory",
				(Characters)10
			},
			{
				"EclipseCStory",
				(Characters)10
			},
			{
				"EclipseDStory",
				(Characters)10
			},
			{
				"DotExeEStory",
				(Characters)24
			},
			{
				"DotExeAStory",
				(Characters)7
			},
			{
				"DotExeBStory",
				(Characters)7
			},
			{
				"DotExeCStory",
				(Characters)7
			},
			{
				"DotExeDStory",
				(Characters)7
			},
			{
				"RedShatteredStory",
				(Characters)25
			},
			{
				"DemonTheoryAStory",
				(Characters)11
			},
			{
				"DemonTheoryBStory",
				(Characters)11
			},
			{
				"DemonTheoryCStory",
				(Characters)11
			},
			{
				"FelixNoJetpackStory",
				(Characters)15
			},
			{
				"FrankAStory",
				(Characters)1
			},
			{
				"FrankBStory",
				(Characters)1
			},
			{
				"FrankCStory",
				(Characters)1
			},
			{
				"FrankDStory",
				(Characters)1
			},
			{
				"FleshPrinceStory",
				(Characters)13
			}
		};

		public static void Prefix(PlayableDirector ___sequence)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			OutfitSwappableCharacter[] componentsInChildren = ((Component)___sequence).GetComponentsInChildren<OutfitSwappableCharacter>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				SwapOutfitSwappable(componentsInChildren[i]);
			}
			Transform[] componentsInChildren2 = ((Component)___sequence).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren2)
			{
				foreach (string key in CutsceneOnlyCharacters.Keys)
				{
					if (((Object)val).name.StartsWith(key))
					{
						SwapCutsceneOnlyCharacter(val, CutsceneOnlyCharacters[key]);
					}
				}
			}
		}

		private static void SwapOutfitSwappable(OutfitSwappableCharacter swappable)
		{
			//IL_0001: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			if (!CharacterDatabase.GetCharacter(swappable.Character, out var characterObject))
			{
				return;
			}
			characterObject.WaitForLoadSync();
			DynamicBone[] components = ((Component)((Component)swappable).transform).GetComponents<DynamicBone>();
			for (int i = 0; i < components.Length; i++)
			{
				((Behaviour)components[i]).enabled = false;
			}
			GameObject gameObject = Object.Instantiate<GameObject>(((Component)characterObject.Definition).gameObject, ((Component)swappable).transform).gameObject;
			Animator val = null;
			IEnumerator enumerator = ((Component)swappable).transform.GetEnumerator();
			try
			{
				while (enumerator.MoveNext() && !((Object)(object)(val = ((Component)(Transform)enumerator.Current).GetComponent<Animator>()) != (Object)null))
				{
				}
			}
			finally
			{
				IDisposable disposable = enumerator as IDisposable;
				if (disposable != null)
				{
					disposable.Dispose();
				}
			}
			Animator component = gameObject.GetComponent<Animator>();
			val.avatar = component.avatar;
			SkinnedMeshRenderer val2 = (swappable.mainRenderer = ((Component)component).GetComponentInChildren<SkinnedMeshRenderer>(true));
			foreach (Transform item in ((Component)val).transform)
			{
				Transform val3 = item;
				if (((Object)val3).name == "root")
				{
					((Object)val3).name = ((Object)val3).name + "_old";
					CharUtil.ReparentAllProps(val3, ((Component)component).transform.Find("root"));
				}
				else
				{
					Object.Destroy((Object)(object)((Component)val3).gameObject);
				}
			}
			gameObject.transform.SetParent(((Component)val).transform, false);
			gameObject.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
			Transform[] componentsInChildren = gameObject.GetComponentsInChildren<Transform>();
			foreach (Transform val4 in componentsInChildren)
			{
				if (!((Object)(object)val4.parent != (Object)(object)gameObject.transform))
				{
					val4.SetParent(((Component)val).transform, false);
				}
			}
			StoryBlinkAnimation component2 = ((Component)val).GetComponent<StoryBlinkAnimation>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				if (characterObject.Definition.CanBlink)
				{
					component2.mainRenderer = val2;
					component2.characterMesh = val2.sharedMesh;
				}
				else
				{
					((Behaviour)component2).enabled = false;
				}
			}
			Object.Destroy((Object)(object)gameObject);
			val.Rebind(true);
		}

		private static void SwapCutsceneOnlyCharacter(Transform root, Characters character)
		{
			//IL_0000: 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)
			if (CharacterDatabase.HasCharacter(character))
			{
				OutfitSwappableCharacter obj = ((Component)root).gameObject.AddComponent<OutfitSwappableCharacter>();
				obj.character = character;
				SwapOutfitSwappable(obj);
			}
		}
	}
	[HarmonyPatch(typeof(StageManager), "GetPlayerCharacter")]
	public class SetupPatch
	{
		public static bool Prefix(ref Characters __result)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected I4, but got Unknown
			Guid lastPlayedCharacter = CharacterSaveSlots.CurrentSaveSlot.LastPlayedCharacter;
			if (lastPlayedCharacter != Guid.Empty && CharacterDatabase.GetCharacterValueFromGuid(lastPlayedCharacter, out var character))
			{
				__result = (Characters)(int)character;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(StyleSwitchMenu), "SkinButtonClicked")]
	public class StyleSwitchMenuPatch
	{
		public static void Postfix()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Player currentPlayer = WorldHandler.instance.GetCurrentPlayer();
			if ((int)currentPlayer.character > 26 && CharacterDatabase.GetFirstOrConfigCharacterId(currentPlayer.character, out var guid))
			{
				CharacterSaveSlots.SaveCharacterData(guid);
			}
		}
	}
	[HarmonyPatch(typeof(SfxLibrary), "Init")]
	public class InitSfxLibraryPatch
	{
		public static void Postfix(SfxLibrary __instance)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Invalid comparison between Unknown and I4
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyValuePair<SfxCollectionID, SfxCollection> item in __instance.sfxCollectionIDDictionary)
			{
				CharacterDatabase.InitializeMissingSfxCollections(VoiceUtility.CharacterFromVoiceCollection(item.Key), item.Value);
			}
			int num = 26;
			for (int i = num + 1; i <= num + CharacterDatabase.NewCharacterCount; i++)
			{
				if (CharacterDatabase.GetCharacter((Characters)i, out var characterObject) && (int)characterObject.SfxID != -1)
				{
					__instance.sfxCollectionIDDictionary.Add(characterObject.SfxID, characterObject.Sfx);
				}
			}
		}
	}
	[HarmonyPatch(typeof(SfxLibrary), "GetSfxCollectionById")]
	public class GetSfxCollectionIdPatch
	{
		public static void Postfix(SfxCollectionID sfxCollectionId, ref SfxCollection __result, SfxLibrary __instance)
		{
			//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)
			if (CharacterDatabase.GetCharacter(VoiceUtility.CharacterFromVoiceCollection(sfxCollectionId), out var characterObject))
			{
				__result = characterObject.Sfx;
			}
		}
	}
	[HarmonyPatch(typeof(AudioManager), "GetCharacterVoiceSfxCollection")]
	public class GetSfxCharacterCollectionPatch
	{
		public static bool Prefix(Characters character, ref SfxCollectionID __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: 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_0017: Expected I4, but got Unknown
			if ((int)character > 26)
			{
				if (CharacterDatabase.GetCharacter(character, out var characterObject))
				{
					__result = (SfxCollectionID)(int)characterObject.SfxID;
					return false;
				}
				__result = (SfxCollectionID)(-1);
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(AudioManager), "PlayVoice")]
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	public class PlayVoicePatch
	{
		public static bool Prefix(ref VoicePriority currentPriority, Characters character, AudioClipID audioClipID, AudioSource audioSource, VoicePriority playbackPriority, AudioManager __instance, AudioMixerGroup[] ___mixerGroups)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: 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_0013: Invalid comparison between Unknown and I4
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected I4, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if ((int)character > 26)
			{
				if (CharacterDatabase.GetCharacter(character, out var characterObject))
				{
					if ((int)playbackPriority <= (int)currentPriority && audioSource.isPlaying)
					{
						return false;
					}
					AudioClip val = null;
					if ((Object)(object)characterObject.Sfx != (Object)null)
					{
						val = characterObject.Sfx.GetRandomAudioClipById(audioClipID);
					}
					__instance.PlayNonloopingSfx(audioSource, val, ___mixerGroups[5], 0f);
					currentPriority = (VoicePriority)(int)playbackPriority;
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(AudioManager), "PlayVoice", new Type[]
	{
		typeof(Characters),
		typeof(AudioClipID)
	})]
	public class PlayVoiceForCharacterPatch
	{
		public static bool Prefix(Characters character, AudioClipID audioClipID, AudioManager __instance, AudioMixerGroup[] ___mixerGroups, AudioSource[] ___audioSources, ref VoicePriority __result)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: 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)
			__result = (VoicePriority)0;
			if ((int)character > 26)
			{
				if (CharacterDatabase.GetCharacter(character, out var characterObject))
				{
					AudioClip val = null;
					if ((Object)(object)characterObject.Sfx != (Object)null)
					{
						val = characterObject.Sfx.GetRandomAudioClipById(audioClipID);
					}
					__instance.PlayNonloopingSfx(___audioSources[5], val, ___mixerGroups[5], 0f);
				}
				return false;
			}
			return true;
		}
	}
}
namespace CrewBoom.Data
{
	public class CustomCharacter
	{
		private static readonly List<AudioClipID> VOICE_IDS = new List<AudioClipID>
		{
			(AudioClipID)484,
			(AudioClipID)485,
			(AudioClipID)486,
			(AudioClipID)498,
			(AudioClipID)487,
			(AudioClipID)488,
			(AudioClipID)489
		};

		private string _path;

		private AssetBundle _bundle;

		public AssetBundleCreateRequest BundleRequest;

		public int References;

		public Action<CustomCharacter> OnLoadedCallback;

		private static Texture2D _defaultGraffitiTexture = null;

		public CharacterDefinition Definition { get; private set; }

		public CharacterStreamData StreamData { get; private set; }

		public SfxCollectionID SfxID { get; private set; }

		public SfxCollection Sfx { get; private set; }

		public GameObject Visual { get; private set; }

		public bool Loaded { get; private set; }

		public bool KeepLoaded { get; private set; }

		public GraffitiArt Graffiti { get; private set; }

		public Texture2D DefaultGraffitiTexture
		{
			get
			{
				if ((Object)(object)_defaultGraffitiTexture == (Object)null)
				{
					_defaultGraffitiTexture = TextureUtil.GetTextureFromBitmap(Resources.default_graffiti, (FilterMode)1);
				}
				return _defaultGraffitiTexture;
			}
		}

		public CustomCharacter(CharacterStreamData streamData, SfxCollectionID sfxID, string path, bool replacement, bool forceLoad)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			StreamData = streamData;
			InitializeSfxCollection();
			SfxID = sfxID;
			_path = path;
			KeepLoaded = replacement || forceLoad;
			if (KeepLoaded)
			{
				LoadSyncFromStartup();
			}
			if (!replacement)
			{
				CreateGraffiti();
			}
		}

		private void CreateGraffiti()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(Shader.Find("Standard"));
			val.mainTexture = (Texture)(object)StreamData.GraffitiTexture;
			string title = StreamData.GrafTitle;
			string text = StreamData.GrafAuthor;
			if (!StreamData.HasGraffiti)
			{
				val.mainTexture = (Texture)(object)DefaultGraffitiTexture;
				title = "Crew BOOM";
				text = "Capry";
			}
			GraffitiArt val2 = new GraffitiArt();
			val2.graffitiSize = (GraffitiSize)0;
			val2.graffitiMaterial = val;
			val2.title = title;
			val2.artistName = text;
			GraffitiAppEntry val3 = ScriptableObject.CreateInstance<GraffitiAppEntry>();
			val3.Size = (GraffitiSize)0;
			val3.GraffitiTexture = val.mainTexture;
			val3.Title = title;
			val3.Artist = text;
			val2.unlockable = val3;
			Graffiti = val2;
		}

		public void AddReference()
		{
			if (!KeepLoaded)
			{
				References++;
				if (CrewBoomSettings.LoadCharactersAsync && CrewBoomSettings.StreamCharacters)
				{
					LoadAsync();
				}
				else
				{
					LoadSync();
				}
			}
		}

		public void RemoveReference()
		{
			if (CrewBoomSettings.UnloadCharacters && !KeepLoaded)
			{
				References--;
				if (References <= 0 && CrewBoomSettings.StreamCharacters)
				{
					Unload();
				}
			}
		}

		public void WaitForLoadSync()
		{
			if (Loaded)
			{
				return;
			}
			if (BundleRequest != null)
			{
				while (((AsyncOperation)BundleRequest).progress < 0.9f)
				{
				}
				BundleRequest.assetBundle.Unload(true);
				BundleRequest = null;
			}
			LoadSync();
		}

		private void CancelAsyncLoad()
		{
			if (!Loaded && BundleRequest != null)
			{
				CharacterStreamer.CancelBundleLoadRequest(this);
				_bundle = null;
			}
		}

		private void LoadAsync()
		{
			if (!Loaded)
			{
				if (BundleRequest == null)
				{
					BundleRequest = AssetBundle.LoadFromFileAsync(_path);
				}
				CharacterStreamer.AddToStreamQueue(this);
			}
		}

		private void LoadSyncFromStartup()
		{
			OnBundleLoaded(AssetBundle.LoadFromFile(_path), fixShaders: false);
		}

		private void LoadSync()
		{
			if (!Loaded)
			{
				CancelAsyncLoad();
				OnBundleLoaded(AssetBundle.LoadFromFile(_path));
			}
		}

		public bool UpdateAsyncLoad()
		{
			if (Loaded)
			{
				return true;
			}
			if (BundleRequest == null)
			{
				return true;
			}
			if (((AsyncOperation)BundleRequest).isDone)
			{
				OnBundleLoaded(BundleRequest.assetBundle);
				return true;
			}
			return false;
		}

		private void OnBundleLoaded(AssetBundle bundle, bool fixShaders = true)
		{
			_bundle = bundle;
			Loaded = true;
			BundleRequest = null;
			GameObject[] array = bundle.LoadAllAssets<GameObject>();
			foreach (GameObject val in array)
			{
				Definition = val.GetComponent<CharacterDefinition>();
				if ((Object)(object)Definition != (Object)null)
				{
					break;
				}
			}
			if (fixShaders)
			{
				FixCharacterShader();
			}
			CreateVisual();
			LoadSfxCollection();
			OnLoadedCallback?.Invoke(this);
		}

		private void Unload()
		{
			CancelAsyncLoad();
			if (Loaded)
			{
				_bundle.Unload(true);
				_bundle = null;
				BundleRequest = null;
				Loaded = false;
				Definition = null;
				DestroyVisual();
				UnloadSfxCollection();
			}
		}

		private void DestroyVisual()
		{
			if (!((Object)(object)Visual == (Object)null))
			{
				Object.Destroy((Object)(object)Visual);
				Visual = null;
			}
		}

		private void CreateVisual()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if (!((Object)(object)Visual != (Object)null))
			{
				GameObject val = new GameObject(Definition.CharacterName + " Visuals");
				Object.DontDestroyOnLoad((Object)(object)val);
				CharacterDefinition val2 = Object.Instantiate<CharacterDefinition>(Definition);
				((Component)val2).transform.SetParent(val.transform, false);
				for (int i = 0; i < val2.Renderers.Length; i++)
				{
					SkinnedMeshRenderer obj = val2.Renderers[i];
					((Renderer)obj).sharedMaterials = Definition.Outfits[0].MaterialContainers[i].Materials;
					((Renderer)obj).receiveShadows = false;
					((Component)obj).gameObject.layer = 15;
					((Component)obj).gameObject.SetActive(Definition.Outfits[0].EnabledRenderers[i]);
				}
				((Component)val2).GetComponentInChildren<Animator>().applyRootMotion = false;
				val.SetActive(false);
				Visual = val;
			}
		}

		private void InitializeSfxCollection()
		{
			Sfx = ScriptableObject.CreateInstance<SfxCollection>();
			UnloadSfxCollection();
		}

		private void UnloadSfxCollection()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Sfx != (Object)null)
			{
				Sfx.audioClipContainers = (RandomAudioClipContainer[])(object)new RandomAudioClipContainer[VOICE_IDS.Count];
				for (int i = 0; i < VOICE_IDS.Count; i++)
				{
					Sfx.audioClipContainers[i] = new RandomAudioClipContainer();
					Sfx.audioClipContainers[i].clipID = VOICE_IDS[i];
					Sfx.audioClipContainers[i].clips = null;
					Sfx.audioClipContainers[i].lastRandomClip = 0;
				}
			}
		}

		private void LoadSfxCollection()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00d0: Expected I4, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Invalid comparison between Unknown and I4
			if (!Definition.HasVoices())
			{
				return;
			}
			SfxCollection val = Sfx;
			if ((Object)

CrewBoomAPI.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("CrewBoomAPI")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("API to interact with Crew Boom.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+fe750cb15aafe2527fad60c5296f5be8aaf0403d")]
[assembly: AssemblyProduct("CrewBoomAPI")]
[assembly: AssemblyTitle("CrewBoomAPI")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CrewBoomAPI
{
	public class CharacterInfo
	{
		public readonly string Name;

		public readonly string GraffitiName;

		public CharacterInfo(string name, string graffitiName)
		{
			Name = name;
			GraffitiName = graffitiName;
		}
	}
	public static class CrewBoomAPIDatabase
	{
		private static Dictionary<int, Guid> _userCharacters;

		public static bool IsInitialized { get; private set; }

		public static CharacterInfo PlayerCharacterInfo { get; private set; }

		public static event Action OnInitialized;

		public static event Action<Guid> OnOverride;

		public static event Action<CharacterInfo> OnPlayerCharacterInfoChanged;

		public static void Initialize(Dictionary<int, Guid> userCharacters)
		{
			_userCharacters = userCharacters;
			CrewBoomAPIDatabase.OnInitialized?.Invoke();
			IsInitialized = true;
		}

		public static void UpdatePlayerCharacter(CharacterInfo characterInfo)
		{
			PlayerCharacterInfo = characterInfo;
			CrewBoomAPIDatabase.OnPlayerCharacterInfoChanged?.Invoke(characterInfo);
		}

		public static bool GetUserGuidForCharacter(int character, out Guid guid)
		{
			guid = Guid.Empty;
			if (_userCharacters.TryGetValue(character, out guid))
			{
				return true;
			}
			return false;
		}

		public static void OverrideNextCharacterLoadedWithGuid(Guid guid)
		{
			CrewBoomAPIDatabase.OnOverride?.Invoke(guid);
		}
	}
}

CrewBoomMono.dll

Decompiled a month ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using CrewBoomMono;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("CrewBoomMono")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Library to supply monobehaviours for Crew Boom characters.")]
[assembly: AssemblyFileVersion("1.10.0.0")]
[assembly: AssemblyInformationalVersion("1.10.0+905ea7ff42b19009cf72f409d144f6bc9dad7f19")]
[assembly: AssemblyProduct("CrewBoomMono")]
[assembly: AssemblyTitle("CrewBoomMono")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.10.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CrewBoom.Mono
{
	public class EmbeddedBundle : IDisposable
	{
		private const string Magic = "STREAM";

		private const byte Version = 0;

		private string _path;

		private FileStream _stream;

		public EmbeddedBundle(string bundlePath)
		{
			_path = bundlePath;
		}

		public void OpenRead()
		{
			Close();
			_stream = new FileStream(_path, FileMode.Open, FileAccess.Read);
		}

		public void OpenWrite()
		{
			Close();
			_stream = new FileStream(_path, FileMode.Open, FileAccess.Write);
		}

		public void Close()
		{
			if (_stream != null)
			{
				_stream.Dispose();
			}
			_stream = null;
		}

		public void Dispose()
		{
			if (_stream != null)
			{
				_stream.Dispose();
			}
		}

		public AssetBundle LoadAssetBundle()
		{
			Close();
			return AssetBundle.LoadFromFile(_path);
		}

		public void AppendStreamData(CharacterStreamData streamData)
		{
			if (_stream == null)
			{
				throw new IOException("There isn't any stream open to write!");
			}
			if (!_stream.CanWrite)
			{
				throw new IOException("The FileStream can't write!");
			}
			_stream.Seek(0L, SeekOrigin.End);
			int value = (int)_stream.Position;
			using BinaryWriter binaryWriter = new BinaryWriter(_stream);
			streamData.Write(binaryWriter);
			binaryWriter.Write(value);
			binaryWriter.Write(Encoding.ASCII.GetBytes("STREAM"));
			binaryWriter.Write((byte)0);
		}

		public bool TryRetrieveStreamData(out CharacterStreamData streamData)
		{
			if (_stream == null)
			{
				throw new IOException("There isn't any stream open to read!");
			}
			if (!_stream.CanRead)
			{
				throw new IOException("The FileStream can't read!");
			}
			streamData = null;
			int num = "STREAM".Length + 1;
			_stream.Seek(-num, SeekOrigin.End);
			byte[] array = new byte[num];
			_stream.Read(array, 0, num);
			if (Encoding.ASCII.GetString(array, 0, "STREAM".Length) != "STREAM")
			{
				return false;
			}
			byte b = array[6];
			if (b < 0 || b > 0)
			{
				throw new IOException($"Unrecognized Stream Data version {b}");
			}
			_stream.Seek(-num - 4, SeekOrigin.End);
			byte[] array2 = new byte[4];
			_stream.Read(array2, 0, 4);
			int num2 = BitConverter.ToInt32(array2, 0);
			_stream.Seek(num2, SeekOrigin.Begin);
			using (BinaryReader reader = new BinaryReader(_stream))
			{
				streamData = new CharacterStreamData();
				streamData.Read(reader);
			}
			return true;
		}
	}
}
namespace CrewBoomMono
{
	[AddComponentMenu("Crew Boom/Character Definition")]
	public class CharacterDefinition : MonoBehaviour
	{
		public bool OverrideBundleFilename;

		public string BundleFilename = "";

		public string CharacterName = "New Custom Character";

		public BrcCharacter FreestyleAnimation = BrcCharacter.Red;

		public BrcCharacter BounceAnimation = BrcCharacter.Red;

		public BrcMovestyle DefaultMovestyle = BrcMovestyle.Skateboard;

		public UnlockType UnlockType;

		public string BoEBounceAnimation = "";

		public bool BoEBounceAnimationVanilla;

		public SkinnedMeshRenderer[] Renderers;

		public CharacterOutfit[] Outfits;

		public Material Graffiti;

		public string GraffitiName;

		public string GraffitiArtist;

		public AudioClip[] VoiceDie;

		public AudioClip[] VoiceDieFall;

		public AudioClip[] VoiceTalk;

		public AudioClip[] VoiceBoostTrick;

		public AudioClip[] VoiceCombo;

		public AudioClip[] VoiceGetHit;

		public AudioClip[] VoiceJump;

		public bool CanBlink;

		public string Id;
	}
	public class CharacterConfig
	{
		public string CharacterToReplace = "None";
	}
	public enum BrcCharacter
	{
		None = -1,
		Vinyl,
		Frank,
		Coil,
		Red,
		Tryce,
		Bel,
		Rave,
		DotExeMember,
		Solace,
		DjCyber,
		EclipseMember,
		DevilTheoryMember,
		FauxWithBoostPack,
		FleshPrince,
		Irene,
		Felix,
		OldHeadMember,
		Base,
		Jet,
		Mesh,
		FuturismMember,
		Rise,
		Shine,
		FauxWithoutBoostPack,
		DotExeBoss,
		FelixWithCyberHead
	}
	public enum BrcMovestyle
	{
		Bmx = 1,
		Skateboard,
		Skates
	}
	public enum UnlockType
	{
		AlwaysUnlocked,
		Unlockable,
		Locked
	}
	public class CharacterOutfit : MonoBehaviour
	{
		public string Name;

		public bool[] EnabledRenderers;

		public CharacterOutfitRenderer[] MaterialContainers;
	}
	public class CharacterOutfitRenderer : MonoBehaviour
	{
		public Material[] Materials;

		public bool[] UseShaderForMaterial;
	}
	public class CharacterStreamData
	{
		private const byte Version = 0;

		public string Id;

		public UnlockType UnlockType;

		public BrcMovestyle DefaultMoveStyle;

		public string Name;

		public string GrafTitle;

		public string GrafAuthor;

		public bool HasGraffiti;

		public BrcCharacter IdleDance;

		public string BoEIdleDance;

		public bool BoEIdleDanceVanilla;

		public Texture2D GraffitiTexture;

		public void FromCharacter(CharacterDefinition character)
		{
			Id = character.Id;
			UnlockType = character.UnlockType;
			DefaultMoveStyle = character.DefaultMovestyle;
			Name = character.CharacterName;
			HasGraffiti = (Object)(object)character.Graffiti != (Object)null;
			GrafTitle = character.GraffitiName;
			GrafAuthor = character.GraffitiArtist;
			IdleDance = character.BounceAnimation;
			BoEIdleDance = character.BoEBounceAnimation;
			BoEIdleDanceVanilla = character.BoEBounceAnimationVanilla;
			if (HasGraffiti)
			{
				Texture mainTexture = character.Graffiti.mainTexture;
				CopyGraffitiTexture((Texture2D)(object)((mainTexture is Texture2D) ? mainTexture : null));
			}
		}

		public void Write(BinaryWriter writer)
		{
			writer.Write((byte)0);
			writer.Write(Id);
			writer.Write((int)UnlockType);
			writer.Write((int)DefaultMoveStyle);
			writer.Write(Name);
			writer.Write(HasGraffiti);
			writer.Write(GrafTitle);
			writer.Write(GrafAuthor);
			writer.Write((int)IdleDance);
			writer.Write(BoEIdleDance);
			writer.Write(BoEIdleDanceVanilla);
			if (HasGraffiti)
			{
				byte[] array = ImageConversion.EncodeToPNG(GraffitiTexture);
				writer.Write(array.Length);
				writer.Write(array);
			}
		}

		public void Read(BinaryReader reader, bool grafreadable = false)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			reader.ReadByte();
			Id = reader.ReadString();
			UnlockType = (UnlockType)reader.ReadInt32();
			DefaultMoveStyle = (BrcMovestyle)reader.ReadInt32();
			Name = reader.ReadString();
			HasGraffiti = reader.ReadBoolean();
			GrafTitle = reader.ReadString();
			GrafAuthor = reader.ReadString();
			IdleDance = (BrcCharacter)reader.ReadInt32();
			BoEIdleDance = reader.ReadString();
			BoEIdleDanceVanilla = reader.ReadBoolean();
			if (HasGraffiti)
			{
				int count = reader.ReadInt32();
				byte[] array = reader.ReadBytes(count);
				GraffitiTexture = new Texture2D(2, 2);
				ImageConversion.LoadImage(GraffitiTexture, array, !grafreadable);
			}
		}

		private void CopyGraffitiTexture(Texture2D source)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)source).width, ((Texture)source).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			Graphics.Blit((Texture)(object)source, temporary);
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = temporary;
			GraffitiTexture = new Texture2D(((Texture)source).width, ((Texture)source).height, (TextureFormat)5, false);
			GraffitiTexture.ReadPixels(new Rect(0f, 0f, (float)((Texture)temporary).width, (float)((Texture)temporary).height), 0, 0);
			GraffitiTexture.Apply();
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
		}

		public void Release()
		{
			if ((Object)(object)GraffitiTexture != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)GraffitiTexture);
			}
		}
	}
}