Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Mercenary Skins Fix v1.2.4
plugins/MercSkinsFix/MercSkinsFix.dll
Decompiled 5 months 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(); } } }