110 lines
3.9 KiBLFS
C#
Executable File
110 lines
3.9 KiBLFS
C#
Executable File
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Threading.Tasks;
|
|
using System.Xml.Linq;
|
|
using Barotrauma;
|
|
using HarmonyLib;
|
|
using Microsoft.Xna.Framework;
|
|
|
|
namespace FastLoadMod
|
|
{
|
|
public class ParallelLoader : IAssemblyPlugin
|
|
{
|
|
private static Harmony harmony;
|
|
private static ConcurrentDictionary<string, XDocument> ParsedCache = new ConcurrentDictionary<string, XDocument>();
|
|
private static FieldInfo subElementField;
|
|
|
|
public void Initialize()
|
|
{
|
|
#if CLIENT
|
|
try
|
|
{
|
|
harmony = new Harmony("com.parallel.mod");
|
|
|
|
// Robust method finder from a previous success in testing. Read below, or use ChatGPT to explain it, IDGAF.
|
|
var originalLoad = AccessTools.Method(
|
|
typeof(Submarine),
|
|
"Load",
|
|
new Type[] { typeof(SubmarineInfo), typeof(bool), typeof(IdRemap) }
|
|
);
|
|
|
|
subElementField = AccessTools.Field(typeof(SubmarineInfo), "submarineElement");
|
|
if (originalLoad != null && subElementField != null)
|
|
{
|
|
var prefix = AccessTools.Method(typeof(ParallelLoader), "PrefixLoad");
|
|
harmony.Patch(originalLoad, new HarmonyMethod(prefix));
|
|
DebugConsole.NewMessage("[EnLo] PL working.", Color.Green);
|
|
}
|
|
else
|
|
{
|
|
if (originalLoad == null) DebugConsole.NewMessage("[EnLo] CRITICAL: Submarine.Load not found!", Color.Red);
|
|
if (subElementField == null) DebugConsole.NewMessage("[EnLo] CRITICAL: SubmarineInfo.submarineElement not found!", Color.Red);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
DebugConsole.NewMessage($"[EnLo] FATAL ERROR IN INIT: {ex}", Color.Red);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
public void OnLoadCompleted() { }
|
|
public void PreInitPatching() { }
|
|
public void Dispose()
|
|
{
|
|
#if CLIENT
|
|
if (harmony != null) Harmony.UnpatchID("com.parallel.mod");
|
|
harmony = null;
|
|
ParsedCache.Clear();
|
|
#endif
|
|
}
|
|
|
|
#if CLIENT
|
|
public static bool PrefixLoad(SubmarineInfo info, bool unloadPrevious, ref Submarine __result)
|
|
{
|
|
if (info == null || string.IsNullOrEmpty(info.FilePath)) return true;
|
|
if (ParsedCache.TryGetValue(info.FilePath, out XDocument readyDoc))
|
|
{
|
|
try
|
|
{
|
|
// Check if the info already has the Element loaded. If not, inject pre-parsed version.
|
|
var currentVal = subElementField.GetValue(info);
|
|
if (currentVal == null)
|
|
{
|
|
subElementField.SetValue(info, readyDoc.Root);
|
|
DebugConsole.NewMessage($"[EnLo] Instant Load: {info.Name}", Color.Cyan);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
DebugConsole.NewMessage($"[EnLo] Injection Failed: {ex.Message}", Color.Orange);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Task.Run(() => PreParseSub(info.FilePath));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private static void PreParseSub(string filePath)
|
|
{
|
|
try
|
|
{
|
|
if (!File.Exists(filePath) || ParsedCache.ContainsKey(filePath)) return;
|
|
XDocument doc = XDocument.Load(filePath);
|
|
ParsedCache.TryAdd(filePath, doc);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// Ignore errors here; the main thread will catch them when it tries to load normally
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
} |