using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using MonoMod.RuntimeDetour;
using Photon.Pun.Simple;
using RoundsDashLoader.Patches;
using RoundsDashLoader.Utils;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Scripting;
[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("RoundsDashLoader")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RoundsDashLoader")]
[assembly: AssemblyTitle("RoundsDashLoader")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[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 RoundsDashLoader
{
public static class Patcher
{
public static IEnumerable<string> TargetDLLs => Array.Empty<string>();
public static void Patch(AssemblyDefinition assembly)
{
}
public static void Initialize()
{
try
{
HarmonyTypeCachePatch.InstallGlobalHooks();
}
catch
{
}
}
}
[BepInPlugin("000_rounds_dashloader", "RoundsDashLoader", "1.0.5")]
[BepInProcess("Rounds.exe")]
public class RoundsDashLoaderPlugin : BaseUnityPlugin
{
public const string ModId = "000_rounds_dashloader";
public const string ModName = "RoundsDashLoader";
public const string ModVersion = "1.0.5";
private static Stopwatch bootStopwatch;
private static float totalBootTimeSeconds = -1f;
private static bool isBootDone = false;
public static RoundsDashLoaderPlugin Instance { get; private set; }
public static ManualLogSource Logger { get; private set; }
private void Awake()
{
//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_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Expected O, but got Unknown
//IL_006d: Expected O, but got Unknown
Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
bootStopwatch = Stopwatch.StartNew();
Logger.LogInfo((object)"[RoundsDashLoader] v1.0.5 initializing Ultra-DashLoader acceleration pipeline...");
try
{
QualitySettings.asyncUploadBufferSize = 32;
QualitySettings.asyncUploadTimeSlice = 4;
QualitySettings.asyncUploadPersistentBuffer = true;
Application.backgroundLoadingPriority = (ThreadPriority)4;
}
catch
{
}
DiskCacheUtil.Initialize();
HarmonyTypeCachePatch.InstallGlobalHooks();
try
{
Harmony val = new Harmony("000_rounds_dashloader");
val.PatchAll();
CombatOptimizationPatch.ApplyDynamicGuards(val);
EveryonePicksPatch.Apply(val);
Logger.LogInfo((object)"[RoundsDashLoader] Ultra-fast reflection caching, texture streaming & intro bypass patches active.");
}
catch (Exception arg)
{
Logger.LogError((object)$"[RoundsDashLoader] Error applying patches: {arg}");
}
}
public static void OnBootCompleted()
{
if (!isBootDone)
{
isBootDone = true;
if (bootStopwatch != null)
{
bootStopwatch.Stop();
totalBootTimeSeconds = (float)bootStopwatch.ElapsedMilliseconds / 1000f;
}
Logger.LogInfo((object)"============================================================");
Logger.LogInfo((object)$"⚡ [RoundsDashLoader] LIGHTNING BOOT COMPLETE in {totalBootTimeSeconds:F2}s!");
Logger.LogInfo((object)$"⚡ [RoundsDashLoader] Reflection Type Hits: {HarmonyTypeCachePatch.CacheHits} (Saved MMHOOK churn)");
Logger.LogInfo((object)$"⚡ [RoundsDashLoader] Texture Cache Hits: {TextureCachePatch.CacheHits} | New Decodes Cached: {TextureCachePatch.DecodedTextures}");
Logger.LogInfo((object)"⚡ [RoundsDashLoader] Intro videos and splash screens bypassed.");
Logger.LogInfo((object)"============================================================");
}
}
private void OnGUI()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: 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)
if (isBootDone && !(totalBootTimeSeconds <= 0f) && Time.timeSinceLevelLoad < 25f)
{
Color color = GUI.color;
GUI.color = new Color(0.2f, 1f, 0.6f, 0.85f);
string text = $"⚡ DashLoader: {totalBootTimeSeconds:F2}s boot";
GUI.Label(new Rect(15f, 12f, 300f, 24f), text);
GUI.color = color;
}
}
}
}
namespace RoundsDashLoader.Utils
{
public static class DiskCacheUtil
{
private static string cacheDir;
private static bool initialized;
public static void Initialize()
{
if (initialized)
{
return;
}
try
{
cacheDir = Path.Combine(Paths.CachePath, "RoundsDashLoader", "textures");
if (!Directory.Exists(cacheDir))
{
Directory.CreateDirectory(cacheDir);
}
initialized = true;
}
catch (Exception ex)
{
Debug.LogWarning("[RoundsDashLoader] Could not initialize disk cache directory: " + ex.Message);
}
}
public static bool TryLoad(long hash, out byte[] rawBytes, out int width, out int height, out TextureFormat format)
{
rawBytes = null;
width = 0;
height = 0;
format = (TextureFormat)4;
if (!initialized || string.IsNullOrEmpty(cacheDir))
{
return false;
}
string path = Path.Combine(cacheDir, $"{hash:X16}.bin");
if (!File.Exists(path))
{
return false;
}
try
{
using FileStream input = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 8192);
using BinaryReader binaryReader = new BinaryReader(input);
width = binaryReader.ReadInt32();
height = binaryReader.ReadInt32();
format = (TextureFormat)binaryReader.ReadInt32();
int num = binaryReader.ReadInt32();
rawBytes = binaryReader.ReadBytes(num);
return rawBytes != null && rawBytes.Length == num;
}
catch
{
return false;
}
}
public static void Save(long hash, byte[] rawBytes, int width, int height, TextureFormat format)
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Expected I4, but got Unknown
if (!initialized || string.IsNullOrEmpty(cacheDir) || rawBytes == null || rawBytes.Length == 0)
{
return;
}
string path = Path.Combine(cacheDir, $"{hash:X16}.bin");
try
{
using FileStream output = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 8192);
using BinaryWriter binaryWriter = new BinaryWriter(output);
binaryWriter.Write(width);
binaryWriter.Write(height);
binaryWriter.Write((int)format);
binaryWriter.Write(rawBytes.Length);
binaryWriter.Write(rawBytes);
}
catch
{
}
}
}
public static class FastHashUtil
{
private const ulong FnvOffsetBasis = 14695981039346656037uL;
private const ulong FnvPrime = 1099511628211uL;
public static long ComputeHash(byte[] data)
{
if (data == null || data.Length == 0)
{
return 0L;
}
ulong num = 14695981039346656037uL;
int num2 = data.Length;
int num3 = ((num2 <= 131072) ? 1 : (num2 / 2048));
for (int i = 0; i < num2; i += num3)
{
num ^= data[i];
num *= 1099511628211L;
}
return (long)num ^ (long)num2;
}
}
}
namespace RoundsDashLoader.Patches
{
[HarmonyPatch]
public static class CombatOptimizationPatch
{
public static bool IsInCombat { get; private set; }
public static void SetCombatMode(bool active)
{
if (IsInCombat == active)
{
return;
}
IsInCombat = active;
try
{
if (active)
{
GarbageCollector.GCMode = (Mode)0;
}
else
{
GarbageCollector.GCMode = (Mode)1;
}
}
catch
{
}
}
[HarmonyPatch(typeof(GM_ArmsRace), "StartGame")]
[HarmonyPostfix]
public static void Postfix_StartGame()
{
SetCombatMode(active: true);
}
[HarmonyPatch(typeof(GM_ArmsRace), "DoStartGame")]
[HarmonyPostfix]
public static void Postfix_DoStartGame()
{
SetCombatMode(active: true);
}
[HarmonyPatch(typeof(GM_ArmsRace), "PointOver")]
[HarmonyPrefix]
public static void Prefix_PointOver()
{
SetCombatMode(active: false);
}
[HarmonyPatch(typeof(GM_ArmsRace), "RoundOver")]
[HarmonyPrefix]
public static void Prefix_RoundOver()
{
SetCombatMode(active: false);
}
[HarmonyPatch(typeof(GM_ArmsRace), "GameOver")]
[HarmonyPrefix]
public static void Prefix_GameOver()
{
SetCombatMode(active: false);
}
[HarmonyPatch(typeof(CardChoice), "StartPick")]
[HarmonyPrefix]
public static void Prefix_StartPick()
{
SetCombatMode(active: false);
}
[HarmonyPatch(typeof(CardChoice), "RPCA_DonePicking")]
[HarmonyPostfix]
public static void Postfix_DonePicking()
{
SetCombatMode(active: false);
}
[HarmonyPatch(typeof(NetworkPhysicsObject), "OnCollisionEnter2D")]
[HarmonyPrefix]
public static bool Prefix_OnCollisionEnter2D(NetworkPhysicsObject __instance, Collision2D collision)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.photonView == (Object)null || collision == null || collision.contacts == null || collision.contacts.Length == 0)
{
return false;
}
return true;
}
[HarmonyPatch(typeof(Player), "FullReset")]
[HarmonyPrefix]
[HarmonyPriority(800)]
public static bool Prefix_PlayerFullReset(Player __instance)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).gameObject == (Object)null || (Object)(object)__instance.data == (Object)null)
{
return false;
}
return true;
}
public static void ApplyDynamicGuards(Harmony harmony)
{
//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_004c: Expected O, but got Unknown
try
{
Type type = AccessTools.TypeByName("ModdingUtils.Patches.PlayerPatchFullReset");
if (type != null)
{
MethodInfo methodInfo = AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null);
if (methodInfo != null)
{
HarmonyMethod val = new HarmonyMethod(typeof(CombatOptimizationPatch), "Guard_ModdingUtils_Prefix", (Type[])null)
{
priority = 800
};
harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
}
catch
{
}
}
public static bool Guard_ModdingUtils_Prefix(Player __instance)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).gameObject == (Object)null)
{
return false;
}
return true;
}
}
public static class EveryonePicksPatch
{
public static void Apply(Harmony harmony)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
try
{
Type type = AccessTools.TypeByName("EveryonePicks.PickBoard");
if (!(type == null))
{
MethodInfo methodInfo = AccessTools.Method(type, "Draw", (Type[])null, (Type[])null);
if (!(methodInfo == null))
{
HarmonyMethod val = new HarmonyMethod(typeof(EveryonePicksPatch), "Transpiler", (Type[])null);
harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
}
catch
{
}
}
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> list = instructions.ToList();
MethodInfo getWidth = AccessTools.PropertyGetter(typeof(Screen), "width");
for (int i = 0; i < list.Count - 1; i++)
{
if (list[i].opcode == OpCodes.Ldc_R4 && Convert.ToSingle(list[i].operand) == 18f && (list[i + 1].opcode == OpCodes.Stloc_S || list[i + 1].opcode == OpCodes.Stloc))
{
int num = -1;
if (list[i + 1].operand is LocalBuilder localBuilder)
{
num = localBuilder.LocalIndex;
}
else if (list[i + 1].operand is int num2)
{
num = num2;
}
else if (list[i + 1].operand is byte b)
{
num = b;
}
if (num == 8)
{
yield return new CodeInstruction(OpCodes.Call, (object)getWidth);
yield return new CodeInstruction(OpCodes.Conv_R4, (object)null);
yield return new CodeInstruction(OpCodes.Ldloc_S, (object)5);
yield return new CodeInstruction(OpCodes.Sub, (object)null);
yield return new CodeInstruction(OpCodes.Ldc_R4, (object)18f);
yield return new CodeInstruction(OpCodes.Sub, (object)null);
yield return new CodeInstruction(list[i + 1].opcode, list[i + 1].operand);
i++;
continue;
}
}
yield return list[i];
}
if (list.Count > 0)
{
yield return list[list.Count - 1];
}
}
}
[HarmonyPatch]
public static class HarmonyTypeCachePatch
{
private static readonly ConcurrentDictionary<Assembly, Type[]> AssemblyTypesCache = new ConcurrentDictionary<Assembly, Type[]>();
private static readonly ConcurrentDictionary<Assembly, Type[]> AssemblyExportedTypesCache = new ConcurrentDictionary<Assembly, Type[]>();
private static readonly ConcurrentDictionary<string, Type> TypeNameCache = new ConcurrentDictionary<string, Type>(StringComparer.Ordinal);
private static readonly ConcurrentDictionary<string, MethodInfo> MethodCache = new ConcurrentDictionary<string, MethodInfo>(StringComparer.Ordinal);
private static readonly ConcurrentDictionary<string, FieldInfo> FieldCache = new ConcurrentDictionary<string, FieldInfo>(StringComparer.Ordinal);
private static readonly ConcurrentDictionary<string, PropertyInfo> PropertyCache = new ConcurrentDictionary<string, PropertyInfo>(StringComparer.Ordinal);
private static Hook hookGetTypes;
private static Hook hookGetExportedTypes;
public static int CacheHits = 0;
public static int FastScans = 0;
public static void InstallGlobalHooks()
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Expected O, but got Unknown
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Expected O, but got Unknown
try
{
HarmonyGlobalSettings.DisallowLegacyGlobalUnpatchAll = true;
MethodInfo method = typeof(Assembly).GetMethod("GetTypes", Type.EmptyTypes);
MethodInfo method2 = typeof(HarmonyTypeCachePatch).GetMethod("Hook_GetTypes", BindingFlags.Static | BindingFlags.Public);
if (method != null && method2 != null)
{
hookGetTypes = new Hook((MethodBase)method, method2);
}
MethodInfo method3 = typeof(Assembly).GetMethod("GetExportedTypes", Type.EmptyTypes);
MethodInfo method4 = typeof(HarmonyTypeCachePatch).GetMethod("Hook_GetExportedTypes", BindingFlags.Static | BindingFlags.Public);
if (method3 != null && method4 != null)
{
hookGetExportedTypes = new Hook((MethodBase)method3, method4);
}
ManualLogSource logger = RoundsDashLoaderPlugin.Logger;
if (logger != null)
{
logger.LogInfo((object)"[RoundsDashLoader] Global CLR reflection hooks (Assembly.GetTypes & GetExportedTypes) active.");
}
}
catch (Exception ex)
{
ManualLogSource logger2 = RoundsDashLoaderPlugin.Logger;
if (logger2 != null)
{
logger2.LogWarning((object)("[RoundsDashLoader] Reflection hooks note: " + ex.Message));
}
}
}
public static Type[] Hook_GetTypes(Func<Assembly, Type[]> orig, Assembly self)
{
if (self == null)
{
return Type.EmptyTypes;
}
if (AssemblyTypesCache.TryGetValue(self, out var value))
{
Interlocked.Increment(ref CacheHits);
return value;
}
Type[] array;
try
{
array = orig(self);
}
catch (ReflectionTypeLoadException ex)
{
array = ((ex.Types != null) ? ex.Types.Where((Type t) => t != null).ToArray() : Type.EmptyTypes);
}
catch
{
array = Type.EmptyTypes;
}
AssemblyTypesCache[self] = array;
Interlocked.Increment(ref FastScans);
return array;
}
public static Type[] Hook_GetExportedTypes(Func<Assembly, Type[]> orig, Assembly self)
{
if (self == null)
{
return Type.EmptyTypes;
}
if (AssemblyExportedTypesCache.TryGetValue(self, out var value))
{
Interlocked.Increment(ref CacheHits);
return value;
}
Type[] array;
try
{
array = orig(self);
}
catch (ReflectionTypeLoadException ex)
{
array = ((ex.Types != null) ? ex.Types.Where((Type t) => t != null).ToArray() : Type.EmptyTypes);
}
catch
{
array = Type.EmptyTypes;
}
AssemblyExportedTypesCache[self] = array;
Interlocked.Increment(ref FastScans);
return array;
}
[HarmonyPatch(typeof(AccessTools), "GetTypesFromAssembly")]
[HarmonyPrefix]
public static bool Prefix_GetTypesFromAssembly(Assembly assembly, ref Type[] __result)
{
if (assembly == null)
{
__result = Type.EmptyTypes;
return false;
}
if (AssemblyTypesCache.TryGetValue(assembly, out var value))
{
Interlocked.Increment(ref CacheHits);
__result = value;
return false;
}
Type[] array;
try
{
array = assembly.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
array = ((ex.Types != null) ? ex.Types.Where((Type t) => t != null).ToArray() : Type.EmptyTypes);
}
catch
{
array = Type.EmptyTypes;
}
AssemblyTypesCache[assembly] = array;
Interlocked.Increment(ref FastScans);
__result = array;
return false;
}
[HarmonyPatch(typeof(AccessTools), "TypeByName")]
[HarmonyPrefix]
public static bool Prefix_TypeByName(string name, ref Type __result)
{
if (string.IsNullOrEmpty(name))
{
return true;
}
if (TypeNameCache.TryGetValue(name, out var value))
{
Interlocked.Increment(ref CacheHits);
__result = value;
return false;
}
return true;
}
[HarmonyPatch(typeof(AccessTools), "TypeByName")]
[HarmonyPostfix]
public static void Postfix_TypeByName(string name, Type __result)
{
if (!string.IsNullOrEmpty(name) && __result != null)
{
TypeNameCache[name] = __result;
}
}
[HarmonyPatch(typeof(AccessTools), "Method", new Type[]
{
typeof(Type),
typeof(string),
typeof(Type[]),
typeof(Type[])
})]
[HarmonyPrefix]
public static bool Prefix_Method(Type type, string name, Type[] parameters, Type[] generics, ref MethodInfo __result)
{
if (type == null || string.IsNullOrEmpty(name))
{
return true;
}
string key = BuildMemberKey(type, name, parameters);
if (MethodCache.TryGetValue(key, out var value))
{
Interlocked.Increment(ref CacheHits);
__result = value;
return false;
}
return true;
}
[HarmonyPatch(typeof(AccessTools), "Method", new Type[]
{
typeof(Type),
typeof(string),
typeof(Type[]),
typeof(Type[])
})]
[HarmonyPostfix]
public static void Postfix_Method(Type type, string name, Type[] parameters, Type[] generics, MethodInfo __result)
{
if (type != null && !string.IsNullOrEmpty(name) && __result != null)
{
string key = BuildMemberKey(type, name, parameters);
MethodCache[key] = __result;
}
}
[HarmonyPatch(typeof(AccessTools), "Field", new Type[]
{
typeof(Type),
typeof(string)
})]
[HarmonyPrefix]
public static bool Prefix_Field(Type type, string name, ref FieldInfo __result)
{
if (type == null || string.IsNullOrEmpty(name))
{
return true;
}
string key = type.FullName + "::" + name;
if (FieldCache.TryGetValue(key, out var value))
{
Interlocked.Increment(ref CacheHits);
__result = value;
return false;
}
return true;
}
[HarmonyPatch(typeof(AccessTools), "Field", new Type[]
{
typeof(Type),
typeof(string)
})]
[HarmonyPostfix]
public static void Postfix_Field(Type type, string name, FieldInfo __result)
{
if (type != null && !string.IsNullOrEmpty(name) && __result != null)
{
string key = type.FullName + "::" + name;
FieldCache[key] = __result;
}
}
[HarmonyPatch(typeof(AccessTools), "Property", new Type[]
{
typeof(Type),
typeof(string)
})]
[HarmonyPrefix]
public static bool Prefix_Property(Type type, string name, ref PropertyInfo __result)
{
if (type == null || string.IsNullOrEmpty(name))
{
return true;
}
string key = type.FullName + "::" + name;
if (PropertyCache.TryGetValue(key, out var value))
{
Interlocked.Increment(ref CacheHits);
__result = value;
return false;
}
return true;
}
[HarmonyPatch(typeof(AccessTools), "Property", new Type[]
{
typeof(Type),
typeof(string)
})]
[HarmonyPostfix]
public static void Postfix_Property(Type type, string name, PropertyInfo __result)
{
if (type != null && !string.IsNullOrEmpty(name) && __result != null)
{
string key = type.FullName + "::" + name;
PropertyCache[key] = __result;
}
}
private static string BuildMemberKey(Type type, string name, Type[] parameters)
{
if (parameters == null || parameters.Length == 0)
{
return type.FullName + "::" + name;
}
return type.FullName + "::" + name + "(" + string.Join(",", parameters.Select((Type p) => (!(p != null)) ? "null" : p.Name)) + ")";
}
[HarmonyPatch(typeof(ContactTrigger), "FindDerivedTypesFromAssembly")]
[HarmonyFinalizer]
public static Exception Finalizer_ContactTrigger(Exception __exception)
{
if (__exception != null)
{
Interlocked.Increment(ref CacheHits);
return null;
}
return null;
}
}
[HarmonyPatch]
public static class IntroAndMenuSkipPatch
{
private static bool skipped;
[HarmonyPatch(typeof(SkipIntro), "Start")]
[HarmonyPostfix]
public static void Postfix_SkipIntroStart(SkipIntro __instance)
{
if ((Object)(object)__instance == (Object)null || skipped)
{
return;
}
try
{
if ((Object)(object)__instance.target != (Object)null)
{
skipped = true;
__instance.target.Open();
}
}
catch
{
}
}
[HarmonyPatch(typeof(SkipIntro), "Update")]
[HarmonyPostfix]
public static void Postfix_SkipIntroUpdate(SkipIntro __instance)
{
if ((Object)(object)__instance == (Object)null || skipped)
{
return;
}
try
{
if ((Object)(object)__instance.target != (Object)null)
{
skipped = true;
__instance.target.Open();
}
}
catch
{
}
}
}
[HarmonyPatch]
public static class MainMenuHandlerPatch
{
private static bool booted;
[HarmonyPatch(typeof(MainMenuHandler), "Awake")]
[HarmonyPostfix]
public static void Postfix_Awake()
{
if (!booted)
{
booted = true;
try
{
QualitySettings.asyncUploadTimeSlice = 4;
QualitySettings.asyncUploadBufferSize = 32;
QualitySettings.asyncUploadPersistentBuffer = true;
Application.backgroundLoadingPriority = (ThreadPriority)4;
}
catch
{
}
try
{
TextureCachePatch.ClearMemoryCache();
}
catch
{
}
RoundsDashLoaderPlugin.OnBootCompleted();
}
}
}
[HarmonyPatch(typeof(Shader), "Find")]
public static class ShaderCachePatch
{
private static readonly ConcurrentDictionary<string, Shader> ShaderCache = new ConcurrentDictionary<string, Shader>(StringComparer.Ordinal);
[HarmonyPrefix]
public static bool Prefix(string name, ref Shader __result)
{
if (string.IsNullOrEmpty(name))
{
return true;
}
if (ShaderCache.TryGetValue(name, out var value))
{
__result = value;
return false;
}
return true;
}
[HarmonyPostfix]
public static void Postfix(string name, Shader __result)
{
if (!string.IsNullOrEmpty(name) && (Object)(object)__result != (Object)null)
{
ShaderCache[name] = __result;
}
}
}
[HarmonyPatch(typeof(SplashScreen), "get_isFinished")]
public static class SplashScreenPatch
{
[HarmonyPrefix]
public static bool Prefix(ref bool __result)
{
__result = true;
return false;
}
}
[HarmonyPatch]
public static class TextureCachePatch
{
private static readonly ConcurrentDictionary<long, byte[]> MemRawCache = new ConcurrentDictionary<long, byte[]>();
private static readonly ConcurrentDictionary<long, (int width, int height, TextureFormat format)> MemFormatCache = new ConcurrentDictionary<long, (int, int, TextureFormat)>();
public static int DecodedTextures = 0;
public static int CacheHits = 0;
[HarmonyPatch(typeof(ImageConversion), "LoadImage", new Type[]
{
typeof(Texture2D),
typeof(byte[])
})]
[HarmonyPrefix]
public static bool Prefix_LoadImage2(Texture2D tex, byte[] data, ref bool __result)
{
return PrefixInternal(tex, data, markNonReadable: false, ref __result);
}
[HarmonyPatch(typeof(ImageConversion), "LoadImage", new Type[]
{
typeof(Texture2D),
typeof(byte[])
})]
[HarmonyPostfix]
public static void Postfix_LoadImage2(Texture2D tex, byte[] data, bool __result)
{
PostfixInternal(tex, data, markNonReadable: false, __result);
}
[HarmonyPatch(typeof(ImageConversion), "LoadImage", new Type[]
{
typeof(Texture2D),
typeof(byte[]),
typeof(bool)
})]
[HarmonyPrefix]
public static bool Prefix_LoadImage3(Texture2D tex, byte[] data, bool markNonReadable, ref bool __result)
{
return PrefixInternal(tex, data, markNonReadable, ref __result);
}
[HarmonyPatch(typeof(ImageConversion), "LoadImage", new Type[]
{
typeof(Texture2D),
typeof(byte[]),
typeof(bool)
})]
[HarmonyPostfix]
public static void Postfix_LoadImage3(Texture2D tex, byte[] data, bool markNonReadable, bool __result)
{
PostfixInternal(tex, data, markNonReadable, __result);
}
private static bool PrefixInternal(Texture2D tex, byte[] data, bool markNonReadable, ref bool __result)
{
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)tex == (Object)null || data == null || data.Length == 0)
{
return true;
}
long num = FastHashUtil.ComputeHash(data);
if (MemRawCache.TryGetValue(num, out var value) && MemFormatCache.TryGetValue(num, out (int, int, TextureFormat) value2) && ApplyRawToTexture(tex, value, value2.Item1, value2.Item2, value2.Item3, markNonReadable))
{
Interlocked.Increment(ref CacheHits);
__result = true;
return false;
}
if (DiskCacheUtil.TryLoad(num, out var rawBytes, out var width, out var height, out var format))
{
MemRawCache[num] = rawBytes;
MemFormatCache[num] = (width, height, format);
if (ApplyRawToTexture(tex, rawBytes, width, height, format, markNonReadable))
{
Interlocked.Increment(ref CacheHits);
__result = true;
return false;
}
}
return true;
}
private static void PostfixInternal(Texture2D tex, byte[] data, bool markNonReadable, bool __result)
{
//IL_0055: 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)
if (!__result || (Object)(object)tex == (Object)null || data == null || data.Length == 0)
{
return;
}
long num = FastHashUtil.ComputeHash(data);
if (MemRawCache.ContainsKey(num))
{
return;
}
try
{
byte[] rawTextureData = tex.GetRawTextureData();
if (rawTextureData != null && rawTextureData.Length != 0)
{
MemRawCache[num] = rawTextureData;
MemFormatCache[num] = (((Texture)tex).width, ((Texture)tex).height, tex.format);
DiskCacheUtil.Save(num, rawTextureData, ((Texture)tex).width, ((Texture)tex).height, tex.format);
Interlocked.Increment(ref DecodedTextures);
}
}
catch
{
}
}
private static bool ApplyRawToTexture(Texture2D tex, byte[] raw, int w, int h, TextureFormat format, bool nonReadable)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
try
{
tex.Resize(w, h, format, false);
tex.LoadRawTextureData(raw);
tex.Apply(false, nonReadable);
return true;
}
catch
{
return false;
}
}
public static void ClearMemoryCache()
{
MemRawCache.Clear();
MemFormatCache.Clear();
}
}
}