Skip to content
This repository was archived by the owner on May 9, 2023. It is now read-only.

Commit 50f0c31

Browse files
committed
Add patch for asset bundle unloading to prevent UnityExplorer's bundle being unloaded
1 parent 9115224 commit 50f0c31

File tree

1 file changed

+79
-27
lines changed

1 file changed

+79
-27
lines changed

src/UI/UIManager.cs

Lines changed: 79 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
using System;
1+
using HarmonyLib;
2+
using System;
3+
using System.Collections;
24
using System.Collections.Generic;
35
using System.IO;
46
using System.Linq;
7+
using System.Reflection;
58
using System.Text;
69
using UnityEngine;
710
using UnityEngine.EventSystems;
@@ -40,18 +43,15 @@ public enum VerticalAnchor
4043

4144
public static bool Initializing { get; internal set; } = true;
4245

43-
private static readonly Dictionary<Panels, UIPanel> UIPanels = new Dictionary<Panels, UIPanel>();
44-
4546
public static VerticalAnchor NavbarAnchor = VerticalAnchor.Top;
4647

47-
// References
4848
public static GameObject CanvasRoot { get; private set; }
4949
public static Canvas Canvas { get; private set; }
5050
public static EventSystem EventSys { get; private set; }
5151

5252
internal static GameObject PoolHolder { get; private set; }
53-
5453
internal static GameObject PanelHolder { get; private set; }
54+
private static readonly Dictionary<Panels, UIPanel> UIPanels = new Dictionary<Panels, UIPanel>();
5555

5656
internal static Font ConsoleFont { get; private set; }
5757
internal static Font DefaultFont { get; private set; }
@@ -158,10 +158,6 @@ public static void Update()
158158
if (!ShowMenu)
159159
return;
160160

161-
// In case the bundle has been unloaded, reload it.
162-
if (!DefaultFont)
163-
LoadBundle();
164-
165161
// Check forceUnlockMouse toggle
166162
if (InputManager.GetKeyDown(ConfigManager.Force_Unlock_Toggle.Value))
167163
CursorUnlocker.Unlock = !CursorUnlocker.Unlock;
@@ -200,15 +196,9 @@ public static void Update()
200196

201197
// Panels
202198

203-
public static UIPanel GetPanel(Panels panel)
204-
{
205-
return UIPanels[panel];
206-
}
199+
public static UIPanel GetPanel(Panels panel) => UIPanels[panel];
207200

208-
public static T GetPanel<T>(Panels panel) where T : UIPanel
209-
{
210-
return (T)UIPanels[panel];
211-
}
201+
public static T GetPanel<T>(Panels panel) where T : UIPanel => (T)UIPanels[panel];
212202

213203
public static void TogglePanel(Panels panel)
214204
{
@@ -329,9 +319,14 @@ private static void CreateRootCanvas()
329319
CanvasRoot.layer = 5;
330320
CanvasRoot.transform.position = new Vector3(0f, 0f, 1f);
331321

322+
CanvasRoot.SetActive(false);
323+
332324
EventSys = CanvasRoot.AddComponent<EventSystem>();
333325
InputManager.AddUIModule();
334326

327+
EventSys.enabled = false;
328+
CanvasRoot.SetActive(true);
329+
335330
Canvas = CanvasRoot.AddComponent<Canvas>();
336331
Canvas.renderMode = RenderMode.ScreenSpaceCamera;
337332
Canvas.referencePixelsPerUnit = 100;
@@ -419,9 +414,12 @@ private static void CreateTopNavBar()
419414

420415
// UI AssetBundle
421416

417+
internal static AssetBundle ExplorerBundle;
418+
422419
private static void LoadBundle()
423420
{
424-
AssetBundle bundle;
421+
SetupAssetBundlePatches();
422+
425423
try
426424
{
427425
// Get the Major and Minor of the Unity version
@@ -432,18 +430,18 @@ private static void LoadBundle()
432430
// Use appropriate AssetBundle for Unity version
433431
// >= 2017
434432
if (major >= 2017)
435-
bundle = LoadBundle("modern");
433+
ExplorerBundle = LoadBundle("modern");
436434
// 5.6.0 to <2017
437435
else if (major == 5 && minor >= 6)
438-
bundle = LoadBundle("legacy.5.6");
436+
ExplorerBundle = LoadBundle("legacy.5.6");
439437
// < 5.6.0
440438
else
441-
bundle = LoadBundle("legacy");
439+
ExplorerBundle = LoadBundle("legacy");
442440
}
443441
catch
444442
{
445443
ExplorerCore.LogWarning($"Exception parsing Unity version, falling back to old AssetBundle load method...");
446-
bundle = LoadBundle("modern") ?? LoadBundle("legacy.5.6") ?? LoadBundle("legacy");
444+
ExplorerBundle = LoadBundle("modern") ?? LoadBundle("legacy.5.6") ?? LoadBundle("legacy");
447445
}
448446

449447
AssetBundle LoadBundle(string id)
@@ -455,7 +453,7 @@ AssetBundle LoadBundle(string id)
455453
.GetManifestResourceStream($"UnityExplorer.Resources.{id}.bundle")));
456454
}
457455

