Decompiled source of SpeedrunTools v2.5.0

Mods/SpeedrunTools.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.IO.Pipes;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Bwr;
using FlatBuffers;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.TinyJSON;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Sst;
using Sst.Common.Boneworks;
using Sst.Common.Ipc;
using Sst.Features;
using Sst.Replays;
using Sst.Speedruns;
using Sst.Utilities;
using Steamworks;
using StressLevelZero;
using StressLevelZero.Arena;
using StressLevelZero.Combat;
using StressLevelZero.Data;
using StressLevelZero.Interaction;
using StressLevelZero.Pool;
using StressLevelZero.Props;
using StressLevelZero.Props.Weapons;
using StressLevelZero.Rig;
using StressLevelZero.Utilities;
using TMPro;
using UnhollowerBaseLib;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Valve.VR;
using Valve.VRRenderingPackage;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SpeedrunTools")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany(null)]
[assembly: AssemblyProduct("SpeedrunTools")]
[assembly: AssemblyCopyright("Created by jakzo")]
[assembly: AssemblyTrademark(null)]
[assembly: ComVisible(false)]
[assembly: AssemblyFileVersion("2.5.0")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: MelonInfo(typeof(Mod), "SpeedrunTools", "2.5.0", "jakzo", "https://boneworks.thunderstore.io/package/jakzo/SpeedrunTools/")]
[assembly: MelonGame("Stress Level Zero", "BONEWORKS")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("2.5.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FlatBuffers
{
	public abstract class ByteBufferAllocator
	{
		public byte[] Buffer { get; protected set; }

		public int Length { get; protected set; }

		public abstract void GrowFront(int newSize);
	}
	public sealed class ByteArrayAllocator : ByteBufferAllocator
	{
		private byte[] _buffer;

		public ByteArrayAllocator(byte[] buffer)
		{
			_buffer = buffer;
			InitBuffer();
		}

		public override void GrowFront(int newSize)
		{
			if ((base.Length & 0xC0000000u) != 0L)
			{
				throw new Exception("ByteBuffer: cannot grow buffer beyond 2 gigabytes.");
			}
			if (newSize < base.Length)
			{
				throw new Exception("ByteBuffer: cannot truncate buffer.");
			}
			byte[] array = new byte[newSize];
			System.Buffer.BlockCopy(_buffer, 0, array, newSize - base.Length, base.Length);
			_buffer = array;
			InitBuffer();
		}

		private void InitBuffer()
		{
			base.Length = _buffer.Length;
			base.Buffer = _buffer;
		}
	}
	public class ByteBuffer
	{
		[StructLayout(LayoutKind.Explicit)]
		private struct ConversionUnion
		{
			[FieldOffset(0)]
			public int intValue;

			[FieldOffset(0)]
			public float floatValue;
		}

		private ByteBufferAllocator _buffer;

		private int _pos;

		private static Dictionary<Type, int> genericSizes = new Dictionary<Type, int>
		{
			{
				typeof(bool),
				1
			},
			{
				typeof(float),
				4
			},
			{
				typeof(double),
				8
			},
			{
				typeof(sbyte),
				1
			},
			{
				typeof(byte),
				1
			},
			{
				typeof(short),
				2
			},
			{
				typeof(ushort),
				2
			},
			{
				typeof(int),
				4
			},
			{
				typeof(uint),
				4
			},
			{
				typeof(ulong),
				8
			},
			{
				typeof(long),
				8
			}
		};

		public int Position
		{
			get
			{
				return _pos;
			}
			set
			{
				_pos = value;
			}
		}

		public int Length => _buffer.Length;

		public ByteBuffer(ByteBufferAllocator allocator, int position)
		{
			_buffer = allocator;
			_pos = position;
		}

		public ByteBuffer(int size)
			: this(new byte[size])
		{
		}

		public ByteBuffer(byte[] buffer)
			: this(buffer, 0)
		{
		}

		public ByteBuffer(byte[] buffer, int pos)
		{
			_buffer = new ByteArrayAllocator(buffer);
			_pos = pos;
		}

		public void Reset()
		{
			_pos = 0;
		}

		public ByteBuffer Duplicate()
		{
			return new ByteBuffer(_buffer, Position);
		}

		public void GrowFront(int newSize)
		{
			_buffer.GrowFront(newSize);
		}

		public byte[] ToArray(int pos, int len)
		{
			return ToArray<byte>(pos, len);
		}

		public static int SizeOf<T>()
		{
			return genericSizes[typeof(T)];
		}

		public static bool IsSupportedType<T>()
		{
			return genericSizes.ContainsKey(typeof(T));
		}

		public static int ArraySize<T>(T[] x)
		{
			return SizeOf<T>() * x.Length;
		}

		public static int ArraySize<T>(ArraySegment<T> x)
		{
			return SizeOf<T>() * x.Count;
		}

		public T[] ToArray<T>(int pos, int len) where T : struct
		{
			AssertOffsetAndLength(pos, len);
			T[] array = new T[len];
			Buffer.BlockCopy(_buffer.Buffer, pos, array, 0, ArraySize(array));
			return array;
		}

		public byte[] ToSizedArray()
		{
			return ToArray<byte>(Position, Length - Position);
		}

		public byte[] ToFullArray()
		{
			return ToArray<byte>(0, Length);
		}

		public ArraySegment<byte> ToArraySegment(int pos, int len)
		{
			return new ArraySegment<byte>(_buffer.Buffer, pos, len);
		}

		public MemoryStream ToMemoryStream(int pos, int len)
		{
			return new MemoryStream(_buffer.Buffer, pos, len);
		}

		public static ushort ReverseBytes(ushort input)
		{
			return (ushort)((uint)((input & 0xFF) << 8) | ((uint)(input & 0xFF00) >> 8));
		}

		public static uint ReverseBytes(uint input)
		{
			return ((input & 0xFF) << 24) | ((input & 0xFF00) << 8) | ((input & 0xFF0000) >> 8) | ((input & 0xFF000000u) >> 24);
		}

		public static ulong ReverseBytes(ulong input)
		{
			return ((input & 0xFF) << 56) | ((input & 0xFF00) << 40) | ((input & 0xFF0000) << 24) | ((input & 0xFF000000u) << 8) | ((input & 0xFF00000000L) >> 8) | ((input & 0xFF0000000000L) >> 24) | ((input & 0xFF000000000000L) >> 40) | ((input & 0xFF00000000000000uL) >> 56);
		}

		protected void WriteLittleEndian(int offset, int count, ulong data)
		{
			if (BitConverter.IsLittleEndian)
			{
				for (int i = 0; i < count; i++)
				{
					_buffer.Buffer[offset + i] = (byte)(data >> i * 8);
				}
			}
			else
			{
				for (int j = 0; j < count; j++)
				{
					_buffer.Buffer[offset + count - 1 - j] = (byte)(data >> j * 8);
				}
			}
		}

		protected ulong ReadLittleEndian(int offset, int count)
		{
			AssertOffsetAndLength(offset, count);
			ulong num = 0uL;
			if (BitConverter.IsLittleEndian)
			{
				for (int i = 0; i < count; i++)
				{
					num |= (ulong)_buffer.Buffer[offset + i] << i * 8;
				}
			}
			else
			{
				for (int j = 0; j < count; j++)
				{
					num |= (ulong)_buffer.Buffer[offset + count - 1 - j] << j * 8;
				}
			}
			return num;
		}

		private void AssertOffsetAndLength(int offset, int length)
		{
			if (offset < 0 || offset > _buffer.Length - length)
			{
				throw new ArgumentOutOfRangeException();
			}
		}

		public void PutSbyte(int offset, sbyte value)
		{
			AssertOffsetAndLength(offset, 1);
			_buffer.Buffer[offset] = (byte)value;
		}

		public void PutByte(int offset, byte value)
		{
			AssertOffsetAndLength(offset, 1);
			_buffer.Buffer[offset] = value;
		}

		public void PutByte(int offset, byte value, int count)
		{
			AssertOffsetAndLength(offset, count);
			for (int i = 0; i < count; i++)
			{
				_buffer.Buffer[offset + i] = value;
			}
		}

		public void Put(int offset, byte value)
		{
			PutByte(offset, value);
		}

		public void PutStringUTF8(int offset, string value)
		{
			AssertOffsetAndLength(offset, value.Length);
			Encoding.UTF8.GetBytes(value, 0, value.Length, _buffer.Buffer, offset);
		}

		public void PutShort(int offset, short value)
		{
			AssertOffsetAndLength(offset, 2);
			WriteLittleEndian(offset, 2, (ulong)value);
		}

		public void PutUshort(int offset, ushort value)
		{
			AssertOffsetAndLength(offset, 2);
			WriteLittleEndian(offset, 2, value);
		}

		public void PutInt(int offset, int value)
		{
			AssertOffsetAndLength(offset, 4);
			WriteLittleEndian(offset, 4, (ulong)value);
		}

		public void PutUint(int offset, uint value)
		{
			AssertOffsetAndLength(offset, 4);
			WriteLittleEndian(offset, 4, value);
		}

		public void PutLong(int offset, long value)
		{
			AssertOffsetAndLength(offset, 8);
			WriteLittleEndian(offset, 8, (ulong)value);
		}

		public void PutUlong(int offset, ulong value)
		{
			AssertOffsetAndLength(offset, 8);
			WriteLittleEndian(offset, 8, value);
		}

		public void PutFloat(int offset, float value)
		{
			AssertOffsetAndLength(offset, 4);
			ConversionUnion conversionUnion = default(ConversionUnion);
			conversionUnion.intValue = 0;
			conversionUnion.floatValue = value;
			WriteLittleEndian(offset, 4, (ulong)conversionUnion.intValue);
		}

		public void PutDouble(int offset, double value)
		{
			AssertOffsetAndLength(offset, 8);
			WriteLittleEndian(offset, 8, (ulong)BitConverter.DoubleToInt64Bits(value));
		}

		public sbyte GetSbyte(int index)
		{
			AssertOffsetAndLength(index, 1);
			return (sbyte)_buffer.Buffer[index];
		}

		public byte Get(int index)
		{
			AssertOffsetAndLength(index, 1);
			return _buffer.Buffer[index];
		}

		public string GetStringUTF8(int startPos, int len)
		{
			return Encoding.UTF8.GetString(_buffer.Buffer, startPos, len);
		}

		public short GetShort(int index)
		{
			return (short)ReadLittleEndian(index, 2);
		}

		public ushort GetUshort(int index)
		{
			return (ushort)ReadLittleEndian(index, 2);
		}

		public int GetInt(int index)
		{
			return (int)ReadLittleEndian(index, 4);
		}

		public uint GetUint(int index)
		{
			return (uint)ReadLittleEndian(index, 4);
		}

		public long GetLong(int index)
		{
			return (long)ReadLittleEndian(index, 8);
		}

		public ulong GetUlong(int index)
		{
			return ReadLittleEndian(index, 8);
		}

		public float GetFloat(int index)
		{
			ConversionUnion conversionUnion = default(ConversionUnion);
			conversionUnion.floatValue = 0f;
			conversionUnion.intValue = (int)ReadLittleEndian(index, 4);
			return conversionUnion.floatValue;
		}

		public double GetDouble(int index)
		{
			return BitConverter.Int64BitsToDouble((long)ReadLittleEndian(index, 8));
		}

		public int Put<T>(int offset, T[] x) where T : struct
		{
			if (x == null)
			{
				throw new ArgumentNullException("Cannot put a null array");
			}
			return Put(offset, new ArraySegment<T>(x));
		}

		public int Put<T>(int offset, ArraySegment<T> x) where T : struct
		{
			if (x.Equals(default(ArraySegment<T>)))
			{
				throw new ArgumentNullException("Cannot put a uninitialized array segment");
			}
			if (x.Count == 0)
			{
				throw new ArgumentException("Cannot put an empty array");
			}
			if (!IsSupportedType<T>())
			{
				throw new ArgumentException("Cannot put an array of type " + typeof(T)?.ToString() + " into this buffer");
			}
			if (BitConverter.IsLittleEndian)
			{
				int num = ArraySize(x);
				offset -= num;
				AssertOffsetAndLength(offset, num);
				int srcOffset = SizeOf<T>() * x.Offset;
				Buffer.BlockCopy(x.Array, srcOffset, _buffer.Buffer, offset, num);
				return offset;
			}
			throw new NotImplementedException("Big Endian Support not implemented yet for putting typed arrays");
		}

		public int Put<T>(int offset, IntPtr ptr, int sizeInBytes) where T : struct
		{
			if (ptr == IntPtr.Zero)
			{
				throw new ArgumentNullException("Cannot add a null pointer");
			}
			if (sizeInBytes <= 0)
			{
				throw new ArgumentException("Cannot put an empty array");
			}
			if (!IsSupportedType<T>())
			{
				throw new ArgumentException("Cannot put an array of type " + typeof(T)?.ToString() + " into this buffer");
			}
			if (BitConverter.IsLittleEndian)
			{
				offset -= sizeInBytes;
				AssertOffsetAndLength(offset, sizeInBytes);
				Marshal.Copy(ptr, _buffer.Buffer, offset, sizeInBytes);
				return offset;
			}
			throw new NotImplementedException("Big Endian Support not implemented yet for putting typed arrays");
		}
	}
	public class ByteBufferUtil
	{
		public static int GetSizePrefix(ByteBuffer bb)
		{
			return bb.GetInt(bb.Position);
		}

		public static ByteBuffer RemoveSizePrefix(ByteBuffer bb)
		{
			ByteBuffer byteBuffer = bb.Duplicate();
			byteBuffer.Position += 4;
			return byteBuffer;
		}
	}
	public class FlatBufferBuilder
	{
		private int _space;

		private ByteBuffer _bb;

		private int _minAlign = 1;

		private int[] _vtable = new int[16];

		private int _vtableSize = -1;

		private int _objectStart;

		private int[] _vtables = new int[16];

		private int _numVtables;

		private int _vectorNumElems;

		private Dictionary<string, StringOffset> _sharedStringMap;

		public bool ForceDefaults { get; set; }

		public int Offset => _bb.Length - _space;

		public ByteBuffer DataBuffer => _bb;

		public FlatBufferBuilder(int initialSize)
		{
			if (initialSize <= 0)
			{
				throw new ArgumentOutOfRangeException("initialSize", initialSize, "Must be greater than zero");
			}
			_space = initialSize;
			_bb = new ByteBuffer(initialSize);
		}

		public FlatBufferBuilder(ByteBuffer buffer)
		{
			_bb = buffer;
			_space = buffer.Length;
			buffer.Reset();
		}

		public void Clear()
		{
			_space = _bb.Length;
			_bb.Reset();
			_minAlign = 1;
			while (_vtableSize > 0)
			{
				_vtable[--_vtableSize] = 0;
			}
			_vtableSize = -1;
			_objectStart = 0;
			_numVtables = 0;
			_vectorNumElems = 0;
			if (_sharedStringMap != null)
			{
				_sharedStringMap.Clear();
			}
		}

		public void Pad(int size)
		{
			_bb.PutByte(_space -= size, 0, size);
		}

		private void GrowBuffer()
		{
			_bb.GrowFront(_bb.Length << 1);
		}

		public void Prep(int size, int additionalBytes)
		{
			if (size > _minAlign)
			{
				_minAlign = size;
			}
			int num = (~(_bb.Length - _space + additionalBytes) + 1) & (size - 1);
			while (_space < num + size + additionalBytes)
			{
				int length = _bb.Length;
				GrowBuffer();
				_space += _bb.Length - length;
			}
			if (num > 0)
			{
				Pad(num);
			}
		}

		public void PutBool(bool x)
		{
			_bb.PutByte(--_space, x ? ((byte)1) : ((byte)0));
		}

		public void PutSbyte(sbyte x)
		{
			_bb.PutSbyte(--_space, x);
		}

		public void PutByte(byte x)
		{
			_bb.PutByte(--_space, x);
		}

		public void PutShort(short x)
		{
			_bb.PutShort(_space -= 2, x);
		}

		public void PutUshort(ushort x)
		{
			_bb.PutUshort(_space -= 2, x);
		}

		public void PutInt(int x)
		{
			_bb.PutInt(_space -= 4, x);
		}

		public void PutUint(uint x)
		{
			_bb.PutUint(_space -= 4, x);
		}

		public void PutLong(long x)
		{
			_bb.PutLong(_space -= 8, x);
		}

		public void PutUlong(ulong x)
		{
			_bb.PutUlong(_space -= 8, x);
		}

		public void PutFloat(float x)
		{
			_bb.PutFloat(_space -= 4, x);
		}

		public void Put<T>(T[] x) where T : struct
		{
			_space = _bb.Put(_space, x);
		}

		public void Put<T>(ArraySegment<T> x) where T : struct
		{
			_space = _bb.Put(_space, x);
		}

		public void Put<T>(IntPtr ptr, int sizeInBytes) where T : struct
		{
			_space = _bb.Put<T>(_space, ptr, sizeInBytes);
		}

		public void PutDouble(double x)
		{
			_bb.PutDouble(_space -= 8, x);
		}

		public void AddBool(bool x)
		{
			Prep(1, 0);
			PutBool(x);
		}

		public void AddSbyte(sbyte x)
		{
			Prep(1, 0);
			PutSbyte(x);
		}

		public void AddByte(byte x)
		{
			Prep(1, 0);
			PutByte(x);
		}

		public void AddShort(short x)
		{
			Prep(2, 0);
			PutShort(x);
		}

		public void AddUshort(ushort x)
		{
			Prep(2, 0);
			PutUshort(x);
		}

		public void AddInt(int x)
		{
			Prep(4, 0);
			PutInt(x);
		}

		public void AddUint(uint x)
		{
			Prep(4, 0);
			PutUint(x);
		}

		public void AddLong(long x)
		{
			Prep(8, 0);
			PutLong(x);
		}

		public void AddUlong(ulong x)
		{
			Prep(8, 0);
			PutUlong(x);
		}

		public void AddFloat(float x)
		{
			Prep(4, 0);
			PutFloat(x);
		}

		public void Add<T>(T[] x) where T : struct
		{
			Add(new ArraySegment<T>(x));
		}

		public void Add<T>(ArraySegment<T> x) where T : struct
		{
			if (x.Count != 0)
			{
				if (!ByteBuffer.IsSupportedType<T>())
				{
					throw new ArgumentException("Cannot add this Type array to the builder");
				}
				int num = ByteBuffer.SizeOf<T>();
				Prep(num, num * (x.Count - 1));
				Put(x);
			}
		}

		public void Add<T>(IntPtr ptr, int sizeInBytes) where T : struct
		{
			if (sizeInBytes != 0)
			{
				if (ptr == IntPtr.Zero)
				{
					throw new ArgumentNullException("Cannot add a null pointer");
				}
				if (sizeInBytes < 0)
				{
					throw new ArgumentOutOfRangeException("sizeInBytes", "sizeInBytes cannot be negative");
				}
				if (!ByteBuffer.IsSupportedType<T>())
				{
					throw new ArgumentException("Cannot add this Type array to the builder");
				}
				int num = ByteBuffer.SizeOf<T>();
				if (sizeInBytes % num != 0)
				{
					throw new ArgumentException("The given size in bytes " + sizeInBytes + " doesn't match the element size of T ( " + num + ")", "sizeInBytes");
				}
				Prep(num, sizeInBytes - num);
				Put<T>(ptr, sizeInBytes);
			}
		}

		public void AddDouble(double x)
		{
			Prep(8, 0);
			PutDouble(x);
		}

		public void AddOffset(int off)
		{
			Prep(4, 0);
			if (off > Offset)
			{
				throw new ArgumentException();
			}
			off = Offset - off + 4;
			PutInt(off);
		}

		public void StartVector(int elemSize, int count, int alignment)
		{
			NotNested();
			_vectorNumElems = count;
			Prep(4, elemSize * count);
			Prep(alignment, elemSize * count);
		}

		public VectorOffset EndVector()
		{
			PutInt(_vectorNumElems);
			return new VectorOffset(Offset);
		}

		public VectorOffset CreateVectorOfTables<T>(Offset<T>[] offsets) where T : struct
		{
			NotNested();
			StartVector(4, offsets.Length, 4);
			for (int num = offsets.Length - 1; num >= 0; num--)
			{
				AddOffset(offsets[num].Value);
			}
			return EndVector();
		}

		public void Nested(int obj)
		{
			if (obj != Offset)
			{
				throw new Exception("FlatBuffers: struct must be serialized inline.");
			}
		}

		public void NotNested()
		{
			if (_vtableSize >= 0)
			{
				throw new Exception("FlatBuffers: object serialization must not be nested.");
			}
		}

		public void StartTable(int numfields)
		{
			if (numfields < 0)
			{
				throw new ArgumentOutOfRangeException("Flatbuffers: invalid numfields");
			}
			NotNested();
			if (_vtable.Length < numfields)
			{
				_vtable = new int[numfields];
			}
			_vtableSize = numfields;
			_objectStart = Offset;
		}

		public void Slot(int voffset)
		{
			if (voffset >= _vtableSize)
			{
				throw new IndexOutOfRangeException("Flatbuffers: invalid voffset");
			}
			_vtable[voffset] = Offset;
		}

		public void AddBool(int o, bool x, bool d)
		{
			if (ForceDefaults || x != d)
			{
				AddBool(x);
				Slot(o);
			}
		}

		public void AddBool(int o, bool? x)
		{
			if (x.HasValue)
			{
				AddBool(x.Value);
				Slot(o);
			}
		}

		public void AddSbyte(int o, sbyte x, sbyte d)
		{
			if (ForceDefaults || x != d)
			{
				AddSbyte(x);
				Slot(o);
			}
		}

		public void AddSbyte(int o, sbyte? x)
		{
			if (x.HasValue)
			{
				AddSbyte(x.Value);
				Slot(o);
			}
		}

		public void AddByte(int o, byte x, byte d)
		{
			if (ForceDefaults || x != d)
			{
				AddByte(x);
				Slot(o);
			}
		}

		public void AddByte(int o, byte? x)
		{
			if (x.HasValue)
			{
				AddByte(x.Value);
				Slot(o);
			}
		}

		public void AddShort(int o, short x, int d)
		{
			if (ForceDefaults || x != d)
			{
				AddShort(x);
				Slot(o);
			}
		}

		public void AddShort(int o, short? x)
		{
			if (x.HasValue)
			{
				AddShort(x.Value);
				Slot(o);
			}
		}

		public void AddUshort(int o, ushort x, ushort d)
		{
			if (ForceDefaults || x != d)
			{
				AddUshort(x);
				Slot(o);
			}
		}

		public void AddUshort(int o, ushort? x)
		{
			if (x.HasValue)
			{
				AddUshort(x.Value);
				Slot(o);
			}
		}

		public void AddInt(int o, int x, int d)
		{
			if (ForceDefaults || x != d)
			{
				AddInt(x);
				Slot(o);
			}
		}

		public void AddInt(int o, int? x)
		{
			if (x.HasValue)
			{
				AddInt(x.Value);
				Slot(o);
			}
		}

		public void AddUint(int o, uint x, uint d)
		{
			if (ForceDefaults || x != d)
			{
				AddUint(x);
				Slot(o);
			}
		}

		public void AddUint(int o, uint? x)
		{
			if (x.HasValue)
			{
				AddUint(x.Value);
				Slot(o);
			}
		}

		public void AddLong(int o, long x, long d)
		{
			if (ForceDefaults || x != d)
			{
				AddLong(x);
				Slot(o);
			}
		}

		public void AddLong(int o, long? x)
		{
			if (x.HasValue)
			{
				AddLong(x.Value);
				Slot(o);
			}
		}

		public void AddUlong(int o, ulong x, ulong d)
		{
			if (ForceDefaults || x != d)
			{
				AddUlong(x);
				Slot(o);
			}
		}

		public void AddUlong(int o, ulong? x)
		{
			if (x.HasValue)
			{
				AddUlong(x.Value);
				Slot(o);
			}
		}

		public void AddFloat(int o, float x, double d)
		{
			if (ForceDefaults || (double)x != d)
			{
				AddFloat(x);
				Slot(o);
			}
		}

		public void AddFloat(int o, float? x)
		{
			if (x.HasValue)
			{
				AddFloat(x.Value);
				Slot(o);
			}
		}

		public void AddDouble(int o, double x, double d)
		{
			if (ForceDefaults || x != d)
			{
				AddDouble(x);
				Slot(o);
			}
		}

		public void AddDouble(int o, double? x)
		{
			if (x.HasValue)
			{
				AddDouble(x.Value);
				Slot(o);
			}
		}

		public void AddOffset(int o, int x, int d)
		{
			if (x != d)
			{
				AddOffset(x);
				Slot(o);
			}
		}

		public StringOffset CreateString(string s)
		{
			if (s == null)
			{
				return new StringOffset(0);
			}
			NotNested();
			AddByte(0);
			int byteCount = Encoding.UTF8.GetByteCount(s);
			StartVector(1, byteCount, 1);
			_bb.PutStringUTF8(_space -= byteCount, s);
			return new StringOffset(EndVector().Value);
		}

		public StringOffset CreateSharedString(string s)
		{
			if (s == null)
			{
				return new StringOffset(0);
			}
			if (_sharedStringMap == null)
			{
				_sharedStringMap = new Dictionary<string, StringOffset>();
			}
			if (_sharedStringMap.ContainsKey(s))
			{
				return _sharedStringMap[s];
			}
			StringOffset stringOffset = CreateString(s);
			_sharedStringMap.Add(s, stringOffset);
			return stringOffset;
		}

		public void AddStruct(int voffset, int x, int d)
		{
			if (x != d)
			{
				Nested(x);
				Slot(voffset);
			}
		}

		public int EndTable()
		{
			if (_vtableSize < 0)
			{
				throw new InvalidOperationException("Flatbuffers: calling EndTable without a StartTable");
			}
			AddInt(0);
			int offset = Offset;
			int num = _vtableSize - 1;
			while (num >= 0 && _vtable[num] == 0)
			{
				num--;
			}
			int num2 = num + 1;
			while (num >= 0)
			{
				short x = (short)((_vtable[num] != 0) ? (offset - _vtable[num]) : 0);
				AddShort(x);
				_vtable[num] = 0;
				num--;
			}
			AddShort((short)(offset - _objectStart));
			AddShort((short)((num2 + 2) * 2));
			int num3 = 0;
			for (num = 0; num < _numVtables; num++)
			{
				int num4 = _bb.Length - _vtables[num];
				int space = _space;
				short @short = _bb.GetShort(num4);
				if (@short != _bb.GetShort(space))
				{
					continue;
				}
				int num5 = 2;
				while (num5 < @short)
				{
					if (_bb.GetShort(num4 + num5) == _bb.GetShort(space + num5))
					{
						num5 += 2;
						continue;
					}
					goto IL_0118;
				}
				num3 = _vtables[num];
				break;
				IL_0118:;
			}
			if (num3 != 0)
			{
				_space = _bb.Length - offset;
				_bb.PutInt(_space, num3 - offset);
			}
			else
			{
				if (_numVtables == _vtables.Length)
				{
					int[] array = new int[_numVtables * 2];
					Array.Copy(_vtables, array, _vtables.Length);
					_vtables = array;
				}
				_vtables[_numVtables++] = Offset;
				_bb.PutInt(_bb.Length - offset, Offset - offset);
			}
			_vtableSize = -1;
			return offset;
		}

		public void Required(int table, int field)
		{
			int num = _bb.Length - table;
			int num2 = num - _bb.GetInt(num);
			if (_bb.GetShort(num2 + field) == 0)
			{
				throw new InvalidOperationException("FlatBuffers: field " + field + " must be set");
			}
		}

		protected void Finish(int rootTable, bool sizePrefix)
		{
			Prep(_minAlign, 4 + (sizePrefix ? 4 : 0));
			AddOffset(rootTable);
			if (sizePrefix)
			{
				AddInt(_bb.Length - _space);
			}
			_bb.Position = _space;
		}

		public void Finish(int rootTable)
		{
			Finish(rootTable, sizePrefix: false);
		}

		public void FinishSizePrefixed(int rootTable)
		{
			Finish(rootTable, sizePrefix: true);
		}

		public byte[] SizedByteArray()
		{
			return _bb.ToSizedArray();
		}

		protected void Finish(int rootTable, string fileIdentifier, bool sizePrefix)
		{
			Prep(_minAlign, 4 + (sizePrefix ? 4 : 0) + 4);
			if (fileIdentifier.Length != 4)
			{
				throw new ArgumentException("FlatBuffers: file identifier must be length " + 4, "fileIdentifier");
			}
			for (int num = 3; num >= 0; num--)
			{
				AddByte((byte)fileIdentifier[num]);
			}
			Finish(rootTable, sizePrefix);
		}

		public void Finish(int rootTable, string fileIdentifier)
		{
			Finish(rootTable, fileIdentifier, sizePrefix: false);
		}

		public void FinishSizePrefixed(int rootTable, string fileIdentifier)
		{
			Finish(rootTable, fileIdentifier, sizePrefix: true);
		}
	}
	public static class FlatBufferConstants
	{
		public const int FileIdentifierLength = 4;

		public const int SizePrefixLength = 4;

		public static void FLATBUFFERS_2_0_8()
		{
		}
	}
	public interface IFlatbufferObject
	{
		ByteBuffer ByteBuffer { get; }

		void __init(int _i, ByteBuffer _bb);
	}
	public struct Offset<T> where T : struct
	{
		public int Value;

		public Offset(int value)
		{
			Value = value;
		}
	}
	public struct StringOffset
	{
		public int Value;

		public StringOffset(int value)
		{
			Value = value;
		}
	}
	public struct VectorOffset
	{
		public int Value;

		public VectorOffset(int value)
		{
			Value = value;
		}
	}
	public struct Struct
	{
		public int bb_pos { get; private set; }

		public ByteBuffer bb { get; private set; }

		public Struct(int _i, ByteBuffer _bb)
		{
			this = default(Struct);
			bb = _bb;
			bb_pos = _i;
		}
	}
	public struct Table
	{
		public int bb_pos { get; private set; }

		public ByteBuffer bb { get; private set; }

		public ByteBuffer ByteBuffer => bb;

		public Table(int _i, ByteBuffer _bb)
		{
			this = default(Table);
			bb = _bb;
			bb_pos = _i;
		}

		public int __offset(int vtableOffset)
		{
			int num = bb_pos - bb.GetInt(bb_pos);
			if (vtableOffset >= bb.GetShort(num))
			{
				return 0;
			}
			return bb.GetShort(num + vtableOffset);
		}

		public static int __offset(int vtableOffset, int offset, ByteBuffer bb)
		{
			int num = bb.Length - offset;
			return bb.GetShort(num + vtableOffset - bb.GetInt(num)) + num;
		}

		public int __indirect(int offset)
		{
			return offset + bb.GetInt(offset);
		}

		public static int __indirect(int offset, ByteBuffer bb)
		{
			return offset + bb.GetInt(offset);
		}

		public string __string(int offset)
		{
			offset += bb.GetInt(offset);
			int @int = bb.GetInt(offset);
			int startPos = offset + 4;
			return bb.GetStringUTF8(startPos, @int);
		}

		public int __vector_len(int offset)
		{
			offset += bb_pos;
			offset += bb.GetInt(offset);
			return bb.GetInt(offset);
		}

		public int __vector(int offset)
		{
			offset += bb_pos;
			return offset + bb.GetInt(offset) + 4;
		}

		public ArraySegment<byte>? __vector_as_arraysegment(int offset)
		{
			int num = __offset(offset);
			if (num == 0)
			{
				return null;
			}
			int pos = __vector(num);
			int len = __vector_len(num);
			return bb.ToArraySegment(pos, len);
		}

		public T[] __vector_as_array<T>(int offset) where T : struct
		{
			if (!BitConverter.IsLittleEndian)
			{
				throw new NotSupportedException("Getting typed arrays on a Big Endian system is not support");
			}
			int num = __offset(offset);
			if (num == 0)
			{
				return null;
			}
			int pos = __vector(num);
			int len = __vector_len(num);
			return bb.ToArray<T>(pos, len);
		}

		public T __union<T>(int offset) where T : struct, IFlatbufferObject
		{
			T result = new T();
			result.__init(__indirect(offset), bb);
			return result;
		}

		public static bool __has_identifier(ByteBuffer bb, string ident)
		{
			if (ident.Length != 4)
			{
				throw new ArgumentException("FlatBuffers: file identifier must be length " + 4, "ident");
			}
			for (int i = 0; i < 4; i++)
			{
				if (ident[i] != bb.Get(bb.Position + 4 + i))
				{
					return false;
				}
			}
			return true;
		}

		public static int CompareStrings(int offset_1, int offset_2, ByteBuffer bb)
		{
			offset_1 += bb.GetInt(offset_1);
			offset_2 += bb.GetInt(offset_2);
			int @int = bb.GetInt(offset_1);
			int int2 = bb.GetInt(offset_2);
			int num = offset_1 + 4;
			int num2 = offset_2 + 4;
			int num3 = Math.Min(@int, int2);
			for (int i = 0; i < num3; i++)
			{
				byte b = bb.Get(i + num);
				byte b2 = bb.Get(i + num2);
				if (b != b2)
				{
					return b - b2;
				}
			}
			return @int - int2;
		}

		public static int CompareStrings(int offset_1, byte[] key, ByteBuffer bb)
		{
			offset_1 += bb.GetInt(offset_1);
			int @int = bb.GetInt(offset_1);
			int num = key.Length;
			int num2 = offset_1 + 4;
			int num3 = Math.Min(@int, num);
			for (int i = 0; i < num3; i++)
			{
				byte b = bb.Get(i + num2);
				if (b != key[i])
				{
					return b - key[i];
				}
			}
			return @int - num;
		}
	}
}
namespace Bwr
{
	[Flags]
	public enum ButtonPress : byte
	{
		A = 1,
		B = 2,
		MENU = 4,
		SECONDARY_MENU = 8,
		THUMB_STICK = 0x10,
		PRIMARY_INTERACTION = 0x20,
		SECONDARY_INTERACTION = 0x40,
		GRABBED_STATE = 0x80
	}
	public struct ChangedSetting : IFlatbufferObject
	{
		private Struct __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public SettingType Type => (SettingType)__p.bb.Get(__p.bb_pos);

		public float Value => __p.bb.GetFloat(__p.bb_pos + 4);

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Struct(_i, _bb);
		}

		public ChangedSetting __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public static Offset<ChangedSetting> CreateChangedSetting(FlatBufferBuilder builder, SettingType Type, float Value)
		{
			builder.Prep(4, 8);
			builder.PutFloat(Value);
			builder.Pad(3);
			builder.PutByte((byte)Type);
			return new Offset<ChangedSetting>(builder.Offset);
		}
	}
	public struct ControllerInput : IFlatbufferObject
	{
		private Struct __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public byte Buttons => __p.bb.Get(__p.bb_pos);

		public Vector2 Thumbstick => default(Vector2).__assign(__p.bb_pos + 4, __p.bb);

		public Transform Transform => default(Transform).__assign(__p.bb_pos + 12, __p.bb);

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Struct(_i, _bb);
		}

		public ControllerInput __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public static Offset<ControllerInput> CreateControllerInput(FlatBufferBuilder builder, byte Buttons, float thumbstick_X, float thumbstick_Y, float transform_position_X, float transform_position_Y, float transform_position_Z, float transform_rotation_euler_X, float transform_rotation_euler_Y, float transform_rotation_euler_Z)
		{
			builder.Prep(4, 36);
			builder.Prep(4, 24);
			builder.Prep(4, 12);
			builder.PutFloat(transform_rotation_euler_Z);
			builder.PutFloat(transform_rotation_euler_Y);
			builder.PutFloat(transform_rotation_euler_X);
			builder.Prep(4, 12);
			builder.PutFloat(transform_position_Z);
			builder.PutFloat(transform_position_Y);
			builder.PutFloat(transform_position_X);
			builder.Prep(4, 8);
			builder.PutFloat(thumbstick_Y);
			builder.PutFloat(thumbstick_X);
			builder.Pad(3);
			builder.PutByte(Buttons);
			return new Offset<ControllerInput>(builder.Offset);
		}
	}
	public struct Frame : IFlatbufferObject
	{
		private Table __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public float Time
		{
			get
			{
				int num = __p.__offset(4);
				if (num == 0)
				{
					return 0f;
				}
				return __p.bb.GetFloat(num + __p.bb_pos);
			}
		}

		public byte SkippedFrames
		{
			get
			{
				int num = __p.__offset(6);
				if (num == 0)
				{
					return 0;
				}
				return __p.bb.Get(num + __p.bb_pos);
			}
		}

		public int ChangedSettingsLength
		{
			get
			{
				int num = __p.__offset(8);
				if (num == 0)
				{
					return 0;
				}
				return __p.__vector_len(num);
			}
		}

		public VrInput? VrInput
		{
			get
			{
				int num = __p.__offset(10);
				if (num == 0)
				{
					return null;
				}
				return default(VrInput).__assign(num + __p.bb_pos, __p.bb);
			}
		}

		public PlayerState? PlayerState
		{
			get
			{
				int num = __p.__offset(12);
				if (num == 0)
				{
					return null;
				}
				return default(PlayerState).__assign(num + __p.bb_pos, __p.bb);
			}
		}

		public int InventoryLength
		{
			get
			{
				int num = __p.__offset(14);
				if (num == 0)
				{
					return 0;
				}
				return __p.__vector_len(num);
			}
		}

		public static void ValidateVersion()
		{
			FlatBufferConstants.FLATBUFFERS_2_0_8();
		}

		public static Frame GetRootAsFrame(ByteBuffer _bb)
		{
			return GetRootAsFrame(_bb, default(Frame));
		}

		public static Frame GetRootAsFrame(ByteBuffer _bb, Frame obj)
		{
			return obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb);
		}

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Table(_i, _bb);
		}

		public Frame __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public ChangedSetting? ChangedSettings(int j)
		{
			int num = __p.__offset(8);
			if (num == 0)
			{
				return null;
			}
			return default(ChangedSetting).__assign(__p.__vector(num) + j * 8, __p.bb);
		}

		public ItemInSlot? Inventory(int j)
		{
			int num = __p.__offset(14);
			if (num == 0)
			{
				return null;
			}
			return default(ItemInSlot).__assign(__p.__vector(num) + j * 2, __p.bb);
		}

		public static void StartFrame(FlatBufferBuilder builder)
		{
			builder.StartTable(6);
		}

		public static void AddTime(FlatBufferBuilder builder, float time)
		{
			builder.AddFloat(0, time, 0.0);
		}

		public static void AddSkippedFrames(FlatBufferBuilder builder, byte skippedFrames)
		{
			builder.AddByte(1, skippedFrames, 0);
		}

		public static void AddChangedSettings(FlatBufferBuilder builder, VectorOffset changedSettingsOffset)
		{
			builder.AddOffset(2, changedSettingsOffset.Value, 0);
		}

		public static void StartChangedSettingsVector(FlatBufferBuilder builder, int numElems)
		{
			builder.StartVector(8, numElems, 4);
		}

		public static void AddVrInput(FlatBufferBuilder builder, Offset<VrInput> vrInputOffset)
		{
			builder.AddStruct(3, vrInputOffset.Value, 0);
		}

		public static void AddPlayerState(FlatBufferBuilder builder, Offset<PlayerState> playerStateOffset)
		{
			builder.AddStruct(4, playerStateOffset.Value, 0);
		}

		public static void AddInventory(FlatBufferBuilder builder, VectorOffset inventoryOffset)
		{
			builder.AddOffset(5, inventoryOffset.Value, 0);
		}

		public static void StartInventoryVector(FlatBufferBuilder builder, int numElems)
		{
			builder.StartVector(2, numElems, 1);
		}

		public static Offset<Frame> EndFrame(FlatBufferBuilder builder)
		{
			return new Offset<Frame>(builder.EndTable());
		}
	}
	public enum GameMode : byte
	{
		NONE,
		SPEEDRUN,
		ANY_PERCENT,
		NO_MAJOR_GLITCHES,
		NEWGAME_PLUS,
		HUNDRED_PERCENT,
		BLINDFOLDED,
		GRIPLESS,
		LEFT_CONTROLLER_GRIPLESS,
		RIGHT_CONTROLLER_GRIPLESS,
		ARMLESS
	}
	public struct HeadsetInput : IFlatbufferObject
	{
		private Struct __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public Transform Transform => default(Transform).__assign(__p.bb_pos, __p.bb);

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Struct(_i, _bb);
		}

		public HeadsetInput __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public static Offset<HeadsetInput> CreateHeadsetInput(FlatBufferBuilder builder, float transform_position_X, float transform_position_Y, float transform_position_Z, float transform_rotation_euler_X, float transform_rotation_euler_Y, float transform_rotation_euler_Z)
		{
			builder.Prep(4, 24);
			builder.Prep(4, 24);
			builder.Prep(4, 12);
			builder.PutFloat(transform_rotation_euler_Z);
			builder.PutFloat(transform_rotation_euler_Y);
			builder.PutFloat(transform_rotation_euler_X);
			builder.Prep(4, 12);
			builder.PutFloat(transform_position_Z);
			builder.PutFloat(transform_position_Y);
			builder.PutFloat(transform_position_X);
			return new Offset<HeadsetInput>(builder.Offset);
		}
	}
	public enum InventorySlot : byte
	{
		LEFT_SHOULDER,
		RIGHT_SHOULDER,
		LEFT_UNDERARM,
		RIGHT_UNDERARM,
		BUTT
	}
	public enum Item : byte
	{
		NONE
	}
	public struct ItemInSlot : IFlatbufferObject
	{
		private Struct __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public InventorySlot Slot => (InventorySlot)__p.bb.Get(__p.bb_pos);

		public Item Item => (Item)__p.bb.Get(__p.bb_pos + 1);

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Struct(_i, _bb);
		}

		public ItemInSlot __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public static Offset<ItemInSlot> CreateItemInSlot(FlatBufferBuilder builder, InventorySlot Slot, Item Item)
		{
			builder.Prep(1, 2);
			builder.PutByte((byte)Item);
			builder.PutByte((byte)Slot);
			return new Offset<ItemInSlot>(builder.Offset);
		}
	}
	public struct Level : IFlatbufferObject
	{
		private Table __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public float StartTime
		{
			get
			{
				int num = __p.__offset(4);
				if (num == 0)
				{
					return 0f;
				}
				return __p.bb.GetFloat(num + __p.bb_pos);
			}
		}

		public float Duration
		{
			get
			{
				int num = __p.__offset(6);
				if (num == 0)
				{
					return 0f;
				}
				return __p.bb.GetFloat(num + __p.bb_pos);
			}
		}

		public float LoadDuration
		{
			get
			{
				int num = __p.__offset(8);
				if (num == 0)
				{
					return 0f;
				}
				return __p.bb.GetFloat(num + __p.bb_pos);
			}
		}

		public bool Completed
		{
			get
			{
				int num = __p.__offset(10);
				if (num == 0)
				{
					return false;
				}
				return __p.bb.Get(num + __p.bb_pos) != 0;
			}
		}

		public int SceneIndex
		{
			get
			{
				int num = __p.__offset(12);
				if (num == 0)
				{
					return 0;
				}
				return __p.bb.GetInt(num + __p.bb_pos);
			}
		}

		public int FrameOffset
		{
			get
			{
				int num = __p.__offset(14);
				if (num == 0)
				{
					return 0;
				}
				return __p.bb.GetInt(num + __p.bb_pos);
			}
		}

		public static void ValidateVersion()
		{
			FlatBufferConstants.FLATBUFFERS_2_0_8();
		}

		public static Level GetRootAsLevel(ByteBuffer _bb)
		{
			return GetRootAsLevel(_bb, default(Level));
		}

		public static Level GetRootAsLevel(ByteBuffer _bb, Level obj)
		{
			return obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb);
		}

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Table(_i, _bb);
		}

		public Level __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public static Offset<Level> CreateLevel(FlatBufferBuilder builder, float start_time = 0f, float duration = 0f, float load_duration = 0f, bool completed = false, int scene_index = 0, int frame_offset = 0)
		{
			builder.StartTable(6);
			AddFrameOffset(builder, frame_offset);
			AddSceneIndex(builder, scene_index);
			AddLoadDuration(builder, load_duration);
			AddDuration(builder, duration);
			AddStartTime(builder, start_time);
			AddCompleted(builder, completed);
			return EndLevel(builder);
		}

		public static void StartLevel(FlatBufferBuilder builder)
		{
			builder.StartTable(6);
		}

		public static void AddStartTime(FlatBufferBuilder builder, float startTime)
		{
			builder.AddFloat(0, startTime, 0.0);
		}

		public static void AddDuration(FlatBufferBuilder builder, float duration)
		{
			builder.AddFloat(1, duration, 0.0);
		}

		public static void AddLoadDuration(FlatBufferBuilder builder, float loadDuration)
		{
			builder.AddFloat(2, loadDuration, 0.0);
		}

		public static void AddCompleted(FlatBufferBuilder builder, bool completed)
		{
			builder.AddBool(3, completed, d: false);
		}

		public static void AddSceneIndex(FlatBufferBuilder builder, int sceneIndex)
		{
			builder.AddInt(4, sceneIndex, 0);
		}

		public static void AddFrameOffset(FlatBufferBuilder builder, int frameOffset)
		{
			builder.AddInt(5, frameOffset, 0);
		}

		public static Offset<Level> EndLevel(FlatBufferBuilder builder)
		{
			return new Offset<Level>(builder.EndTable());
		}
	}
	public struct Metadata : IFlatbufferObject
	{
		private Table __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public GameMode GameMode
		{
			get
			{
				int num = __p.__offset(4);
				if (num == 0)
				{
					return GameMode.NONE;
				}
				return (GameMode)__p.bb.Get(num + __p.bb_pos);
			}
		}

		public long StartTime
		{
			get
			{
				int num = __p.__offset(6);
				if (num == 0)
				{
					return 0L;
				}
				return __p.bb.GetLong(num + __p.bb_pos);
			}
		}

		public bool Completed
		{
			get
			{
				int num = __p.__offset(8);
				if (num == 0)
				{
					return false;
				}
				return __p.bb.Get(num + __p.bb_pos) != 0;
			}
		}

		public float Duration
		{
			get
			{
				int num = __p.__offset(10);
				if (num == 0)
				{
					return 0f;
				}
				return __p.bb.GetFloat(num + __p.bb_pos);
			}
		}

		public int LevelsLength
		{
			get
			{
				int num = __p.__offset(12);
				if (num == 0)
				{
					return 0;
				}
				return __p.__vector_len(num);
			}
		}

		public static void ValidateVersion()
		{
			FlatBufferConstants.FLATBUFFERS_2_0_8();
		}

		public static Metadata GetRootAsMetadata(ByteBuffer _bb)
		{
			return GetRootAsMetadata(_bb, default(Metadata));
		}

		public static Metadata GetRootAsMetadata(ByteBuffer _bb, Metadata obj)
		{
			return obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb);
		}

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Table(_i, _bb);
		}

		public Metadata __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public Level? Levels(int j)
		{
			int num = __p.__offset(12);
			if (num == 0)
			{
				return null;
			}
			return default(Level).__assign(__p.__indirect(__p.__vector(num) + j * 4), __p.bb);
		}

		public static Offset<Metadata> CreateMetadata(FlatBufferBuilder builder, GameMode game_mode = GameMode.NONE, long start_time = 0L, bool completed = false, float duration = 0f, VectorOffset levelsOffset = default(VectorOffset))
		{
			builder.StartTable(5);
			AddStartTime(builder, start_time);
			AddLevels(builder, levelsOffset);
			AddDuration(builder, duration);
			AddCompleted(builder, completed);
			AddGameMode(builder, game_mode);
			return EndMetadata(builder);
		}

		public static void StartMetadata(FlatBufferBuilder builder)
		{
			builder.StartTable(5);
		}

		public static void AddGameMode(FlatBufferBuilder builder, GameMode gameMode)
		{
			builder.AddByte(0, (byte)gameMode, 0);
		}

		public static void AddStartTime(FlatBufferBuilder builder, long startTime)
		{
			builder.AddLong(1, startTime, 0L);
		}

		public static void AddCompleted(FlatBufferBuilder builder, bool completed)
		{
			builder.AddBool(2, completed, d: false);
		}

		public static void AddDuration(FlatBufferBuilder builder, float duration)
		{
			builder.AddFloat(3, duration, 0.0);
		}

		public static void AddLevels(FlatBufferBuilder builder, VectorOffset levelsOffset)
		{
			builder.AddOffset(4, levelsOffset.Value, 0);
		}

		public static VectorOffset CreateLevelsVector(FlatBufferBuilder builder, Offset<Level>[] data)
		{
			builder.StartVector(4, data.Length, 4);
			for (int num = data.Length - 1; num >= 0; num--)
			{
				builder.AddOffset(data[num].Value);
			}
			return builder.EndVector();
		}

		public static VectorOffset CreateLevelsVectorBlock(FlatBufferBuilder builder, Offset<Level>[] data)
		{
			builder.StartVector(4, data.Length, 4);
			builder.Add(data);
			return builder.EndVector();
		}

		public static VectorOffset CreateLevelsVectorBlock(FlatBufferBuilder builder, ArraySegment<Offset<Level>> data)
		{
			builder.StartVector(4, data.Count, 4);
			builder.Add(data);
			return builder.EndVector();
		}

		public static VectorOffset CreateLevelsVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes)
		{
			builder.StartVector(1, sizeInBytes, 1);
			builder.Add<Offset<Level>>(dataPtr, sizeInBytes);
			return builder.EndVector();
		}

		public static void StartLevelsVector(FlatBufferBuilder builder, int numElems)
		{
			builder.StartVector(4, numElems, 4);
		}

		public static Offset<Metadata> EndMetadata(FlatBufferBuilder builder)
		{
			int num = builder.EndTable();
			builder.Required(num, 12);
			return new Offset<Metadata>(num);
		}
	}
	public struct PlayerState : IFlatbufferObject
	{
		private Struct __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public Vector3 BodyPosition => default(Vector3).__assign(__p.bb_pos, __p.bb);

		public float RootRotation => __p.bb.GetFloat(__p.bb_pos + 12);

		public float FeetOffset => __p.bb.GetFloat(__p.bb_pos + 16);

		public Vector3 HeadPosition => default(Vector3).__assign(__p.bb_pos + 20, __p.bb);

		public Transform LeftHand => default(Transform).__assign(__p.bb_pos + 32, __p.bb);

		public Transform RightHand => default(Transform).__assign(__p.bb_pos + 56, __p.bb);

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Struct(_i, _bb);
		}

		public PlayerState __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public static Offset<PlayerState> CreatePlayerState(FlatBufferBuilder builder, float body_position_X, float body_position_Y, float body_position_Z, float RootRotation, float FeetOffset, float head_position_X, float head_position_Y, float head_position_Z, float left_hand_position_X, float left_hand_position_Y, float left_hand_position_Z, float left_hand_rotation_euler_X, float left_hand_rotation_euler_Y, float left_hand_rotation_euler_Z, float right_hand_position_X, float right_hand_position_Y, float right_hand_position_Z, float right_hand_rotation_euler_X, float right_hand_rotation_euler_Y, float right_hand_rotation_euler_Z)
		{
			builder.Prep(4, 80);
			builder.Prep(4, 24);
			builder.Prep(4, 12);
			builder.PutFloat(right_hand_rotation_euler_Z);
			builder.PutFloat(right_hand_rotation_euler_Y);
			builder.PutFloat(right_hand_rotation_euler_X);
			builder.Prep(4, 12);
			builder.PutFloat(right_hand_position_Z);
			builder.PutFloat(right_hand_position_Y);
			builder.PutFloat(right_hand_position_X);
			builder.Prep(4, 24);
			builder.Prep(4, 12);
			builder.PutFloat(left_hand_rotation_euler_Z);
			builder.PutFloat(left_hand_rotation_euler_Y);
			builder.PutFloat(left_hand_rotation_euler_X);
			builder.Prep(4, 12);
			builder.PutFloat(left_hand_position_Z);
			builder.PutFloat(left_hand_position_Y);
			builder.PutFloat(left_hand_position_X);
			builder.Prep(4, 12);
			builder.PutFloat(head_position_Z);
			builder.PutFloat(head_position_Y);
			builder.PutFloat(head_position_X);
			builder.PutFloat(FeetOffset);
			builder.PutFloat(RootRotation);
			builder.Prep(4, 12);
			builder.PutFloat(body_position_Z);
			builder.PutFloat(body_position_Y);
			builder.PutFloat(body_position_X);
			return new Offset<PlayerState>(builder.Offset);
		}
	}
	public enum SettingType : byte
	{
		REFRESH_RATE,
		BELT_RIGHT_SIDE,
		IS_INVERTED,
		IS_RIGHT_HANDED,
		JOY_SENSITIVITY,
		LOCO_CURVE,
		LOCO_DEGREES_PER_SNAP,
		LOCO_DIRECTION,
		LOCO_SNAP_DEGREES_PER_FRAME,
		OFFSET_FLOOR,
		OFFSET_SITTING,
		PHYSICS_UPDATE_RATE,
		PLAYER_HEIGHT,
		SNAP_ENABLED,
		STANDING,
		VIRTUAL_CROUCHING
	}
	public struct Transform : IFlatbufferObject
	{
		private Struct __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public Vector3 Position => default(Vector3).__assign(__p.bb_pos, __p.bb);

		public Vector3 RotationEuler => default(Vector3).__assign(__p.bb_pos + 12, __p.bb);

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Struct(_i, _bb);
		}

		public Transform __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public static Offset<Transform> CreateTransform(FlatBufferBuilder builder, float position_X, float position_Y, float position_Z, float rotation_euler_X, float rotation_euler_Y, float rotation_euler_Z)
		{
			builder.Prep(4, 24);
			builder.Prep(4, 12);
			builder.PutFloat(rotation_euler_Z);
			builder.PutFloat(rotation_euler_Y);
			builder.PutFloat(rotation_euler_X);
			builder.Prep(4, 12);
			builder.PutFloat(position_Z);
			builder.PutFloat(position_Y);
			builder.PutFloat(position_X);
			return new Offset<Transform>(builder.Offset);
		}
	}
	public struct Vector2 : IFlatbufferObject
	{
		private Struct __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public float X => __p.bb.GetFloat(__p.bb_pos);

		public float Y => __p.bb.GetFloat(__p.bb_pos + 4);

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Struct(_i, _bb);
		}

		public Vector2 __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public static Offset<Vector2> CreateVector2(FlatBufferBuilder builder, float X, float Y)
		{
			builder.Prep(4, 8);
			builder.PutFloat(Y);
			builder.PutFloat(X);
			return new Offset<Vector2>(builder.Offset);
		}
	}
	public struct Vector3 : IFlatbufferObject
	{
		private Struct __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public float X => __p.bb.GetFloat(__p.bb_pos);

		public float Y => __p.bb.GetFloat(__p.bb_pos + 4);

		public float Z => __p.bb.GetFloat(__p.bb_pos + 8);

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Struct(_i, _bb);
		}

		public Vector3 __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public static Offset<Vector3> CreateVector3(FlatBufferBuilder builder, float X, float Y, float Z)
		{
			builder.Prep(4, 12);
			builder.PutFloat(Z);
			builder.PutFloat(Y);
			builder.PutFloat(X);
			return new Offset<Vector3>(builder.Offset);
		}
	}
	public struct VrInput : IFlatbufferObject
	{
		private Struct __p;

		public ByteBuffer ByteBuffer => __p.bb;

		public HeadsetInput Headset => default(HeadsetInput).__assign(__p.bb_pos, __p.bb);

		public ControllerInput LeftController => default(ControllerInput).__assign(__p.bb_pos + 24, __p.bb);

		public ControllerInput RightController => default(ControllerInput).__assign(__p.bb_pos + 60, __p.bb);

		public void __init(int _i, ByteBuffer _bb)
		{
			__p = new Struct(_i, _bb);
		}

		public VrInput __assign(int _i, ByteBuffer _bb)
		{
			__init(_i, _bb);
			return this;
		}

		public static Offset<VrInput> CreateVrInput(FlatBufferBuilder builder, float headset_transform_position_X, float headset_transform_position_Y, float headset_transform_position_Z, float headset_transform_rotation_euler_X, float headset_transform_rotation_euler_Y, float headset_transform_rotation_euler_Z, byte left_controller_Buttons, float left_controller_thumbstick_X, float left_controller_thumbstick_Y, float left_controller_transform_position_X, float left_controller_transform_position_Y, float left_controller_transform_position_Z, float left_controller_transform_rotation_euler_X, float left_controller_transform_rotation_euler_Y, float left_controller_transform_rotation_euler_Z, byte right_controller_Buttons, float right_controller_thumbstick_X, float right_controller_thumbstick_Y, float right_controller_transform_position_X, float right_controller_transform_position_Y, float right_controller_transform_position_Z, float right_controller_transform_rotation_euler_X, float right_controller_transform_rotation_euler_Y, float right_controller_transform_rotation_euler_Z)
		{
			builder.Prep(4, 96);
			builder.Prep(4, 36);
			builder.Prep(4, 24);
			builder.Prep(4, 12);
			builder.PutFloat(right_controller_transform_rotation_euler_Z);
			builder.PutFloat(right_controller_transform_rotation_euler_Y);
			builder.PutFloat(right_controller_transform_rotation_euler_X);
			builder.Prep(4, 12);
			builder.PutFloat(right_controller_transform_position_Z);
			builder.PutFloat(right_controller_transform_position_Y);
			builder.PutFloat(right_controller_transform_position_X);
			builder.Prep(4, 8);
			builder.PutFloat(right_controller_thumbstick_Y);
			builder.PutFloat(right_controller_thumbstick_X);
			builder.Pad(3);
			builder.PutByte(right_controller_Buttons);
			builder.Prep(4, 36);
			builder.Prep(4, 24);
			builder.Prep(4, 12);
			builder.PutFloat(left_controller_transform_rotation_euler_Z);
			builder.PutFloat(left_controller_transform_rotation_euler_Y);
			builder.PutFloat(left_controller_transform_rotation_euler_X);
			builder.Prep(4, 12);
			builder.PutFloat(left_controller_transform_position_Z);
			builder.PutFloat(left_controller_transform_position_Y);
			builder.PutFloat(left_controller_transform_position_X);
			builder.Prep(4, 8);
			builder.PutFloat(left_controller_thumbstick_Y);
			builder.PutFloat(left_controller_thumbstick_X);
			builder.Pad(3);
			builder.PutByte(left_controller_Buttons);
			builder.Prep(4, 24);
			builder.Prep(4, 24);
			builder.Prep(4, 12);
			builder.PutFloat(headset_transform_rotation_euler_Z);
			builder.PutFloat(headset_transform_rotation_euler_Y);
			builder.PutFloat(headset_transform_rotation_euler_X);
			builder.Prep(4, 12);
			builder.PutFloat(headset_transform_position_Z);
			builder.PutFloat(headset_transform_position_Y);
			builder.PutFloat(headset_transform_position_X);
			return new Offset<VrInput>(builder.Offset);
		}
	}
}
namespace Sst
{
	internal static class AppVersion
	{
		public const string Value = "2.5.0";
	}
	public static class BuildInfo
	{
		public const string Name = "SpeedrunTools";

