Decompiled source of VRisingTextureReplacer v1.0.1

VRisingTextureReplacer.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using ProjectM;
using ProjectM.Hybrid;
using Stunlock.Core;
using Unity.Collections;
using Unity.Entities;
using UnityEngine;
using VRisingTextureReplacer.Helpers;
using VRisingTextureReplacer.Replacer;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("VRisingTextureReplacer")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+9582431cdc624a37d51ac0f0a07a43ef85da2fcd")]
[assembly: AssemblyProduct("My first plugin")]
[assembly: AssemblyTitle("VRisingTextureReplacer")]
[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 VRisingTextureReplacer
{
	[BepInPlugin("VRisingTextureReplacer", "VRisingTextureReplacer", "1.0.0")]
	public class Plugin : BasePlugin
	{
		internal static ManualLogSource Logger;

		internal static ConfigEntry<bool> LoggingEnabledConfig;

		internal static Dictionary<string, Texture2D> ReplacementTextures = new Dictionary<string, Texture2D>();

		internal static Harmony Harmony = new Harmony("VRisingTextureReplacer");

		internal static bool LoggingEnabled => LoggingEnabledConfig?.Value ?? false;

		internal static void Info(string msg)
		{
			if (LoggingEnabled)
			{
				Logger.LogInfo((object)msg);
			}
		}

		internal static void Warning(string msg)
		{
			Logger.LogWarning((object)msg);
		}

		internal static void Error(string msg)
		{
			Logger.LogError((object)msg);
		}

		public override void Load()
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BasePlugin)this).Log;
			LoggingEnabledConfig = ((BasePlugin)this).Config.Bind<bool>("Debug", "EnableInfoLogging", false, "Enable info-level logging. Useful for diagnosing issues; disable for cleaner logs.");
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Textures");
			if (!Directory.Exists(text))
			{
				Error("Textures folder not found: " + text);
				return;
			}
			string[] files = Directory.GetFiles(text, "*.png");
			foreach (string text2 in files)
			{
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text2);
				bool flag = fileNameWithoutExtension.EndsWith("_n", StringComparison.OrdinalIgnoreCase);
				byte[] array = File.ReadAllBytes(text2);
				Texture2D val = (flag ? new Texture2D(2, 2, (TextureFormat)4, true, true) : new Texture2D(2, 2, (TextureFormat)4, true, false));
				if (!ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(array)))
				{
					Error("Failed to load image: " + text2);
					continue;
				}
				val.Compress(true);
				((Object)val).name = fileNameWithoutExtension;
				((Object)val).hideFlags = (HideFlags)32;
				Object.DontDestroyOnLoad((Object)(object)val);
				ReplacementTextures[fileNameWithoutExtension] = val;
				Info($"Loaded: {fileNameWithoutExtension} ({((Texture)val).width}x{((Texture)val).height}) fmt={val.format}{(flag ? " [normal map]" : "")}");
			}
			if (ReplacementTextures.Count == 0)
			{
				Warning("No replacement textures loaded — skipping patch.");
				return;
			}
			ClassInjector.RegisterTypeInIl2Cpp<CoroutineHelper>();
			Harmony.PatchAll();
			Info($"Patched — {ReplacementTextures.Count} replacement texture(s) ready.");
		}

		public override bool Unload()
		{
			foreach (Texture2D value in ReplacementTextures.Values)
			{
				Object.Destroy((Object)(object)value);
			}
			ReplacementTextures.Clear();
			Harmony.UnpatchSelf();
			Info("Unloaded.");
			return true;
		}
	}
}
namespace VRisingTextureReplacer.Replacer
{
	internal static class TextureReplacer
	{
		private static int SwapMaterialTextures(Material material)
		{
			int num = 0;
			foreach (string item in (Il2CppArrayBase<string>)(object)material.GetTexturePropertyNames())
			{
				Texture texture = material.GetTexture(item);
				if (!((Object)(object)texture == (Object)null))
				{
					string name = ((Object)texture).name;
					if (!string.IsNullOrEmpty(name) && Plugin.ReplacementTextures.TryGetValue(name, out var value) && ((Object)texture).GetInstanceID() != ((Object)value).GetInstanceID())
					{
						material.SetTexture(item, (Texture)(object)value);
						Plugin.Info("[TextureReplacer] Swapped: " + name + " on " + item);
						num++;
					}
				}
			}
			return num;
		}

