Decompiled source of LessRam v1.0.3

plugins/LessRam/LessRam.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using IEVO.UI.uGUIDirectedNavigation;
using Microsoft.CodeAnalysis;
using Steamworks;
using Steamworks.Data;
using Steamworks.Ugc;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;
using VGFunctions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LessRam")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("title")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+786e633056fcf309aed952b5636e8ad233e9f3d2")]
[assembly: AssemblyProduct("LessRam")]
[assembly: AssemblyTitle("LessRam")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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 LessRam
{
	[HarmonyPatch(typeof(GameManager))]
	public static class GameManagerPatch
	{
		[HarmonyPatch("LoadAudio")]
		[HarmonyPrefix]
		public static bool PreLoadAudio(ref IEnumerator __result, VGLevel _level)
		{
			if (!SingletonBase<GameManager>.Inst.IsArcade || Object.op_Implicit((Object)(object)_level.LevelMusic))
			{
				return true;
			}
			__result = LoadAudio(SingletonBase<ArcadeManager>.Inst.CurrentArcadeLevel);
			return false;
		}

		private static IEnumerator LoadAudio(VGLevel _level)
		{
			VGLevelWrapper valueOrDefault = LessRam.Levels.GetValueOrDefault(((Object)_level).name, null);
			Coroutine val = ((MonoBehaviour)DataManager.inst).StartCoroutine(LevelLoaderHelper.LoadAudio(_level, valueOrDefault.AudioPath));
			Coroutine coroutine2 = ((MonoBehaviour)DataManager.inst).StartCoroutine(LevelLoaderHelper.LoadImage(_level, valueOrDefault.ImagePath));
			yield return val;
			yield return coroutine2;
			SingletonBase<GameManager>.Inst.LevelAudio = _level.LevelMusic;
			SingletonBase<GameManager>.Inst.CurLoadingState.Audio = true;
		}

		[HarmonyPatch("PlayGame")]
		[HarmonyPostfix]
		private static void OnPlayGame()
		{
			ArcadeMenuPatch.CleanLevels();
		}
	}
	public static class LevelLoaderHelper
	{
		public static IEnumerator LoadAudio(VGLevel level, string path)
		{
			DownloadHandlerAudioClip val = new DownloadHandlerAudioClip(path, (AudioType)14);
			val.streamAudio = true;
			UnityWebRequest audioUwr = new UnityWebRequest(path, "GET", (DownloadHandler)(object)val, (UploadHandler)null);
			try
			{
				yield return audioUwr.SendWebRequest();
				if ((int)audioUwr.result != 1)
				{
					LessRam.Logger.LogError((object)audioUwr.error);
				}
				else if (Object.op_Implicit((Object)(object)level))
				{
					AudioClip content = DownloadHandlerAudioClip.GetContent(audioUwr);
					if (!Object.op_Implicit((Object)(object)content))
					{
						LessRam.Logger.LogError((object)("Remove invalid song from arcade. No audio file. [" + ((Object)level).name + "]"));
						yield break;
					}
					ArcadeMenuPatch.activeClips.Add(content);
					((Object)content).name = ((Object)level).name;
					level.LevelMusic = content;
				}
			}
			finally
			{
				((IDisposable)audioUwr)?.Dispose();
			}
		}

		public static IEnumerator LoadImage(VGLevel level, string path)
		{
			Task<Sprite> spriteTask = Task.Run(() => InternalLoadImage(path));
			while (!spriteTask.IsCompleted)
			{
				yield return null;
			}
			if (Object.op_Implicit((Object)(object)spriteTask.Result))
			{
				Sprite result = spriteTask.Result;
				if (!Object.op_Implicit((Object)(object)level))
				{
					Object.Destroy((Object)(object)result.texture);
					Object.Destroy((Object)(object)result);
				}
				else
				{
					ArcadeMenuPatch.activeSprites.Add(result);
					level.AlbumArt = result;
				}
			}
		}

		private static async Task<Sprite?> InternalLoadImage(string path)
		{
			UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(path, false);
			try
			{
				SimpleCoroutineAwaiter<AsyncOperation> val = IEnumeratorAwaitExtensions.GetAwaiter((AsyncOperation)(object)uwr.SendWebRequest());
				if (!val.IsCompleted)
				{
					await val;
					object obj = default(object);
					val = (SimpleCoroutineAwaiter<AsyncOperation>)obj;
				}
				val.GetResult();
				if ((int)uwr.result != 1)
				{
					LessRam.Logger.LogError((object)uwr.error);
					return null;
				}
				Texture2D content = DownloadHandlerTexture.GetContent(uwr);
				int width = ((Texture)content).width;
				int height = ((Texture)content).height;
				if (width <= 512 && height <= 512 && width == height)
				{
					return Sprite.Create(content, new Rect(0f, 0f, (float)width, (float)height), new Vector2(0.5f, 0.5f), 72f, 0u, (SpriteMeshType)0);
				}
				return null;
			}
			finally
			{
				((IDisposable)uwr)?.Dispose();
			}
		}
	}
	public static class VGLevelExtension
	{
		public static bool InitSteamInfoFix(this VGLevel level, ulong _id, string _folder)
		{
			//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_0012: 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_0021: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			if (string.IsNullOrEmpty(_folder))
			{
				return false;
			}
			level.SteamInfo = new SteamData
			{
				ItemID = PublishedFileId.op_Implicit(_id)
			};
			level.BaseLevelData = new LevelDataBase
			{
				LevelID = _id.ToString(),
				LocalFolder = _folder
			};
			level.LevelData = level.BaseLevelData;
			return true;
		}
	}
	[BepInPlugin("me.ytarame.LessRam", "LessRam", "1.0.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class LessRam : BaseUnityPlugin
	{
		private Harmony _harmony;

		private const string Guid = "me.ytarame.LessRam";

		private const string Name = "LessRam";

		private const string Version = "1.0.3";

		internal static readonly Dictionary<string, VGLevelWrapper> Levels = new Dictionary<string, VGLevelWrapper>();

		internal static ManualLogSource Logger;

		internal static int SemaphoreCount = 5;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			_harmony = new Harmony("me.ytarame.LessRam");
			_harmony.PatchAll();
			SemaphoreCount = ((BaseUnityPlugin)this).Config.Bind<int>(new ConfigDefinition("LessRam", "Semaphore count"), 5, (ConfigDescription)null).Value;
			Logger.LogInfo((object)"Plugin me.ytarame.LessRam is loaded!");
		}
	}
	[HarmonyPatch(typeof(SteamWorkshopFacepunch))]
	public static class SteamWorkshopPatch
	{
		private static object _lockObject = new object();

		[HarmonyPatch("DownloadLevels")]
		[HarmonyPrefix]
		public static bool PreStart(SteamWorkshopFacepunch __instance, ref Task __result)
		{
			__result = LoadLevels(__instance);
			return false;
		}

		private static async Task LoadLevels(SteamWorkshopFacepunch facepunch)
		{
			Stopwatch stopWatch = new Stopwatch();
			stopWatch.Start();
			facepunch.TotalSteamWorkshopSubscriptions = 0;
			facepunch.TotalSteamWorkshopSubscriptionsDone = 0;
			SteamWorkshopFacepunch.inst.isLoadingLevels = true;
			Query val = Query.ItemsReadyToUse;
			val = ((Query)(ref val)).WhereUserSubscribed(default(SteamId));
			Query q = ((Query)(ref val)).SortByCreationDate();
			ResultPage? val2 = await ((Query)(ref q)).GetPageAsync(1);
			if (!val2.HasValue)
			{
				stopWatch.Stop();
				LessRam.Logger.LogError((object)$"Level loading failure [{stopWatch.ElapsedMilliseconds}]");
				return;
			}
			facepunch.TotalSteamWorkshopSubscriptions = val2.Value.TotalCount;
			ResultPage value = val2.Value;
			foreach (Item entry in ((ResultPage)(ref value)).Entries)
			{
				Item current = entry;
				if (SingletonBase<ArcadeManager>.Inst.skippedLoad)
				{
					return;
				}
				if (((Item)(ref current)).IsInstalled)
				{
					(VGLevel, VGLevelWrapper)? tuple = CreateEntry(facepunch, current);
					if (tuple.HasValue)
					{
						LessRam.Levels.Add(((Object)tuple.Value.Item1).name, tuple.Value.Item2);
						SingletonBase<ArcadeLevelDataManager>.Inst.ArcadeLevels.Add(tuple.Value.Item1);
						SteamWorkshopFacepunch obj = facepunch;
						obj.TotalSteamWorkshopSubscriptionsDone++;
					}
				}
			}
			int totalPages = Mathf.CeilToInt((float)val2.Value.TotalCount / (float)val2.Value.ResultCount);
			SemaphoreSlim semaphore = new SemaphoreSlim(LessRam.SemaphoreCount);
			try
			{
				List<Task> tasks = new List<Task>();
				for (int i = 2; i < totalPages; i++)
				{
					await semaphore.WaitAsync();
					LessRam.Logger.LogInfo((object)$"loading page {i}");
					int iteration = i;
					tasks.Add(Task.Run(async delegate
					{
						try
						{
							ResultPage? val3 = await ((Query)(ref q)).GetPageAsync(iteration);
							if (!val3.HasValue)
							{
								LessRam.Logger.LogError((object)$"{iteration} no value");
								return;
							}
							List<(VGLevel, VGLevelWrapper)> list = new List<(VGLevel, VGLevelWrapper)>(val3.Value.ResultCount);
							ResultPage value2 = val3.Value;
							foreach (Item entry2 in ((ResultPage)(ref value2)).Entries)
							{
								Item current2 = entry2;
								if (SingletonBase<ArcadeManager>.Inst.skippedLoad)
								{
									return;
								}
								if (((Item)(ref current2)).IsInstalled)
								{
									(VGLevel, VGLevelWrapper)? tuple2 = CreateEntry(facepunch, current2);
									if (tuple2.HasValue)
									{
										list.Add(tuple2.Value);
									}
								}
							}
							lock (_lockObject)
							{
								foreach (var item in list)
								{
									LessRam.Levels.Add(((Object)item.Item1).name, item.Item2);
									SingletonBase<ArcadeLevelDataManager>.Inst.ArcadeLevels.Add(item.Item1);
									SteamWorkshopFacepunch obj2 = facepunch;
									obj2.TotalSteamWorkshopSubscriptionsDone++;
								}
							}
						}
						finally
						{
							LessRam.Logger.LogError((object)$"{iteration} Release");
							semaphore.Release();
						}
					}));
				}
				await Task.WhenAll(tasks);
				stopWatch.Stop();
				SteamWorkshopFacepunch.inst.isLoadingLevels = false;
				LessRam.Logger.LogInfo((object)$"Time to load levels [{stopWatch.ElapsedMilliseconds}ms]");
			}
			finally
			{
				if (semaphore != null)
				{
					((IDisposable)semaphore).Dispose();
				}
			}
		}

		private static (VGLevel, VGLevelWrapper)? CreateEntry(SteamWorkshopFacepunch facepunch, Item entry)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			VGLevelWrapper vGLevelWrapper = MakeLevelRealmObject(((object)((Item)(ref entry)).Id/*cast due to .constrained prefix*/).ToString(), ((Item)(ref entry)).Directory);
			if (vGLevelWrapper == null)
			{
				return null;
			}
			VGLevel val = ScriptableObject.CreateInstance<VGLevel>();
			if (val.InitArcadeData(((Item)(ref entry)).Directory) && val.InitSteamInfoFix(PublishedFileId.op_Implicit(((Item)(ref entry)).Id), ((Item)(ref entry)).Directory))
			{
				((Object)val).name = ((object)((Item)(ref entry)).Id/*cast due to .constrained prefix*/).ToString();
				return (val, vGLevelWrapper);
			}
			return null;
		}

		private static VGLevelWrapper? MakeLevelRealmObject(string id, string directory)
		{
			if (string.IsNullOrEmpty(directory))
			{
				return null;
			}
			VGLevelWrapper obj = new VGLevelWrapper
			{
				LevelPath = directory
			};
			FileTypeDefinition fileTypeInfo = DataManager.inst.GetFileTypeInfo((FileType)5);
			string text = directory + "\\" + fileTypeInfo.CurrentFile;
			if (!LSFile.FileExists(text))
			{
				text = directory + "\\" + fileTypeInfo.LegacyFile;
			}
			obj.ImagePath = text;
			FileTypeDefinition fileTypeInfo2 = DataManager.inst.GetFileTypeInfo((FileType)2);
			string text2 = directory + "\\" + fileTypeInfo2.CurrentFile;
			if (!LSFile.FileExists(text2))
			{
				text2 = directory + "\\" + fileTypeInfo2.LegacyFile;
			}
			obj.AudioPath = text2;
			return obj;
		}
	}
	[HarmonyPatch(typeof(ArcadeMenu))]
	public static class ArcadeMenuPatch
	{
		private static List<Coroutine> activeCoroutines = new List<Coroutine>();

		public static readonly List<Sprite> activeSprites = new List<Sprite>();

		public static readonly List<AudioClip> activeClips = new List<AudioClip>();

		[HarmonyPatch("SelectPage", new Type[]
		{
			typeof(int),
			typeof(bool)
		})]
		[HarmonyPrefix]
		private static bool PreSelectPage(int _page, bool _forceButton, ArcadeMenu __instance)
		{
			((MonoBehaviour)__instance).StartCoroutine(SelectPage(_page, _forceButton, __instance));
			return false;
		}

		public static void CleanLevels()
		{
			foreach (Coroutine activeCoroutine in activeCoroutines)
			{
				if (activeCoroutine != null)
				{
					((MonoBehaviour)SingletonBase<ArcadeLevelDataManager>.Inst).StopCoroutine(activeCoroutine);
				}
			}
			activeCoroutines.Clear();
			int num = 0;
			while (num < activeClips.Count)
			{
				if (Object.op_Implicit((Object)(object)activeClips[num]) && (Object)(object)SingletonBase<AudioManager>.Inst.CurrentAudioClip != (Object)(object)activeClips[num] && (!Object.op_Implicit((Object)(object)SingletonBase<ArcadeManager>.Inst.CurrentArcadeLevel) || (Object)(object)SingletonBase<ArcadeManager>.Inst.CurrentArcadeLevel.LevelMusic != (Object)(object)activeClips[num]))
				{
					Object.Destroy((Object)(object)activeClips[num]);
					activeClips.RemoveAt(num);
				}
				else
				{
					num++;
				}
			}
			int num2 = 0;
			while (num2 < activeSprites.Count)
			{
				if (Object.op_Implicit((Object)(object)activeSprites[num2]) && (!Object.op_Implicit((Object)(object)SingletonBase<ArcadeManager>.Inst.CurrentArcadeLevel) || (Object)(object)SingletonBase<ArcadeManager>.Inst.CurrentArcadeLevel.AlbumArt != (Object)(object)activeSprites[num2]))
				{
					Object.Destroy((Object)(object)activeSprites[num2].texture);
					Object.Destroy((Object)(object)activeSprites[num2]);
					activeSprites.RemoveAt(num2);
				}
				else
				{
					num2++;
				}
			}
		}

		private static IEnumerator SelectPage(int _page, bool _forceButton, ArcadeMenu arcadeMenu)
		{
			CleanLevels();
			if (arcadeMenu.Page != _page)
			{
				SingletonBase<AudioManager>.Inst.PlaySound("PageSwap", 1f);
			}
			if (arcadeMenu.SearchedLevels.Count <= 0)
			{
				if (arcadeMenu.SearchedLevels.Count > 0)
				{
					arcadeMenu.ShowNoResults();
				}
				else
				{
					arcadeMenu.ShowNoLevels();
				}
			}
			else
			{
				if (_page < 0 || (arcadeMenu.SearchedLevels.Count > 0 && _page * 12 >= arcadeMenu.SearchedLevels.Count))
				{
					yield break;
				}
				if (((UIElement)arcadeMenu.NoResults).IsVisible)
				{
					((UIElement)arcadeMenu.NoResults).Hide((Action)null);
				}
				if (((UIElement)arcadeMenu.NoLevels).IsVisible)
				{
					((UIElement)arcadeMenu.NoLevels).Hide((Action)null);
				}
				if (((UIElement)arcadeMenu.KeyboardButtons[0].UIButton).IsVisible)
				{
					arcadeMenu.HideAllKeyboardButtons();
				}
				arcadeMenu.PageIsChanging = true;
				((MonoBehaviour)arcadeMenu).StartCoroutine(arcadeMenu.DelayAnim(_forceButton));
				arcadeMenu.Page = _page;
				int num = _page * 12;
				int num2 = Mathf.Clamp(num + 12, 0, arcadeMenu.SearchedLevels.Count - 1) - num;
				arcadeMenu.PageSlider.UpdateValueAndRange((float)_page, new Vector2(0f, Mathf.Ceil((float)((arcadeMenu.SearchedLevels.Count - 1) / 12))), new Vector2(0f, 9f));
				arcadeMenu.PageSlider.UpdateValue(false);
				((Selectable)arcadeMenu.PageSlider.LeftButton).interactable = !arcadeMenu.IsFirstPage();
				((Selectable)arcadeMenu.PageSlider.RightButton).interactable = !arcadeMenu.IsLastPage();
				((Component)arcadeMenu.LeftPageTrigger).gameObject.SetActive(true);
				((Component)arcadeMenu.RightPageTrigger).gameObject.SetActive(true);
				((Selectable)arcadeMenu.LeftPageTrigger).interactable = !arcadeMenu.IsFirstPage();
				((Selectable)arcadeMenu.RightPageTrigger).interactable = !arcadeMenu.IsLastPage();
				int num3 = 0;
				foreach (ArcadeButtonRefs button in arcadeMenu.LevelButtons)
				{
					if (num3 > num2)
					{
						button.Button.ClearActions();
						button.Button.LockButtonState(true);
						((UnityEventBase)((Button)button.Button).onClick).RemoveAllListeners();
						if (((UIElement)button.LevelButton).IsVisible)
						{
							LSHelpers.Delay(Random.Range(0f, 0.025f), (Action)delegate
							{
								((UIElement)button.LevelButton).Hide((Action)null);
							});
						}
					}
					else
					{
						activeCoroutines.Add(((MonoBehaviour)SingletonBase<ArcadeLevelDataManager>.Inst).StartCoroutine(CreateButton(button, arcadeMenu.SearchedLevels[num + num3], arcadeMenu)));
					}
					num3++;
				}
			}
		}

		private static IEnumerator CreateButton(ArcadeButtonRefs button, VGLevel level, ArcadeMenu arcadeMenu)
		{
			VGLevelWrapper valueOrDefault = LessRam.Levels.GetValueOrDefault(((Object)level).name, null);
			if (valueOrDefault != null)
			{
				Coroutine val = ((MonoBehaviour)arcadeMenu).StartCoroutine(LevelLoaderHelper.LoadAudio(level, valueOrDefault.AudioPath));
				Coroutine coroutine2 = ((MonoBehaviour)arcadeMenu).StartCoroutine(LevelLoaderHelper.LoadImage(level, valueOrDefault.ImagePath));
				yield return val;
				yield return coroutine2;
			}
			DifficultySetting difficulty = arcadeMenu.GetDifficulty(level.Difficulty);
			((Component)button.Button).GetComponent<DirectedNavigation>().Active = false;
			button.Button.LockButtonState(true);
			((UnityEventBase)((Button)button.Button).onClick).RemoveAllListeners();
			button.Button.ClearActions();
			button.Button.OnSelectButton += delegate
			{
				arcadeMenu.LastSelectedButtonOffset = 0;
				arcadeMenu.LastSelectedButton = ((Component)button.Button).gameObject;
				arcadeMenu.selectedLevelGO = ((Component)button.Button).gameObject;
				arcadeMenu._songPreviewDebounce.Run((Action)delegate
				{
					arcadeMenu.PlaySongPreview(level);
				}, 0.6f, (MonoBehaviour)(object)arcadeMenu);
			};
			button.Button.OnHoverEnterButton += delegate
			{
				arcadeMenu.LastSelectedButtonOffset = 0;
				arcadeMenu.LastSelectedButton = ((Component)button.Button).gameObject;
				arcadeMenu.selectedLevelGO = ((Component)button.Button).gameObject;
				arcadeMenu._songPreviewDebounce.Run((Action)delegate
				{
					arcadeMenu.PlaySongPreview(level);
				}, 0.3f, (MonoBehaviour)(object)arcadeMenu);
			};
			((UnityEvent)((Button)button.Button).onClick).AddListener((UnityAction)delegate
			{
				arcadeMenu.LastSelectedButtonOffset = 0;
				arcadeMenu.LastSelectedButton = ((Component)button.Button).gameObject;
				arcadeMenu.selectedLevelGO = ((Component)button.Button).gameObject;
				if (SingletonBase<AudioManager>.Inst.currentSongGroup == level.TrackName)
				{
					arcadeMenu._songPreviewDebounce.ResetTime((MonoBehaviour)(object)arcadeMenu);
				}
				arcadeMenu.SetupSongMenu(level);
				((Selectable)arcadeMenu.LeftPageTrigger).interactable = false;
				((Selectable)arcadeMenu.RightPageTrigger).interactable = false;
				arcadeMenu.SetSelectedGO((GameObject)null);
				arcadeMenu.ViewManager.SwapPage("Song Menu");
			});
			button.LevelButton.UpdateTitle(LSText.ClampString(level.TrackName, 20, " -"));
			button.LevelButton.UpdateDifficulty(difficulty);
			button.LevelButton.UpdateAlbumArt(level.AlbumArt);
			button.LevelButton.UpdateContent(arcadeMenu.getLevelButtonContent(level));
			button.LevelButton.UpdateRank(SingletonBase<SavesManager>.Inst.FetchArcadeSave(level.LevelData.LevelID, true).LevelRank);
			((UIElement)button.LevelButton).Stutter(true, (Action)null);
			((UIElement)button.LevelButton).Show(0f, 0.1f);
			((Component)button.Button).GetComponent<DirectedNavigation>().Active = true;
			button.Button.LockButtonState(false);
		}
	}
	[HarmonyPatch(typeof(ArcadeLevelDataManager))]
	public static class ArcadeDataPatch
	{
		[HarmonyPatch("GetLocalCustomLevel")]
		[HarmonyPostfix]
		private static void preGetLevel(ArcadeLevelDataManager __instance, string _id, ref VGLevel __result)
		{
			if (Object.op_Implicit((Object)(object)__result) && !Object.op_Implicit((Object)(object)__result.LevelMusic))
			{
				VGLevelWrapper valueOrDefault = LessRam.Levels.GetValueOrDefault(_id, null);
				if (valueOrDefault != null)
				{
					((MonoBehaviour)__instance).StartCoroutine(LevelLoaderHelper.LoadAudio(__result, valueOrDefault.AudioPath));
					((MonoBehaviour)__instance).StartCoroutine(LevelLoaderHelper.LoadImage(__result, valueOrDefault.ImagePath));
				}
			}
		}
	}
	[HarmonyPatch(typeof(LSText))]
	public static class LSTextPatch
	{
		[HarmonyPatch("ClampString")]
		[HarmonyPrefix]
		private static bool PreClamp(ref string __result, string _inputStr, int _maxLength, string _end)
		{
			if (!SteamWorkshopFacepunch.inst.isLoadingLevels)
			{
				return true;
			}
			if (string.IsNullOrEmpty(_inputStr) || _inputStr.Length <= _maxLength)
			{
				__result = _inputStr;
				return false;
			}
			StringBuilder stringBuilder = new StringBuilder();
			if (_end == null)
			{
				stringBuilder.Append(_inputStr.Substring(0, _maxLength));
			}
			else
			{
				stringBuilder.Append(_inputStr.Substring(0, _maxLength - (_end.Length - 1)));
				stringBuilder.Append(_end);
			}
			__result = stringBuilder.ToString();
			return false;
		}
	}
	public class VGLevelWrapper
	{
		public string ImagePath { get; set; }

		public string AudioPath { get; set; }

		public string LevelPath { get; set; }
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "LessRam";

		public const string PLUGIN_NAME = "LessRam";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}