		public const string Author = "jakzo";

		public const string Company = null;

		public const string Version = "2.5.0";

		public const string DownloadLink = "https://boneworks.thunderstore.io/package/jakzo/SpeedrunTools/";

		public const string Developer = "Stress Level Zero";

		public const string GameName = "BONEWORKS";
	}
	public class Mod : MelonMod
	{
		[HarmonyPatch(typeof(BoneworksSceneManager), "LoadNext")]
		private class BoneworksSceneManager_LoadNext_Patch
		{
			[HarmonyPrefix]
			internal static void Prefix()
			{
				GameState.didPrevLevelComplete = true;
			}
		}

		[HarmonyPatch(typeof(BoneworksSceneManager), "LoadScene", new Type[] { typeof(string) })]
		private class BoneworksSceneManager_LoadScene_Patch
		{
			[HarmonyPrefix]
			internal static void Prefix(string sceneName)
			{
				Dbg.Log("LoadScene: " + sceneName);
				GameState.nextSceneIdx = Utils.SCENE_INDEXES_BY_NAME[sceneName];
			}
		}

		[HarmonyPatch(typeof(CVRCompositor), "FadeGrid")]
		private class CVRCompositor_FadeGrid_Patch
		{
			[HarmonyPrefix]
			internal static void Prefix(float fSeconds, bool bFadeIn)
			{
				if (bFadeIn)
				{
					GameState.prevSceneIdx = GameState.currentSceneIdx;
					int prevSceneIdx = GameState.currentSceneIdx.GetValueOrDefault();
					GameState.currentSceneIdx = null;
					GameState.rigManager = null;
					OnFeatureCallback(delegate(Feature feature)
					{
						feature.OnLoadingScreen(GameState.nextSceneIdx.GetValueOrDefault(), prevSceneIdx);
					});
				}
				else
				{
					GameState.currentSceneIdx = GameState.nextSceneIdx;
					GameState.nextSceneIdx = null;
					GameState.rigManager = Boneworks.GetRigManager();
					OnFeatureCallback(delegate(Feature feature)
					{
						feature.OnLevelStart(GameState.currentSceneIdx.GetValueOrDefault());
					});
					GameState.didPrevLevelComplete = false;
				}
			}
		}