		public static int SwapTexturesForEntity(Entity entity)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			GameObject forEntity = PlayerGameObject.GetForEntity(entity);
			if ((Object)(object)forEntity == (Object)null)
			{
				return 0;
			}
			int num = 0;
			foreach (SkinnedMeshRenderer componentsInChild in forEntity.GetComponentsInChildren<SkinnedMeshRenderer>(true))
			{
				foreach (Material item in (Il2CppArrayBase<Material>)(object)((Renderer)componentsInChild).sharedMaterials)
				{
					if ((Object)(object)item != (Object)null)
					{
						num += SwapMaterialTextures(item);
					}
				}
			}
			foreach (MeshRenderer componentsInChild2 in forEntity.GetComponentsInChildren<MeshRenderer>(true))
			{
				foreach (Material item2 in (Il2CppArrayBase<Material>)(object)((Renderer)componentsInChild2).sharedMaterials)
				{
					if ((Object)(object)item2 != (Object)null)
					{
						num += SwapMaterialTextures(item2);
					}
				}
			}
			return num;
		}
	}
}
namespace VRisingTextureReplacer.Patches
{
	[HarmonyPatch]
	internal static class BuffPollingPatch
	{
		private const int BUFF_VBLOODABILITYREPLACE = 1171608023;

		private static bool _bloodmendActive;

		[HarmonyPatch(typeof(AbilityRunScriptsSystem_Client), "OnUpdate")]
		[HarmonyPostfix]
		private static void OnUpdatePostfix(AbilityRunScriptsSystem_Client __instance)
		{
			bool flag = PlayerState.HasBuff(1171608023);
			if (flag && !_bloodmendActive)
			{
				((MonoBehaviour)CoroutineHelper.Instance).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(HybridEquipmentSystemPatch.DelayedRescan(5f)));
				Plugin.Info("[BuffPollingPatch] Bloodmend added to player character.");
			}
			_bloodmendActive = flag;
		}
	}
	[HarmonyPatch]
	internal static class HybridEquipmentSystemPatch
	{
		[CompilerGenerated]
		private sealed class <DelayedRescan>d__5 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float delay;

			private int <swapped>5__1;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Expected O, but got Unknown
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(delay);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (!PlayerState.EnsurePlayerCache())
					{
						return false;
					}
					<swapped>5__1 = TextureReplacer.SwapTexturesForEntity(PlayerState.Character);
					if (<swapped>5__1 > 0)
					{
						Plugin.Info($"[TextureReplacer] Delayed — {<swapped>5__1}");
					}
					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();
			}
		}

		private static long _signature;

		private static bool _hasInitial;

		[HarmonyPatch(typeof(HybridEquipmentSystem), "OnUpdate")]
		[HarmonyPostfix]
		private static void OnUpdatePostfix(HybridEquipmentSystem __instance)
		{
			//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_001f: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if (!PlayerState.EnsurePlayerCache())
			{
				return;
			}
			EntityManager entityManager = PlayerState.GameWorld.EntityManager;
			if (!((EntityManager)(ref entityManager)).HasComponent<Equipment>(PlayerState.Character))
			{
				return;
			}
			Equipment componentData = ((EntityManager)(ref entityManager)).GetComponentData<Equipment>(PlayerState.Character);
			long num = ComputeSignature(componentData);
			if (!_hasInitial)
			{
				_signature = num;
				_hasInitial = true;
				int num2 = TextureReplacer.SwapTexturesForEntity(PlayerState.Character);
				if (num2 > 0)
				{
					Plugin.Info($"[TextureReplacer] Initial — {num2}");
				}
				((MonoBehaviour)CoroutineHelper.Instance).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(DelayedRescan(0.1f)));
			}
			else if (num != _signature)
			{
				_signature = num;
				int num3 = TextureReplacer.SwapTexturesForEntity(PlayerState.Character);
				if (num3 > 0)
				{
					Plugin.Info($"[TextureReplacer] Immediate — {num3}");
				}
				((MonoBehaviour)CoroutineHelper.Instance).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(DelayedRescan(0.1f)));
			}
		}

		private static long ComputeSignature(Equipment e)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_001d: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0053: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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)
			//IL_009b: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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)
			//IL_00d0: 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)
			long num = 17L;
			num = num * 31 + HashSlot(e.ArmorHeadgearSlot);
			num = num * 31 + HashSlot(e.ArmorChestSlot);
			num = num * 31 + HashSlot(e.WeaponSlot);
			num = num * 31 + HashSlot(e.ArmorFootgearSlot);
			num = num * 31 + HashSlot(e.ArmorLegsSlot);
			num = num * 31 + HashSlot(e.CloakSlot);
			num = num * 31 + HashSlot(e.ArmorGlovesSlot);
			num = num * 31 + HashSlot(e.ChestCosmeticSlot);
			num = num * 31 + HashSlot(e.FootgearCosmeticSlot);
			num = num * 31 + HashSlot(e.LegsCosmeticSlot);
			num = num * 31 + HashSlot(e.CloakCosmeticSlot);
			return num * 31 + HashSlot(e.GlovesCosmeticSlot);
		}

		private static long HashSlot(EquipmentSlot s)
		{
			//IL_0012: 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)
			long num = ((PrefabGUID)(ref s.SlotId)).GuidHash;
			num = (num << 8) | s.TransmogIndex;
			return (num << 1) | (s.HideEquipment ? 1 : 0);
		}

		[IteratorStateMachine(typeof(<DelayedRescan>d__5))]
		internal static IEnumerator DelayedRescan(float delay)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedRescan>d__5(0)
			{
				delay = delay
			};
		}
	}
}
namespace VRisingTextureReplacer.Helpers
{
	public class CoroutineHelper : MonoBehaviour
	{
		private static CoroutineHelper _instance;

