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 VojtapekObrazky v1.0.1
CustomPaintings.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.Threading.Tasks; using BepInEx; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; 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("CustomPaintings")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CustomPaintings")] [assembly: AssemblyTitle("CustomPaintings")] [assembly: AssemblyVersion("1.0.0.0")] [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 CustomPaintings { [BepInPlugin("UnderratedJunk.CustomPaintings", "CustomPaintings", "1.0.7")] public class CustomPaintings : BaseUnityPlugin { [HarmonyPatch(typeof(LoadingUI), "LevelAnimationComplete")] public class PaintingSwapPatch { private static void Postfix() { Task.Run(async delegate { int waited = 0; int interval = 50; while (!receivedSeed.HasValue && waited < maxWaitTimeMs) { await Task.Delay(interval); waited += interval; } if (receivedSeed.HasValue) { logger.LogInfo($"[Postfix] Client using received seed: {receivedSeed.Value}"); CustomPaintingsSwap.ReceivedSeed = receivedSeed.Value; receivedSeed = null; } else { logger.LogWarning("[Postfix] Client did not receive seed in time. Proceeding without it."); } swapper.ReplacePaintings(); }); } private static void Prefix() { if (swapper.GetModState() == CustomPaintingsSwap.ModState.Client) { PhotonNetwork.AddCallbackTarget((object)sync); } if (swapper.GetModState() == CustomPaintingsSwap.ModState.Host) { CustomPaintingsSwap.HostSeed = Random.Range(0, int.MaxValue); logger.LogInfo($"Generated Hostseed: {CustomPaintingsSwap.HostSeed}"); PhotonNetwork.AddCallbackTarget((object)sync); sync.SendSeed(CustomPaintingsSwap.HostSeed); } } } [HarmonyPatch(typeof(NetworkConnect), "TryJoiningRoom")] public class JoinLobbyPatch { private static void Prefix() { if (swapper.GetModState() != 0) { swapper.SetState(CustomPaintingsSwap.ModState.Client); } } } [HarmonyPatch(typeof(SteamManager), "HostLobby")] public class HostLobbyPatch { private static bool Prefix() { swapper.SetState(CustomPaintingsSwap.ModState.Host); return true; } } [HarmonyPatch(typeof(SteamManager), "LeaveLobby")] public class LeaveLobbyPatch { private static void Postfix() { PhotonNetwork.RemoveCallbackTarget((object)sync); swapper.SetState(CustomPaintingsSwap.ModState.SinglePlayer); } } private static Logger logger; private static CustomPaintingsLoader loader; private static CustomPaintingsSwap swapper; private static CustomPaintingsSync sync; public static int? receivedSeed = null; public static readonly int maxWaitTimeMs = 1000; private readonly Harmony harmony = new Harmony("UnderratedJunk.CustomPaintings"); private void Awake() { logger = new Logger("CustomPaintings"); logger.LogInfo("CustomPaintings mod initialized."); loader = new CustomPaintingsLoader(logger); loader.LoadImagesFromAllPlugins(); swapper = new CustomPaintingsSwap(logger, loader); sync = new CustomPaintingsSync(logger); harmony.PatchAll(); } } public class CustomPaintingsLoader { private const string IMAGE_FOLDER_NAME = "CustomPaintings"; private readonly Logger logger; public List<Material> LoadedMaterials { get; } = new List<Material>(); public CustomPaintingsLoader(Logger logger) { this.logger = logger; } public void LoadImagesFromAllPlugins() { string text = Path.Combine(Paths.PluginPath); if (!Directory.Exists(text)) { logger.LogWarning("Plugins directory not found: " + text); return; } string[] directories = Directory.GetDirectories(text, "CustomPaintings", SearchOption.AllDirectories); if (directories.Length == 0) { logger.LogWarning("No 'CustomPaintings' folders found in plugins."); return; } string[] array = directories; foreach (string text2 in array) { logger.LogInfo("Loading images from: " + text2); LoadImagesFromDirectory(text2); } } private void LoadImagesFromDirectory(string directoryPath) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown if (!Directory.Exists(directoryPath)) { logger.LogWarning("Directory does not exist: " + directoryPath); return; } string[] validExtensions = new string[4] { ".png", ".jpg", ".jpeg", ".bmp" }; string[] array = (from file in Directory.EnumerateFiles(directoryPath, "*.*", SearchOption.AllDirectories) where validExtensions.Contains(Path.GetExtension(file).ToLower()) select file).ToArray(); if (array.Length == 0) { logger.LogWarning("No images found in " + directoryPath); return; } for (int i = 0; i < array.Length; i++) { string text = array[i]; Texture2D val = LoadTextureFromFile(text); if ((Object)(object)val != (Object)null) { Material item = new Material(Shader.Find("Standard")) { mainTexture = (Texture)(object)val }; LoadedMaterials.Add(item); logger.LogInfo($"Loaded image #{i + 1}: {Path.GetFileName(text)}"); } else { logger.LogWarning($"Failed to load image #{i + 1}: {text}"); } } logger.LogInfo($"Total images loaded: {LoadedMaterials.Count}"); } 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.Apply(); return val; } return null; } } public class CustomPaintingsSwap { public enum ModState { Host, Client, SinglePlayer } private readonly Logger logger; private readonly CustomPaintingsLoader loader; private static int randomSeed = 0; public static int HostSeed = 0; public static int ReceivedSeed = 0; public static int Seed = 0; private int paintingsChangedCount; private static ModState currentState = ModState.SinglePlayer; public ModState GetModState() { return currentState; } public CustomPaintingsSwap(Logger logger, CustomPaintingsLoader loader) { this.logger = logger; this.loader = loader; logger.LogInfo($"Initial ModState: {currentState}"); if (randomSeed == 0) { randomSeed = Random.Range(0, int.MaxValue); logger.LogInfo($"Generated initial random seed: {randomSeed}"); } } public void ReplacePaintings() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (currentState == ModState.SinglePlayer) { Seed = randomSeed; } if (currentState == ModState.Host) { Seed = HostSeed; } if (currentState == ModState.Client) { Seed = ReceivedSeed; } Scene activeScene = SceneManager.GetActiveScene(); logger.LogInfo($"Applying seed {Seed} for painting swaps in scene: {((Scene)(ref activeScene)).name}"); logger.LogInfo("Replacing all materials containing 'painting' with custom images..."); paintingsChangedCount = 0; int num = 0; Scene activeScene2 = SceneManager.GetActiveScene(); GameObject[] rootGameObjects = ((Scene)(ref activeScene2)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { MeshRenderer[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val in componentsInChildren) { Material[] sharedMaterials = ((Renderer)val).sharedMaterials; for (int k = 0; k < sharedMaterials.Length; k++) { num++; if ((Object)(object)sharedMaterials[k] != (Object)null && ((Object)sharedMaterials[k]).name.ToLower().Contains("painting") && !((Object)sharedMaterials[k]).name.Contains("Painting Frame Vertical Gold") && !((Object)sharedMaterials[k]).name.Contains("Painting Frame Horizontal Gold") && loader.LoadedMaterials.Count > 0) { int index = Mathf.Abs((Seed + paintingsChangedCount) % loader.LoadedMaterials.Count); sharedMaterials[k] = loader.LoadedMaterials[index]; paintingsChangedCount++; } } ((Renderer)val).sharedMaterials = sharedMaterials; } } logger.LogInfo($"Total materials checked: {num}"); logger.LogInfo($"Total paintings changed in this scene: {paintingsChangedCount}"); logger.LogInfo($"RandomSeed = {randomSeed}"); logger.LogInfo($"HostSeed = {HostSeed}"); logger.LogInfo($"ReceivedSeed = {ReceivedSeed}"); } public void SetState(ModState newState) { currentState = newState; logger.LogInfo($"Mod state set to: {currentState}"); } } public class CustomPaintingsSync : MonoBehaviourPunCallbacks, IOnEventCallback { private readonly Logger logger; public const byte SeedEventCode = 1; public CustomPaintingsSync(Logger logger) { this.logger = logger; } public void SendSeed(int seed) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_002c: 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_0034: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) object[] array = new object[1] { seed }; logger.LogInfo("sharing seed with other clients"); RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)1, CachingOption = (EventCaching)4 }; PhotonNetwork.RaiseEvent((byte)1, (object)array, val, SendOptions.SendReliable); } public void OnEvent(EventData photonEvent) { if (photonEvent.Code == 1) { int num = (int)((object[])photonEvent.CustomData)[0]; logger.LogInfo($"Received seed: {num}"); CustomPaintingsSwap.ReceivedSeed = num; } } } public class Logger { private readonly string logFilePath; private readonly ManualLogSource logSource; public Logger(string modName) { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); logFilePath = Path.Combine(directoryName, modName + "_log.txt"); if (File.Exists(logFilePath)) { File.Delete(logFilePath); } logSource = Logger.CreateLogSource(modName); } public void LogInfo(string message) { WriteLog("INFO", message); logSource.LogInfo((object)message); } public void LogWarning(string message) { WriteLog("WARNING", message); logSource.LogWarning((object)message); } public void LogError(string message) { WriteLog("ERROR", message); logSource.LogError((object)message); } private void WriteLog(string level, string message) { string text = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{level}] {message}"; File.AppendAllText(logFilePath, text + Environment.NewLine); } public void LogMaterial(Material material) { if ((Object)(object)material != (Object)null && ((Object)material).name.ToLower().Contains("painting")) { LogInfo("Material containing 'painting': " + ((Object)material).name); } } public void ClearLog() { if (File.Exists(logFilePath)) { File.Delete(logFilePath); } } } }