Skip to content

Commit

Permalink
fix: Fix double tooltips and improve SMLHelper compatibility (#444)
Browse files Browse the repository at this point in the history
* Improve SMLHelperCompatibilityPatcher

* SMLHelperCompatibilityPatcher support for BZ too

* Update TooltipPatcher to account for SML items

* Fixes
  • Loading branch information
LeeTwentyThree authored Jul 31, 2023
1 parent aec71e6 commit 0ef6fb1
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 16 deletions.
52 changes: 47 additions & 5 deletions Nautilus/Patchers/SMLHelperCompatibilityPatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand Down
84 changes: 73 additions & 11 deletions Nautilus/Patchers/TooltipPatcher.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.IO;
using System.IO;
using System.Reflection;
using System.Text;
using BepInEx.Logging;
Expand All @@ -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();
Expand Down Expand Up @@ -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<size=19><color=#808080FF>{0} ({1})</color></size>", techType.AsString(), (int)techType);
sb.AppendFormat("\n\n<size=19><color=#808080FF>{0} ({1})</color></size>", techType.AsString(), (int) techType);
}
internal static void WriteModName(StringBuilder sb, string text)
{
Expand All @@ -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");
}
Expand Down Expand Up @@ -136,7 +198,7 @@ internal static void Initialize()
}

Initialized = true;

var nautilusFolder = Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetExecutingAssembly().GetName().Name);
Directory.CreateDirectory(nautilusFolder);

Expand Down

0 comments on commit 0ef6fb1

Please sign in to comment.