using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using ObrazkyJakCyp.Components; using StbImageSharp; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ObrazkyJakCyp")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("997-13854")] [assembly: AssemblyProduct("ObrazkyJakCyp")] [assembly: AssemblyCopyright("Copyright © 997-13854 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("1e5440df-10c4-4220-8554-1e5edfe67572")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace ObrazkyJakCyp { internal static class Extensions { public static bool IsPainting(this GrabbableObject obj) { return obj.itemProperties.itemName == "Painting"; } } internal static class Globals { public static Random GRandom = new Random(); public static AssetBundle Bundle = null; public static Shader PaintingShader = null; public static List ValidImages = new List(); public static Dictionary Paintings = new Dictionary(); } internal static class ContentLoader { private struct GifFrame { public Texture2D Frame; public int Delay; } private static Dictionary _cache = new Dictionary(); internal static int _CurrIdx = 0; private static Texture2D TextureFromResult(ImageResult img) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown int num = img.Width * 4; byte[] array = new byte[img.Data.LongLength]; Texture2D val = new Texture2D(img.Width, img.Height, (TextureFormat)4, false); for (int i = 0; i < img.Height; i++) { int srcOffset = i * num; int dstOffset = (img.Height - 1 - i) * num; Buffer.BlockCopy(img.Data, srcOffset, array, dstOffset, num); } val.LoadRawTextureData(array); val.Apply(); return val; } public static PaintingContent GetNextContent() { //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Expected O, but got Unknown string text = Globals.ValidImages[_CurrIdx = (_CurrIdx + 1) % Globals.ValidImages.Count]; if (_cache.TryGetValue(text, out var value)) { return value; } value = new PaintingContent(); value.IsRawTexture = Path.GetFileNameWithoutExtension(text).EndsWith("_tex"); using (FileStream fileStream = File.OpenRead(text)) { try { IEnumerable enumerable = ImageResult.AnimatedGifFramesFromStream((Stream)fileStream, (ColorComponents)4); List list = new List(); value.FramesCnt = 0; foreach (AnimatedFrameResult item in enumerable) { list.Add(new GifFrame { Frame = TextureFromResult((ImageResult)(object)item), Delay = item.DelayInMs }); } GifFrame gifFrame = list.First(); value.IsWide = ((Texture)gifFrame.Frame).width > ((Texture)gifFrame.Frame).height; value.FramesCnt = list.Count; value.Delays = new int[value.FramesCnt]; value.Frames = new Texture2DArray(((Texture)gifFrame.Frame).width, ((Texture)gifFrame.Frame).height, value.FramesCnt, gifFrame.Frame.format, false); for (int i = 0; i < value.FramesCnt; i++) { GifFrame gifFrame2 = list[i]; value.Delays[i] = gifFrame2.Delay; Graphics.CopyTexture((Texture)(object)gifFrame2.Frame, 0, (Texture)(object)value.Frames, i); Object.Destroy((Object)(object)gifFrame2.Frame); } } catch (Exception) { try { ImageResult val = ImageResult.FromStream((Stream)fileStream, (ColorComponents)4); value.IsWide = val.Width > val.Height; value.FramesCnt = 1; value.Delays = null; value.Frames = new Texture2DArray(val.Width, val.Height, 1, (TextureFormat)4, false); Texture2D obj = TextureFromResult(val); Graphics.CopyTexture((Texture)(object)obj, 0, (Texture)(object)value.Frames, 0); Object.Destroy((Object)(object)obj); } catch (Exception ex) { Plugin.logger.LogError((object)ex); return null; } } } value.Frames.Apply(); return _cache[text] = value; } public static void Clear() { foreach (KeyValuePair item in _cache) { Object.DestroyImmediate((Object)(object)item.Value.Frames); } _cache.Clear(); } } internal class PaintingContent { public bool IsRawTexture; public bool IsWide; public int FramesCnt; public int[] Delays; public Texture2DArray Frames; } [BepInPlugin("CecekMan.ObrazkyJakCyp", "ObrazkyJakCyp", "1.1.3")] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class d__14 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private string <>2__current; private int <>l__initialThreadId; private List 5__2; private List.Enumerator <>7__wrap2; private int 5__4; private int 5__5; string IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__14(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>7__wrap2 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; string directory = Config.Directory; if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } 5__2 = new List(); Stack stack = new Stack(); stack.Push(directory); while (stack.Count > 0) { string path = stack.Pop(); string[] directories = Directory.GetDirectories(path); foreach (string item in directories) { stack.Push(item); } directories = Directory.GetFiles(path); foreach (string item2 in directories) { 5__2.Add(item2); } } if (5__2.Count <= Config.MaxImages) { <>7__wrap2 = 5__2.GetEnumerator(); <>1__state = -3; goto IL_012b; } goto IL_0211; } case 1: <>1__state = -3; goto IL_012b; case 2: <>1__state = -1; 5__2.RemoveAt((5__4 + 5__5) % 5__2.Count); goto IL_0211; case 3: { <>1__state = -1; return false; } IL_012b: if (<>7__wrap2.MoveNext()) { string current = <>7__wrap2.Current; <>2__current = current; <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap2 = default(List.Enumerator); goto IL_0222; IL_0211: if (5__2.Count > 0) { 5__4 = ((5__2.Count != 1) ? Globals.GRandom.Next(5__2.Count) : 0); string[] array = new string[64]; for (int j = 0; j < 64; j++) { array[j] = 5__2[(5__4 + j) % 5__2.Count]; } 5__5 = Globals.GRandom.Next(64); <>2__current = array[5__5]; <>1__state = 2; return true; } goto IL_0222; IL_0222: <>2__current = null; <>1__state = 3; return true; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap2).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__14(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private const int IMAGE_BLOCK_LEN = 64; public static ManualLogSource logger { get; private set; } public static PluginConfig Config { get; private set; } internal static bool IsInitialized { get; private set; } private void GetResource(string name, Action then) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ObrazkyJakCyp." + name); if (stream == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to find " + name + "!")); return; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); then(memoryStream); } [IteratorStateMachine(typeof(d__14))] private IEnumerable GetImage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__14(-2); } private void Awake() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) try { if (IsInitialized) { return; } logger = ((BaseUnityPlugin)this).Logger; Config = new PluginConfig(((BaseUnityPlugin)this).Config); if ((Object)(object)Globals.Bundle == (Object)null) { GetResource("Bundle.unity3d", delegate(MemoryStream ms) { Globals.Bundle = AssetBundle.LoadFromStream((Stream)ms); Globals.Bundle.LoadAllAssets(); }); } if ((Object)(object)Globals.Bundle != (Object)null && (Object)(object)Globals.PaintingShader == (Object)null) { Globals.PaintingShader = Globals.Bundle.LoadAsset("PaintingShader"); } new Thread((ThreadStart)delegate { int maxImages = Config.MaxImages; foreach (string item in GetImage()) { if (item == null || (maxImages != -1 && maxImages <= Globals.ValidImages.Count)) { break; } using FileStream fileStream = File.OpenRead(item); if (ImageInfo.FromStream((Stream)fileStream).HasValue) { Globals.ValidImages.Add(item); } else { ((BaseUnityPlugin)this).Logger.LogError((object)("Painting: '" + Path.GetFileName(item) + "' is not a valid image file!")); } } ContentLoader._CurrIdx = Globals.GRandom.Next(Globals.ValidImages.Count); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded {Globals.ValidImages.Count} images!"); }).Start(); new Harmony("CecekMan.ObrazkyJakCyp").PatchAll(); IsInitialized = true; } catch (Exception ex) { logger.LogError((object)ex); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ChangePainting(GrabbableObject obj) { int instanceID = ((Object)obj).GetInstanceID(); if (!Globals.Paintings.TryGetValue(instanceID, out var value)) { value = ((Component)obj).gameObject.AddComponent(); Globals.Paintings[instanceID] = value; } value.SetupPainting(); } } public class PluginConfig { public string Directory { get; private set; } = "Paintings"; public int MaxImages { get; private set; } = 500; public PluginConfig(ConfigFile cfg) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown ConfigEntry val = cfg.Bind(new ConfigDefinition("General", "Directory"), Directory, (ConfigDescription)null); ConfigEntry val2 = cfg.Bind(new ConfigDefinition("General", "Max Images"), MaxImages, (ConfigDescription)null); if (Path.IsPathRooted(val.Value)) { Directory = val.Value; } else { Directory = Path.GetFullPath(Path.Combine(Paths.BepInExRootPath, val.Value)); } MaxImages = val2.Value; } } } namespace ObrazkyJakCyp.Patches { [HarmonyPatch] internal static class GameNetworkManagerPatches { [HarmonyPatch(typeof(GameNetworkManager), "ResetGameValuesToDefault")] [HarmonyPostfix] private static void OnResetGameValues() { if (Plugin.IsInitialized) { Globals.Paintings.Clear(); } } } [HarmonyPatch] internal static class GrabbableObjectPatches { [HarmonyPatch(typeof(GrabbableObject), "Start")] [HarmonyPrefix] private static void OnStart(GrabbableObject __instance) { if (Plugin.IsInitialized && __instance.IsPainting()) { Plugin.ChangePainting(__instance); } } } [HarmonyPatch] internal static class RoundManagerPatches { [HarmonyPatch(typeof(RoundManager), "SyncScrapValuesClientRpc")] [HarmonyPostfix] private static void OnSyncScrapValues(NetworkObjectReference[] spawnedScrap) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.IsInitialized) { return; } NetworkObject val2 = default(NetworkObject); for (int i = 0; i < spawnedScrap.Length; i++) { NetworkObjectReference val = spawnedScrap[i]; if (((NetworkObjectReference)(ref val)).TryGet(ref val2, (NetworkManager)null)) { GrabbableObject component = ((Component)val2).GetComponent(); if (component.IsPainting()) { Plugin.ChangePainting(component); } } } } [HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")] [HarmonyPrefix] private static void OnGenerateNewLevel(int randomSeed) { Globals.GRandom = new Random(randomSeed + 300); } } } namespace ObrazkyJakCyp.Components { internal class CustomPainting : MonoBehaviour { private GrabbableObject Obj; private MeshRenderer Renderer; private bool IsAnimation; private float Timer; private int Frame; public Material Mat; public PaintingContent Content; private void Awake() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown Content = ContentLoader.GetNextContent(); if (Content == null) { Plugin.logger.LogError((object)"Failed to get an image for painting!"); return; } IsAnimation = Content.Delays != null; Obj = ((Component)this).GetComponent(); Mat = new Material(Obj.itemProperties.materialVariants[0]); Mat.shader = Globals.PaintingShader; Mat.SetTexture("_Images", (Texture)(object)Content.Frames); Mat.SetInt("_Index", 0); Mat.SetInt("_Rotate", Content.IsWide ? 1 : 0); Mat.SetInt("_IsTexture", Content.IsRawTexture ? 1 : 0); } private void Update() { if (IsAnimation && Object.op_Implicit((Object)(object)Renderer)) { float num = (float)Content.Delays[Frame] / 1000f; Timer += Time.deltaTime; if (Timer >= num) { Timer -= num; Frame = (Frame + 1) % Content.FramesCnt; ((Renderer)Renderer).material.SetInt("_Index", Frame); } } } public void SetupPainting() { Renderer = ((Component)this).GetComponent(); if (Object.op_Implicit((Object)(object)Renderer)) { ((Renderer)Renderer).material = Mat; } } } }