		public static CoroutineHelper Instance
		{
			get
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Expected O, but got Unknown
				if ((Object)(object)_instance == (Object)null)
				{
					GameObject val = new GameObject("VRisingTextureReplacer_CoroutineHelper");
					Object.DontDestroyOnLoad((Object)(object)val);
					_instance = ((Il2CppObjectBase)val.AddComponent(Il2CppType.Of<CoroutineHelper>())).Cast<CoroutineHelper>();
				}
				return _instance;
			}
		}
	}
	public static class PlayerGameObject
	{
		private static World _clientWorld;

		private static HybridModelSystem _hybridModelSystem;

		public static GameObject GetForEntity(Entity entity)
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (_clientWorld == null || !_clientWorld.IsCreated)
			{
				_clientWorld = null;
				Enumerator<World> enumerator = World.All.GetEnumerator();
				while (enumerator.MoveNext())
				{
					World current = enumerator.Current;
					if (current.IsCreated && current.Name == "Client_0")
					{
						_clientWorld = current;
						break;
					}
				}
				if (_clientWorld == null)
				{
					return null;
				}
				_hybridModelSystem = null;
			}
			if (_hybridModelSystem == null)
			{
				_hybridModelSystem = _clientWorld.GetExistingSystemManaged<HybridModelSystem>();
				if (_hybridModelSystem == null)
				{
					return null;
				}
			}
			Dictionary<Entity, GameObject> entityToGameObjectMap = _hybridModelSystem.GetEntityToGameObjectMap();
			if (entityToGameObjectMap == null)
			{
				return null;
			}
			GameObject val = default(GameObject);
			return entityToGameObjectMap.TryGetValue(entity, ref val) ? val : null;
		}
	}
	internal static class PlayerState
	{
		private static EntityQuery _playerQuery;

		public static World GameWorld { get; private set; }

		public static Entity Character { get; private set; } = Entity.Null;


		public static bool EnsurePlayerCache()
		{
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: 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_0103: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			if (GameWorld == null || !GameWorld.IsCreated)
			{
				GameWorld = null;
				Character = Entity.Null;
				Enumerator<World> enumerator = World.All.GetEnumerator();
				while (enumerator.MoveNext())
				{
					World current = enumerator.Current;
					if (!current.IsCreated || current.Name.Contains("Loading"))
					{
						continue;
					}
					try
					{
						EntityManager entityManager = current.EntityManager;
						EntityQuery playerQuery = ((EntityManager)(ref entityManager)).CreateEntityQuery((ComponentType[])(object)new ComponentType[1] { ComponentType.ReadOnly<PlayerCharacter>() });
						if (((EntityQuery)(ref playerQuery)).CalculateEntityCount() > 0)
						{
							GameWorld = current;
							_playerQuery = playerQuery;
							break;
						}
					}
					catch
					{
					}
				}
				if (GameWorld == null)
				{
					return false;
				}
			}
			EntityManager entityManager2 = GameWorld.EntityManager;
			if (Character == Entity.Null || !((EntityManager)(ref entityManager2)).Exists(Character))
			{
				NativeArray<Entity> val = ((EntityQuery)(ref _playerQuery)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2));
				Character = ((val.Length > 0) ? val[0] : Entity.Null);
				val.Dispose();
				if (Character == Entity.Null)
				{
					return false;
				}
			}
			return true;
		}

		public static bool HasBuff(int buffGuidHash)
		{
			//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)
			//IL_001e: 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_003d: 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_004d: 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)
			if (!EnsurePlayerCache())
			{
				return false;
			}
			EntityManager entityManager = GameWorld.EntityManager;
			if (!((EntityManager)(ref entityManager)).HasBuffer<BuffBuffer>(Character))
			{
				return false;
			}
			DynamicBuffer<BuffBuffer> buffer = ((EntityManager)(ref entityManager)).GetBuffer<BuffBuffer>(Character, false);
			for (int i = 0; i < buffer.Length; i++)
			{
				BuffBuffer val = buffer[i];
				if (((PrefabGUID)(ref val.PrefabGuid)).GuidHash == buffGuidHash)
				{
					return true;
				}
			}
			return false;
		}

		public static bool HasComponent<T>() where T : struct
		{
			//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)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!EnsurePlayerCache())
			{
				return false;
			}
			EntityManager entityManager = GameWorld.EntityManager;
			return ((EntityManager)(ref entityManager)).HasComponent<T>(Character);
		}

		public static T GetComponent<T>() where T : struct
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			EntityManager entityManager = GameWorld.EntityManager;
			return ((EntityManager)(ref entityManager)).GetComponentData<T>(Character);
		}
	}
}