		[HarmonyPatch(typeof(Controller), "CacheInputs")]
		private class Controller_CacheInputs_Patch
		{
			[HarmonyPostfix]
			internal static void Postfix(Controller __instance)
			{
				Gripless.OnCacheInputs(__instance);
				Armless.OnCacheInputs(__instance);
			}
		}

		[HarmonyPatch(typeof(Controller), "ProcessFingers")]
		private class Controller_ProcessFingers_Patch
		{
			[HarmonyPostfix]
			internal static void Postfix(Controller __instance)
			{
				Gripless.OnProcessFingers(__instance);
				Armless.OnProcessFingers(__instance);
			}
		}

		[HarmonyPatch(typeof(Controller), "SolveGrip")]
		private class Controller_SolveGrip_Patch
		{
			[HarmonyPostfix]
			internal static void Postfix(Controller __instance)
			{
				Gripless.OnSolveGrip(__instance);
				Armless.OnSolveGrip(__instance);
			}
		}

		private static readonly Feature[] features = new Feature[23]
		{
			new Speedrun(),
			new RemoveBossClawRng(),
			new Teleport(),
			new Blindfold(),
			new Gripless(),
			new Armless(),
			new RestartLevel(),
			new ArenaSplitState(),
			new CollectibleRecorder(),
			new HundredPercentServer(),
			new Speedometer(),
			new Sst.Features.Timer(),
			new Sst.Features.Replay(),
			new DebugGunFly(),
			new ControlTesting(),
			new Fps(),
			new Tas(),
			new FixPhysicsRate(),
			new DebugColliders(),
			new LootChanceViewer(),
			new MuseumBhopTimer(),
			new Sst.Features.DebugStats(),
			new GripFlyFinder()
		};

