Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of Mercenary Skins Fix v1.2.4
plugins/MercSkinsFix/MercSkinsFix.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HG; using HarmonyLib; using Microsoft.CodeAnalysis; using MonoMod.RuntimeDetour; using R2API.Utils; using RiskOfOptions; using RiskOfOptions.Options; using RoR2; using RoR2BepInExPack.GameAssetPaths.Version_1_35_0; using UnityEngine; using UnityEngine.AddressableAssets; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: NetworkCompatibility(/*Could not decode attribute arguments.*/)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("MercSkinsFix")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+ec5d5c865e15669d9885120c1db36be980c8024c")] [assembly: AssemblyProduct("MercSkinsFix")] [assembly: AssemblyTitle("MercSkinsFix")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.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 MercSkinsFix { internal static class Log { private static readonly StringBuilder _sharedStringBuilder; private static readonly object _stringBuilderLock; private static readonly int _cachedCallerPathPrefixLength; private static ManualLogSource _logSource; static Log() { _sharedStringBuilder = new StringBuilder(256); _stringBuilderLock = new object(); _cachedCallerPathPrefixLength = getCallerPathPrefixLength("D:\\Git\\RoR2\\MercSkinsFix\\MercSkinsFix\\Log.cs"); static int getCallerPathPrefixLength([CallerFilePath] string callerPath = null) { int num = callerPath.LastIndexOf("MercSkinsFix\\"); if (num >= 0) { return num + "MercSkinsFix\\".Length; } Debug.LogError((object)"[MercSkinsFix] Logger failed to determine caller path prefix length"); return 0; } } internal static void Init(ManualLogSource logSource) { _logSource = logSource; } private static string buildCallerLogString(string callerPath, string callerMemberName, int callerLineNumber, object data) { lock (_stringBuilderLock) { return _sharedStringBuilder.Clear().Append(callerPath, _cachedCallerPathPrefixLength, callerPath.Length - _cachedCallerPathPrefixLength).Append(':') .Append(callerLineNumber) .Append(" (") .Append(callerMemberName) .Append("): ") .Append(data) .ToString(); } } [Conditional("DEBUG")] internal static void Debug(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogDebug((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Conditional("DEBUG")] internal static void Debug_NoCallerPrefix(object data) { _logSource.LogDebug(data); } internal static void Error(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogError((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Error_NoCallerPrefix(object data) { _logSource.LogError(data); } internal static void Fatal(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogFatal((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Fatal_NoCallerPrefix(object data) { _logSource.LogFatal(data); } internal static void Info(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogInfo((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Info_NoCallerPrefix(object data) { _logSource.LogInfo(data); } internal static void Message(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogMessage((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Message_NoCallerPrefix(object data) { _logSource.LogMessage(data); } internal static void Warning(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogWarning((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Warning_NoCallerPrefix(object data) { _logSource.LogWarning(data); } internal static void LogType(LogLevel level, object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { //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_000c: Unknown result type (might be due to invalid IL or missing references) if ((level & 0x20) == 0) { _logSource.Log(level, (object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void LogType_NoCallerPrefix(LogLevel level, object data) { //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_000c: Unknown result type (might be due to invalid IL or missing references) if ((level & 0x20) == 0) { _logSource.Log(level, data); } } } [BepInPlugin("___com.Gorakh.MercSkinsFix", "MercSkinsFix", "1.2.4")] public sealed class MercSkinsFixPlugin : BaseUnityPlugin { private delegate ScriptableObject orig_ScriptableObject_CreateInstance(Type type); public const string PluginGUID = "___com.Gorakh.MercSkinsFix"; public const string PluginAuthor = "Gorakh"; public const string PluginName = "MercSkinsFix"; public const string PluginVersion = "1.2.4"; private static readonly Dictionary<Assembly, PluginInfo> _assemblyPluginLookup = new Dictionary<Assembly, PluginInfo>(); private static readonly Dictionary<SkinDef, Assembly> _skinOwnerAssemblies = new Dictionary<SkinDef, Assembly>(); private static readonly Dictionary<Assembly, DateTime?> _assemblyTimestampLookup = new Dictionary<Assembly, DateTime?>(); private Hook _scriptableObjectCreateInstanceHook; internal static MercSkinsFixPlugin Instance { get; private set; } private void Awake() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown Stopwatch stopwatch = Stopwatch.StartNew(); Log.Init(((BaseUnityPlugin)this).Logger); Instance = SingletonHelper.Assign<MercSkinsFixPlugin>(Instance, this); _scriptableObjectCreateInstanceHook = new Hook((MethodBase)SymbolExtensions.GetMethodInfo((Expression<Action>)(() => ScriptableObject.CreateInstance((Type)null))), (Delegate)new Func<orig_ScriptableObject_CreateInstance, Type, ScriptableObject>(ScriptableObject_CreateInstance)); stopwatch.Stop(); Log.Info_NoCallerPrefix($"Initialized in {stopwatch.Elapsed.TotalSeconds:F2} seconds"); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(onLoad)); } private void OnDestroy() { Instance = SingletonHelper.Unassign<MercSkinsFixPlugin>(Instance, this); Hook scriptableObjectCreateInstanceHook = _scriptableObjectCreateInstanceHook; if (scriptableObjectCreateInstanceHook != null) { scriptableObjectCreateInstanceHook.Dispose(); } _scriptableObjectCreateInstanceHook = null; } private static ScriptableObject ScriptableObject_CreateInstance(orig_ScriptableObject_CreateInstance orig, Type type) { ScriptableObject val = orig(type); try { SkinDef val2 = (SkinDef)(object)((val is SkinDef) ? val : null); if (val2 != null) { StackTrace stackTrace = new StackTrace(); for (int i = 0; i < stackTrace.FrameCount; i++) { Assembly assembly = stackTrace.GetFrame(i)?.GetMethod()?.DeclaringType?.Assembly; if (assembly == null || assembly == Assembly.GetExecutingAssembly()) { continue; } if (!_assemblyPluginLookup.TryGetValue(assembly, out var value)) { value = null; foreach (PluginInfo value3 in Chainloader.PluginInfos.Values) { if (Object.op_Implicit((Object)(object)value3.Instance) && ((object)value3.Instance).GetType().Assembly == assembly) { value = value3; break; } } _assemblyPluginLookup.Add(assembly, value); } if (value == null) { continue; } if (!_assemblyTimestampLookup.ContainsKey(assembly)) { DateTime? value2 = null; string location = assembly.Location; if (!string.IsNullOrEmpty(location) && File.Exists(location)) { try { using FileStream fileStream = File.Open(location, FileMode.Open, FileAccess.Read, FileShare.Read); byte[] array = new byte[2048]; int num = fileStream.Read(array, 0, 2048); if (num >= 60) { int num2 = BitConverter.ToInt32(array, 60) + 8; if (num >= num2 + 4) { int num3 = BitConverter.ToInt32(array, num2); DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(num3); if (dateTime > new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc) && dateTime < DateTime.UtcNow) { value2 = dateTime; } } } } catch (Exception arg) { Log.Error_NoCallerPrefix($"Failed to determine assembly date for {assembly.GetName()}: {arg}"); } } _assemblyTimestampLookup.Add(assembly, value2); } _skinOwnerAssemblies.Add(val2, assembly); break; } } } catch (Exception data) { Log.Error_NoCallerPrefix(data); } return val; } private void onLoad() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Expected O, but got Unknown //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_049f: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Expected O, but got Unknown RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(onLoad)); SkinDef[] array = (SkinDef[])(object)new SkinDef[5] { Addressables.LoadAssetAsync<SkinDef>((object)RoR2_Base_Merc.skinMercDefault_asset).WaitForCompletion(), Addressables.LoadAssetAsync<SkinDef>((object)RoR2_Base_Merc.skinMercAlt_asset).WaitForCompletion(), Addressables.LoadAssetAsync<SkinDef>((object)RoR2_Base_Merc.skinMercAltPrisoner_asset).WaitForCompletion(), Addressables.LoadAssetAsync<SkinDef>((object)RoR2_Base_Merc.skinMercAltColossus_asset).WaitForCompletion(), Addressables.LoadAssetAsync<SkinDef>((object)RoR2_Base_Merc.skinMercAltVulture_asset).WaitForCompletion() }; Dictionary<string, HashSet<string>> dictionary = new Dictionary<string, HashSet<string>>(); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; bool flag = false; SkinDef[] bodySkinDefs = SkinCatalog.GetBodySkinDefs(BodyCatalog.FindBodyIndex("MercBody")); foreach (SkinDef skin in bodySkinDefs) { if (Array.IndexOf(array, skin) != -1) { continue; } Assembly valueSafe = GeneralExtensions.GetValueSafe<SkinDef, Assembly>(_skinOwnerAssemblies, skin); PluginInfo val = ((valueSafe != null) ? GeneralExtensions.GetValueSafe<Assembly, PluginInfo>(_assemblyPluginLookup, valueSafe) : null); string key = "Unknown"; bool flag2 = false; if (val != null && valueSafe != null) { if (_assemblyTimestampLookup.TryGetValue(valueSafe, out var value) && value.HasValue) { DateTime dateTime = new DateTime(2024, 5, 20, 0, 0, 0, DateTimeKind.Utc); if (value.Value < dateTime) { flag2 = true; } } key = val.Metadata.Name + " (" + Path.GetFileName(valueSafe.Location) + ")"; } string text; if (!string.IsNullOrEmpty(skin.nameToken)) { text = ((!string.IsNullOrEmpty(((Object)skin).name)) ? (Language.GetString(skin.nameToken, "en") + " (" + ((Object)skin).name + ")") : Language.GetString(skin.nameToken, "en")); } else if (string.IsNullOrEmpty(((Object)skin).name)) { SkinIndex skinIndex = skin.skinIndex; text = ((object)(SkinIndex)(ref skinIndex)).ToString(); } else { text = ((Object)skin).name; } string text2 = Regex.Replace(text, "<[^<>]+>", string.Empty); if (!string.IsNullOrEmpty(text2)) { text = text2; } text = text.FilterConfigKey(); if (string.IsNullOrEmpty(text)) { Random random = new Random(skin.nameToken.GetHashCode()); StringBuilder stringBuilder = StringBuilderPool.RentStringBuilder(); byte[] array2 = new byte[16]; random.NextBytes(array2); for (int j = 0; j < array2.Length; j++) { stringBuilder.Append(array2[j].ToString("X2")); } text = $"INVALID SKIN NAME {stringBuilder}"; StringBuilderPool.ReturnStringBuilder(stringBuilder); } if (dictionary.TryGetValue(key, out var value2)) { if (!value2.Add(text)) { string arg = text; int num = 1; do { text = $"{arg} ({num})"; num++; } while (!value2.Add(text)); } } else { dictionary.Add(key, new HashSet<string> { text }); } ConfigEntry<bool> obj = ((BaseUnityPlugin)this).Config.Bind<bool>(key.FilterConfigKey(), ("Fix " + text).FilterConfigKey(), flag2, "Apply the fix to this skin"); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(obj), "___com.Gorakh.MercSkinsFix", "Mercenary Skins Fix"); flag = true; if (obj.Value) { RebakeSkin.SetApplyToSkin(skin, apply: true); } obj.SettingChanged += delegate(object s, EventArgs e) { SettingChangedEventArgs val3 = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null); if (val3 != null) { bool apply = (bool)val3.ChangedSetting.BoxedValue; RebakeSkin.SetApplyToSkin(skin, apply); } }; } ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; ((BaseUnityPlugin)this).Config.Save(); if (flag) { ModSettingsManager.SetModDescription("Fix broken Mercenary skins after the Devotion update", "___com.Gorakh.MercSkinsFix", "Mercenary Skins Fix"); FileInfo fileInfo = null; DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location)); do { FileInfo[] files = directoryInfo.GetFiles("icon.png", SearchOption.TopDirectoryOnly); if (files != null && files.Length != 0) { fileInfo = files[0]; break; } directoryInfo = directoryInfo.Parent; } while (directoryInfo != null && !string.Equals(directoryInfo.Name, "plugins", StringComparison.OrdinalIgnoreCase)); if (fileInfo != null) { Texture2D val2 = new Texture2D(256, 256); if (ImageConversion.LoadImage(val2, File.ReadAllBytes(fileInfo.FullName))) { ModSettingsManager.SetModIcon(Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f)), "___com.Gorakh.MercSkinsFix", "Mercenary Skins Fix"); } } } Hook scriptableObjectCreateInstanceHook = _scriptableObjectCreateInstanceHook; if (scriptableObjectCreateInstanceHook != null) { scriptableObjectCreateInstanceHook.Dispose(); } _scriptableObjectCreateInstanceHook = null; } } public static class RebakeSkin { public static void SetApplyToSkin(SkinDef skin, bool apply) { GameObject gameObject = ((Component)BodyCatalog.FindBodyPrefab("MercBody").GetComponent<ModelLocator>().modelTransform).gameObject; Renderer[] componentsInChildren = gameObject.GetComponentsInChildren<Renderer>(true); Renderer[] array = new Renderer[5]; Transform obj = gameObject.transform.Find("MercArmature/ROOT/base/stomach/chest/PreDashEffect/ContractingEnergy"); array[0] = ((obj != null) ? ((Component)obj).GetComponent<Renderer>() : null); Transform obj2 = gameObject.transform.Find("MercArmature/ROOT/base/stomach/chest/PreDashEffect/FireEmission"); array[1] = ((obj2 != null) ? ((Component)obj2).GetComponent<Renderer>() : null); Transform obj3 = gameObject.transform.Find("MercArmature/ROOT/base/stomach/chest/PreDashEffect/BrightRing"); array[2] = ((obj3 != null) ? ((Component)obj3).GetComponent<Renderer>() : null); Transform obj4 = gameObject.transform.Find("MercMesh"); array[3] = ((obj4 != null) ? ((Component)obj4).GetComponent<Renderer>() : null); Transform obj5 = gameObject.transform.Find("MercSwordMesh"); array[4] = ((obj5 != null) ? ((Component)obj5).GetComponent<Renderer>() : null); Renderer[] array2 = (Renderer[])(object)array; Renderer[] array3 = (apply ? componentsInChildren : array2); Renderer[] array4 = (apply ? array2 : componentsInChildren); for (int i = 0; i < skin.rendererInfos.Length; i++) { ref RendererInfo reference = ref skin.rendererInfos[i]; if (Object.op_Implicit((Object)(object)reference.renderer)) { int num = Array.IndexOf(array3, reference.renderer); if (num >= 0 && num < array4.Length) { Log.Info($"Changing {((Object)skin).name} RendererInfo renderer {reference.renderer} -> {array4[num]}", "D:\\Git\\RoR2\\MercSkinsFix\\MercSkinsFix\\RebakeSkin.cs", "SetApplyToSkin", 38); reference.renderer = array4[num]; } } } for (int j = 0; j < skin.meshReplacements.Length; j++) { ref MeshReplacement reference2 = ref skin.meshReplacements[j]; if (Object.op_Implicit((Object)(object)reference2.renderer)) { int num2 = Array.IndexOf(array3, reference2.renderer); if (num2 >= 0 && num2 < array4.Length) { Log.Info($"Changing {((Object)skin).name} MeshReplacement renderer {reference2.renderer} -> {array4[num2]}", "D:\\Git\\RoR2\\MercSkinsFix\\MercSkinsFix\\RebakeSkin.cs", "SetApplyToSkin", 52); reference2.renderer = array4[num2]; } } } if (skin.runtimeSkin != null) { RebakeSkinAsync(skin); } } public static void RebakeSkinAsync(SkinDef orig) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) orig._runtimeSkin = null; SkinDefParams skinDefParams = orig.skinDefParams; if (Object.op_Implicit((Object)(object)skinDefParams)) { skinDefParams.rendererInfos = ((orig.rendererInfos != null) ? ArrayUtils.Clone<RendererInfo>(orig.rendererInfos) : Array.Empty<RendererInfo>()); SkinDefParams val = skinDefParams; GameObjectActivation[] gameObjectActivations2; if (orig.gameObjectActivations != null) { GameObjectActivation[] gameObjectActivations = orig.gameObjectActivations; int num = 0; GameObjectActivation[] array = (GameObjectActivation[])(object)new GameObjectActivation[gameObjectActivations.Length]; GameObjectActivation[] array2 = gameObjectActivations; foreach (GameObjectActivation val2 in array2) { array[num] = GameObjectActivation.op_Implicit(val2); num++; } gameObjectActivations2 = array; } else { gameObjectActivations2 = Array.Empty<GameObjectActivation>(); } val.gameObjectActivations = gameObjectActivations2; val = skinDefParams; MeshReplacement[] meshReplacements2; if (orig.meshReplacements != null) { MeshReplacement[] meshReplacements = orig.meshReplacements; int num = 0; MeshReplacement[] array3 = (MeshReplacement[])(object)new MeshReplacement[meshReplacements.Length]; MeshReplacement[] array4 = meshReplacements; foreach (MeshReplacement val3 in array4) { array3[num] = MeshReplacement.op_Implicit(val3); num++; } meshReplacements2 = array3; } else { meshReplacements2 = Array.Empty<MeshReplacement>(); } val.meshReplacements = meshReplacements2; val = skinDefParams; ProjectileGhostReplacement[] projectileGhostReplacements2; if (orig.projectileGhostReplacements != null) { ProjectileGhostReplacement[] projectileGhostReplacements = orig.projectileGhostReplacements; int num = 0; ProjectileGhostReplacement[] array5 = (ProjectileGhostReplacement[])(object)new ProjectileGhostReplacement[projectileGhostReplacements.Length]; ProjectileGhostReplacement[] array6 = projectileGhostReplacements; foreach (ProjectileGhostReplacement val4 in array6) { array5[num] = ProjectileGhostReplacement.op_Implicit(val4); num++; } projectileGhostReplacements2 = array5; } else { projectileGhostReplacements2 = Array.Empty<ProjectileGhostReplacement>(); } val.projectileGhostReplacements = projectileGhostReplacements2; val = skinDefParams; MinionSkinReplacement[] minionSkinReplacements2; if (orig.minionSkinReplacements != null) { MinionSkinReplacement[] minionSkinReplacements = orig.minionSkinReplacements; int num = 0; MinionSkinReplacement[] array7 = (MinionSkinReplacement[])(object)new MinionSkinReplacement[minionSkinReplacements.Length]; MinionSkinReplacement[] array8 = minionSkinReplacements; foreach (MinionSkinReplacement val5 in array8) { array7[num] = MinionSkinReplacement.op_Implicit(val5); num++; } minionSkinReplacements2 = array7; } else { minionSkinReplacements2 = Array.Empty<MinionSkinReplacement>(); } val.minionSkinReplacements = minionSkinReplacements2; } IEnumerator enumerator = orig.BakeAsync(); while (enumerator.MoveNext()) { } } } public static class StringExtensions { private static readonly char[] _invalidConfigDefinitionChars = (char[])AccessTools.DeclaredField(typeof(ConfigDefinition), "_invalidConfigChars")?.GetValue(null); public static string FilterChars(this string str, char[] invalidChars) { if (str.IndexOfAny(invalidChars) == -1) { return str; } StringBuilder stringBuilder = StringBuilderPool.RentStringBuilder(); foreach (char value in str) { if (Array.IndexOf(invalidChars, value) == -1) { stringBuilder.Append(value); } } string result = stringBuilder.ToString(); StringBuilderPool.ReturnStringBuilder(stringBuilder); return result; } public static string FilterConfigKey(this string key) { if (_invalidConfigDefinitionChars == null) { Log.Error("_invalidConfigDefinitionChars is null", "D:\\Git\\RoR2\\MercSkinsFix\\MercSkinsFix\\StringExtensions.cs", "FilterConfigKey", 36); return key; } return key.FilterChars(_invalidConfigDefinitionChars).Trim(); } } }