using 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;
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+9cbde37c5a792561bb6fd952e251bc2114c8ae9d")]
[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);
}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("___com.Gorakh.MercSkinsFix", "MercSkinsFix", "1.2.3")]
public 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.3";
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);
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_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0423: Unknown result type (might be due to invalid IL or missing references)
//IL_042a: Expected O, but got Unknown
//IL_0189: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Unknown result type (might be due to invalid IL or missing references)
//IL_045b: Unknown result type (might be due to invalid IL or missing references)
//IL_046a: Unknown result type (might be due to invalid IL or missing references)
//IL_033b: Unknown result type (might be due to invalid IL or missing references)
//IL_034f: Expected O, but got Unknown
SkinDef[] array = (SkinDef[])(object)new SkinDef[4]
{
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()
};
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)
{
bool apply = (bool)((SettingChangedEventArgs)((e is SettingChangedEventArgs) ? e : null)).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]}", "X:\\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]}", "X:\\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_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: 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)
orig._runtimeSkin = null;
SkinDefParams skinDefParams = orig.skinDefParams;
skinDefParams.rendererInfos = ArrayUtils.Clone<RendererInfo>(orig.rendererInfos);
skinDefParams.gameObjectActivations = (GameObjectActivation[])(object)new GameObjectActivation[orig.gameObjectActivations.Length];
for (int i = 0; i < orig.gameObjectActivations.Length; i++)
{
skinDefParams.gameObjectActivations[i] = GameObjectActivation.op_Implicit(orig.gameObjectActivations[i]);
}
skinDefParams.meshReplacements = (MeshReplacement[])(object)new MeshReplacement[orig.meshReplacements.Length];
for (int j = 0; j < orig.meshReplacements.Length; j++)
{
skinDefParams.meshReplacements[j] = MeshReplacement.op_Implicit(orig.meshReplacements[j]);
}
skinDefParams.projectileGhostReplacements = (ProjectileGhostReplacement[])(object)new ProjectileGhostReplacement[orig.projectileGhostReplacements.Length];
for (int k = 0; k < orig.projectileGhostReplacements.Length; k++)
{
skinDefParams.projectileGhostReplacements[k] = ProjectileGhostReplacement.op_Implicit(orig.projectileGhostReplacements[k]);
}
skinDefParams.minionSkinReplacements = (MinionSkinReplacement[])(object)new MinionSkinReplacement[orig.minionSkinReplacements.Length];
for (int l = 0; l < orig.minionSkinReplacements.Length; l++)
{
skinDefParams.minionSkinReplacements[l] = MinionSkinReplacement.op_Implicit(orig.minionSkinReplacements[l]);
}
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", "X:\\Git\\RoR2\\MercSkinsFix\\MercSkinsFix\\StringExtensions.cs", "FilterConfigKey", 36);
return key;
}
return key.FilterChars(_invalidConfigDefinitionChars).Trim();
}
}
}