		private static List<Feature> enabledFeatures = new List<Feature>();

		private static Dictionary<Feature, Pref<bool>> featureEnabledPrefs = new Dictionary<Feature, Pref<bool>>();

		private static Hotkeys s_hotkeys = new Hotkeys();

		public static bool IsRunActive = false;

		public static GameState GameState = default(GameState);

		private static void EnableFeature(Feature feature)
		{
			if (enabledFeatures.Contains(feature))
			{
				return;
			}
			MelonLogger.Msg("Enabling feature: " + feature.GetType().Name);
			enabledFeatures.Add(feature);
			feature.IsEnabled = true;
			foreach (Hotkey hotkey in feature.Hotkeys)
			{
				s_hotkeys.AddHotkey(feature, hotkey);
			}
			feature.OnEnabled();
		}

		private static void DisableFeature(Feature feature)
		{
			if (!enabledFeatures.Contains(feature))
			{
				return;
			}
			MelonLogger.Msg("Disabling feature: " + feature.GetType().Name);
			enabledFeatures.Remove(feature);
			feature.IsEnabled = false;
			foreach (Hotkey hotkey in feature.Hotkeys)
			{
				s_hotkeys.RemoveHotkey(hotkey);
			}
			feature.OnDisabled();
		}

		private static void OnFeatureCallback(Action<Feature> action)
		{
			foreach (Feature enabledFeature in enabledFeatures)
			{
				if (!IsRunActive || enabledFeature.IsAllowedInRuns)
				{
					try
					{
						action(enabledFeature);
					}
					catch (Exception ex)
					{
						MelonLogger.Error((object)ex);
					}
				}
			}
		}

