using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using Bounce.Singletons;
using ModdingTales;
using SRF;
using UnityEngine;
using UnityEngine.Video;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RetexturePlugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RetexturePlugin")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("RetexturePlugin")]
[assembly: ComVisible(false)]
[assembly: Guid("c303405d-e66c-4316-9cdb-4e3ca15c6360")]
[assembly: AssemblyFileVersion("3.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("3.0.0.0")]
namespace LordAshes;
[BepInPlugin("org.lordashes.plugins.retexture", "Retexture Plug-In", "3.0.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class RetexturePlugin : BaseUnityPlugin
{
public static class Utility
{
public static bool isBoardLoaded()
{
return SimpleSingletonBehaviour<CameraController>.HasInstance && SingletonStateMBehaviour<BoardSessionManager, State<BoardSessionManager>>.HasInstance && !BoardSessionManager.IsLoading;
}
public static float ParseFloat(string value)
{
return float.Parse(value, CultureInfo.InvariantCulture);
}
public static object FindObjectInHierarchy<T>(GameObject start, string fullName = null, string partialName = null)
{
return FindObjectsInHierarchy<T>(start, fullName, partialName)?.ElementAt(0);
}
public static object[] FindObjectsInHierarchy<T>(GameObject start, string fullName = null, string partialName = null)
{
List<object> results = new List<object>();
Traverse<T>(start, ref results, fullName, partialName);
if (results.Count > 0)
{
return results.ToArray();
}
return null;
}
public static void Traverse<T>(GameObject start, ref List<object> results, string fullName = null, string partialName = null)
{
LoggingPlugin.LogDebug("Found GameObject " + ((Object)start).name + " (" + ((Object)start.transform).name + ") While Seeking " + typeof(T).ToString() + " With Name " + ((fullName == null) ? "Unspecified" : fullName) + " And Parial Name " + ((partialName == null) ? "Unspecified" : partialName));
if (((object)start).GetType() == typeof(T) && (fullName == null || ((Object)start).name == fullName) && (partialName == null || ((Object)start).name.Contains(partialName)))
{
LoggingPlugin.LogDebug("Adding GameObject " + ((Object)start).name + " To Results");
results.Add(start);
}
Component[] components = start.GetComponents(typeof(T));
foreach (Component val in components)
{
LoggingPlugin.LogDebug("Found GameObject " + ((Object)start).name + " (" + ((Object)start.transform).name + ") Component " + ((Object)val).name + " (" + ((object)val).GetType().ToString() + ") While Seeking " + typeof(T).ToString() + " With Name " + ((fullName == null) ? "Unspecified" : fullName) + " And Parial Name " + ((partialName == null) ? "Unspecified" : partialName));
if ((fullName == null || ((Object)start).name == fullName) && (partialName == null || ((Object)start).name.Contains(partialName)))
{
LoggingPlugin.LogDebug("Assing GameObject " + ((Object)start).name + " Component " + ((Object)val).name + " To Results");
results.Add(val);
}
}
foreach (Transform child in SRFTransformExtensions.GetChildren(start.transform))
{
Traverse<T>(((Component)child).gameObject, ref results, fullName, partialName);
}
}
public static GameObject FindObjectWithInHierarchy<T>(GameObject start, string fullName = null, string partialName = null)
{
return FindObjectsWithInHierarchy<T>(start, fullName, partialName)?.ElementAt(0);
}
public static GameObject[] FindObjectsWithInHierarchy<T>(GameObject start, string fullName = null, string partialName = null)
{
List<GameObject> results = new List<GameObject>();
TraverseWith<T>(start, ref results, fullName, partialName);
if (results.Count > 0)
{
return results.ToArray();
}
return null;
}
public static void TraverseWith<T>(GameObject start, ref List<GameObject> results, string fullName = null, string partialName = null)
{
LoggingPlugin.LogDebug("Found GameObject " + ((Object)start).name + " (" + ((Object)start.transform).name + ") While Seeking " + typeof(T).ToString() + " With Name " + ((fullName == null) ? "Unspecified" : fullName) + " And Parial Name " + ((partialName == null) ? "Unspecified" : partialName));
if (((object)start).GetType() == typeof(T) && (fullName == null || ((Object)start).name == fullName) && (partialName == null || ((Object)start).name.Contains(partialName)))
{
LoggingPlugin.LogDebug("Adding GameObject " + ((Object)start).name + " To Results");
results.Add(start);
}
Component[] components = start.GetComponents(typeof(T));
foreach (Component val in components)
{
LoggingPlugin.LogDebug("Found GameObject " + ((Object)start).name + " (" + ((Object)start.transform).name + ") Component " + ((Object)val).name + " (" + ((object)val).GetType().ToString() + ") While Seeking " + typeof(T).ToString() + " With Name " + ((fullName == null) ? "Unspecified" : fullName) + " And Parial Name " + ((partialName == null) ? "Unspecified" : partialName));
if ((fullName == null || ((Object)start).name == fullName) && (partialName == null || ((Object)start).name.Contains(partialName)))
{
LoggingPlugin.LogDebug("Adding GameObject " + ((Object)start).name + " Component To Results");
results.Add(start);
}
}
foreach (Transform child in SRFTransformExtensions.GetChildren(start.transform))
{
TraverseWith<T>(((Component)child).gameObject, ref results, fullName, partialName);
}
}
public static object LookUp(in Dictionary<string, object> dictionary, string key)
{
foreach (KeyValuePair<string, object> item in dictionary)
{
if (item.Key.ToUpper() == key.ToUpper())
{
return item.Value;
}
}
return null;
}
public static void PostOnMainPage(BaseUnityPlugin plugin)
{
string text = "Lord Ashes" + ("Lord Ashes".ToUpper().EndsWith("S") ? "'" : "'s");
ModdingUtils.AddPluginToMenuList(plugin, text);
}
}
public const string Name = "Retexture Plug-In";
public const string Guid = "org.lordashes.plugins.retexture";
public const string Version = "3.0.0.0";
public const string Author = "Lord Ashes";
private Dictionary<CreatureGuid, Material> originalMaterials = new Dictionary<CreatureGuid, Material>();
private Guid subscriptionId = System.Guid.Empty;
private ConfigEntry<KeyboardShortcut> triggerKey { get; set; }
private ConfigEntry<KeyboardShortcut> triggerResetKey { get; set; }
private void Awake()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
LoggingPlugin.SetLogLevel(((BaseUnityPlugin)this).Config.Bind<DiagnosticLevel>("Settings", "Diagnostic Level", (DiagnosticLevel)3, (ConfigDescription)null).Value);
string? assemblyQualifiedName = ((object)this).GetType().AssemblyQualifiedName;
DiagnosticLevel logLevel = LoggingPlugin.GetLogLevel();
LoggingPlugin.LogInfo(assemblyQualifiedName + ": Active. (Diagnostic Mode = " + ((object)(DiagnosticLevel)(ref logLevel)).ToString() + ")");
triggerKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Repaint Asset Activation", new KeyboardShortcut((KeyCode)120, (KeyCode[])(object)new KeyCode[1] { (KeyCode)305 }), (ConfigDescription)null);
triggerResetKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Transform (Recall) Repainted", new KeyboardShortcut((KeyCode)121, (KeyCode[])(object)new KeyCode[1] { (KeyCode)305 }), (ConfigDescription)null);
AssetDataPlugin.Subscribe("org.lordashes.plugins.retexture", (Action<DatumChange>)RequestHandler, (Func<DatumChange, bool>)Checker.CheckSourceAsCreature);
Utility.PostOnMainPage((BaseUnityPlugin)(object)this);
}
private void Update()
{
//IL_0007: 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)
//IL_00a9: 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_002d: Unknown result type (might be due to invalid IL or missing references)
KeyboardShortcut value = triggerKey.Value;
if (((KeyboardShortcut)(ref value)).IsUp())
{
LoggingPlugin.LogDebug("Make Retexture Request For Selected Mini");
CreatureBoardAsset asset = default(CreatureBoardAsset);
CreaturePresenter.TryGetAsset(LocalClient.SelectedCreatureId, ref asset);
if ((Object)(object)asset != (Object)null)
{
SystemMessage.AskForTextInput("Replacement Texture...", "\r\nSource:", "Texture", (Action<string>)delegate(string source)
{
//IL_0007: 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)
CreatureGuid creatureId2 = asset.CreatureId;
AssetDataPlugin.SetInfo(((object)(CreatureGuid)(ref creatureId2)).ToString(), "org.lordashes.plugins.retexture", source, false);
}, (Action)null, "Original", (Action)delegate
{
//IL_0007: 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)
CreatureGuid creatureId = asset.CreatureId;
AssetDataPlugin.ClearInfo(((object)(CreatureGuid)(ref creatureId)).ToString(), "org.lordashes.plugins.retexture", false);
}, "");
}
else
{
SystemMessage.DisplayInfoText("Retexture Plugin Requires A Selected Mini", 2.5f, 0f, (Action)null);
}
}
value = triggerResetKey.Value;
if (((KeyboardShortcut)(ref value)).IsUp())
{
LoggingPlugin.LogDebug("Reset Retexture Subscription");
if (subscriptionId != System.Guid.Empty)
{
AssetDataPlugin.Unsubscribe(subscriptionId);
AssetDataPlugin.Subscribe("org.lordashes.plugins.retexture", (Action<DatumChange>)RequestHandler, (Func<DatumChange, bool>)Checker.CheckSourceAsCreature);
}
}
}
private void RequestHandler(DatumChange change)
{
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Expected O, but got Unknown
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01b8: Invalid comparison between Unknown and I4
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Expected O, but got Unknown
if (change.source != null && change.source != "" && change.key != null && change.value != null)
{
LoggingPlugin.LogDebug("Request To Retexture " + change.source + " To " + change.value);
CreatureBoardAsset val = null;
CreaturePresenter.TryGetAsset(new CreatureGuid(change.source), ref val);
Material val2 = null;
GameObject val3 = Utility.FindObjectWithInHierarchy<GameObject>(((Component)val).gameObject, null, "Effect:");
if ((Object)(object)val3 == (Object)null)
{
val3 = (GameObject)Utility.FindObjectInHierarchy<GameObject>(((Component)val).gameObject, null, "_Rotator");
bool flag = val3.GetComponentsInChildren<MeshFilter>().Any((MeshFilter mf) => StartsWithGuid(((Object)mf).name));
LoggingPlugin.LogDebug("Asset Is ANGEL Asset? " + ((Behaviour)this).isActiveAndEnabled);
if (!flag)
{
val3 = (GameObject)Utility.FindObjectInHierarchy<GameObject>(((Component)val).gameObject, null, "local[br");
}
LoggingPlugin.LogDebug("Starting Asset Seek At " + ((Object)val3).name);
}
else
{
LoggingPlugin.LogDebug("Starting Effect Seek At " + ((Object)val3).name);
}
val2 = FindMaterial(val3, "RETEXTURE_MAT");
LoggingPlugin.LogDebug("Modifying " + ((Object)val2).name + ", Texture " + ((Object)val2.mainTexture).name + ", Shader " + ((Object)val2.shader).name);
if ((int)change.action != 1 && (Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
{
ApplyTexture(val, val3, val2, change.value.ToString());
}
else if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
{
RestoreTexture(val, val3, val2);
}
}
else
{
LoggingPlugin.LogWarning("Retexture Request Incomplete");
if (change.source == null || change.source == "")
{
LoggingPlugin.LogWarning("Retexture Request Missing Souce");
}
if (change.key == null)
{
LoggingPlugin.LogWarning("Retexture Request Missing Key");
}
if (change.value == null)
{
LoggingPlugin.LogWarning("Retexture Request Missing Value");
}
}
}
private void ApplyTexture(CreatureBoardAsset asset, GameObject go, Material mat, string source)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)asset != (Object)null && (Object)(object)mat != (Object)null && source != null && source != "")
{
if (!originalMaterials.ContainsKey(asset.CreatureId))
{
LoggingPlugin.LogDebug("Storing orignal " + asset.Name + " material");
originalMaterials.Add(asset.CreatureId, mat);
}
if (source.EndsWith(".mp4") || source.EndsWith(".mov;") || source.EndsWith(".webm;") || source.EndsWith(".wmv;"))
{
ApplyVideo(go, "RETEXTURE_MAT", source);
return;
}
SRFGameObjectExtensions.RemoveComponentIfExists<VideoPlayer>(go);
IEnumerable<GameObject> enumerable = from v in go.GetComponentsInChildren<VideoPlayer>()
select ((Component)v).gameObject;
foreach (GameObject item in enumerable)
{
SRFGameObjectExtensions.RemoveComponentIfExists<VideoPlayer>(item);
}
LoggingPlugin.LogDebug("Retexturing " + asset.Name + " main texture (" + ((Object)mat).name + ":" + ((Object)mat.mainTexture).name + ") with '" + source + "'");
mat.mainTexture = (Texture)(object)LoadTextureRGBA32(File.Find(source, (CacheType)999).First());
}
else
{
LoggingPlugin.LogWarning("Apply Texture Has Null Asset, Null Mateiral, Or Null Source");
}
}
private void RestoreTexture(CreatureBoardAsset asset, GameObject go, Material mat)
{
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
if (((Object)(object)asset != (Object)null) & ((Object)(object)mat != (Object)null))
{
SRFGameObjectExtensions.RemoveComponentIfExists<VideoPlayer>(go);
IEnumerable<GameObject> enumerable = from v in go.GetComponentsInChildren<VideoPlayer>()
select ((Component)v).gameObject;
foreach (GameObject item in enumerable)
{
SRFGameObjectExtensions.RemoveComponentIfExists<VideoPlayer>(item);
}
LoggingPlugin.LogDebug("Restoring " + asset.Name + " original material");
mat = originalMaterials[asset.CreatureId];
LoggingPlugin.LogDebug("Removing stored material for " + asset.Name);
originalMaterials.Remove(asset.CreatureId);
}
else
{
LoggingPlugin.LogWarning("Restore Texture Has Null Asset, or Null Mateiral");
}
}
private Material FindMaterial(GameObject asset, string name, bool useDefault = true)
{
List<Renderer> list = new List<Renderer>();
MeshRenderer[] componentsInChildren = asset.GetComponentsInChildren<MeshRenderer>();
foreach (MeshRenderer val in componentsInChildren)
{
LoggingPlugin.LogDebug("Adding MeshRenderer " + ((Object)val).name);
list.Add((Renderer)(object)val);
}
SkinnedMeshRenderer[] componentsInChildren2 = asset.GetComponentsInChildren<SkinnedMeshRenderer>();
foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
{
LoggingPlugin.LogDebug("Adding SkinnedMeshRenderer " + ((Object)val2).name);
list.Add((Renderer)(object)val2);
}
foreach (Renderer item in list)
{
Material[] materials = item.materials;
foreach (Material val3 in materials)
{
LoggingPlugin.LogDebug("Looking At Material " + ((Object)item).name + "." + ((Object)val3).name);
if (((Object)val3).name.Contains(name))
{
LoggingPlugin.LogDebug("Retexture Plug-In Found " + ((Object)item).name + "." + ((Object)val3).name);
return val3;
}
}
}
LoggingPlugin.LogDebug("Using Default/Null");
return useDefault ? list[0].material : null;
}
private void ApplyVideo(GameObject asset, string name, string source)
{
if ((Object)(object)asset != (Object)null && name != null && name != "" && source != null && source != "")
{
List<Renderer> list = new List<Renderer>();
MeshRenderer[] componentsInChildren = asset.GetComponentsInChildren<MeshRenderer>();
foreach (MeshRenderer val in componentsInChildren)
{
LoggingPlugin.LogDebug("Adding MeshRenderer " + ((Object)val).name);
list.Add((Renderer)(object)val);
}
SkinnedMeshRenderer[] componentsInChildren2 = asset.GetComponentsInChildren<SkinnedMeshRenderer>();
foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
{
LoggingPlugin.LogDebug("Adding SkinnedMeshRenderer " + ((Object)val2).name);
list.Add((Renderer)(object)val2);
}
{
VideoPlayer val4 = default(VideoPlayer);
foreach (Renderer item in list)
{
Material[] materials = item.materials;
foreach (Material val3 in materials)
{
LoggingPlugin.LogDebug("Looking At Material " + ((Object)item).name + "." + ((Object)val3).name);
if (((Object)val3).name.Contains(name))
{
LoggingPlugin.LogDebug("Found " + ((Object)item).name + "." + ((Object)val3).name);
GameObject gameObject = ((Component)item).gameObject;
if (!gameObject.TryGetComponent<VideoPlayer>(ref val4))
{
val4 = gameObject.AddComponent<VideoPlayer>();
}
val4.playOnAwake = true;
val4.source = (VideoSource)1;
if (!source.StartsWith("http"))
{
source = "file://" + source;
}
val4.url = source;
val4.isLooping = true;
return;
}
}
}
return;
}
}
LoggingPlugin.LogWarning("Apply Vide Has Null Asset, Null Name, or Null Source");
}
private static string Lineage(GameObject gameObject)
{
string text = ((Object)gameObject).name;
while ((Object)(object)gameObject.transform.parent != (Object)null)
{
gameObject = ((Component)gameObject.transform.parent).gameObject;
text = ((Object)gameObject).name + "." + text;
}
return text;
}
public static bool StartsWithGuid(string input)
{
if (string.IsNullOrWhiteSpace(input))
{
return false;
}
int num = Math.Min(input.Length, 38);
for (int i = 32; i <= num; i++)
{
if (System.Guid.TryParse(input.Substring(0, i), out var _))
{
return true;
}
}
return false;
}
public static Texture2D LoadTextureRGBA32(string filePath)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
if (!File.Exists(filePath))
{
Debug.LogError((object)("Texture file not found: " + filePath));
return null;
}
byte[] array = File.ReadAllBytes(filePath);
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false, false);
if (!ImageConversion.LoadImage(val, array, false))
{
Debug.LogError((object)("Failed to load image: " + filePath));
return null;
}
((Texture)val).wrapMode = (TextureWrapMode)1;
((Texture)val).filterMode = (FilterMode)1;
val.Apply();
return val;
}
}