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 AnotherRandomPaintingSwap v1.0.5
RandomPaintingSwap.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; 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 HarmonyLib; using Microsoft.CodeAnalysis; using RandomPaintingSwap; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RandomPaintingSwap")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+ff6399ba9851f93138ba93ed9f826aa8c9d0ee43")] [assembly: AssemblyProduct("Random Painting Swap")] [assembly: AssemblyTitle("RandomPaintingSwap")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.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 AnotherRandomPaintingSwap { [BepInPlugin("phnod.randompaintingswap", "Another Random Painting Swap", "1.0.3")] public class Plugin : BaseUnityPlugin { public class CustomPainting { public Material material; public string textureName = "UNASSIGNED STRING"; } public class ReplaceablePainting { public MeshRenderer meshRenderer; } public class PaintingGroup { public string paintingType; public string paintingFolderName; public HashSet<string> whitelistMaterials; public List<CustomPainting> customPaintings; public List<CustomPainting> unusedPaintings; public Material baseMaterial; public PaintingGroup(string InPaintingType, string InPaintingFolderName, HashSet<string> InWhitelistMaterials) { paintingType = InPaintingType; paintingFolderName = InPaintingFolderName; whitelistMaterials = InWhitelistMaterials; customPaintings = new List<CustomPainting>(); unusedPaintings = new List<CustomPainting>(); } } [HarmonyPatch(typeof(LoadingUI), "LevelAnimationComplete")] public class PatchLoadingUI { [HarmonyPostfix] private static void Postfix() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); List<GameObject> list = ((Scene)(ref activeScene)).GetRootGameObjects().ToList(); DebugLog($"Num of GameObjects: [{list.Count}]"); if (list.Count > 0) { UpdateMaterialParameters(); GetReplacableMaterials(list); ReplaceMaterials(); } } } private const string IMAGE_LANDSCAPE_FOLDER_NAME = "RandomLandscapePaintingSwap_Images"; private const string IMAGE_SQUARE_FOLDER_NAME = "RandomSquarePaintingSwap_Images"; private const string IMAGE_PORTRAIT_FOLDER_NAME = "RandomPortraitPaintingSwap_Images"; private const string MATERIAL_LANDSCAPE_ASSET_NAME = "GrungeHorizontalMaterial"; private const string MATERIAL_PORTRAIT_ASSET_NAME = "GrungeVerticalMaterial"; private static Material _LandscapeMaterial; private static Material _PortraitMaterial; public static readonly HashSet<string> whitelistLandscapeMaterials; public static readonly HashSet<string> whitelistSquareMaterials; public static readonly HashSet<string> whitelistPortraitMaterials; internal static List<ReplaceablePainting> replaceablePaintings; internal static int pseudorandomSeed; public static List<PaintingGroup> paintingGroups; internal static ManualLogSource Logger; public static readonly HashSet<string> imagePatterns; private readonly Harmony harmony = new Harmony("phnod.anotherrandompaintingswap"); public static Plugin Instance { get; private set; } static Plugin() { whitelistLandscapeMaterials = new HashSet<string> { "Painting_H_Landscape", "Painting_H_crow", "Painting_H_crow_0", "PaintingMedium" }; whitelistSquareMaterials = new HashSet<string> { "Painting_S_Creep", "Painting_S_Creep 2_0", "Painting_S_Creep 2", "Painting Wizard Class" }; whitelistPortraitMaterials = new HashSet<string> { "Painting_V_jannk", "Painting_V_Furman", "Painting_V_surrealistic", "Painting_V_surrealistic_0", "painting teacher01", "painting teacher02", "painting teacher03", "painting teacher04", "Painting_S_Tree" }; replaceablePaintings = new List<ReplaceablePainting>(); pseudorandomSeed = 0; imagePatterns = new HashSet<string> { "*.png", "*.jpg", "*.jpeg", "*.psd" }; paintingGroups = new List<PaintingGroup> { new PaintingGroup("Landscape", "RandomLandscapePaintingSwap_Images", whitelistLandscapeMaterials), new PaintingGroup("Square", "RandomSquarePaintingSwap_Images", whitelistSquareMaterials), new PaintingGroup("Portrait", "RandomPortraitPaintingSwap_Images", whitelistPortraitMaterials) }; } private void Awake() { Instance = this; Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin Another Random Painting Swap is loaded!"); PluginConfig.Init(((BaseUnityPlugin)this).Config); harmony.PatchAll(Assembly.GetExecutingAssembly()); DebugLog("DebugLog enabled. Expect bad loading performance"); AssignMaterialGroups(); LoadImagesFromAllPlugins(); } private static void UpdateMaterialParameters() { //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0189: 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) //IL_009a: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) foreach (PaintingGroup paintingGroup in paintingGroups) { string paintingType = paintingGroup.paintingType; if (paintingType == "Portrait") { paintingGroup.baseMaterial = _PortraitMaterial; } else { paintingGroup.baseMaterial = _LandscapeMaterial; } if ((Object)(object)paintingGroup.baseMaterial == (Object)null) { Logger.LogWarning((object)("No base material found for [" + paintingType + "]!")); } else if (PluginConfig.Grunge.enableGrunge.Value) { paintingGroup.baseMaterial.SetColor(((ConfigEntryBase)PluginConfig.Grunge._BaseColor).Definition.Key, PluginConfig.Grunge._BaseColor.Value); paintingGroup.baseMaterial.SetColor(((ConfigEntryBase)PluginConfig.Grunge._MainColor).Definition.Key, PluginConfig.Grunge._MainColor.Value); paintingGroup.baseMaterial.SetColor(((ConfigEntryBase)PluginConfig.Grunge._CracksColor).Definition.Key, PluginConfig.Grunge._CracksColor.Value); paintingGroup.baseMaterial.SetColor(((ConfigEntryBase)PluginConfig.Grunge._OutlineColor).Definition.Key, PluginConfig.Grunge._OutlineColor.Value); paintingGroup.baseMaterial.SetFloat(((ConfigEntryBase)PluginConfig.Grunge._CracksPower).Definition.Key, PluginConfig.Grunge._CracksPower.Value); } else { paintingGroup.baseMaterial.SetColor(((ConfigEntryBase)PluginConfig.Grunge._BaseColor).Definition.Key, Color.clear); paintingGroup.baseMaterial.SetColor(((ConfigEntryBase)PluginConfig.Grunge._MainColor).Definition.Key, Color.clear); paintingGroup.baseMaterial.SetColor(((ConfigEntryBase)PluginConfig.Grunge._CracksColor).Definition.Key, Color.clear); paintingGroup.baseMaterial.SetColor(((ConfigEntryBase)PluginConfig.Grunge._OutlineColor).Definition.Key, Color.clear); } } } private void AssignMaterialGroups() { string? directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = "painting"; string text2 = Path.Combine(directoryName, text); Logger.LogInfo((object)("Loading [" + text2 + "]")); if (File.Exists(text2)) { Logger.LogInfo((object)"Asset Bundle exists"); } else { Logger.LogWarning((object)"Asset Bundle doesn't exist"); } AssetBundle val = AssetBundle.LoadFromFile(text2); if ((Object)(object)val == (Object)null) { Logger.LogError((object)("Failed to load [" + text + "]")); } else { _LandscapeMaterial = val.LoadAsset<Material>("GrungeHorizontalMaterial"); if ((Object)(object)_LandscapeMaterial == (Object)null) { Logger.LogError((object)"Could not load landscape painting material [GrungeHorizontalMaterial]!"); } _PortraitMaterial = val.LoadAsset<Material>("GrungeVerticalMaterial"); if ((Object)(object)_PortraitMaterial == (Object)null) { Logger.LogError((object)"Could not load portrait painting material [GrungeVerticalMaterial]!"); } } UpdateMaterialParameters(); } private void LoadImagesFromAllPlugins() { string text = Path.Combine(Paths.PluginPath); if (!Directory.Exists(text)) { Logger.LogWarning((object)("Plugins directory not found: [" + text + "]")); return; } foreach (PaintingGroup paintingGroup in paintingGroups) { string paintingFolderName = paintingGroup.paintingFolderName; string[] directories = Directory.GetDirectories(text, paintingFolderName, SearchOption.AllDirectories); if (directories.Length == 0) { Logger.LogWarning((object)"No 'CustomPaintings' folders found in plugins."); break; } string[] array = directories; foreach (string text2 in array) { Logger.LogInfo((object)("Loading images from: [" + text2 + "]")); LoadImagesFromDirectory(paintingGroup, text2); } } } private void LoadImagesFromDirectory(PaintingGroup InPaintingGroup, string directoryPath) { //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown string paintingType = InPaintingGroup.paintingType; if (!Directory.Exists(directoryPath)) { Logger.LogWarning((object)("The folder [" + directoryPath + "] does not exist!")); return; } Logger.LogInfo((object)("Selecting image patterns for group [" + paintingType + "] for files : " + directoryPath)); List<string> list = imagePatterns.SelectMany((string pattern) => Directory.GetFiles(directoryPath, pattern)).ToList(); if (!list.Any()) { Logger.LogWarning((object)("No images found in the folder [" + directoryPath + "]")); return; } foreach (string item in list) { string fileName = Path.GetFileName(item); Texture2D val = LoadTextureFromFile(item); if ((Object)(object)val == (Object)null) { Logger.LogWarning((object)("Error loading image : [" + item + "]")); continue; } Material baseMaterial = InPaintingGroup.baseMaterial; Material val2; if ((Object)(object)baseMaterial == (Object)null) { val2 = new Material(Shader.Find("Standard")) { mainTexture = (Texture)(object)val }; } else { val2 = new Material(baseMaterial); val2.SetTexture("_MainTex", (Texture)(object)val); } CustomPainting customPainting = new CustomPainting(); customPainting.material = val2; customPainting.textureName = fileName; InPaintingGroup.customPaintings.Add(customPainting); Logger.LogInfo((object)("Created Material for group [" + paintingType + "] for loaded image : " + fileName)); } InPaintingGroup.unusedPaintings.Clear(); InPaintingGroup.unusedPaintings.AddRange(InPaintingGroup.customPaintings); Logger.LogInfo((object)$"Total Images for group [{paintingType}] : [{list.Count}]"); } private static int HashRoundedPosition(Vector3 position) { //IL_0005: 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) return ((17 * 23 + ((int)(position.x * 10f)).GetHashCode()) * 23 + ((int)(position.y * 10f)).GetHashCode()) * 23 + ((int)(position.z * 10f)).GetHashCode(); } private static void PseudorandomSortList(List<ReplaceablePainting> InList) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) Logger.LogDebug((object)"Randomly sorting painting list"); if (InList == null || InList.Count <= 0) { return; } pseudorandomSeed = 17; foreach (ReplaceablePainting In in InList) { MeshRenderer meshRenderer = In.meshRenderer; pseudorandomSeed = pseudorandomSeed * 23 + HashRoundedPosition(((Component)meshRenderer).transform.position); } InList.Sort(delegate(ReplaceablePainting a, ReplaceablePainting b) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) int num = ((Component)b.meshRenderer).transform.position.z.CompareTo(((Component)a.meshRenderer).transform.position.z); if (num != 0) { return num; } int num2 = ((Component)b.meshRenderer).transform.position.x.CompareTo(((Component)a.meshRenderer).transform.position.x); return (num2 != 0) ? num2 : ((Component)b.meshRenderer).transform.position.y.CompareTo(((Component)a.meshRenderer).transform.position.y); }); } private static CustomPainting GetPseudorandomPainting(PaintingGroup InPaintingGroup, MeshRenderer InMeshRenderer, out int OutHash) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) OutHash = 0; if (InPaintingGroup == null) { Logger.LogError((object)"Painting Group is NULL"); return null; } if ((Object)(object)InMeshRenderer == (Object)null) { Logger.LogError((object)"InMeshRenderer is NULL"); return null; } if (InPaintingGroup.customPaintings == null) { Logger.LogError((object)"Painting Group custompaintings is NULL"); return null; } if (InPaintingGroup.unusedPaintings == null) { Logger.LogError((object)"Painting Group unusedPaintings is NULL"); return null; } if (InPaintingGroup.unusedPaintings.Count <= 0) { InPaintingGroup.unusedPaintings.AddRange(InPaintingGroup.customPaintings); Logger.LogInfo((object)("Added all possible custom paintings for [" + InPaintingGroup.paintingType + "], adding new set of duplicates.")); } if (InPaintingGroup.unusedPaintings.Count <= 0) { return null; } OutHash = Mathf.Abs(HashRoundedPosition(((Component)InMeshRenderer).transform.position)); int index = OutHash % InPaintingGroup.unusedPaintings.Count; CustomPainting result = InPaintingGroup.unusedPaintings[index]; InPaintingGroup.unusedPaintings.RemoveAt(index); return result; } private Texture2D LoadTextureFromFile(string filePath) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown byte[] array = File.ReadAllBytes(filePath); Texture2D val = new Texture2D(2, 2); if (!ImageConversion.LoadImage(val, array)) { val = null; return null; } val.Apply(); return val; } private static void ReplaceMaterials() { //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) PseudorandomSortList(replaceablePaintings); Logger.LogDebug((object)"Replacing base images with plugin images"); foreach (ReplaceablePainting replaceablePainting in replaceablePaintings) { MeshRenderer meshRenderer = replaceablePainting.meshRenderer; Material[] sharedMaterials = ((Renderer)meshRenderer).sharedMaterials; if (sharedMaterials == null) { continue; } for (int i = 0; i < sharedMaterials.Length; i++) { foreach (PaintingGroup paintingGroup in paintingGroups) { Material val = sharedMaterials[i]; if ((Object)(object)val == (Object)null || !paintingGroup.whitelistMaterials.Contains(((Object)val).name) || paintingGroup.customPaintings.Count <= 0) { continue; } int OutHash; CustomPainting pseudorandomPainting = GetPseudorandomPainting(paintingGroup, meshRenderer, out OutHash); if (pseudorandomPainting == null) { Logger.LogError((object)$"Could not get painting from [{paintingGroup}][{meshRenderer}]"); continue; } float num = (float)new Random(OutHash).NextDouble(); float value = PluginConfig.customPaintingChance.Value; if (num > PluginConfig.customPaintingChance.Value) { Logger.LogInfo((object)$"[{((Object)val).name}] will not be replaced by a [{paintingGroup.paintingType}]. Random Probability - [{num}/{value}]"); continue; } sharedMaterials[i] = pseudorandomPainting.material; Logger.LogInfo((object)("Found ------------> [" + ((Object)val).name + "] with texture [" + ((Object)val.mainTexture).name + "]")); Logger.LogInfo((object)("Converted to -----> [" + pseudorandomPainting.textureName + "]")); Vector3 position = ((Component)meshRenderer).transform.position; string text = position.x.ToString("F1").PadLeft(7) + "," + position.y.ToString("F1").PadLeft(7) + "," + position.z.ToString("F1").PadLeft(7); Logger.LogDebug((object)("Located at -> [" + text + "]")); } } ((Renderer)meshRenderer).sharedMaterials = sharedMaterials; } } private static void GetReplacableMaterials(List<GameObject> InGameObjects) { Logger.LogInfo((object)"Finding replaceable paintings"); replaceablePaintings.Clear(); foreach (PaintingGroup paintingGroup in paintingGroups) { paintingGroup.unusedPaintings.Clear(); paintingGroup.unusedPaintings.AddRange(paintingGroup.customPaintings); } foreach (GameObject InGameObject in InGameObjects) { MeshRenderer[] componentsInChildren = InGameObject.GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val in componentsInChildren) { bool flag = false; ReplaceablePainting replaceablePainting = null; Material[] sharedMaterials = ((Renderer)val).sharedMaterials; if (sharedMaterials == null) { continue; } for (int j = 0; j < sharedMaterials.Length; j++) { foreach (PaintingGroup paintingGroup2 in paintingGroups) { Material val2 = sharedMaterials[j]; if (!((Object)(object)val2 == (Object)null) && paintingGroup2.whitelistMaterials.Contains(((Object)val2).name) && paintingGroup2.customPaintings.Count > 0) { flag = true; replaceablePainting = new ReplaceablePainting { meshRenderer = val }; } } } if (flag) { if (replaceablePainting == null) { Logger.LogError((object)"Replaceable painting is null, this shouldn't be possible!"); } else { replaceablePaintings.Add(replaceablePainting); } } } } } private static void ReplaceWithCustomImages(List<GameObject> InGameObjects) { foreach (GameObject InGameObject in InGameObjects) { MeshRenderer[] componentsInChildren = InGameObject.GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val in componentsInChildren) { Material[] sharedMaterials = ((Renderer)val).sharedMaterials; if (sharedMaterials == null) { continue; } for (int j = 0; j < sharedMaterials.Length; j++) { foreach (PaintingGroup paintingGroup in paintingGroups) { Material val2 = sharedMaterials[j]; if (!((Object)(object)val2 == (Object)null) && paintingGroup.whitelistMaterials.Contains(((Object)val2).name) && paintingGroup.customPaintings.Count > 0) { int OutHash; CustomPainting pseudorandomPainting = GetPseudorandomPainting(paintingGroup, val, out OutHash); float num = Random.Range(0f, 1f); float value = PluginConfig.customPaintingChance.Value; if (num > PluginConfig.customPaintingChance.Value) { Logger.LogInfo((object)$"[{((Object)val2).name}] will not be replaced by a [{paintingGroup.paintingType}]. Random Probability - [{num}/{value}]"); } else { Random.Range(0, paintingGroup.customPaintings.Count); sharedMaterials[j] = pseudorandomPainting.material; Logger.LogInfo((object)("Found ------------> [" + ((Object)val2).name + "] with texture [" + ((Object)val2.mainTexture).name + "]")); Logger.LogInfo((object)("Converted to -----> [" + pseudorandomPainting.textureName + "]")); } } } } ((Renderer)val).sharedMaterials = sharedMaterials; } } } public static void DebugLog(string InMessage) { if (PluginConfig.enableDebugLog.Value) { Logger.LogDebug((object)InMessage); } } } } namespace RandomPaintingSwap { internal static class PluginConfig { internal static class Grunge { internal static ConfigEntry<bool> enableGrunge; internal static ConfigEntry<Color> _BaseColor; internal static ConfigEntry<Color> _MainColor; internal static ConfigEntry<Color> _CracksColor; internal static ConfigEntry<Color> _OutlineColor; internal static ConfigEntry<float> _CracksPower; } internal static ConfigEntry<bool> enableDebugLog; internal static ConfigEntry<float> customPaintingChance; internal static void Init(ConfigFile InConfig) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) enableDebugLog = InConfig.Bind<bool>("General", "DebugLog", false, "Print extra logs for debugging"); customPaintingChance = InConfig.Bind<float>("General", "CustomPaintingChance", 1f, "The chance of a painting being replaced by a custom painting (1 = 100%, 0.5 = 50%)"); Grunge.enableGrunge = InConfig.Bind<bool>("Grunge", "EnableGrunge", true, "Whether the grunge effect is enabled"); Grunge._BaseColor = InConfig.Bind<Color>("Grunge", "_GrungeBaseColor", new Color(0f, 0f, 0f, 1f), "The base color of the grunge"); Grunge._MainColor = InConfig.Bind<Color>("Grunge", "_GrungeMainColor", new Color(0f, 0f, 0f, 1f), "The color of the main overlay of grunge"); Grunge._CracksColor = InConfig.Bind<Color>("Grunge", "_GrungeCracksColor", new Color(0f, 0f, 0f, 1f), "The color of the cracks in the grunge"); Grunge._OutlineColor = InConfig.Bind<Color>("Grunge", "_GrungeOutlineColor", new Color(0f, 0f, 0f, 1f), "The color of the grunge outlining the painting"); Grunge._CracksPower = InConfig.Bind<float>("Grunge", "_GrungeCracksPow", 1f, "The inverse of intensity of the cracks. 1.0 will have plenty of cracks, higher numbers will have less cracks (Values below 1.0 will start to look bad)"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "RandomPaintingSwap"; public const string PLUGIN_NAME = "Random Painting Swap"; public const string PLUGIN_VERSION = "1.1.0"; } }