		public override void OnApplicationStart()
		{
			Dbg.Init("SpeedrunTools");
			Directory.CreateDirectory(Utils.DIR);
			Utils.s_prefCategory = MelonPreferences.CreateCategory("SpeedrunTools");
			Feature[] array = features;
			foreach (Feature feature2 in array)
			{
				string name = feature2.GetType().Name;
				string text = (feature2.IsDev ? "Dev" : "");
				string text2 = (feature2.IsDev ? "dev " : "");
				Pref<bool> pref = new Pref<bool>
				{
					Id = "enable" + text + "Feature" + name,
					Name = "Enable " + text2 + "feature: " + name,
					DefaultValue = (feature2.IsEnabledByDefault && !feature2.IsDev)
				};
				pref.Create();
				featureEnabledPrefs[feature2] = pref;
				FieldInfo[] fields = feature2.GetType().GetFields();
				foreach (FieldInfo fieldInfo in fields)
				{
					Type type = Nullable.GetUnderlyingType(fieldInfo.FieldType) ?? fieldInfo.FieldType;
					if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Pref<>))
					{
						(fieldInfo.GetValue(feature2) as IPref).Create();
					}
				}
				if (pref.Read())
				{
					EnableFeature(feature2);
				}
			}
			Dbg.Log("OnApplicationStart");
			OnFeatureCallback(delegate(Feature feature)
			{
				feature.OnApplicationStart();
			});
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			Dbg.Log("OnSceneWasLoaded");
			Feature[] array = features;
			foreach (Feature feature2 in array)
			{
				if (featureEnabledPrefs[feature2].Read())
				{
					EnableFeature(feature2);
				}
				else
				{
					DisableFeature(feature2);
				}
			}
			OnFeatureCallback(delegate(Feature feature)
			{
				feature.OnSceneWasLoaded(buildIndex, sceneName);
			});
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			Dbg.Log("OnSceneWasInitialized");
			GameState.rigManager = Boneworks.GetRigManager();
			s_hotkeys.Init();
			OnFeatureCallback(delegate(Feature feature)
			{
				feature.OnSceneWasInitialized(buildIndex, sceneName);
			});
		}

		public override void OnUpdate()
		{
			s_hotkeys.OnUpdate();
			OnFeatureCallback(delegate(Feature feature)
			{
				feature.OnUpdate();
			});
		}

		public override void OnLateUpdate()
		{
			OnFeatureCallback(delegate(Feature feature)
			{
				feature.OnLateUpdate();
			});
		}

		public override void OnFixedUpdate()
		{
			OnFeatureCallback(delegate(Feature feature)
			{
				feature.OnFixedUpdate();
			});
		}
	}
	internal class Utils
	{
		public const string PREF_CATEGORY = "SpeedrunTools";

		public static readonly string DIR = Path.Combine(MelonUtils.UserDataDirectory, "SpeedrunTools");

		public static readonly string REPLAYS_DIR = Path.Combine(DIR, "replays");

		public const int SCENE_MENU_IDX = 1;

		public const string SCENE_INTRO_NAME = "scene_theatrigon_movie01";

		public static readonly Dictionary<string, int> SCENE_INDEXES_BY_NAME = new Dictionary<string, int>
		{
			["scene_introStart"] = 0,
			["scene_mainMenu"] = 1,
			["scene_MainMenu"] = 1,
			["Main Menu"] = 1,
			["scene_theatrigon_movie01"] = 2,
			["scene_breakroom"] = 3,
			["Breakroom"] = 3,
			["scene_museum"] = 4,
			["Museum"] = 4,
			["scene_streets"] = 5,
			["Streets"] = 5,
			["scene_runoff"] = 6,
			["Runoff"] = 6,
			["scene_sewerStation"] = 7,
			["Sewers"] = 7,
			["scene_warehouse"] = 8,
			["Warehouse"] = 8,
			["scene_subwayStation"] = 9,
			["Central Station"] = 9,
			["scene_tower"] = 10,
			["Tower"] = 10,
			["scene_towerBoss"] = 11,
			["Time Tower"] = 11,
			["scene_theatrigon_movie02"] = 12,
			["scene_dungeon"] = 13,
			["Dungeon"] = 13,
			["scene_arena"] = 14,
			["Arena"] = 14,
			["scene_throneRoom"] = 15,
			["Throne Room"] = 15,
			["arena_fantasy"] = 16,
			["scene_Tuscany"] = 17,
			["scene_redactedChamber"] = 18,
			["sandbox_handgunBox"] = 19,
			["sandbox_museumBasement"] = 20,
			["sandbox_blankBox"] = 21,
			["scene_hoverJunkers"] = 22,
			["zombie_warehouse"] = 23,
			["empty_scene"] = 24,
			["loadingScene"] = 25
		};

		public static readonly Dictionary<int, string> SCENE_NAME_BY_INDEX = GetSceneNamesByIndex();

		public static MelonPreferences_Category s_prefCategory;

		private static Dictionary<int, string> GetSceneNamesByIndex()
		{
			Dictionary<int, string> dictionary = new Dictionary<int, string>();
			foreach (KeyValuePair<string, int> item in SCENE_INDEXES_BY_NAME)
			{
				if (!dictionary.ContainsKey(item.Value))
				{
					dictionary.Add(item.Value, item.Key);
				}
			}
			return dictionary;
		}

		public static Vector3 GetPlayerPos()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)Mod.GameState.rigManager.gameWorldSkeletonRig).transform.position;
		}

		public static bool GetKeyControl()
		{
			if (!Input.GetKey((KeyCode)306))
			{
				return Input.GetKey((KeyCode)305);
			}
			return true;
		}
	}
	internal class Pref<T> : IPref
	{
		public string Name;

		public T DefaultValue;

		public string Id { get; set; }

		public void Create()
		{
			Utils.s_prefCategory.CreateEntry<T>(Id, DefaultValue, Name, (string)null, false, false, (ValueValidator)null, (string)null);
		}

		public T Read()
		{
			return Utils.s_prefCategory.GetEntry<T>(Id).Value;
		}
	}
	internal interface IPref
	{
		string Id { get; }

		void Create();
	}
	public class Hotkeys
	{
		private Dictionary<Hotkey, (Feature, bool)> _hotkeys = new Dictionary<Hotkey, (Feature, bool)>();

		private BaseController[] _controllers;

		public void Init()
		{
			Il2CppArrayBase<BaseController> controllerObjects = Object.FindObjectsOfType<BaseController>();
			_controllers = new string[2] { "left", "right" }.Select((string type) => "Controller (" + type + ")").Select((Func<string, BaseController>)delegate(string name)
			{
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Expected O, but got Unknown
				try
				{
					return ((IEnumerable<BaseController>)controllerObjects).First((BaseController controller) => ((Object)controller).name == name);
				}
				catch
				{
					string text = string.Join("", ((IEnumerable<BaseController>)controllerObjects).Select((BaseController controller) => "\n- " + ((Object)controller).name));
					MelonLogger.Warning("Could not find " + name + ". Hotkeys will not work until reloading the level. Found controllers are:" + text);
					return new BaseController();
				}
			}).ToArray();
		}

		public void AddHotkey(Feature feature, Hotkey hotkey)
		{
			if (!_hotkeys.ContainsKey(hotkey))
			{
				_hotkeys.Add(hotkey, (feature, false));
			}
		}

		public void RemoveHotkey(Hotkey hotkey)
		{
			_hotkeys.Remove(hotkey);
		}

		public void OnUpdate()
		{
			if (_controllers == null || _controllers.Length < 2)
			{
				return;
			}
			(int, Hotkey, Feature, bool)[] array = _hotkeys.Select((KeyValuePair<Hotkey, (Feature, bool)> entry, int i) => (i, entry.Key, entry.Value.Item1, entry.Value.Item2)).ToArray();
			for (int j = 0; j < array.Length; j++)
			{
				(int, Hotkey, Feature, bool) tuple = array[j];
				Hotkey item = tuple.Item2;
				Feature item2 = tuple.Item3;
				bool item3 = tuple.Item4;
				if (Mod.IsRunActive && !item2.IsAllowedInRuns)
				{
					continue;
				}
				if (item.Predicate(_controllers[0], _controllers[1]))
				{
					if (!item3)
					{
						_hotkeys[item] = (item2, true);
						item.Handler();
					}
				}
				else
				{
					_hotkeys[item] = (item2, false);
				}
			}
		}
	}
	public class Hotkey
	{
		public Func<BaseController, BaseController, bool> Predicate { get; set; }

		public Action Handler { get; set; }
	}
	public abstract class Feature
	{
		public List<Hotkey> Hotkeys = new List<Hotkey>();

		public bool IsAllowedInRuns;

		public bool IsEnabled;

		public bool IsEnabledByDefault = true;

		public bool IsDev;

		public virtual void OnApplicationStart()
		{
		}

		public virtual void OnLoadingScreen(int nextSceneIdx, int prevSceneIdx)
		{
		}

		public virtual void OnLevelStart(int sceneIdx)
		{
		}

		public virtual void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
		}

		public virtual void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
		}

		public virtual void OnUpdate()
		{
		}

		public virtual void OnLateUpdate()
		{
		}

		public virtual void OnFixedUpdate()
		{
		}

		public virtual void OnEnabled()
		{
		}

		public virtual void OnDisabled()
		{
		}
	}
	public struct GameState
	{
		public int? prevSceneIdx;

		public int? currentSceneIdx;

		public int? nextSceneIdx;

		public bool didPrevLevelComplete;

		public RigManager rigManager;
	}
	public class Dbg
	{
		private static Instance _logger;

		private static MelonPreferences_Entry<bool> _prefPrintDebugLogs;

		public static void Init(string prefCategoryId, Instance logger = null)
		{
			_logger = logger;
			_prefPrintDebugLogs = MelonPreferences.CreateCategory(prefCategoryId).CreateEntry<bool>("printDebugLogs", false, "Print debug logs", "Print debug logs to console", false, true, (ValueValidator)null, (string)null);
		}

		public static void Log(params object[] data)
		{
			if (_prefPrintDebugLogs.Value)
			{
				string text = "dbg: " + string.Join(" ", data.Select((object d) => (d != null) ? d.ToString() : ""));
				if (_logger != null)
				{
					_logger.Msg(text);
				}
				else
				{
					MelonLogger.Msg(text);
				}
			}
		}
	}
	public class Metadata
	{
		public const string AUTHOR = "jakzo";

		public const string COMPANY = null;

		public const string DEVELOPER = "Stress Level Zero";

		public const string GAME = "BONELAB";

		public const string GAME_BONEWORKS = "BONEWORKS";
	}
}
namespace Sst.Common.Ipc
{
	public abstract class Logger
	{
		public abstract void Debug(string message);

