Decompiled source of RumblePhotoAlbum v1.2.0

Mods/RumblePhotoAlbum.dll

Decompiled 3 weeks ago
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