diff --git a/Nautilus/Patchers/SMLHelperCompatibilityPatcher.cs b/Nautilus/Patchers/SMLHelperCompatibilityPatcher.cs
index b16d5e6d..873da48f 100644
--- a/Nautilus/Patchers/SMLHelperCompatibilityPatcher.cs
+++ b/Nautilus/Patchers/SMLHelperCompatibilityPatcher.cs
@@ -13,19 +13,45 @@ namespace Nautilus.Patchers;
// This class can be SAFELY removed if we ever decide to make Nautilus incompatible with SMLHelper (which it already kinda is...)
internal class SMLHelperCompatibilityPatcher
{
- private const string SMLHarmonyInstance = "com.ahk1221.smlhelper"; // This string is both the harmony instance & plugin GUID.
+ public const string SMLHarmonyInstance = "com.ahk1221.smlhelper"; // This string is both the harmony instance & plugin GUID.
+ public const string QModManagerGUID = "QModManager.QMMLoader";
private const string SMLAssemblyName = "SMLHelper";
+ private const string SMLHelperModJsonID = "SMLHelper";
private static Assembly _smlHelperAssembly;
- internal static void Patch(Harmony harmony)
+ private static bool? _smlHelperInstalled;
+
+ public static bool SMLHelperInstalled
{
- if (BepInEx.Bootstrap.Chainloader.PluginInfos.ContainsKey(SMLHarmonyInstance))
+ get
{
- CoroutineHost.StartCoroutine(WaitOnSMLHelperForPatches(harmony));
+ if (!_smlHelperInstalled.HasValue)
+ {
+ _smlHelperInstalled = GetSMLHelperExists();
+ }
+ return _smlHelperInstalled.Value;
}
}
+ private static bool GetSMLHelperExists()
+ {
+#if SUBNAUTICA
+ return BepInEx.Bootstrap.Chainloader.PluginInfos.ContainsKey(SMLHarmonyInstance);
+#elif BELOWZERO
+ if (!BepInEx.Bootstrap.Chainloader.PluginInfos.TryGetValue(QModManagerGUID, out var qmodManager))
+ return false;
+ var qmodServices = Assembly.GetAssembly(qmodManager.Instance.GetType()).GetType("QModManager.API.QModServices");
+ var qmodServicesInstance = AccessTools.PropertyGetter(qmodServices, "Main").Invoke(null, new object[0]);
+ return (bool)AccessTools.Method(qmodServices, "ModPresent").Invoke(qmodServicesInstance, new object[] { SMLHelperModJsonID });
+#endif
+ }
+
+ internal static void Patch(Harmony harmony)
+ {
+ CoroutineHost.StartCoroutine(WaitOnSMLHelperForPatches(harmony));
+ }
+
private static IEnumerator WaitOnSMLHelperForPatches(Harmony harmony)
{
// This code is arbitrary but was taken from an older version of SMLHelper so that this patch applies only AFTER has been patched.
@@ -44,10 +70,18 @@ private static IEnumerator WaitOnSMLHelperForPatches(Harmony harmony)
yield return null;
+ if (!SMLHelperInstalled)
+ {
+ yield break;
+ }
+
InternalLogger.Log("Patching SMLHelper compatibility fixes", BepInEx.Logging.LogLevel.Info);
+ // Finally apply the patches:
+
UnpatchSMLOptionsMethods(harmony);
FixSMLOptionsException(harmony);
+ UnpatchSMLTooltipPatches(harmony);
}
private static void UnpatchSMLOptionsMethods(Harmony harmony)
@@ -114,6 +148,14 @@ private static bool ChangeAdjusterComponentPrefix(object __instance, ref Type __
return false;
}
+ // We don't want duplicate tooltips!!
+ private static void UnpatchSMLTooltipPatches(Harmony harmony)
+ {
+ harmony.Unpatch(AccessTools.Method(typeof(TooltipFactory), nameof(TooltipFactory.BuildTech)), HarmonyPatchType.Postfix, SMLHarmonyInstance);
+ harmony.Unpatch(AccessTools.Method(typeof(TooltipFactory), nameof(TooltipFactory.ItemCommons)), HarmonyPatchType.Postfix, SMLHarmonyInstance);
+ harmony.Unpatch(AccessTools.Method(typeof(TooltipFactory), nameof(TooltipFactory.CraftRecipe)), HarmonyPatchType.Postfix, SMLHarmonyInstance);
+ }
+
private static Assembly GetSMLAssembly()
{
if (_smlHelperAssembly != null)
@@ -130,7 +172,7 @@ private static Assembly GetSMLAssembly()
return _smlHelperAssembly;
}
- private static Type GetSMLType(string typeName)
+ internal static Type GetSMLType(string typeName)
{
var assembly = GetSMLAssembly();
return assembly.GetType(typeName);
diff --git a/Nautilus/Patchers/TooltipPatcher.cs b/Nautilus/Patchers/TooltipPatcher.cs
index bb127747..493479c0 100644
--- a/Nautilus/Patchers/TooltipPatcher.cs
+++ b/Nautilus/Patchers/TooltipPatcher.cs
@@ -1,4 +1,4 @@
-using System.IO;
+using System.IO;
using System.Reflection;
using System.Text;
using BepInEx.Logging;
@@ -12,6 +12,11 @@ internal class TooltipPatcher
{
internal static bool DisableEnumIsDefinedPatch = false;
+ // For compatibility purposes:
+
+ private static MethodInfo _smlHelperIsVanillaTechTypeMethod;
+ private static MethodInfo _smlHelperWriteModNameFromTechTypeMethod;
+
internal static void Patch(Harmony harmony)
{
Initialize();
@@ -45,25 +50,82 @@ internal static void CustomTooltip(StringBuilder sb, TechType techType)
WriteSpace(sb);
}
- if (techType.IsDefinedByDefault())
+ // Compatibility for SMLHelper if it is installed
+ if (SMLHelperCompatibilityPatcher.SMLHelperInstalled)
+ {
+ var safeToUseSMLMethods = EnsureSMLHelperMethodReferences();
+
+ if (techType.IsDefinedByDefault())
+ {
+ if (safeToUseSMLMethods && !(bool)_smlHelperIsVanillaTechTypeMethod.Invoke(null, new object[] { techType }))
+ {
+ _smlHelperWriteModNameFromTechTypeMethod.Invoke(null, new object[] { sb, techType });
+ }
+ else
+ {
+#if SUBNAUTICA
+ WriteModName(sb, "Subnautica");
+#elif BELOWZERO
+ WriteModName(sb, "BelowZero");
+#endif
+ }
+ }
+ else if (EnumHandler.TryGetOwnerAssembly(techType, out Assembly assembly))
+ {
+ WriteModNameFromAssembly(sb, assembly);
+ }
+ else
+ {
+ WriteModNameError(sb, "Unknown Mod", "Item added without Nautilus");
+ }
+ }
+ // Otherwise use a more basic method of doing things
+ else
+ {
+ if (techType.IsDefinedByDefault())
#if SUBNAUTICA
- WriteModName(sb, "Subnautica");
+ WriteModName(sb, "Subnautica");
#elif BELOWZERO
WriteModName(sb, "BelowZero");
#endif
- else if (EnumHandler.TryGetOwnerAssembly(techType, out Assembly assembly))
+ else if (EnumHandler.TryGetOwnerAssembly(techType, out Assembly assembly))
+ {
+ WriteModNameFromAssembly(sb, assembly);
+ }
+ else
+ {
+ WriteModNameError(sb, "Unknown Mod", "Item added without Nautilus");
+ }
+ }
+ }
+
+ // For SMLHelper compatibility only
+ private static bool EnsureSMLHelperMethodReferences()
+ {
+ if (_smlHelperIsVanillaTechTypeMethod == null)
{
- WriteModNameFromAssembly(sb, assembly);
+ _smlHelperIsVanillaTechTypeMethod = AccessTools.Method(SMLHelperCompatibilityPatcher.GetSMLType("SMLHelper.V2.Patchers.TooltipPatcher"), "IsVanillaTechType");
+ if (_smlHelperIsVanillaTechTypeMethod == null)
+ {
+ InternalLogger.Error("Failed to locate SMLHelper's TooltipPatcher.IsVanillaTechType method!");
+ return false;
+ }
}
- else
+ if (_smlHelperWriteModNameFromTechTypeMethod == null)
{
- WriteModNameError(sb, "Unknown Mod", "Item added without Nautilus");
+ _smlHelperWriteModNameFromTechTypeMethod = AccessTools.Method(SMLHelperCompatibilityPatcher.GetSMLType("SMLHelper.V2.Patchers.TooltipPatcher"), "WriteModNameFromTechType");
+ if (_smlHelperWriteModNameFromTechTypeMethod == null)
+ {
+ InternalLogger.Error("Failed to locate SMLHelper's TooltipPatcher.WriteModNameFromTechType method!");
+ return false;
+ }
}
+ return true;
}
-
+
internal static void WriteTechType(StringBuilder sb, TechType techType)
{
- sb.AppendFormat("\n\n{0} ({1})", techType.AsString(), (int)techType);
+ sb.AppendFormat("\n\n{0} ({1})", techType.AsString(), (int) techType);
}
internal static void WriteModName(StringBuilder sb, string text)
{
@@ -77,7 +139,7 @@ internal static void WriteModNameFromAssembly(StringBuilder sb, Assembly assembl
{
string modName = assembly.GetName().Name;
- if(string.IsNullOrEmpty(modName))
+ if (string.IsNullOrEmpty(modName))
{
WriteModNameError(sb, "Unknown Mod", "Mod could not be determined");
}
@@ -136,7 +198,7 @@ internal static void Initialize()
}
Initialized = true;
-
+
var nautilusFolder = Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetExecutingAssembly().GetName().Name);
Directory.CreateDirectory(nautilusFolder);