		public abstract void Error(string message);
	}
	public class Server : IDisposable
	{
		public string Name;

		private const int BUFFER_SIZE = 4096;

		private const int MAX_NUMBER_OF_SERVER_INSTANCES = 10;

		private HashSet<NamedPipeServerStream> _streams = new HashSet<NamedPipeServerStream>();

		private bool _isDisposed;

		private Logger _logger;

		public event Action<NamedPipeServerStream> OnClientConnected;

		public event Action<NamedPipeServerStream> OnClientDisconnected;

		public event Action<string> OnMessageReceived;

		public Server(string name, Logger logger)
		{
			Name = name;
			_logger = logger;
			StartNewPipeServerThread();
		}

		public void Dispose()
		{
			if (!_isDisposed)
			{
				_isDisposed = true;
				NamedPipeServerStream[] array = _streams.ToArray();
				foreach (NamedPipeServerStream stream in array)
				{
					DisposeStream(stream);
				}
			}
		}

		public void Send(string message)
		{
			NamedPipeServerStream[] array = _streams.ToArray();
			foreach (NamedPipeServerStream stream in array)
			{
				try
				{
					SendToStream(stream, message);
				}
				catch (Exception ex)
				{
					_logger.Error("Error sending IPC message:");
					_logger.Error(ex.ToString());
					DisposeStream(stream);
				}
			}
		}

		public static void SendToStream(NamedPipeServerStream stream, string message)
		{
			if (stream.IsConnected)
			{
				byte[] bytes = Encoding.UTF8.GetBytes(message);
				stream.Write(bytes, 0, bytes.Length);
			}
		}

		private void StartNewPipeServerThread()
		{
			Task.Run((Action)StartNewPipeServer);
		}

		private void StartNewPipeServer()
		{
			try
			{
				NamedPipeServerStream stream = new NamedPipeServerStream(Name, PipeDirection.InOut, 10, PipeTransmissionMode.Message, PipeOptions.None, 4096, 4096);
				_streams.Add(stream);
				stream.WaitForConnection();
				_logger.Debug("Client connected");
				if (!_isDisposed)
				{
					SafeInvoke(delegate
					{
						this.OnClientConnected?.Invoke(stream);
					});
				}
			}
			catch (Exception arg)
			{
				_logger.Error($"Pipe server failed: {arg}");
			}
			finally
			{
				if (!_isDisposed)
				{
					StartNewPipeServerThread();
				}
			}
		}

		private void ReadFromPipeConnection(NamedPipeServerStream stream)
		{
			byte[] array = new byte[4096];
			StringBuilder stringBuilder = null;
			while (true)
			{
				if (stringBuilder == null)
				{
					stringBuilder = new StringBuilder();
				}
				int num = stream.Read(array, 0, array.Length);
				if (_isDisposed)
				{
					return;
				}
				if (num <= 0)
				{
					break;
				}
				stringBuilder.Append(Encoding.UTF8.GetString(array, 0, num));
				if (stream.IsMessageComplete)
				{
					string message = stringBuilder.ToString().TrimEnd(new char[1]);
					SafeInvoke(delegate
					{
						this.OnMessageReceived?.Invoke(message);
					});
					stringBuilder = null;
				}
			}
			DisposeStream(stream);
		}

		private void ReadFromPipeConnection2(NamedPipeServerStream stream)
		{
			byte[] buffer = new byte[4096];
			StringBuilder sb = new StringBuilder();
			try
			{
				stream.BeginRead(buffer, 0, buffer.Length, ReadCallback, null);
			}
			catch (Exception ex)
			{
				_logger.Error("Failed to begin read operation:");
				_logger.Error(ex.ToString());
				DisposeStream(stream);
			}
			void ReadCallback(IAsyncResult ar)
			{
				try
				{
					int num = stream.EndRead(ar);
					if (!_isDisposed)
					{
						if (num <= 0)
						{
							DisposeStream(stream);
						}
						else
						{
							sb.Append(Encoding.UTF8.GetString(buffer, 0, num));
							if (stream.IsMessageComplete)
							{
								string message = sb.ToString().TrimEnd(new char[1]);
								SafeInvoke(delegate
								{
									this.OnMessageReceived?.Invoke(message);
								});
								sb.Clear();
							}
							stream.BeginRead(buffer, 0, buffer.Length, ReadCallback, null);
						}
					}
				}
				catch (Exception ex2)
				{
					_logger.Error("Error while reading from pipe connection:");
					_logger.Error(ex2.ToString());
					DisposeStream(stream);
				}
			}
		}

