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 Painting Texture Replacer v1.0.0
PaintingReplacer.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [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("PaintingReplacer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PaintingReplacer")] [assembly: AssemblyTitle("PaintingReplacer")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 PaintingReplacer { [BepInPlugin("RKMods.PaintingReplacer", "Painting Texture Replacer", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "RKMods.PaintingReplacer"; public const string PluginName = "Painting Texture Replacer"; public const string PluginVersion = "1.0.0"; private static readonly Random TextureRandom = new Random(); private Harmony? _harmony; internal static ManualLogSource ModLogger { get; private set; } = null; internal static IReadOnlyList<PaintingTexture> PaintingTextures { get; private set; } = Array.Empty<PaintingTexture>(); private void Awake() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown ModLogger = ((BaseUnityPlugin)this).Logger; LoadPaintingTextures(); _harmony = new Harmony("RKMods.PaintingReplacer"); _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Painting Texture Replacer 1.0.0 successfully loaded."); } private void LoadPaintingTextures() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); if (string.IsNullOrEmpty(directoryName)) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not determine the PaintingReplacer plugin directory; painting PNG files cannot be loaded."); return; } string[] files = Directory.GetFiles(directoryName, "painting*.png", SearchOption.TopDirectoryOnly); Array.Sort(files, (IComparer<string>?)StringComparer.OrdinalIgnoreCase); if (files.Length == 0) { ((BaseUnityPlugin)this).Logger.LogError((object)("No painting PNG files were found next to PaintingReplacer.dll in: " + directoryName)); ((BaseUnityPlugin)this).Logger.LogError((object)"Add one or more files named painting.png, painting1.png, painting2.png, and so on."); return; } List<PaintingTexture> list = new List<PaintingTexture>(); string[] array = files; foreach (string text in array) { try { byte[] imageData = File.ReadAllBytes(text); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!val.LoadImage(imageData)) { Object.Destroy((Object)(object)val); ((BaseUnityPlugin)this).Logger.LogError((object)("Painting image could not be decoded and was skipped: " + text)); continue; } string fileName = Path.GetFileName(text); ((Object)val).name = "PaintingReplacer_" + Path.GetFileNameWithoutExtension(fileName); list.Add(new PaintingTexture(fileName, val)); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Painting image successfully loaded: " + fileName)); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to load painting image '{text}': {arg}"); } } PaintingTextures = list; if (list.Count > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Successfully loaded {list.Count} painting image(s)."); } } internal static PaintingTexture? GetRandomPaintingTexture() { if (PaintingTextures.Count == 0) { return null; } return PaintingTextures[TextureRandom.Next(PaintingTextures.Count)]; } } internal sealed class PaintingTexture { internal string FileName { get; } internal Texture2D Texture { get; } internal PaintingTexture(string fileName, Texture2D texture) { FileName = fileName; Texture = texture; } } internal static class Texture2DLoadImageCompatibility { internal static bool LoadImage(this Texture2D texture, byte[] imageData) { MethodInfo? obj = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule", throwOnError: false)?.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }, null); if (obj == null) { throw new MissingMethodException("UnityEngine.ImageConversion.LoadImage(Texture2D, byte[], bool) was not found."); } object obj2 = obj.Invoke(null, new object[3] { texture, imageData, false }); bool flag = default(bool); int num; if (obj2 is bool) { flag = (bool)obj2; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } } } namespace PaintingReplacer.Patches { [HarmonyPatch(typeof(GrabbableObject), "SetScrapValue")] internal static class PaintingPatch { private const int AtlasSize = 512; private static readonly Rect PaintingArea = new Rect(264f, 20f, 243f, 324f); private static readonly Dictionary<string, Texture2D> AtlasCache = new Dictionary<string, Texture2D>(); [HarmonyPostfix] private static void SetScrapValuePostfix(GrabbableObject __instance) { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.itemProperties == (Object)null || __instance.itemProperties.itemName != "Painting") { return; } PaintingTexture randomPaintingTexture = Plugin.GetRandomPaintingTexture(); if (randomPaintingTexture == null) { return; } Material[] materialVariants = __instance.itemProperties.materialVariants; if (materialVariants == null || materialVariants.Length == 0) { Plugin.ModLogger.LogWarning((object)"Painting found, but its expected materialVariants do not exist."); return; } if (materialVariants.Length < 2) { Plugin.ModLogger.LogWarning((object)$"Painting has {materialVariants.Length} materialVariant(s); 2 were expected."); } if ((Object)(object)__instance.mainObjectRenderer == (Object)null) { Plugin.ModLogger.LogWarning((object)"Painting found, but its mainObjectRenderer is missing."); return; } Material sharedMaterial = ((Renderer)__instance.mainObjectRenderer).sharedMaterial; if ((Object)(object)sharedMaterial == (Object)null) { Plugin.ModLogger.LogWarning((object)"Painting found, but its selected vanilla material is missing."); } else if (!((Object)sharedMaterial).name.StartsWith("PaintingReplacer_Instance")) { Texture2D orCreateAtlas = GetOrCreateAtlas(sharedMaterial, randomPaintingTexture); if (!((Object)(object)orCreateAtlas == (Object)null)) { Material val = new Material(sharedMaterial) { name = "PaintingReplacer_Instance_" + ((Object)sharedMaterial).name }; val.mainTexture = (Texture)(object)orCreateAtlas; ((Renderer)__instance.mainObjectRenderer).sharedMaterial = val; Plugin.ModLogger.LogInfo((object)("Painting found and random texture applied: " + randomPaintingTexture.FileName)); } } } private static Texture2D? GetOrCreateAtlas(Material material, PaintingTexture selectedPainting) { //IL_011c: 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_0147: Expected O, but got Unknown //IL_015d: Unknown result type (might be due to invalid IL or missing references) string key = $"{((Object)material).GetInstanceID()}:{((Object)selectedPainting.Texture).GetInstanceID()}"; if (AtlasCache.TryGetValue(key, out Texture2D value)) { return value; } Texture mainTexture = material.mainTexture; if ((Object)(object)mainTexture == (Object)null) { Plugin.ModLogger.LogWarning((object)("Painting material '" + ((Object)material).name + "' has no mainTexture to use as an atlas base.")); return null; } if (mainTexture.width != 512 || mainTexture.height != 512) { Plugin.ModLogger.LogWarning((object)($"Painting material '{((Object)material).name}' uses a {mainTexture.width}x{mainTexture.height} texture; " + $"the expected vanilla atlas size is {512}x{512}.")); return null; } RenderTexture temporary = RenderTexture.GetTemporary(512, 512, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)0); RenderTexture active = RenderTexture.active; try { Graphics.Blit(mainTexture, temporary); RenderTexture.active = temporary; GL.PushMatrix(); try { GL.LoadPixelMatrix(0f, 512f, 512f, 0f); Graphics.DrawTexture(PaintingArea, (Texture)(object)selectedPainting.Texture); } finally { GL.PopMatrix(); } Texture2D val = new Texture2D(512, 512, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, 512f, 512f), 0, 0, false); val.Apply(false, false); ((Object)val).name = "PaintingReplacer_Atlas_" + ((Object)material).name + "_" + selectedPainting.FileName; AtlasCache.Add(key, val); return val; } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } } } }