RUMBLE does not support other mod managers. If you want to use a manager, you must use the RUMBLE Mod Manager, a manager specifically designed for this game.
Decompiled source of RumblePhotoAlbum v1.2.0
Mods/RumblePhotoAlbum.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
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.Text; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppRUMBLE.Interactions.InteractionBase; using Il2CppRUMBLE.Players; using Il2CppRUMBLE.Recording.LCK; using Il2CppRUMBLE.Serialization; using Il2CppRUMBLE.Tutorial.MoveLearning; using Il2CppRUMBLE.Utilities; using Il2CppTMPro; using MelonLoader; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using RumbleModUI; using RumbleModdingAPI; using RumblePhotoAlbum; using ThreeDISevenZeroR.UnityGifDecoder; using ThreeDISevenZeroR.UnityGifDecoder.Decode; using ThreeDISevenZeroR.UnityGifDecoder.Model; using ThreeDISevenZeroR.UnityGifDecoder.Utils; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(MainClass), "RumblePhotoAlbum", "1.2.0", "Kalamart", null)] [assembly: VerifyLoaderVersion(0, 6, 5, true)] [assembly: MelonGame("Buckethead Entertainment", "RUMBLE")] [assembly: MelonColor(255, 255, 31, 90)] [assembly: MelonAuthorColor(255, 255, 31, 90)] [assembly: AssemblyDescription("Decorate your environment with framed pictures")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("621d30a5-8fa1-4d87-9826-92c0149b033e")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("RumblePhotoAlbum")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+bd119323e49bf75e99045a346c728f6e9f3cb319")] [assembly: AssemblyProduct("RumblePhotoAlbum")] [assembly: AssemblyTitle("RumblePhotoAlbum")] [assembly: AssemblyVersion("1.0.0.0")] namespace ThreeDISevenZeroR.UnityGifDecoder { public class GifBitBlockReader { private Stream stream; private int currentByte; private int currentBitPosition; private int currentBufferPosition; private int currentBufferSize; private bool endReached; private readonly byte[] buffer; public GifBitBlockReader() { buffer = new byte[256]; } public GifBitBlockReader(Stream stream) : this() { SetStream(stream); } public void SetStream(Stream stream) { this.stream = stream; } public void StartNewReading() { currentByte = 0; currentBitPosition = 8; ReadNextBlock(); } public void FinishReading() { while (!endReached) { ReadNextBlock(); } } public int ReadBits(int count) { int num = 0; int num2 = count; int num3 = 0; int num4 = 8 - currentBitPosition; while (num2 > 0) { if (currentBitPosition >= 8) { currentBitPosition = 0; num4 = 8; if (endReached) { currentByte = 0; } else { currentByte = buffer[currentBufferPosition++]; if (currentBufferPosition == currentBufferSize) { ReadNextBlock(); } } } byte b = (byte)((1 << num2) - 1 << currentBitPosition); int num5 = ((num4 < num2) ? num4 : num2); num += (b & currentByte) >> currentBitPosition << num3; currentBitPosition += num5; num2 -= num5; num3 += num5; } return num; } private void ReadNextBlock() { currentBufferSize = stream.ReadByte8(); currentBufferPosition = 0; endReached = currentBufferSize == 0; if (!endReached) { stream.Read(buffer, 0, currentBufferSize); } } } public class GifCanvas { private Color32[] canvasColors; private Color32[] revertDisposalBuffer; private int canvasWidth; private int canvasHeight; private bool canvasIsEmpty; private Color32[] framePalette; private GifDisposalMethod frameDisposalMethod; private int frameCanvasPosition; private int frameCanvasRowEndPosition; private int frameTransparentColorIndex; private int frameRowCurrent; private int frameX; private int frameY; private int frameWidth; private int frameHeight; private int[] frameRowStart; private int[] frameRowEnd; public Color32[] Colors => canvasColors; public bool FlipVertically { get; set; } = true; public Color32 BackgroundColor { get; set; } public GifCanvas() { canvasIsEmpty = true; } public GifCanvas(int width, int height) : this() { SetSize(width, height); } public void SetSize(int width, int height) { if (width != canvasWidth || height != canvasHeight) { int num = width * height; canvasColors = (Color32[])(object)new Color32[num]; frameRowStart = new int[height]; frameRowEnd = new int[height]; revertDisposalBuffer = null; canvasWidth = width; canvasHeight = height; } Reset(); } public void Reset() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) frameDisposalMethod = GifDisposalMethod.Keep; frameX = 0; frameY = 0; frameWidth = canvasWidth; frameHeight = canvasHeight; if (!canvasIsEmpty) { FillWithColor(0, 0, canvasWidth, canvasHeight, new Color32(BackgroundColor.r, BackgroundColor.g, BackgroundColor.b, (byte)0)); canvasIsEmpty = true; } } public void BeginNewFrame(int x, int y, int width, int height, Color32[] palette, int transparentColorIndex, bool isInterlaced, GifDisposalMethod disposalMethod) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) switch (frameDisposalMethod) { case GifDisposalMethod.ClearToBackgroundColor: FillWithColor(frameX, frameY, frameWidth, frameHeight, new Color32(BackgroundColor.r, BackgroundColor.g, BackgroundColor.b, (byte)0)); break; case GifDisposalMethod.Revert: if (disposalMethod != 0) { Array.Copy(revertDisposalBuffer, 0, canvasColors, 0, revertDisposalBuffer.Length); } break; } if (disposalMethod == GifDisposalMethod.Revert) { if (revertDisposalBuffer == null) { revertDisposalBuffer = (Color32[])(object)new Color32[canvasColors.Length]; } Array.Copy(canvasColors, 0, revertDisposalBuffer, 0, revertDisposalBuffer.Length); } framePalette = palette; frameDisposalMethod = disposalMethod; canvasIsEmpty = false; frameWidth = width; frameHeight = height; frameX = x; frameY = y; frameCanvasPosition = 0; frameRowCurrent = -1; frameCanvasRowEndPosition = -1; frameTransparentColorIndex = transparentColorIndex; RouteFrameDrawing(x, y, width, height, isInterlaced); } public void OutputPixel(int color) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (frameCanvasPosition >= frameCanvasRowEndPosition) { frameRowCurrent++; frameCanvasPosition = frameRowStart[frameRowCurrent]; frameCanvasRowEndPosition = frameRowEnd[frameRowCurrent]; } if (color != frameTransparentColorIndex) { canvasColors[frameCanvasPosition] = framePalette[color]; } frameCanvasPosition++; } public void FillWithColor(int x, int y, int width, int height, Color32 color) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) if (width == canvasWidth && height == canvasHeight) { for (int num = canvasColors.Length - 1; num >= 0; num--) { canvasColors[num] = color; } return; } int num2; int num3; if (FlipVertically) { num2 = (canvasHeight - y) * canvasWidth + x; num3 = num2 - canvasWidth * height; } else { num3 = y * canvasWidth + x; num2 = num3 + height * canvasWidth; } for (int i = num3; i < num2; i += canvasWidth) { int num4 = i + width; for (int j = i; j < num4; j++) { canvasColors[j] = color; } } } private void RouteFrameDrawing(int x, int y, int width, int height, bool deinterlace) { int currentRow = 0; if (deinterlace) { for (int i = 0; i < height; i += 8) { ScheduleRowIndex(i); } for (int j = 4; j < height; j += 8) { ScheduleRowIndex(j); } for (int k = 2; k < height; k += 4) { ScheduleRowIndex(k); } for (int l = 1; l < height; l += 2) { ScheduleRowIndex(l); } } else { for (int m = 0; m < height; m++) { ScheduleRowIndex(m); } } void ScheduleRowIndex(int row) { int num = (FlipVertically ? ((canvasHeight - 1 - (y + row)) * canvasWidth + x) : ((y + row) * canvasWidth + x)); frameRowStart[currentRow] = num; frameRowEnd[currentRow] = num + width; currentRow++; } } } public class GifStream : IDisposable { public enum Token { Header, Palette, GraphicsControl, ImageDescriptor, Image, Comment, PlainText, NetscapeExtension, ApplicationExtension, EndOfFile } private Stream currentStream; private long headerStartPosition; private long firstFrameStartPosition; private GifHeader header; private GifGraphicControl graphicControl; private GifImageDescriptor imageDescriptor; private GifCanvas canvas; private GifLzwDictionary lzwDictionary; private GifBitBlockReader blockReader; private Color32[] globalColorTable; private Color32[] localColorTable; private readonly byte[] headerBuffer; private readonly byte[] colorTableBuffer; private readonly byte[] extensionApplicationBuffer; private bool nextPaletteIsGlobal; private const int ExtensionBlock = 33; private const int ImageDescriptorBlock = 44; private const int EndOfFile = 59; private const int PlainTextLabel = 1; private const int GraphicControlLabel = 249; private const int commentLabel = 254; private const int applicationExtensionLabel = 255; public bool FlipVertically { get { return canvas.FlipVertically; } set { canvas.FlipVertically = value; } } public bool DrawPlainTextBackground { get; set; } public GifHeader Header => header; public bool HasMoreData => CurrentToken != Token.EndOfFile; public Token CurrentToken { get; private set; } public Stream BaseStream { get { return currentStream; } set { SetStream(value); } } public GifStream() { lzwDictionary = new GifLzwDictionary(); canvas = new GifCanvas(); blockReader = new GifBitBlockReader(); globalColorTable = (Color32[])(object)new Color32[256]; localColorTable = (Color32[])(object)new Color32[256]; headerBuffer = new byte[6]; extensionApplicationBuffer = new byte[11]; colorTableBuffer = new byte[768]; } public GifStream(Stream stream) : this() { SetStream(stream); } public GifStream(byte[] gifBytes) : this(new MemoryStream(gifBytes)) { } public GifStream(string path) : this(File.OpenRead(path)) { } public void SetStream(Stream stream, bool disposePrevious = false) { if (disposePrevious) { currentStream?.Dispose(); } header = default(GifHeader); imageDescriptor = default(GifImageDescriptor); graphicControl = default(GifGraphicControl); currentStream = stream; CurrentToken = Token.Header; blockReader.SetStream(stream); } public void Dispose() { currentStream?.Dispose(); } public void SkipToken() { switch (CurrentToken) { case Token.Header: ReadHeader(); break; case Token.Palette: ReadPalette(); break; case Token.GraphicsControl: ReadGraphicsControl(); break; case Token.ImageDescriptor: ReadImageDescriptor(); break; case Token.Image: ReadImage(); break; case Token.Comment: SkipComment(); break; case Token.PlainText: SkipPlainText(); break; case Token.NetscapeExtension: SkipNetscapeExtension(); break; case Token.ApplicationExtension: SkipApplicationExtension(); break; default: throw new InvalidOperationException($"Cannot skip token {CurrentToken}"); } } public void Reset(bool skipHeader = true, bool resetCanvas = true) { long num = ((skipHeader && firstFrameStartPosition != -1) ? firstFrameStartPosition : headerStartPosition); if (currentStream.Position != num) { currentStream.Position = num; } SetCurrentToken(Token.Header); if (resetCanvas) { canvas.Reset(); } } public GifHeader ReadHeader() { AssertToken(Token.Header); headerStartPosition = currentStream.Position; firstFrameStartPosition = -1L; currentStream.Read(headerBuffer, 0, headerBuffer.Length); if (BitUtils.CheckString(headerBuffer, "GIF87a")) { header.version = GifVersion.Gif87a; } else { if (!BitUtils.CheckString(headerBuffer, "GIF89a")) { throw new ArgumentException("Invalid or corrupted Gif file"); } header.version = GifVersion.Gif89a; } header.width = currentStream.ReadInt16LittleEndian(); header.height = currentStream.ReadInt16LittleEndian(); byte b = currentStream.ReadByte8(); header.globalColorTableSize = BitUtils.GetColorTableSize(b.GetBitsFromByte(0, 3)); header.sortColors = b.GetBitFromByte(3); header.colorResolution = b.GetBitsFromByte(4, 3); header.hasGlobalColorTable = b.GetBitFromByte(7); header.transparentColorIndex = currentStream.ReadByte8(); header.pixelAspectRatio = currentStream.ReadByte8(); canvas.SetSize(header.width, header.height); if (header.hasGlobalColorTable) { SetCurrentToken(Token.Palette); nextPaletteIsGlobal = true; } else { DetermineNextToken(); } return header; } public GifPalette ReadPalette() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) AssertToken(Token.Palette); int num = (nextPaletteIsGlobal ? header.globalColorTableSize : imageDescriptor.localColorTableSize); Color32[] array = (nextPaletteIsGlobal ? globalColorTable : localColorTable); currentStream.Read(colorTableBuffer, 0, num * 3); int num2 = 0; for (int i = 0; i < num; i++) { array[i] = new Color32(colorTableBuffer[num2++], colorTableBuffer[num2++], colorTableBuffer[num2++], byte.MaxValue); } if (nextPaletteIsGlobal) { firstFrameStartPosition = currentStream.Position; DetermineNextToken(); } else { SetCurrentToken(Token.Image); } GifPalette result = default(GifPalette); result.palette = array; result.size = num; result.isGlobal = nextPaletteIsGlobal; return result; } public GifGraphicControl ReadGraphicsControl() { AssertToken(Token.GraphicsControl); currentStream.AssertByte(4); byte b = currentStream.ReadByte8(); int bitsFromByte = b.GetBitsFromByte(2, 3); graphicControl.hasTransparency = b.GetBitFromByte(0); graphicControl.userInput = b.GetBitFromByte(1); graphicControl.delayTime = currentStream.ReadInt16LittleEndian(); graphicControl.transparentColorIndex = currentStream.ReadByte8(); if (!graphicControl.hasTransparency) { graphicControl.transparentColorIndex = -1; } switch (bitsFromByte) { case 0: case 1: graphicControl.disposalMethod = GifDisposalMethod.Keep; break; case 2: graphicControl.disposalMethod = GifDisposalMethod.ClearToBackgroundColor; break; case 3: graphicControl.disposalMethod = GifDisposalMethod.Revert; break; default: throw new ArgumentException($"Invalid disposal method type: {bitsFromByte}"); } currentStream.AssertByte(0); DetermineNextToken(); return graphicControl; } public GifImageDescriptor ReadImageDescriptor() { AssertToken(Token.ImageDescriptor); imageDescriptor.left = currentStream.ReadInt16LittleEndian(); imageDescriptor.top = currentStream.ReadInt16LittleEndian(); imageDescriptor.width = currentStream.ReadInt16LittleEndian(); imageDescriptor.height = currentStream.ReadInt16LittleEndian(); byte b = currentStream.ReadByte8(); imageDescriptor.localColorTableSize = BitUtils.GetColorTableSize(b.GetBitsFromByte(0, 3)); imageDescriptor.isInterlaced = b.GetBitFromByte(6); imageDescriptor.hasLocalColorTable = b.GetBitFromByte(7); if (imageDescriptor.hasLocalColorTable) { nextPaletteIsGlobal = false; SetCurrentToken(Token.Palette); } else { SetCurrentToken(Token.Image); } return imageDescriptor; } public GifImage ReadImage() { AssertToken(Token.Image); Color32[] colorTable = (imageDescriptor.hasLocalColorTable ? localColorTable : globalColorTable); byte b = currentStream.ReadByte8(); if (b == 0 || b > 8) { throw new ArgumentException("Invalid lzw min code size"); } DecodeLzwImageToCanvas(b, imageDescriptor.left, imageDescriptor.top, imageDescriptor.width, imageDescriptor.height, colorTable, graphicControl.transparentColorIndex, imageDescriptor.isInterlaced, graphicControl.disposalMethod); DetermineNextToken(); return new GifImage { colors = canvas.Colors, userInput = graphicControl.userInput, delay = graphicControl.delayTime }; } public string ReadComment() { AssertToken(Token.Comment); string @string = Encoding.ASCII.GetString(BitUtils.ReadGifBlocks(currentStream)); DetermineNextToken(); return @string; } public void SkipComment() { SkipBlock(Token.Comment); } public GifPlainText ReadPlainText() { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) AssertToken(Token.PlainText); currentStream.AssertByte(12); GifPlainText gifPlainText = default(GifPlainText); gifPlainText.left = currentStream.ReadInt16LittleEndian(); gifPlainText.top = currentStream.ReadInt16LittleEndian(); gifPlainText.width = currentStream.ReadInt16LittleEndian(); gifPlainText.height = currentStream.ReadInt16LittleEndian(); gifPlainText.charWidth = currentStream.ReadByte8(); gifPlainText.charHeight = currentStream.ReadByte8(); gifPlainText.foregroundColor = globalColorTable[currentStream.ReadByte8()]; gifPlainText.backgroundColor = globalColorTable[currentStream.ReadByte8()]; gifPlainText.text = Encoding.ASCII.GetString(BitUtils.ReadGifBlocks(currentStream)); gifPlainText.colors = canvas.Colors; if (DrawPlainTextBackground) { FillPlainTextBackground(gifPlainText); } DetermineNextToken(); return gifPlainText; } public void SkipPlainText() { if (DrawPlainTextBackground) { ReadPlainText(); } else { SkipBlock(Token.PlainText); } } public GifNetscapeExtension ReadNetscapeExtension() { AssertToken(Token.NetscapeExtension); bool hasBufferSize = false; bool hasLoopCount = false; int loopCount = 0; int bufferSize = 0; while (true) { byte b = currentStream.ReadByte8(); if (b == 0) { break; } switch (currentStream.ReadByte8()) { case 1: hasLoopCount = true; loopCount = currentStream.ReadInt16LittleEndian(); break; case 2: hasBufferSize = true; bufferSize = currentStream.ReadInt32LittleEndian(); break; default: currentStream.Seek(b - 1, SeekOrigin.Current); break; } } DetermineNextToken(); GifNetscapeExtension result = default(GifNetscapeExtension); result.hasLoopCount = hasLoopCount; result.hasBufferSize = hasBufferSize; result.loopCount = loopCount; result.bufferSize = bufferSize; return result; } public void SkipNetscapeExtension() { SkipBlock(Token.NetscapeExtension); } public GifApplicationExtension ReadApplicationExtension() { AssertToken(Token.ApplicationExtension); List<byte[]> list = new List<byte[]>(); string @string = Encoding.ASCII.GetString(extensionApplicationBuffer, 0, 8); string string2 = Encoding.ASCII.GetString(extensionApplicationBuffer, 8, 3); while (true) { byte b = currentStream.ReadByte8(); if (b == 0) { break; } byte[] array = new byte[b]; currentStream.Read(array, 0, b); list.Add(array); } DetermineNextToken(); return new GifApplicationExtension { applicationIdentifier = @string, applicationAuthCode = string2, applicationData = list.ToArray() }; } public void SkipApplicationExtension() { SkipBlock(Token.ApplicationExtension); } private void DecodeLzwImageToCanvas(int lzwMinCodeSize, int x, int y, int width, int height, Color32[] colorTable, int transparentColorIndex, bool isInterlaced, GifDisposalMethod disposalMethod) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (header.hasGlobalColorTable) { canvas.BackgroundColor = globalColorTable[header.transparentColorIndex]; } canvas.BeginNewFrame(x, y, width, height, colorTable, transparentColorIndex, isInterlaced, disposalMethod); lzwDictionary.InitWithWordSize(lzwMinCodeSize); blockReader.StartNewReading(); lzwDictionary.DecodeStream(blockReader, canvas); blockReader.FinishReading(); } private Token DetermineNextToken() { while (true) { byte b = currentStream.ReadByte8(); switch (b) { case 33: switch (currentStream.ReadByte8()) { case 254: return SetCurrentToken(Token.Comment); case 1: return SetCurrentToken(Token.PlainText); case 249: return SetCurrentToken(Token.GraphicsControl); case byte.MaxValue: { currentStream.AssertByte(11); currentStream.Read(extensionApplicationBuffer, 0, 11); Token currentToken = (BitUtils.CheckString(extensionApplicationBuffer, "NETSCAPE2.0") ? Token.NetscapeExtension : Token.ApplicationExtension); return SetCurrentToken(currentToken); } } break; case 44: return SetCurrentToken(Token.ImageDescriptor); case 59: return SetCurrentToken(Token.EndOfFile); default: throw new ArgumentException($"Unknown block type {b}"); } BitUtils.SkipGifBlocks(currentStream); } } private Token SetCurrentToken(Token token) { CurrentToken = token; return token; } private void FillPlainTextBackground(GifPlainText text) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) canvas.BeginNewFrame(text.left, text.top, text.width, text.height, globalColorTable, graphicControl.transparentColorIndex, imageDescriptor.isInterlaced, graphicControl.disposalMethod); canvas.FillWithColor(text.left, text.top, text.width, text.height, text.backgroundColor); } private void AssertToken(Token token) { if (CurrentToken != token) { throw new InvalidOperationException($"Cannot invoke this method while current token is \"{CurrentToken}\", method should be called when token is {token}"); } } private void SkipBlock(Token token) { AssertToken(token); BitUtils.SkipGifBlocks(currentStream); DetermineNextToken(); } } } namespace ThreeDISevenZeroR.UnityGifDecoder.Utils { public static class BitUtils { public static bool CheckString(byte[] array, string s) { for (int i = 0; i < array.Length; i++) { if (array[i] != s[i]) { return false; } } return true; } public static int ReadInt16LittleEndian(this Stream reader) { byte b = reader.ReadByte8(); byte b2 = reader.ReadByte8(); return (b2 << 8) + b; } public static int ReadInt32LittleEndian(this Stream reader) { byte b = reader.ReadByte8(); byte b2 = reader.ReadByte8(); byte b3 = reader.ReadByte8(); byte b4 = reader.ReadByte8(); return (b4 << 24) + (b3 << 16) + (b2 << 8) + b; } public static byte ReadByte8(this Stream reader) { int num = reader.ReadByte(); if (num == -1) { throw new EndOfStreamException(); } return (byte)num; } public static void AssertByte(this Stream reader, int expectedValue) { byte b = reader.ReadByte8(); if (b != expectedValue) { throw new ArgumentException($"Invalid byte, expected {expectedValue}, got {b}"); } } public static int GetColorTableSize(int data) { return 1 << data + 1; } public static int GetBitsFromByte(this byte b, int offset, int count) { int num = 0; for (int i = 0; i < count; i++) { num += (b.GetBitFromByte(offset + i) ? 1 : 0) << i; } return num; } public static bool GetBitFromByte(this byte b, int offset) { return (b & (1 << offset)) != 0; } public static byte[] ReadGifBlocks(Stream reader) { List<byte> list = new List<byte>(); while (true) { byte b = reader.ReadByte8(); if (b == 0) { break; } byte[] array = new byte[b]; reader.Read(array, 0, array.Length); list.AddRange(array); } return list.ToArray(); } public static void SkipGifBlocks(Stream reader) { while (true) { byte b = reader.ReadByte8(); if (b == 0) { break; } reader.Seek(b, SeekOrigin.Current); } } } } namespace ThreeDISevenZeroR.UnityGifDecoder.Model { public class GifApplicationExtension { public string applicationIdentifier; public string applicationAuthCode; public byte[][] applicationData; } public enum GifDisposalMethod { Keep, ClearToBackgroundColor, Revert } public struct GifGraphicControl { public bool userInput; public GifDisposalMethod disposalMethod; public int delayTime; public bool hasTransparency; public int transparentColorIndex; } public struct GifHeader { public GifVersion version; public int width; public int height; public bool hasGlobalColorTable; public int globalColorTableSize; public int transparentColorIndex; public bool sortColors; public int colorResolution; public int pixelAspectRatio; } public class GifImage { public bool userInput; public Color32[] colors; public int delay; public int DelayMs => delay * 10; public float SafeDelayMs => (delay > 1) ? DelayMs : 100; public float DelaySeconds => (float)delay / 100f; public float SafeDelaySeconds => SafeDelayMs / 1000f; } public struct GifImageDescriptor { public int left; public int top; public int width; public int height; public bool isInterlaced; public bool hasLocalColorTable; public int localColorTableSize; } public struct GifNetscapeExtension { public bool hasLoopCount; public bool hasBufferSize; public int loopCount; public int bufferSize; } public struct GifPalette { public Color32[] palette; public int size; public bool isGlobal; } public struct GifPlainText { public int left; public int top; public int width; public int height; public int charWidth; public int charHeight; public Color32 backgroundColor; public Color32 foregroundColor; public string text; public Color32[] colors; } public enum GifVersion { Gif89a, Gif87a } } namespace ThreeDISevenZeroR.UnityGifDecoder.Decode { public class GifLzwDictionary { private readonly int[] dictionaryEntryOffsets; private readonly int[] dictionaryEntrySizes; private byte[] dictionaryHeap; private int dictionarySize; private int dictionaryHeapPosition; private int initialDictionarySize; private int initialLzwCodeSize; private int initialDictionaryHeapPosition; private int nextLzwCodeGrowth; private int currentMinLzwCodeSize; private int codeSize; private int clearCodeId; private int stopCodeId; private int lastCodeId; private bool isFull; public GifLzwDictionary() { dictionaryEntryOffsets = new int[4096]; dictionaryEntrySizes = new int[4096]; dictionaryHeap = new byte[32768]; } public void InitWithWordSize(int minLzwCodeSize) { if (currentMinLzwCodeSize != minLzwCodeSize) { currentMinLzwCodeSize = minLzwCodeSize; dictionaryHeapPosition = 0; dictionarySize = 0; int num = 1 << minLzwCodeSize; for (int i = 0; i < num; i++) { dictionaryEntryOffsets[i] = dictionaryHeapPosition; dictionaryEntrySizes[i] = 1; dictionaryHeap[dictionaryHeapPosition++] = (byte)i; } initialDictionarySize = num + 2; initialLzwCodeSize = minLzwCodeSize + 1; initialDictionaryHeapPosition = dictionaryHeapPosition; clearCodeId = num; stopCodeId = num + 1; } Clear(); } public void Clear() { codeSize = initialLzwCodeSize; dictionarySize = initialDictionarySize; dictionaryHeapPosition = initialDictionaryHeapPosition; nextLzwCodeGrowth = 1 << codeSize; isFull = false; lastCodeId = -1; } public void DecodeStream(GifBitBlockReader reader, GifCanvas c) { while (true) { int num = reader.ReadBits(codeSize); if (num == clearCodeId) { Clear(); continue; } if (num == stopCodeId) { break; } if (num < dictionarySize) { if (lastCodeId >= 0) { CreateNewCode(lastCodeId, num); } lastCodeId = num; } else { lastCodeId = CreateNewCode(lastCodeId, lastCodeId); } int num2 = dictionaryEntryOffsets[lastCodeId]; int num3 = dictionaryEntrySizes[lastCodeId]; int num4 = num2 + num3; for (int i = num2; i < num4; i++) { c.OutputPixel(dictionaryHeap[i]); } } } public int CreateNewCode(int baseEntry, int deriveEntry) { if (isFull) { return -1; } int num = dictionaryEntryOffsets[baseEntry]; int num2 = dictionaryEntrySizes[baseEntry]; int num3 = dictionaryHeapPosition; int num4 = num2 + 1; int num5 = num3 + num4; if (dictionaryHeap.Length < num5) { Array.Resize(ref dictionaryHeap, Math.Max(dictionaryHeap.Length * 2, num5)); } if (num2 < 12) { int num6 = num + num2; for (int i = num; i < num6; i++) { dictionaryHeap[dictionaryHeapPosition++] = dictionaryHeap[i]; } } else { Buffer.BlockCopy(dictionaryHeap, num, dictionaryHeap, dictionaryHeapPosition, num2); dictionaryHeapPosition += num2; } dictionaryHeap[dictionaryHeapPosition++] = ((deriveEntry < initialDictionarySize) ? ((byte)deriveEntry) : dictionaryHeap[dictionaryEntryOffsets[deriveEntry]]); int num7 = dictionarySize++; dictionaryEntryOffsets[num7] = num3; dictionaryEntrySizes[num7] = num4; if (dictionarySize >= nextLzwCodeGrowth) { codeSize++; nextLzwCodeGrowth = ((codeSize == 12) ? int.MaxValue : (1 << codeSize)); } if (dictionarySize >= 4096) { isFull = true; } return num7; } } } namespace RumblePhotoAlbum { public class PictureData : MainClass.PictureDataInternal { public void delete() { PhotoAPI.DeletePicture(this); } } public class PhotoAPI : MainClass { public static PictureData CreatePicture(string path, Vector3 position, Vector3 rotation, float width = 0f, float height = 0f, float? padding = null, float? thickness = null, Color? color = null, bool? alpha = null) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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) //IL_0016: 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) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) PictureData pictureData = new PictureData { path = path, position = position, rotation = rotation, width = width, height = width, padding = (padding ?? MainClass.defaultPadding), thickness = (thickness ?? MainClass.defaultThickness), color = (Color)(((??)color) ?? MainClass.defaultColor), alpha = (alpha ?? MainClass.enableAlpha) }; MainClass.CreatePicture(ref pictureData, MainClass.photoAlbum.transform); return pictureData; } public static void DeletePicture(PictureData pictureData) { MainClass.deletePicture(pictureData, keepFile: true); } } public class MainClass : MelonMod { private class FrameData { public Texture2D texture; public WaitForSeconds delay; } private class GifData { public Renderer renderer; public GifStream gifStream; public FrameData firstFrame; public string path; } [HarmonyPatch(typeof(PlayerController), "Initialize", new Type[] { typeof(Player) })] private static class PlayerSpawnPatch { private static void Postfix(ref PlayerController __instance, ref Player player) { if (Players.GetLocalPlayer() == player) { InitGrabbing(); initializeRockCam(); } } } [HarmonyPatch(typeof(LCKTabletUtility), "TakePhoto", new Type[] { })] private static class PhotoTakenPatch { private static bool Prefix(ref LCKTabletUtility __instance) { PhotoPrintingIndex = 0; return true; } } public class PictureDataInternal { public string path; public Vector3 position; public Vector3 rotation; public float width = 0f; public float height = 0f; public float padding = defaultPadding; public float thickness = defaultThickness; public Color color = defaultColor; public bool alpha = false; public bool visible = true; public GameObject obj = null; public JToken jsonConfig = null; } [CompilerGenerated] private sealed class <LoadAlbum>d__11 : IEnumerator<WaitForSeconds>, IEnumerator, IDisposable { private int <>1__state; private WaitForSeconds <>2__current; public string sceneName; private JArray <album>5__1; private JToken <sceneObj>5__2; private WaitForSeconds <wait>5__3; private JArray <cleanedAlbum>5__4; private string <json>5__5; private Exception <ex>5__6; private IEnumerator<JToken> <>s__7; private JToken <entry>5__8; private PictureData <pictureData>5__9; private Exception <ex>5__10; private Exception <ex>5__11; private Exception <ex>5__12; WaitForSeconds IEnumerator<WaitForSeconds>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadAlbum>d__11(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <album>5__1 = null; <sceneObj>5__2 = null; <wait>5__3 = null; <cleanedAlbum>5__4 = null; <json>5__5 = null; <ex>5__6 = null; <>s__7 = null; <entry>5__8 = null; <pictureData>5__9 = null; <ex>5__10 = null; <ex>5__11 = null; <ex>5__12 = null; <>1__state = -2; } private bool MoveNext() { //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Expected O, but got Unknown //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Invalid comparison between Unknown and I4 //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; Log("Reading from disk"); PicturesList = new List<PictureData>(); <album>5__1 = null; <sceneObj>5__2 = null; try { if (!File.Exists(fullPath)) { LogWarn("Creating new configuration file at: " + fullPath + "."); root = new JObject(); } else { <json>5__5 = File.ReadAllText(fullPath); root = JObject.Parse(<json>5__5); <json>5__5 = null; } if (!root.TryGetValue(sceneName, ref <sceneObj>5__2) || (int)<sceneObj>5__2.Type != 1) { LogWarn("No valid entry found for scene \"" + sceneName + "\". Creating an empty object."); <sceneObj>5__2 = (JToken)new JObject(); root[sceneName] = <sceneObj>5__2; } ref JArray reference = ref <album>5__1; JToken obj = <sceneObj>5__2[(object)"album"]; reference = (JArray)(((object)((obj is JArray) ? obj : null)) ?? ((object)new JArray())); photoAlbum = new GameObject(); ((Object)photoAlbum).name = "PhotoAlbum"; } catch (Exception ex) { <ex>5__6 = ex; LogError("Failed to load or parse config.json: " + <ex>5__6.Message); } if (<album>5__1 == null || <sceneObj>5__2 == null) { return false; } <wait>5__3 = new WaitForSeconds(0.02f); gifs = new List<GifData>(); gifsPlaying = false; gifsLoading = true; <cleanedAlbum>5__4 = new JArray(); <>s__7 = <album>5__1.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; <pictureData>5__9 = null; <entry>5__8 = null; break; } while (<>s__7.MoveNext()) { <entry>5__8 = <>s__7.Current; <pictureData>5__9 = null; try { <pictureData>5__9 = ParsePictureData(<entry>5__8); Log("Creating picture " + <pictureData>5__9.path); if (<pictureData>5__9 == null) { continue; } } catch (Exception ex) { <ex>5__10 = ex; LogError("Failed to parse entry: " + <ex>5__10.Message); continue; } try { CreatePicture(ref <pictureData>5__9, photoAlbum.transform); <cleanedAlbum>5__4.Add(<entry>5__8); <pictureData>5__9.jsonConfig = <cleanedAlbum>5__4[((JContainer)<cleanedAlbum>5__4).Count - 1]; } catch (Exception ex) { <ex>5__11 = ex; LogError("Failed to parse entry: " + <ex>5__11.Message); if (<ex>5__11.Message != "file doesn't exist") { <cleanedAlbum>5__4.Add(<entry>5__8); <pictureData>5__9.jsonConfig = <cleanedAlbum>5__4[((JContainer)<cleanedAlbum>5__4).Count - 1]; } continue; } <>2__current = <wait>5__3; <>1__state = 1; return true; } <>m__Finally1(); <>s__7 = null; gifsPlaying = true; MelonCoroutines.Start((IEnumerator)PlayAllGifs()); try { reloadStash(); <sceneObj>5__2[(object)"album"] = (JToken)(object)<cleanedAlbum>5__4; File.WriteAllText(fullPath, ((JToken)root).ToString((Formatting)1)); stashJson = (JArray)root[currentScene][(object)"stash"]; albumJson = (JArray)root[currentScene][(object)"album"]; } catch (Exception ex) { <ex>5__12 = ex; LogError("Failed to update configuration file: " + <ex>5__12.Message); } return false; } 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; if (<>s__7 != null) { <>s__7.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <PlayAllGifs>d__22 : IEnumerator<WaitForSeconds>, IEnumerator, IDisposable { private int <>1__state; private WaitForSeconds <>2__current; private WaitForSeconds <wait>5__1; private int <gifIndex>5__2; private GifData <gifData>5__3; private List<FrameData> <frames>5__4; private int <index>5__5; private FrameData <frame>5__6; private Exception <ex>5__7; WaitForSeconds IEnumerator<WaitForSeconds>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PlayAllGifs>d__22(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__1 = null; <gifData>5__3 = null; <frames>5__4 = null; <frame>5__6 = null; <ex>5__7 = null; <>1__state = -2; } private bool MoveNext() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (gifs == null) { return false; } Log("Starting coroutine to load all gifs"); <wait>5__1 = new WaitForSeconds(0.01f); <gifIndex>5__2 = 0; goto IL_01ef; case 1: <>1__state = -1; <frame>5__6 = ReadGifFrame(<gifData>5__3.gifStream); if (<frame>5__6 != null) { <frames>5__4.Add(<frame>5__6); } <frame>5__6 = null; goto IL_0105; case 2: { <>1__state = -1; <gifData>5__3 = null; <frames>5__4 = null; goto IL_01ef; } IL_01ef: if (!gifsPlaying || gifs == null || <gifIndex>5__2 >= gifs.Count) { break; } <gifData>5__3 = gifs[<gifIndex>5__2]; <frames>5__4 = new List<FrameData>(); <frames>5__4.Add(<gifData>5__3.firstFrame); <index>5__5 = 0; goto IL_0105; IL_0105: if (<gifData>5__3.gifStream.HasMoreData) { <>2__current = <wait>5__1; <>1__state = 1; return true; } try { if (<gifData>5__3.renderer != null) { Object.Destroy((Object)(object)((Component)((Component)<gifData>5__3.renderer).gameObject.transform.parent.GetChild(2)).gameObject); Log("Starting coroutine to play gif: " + <gifData>5__3.path); MelonCoroutines.Start((IEnumerator)PlayGif(<gifData>5__3.renderer, <frames>5__4, <gifData>5__3.path)); } } catch (Exception ex) { <ex>5__7 = ex; } <gifIndex>5__2++; <>2__current = <wait>5__1; <>1__state = 2; return true; } if (<gifIndex>5__2 == gifs.Count) { gifs = new List<GifData>(); } gifsLoading = false; Log("Stopping coroutine to load all gifs"); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <PlayGif>d__23 : IEnumerator<WaitForSeconds>, IEnumerator, IDisposable { private int <>1__state; private WaitForSeconds <>2__current; public Renderer renderer; public List<FrameData> frames; public string path; private int <i>5__1; private FrameData <frame>5__2; private Exception <ex>5__3; WaitForSeconds IEnumerator<WaitForSeconds>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PlayGif>d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <frame>5__2 = null; <ex>5__3 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <i>5__1 = 0; break; case 1: <>1__state = -1; break; case 2: <>1__state = -1; <>2__current = <frame>5__2.delay; <>1__state = 3; return true; case 3: <>1__state = -1; <i>5__1 = (<i>5__1 + 1) % frames.Count; <frame>5__2 = null; break; } if (gifsPlaying) { <frame>5__2 = frames[<i>5__1]; if ((Object)(object)<frame>5__2.texture == (Object)null) { <i>5__1 = (<i>5__1 + 1) % frames.Count; <>2__current = <frame>5__2.delay; <>1__state = 1; return true; } try { renderer.material.SetTexture("_Albedo", (Texture)(object)<frame>5__2.texture); } catch (Exception ex) { <ex>5__3 = ex; } <>2__current = null; <>1__state = 2; return true; } Log("Stopping coroutine to play gif: " + path); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <RunMailTubeAnimation>d__87 : IEnumerator<WaitForSeconds>, IEnumerator, IDisposable { private int <>1__state; private WaitForSeconds <>2__current; WaitForSeconds IEnumerator<WaitForSeconds>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RunMailTubeAnimation>d__87(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Expected O, but got Unknown //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Expected O, but got Unknown //IL_016b: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; mailTubePicture = new PictureData(); mailTubePicture.path = ((object)stashJson[0]).ToString(); stashJson.RemoveAt(0); mailTubePicture.padding = defaultPadding; mailTubePicture.thickness = defaultThickness; mailTubePicture.color = defaultColor; mailTubePicture.rotation = new Vector3(0f, 180f, 0f); mailTubePicture.jsonConfig = (JToken)new JObject(); mailTubePicture.jsonConfig[(object)"path"] = JToken.op_Implicit(mailTubePicture.path); CreatePicture(ref mailTubePicture, mailTubeHandle.transform); animationRunning = true; mailTube.ExecuteMailTubeAnimation(); SetPreviewSlabVisibility(visible: false); <>2__current = new WaitForSeconds(7f); <>1__state = 1; return true; case 1: <>1__state = -1; if (mailTubePicture != null) { mailTubePicture.obj.transform.SetParent(photoAlbum.transform, true); mailTubePicture.obj.transform.localScale = Vector3.one; } <>2__current = new WaitForSeconds(2f); <>1__state = 2; return true; case 2: <>1__state = -1; SetPreviewSlabVisibility(visible: true); animationRunning = false; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string UserDataPath = "UserData/RumblePhotoAlbum"; private const string picturesFolder = "pictures"; private const string configFile = "config.json"; private const float imageOffset = 0.001f; private static JObject root = null; private static string fullPath = Path.Combine(Application.dataPath, "..", "UserData/RumblePhotoAlbum", "config.json"); private static List<GifData> gifs = null; private static bool gifsLoading = false; private static bool gifsPlaying = false; private static float gifSpeed = 1f; private Mod Mod = new Mod(); private static bool[] grip = new bool[2]; private static bool[] holding = new bool[2]; private static GameObject[] hand = (GameObject[])(object)new GameObject[2]; private static PictureData currentlyModified = null; private static GameObject resizingHandle = null; private const float hold_distance = 0.05f; private static GameObject AlbumInteractionItems = null; private static GameObject friendButton = null; private static GameObject gearMarketButton = null; private static GameObject mailTubeObj = null; private static GameObject rockCamButton = null; private static Transform rockCamTf = null; private static GameObject rockCamHandle = null; private static PictureData rockCamPicture = null; private static bool rockCamInitialized = false; private static int PhotoPrintingIndex = 0; private static MailTube mailTube = null; private static GameObject mailTubeHandle = null; private static PictureData mailTubePicture = null; private static Transform purchaseSlab = null; private static bool animationRunning = false; private static JArray stashJson; private static JArray albumJson; private const float mailTubeScale = 0.505f; private const float maxPictureSize = 5f; protected static float defaultSize = 0.5f; protected static float defaultThickness = 0.01f; protected static float defaultPadding = 0.01f; protected static Color defaultColor = new Color(0.48f, 0.8f, 0.76f); protected static bool enableAlpha = false; protected static bool visibility = true; protected static bool buttonsVisibility = true; protected static GameObject photoAlbum = null; protected static string currentScene = ""; private static List<PictureData> PicturesList = null; private static void EnsureUserDataFolders() { string path = Path.Combine(Application.dataPath, "..", "UserData/RumblePhotoAlbum", "pictures"); Directory.CreateDirectory("UserData/RumblePhotoAlbum"); Directory.CreateDirectory(path); } [IteratorStateMachine(typeof(<LoadAlbum>d__11))] private static IEnumerator<WaitForSeconds> LoadAlbum(string sceneName) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadAlbum>d__11(0) { sceneName = sceneName }; } private static void reloadStash() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Expected O, but got Unknown JObject val = (JObject)root[currentScene]; ? val2 = (JArray)val["stash"]; if ((int)val2 == 0) { val2 = new JArray(); } JArray val3 = (JArray)val2; JToken obj = val["album"]; JArray source = (JArray)(((object)((obj is JArray) ? obj : null)) ?? ((object)new JArray())); HashSet<string> other = new HashSet<string>(from e in (IEnumerable<JToken>)source where e[(object)"path"] != null select ((object)e[(object)"path"]).ToString()); HashSet<string> hashSet = new HashSet<string>(); foreach (JToken item in val3) { string text = ((object)item).ToString(); if (!File.Exists(text)) { string path = Path.Combine(Application.dataPath, "..", "UserData/RumblePhotoAlbum", "pictures", text); if (!File.Exists(path)) { LogWarn("Removed missing file from stash: " + text); } else { hashSet.Add(text); } } } HashSet<string> hashSet2 = new HashSet<string>(hashSet); hashSet2.UnionWith(other); string path2 = Path.Combine(Application.dataPath, "..", "UserData/RumblePhotoAlbum", "pictures"); HashSet<string> hashSet3 = new HashSet<string>(Directory.Exists(path2) ? (from f in Directory.GetFiles(path2) where f.EndsWith(".png") || f.EndsWith(".jpg") || f.EndsWith(".jpeg") || f.EndsWith(".gif") select (f)) : Enumerable.Empty<string>()); foreach (string item2 in hashSet3) { string fileName = Path.GetFileName(item2); if (!hashSet2.Contains(fileName)) { hashSet.Add(fileName); } } val["stash"] = (JToken)new JArray((object)hashSet); } private static PictureData ParsePictureData(JToken pictureJson) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) if (pictureJson == null || (int)pictureJson.Type != 1) { throw new ArgumentException("Invalid JSON object for PictureData."); } JObject val = (JObject)pictureJson; PictureData pictureData = new PictureData(); pictureData.path = ((JToken)val).Value<string>((object)"path"); if (string.IsNullOrEmpty(pictureData.path)) { throw new ArgumentException("Missing field \"path\""); } pictureData.position = ParseVector3(val["position"], "position"); pictureData.rotation = ParseVector3(val["rotation"], "rotation"); pictureData.width = Math.Min(((JToken)val).Value<float?>((object)"width").GetValueOrDefault(), 5f); pictureData.height = Math.Min(((JToken)val).Value<float?>((object)"height").GetValueOrDefault(), 5f); pictureData.padding = ((JToken)val).Value<float?>((object)"padding") ?? defaultPadding; pictureData.thickness = ((JToken)val).Value<float?>((object)"thickness") ?? defaultThickness; pictureData.color = defaultColor; JToken token = default(JToken); if (val.TryGetValue("color", ref token)) { pictureData.color = ParseColor(token); } pictureData.alpha = ((JToken)val).Value<bool?>((object)"alpha") ?? enableAlpha; pictureData.visible = ((JToken)val).Value<bool?>((object)"visible") ?? visibility; return pictureData; } private static Vector3 ParseVector3(JToken token, string fieldName) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) if (token == null) { throw new ArgumentException("Missing field \"" + fieldName + "\""); } if ((int)token.Type != 2) { throw new ArgumentException(fieldName + "' must be an array [x, y, z] (got " + ((object)token).ToString() + ")"); } float[] array = token.ToObject<float[]>(); if (array.Length != 3) { throw new ArgumentException(fieldName + "' must have exactly 3 elements (got " + ((object)token).ToString() + ")"); } return new Vector3(array[0], array[1], array[2]); } private static Color ParseColor(JToken token) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((int)token.Type == 2) { float[] array = token.ToObject<float[]>(); if (array.Length >= 3) { return new Color(array[0], array[1], array[2], (array.Length >= 4) ? array[3] : 1f); } } else if ((int)token.Type == 8) { string hex = ((object)token).ToString(); return Hex2Color(hex); } throw new ArgumentException("PictureData: 'color' must be [r,g,b,a?] or hex string."); } private static Color Hex2Color(string hex) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); if (ColorUtility.TryParseHtmlString(hex, ref result)) { return result; } throw new ArgumentException("PictureData: 'color' must be [r,g,b,a?] or hex string."); } protected static void CreatePicture(ref PictureData pictureData, Transform parent) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) string text = pictureData.path; if (!File.Exists(text)) { string text2 = Path.Combine(Application.dataPath, "..", "UserData/RumblePhotoAlbum", "pictures", pictureData.path); if (!File.Exists(text2)) { throw new Exception("file doesn't exist"); } text = text2; } if (pictureData.path.EndsWith(".gif", StringComparison.OrdinalIgnoreCase)) { CreateGifBlock(text, ref pictureData, parent); return; } Texture2D val = null; val = ((!pictureData.alpha) ? LoadTexture(text) : LoadFlattenedTexture(text, pictureData.color)); CreatePictureBlock(ref pictureData, parent, val); } private static Renderer CreatePictureBlock(ref PictureData pictureData, Transform parent, Texture2D imageTexture) { //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) int layer = (pictureData.visible ? LayerMask.NameToLayer("UI") : LayerMask.NameToLayer("PlayerFade")); float num = (float)((Texture)imageTexture).height / (float)((Texture)imageTexture).width; if (pictureData.width == 0f && pictureData.height == 0f) { if (num > 1f) { pictureData.height = defaultSize; } else { pictureData.width = defaultSize; } } if (pictureData.width == 0f) { pictureData.width = (pictureData.height - 2f * pictureData.padding) / num + 2f * pictureData.padding; } else { pictureData.height = (pictureData.width - 2f * pictureData.padding) * num + 2f * pictureData.padding; } GameObject val = new GameObject(); val.layer = layer; ((Object)val).name = "PictureBlock: " + Path.GetFileNameWithoutExtension(pictureData.path); val.transform.SetParent(parent, false); val.transform.localPosition = pictureData.position; val.transform.localRotation = Quaternion.Euler(pictureData.rotation); GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)3); val2.layer = layer; ((Object)val2).name = "frame"; val2.transform.SetParent(val.transform, false); val2.transform.localScale = new Vector3(pictureData.width, pictureData.height, pictureData.thickness); val2.transform.localPosition = new Vector3(0f, 0f, pictureData.thickness / 2f); Renderer component = val2.GetComponent<Renderer>(); component.material.shader = Shader.Find("Shader Graphs/RUMBLE_Prop"); component.material.SetColor("_Overlay", pictureData.color); GameObject val3 = GameObject.CreatePrimitive((PrimitiveType)5); val3.layer = layer; ((Object)val3).name = "picture"; val3.transform.SetParent(val.transform, false); val3.transform.localScale = new Vector3(pictureData.width - 2f * pictureData.padding, pictureData.height - 2f * pictureData.padding, 1f); val3.transform.localPosition = new Vector3(0f, 0f, -0.001f); val3.transform.localRotation = Quaternion.identity; Renderer component2 = val3.GetComponent<Renderer>(); component2.material.shader = Shader.Find("Shader Graphs/RUMBLE_Prop"); component2.material.SetTexture("_Albedo", (Texture)(object)imageTexture); pictureData.obj = val; pictureData = pictureData; PicturesList.Add(pictureData); CreateActionButtons(pictureData); return component2; } private static void CreateGifBlock(string filePath, ref PictureData pictureData, Transform parent) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) GifStream gifStream = new GifStream(filePath); FrameData frameData = null; while (frameData == null && gifStream.HasMoreData) { frameData = ReadGifFrame(gifStream); } Renderer val = CreatePictureBlock(ref pictureData, parent, frameData.texture); GameObject val2 = Create.NewText(); TextMeshPro component = val2.GetComponent<TextMeshPro>(); ((TMP_Text)component).text = "Loading..."; ((TMP_Text)component).fontSize = 1f; ((Graphic)component).color = Color.black; ((Object)val2).name = "loadingText"; val2.transform.SetParent(((Component)val).gameObject.transform.parent, true); val2.transform.localPosition = new Vector3(0f, 0f, -0.002f); val2.transform.localRotation = Quaternion.Euler(new Vector3(0f, 0f, 0f)); if (gifs != null) { gifs.Add(new GifData { renderer = val, gifStream = gifStream, firstFrame = frameData, path = pictureData.path }); if (!gifsLoading) { gifsLoading = true; gifsPlaying = true; MelonCoroutines.Start((IEnumerator)PlayAllGifs()); } } } [IteratorStateMachine(typeof(<PlayAllGifs>d__22))] private static IEnumerator<WaitForSeconds> PlayAllGifs() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PlayAllGifs>d__22(0); } [IteratorStateMachine(typeof(<PlayGif>d__23))] private static IEnumerator<WaitForSeconds> PlayGif(Renderer renderer, List<FrameData> frames, string path) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PlayGif>d__23(0) { renderer = renderer, frames = frames, path = path }; } private static FrameData ReadGifFrame(GifStream gifStream) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown GifStream.Token currentToken = gifStream.CurrentToken; GifStream.Token token = currentToken; if (token == GifStream.Token.Image) { GifImage gifImage = gifStream.ReadImage(); Texture2D val = new Texture2D(gifStream.Header.width, gifStream.Header.height, (TextureFormat)5, false); val.SetPixels32(Il2CppStructArray<Color32>.op_Implicit(gifImage.colors)); val.Apply(); float num = gifImage.SafeDelaySeconds / gifSpeed - 0.015f; if (num < 0.001f) { num = 0.001f; } return new FrameData { texture = val, delay = new WaitForSeconds(num) }; } gifStream.SkipToken(); return null; } private static void CreateActionButtons(PictureData pictureData) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)pictureData.obj.transform.GetChild(0)).gameObject; float num = pictureData.width / 6f; Vector3 localScale = default(Vector3); ((Vector3)(ref localScale))..ctor(10f * num, pictureData.thickness / 0.03f, 10f * num); float num2 = pictureData.height / 2f + num * 0.6f; GameObject val = new GameObject(); ((Object)val).name = "actionButtons"; val.transform.localScale = Vector3.one; Action action = delegate { stashPicture(pictureData); }; GameObject val2 = NewFriendButton("stash", "Stash", action); val2.transform.localScale = localScale; val2.transform.SetParent(val.transform, true); val2.transform.localPosition = new Vector3((0f - pictureData.width) / 2f + num / 2f, 0f, 0f); val2.transform.localRotation = Quaternion.Euler(new Vector3(90f, 90f, -90f)); action = delegate { togglePictureVisibility(pictureData); }; GameObject val3 = NewFriendButton("visibility", pictureData.visible ? "Hide" : "Show", action); val3.transform.localScale = localScale; val3.transform.SetParent(val.transform, true); val3.transform.localPosition = new Vector3(0f, 0f, 0f); val3.transform.localRotation = Quaternion.Euler(new Vector3(90f, 90f, -90f)); action = delegate { deletePicture(pictureData, keepFile: false); }; GameObject val4 = NewFriendButton("delete", "Delete", action); val4.transform.localScale = localScale; val4.transform.SetParent(val.transform, true); val4.transform.localPosition = new Vector3(pictureData.width / 2f - num / 2f, 0f, 0f); val4.transform.localRotation = Quaternion.Euler(new Vector3(90f, 90f, -90f)); val.transform.SetParent(gameObject.transform); val.transform.localScale = new Vector3(1f / gameObject.transform.localScale.x, 1f / gameObject.transform.localScale.y, 1f / gameObject.transform.localScale.z); val.transform.localPosition = new Vector3(0f, num2 / pictureData.height, 0f); val.transform.localRotation = Quaternion.Euler(Vector3.zero); val.SetActive(false); } private static Texture2D LoadTexture(string path) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(array)); return val; } private static Texture2D LoadFlattenedTexture(string path, Color background) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(array)); Color[] array2 = Il2CppArrayBase<Color>.op_Implicit((Il2CppArrayBase<Color>)(object)val.GetPixels()); Color[] array3 = (Color[])(object)new Color[array2.Length]; for (int i = 0; i < array2.Length; i++) { Color val2 = array2[i]; float a = val2.a; array3[i] = new Color(val2.r * a + background.r * (1f - a), val2.g * a + background.g * (1f - a), val2.b * a + background.b * (1f - a)); } Texture2D val3 = new Texture2D(((Texture)val).width, ((Texture)val).height, (TextureFormat)3, false); val3.SetPixels(Il2CppStructArray<Color>.op_Implicit(array3)); val3.Apply(); return val3; } private static void UpdatePictureConfig(PictureData pictureData) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown if (pictureData.jsonConfig != null) { Vector3 position = pictureData.obj.transform.position; Vector3 eulerAngles = pictureData.obj.transform.eulerAngles; JToken jsonConfig = pictureData.jsonConfig; JArray val = new JArray(); val.Add(JToken.op_Implicit(position.x)); val.Add(JToken.op_Implicit(position.y)); val.Add(JToken.op_Implicit(position.z)); jsonConfig[(object)"position"] = (JToken)val; JToken jsonConfig2 = pictureData.jsonConfig; JArray val2 = new JArray(); val2.Add(JToken.op_Implicit(eulerAngles.x)); val2.Add(JToken.op_Implicit(eulerAngles.y)); val2.Add(JToken.op_Implicit(eulerAngles.z)); jsonConfig2[(object)"rotation"] = (JToken)val2; if (pictureData.jsonConfig[(object)"height"] != null) { pictureData.jsonConfig[(object)"height"] = JToken.op_Implicit(pictureData.height); } else { pictureData.jsonConfig[(object)"width"] = JToken.op_Implicit(pictureData.width); } if (pictureData.jsonConfig[(object)"visible"] != null || pictureData.visible != visibility) { pictureData.jsonConfig[(object)"visible"] = JToken.op_Implicit(pictureData.visible); } File.WriteAllText(fullPath, ((JToken)root).ToString((Formatting)1)); } } private void InitModUI() { UI.instance.UI_Initialized += OnUIInit; SetUIOptions(); ReadModUIOptions(); } private void SetUIOptions() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown Mod.ModName = "RumblePhotoAlbum"; Mod.ModVersion = "1.2.0"; Mod.SetFolder("RumblePhotoAlbum"); Mod.AddToList("Default frame color", "#7accc2", "You can set the frame color individually by adding a \"color\" field to the picture's JSON config.", new Tags()); Mod.AddToList("Default frame padding", 0.01f, "You can set the frame padding individually by adding a \"padding\" field to the picture's JSON config.", new Tags()); Mod.AddToList("Default frame thickness", 0.01f, "You can set the frame thickness individually by adding a \"thickness\" field to the picture's JSON config.", new Tags()); Mod.AddToList("Default picture size", 0.5f, "This is the default size of the pictures when they spawn. It will not change the pictures that are already positioned.", new Tags()); Mod.AddToList("Enable transparency", false, 0, "WARNING: this option adds a lag spike on picture creation.\nTo lower the effect, you can enable transparency individually by adding a boolean field \"alpha\" to the picture's JSON config.", new Tags()); Mod.AddToList("Show on camera", true, 0, "If disabled, this will hide all pictures from legacy camera, as well as LIV and Rock Cam.\nYou can hide/show any individual picture by clicking the corresponding button while holding it.", new Tags()); Mod.AddToList("Show action buttons", true, 0, "If disabled, the 3 buttons on the held picture won't appear.", new Tags()); Mod.AddToList("GIF playing speed", 1f, "The hardcoded mimimum delay between frames is 1000ms, so there is a maximum speed.", new Tags()); Mod.GetFromFile(); } private void OnUIInit() { Mod.ModSaved += OnUISaved; UI.instance.AddMod(Mod); } private void ReadModUIOptions() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) defaultColor = Hex2Color((string)Mod.Settings[0].SavedValue); defaultPadding = (float)Mod.Settings[1].SavedValue; defaultThickness = (float)Mod.Settings[2].SavedValue; defaultSize = (float)Mod.Settings[3].SavedValue; enableAlpha = (bool)Mod.Settings[4].SavedValue; visibility = (bool)Mod.Settings[5].SavedValue; buttonsVisibility = (bool)Mod.Settings[6].SavedValue; gifSpeed = (float)Mod.Settings[7].SavedValue; } private void OnUISaved() { ReadModUIOptions(); Object.Destroy((Object)(object)photoAlbum); MelonCoroutines.Start((IEnumerator)LoadAlbum(currentScene)); } private static void InitGrabbing() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown Transform child = ((Component)Players.GetPlayerController()).gameObject.transform.GetChild(2); grip[0] = false; grip[1] = false; holding[0] = false; holding[1] = false; hand[0] = ((Component)child.GetChild(1)).gameObject; hand[1] = ((Component)child.GetChild(2)).gameObject; currentlyModified = null; resizingHandle = new GameObject("ResizingHandle"); resizingHandle.transform.SetParent(child, true); } private static void ProcessGrabbing() { if ((ProcessGrabbing(0) || ProcessGrabbing(1)) && currentlyModified != null) { UpdatePictureParent(currentlyModified); if (!holding[0] && !holding[1]) { GameObject gameObject = ((Component)currentlyModified.obj.transform.GetChild(0).GetChild(0)).gameObject; gameObject.SetActive(false); currentlyModified = null; } } } private static bool ProcessGrabbing(int index) { bool flag = CheckIfGripChanged(index); if (flag) { bool flag2 = holding[index]; UpdateHolding(index); flag = holding[index] != flag2; } return flag; } private static bool CheckIfGripChanged(int index) { bool flag = false; switch (index) { case 0: flag = LeftController.GetTrigger() > 0.5f || LeftController.GetGrip() > 0.5f; break; case 1: flag = RightController.GetTrigger() > 0.5f || RightController.GetGrip() > 0.5f; break; } bool result = flag != grip[index]; if (flag && !grip[index]) { grip[index] = true; } else if (!flag && grip[index]) { grip[index] = false; } return result; } private static void UpdateHolding(int index) { if (PicturesList == null) { return; } if (!grip[index]) { holding[index] = false; return; } if (currentlyModified != null) { float num = DistanceToPictureSurface(hand[index], currentlyModified); holding[index] = num < 0.05f; return; } float num2 = 0.05f; foreach (PictureData pictures in PicturesList) { if (pictures.obj == null) { LogWarn("Framed picture " + pictures.path + " has no GameObject associated with it."); continue; } float num3 = DistanceToPictureSurface(hand[index], pictures); if (num3 < num2) { holding[index] = true; num2 = num3; currentlyModified = pictures; if (buttonsVisibility) { GameObject gameObject = ((Component)currentlyModified.obj.transform.GetChild(0).GetChild(0)).gameObject; gameObject.SetActive(true); } if (pictures == mailTubePicture) { mailTubePicture = null; albumJson.Add(pictures.jsonConfig); } if (pictures == rockCamPicture) { rockCamPicture = null; albumJson.Add(pictures.jsonConfig); } } } } private static float DistanceToPictureSurface(GameObject hand, PictureData pictureData) { //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_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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00b5: Unknown result type (might be due to invalid IL or missing references) Vector3 position = hand.transform.position; Transform child = pictureData.obj.transform.GetChild(0); Vector3 position2 = child.position; Quaternion rotation = child.rotation; Vector3 val = new Vector3(pictureData.width, pictureData.height, pictureData.thickness) * 0.5f; Vector3 val2 = Quaternion.Inverse(rotation) * (position - position2); float num = Mathf.Max(0f, Mathf.Abs(val2.x) - val.x); float num2 = Mathf.Max(0f, Mathf.Abs(val2.y) - val.y); float num3 = Mathf.Max(0f, Mathf.Abs(val2.z) - val.z); if (num == 0f && num2 == 0f && num3 == 0f) { return 0f; } return Mathf.Sqrt(num * num + num2 * num2 + num3 * num3); } private static void UpdatePictureParent(PictureData pictureData) { if (holding[0]) { if (holding[1]) { UpdateResizingHandle(); pictureData.obj.transform.SetParent(resizingHandle.transform, true); } else { pictureData.obj.transform.SetParent(hand[0].transform, true); } } else if (holding[1]) { pictureData.obj.transform.SetParent(hand[1].transform, true); } else { pictureData.obj.transform.SetParent(photoAlbum.transform, true); UpdatePictureConfig(pictureData); } } private static void UpdateResizingIfNeeded() { if (holding[0] && holding[1]) { UpdateResizingHandle(); UpdatePictureSize(currentlyModified); } } private static void UpdateResizingHandle() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_003e: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_007c: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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) //IL_0098: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) Transform transform = hand[0].transform; Transform transform2 = hand[1].transform; Vector3 localPosition = (transform.localPosition + transform2.localPosition) * 0.5f; Vector3 val = transform2.localPosition - transform.localPosition; Vector3 normalized = ((Vector3)(ref val)).normalized; Quaternion val2 = Quaternion.Slerp(transform.localRotation, transform2.localRotation, 0.5f); val = Vector3.ProjectOnPlane(val2 * Vector3.up, normalized); Vector3 normalized2 = ((Vector3)(ref val)).normalized; val = Vector3.Cross(normalized, normalized2); Vector3 normalized3 = ((Vector3)(ref val)).normalized; normalized2 = Vector3.Cross(normalized3, normalized); Quaternion localRotation = Quaternion.LookRotation(normalized3, normalized2); float num = Vector3.Distance(transform.localPosition, transform2.localPosition); float num2 = currentlyModified.obj.transform.localScale.x * num; Transform child = currentlyModified.obj.transform.GetChild(0); float num3 = Math.Max(child.localScale.x, child.localScale.y); float num4 = Math.Min(num3, 5f / num2) / num3; resizingHandle.transform.localScale = Vector3.one * num * num4; resizingHandle.transform.localPosition = localPosition; resizingHandle.transform.localRotation = localRotation; } private static void UpdatePictureSize(PictureData pictureData) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_013a: Unknown result type (might be due to invalid IL or missing references) float num = pictureData.obj.transform.localScale.x * resizingHandle.transform.localScale.x; Transform child = pictureData.obj.transform.GetChild(0); Transform child2 = pictureData.obj.transform.GetChild(1); float num2 = child2.localScale.y / child2.localScale.x; float num3 = child.localScale.x - 2f * pictureData.padding / num; child2.localScale = new Vector3(num3, num3 * num2, 1f); child.localScale = new Vector3(child.localScale.x, child2.localScale.y + 2f * pictureData.padding / num, pictureData.thickness / num); pictureData.width = child.localScale.x * num; pictureData.height = child.localScale.y * num; ((Component)child).transform.localPosition = new Vector3(0f, 0f, pictureData.thickness / (2f * num)); ((Component)child2).transform.localPosition = new Vector3(0f, 0f, -0.001f / num); } private static void initializeInteractionObjects() { rockCamInitialized = false; if (currentScene == "Loader") { return; } if (currentScene == "Gym") { if (AlbumInteractionItems == null) { initializeGlobals(); } initializeGymObjects(); } else if (currentScene == "Park") { initializeParkObjects(); } initializeRockCam(); } private static void initializeGlobals() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) AlbumInteractionItems = new GameObject(); ((Object)AlbumInteractionItems).name = "AlbumInteractionItems"; Object.DontDestroyOnLoad((Object)(object)AlbumInteractionItems); friendButton = Object.Instantiate<GameObject>(Button.GetGameObject()); ((Object)friendButton).name = "friendButton"; friendButton.SetActive(false); ((Behaviour)friendButton.GetComponent<InteractionButton>()).enabled = true; ((Component)friendButton.transform.GetChild(4)).gameObject.SetActive(false); GameObject val = Create.NewText(); TextMeshPro component = val.GetComponent<TextMeshPro>(); ((TMP_Text)component).alignment = (TextAlignmentOptions)514; Color val2 = default(Color); ((Color)(ref val2))..ctor(1f, 0.98f, 0.75f); ((Graphic)component).color = val2; ((TMP_Text)component).colorGradient = new VertexGradient(val2); ((TMP_Text)component).fontSize = 0.4f; ((Object)component).name = "text"; val.transform.SetParent(friendButton.transform, false); val.transform.localPosition = new Vector3(0f, 0.015f, 0f); val.transform.localRotation = Quaternion.Euler(new Vector3(90f, 180f, 0f)); friendButton.transform.SetParent(AlbumInteractionItems.transform); gearMarketButton = Object.Instantiate<GameObject>(OneButtonLayout.GetGameObject()); ((Object)gearMarketButton).name = "gearMarketButton"; gearMarketButton.SetActive(false); ((Behaviour)((Component)gearMarketButton.transform.GetChild(0)).gameObject.GetComponent<InteractionTouch>()).enabled = true; gearMarketButton.transform.SetParent(AlbumInteractionItems.transform); mailTubeObj = Object.Instantiate<GameObject>(MailTube.GetGameObject()); ((Object)mailTubeObj).name = "mailTube"; mailTubeObj.SetActive(false); mailTubeObj.transform.SetParent(AlbumInteractionItems.transform); rockCamTf = ((Component)Players.GetPlayerController()).gameObject.transform.GetChild(10).GetChild(2); rockCamButton = Object.Instantiate<GameObject>(((Component)rockCamTf.GetChild(2).GetChild(0).GetChild(1) .GetChild(4) .GetChild(0)).gameObject); ((Object)rockCamButton).name = "rockCamButton"; rockCamButton.SetActive(false); rockCamButton.transform.SetParent(AlbumInteractionItems.transform); } private static void initializeRockCam() { //IL_00c2: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) try { if (rockCamInitialized || rockCamButton == null || gearMarketButton == null) { return; } PlayerController playerController = Players.GetPlayerController(); if (playerController != null) { rockCamPicture = null; rockCamTf = ((Component)playerController).gameObject.transform.GetChild(10).GetChild(2); Action action = delegate { PrintPhoto(); }; GameObject val = NewRockCamButton("printButton", "Print photo", action); val.transform.SetParent(rockCamTf.GetChild(2).GetChild(0), true); val.transform.localPosition = new Vector3(-0.08f, 0.034f, 0.143f); val.transform.localRotation = Quaternion.Euler(new Vector3(90f, 0f, 0f)); rockCamHandle = new GameObject(); ((Object)rockCamHandle).name = "printHandle"; rockCamHandle.transform.localScale = Vector3.one; rockCamHandle.transform.SetParent(rockCamTf.GetChild(2).GetChild(0), true); rockCamHandle.transform.localPosition = new Vector3(0f, 0.079f, 0.22f); rockCamHandle.transform.localRotation = Quaternion.Euler(new Vector3(-50f, 180f, 0f)); PhotoPrintingIndex = 0; rockCamInitialized = true; } } catch (Exception) { rockCamInitialized = false; } } private static void initializeGymObjects() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) mailTube = MailTube.GetGameObject().GetComponent<MailTube>(); Action action = delegate { SpawnPicture(); }; GameObject val = NewGearMarketButton("spawnButton", "Spawn picture", action); GameObject gameObject = Gearmarket.GetGameObject(); val.transform.SetParent(gameObject.transform); val.transform.localPosition = new Vector3(0.075f, 1.1f, 0.19f); val.transform.localRotation = Quaternion.Euler(new Vector3(270f, 270f, 0f)); initializeMailTubeObjects(); } private static void stashPicture(PictureData pictureData) { if (pictureData.jsonConfig != null) { pictureData.jsonConfig.Remove(); } Object.Destroy((Object)(object)pictureData.obj); currentlyModified = null; stashJson.Add(JToken.op_Implicit(pictureData.path)); PicturesList.Remove(pictureData); File.WriteAllText(fullPath, ((JToken)root).ToString((Formatting)1)); Log("Stashed a picture"); } private static void togglePictureVisibility(PictureData pictureData) { pictureData.visible = !pictureData.visible; int layer = (pictureData.visible ? LayerMask.NameToLayer("UI") : LayerMask.NameToLayer("PlayerFade")); ((Component)pictureData.obj.transform.GetChild(0)).gameObject.layer = layer; ((Component)pictureData.obj.transform.GetChild(1)).gameObject.layer = layer; Transform child = pictureData.obj.transform.GetChild(0).GetChild(0).GetChild(1); TextMeshPro component = ((Component)child.GetChild(6)).gameObject.GetComponent<TextMeshPro>(); ((TMP_Text)component).SetText(pictureData.visible ? "Hide" : "Show"); Log("Made a picture " + (pictureData.visible ? "visible" : "invisible") + " to all cameras"); } protected static void deletePicture(PictureData pictureData, bool keepFile) { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown if (pictureData.jsonConfig != null) { pictureData.jsonConfig.Remove(); File.WriteAllText(fullPath, ((JToken)root).ToString((Formatting)1)); } Object.Destroy((Object)(object)pictureData.obj); currentlyModified = null; PicturesList.Remove(pictureData); if (File.Exists(pictureData.path) || keepFile) { return; } string path = Path.Combine(Application.dataPath, "..", "UserData/RumblePhotoAlbum", "pictures", pictureData.path); if (!File.Exists(path)) { return; } bool flag = false; foreach (KeyValuePair<string, JToken> item in root) { JArray val = (JArray)item.Value[(object)"album"]; foreach (JToken item2 in val) { if (item2.Valu