		private void PollPipeConnection(NamedPipeServerStream stream)
		{
			byte[] array = new byte[4096];
			StringBuilder stringBuilder = new StringBuilder();
			try
			{
				while (!_isDisposed)
				{
					if (stream.IsConnected)
					{
						while (stream.IsMessageComplete)
						{
							int num = stream.Read(array, 0, array.Length);
							if (num > 0)
							{
								stringBuilder.Append(Encoding.UTF8.GetString(array, 0, num));
								if (stream.IsMessageComplete)
								{
									string message = stringBuilder.ToString().TrimEnd(new char[1]);
									_logger.Debug("Finally got a message! " + message);
									SafeInvoke(delegate
									{
										this.OnMessageReceived?.Invoke(message);
									});
									stringBuilder.Clear();
								}
								continue;
							}
							DisposeStream(stream);
							return;
						}
					}
					_logger.Debug("IPC waiting " + stream.IsConnected + " " + stream.IsMessageComplete);
					Thread.Sleep(1000);
				}
			}
			catch (Exception ex)
			{
				_logger.Error("Error while reading from pipe:");
				_logger.Error(ex.ToString());
				DisposeStream(stream);
			}
		}

		private void DisposeStream(NamedPipeServerStream stream)
		{
			_streams.Remove(stream);
			try
			{
				if (stream.IsConnected)
				{
					stream.Disconnect();
					SafeInvoke(delegate
					{
						this.OnClientDisconnected?.Invoke(stream);
					});
				}
			}
			catch (Exception arg)
			{
				_logger.Error($"Failed to stop pipe server: {arg}");
			}
			finally
			{
				stream.Close();
				stream.Dispose();
			}
		}

		private void SafeInvoke(Action action)
		{
			try
			{
				action();
			}
			catch (Exception arg)
			{
				_logger.Error($"Failed to run event: {arg}");
			}
		}
	}
}
namespace Sst.Common.Boneworks
{
	public class DebugStats
	{
		public const string NAMED_PIPE = "BoneworksDebugStats";

		public float fps;

		public float physicsRate;

		public int droppedFrames;

		public int extraFrames;

		public int numFixedUpdatesMagNotTouching;
	}
	public class HundredPercentState
	{
		public class Collectible
		{
			public string Type;

			public string Uuid;

			public string DisplayName;
		}

		public class RngState
		{
			public string name;

			public int attempts;

			public float prevAttemptChance;

			public float probabilityNotDroppedYet;

			public bool hasDropped;
		}

		public const string NAMED_PIPE = "BoneworksHundredPercent";

		public const string TYPE_AMMO_LIGHT = "ammo_light";

		public const string TYPE_AMMO_MEDIUM = "ammo_medium";

		public const string TYPE_ITEM = "item";

		public Dictionary<string, RngState> rngUnlocks = new(string, string, float)[3]
		{
			("Baseball", "81207815-e447-430b-9ea6-6d8c35842fef", 0.1f),
			("Golf Club", "290780a8-4f88-451a-88a5-1599f8e7e89f", 0.02f),
			("Baton", "53e4ff47-b0f4-426c-956d-ed391ca6f5f7", 0.1f)
		}.ToDictionary(((string, string, float) def) => def.Item2, ((string, string, float) def) => new RngState
		{
			name = def.Item1,
			attempts = 0,
			prevAttemptChance = def.Item3,
			probabilityNotDroppedYet = 1f,
			hasDropped = false
		});

		public int unlockLevelCount;

		public int unlockLevelMax;

		public int ammoLevelCount;

		public int ammoLevelMax;

		public Collectible[] justCollected;

		public Collectible[] levelCollectibles;
	}
}
namespace Sst.Utilities
{
	public class Boneworks
	{
		public static RigManager GetRigManager()
		{
			return GameObject.Find("[RigManager (Default Brett)]").GetComponent<RigManager>();
		}
	}
	public class Geometry
	{
		public static class IcoSphere
		{
			private static int getMiddlePoint(int p1, int p2, ref List<Vector3> vertices, ref Dictionary<long, int> cache, float radius)
			{
				//IL_0036: 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_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: 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_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: 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_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: 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)
				bool num = p1 < p2;
				int num2 = (num ? p1 : p2);
				int num3 = (num ? p2 : p1);
				long key = ((long)num2 << 32) + num3;
				if (cache.TryGetValue(key, out var value))
				{
					return value;
				}
				int count = vertices.Count;
				Vector3 val = vertices[p1];
				Vector3 val2 = vertices[p2];
				Vector3 val3 = default(Vector3);
				((Vector3)(ref val3))..ctor((val.x + val2.x) / 2f, (val.y + val2.y) / 2f, (val.z + val2.z) / 2f);
				vertices.Add(((Vector3)(ref val3)).normalized * radius);
				cache.Add(key, count);
				return count;
			}

			public static (Vector3[], int[], Vector3[]) Create(float radius, int subdivisions)
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: 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_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: 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_005c: 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_0078: 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_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_0099: 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_00a2: 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_00be: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c7: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_0109: Unknown result type (might be due to invalid IL or missing references)
				//IL_010e: 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_0118: Unknown result type (might be due to invalid IL or missing references)
				//IL_012f: 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_0138: Unknown result type (might be due to invalid IL or missing references)
				//IL_013e: 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)
				//IL_0159: Unknown result type (might be due to invalid IL or missing references)
				//IL_015d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0163: Unknown result type (might be due to invalid IL or missing references)
				//IL_0179: Unknown result type (might be due to invalid IL or missing references)
				//IL_017e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0182: Unknown result type (might be due to invalid IL or missing references)
				//IL_0188: Unknown result type (might be due to invalid IL or missing references)
				//IL_019f: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
				float num = (1f + Mathf.Sqrt(5f)) / 2f;
				List<Vector3> list = new List<Vector3>();
				Vector3 val = new Vector3(-1f, num, 0f);
				list.Add(((Vector3)(ref val)).normalized * radius);
				val = new Vector3(1f, num, 0f);
				list.Add(((Vector3)(ref val)).normalized * radius);
				val = new Vector3(-1f, 0f - num, 0f);
				list.Add(((Vector3)(ref val)).normalized * radius);
				val = new Vector3(1f, 0f - num, 0f);
				list.Add(((Vector3)(ref val)).normalized * radius);
				val = new Vector3(0f, -1f, num);
				list.Add(((Vector3)(ref val)).normalized * radius);
				val = new Vector3(0f, 1f, num);
				list.Add(((Vector3)(ref val)).normalized * radius);
				val = new Vector3(0f, -1f, 0f - num);
				list.Add(((Vector3)(ref val)).normalized * radius);
				val = new Vector3(0f, 1f, 0f - num);
				list.Add(((Vector3)(ref val)).normalized * radius);
				val = new Vector3(num, 0f, -1f);
				list.Add(((Vector3)(ref val)).normalized * radius);
				val = new Vector3(num, 0f, 1f);
				list.Add(((Vector3)(ref val)).normalized * radius);
				val = new Vector3(0f - num, 0f, -1f);
				list.Add(((Vector3)(ref val)).normalized * radius);
				val = new Vector3(0f - num, 0f, 1f);
				list.Add(((Vector3)(ref val)).normalized * radius);
				List<Vector3> vertices = list;
				int[] array = new int[60]
				{
					0, 11, 5, 0, 5, 1, 0, 1, 7, 0,
					7, 10, 0, 10, 11, 1, 5, 9, 5, 11,
					4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
					3, 9, 4, 3, 4, 2, 3, 2, 6, 3,
					6, 8, 3, 8, 9, 4, 9, 5, 2, 4,
					11, 6, 2, 10, 8, 6, 7, 9, 8, 1
				};
				Dictionary<long, int> cache = new Dictionary<long, int>();
				for (int i = 0; i < subdivisions; i++)
				{
					int[] array2 = new int[array.Length * 4];
					for (int j = 0; j < array.Length; j += 3)
					{
						int num2 = array[j];
						int num3 = array[j + 1];
						int num4 = array[j + 2];
						int middlePoint = getMiddlePoint(num2, num3, ref vertices, ref cache, radius);
						int middlePoint2 = getMiddlePoint(num3, num4, ref vertices, ref cache, radius);
						int middlePoint3 = getMiddlePoint(num4, num2, ref vertices, ref cache, radius);
						new int[12]
						{
							num2, middlePoint, middlePoint3, num3, middlePoint2, middlePoint, num4, middlePoint3, middlePoint2, middlePoint,
							middlePoint2, middlePoint3
						}.CopyTo(array2, j * 4);
					}
					array = array2;
				}
				Vector3[] item = vertices.Select((Vector3 vertex) => ((Vector3)(ref vertex)).normalized).ToArray();
				return (vertices.ToArray(), array, item);
			}
		}

