using System;
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 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.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("MercSkinsFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+2a7e882ffe00543beb2a5b0726b92ce89842d057")]
[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 DelegateUtils
{
public static void Append<TDelegate>(ref TDelegate original, TDelegate append) where TDelegate : Delegate
{
original = (TDelegate)Delegate.Combine(original, append);
}
}
internal static class Log
{
internal static ManualLogSource _logSource;
internal static void Init(ManualLogSource logSource)
{
_logSource = logSource;
}
private static string getLogPrefix(string callerPath, string callerMemberName, int callerLineNumber)
{
int num = callerPath.LastIndexOf("MercSkinsFix\\");
if (num >= 0)
{
callerPath = callerPath.Substring(num + "MercSkinsFix\\".Length);
}
return $"{callerPath}:{callerLineNumber} ({callerMemberName}) ";
}
internal static void Error(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1)
{
_logSource.LogError((object)(getLogPrefix(callerPath, callerMemberName, callerLineNumber) + data));
}
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)(getLogPrefix(callerPath, callerMemberName, callerLineNumber) + data));
}
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)(getLogPrefix(callerPath, callerMemberName, callerLineNumber) + data));
}
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)(getLogPrefix(callerPath, callerMemberName, callerLineNumber) + data));
}
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)(getLogPrefix(callerPath, callerMemberName, callerLineNumber) + data));
}
internal static void Warning_NoCallerPrefix(object data)
{
_logSource.LogWarning(data);
}
}
[BepInPlugin("Gorakh.MercSkinsFix", "MercSkinsFix", "1.2.0")]
public class MercSkinsFixPlugin : BaseUnityPlugin
{
private delegate ScriptableObject orig_ScriptableObject_CreateInstance(Type type);
public const string PluginGUID = "Gorakh.MercSkinsFix";
public const string PluginAuthor = "Gorakh";
public const string PluginName = "MercSkinsFix";
public const string PluginVersion = "1.2.0";
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");
DelegateUtils.Append(ref RoR2Application.onLoad, 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);
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;
}
}
return val;
}
private void onLoad()
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_04da: Unknown result type (might be due to invalid IL or missing references)
//IL_04e1: Expected O, but got Unknown
//IL_0512: Unknown result type (might be due to invalid IL or missing references)
//IL_0521: Unknown result type (might be due to invalid IL or missing references)
//IL_0250: Unknown result type (might be due to invalid IL or missing references)
//IL_0255: Unknown result type (might be due to invalid IL or missing references)
//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0413: Expected O, but got Unknown
SkinDef[] array = (SkinDef[])(object)new SkinDef[3]
{
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()
};
GameObject val = BodyCatalog.FindBodyPrefab("MercBody");
GameObject gameObject = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
Renderer[] renderers = gameObject.GetComponentsInChildren<Renderer>(true);
Renderer[] array2 = new Renderer[5];
Transform obj = gameObject.transform.Find("MercArmature/ROOT/base/stomach/chest/PreDashEffect/ContractingEnergy");
array2[0] = ((obj != null) ? ((Component)obj).GetComponent<Renderer>() : null);
Transform obj2 = gameObject.transform.Find("MercArmature/ROOT/base/stomach/chest/PreDashEffect/FireEmission");
array2[1] = ((obj2 != null) ? ((Component)obj2).GetComponent<Renderer>() : null);
Transform obj3 = gameObject.transform.Find("MercArmature/ROOT/base/stomach/chest/PreDashEffect/BrightRing");
array2[2] = ((obj3 != null) ? ((Component)obj3).GetComponent<Renderer>() : null);
Transform obj4 = gameObject.transform.Find("MercMesh");
array2[3] = ((obj4 != null) ? ((Component)obj4).GetComponent<Renderer>() : null);
Transform obj5 = gameObject.transform.Find("MercSwordMesh");
array2[4] = ((obj5 != null) ? ((Component)obj5).GetComponent<Renderer>() : null);
Renderer[] preDevotionRenderersList = (Renderer[])(object)array2;
SkinDef[] bodySkins = BodyCatalog.GetBodySkins(BodyCatalog.FindBodyIndex(val));
Dictionary<string, HashSet<string>> dictionary = new Dictionary<string, HashSet<string>>();
((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
SkinDef[] array3 = bodySkins;
foreach (SkinDef skin in array3)
{
if (Array.IndexOf(array, skin) >= 0)
{
continue;
}
Assembly valueSafe = GeneralExtensions.GetValueSafe<SkinDef, Assembly>(_skinOwnerAssemblies, skin);
PluginInfo val2 = ((valueSafe != null) ? GeneralExtensions.GetValueSafe<Assembly, PluginInfo>(_assemblyPluginLookup, valueSafe) : null);
string key = "Unknown";
bool flag = false;
if (val2 != 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)
{
flag = true;
}
}
key = val2.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[] array4 = new byte[16];
random.NextBytes(array4);
for (int j = 0; j < array4.Length; j++)
{
stringBuilder.Append(array4[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> obj6 = ((BaseUnityPlugin)this).Config.Bind<bool>(key.FilterConfigKey(), "Fix " + text, flag, "Apply the fix to this skin");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(obj6), "Gorakh.MercSkinsFix", "Mercenary Skins Fix");
if (obj6.Value)
{
setApplyToSkin(apply: true);
}
obj6.SettingChanged += delegate(object s, EventArgs e)
{
bool applyToSkin = (bool)((SettingChangedEventArgs)((e is SettingChangedEventArgs) ? e : null)).ChangedSetting.BoxedValue;
setApplyToSkin(applyToSkin);
};
void setApplyToSkin(bool apply)
{
Renderer[] array5 = (apply ? renderers : preDevotionRenderersList);
Renderer[] array6 = (apply ? preDevotionRenderersList : renderers);
for (int k = 0; k < skin.rendererInfos.Length; k++)
{
ref RendererInfo reference = ref skin.rendererInfos[k];
if (Object.op_Implicit((Object)(object)reference.renderer))
{
int num2 = Array.IndexOf(array5, reference.renderer);
if (num2 >= 0 && num2 < array6.Length)
{
Log.Info($"Changing {((Object)skin).name} RendererInfo renderer {reference.renderer} -> {array6[num2]}", "E:\\Git\\RoR2\\MercSkinsFix\\MercSkinsFix\\MercSkinsFixPlugin.cs", "onLoad", 206);
reference.renderer = array6[num2];
}
}
}
for (int l = 0; l < skin.meshReplacements.Length; l++)
{
ref MeshReplacement reference2 = ref skin.meshReplacements[l];
if (Object.op_Implicit((Object)(object)reference2.renderer))
{
int num3 = Array.IndexOf(array5, reference2.renderer);
if (num3 >= 0 && num3 < array6.Length)
{
Log.Info($"Changing {((Object)skin).name} MeshReplacement renderer {reference2.renderer} -> {array6[num3]}", "E:\\Git\\RoR2\\MercSkinsFix\\MercSkinsFix\\MercSkinsFixPlugin.cs", "onLoad", 220);
reference2.renderer = array6[num3];
}
}
}
if (skin.runtimeSkin != null)
{
skin.runtimeSkin = null;
skin.Bake();
}
}
}
((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
((BaseUnityPlugin)this).Config.Save();
ModSettingsManager.SetModDescription("Fix broken Mercenary skins after the Devotion update", "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 val3 = new Texture2D(256, 256);
if (ImageConversion.LoadImage(val3, File.ReadAllBytes(fileInfo.FullName)))
{
ModSettingsManager.SetModIcon(Sprite.Create(val3, new Rect(0f, 0f, (float)((Texture)val3).width, (float)((Texture)val3).height), new Vector2(0.5f, 0.5f)), "Gorakh.MercSkinsFix", "Mercenary Skins Fix");
}
}
Hook scriptableObjectCreateInstanceHook = _scriptableObjectCreateInstanceHook;
if (scriptableObjectCreateInstanceHook != null)
{
scriptableObjectCreateInstanceHook.Dispose();
}
_scriptableObjectCreateInstanceHook = null;
}
}
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", "E:\\Git\\RoR2\\MercSkinsFix\\MercSkinsFix\\StringExtensions.cs", "FilterConfigKey", 36);
return key;
}
return key.FilterChars(_invalidConfigDefinitionChars);
}
}
}