Skip to content
This repository was archived by the owner on Feb 28, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 56 additions & 11 deletions NeosModLoader/AssemblyHider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using BaseX;
using FrooxEngine;
using HarmonyLib;
using System;
using System.Collections.Generic;
Expand All @@ -23,9 +24,21 @@ internal static void PatchNeos(Harmony harmony, HashSet<Assembly> initialAssembl
{
neosAssemblies = GetNeosAssemblies(initialAssemblies);
modAssemblies = GetModAssemblies();
MethodInfo target = AccessTools.DeclaredMethod(typeof(TypeHelper), nameof(TypeHelper.FindType));
MethodInfo patch = AccessTools.DeclaredMethod(typeof(AssemblyHider), nameof(FindTypePostfix));
harmony.Patch(target, postfix: new HarmonyMethod(patch));

// TypeHelper.FindType explicitly does a type search
MethodInfo findTypeTarget = AccessTools.DeclaredMethod(typeof(TypeHelper), nameof(TypeHelper.FindType));
MethodInfo findTypePatch = AccessTools.DeclaredMethod(typeof(AssemblyHider), nameof(FindTypePostfix));
harmony.Patch(findTypeTarget, postfix: new HarmonyMethod(findTypePatch));

// WorkerManager.IsValidGenericType checks a type for validity, and if it returns `true` it reveals that the type exists
MethodInfo isValidGenericTypeTarget = AccessTools.DeclaredMethod(typeof(WorkerManager), nameof(WorkerManager.IsValidGenericType));
MethodInfo isValidGenericTypePatch = AccessTools.DeclaredMethod(typeof(AssemblyHider), nameof(IsValidTypePostfix));
harmony.Patch(isValidGenericTypeTarget, postfix: new HarmonyMethod(isValidGenericTypePatch));

// WorkerManager.GetType uses FindType, but upon failure fails back to doing a (strangely) exhausitive reflection-based search for the type
MethodInfo getTypeTarget = AccessTools.DeclaredMethod(typeof(WorkerManager), nameof(WorkerManager.GetType));
MethodInfo getTypePatch = AccessTools.DeclaredMethod(typeof(AssemblyHider), nameof(FindTypePostfix));
harmony.Patch(getTypeTarget, postfix: new HarmonyMethod(getTypePatch));
}
}

Expand All @@ -51,24 +64,56 @@ private static HashSet<Assembly> GetModAssemblies()
return assemblies;
}

private static void FindTypePostfix(ref Type? __result)
private static bool IsModType(Type type)
{
if (__result != null && !neosAssemblies!.Contains(__result.Assembly))
if (neosAssemblies!.Contains(type.Assembly))
{
// the type belongs to a Neos assembly
return false; // don't hide the type
}
else
{
if (!modAssemblies!.Contains(__result.Assembly))
if (modAssemblies!.Contains(type.Assembly))
{
// known type from a mod assembly
Logger.DebugInternal($"Hid type \"{type}\" from Neos");
return true; // hide the type
}
else
{
// an assembly was in neither neosAssemblies nor modAssemblies
// this implies someone late-loaded an assembly after NML, and it was later used in-game
// this is super weird, and probably shouldn't ever happen... but if it does, I want to know about it.
// since this is an edge case users may want to handle in different ways, the HideLateTypes nml config option allows them to choose.
bool hideLate = ModLoaderConfiguration.Get().HideLateTypes;
Logger.WarnInternal($"The \"{__result}\" type does not appear to part of Neos or a mod. It is unclear whether it should be hidden or not. due to the HideLateTypes config option being {hideLate} it will be {(hideLate ? "Hidden" : "Shown")}");
if (hideLate) __result = null;
Logger.WarnInternal($"The \"{type}\" type does not appear to part of Neos or a mod. It is unclear whether it should be hidden or not. Due to the HideLateTypes config option being {hideLate} it will be {(hideLate ? "Hidden" : "Shown")}");
return hideLate; // hide the type only if hideLate == true
}
else
}
}

// postfix for a method that searches for a type, and returns a reference to it if found (TypeHelper.FindType and WorkerManager.GetType)
private static void FindTypePostfix(ref Type? __result)
{
if (__result != null)
{
// we only need to think about types if the method actually returned a non-null result
if (IsModType(__result))
{
__result = null;
}
}
}

// postfix for a method that validates a type (WorkerManager.IsValidGenericType)
private static void IsValidTypePostfix(ref bool __result, Type type)
{
if (__result == true)
{
// we only need to think about types if the method actually returned a true result
if (IsModType(type))
{
Logger.DebugInternal($"Hid type \"{__result}\" from Neos");
__result = null; // Pretend the type doesn't exist
__result = false;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion NeosModLoader/ModLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace NeosModLoader
{
public class ModLoader
{
internal const string VERSION_CONSTANT = "1.12.4";
internal const string VERSION_CONSTANT = "1.12.5";
/// <summary>
/// NeosModLoader's version
/// </summary>
Expand Down