		public static GameObject CreatePrefabCube(string name, Color color, float left, float right, float top, float bottom, float front, float back)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = CreatePrefab(name);
			((Renderer)AddCubeMesh(ref gameObject, left, right, top, bottom, front, back)).material.color = color;
			return gameObject;
		}

		public static GameObject CreatePrefabUnclosedCylinder(string name, Color color, float radius, int segments, float top, float bottom)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = CreatePrefab(name);
			((Renderer)AddUnclosedCylinderMesh(ref gameObject, radius, segments, top, bottom)).material.color = color;
			return gameObject;
		}

		public static GameObject CreatePrefabSphere(string name, Color color, float radius, int subdivisions)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = CreatePrefab(name);
			((Renderer)AddSphereMesh(ref gameObject, radius, subdivisions)).material.color = color;
			return gameObject;
		}

		public static GameObject CreatePrefab(string name)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_001e: Expected O, but got Unknown
			GameObject val = new GameObject("SpeedrunTools_Prefab_" + name)
			{
				active = false
			};
			Object.DontDestroyOnLoad((Object)val);
			return val;
		}

		public static MeshRenderer AddCubeMesh(ref GameObject gameObject, float left, float right, float bottom, float top, float back, float front)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_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_005c: 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_006c: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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)
			MeshFilter val = gameObject.AddComponent<MeshFilter>();
			val.mesh.Clear();
			val.mesh.vertices = Il2CppStructArray<Vector3>.op_Implicit((Vector3[])(object)new Vector3[8]
			{
				new Vector3(right, top, back),
				new Vector3(left, top, back),
				new Vector3(left, bottom, back),
				new Vector3(right, bottom, back),
				new Vector3(right, bottom, front),
				new Vector3(left, bottom, front),
				new Vector3(left, top, front),
				new Vector3(right, top, front)
			});
			val.mesh.triangles = Il2CppStructArray<int>.op_Implicit(new int[36]
			{
				0, 2, 1, 0, 3, 2, 2, 3, 4, 2,
				4, 5, 1, 2, 5, 1, 5, 6, 0, 7,
				4, 0, 4, 3, 5, 4, 7, 5, 7, 6,
				0, 6, 7, 0, 1, 6
			});
			val.mesh.Optimize();
			val.mesh.RecalculateBounds();
			val.mesh.RecalculateTangents();
			val.mesh.RecalculateNormals();
			return gameObject.AddComponent<MeshRenderer>();
		}

		public static MeshRenderer AddSphereMesh(ref GameObject gameObject, float radius, int subdivisions)
		{
			MeshFilter obj = gameObject.AddComponent<MeshFilter>();
			obj.mesh.Clear();
			var (array, array2, array3) = IcoSphere.Create(radius, subdivisions);
			obj.mesh.vertices = Il2CppStructArray<Vector3>.op_Implicit(array);
			obj.mesh.triangles = Il2CppStructArray<int>.op_Implicit(array2);
			obj.mesh.normals = Il2CppStructArray<Vector3>.op_Implicit(array3);
			obj.mesh.Optimize();
			obj.mesh.RecalculateBounds();
			obj.mesh.RecalculateTangents();
			obj.mesh.RecalculateNormals();
			return gameObject.AddComponent<MeshRenderer>();
		}

		public static MeshRenderer AddUnclosedCylinderMesh(ref GameObject gameObject, float radius, int segments, float top, float bottom)
		{
			MeshFilter val = gameObject.AddComponent<MeshFilter>();
			val.mesh.Clear();
			IEnumerable<Vector2> circleCoords = Enumerable.Range(0, segments).Select((Func<int, Vector2>)delegate(int i)
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				float num2 = (float)i / (float)segments * (float)Math.PI * 2f;
				return new Vector2(Mathf.Sin(num2) * radius, Mathf.Cos(num2) * radius);
			});
			val.mesh.vertices = Il2CppStructArray<Vector3>.op_Implicit(new float[2] { bottom, top }.SelectMany((float y) => circleCoords.Select((Func<Vector2, Vector3>)((Vector2 coord) => new Vector3(coord.x, y, coord.y)))).ToArray());
			val.mesh.triangles = Il2CppStructArray<int>.op_Implicit(Enumerable.Range(0, segments).SelectMany(delegate(int idx)
			{
				int num = (idx + 1) % segments;
				return new int[6]
				{
					idx,
					num,
					segments + idx,
					num,
					segments + num,
					segments + idx
				};
			}).ToArray());
			val.mesh.Optimize();
			val.mesh.RecalculateBounds();
			val.mesh.RecalculateTangents();
			val.mesh.RecalculateNormals();
			return gameObject.AddComponent<MeshRenderer>();
		}

		public static void SetMaterial(GameObject gameObject, Color color, Shader shader = null)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			MeshRenderer component = gameObject.GetComponent<MeshRenderer>();
			((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)component).receiveShadows = false;
			Material material = ((Renderer)component).material;
			if ((Object)(object)shader != (Object)null)
			{
				material.shader = shader;
			}
			material.color = color;
		}
	}
	public static class Unity
	{
		public static Transform FindDescendantTransform(Transform transform, string name)
		{
			if (((Object)transform).name == name)
			{
				return transform;
			}
			for (int i = 0; i < transform.childCount; i++)
			{
				Transform val = FindDescendantTransform(transform.GetChild(i), name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		public static void FindDescendantComponentsOfType<T>(ref List<T> output, Transform parent, bool includeInactive)
		{
			if (includeInactive || ((Component)parent).gameObject.active)
			{
				output.AddRange((IEnumerable<T>)((Component)parent).GetComponents<T>());
				for (int i = 0; i < parent.childCount; i++)
				{
					FindDescendantComponentsOfType(ref output, parent.GetChild(i), includeInactive);
				}
			}
		}

		public static IEnumerable<Transform> AllDescendantTransforms(Transform parent, bool includeInactive)
		{
			Stack<(Transform, int)> stack = new Stack<(Transform, int)>();
			stack.Push((parent, 0));
			while (stack.Count > 0)
			{
				var (t, i) = stack.Pop();
				if (i < t.childCount)
				{
					Transform child = t.GetChild(i);
					if (includeInactive || ((Component)child).gameObject.active)
					{
						yield return child;
					}
					stack.Push((t, i + 1));
					stack.Push((child, 0));
				}
			}
		}

		public static IEnumerable<T> AllDescendantComponents<T>(Transform parent, bool includeInactive) where T : Component
		{
			foreach (Transform item in AllDescendantTransforms(parent, includeInactive))
			{
				foreach (T component in ((Component)item).GetComponents<T>())
				{
					yield return component;
				}
			}
		}

		public static GameObject[] FindAllInDescendants(GameObject root, string name)
		{
			List<GameObject> result = new List<GameObject>();
			_FindAllInDescendants(root.transform, name, ref result);
			return result.ToArray();
		}

		private static void _FindAllInDescendants(Transform transform, string name, ref List<GameObject> result)
		{
			if (((Object)transform).name == name)
			{
				result.Add(((Component)transform).gameObject);
			}
			int i = 0;
			for (int childCount = transform.childCount; i < childCount; i++)
			{
				_FindAllInDescendants(transform.GetChild(i), name, ref result);
			}
		}

		public static GameObject[] ChildrenToArray(GameObject parent)
		{
			List<GameObject> list = new List<GameObject>();
			for (int i = 0; i < parent.transform.childCount; i++)
			{
				list.Add(((Component)parent.transform.GetChild(i)).gameObject);
			}
			return list.ToArray();
		}

		public static IEnumerable<GameObject> RootObjects()
		{
			for (int i = 0; i < SceneManager.sceneCount; i++)
			{
				Scene sceneAt = SceneManager.GetSceneAt(i);
				if (!((Scene)(ref sceneAt)).isLoaded)
				{
					continue;
				}
				foreach (GameObject item in (Il2CppArrayBase<GameObject>)(object)((Scene)(ref sceneAt)).GetRootGameObjects())
				{
					yield return item;
				}
			}
		}

		public static Color GenerateColor(int i)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			return Color.HSVToRGB((float)i * 0.064f % 1f, 0.9f - (float)(i / 16) * 0.3f % 0.8f, 0.9f);
		}

		public static Shader FindShader(string name)
		{
			return ((IEnumerable<Shader>)Resources.FindObjectsOfTypeAll<Shader>()).First((Shader shader) => ((Object)shader).name == name);
		}
	}
	public static class Resources
	{
		public static void ExtractResource(string resourceName, string dir)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(resourceName));
			using Stream stream = executingAssembly.GetManifestResourceStream(name);
			using ZipArchive zipArchive = new ZipArchive(stream, ZipArchiveMode.Read);
			foreach (ZipArchiveEntry entry in zipArchive.Entries)
			{
				Stream stream2 = entry.Open();
				using FileStream destination = File.Create(Path.Combine(dir, entry.FullName));
				stream2.CopyTo(destination);
			}
		}
	}
}
namespace Sst.Speedruns
{
	internal class AntiCheat
	{
		public enum RunIllegitimacyReason
		{
			DISALLOWED_MODS,
			DISALLOWED_PLUGINS
		}

		private static HashSet<string> ALLOWED_MODS = new HashSet<string> { "LootDropBugfix", "PhysicsTickFixer" };

		private static HashSet<string> ALLOWED_PLUGINS = new HashSet<string> { "Backwards Compatibility Plugin" };

		public static Dictionary<RunIllegitimacyReason, string> ComputeRunLegitimacy()
		{
			Dictionary<RunIllegitimacyReason, string> dictionary = new Dictionary<RunIllegitimacyReason, string>();
			IEnumerable<MelonMod> source = MelonHandler.Mods.Where((MelonMod mod) => !(mod is Mod) && !ALLOWED_MODS.Contains(((MelonBase)mod).Info.Name));
			if (source.Count() > 0)
			{
				string text = string.Join(", ", source.Select((MelonMod mod) => ((MelonBase)mod).Info.Name));
				dictionary[RunIllegitimacyReason.DISALLOWED_MODS] = "Disallowed mods are active: " + text;
			}
			IEnumerable<MelonPlugin> source2 = MelonHandler.Plugins.Where((MelonPlugin plugin) => !ALLOWED_PLUGINS.Contains(((MelonBase)plugin).Info.Name));
			if (source2.Count() > 0)
			{
				IEnumerable<string> values = source2.Select((MelonPlugin mod) => ((MelonBase)mod).Info.Name);
				dictionary[RunIllegitimacyReason.DISALLOWED_PLUGINS] = "Disallowed plugins are active: " + string.Join(", ", values);
			}
			return dictionary;
		}
	}
	internal class Mode
	{
		public static readonly Mode DISABLED = new Mode
		{
			replayMode = GameMode.NONE,
			color = new Color(0.8f, 0.1f, 0.1f),
			colorRgb = "cc1111"
		};

		public static readonly Mode NORMAL = new Mode
		{
			name = "Speedrun",
			replayMode = GameMode.SPEEDRUN,
			hotkeyKey = (KeyCode)115,
			color = new Color(0.2f, 0.9f, 0.1f),
			colorRgb = "22ee11",
			resetSaveOnEnable = true,
			resetSaveOnMainMenu = true,
			resetTimerOnMainMenu = true
		};

		public static readonly Mode NEWGAME_PLUS = new Mode
		{
			name = "Newgame+ speedrun",
			replayMode = GameMode.NEWGAME_PLUS,
			hotkeyKey = (KeyCode)110,
			color = new Color(0.9f, 0.9f, 0.1f),
			colorRgb = "eeee11",
			resetSaveOnEnable = false,
			resetSaveOnMainMenu = false,
			saveResourceFilename = "NewgamePlusSave.zip",
			resetTimerOnMainMenu = true
		};

		public static readonly Mode HUNDRED_PERCENT = new Mode
		{
			name = "100% speedrun",
			replayMode = GameMode.HUNDRED_PERCENT,
			hotkeyKey = (KeyCode)104,
			color = new Color(0.3f, 0.3f, 0.9f),
			colorRgb = "4444ee",
			resetSaveOnEnable = true,
			resetSaveOnMainMenu = false,
			resetTimerOnMainMenu = false,
			OnEnable = delegate
			{
				SteamUserStats.ResetAllStats(true);
				HundredPercentServer.Instance.Reset();
			}
		};

		public static readonly Mode BLINDFOLD = new Mode
		{
			name = "Blindfold",
			replayMode = GameMode.BLINDFOLDED,
			hotkeyKey = (KeyCode)98,
			color = new Color(0.4f, 0.4f, 0.4f),
			colorRgb = "666666",
			resetSaveOnEnable = true,
			resetSaveOnMainMenu = true,
			resetTimerOnMainMenu = true,
			OnSceneWasLoaded = delegate(int sceneIdx)
			{
				if (sceneIdx == 1)
				{
					Blindfold.s_blindfolder.SetBlindfold(blindfolded: false);
				}
				else
				{
					Blindfold.s_blindfolder.SetBlindfold(blindfolded: true);
				}
			},
			OnUpdate = delegate
			{
				Blindfold.s_blindfolder.OnUpdate();
			},
			OnDisable = delegate
			{
				Blindfold.s_blindfolder.SetBlindfold(blindfolded: false);
			}
		};

		public static readonly Mode GRIPLESS = new Mode
		{
			name = "Gripless",
			replayMode = GameMode.GRIPLESS,
			hotkeyKey = (KeyCode)103,
			color = new Color(0.4f, 0.4f, 0.4f),
			colorRgb = "666666",
			resetSaveOnEnable = true,
			resetSaveOnMainMenu = true,
			resetTimerOnMainMenu = true,
			OnEnable = delegate
			{
				Gripless.IsGripDisabled = true;
			},
			OnDisable = delegate
			{
				Gripless.IsGripDisabled = false;
			}
		};

		public static readonly Mode LEFT_CONTROLLER_GRIPLESS = new Mode
		{
			name = "Left controller only gripless",
			replayMode = GameMode.LEFT_CONTROLLER_GRIPLESS,
			hotkeyKey = (KeyCode)108,
			color = new Color(0.4f, 0.4f, 0.4f),
			colorRgb = "666666",
			resetSaveOnEnable = true,
			resetSaveOnMainMenu = true,
			resetTimerOnMainMenu = true,
			OnEnable = delegate
			{
				Gripless.IsGripDisabled = true;
				Armless.SetArmsEnabled(isLeftArmEnabled: true, isRightArmEnabled: false, alsoSetControllers: true);
			},
			OnSceneWasInitialized = Armless.OnSceneWasInitializedStatic,
			OnDisable = delegate
			{
				Gripless.IsGripDisabled = false;
				Armless.SetArmsEnabled(isLeftArmEnabled: true, isRightArmEnabled: true, alsoSetControllers: true);
			}
		};

		public static readonly Mode RIGHT_CONTROLLER_GRIPLESS = new Mode
		{
			name = "Right controller only gripless",
			replayMode = GameMode.RIGHT_CONTROLLER_GRIPLESS,
			hotkeyKey = (KeyCode)111,
			color = new Color(0.4f, 0.4f, 0.4f),
			colorRgb = "666666",
			resetSaveOnEnable = true,
			resetSaveOnMainMenu = true,
			resetTimerOnMainMenu = true,
			OnEnable = delegate
			{
				Gripless.IsGripDisabled = true;
				Armless.SetArmsEnabled(isLeftArmEnabled: false, isRightArmEnabled: true, alsoSetControllers: true);
			},
			OnSceneWasInitialized = Armless.OnSceneWasInitializedStatic,
			OnDisable = delegate
			{
				Gripless.IsGripDisabled = false;
				Armless.SetArmsEnabled(isLeftArmEnabled: true, isRightArmEnabled: true, alsoSetControllers: true);
			}
		};

		public static readonly Mode ARMLESS = new Mode
		{
			name = "Armless",
			replayMode = GameMode.ARMLESS,
			hotkeyKey = (KeyCode)97,
			color = new Color(0.4f, 0.4f, 0.4f),
			colorRgb = "666666",
			resetSaveOnEnable = true,
			resetSaveOnMainMenu = true,
			resetTimerOnMainMenu = true,
			OnEnable = delegate
			{
				Armless.SetArmsEnabled(isLeftArmEnabled: false, isRightArmEnabled: false, alsoSetControllers: false);
			},
			OnSceneWasInitialized = Armless.OnSceneWasInitializedStatic,
			OnDisable = delegate
			{
				Armless.SetArmsEnabled(isLeftArmEnabled: true, isRightArmEnabled: true, alsoSetControllers: false);
			}
		};

		public static Mode CurrentMode = DISABLED;

		public string name;

		public GameMode replayMode = GameMode.SPEEDRUN;

		public KeyCode hotkeyKey;

		public Color color;

		public string colorRgb;

		public bool resetSaveOnEnable;

		public bool resetSaveOnMainMenu;

		public bool resetTimerOnMainMenu;

		public string saveResourceFilename;

		public Action OnEnable;

		public Action OnDisable;

		public Action<int> OnSceneWasLoaded;

		public Action<int, string> OnSceneWasInitialized;

		public Action OnUpdate;
	}
	internal class Overlay
	{
		private const string LOADING_TEXT_NAME = "SpeedrunTools_LoadingText";

		private static readonly string OVERLAY_KEY = SteamVR_Overlay.key + ".SpeedrunTools_RunStatus";

		private GameObject s_loadingText;

		private ulong s_overlayHandle;

		public void Show(string text)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			/