458-
if (bundle == null)
456+
if (ExplorerBundle == null)
459457
{
460458
ExplorerCore.LogWarning("Could not load the ExplorerUI Bundle!");
461459
DefaultFont = ConsoleFont = Resources.GetBuiltinResource<Font>("Arial.ttf");
@@ -464,15 +462,17 @@ AssetBundle LoadBundle(string id)
464462

465463
// Bundle loaded
466464

467-
ConsoleFont = bundle.LoadAsset<Font>("CONSOLA");
465+
ConsoleFont = ExplorerBundle.LoadAsset<Font>("CONSOLA");
468466
ConsoleFont.hideFlags = HideFlags.HideAndDontSave;
469467
UnityEngine.Object.DontDestroyOnLoad(ConsoleFont);
470468

471-
DefaultFont = bundle.LoadAsset<Font>("arial");
469+
DefaultFont = ExplorerBundle.LoadAsset<Font>("arial");
472470
DefaultFont.hideFlags = HideFlags.HideAndDontSave;
473471
UnityEngine.Object.DontDestroyOnLoad(DefaultFont);
474472

475-
BackupShader = bundle.LoadAsset<Shader>("DefaultUI");
473+
BackupShader = ExplorerBundle.LoadAsset<Shader>("DefaultUI");
474+
BackupShader.hideFlags = HideFlags.HideAndDontSave;
475+
UnityEngine.Object.DontDestroyOnLoad(BackupShader);
476476
// Fix for games which don't ship with 'UI/Default' shader.
477477
if (Graphic.defaultGraphicMaterial.shader?.name != "UI/Default")
478478
{
@@ -481,7 +481,6 @@ AssetBundle LoadBundle(string id)
481481
}
482482
else
483483
BackupShader = Graphic.defaultGraphicMaterial.shader;
484-
485484
}
486485

487486
private static byte[] ReadFully(Stream input)
@@ -495,5 +494,58 @@ private static byte[] ReadFully(Stream input)
495494
return ms.ToArray();
496495
}
497496
}
497+
498+
// AssetBundle patch
499+
500+
static bool donePatch;
501+
private static Type T_AssetBundle => ReflectionUtility.GetTypeByName("UnityEngine.AssetBundle");
502+
503+
private static void SetupAssetBundlePatches()
504+
{
505+
if (!donePatch)
506+
{
507+
try
508+
{
509+
if (T_AssetBundle.GetMethod("UnloadAllAssetBundles", AccessTools.all) is MethodInfo unloadAllBundles)
510+
{
511+
var processor = ExplorerCore.Harmony.CreateProcessor(unloadAllBundles);
512+
var prefix = new HarmonyMethod(typeof(UIManager).GetMethod(nameof(Prefix_UnloadAllAssetBundles), AccessTools.all));
513+
processor.AddPrefix(prefix);
514+
processor.Patch();
515+
516+
donePatch = true;
517+
}
518+
}
519+
catch (Exception ex)
520+
{
521+
ExplorerCore.LogWarning($"Exception setting up AssetBundle.UnloadAllAssetBundles patch: {ex}");
522+
}
523+
}
524+
}
525+
526+
527+
static bool Prefix_UnloadAllAssetBundles(bool unloadAllObjects)
528+
{
529+
try
530+
{
531+
var method = typeof(AssetBundle).GetMethod("GetAllLoadedAssetBundles", AccessTools.all);
532+
if (method == null)
533+
return true;
534+
var bundles = method.Invoke(null, ArgumentUtility.EmptyArgs) as AssetBundle[];
535+
foreach (var obj in bundles)
536+
{
537+
if (obj.m_CachedPtr == ExplorerBundle.m_CachedPtr)
538+
continue;
539+
540+
obj.Unload(unloadAllObjects);
541+
}
542+
}
543+
catch (Exception ex)
544+
{
545+
ExplorerCore.LogWarning($"Exception unloading AssetBundles: {ex}");
546+
}
547+
548+
return false;
549+
}
498550
}
499551
}

0 commit comments

Comments
 (0)