Skip to content

Commit

Permalink
Merge pull request #212 from Arkhist/develop
Browse files Browse the repository at this point in the history
5.3.0
  • Loading branch information
Windows10CE authored Jan 29, 2023
2 parents 9d3822b + 3d4820e commit bdb1bdd
Show file tree
Hide file tree
Showing 20 changed files with 443 additions and 193 deletions.
67 changes: 40 additions & 27 deletions BepInEx.Hacknet/HacknetChainloader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Reflection;
using System.Reflection;
using BepInEx.Logging;
using BepInEx.Bootstrap;
using Hacknet.Extensions;
Expand All @@ -21,7 +21,7 @@ private static Tuple<string, string, string> __UpdaterData
"BepInEx/core/BepInEx.Hacknet.dll"
);

public const string VERSION = "5.2.0";
public const string VERSION = "5.3.0";
public static readonly Version Version = Version.Parse(VERSION);

public static HacknetChainloader Instance;
Expand Down Expand Up @@ -53,28 +53,20 @@ protected override IList<PluginInfo> DiscoverPlugins()
}

var plugins = base.DiscoverPlugins();
TemporaryPluginGUIDs = plugins.Select(plugin => plugin.Metadata.GUID).ToList();
return plugins;
}

public override HacknetPlugin LoadPlugin(PluginInfo pluginInfo, Assembly pluginAssembly)
{
var type = pluginAssembly.GetType(pluginInfo.TypeName);

HacknetPlugin pluginInstance = null;
try
HacknetPlugin pluginInstance = (HacknetPlugin) Activator.CreateInstance(type);
if (!pluginInstance.Load())
{
pluginInstance = (HacknetPlugin) Activator.CreateInstance(type);
if (!pluginInstance.Load())
{
throw new Exception($"{pluginInfo.Metadata.GUID} returned false on its load method");
}
}
catch
{
TemporaryPluginGUIDs.Remove(pluginInfo.Metadata.GUID);
throw;
throw new Exception($"{pluginInfo.Metadata.GUID} returned false on its load method");
}
if (HN.Settings.IsInExtensionMode)
TemporaryPluginGUIDs.Add(pluginInfo.Metadata.GUID);

return pluginInstance;
}
Expand All @@ -90,7 +82,7 @@ internal void UnloadTemps()
{
Log.LogMessage("Unloading extension plugins...");

foreach (var temp in TemporaryPluginGUIDs)
foreach (var temp in TemporaryPluginGUIDs.Reverse<string>())
{
if (!((HacknetPlugin)this.Plugins[temp].Instance).Unload())
{
Expand All @@ -101,7 +93,7 @@ internal void UnloadTemps()
Log.LogMessage($"Unloaded {temp}");
}
TemporaryPluginGUIDs.Clear();
ChainloaderFix.Remaps.Clear();
ChainloaderFix.ClearRemaps();

Log.LogMessage("Finished unloading extension plugins");
}
Expand Down Expand Up @@ -131,6 +123,9 @@ internal static void LoadTempPluginsPrefix(ExtensionInfo info, ref bool __runOri

try
{
HN.Settings.IsInExtensionMode = true;
ExtensionLoader.ActiveExtensionInfo = info;

var newPluginPath = Path.Combine(info.GetFullFolderPath(), "Plugins");
var newConfigPath = Path.Combine(newPluginPath, "Configs");

Expand All @@ -145,6 +140,8 @@ internal static void LoadTempPluginsPrefix(ExtensionInfo info, ref bool __runOri
}
catch (Exception ex)
{
HN.Settings.IsInExtensionMode = false;

HacknetChainloader.Instance.Log.LogError($"A fatal exception occured while loading extension plugins, aborting:\n{ex}");

__runOriginal = false;
Expand Down Expand Up @@ -187,6 +184,7 @@ private static bool ReturnCorrectDirectoryPrefix(out string __result)
internal static class ChainloaderFix
{
internal static Dictionary<string, Assembly> Remaps = new Dictionary<string, Assembly>();
internal static Dictionary<string, AssemblyDefinition> RemapDefinitions = new Dictionary<string, AssemblyDefinition>();

[HarmonyILManipulator]
[HarmonyPatch(typeof(BaseChainloader<HacknetPlugin>), "Execute")]
Expand All @@ -204,25 +202,40 @@ internal static void PluginCecilHacks(ILContext il)
byte[] asmBytes;
string name;
using (var asm = AssemblyDefinition.ReadAssembly(path))
var asm = AssemblyDefinition.ReadAssembly(path, new ReaderParameters()
{
name = asm.Name.Name;
asm.Name.Name = asm.Name.Name + "-" + DateTime.Now.Ticks;
using (var ms = new MemoryStream())
{
asm.Write(ms);
asmBytes = ms.ToArray();
}
AssemblyResolver = new RenamedAssemblyResolver()
});
name = asm.Name.Name;
asm.Name.Name = asm.Name.Name + "-" + DateTime.Now.Ticks;
using (var ms = new MemoryStream())
{
asm.Write(ms);
asmBytes = ms.ToArray();
}
var loaded = Assembly.Load(asmBytes);
Remaps[name] = loaded;
RemapDefinitions[name] = asm;
return loaded;
});
}
internal static void ClearRemaps()
{
Remaps.Clear();
foreach (var asm in RemapDefinitions.Values)
asm.Dispose();
RemapDefinitions.Clear();
}
}
internal class RenamedAssemblyResolver : DefaultAssemblyResolver
{
public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) =>
ChainloaderFix.RemapDefinitions.TryGetValue(name.Name, out var asm)
? asm
: base.Resolve(name, parameters);
}

[HarmonyPatch]
Expand All @@ -236,4 +249,4 @@ internal static void WriteWriteLineToLog(string value)
{
LogWriter?.WriteLine(value);
}
}
}
25 changes: 17 additions & 8 deletions PathfinderAPI/Administrator/AdministratorManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Pathfinder.Administrator;

public static class AdministratorManager
{
private static readonly List<Type> CustomAdministrators = new List<Type>();
private static readonly Dictionary<string, Type> CustomAdministrators = new Dictionary<string, Type>();

static AdministratorManager()
{
Expand All @@ -20,8 +20,8 @@ internal static void LoadAdministrator(ElementInfo info, Computer comp, OS os)
if (!info.Attributes.TryGetValue("type", out var adminTypeName))
return;

var adminType = CustomAdministrators.FirstOrDefault(x => x.Name == adminTypeName);
if (adminType != null) {
if (CustomAdministrators.TryGetValue(adminTypeName, out Type adminType))
{
BaseAdministrator admin = (BaseAdministrator)Activator.CreateInstance(adminType, new object[] { comp, os });
admin.LoadFromXml(info);
comp.admin = admin;
Expand Down Expand Up @@ -54,19 +54,28 @@ internal static void LoadAdministrator(ElementInfo info, Computer comp, OS os)

private static void onPluginUnload(Assembly pluginAsm)
{
CustomAdministrators.RemoveAll(x => x.Assembly == pluginAsm);
foreach (var name in CustomAdministrators.Where(x => x.Value.Assembly == pluginAsm).Select(x => x.Key).ToList())
CustomAdministrators.Remove(name);
}

public static void RegisterAdministrator<T>() where T : BaseAdministrator => RegisterAdministrator(typeof(T));
public static void RegisterAdministrator(Type adminType)
public static void RegisterAdministrator(Type adminType) => RegisterAdministrator(adminType, adminType.Name);
public static void RegisterAdministrator<T>(string xmlName) where T : BaseAdministrator => RegisterAdministrator(typeof(T), xmlName);
public static void RegisterAdministrator(Type adminType, string xmlName)
{
adminType.ThrowNotInherit<BaseAdministrator>(nameof(adminType));
CustomAdministrators.Add(adminType);
CustomAdministrators.Add(xmlName, adminType);
}

public static void UnregisterAdministrator<T>() where T : BaseAdministrator => UnregisterAdministrator(typeof(T));
public static void UnregisterAdministrator(Type adminType)
{
CustomAdministrators.Remove(adminType);
var xmlName = CustomAdministrators.FirstOrDefault(x => x.Value == adminType).Key;
if (xmlName != null)
CustomAdministrators.Remove(xmlName);
}
public static void UnregisterAdministrator(string xmlName)
{
CustomAdministrators.Remove(xmlName);
}
}
}
71 changes: 71 additions & 0 deletions PathfinderAPI/BaseGameFixes/FixExtensionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using Hacknet;
using Hacknet.Extensions;
using Hacknet.Misc;
using HarmonyLib;
using MonoMod.Cil;
using Mono.Cecil.Cil;

namespace Pathfinder.BaseGameFixes;

[HarmonyPatch]
public static class FixExtensionTests
{
[HarmonyILManipulator]
[HarmonyPatch(typeof(ExtensionTests), nameof(ExtensionTests.TestExtensionForRuntime))]
[HarmonyPatch(typeof(ExtensionTests), nameof(ExtensionTests.TestExtensionMission))]
internal static void TestMissionStartingMissionNONEFix(ILContext il)
{
ILCursor c = new ILCursor(il);

// string _text = TestSuite.TestMission(ExtensionLoader.ActiveExtensionInfo.FolderPath + "/" + ExtensionLoader.ActiveExtensionInfo.StartingMissionPath, _os);
c.GotoNext(MoveType.After,
x => x.MatchLdsfld(AccessTools.Field(typeof(ExtensionLoader), nameof(ExtensionLoader.ActiveExtensionInfo))),
x => x.MatchLdfld(AccessTools.Field(typeof(ExtensionInfo), nameof(ExtensionInfo.FolderPath))),
x => x.MatchLdstr("/"),
x => x.MatchLdsfld(AccessTools.Field(typeof(ExtensionLoader), nameof(ExtensionLoader.ActiveExtensionInfo))),
x => x.MatchLdfld(AccessTools.Field(typeof(ExtensionInfo), nameof(ExtensionInfo.StartingMissionPath))),
x => x.MatchCall(AccessTools.Method(typeof(string), nameof(string.Concat), new Type[] { typeof(string), typeof(string), typeof(string) })),
_ => true,
x => x.MatchCall(AccessTools.Method(typeof(TestSuite), nameof(TestSuite.TestMission))),
x => x.MatchStloc(out int _)
);
c.Index--;
ILLabel labelDontTestStartingMission = c.MarkLabel();
c.Index -= 7;
ILLabel labelTestStartingMission = c.MarkLabel();
c.MoveBeforeLabels();

c.Emit(OpCodes.Dup);
c.EmitDelegate<Func<ExtensionInfo, bool>>(info =>
info.StartingMissionPath == null
);
c.Emit(OpCodes.Brfalse, labelTestStartingMission);
c.Emit(OpCodes.Pop);
c.Emit(OpCodes.Ldstr, "");
c.Emit(OpCodes.Br, labelDontTestStartingMission);
}
[HarmonyILManipulator]
[HarmonyPatch(typeof(ExtensionInfo), nameof(ExtensionInfo.VerifyExtensionInfo))]
internal static void ExtensionInfoStartingMissionNONEFix(ILContext il)
{
ILCursor c = new ILCursor(il);
// if (!File.Exists(info.FolderPath + "/" + info.StartingMissionPath))
c.GotoNext(MoveType.After,
x => x.MatchLdarg(0),
x => x.MatchLdfld(AccessTools.Field(typeof(ExtensionInfo), nameof(ExtensionInfo.FolderPath))),
x => x.MatchLdstr("/"),
x => x.MatchLdarg(0),
x => x.MatchLdfld(AccessTools.Field(typeof(ExtensionInfo), nameof(ExtensionInfo.StartingMissionPath))),
x => x.MatchCall(AccessTools.Method(typeof(string), nameof(string.Concat), new Type[] { typeof(string), typeof(string), typeof(string) })),
x => x.MatchCall(AccessTools.Method(typeof(File), nameof(File.Exists))),
x => x.MatchStloc(3),
x => x.MatchLdloc(3),
x => x.MatchBrtrue(out ILLabel _)
);
c.Index--;
c.Emit(OpCodes.Ldarg_0);
c.EmitDelegate<Func<bool, ExtensionInfo, bool>>((b, info) =>
b || info.StartingMissionPath == null
);
}
}
50 changes: 45 additions & 5 deletions PathfinderAPI/BaseGameFixes/FixTutorialStartup.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,58 @@
using Hacknet;
using Hacknet.Extensions;
using HarmonyLib;
using MonoMod.Cil;
using Mono.Cecil.Cil;

namespace Pathfinder.BaseGameFixes;

[HarmonyPatch]
public static class FixTutorialStartup
{
[HarmonyPrefix]
[HarmonyILManipulator]
[HarmonyPatch(typeof(Programs), nameof(Programs.firstTimeInit))]
internal static void FirstTimeInitSetStartingMissionForTutorial(ILContext il)
{
ILCursor c = new ILCursor(il);

c.GotoNext(MoveType.After,
x => x.MatchLdstr("Launching Tutorial...")
);

c.Emit(OpCodes.Ldarg_1);
c.EmitDelegate<Action<OS>>(os =>
{
if (Settings.IsInExtensionMode && ExtensionLoader.ActiveExtensionInfo?.StartingMissionPath != null)
os.currentMission = (ActiveMission)ComputerLoader.readMission(ExtensionLoader.ActiveExtensionInfo.FolderPath + "/" + ExtensionLoader.ActiveExtensionInfo.StartingMissionPath);
});
}
[HarmonyILManipulator]
[HarmonyPatch(typeof(AdvancedTutorial), nameof(AdvancedTutorial.Killed))]
internal static bool AdvancedTutorialLoadStartingMission(AdvancedTutorial __instance)
internal static void AdvancedTutorialKilledNullMissionFix(ILContext il)
{
if (!__instance.os.multiplayer && __instance.os.initShowsTutorial && Settings.IsInExtensionMode && __instance.os.currentMission is null)
__instance.os.currentMission = (ActiveMission)ComputerLoader.readMission(ExtensionLoader.ActiveExtensionInfo.FolderPath + "/" + ExtensionLoader.ActiveExtensionInfo.StartingMissionPath);
return true;
ILCursor c = new ILCursor(il);

// os.currentMission.sendEmail(os);
c.GotoNext(MoveType.After,
x => x.MatchNop(),
x => x.MatchLdarg(0),
x => x.MatchLdfld(AccessTools.Field(typeof(Module), nameof(Module.os))),
x => x.MatchLdfld(AccessTools.Field(typeof(OS), nameof(OS.currentMission))),
x => x.MatchLdarg(0),
x => x.MatchLdfld(AccessTools.Field(typeof(Module), nameof(Module.os))),
x => x.MatchCallvirt(AccessTools.Method(typeof(ActiveMission), nameof(ActiveMission.sendEmail)))
);
// os.Flags.AddFlag("TutorialComplete");
ILLabel nextLine = c.MarkLabel();
c.Index -= 3;
ILLabel continueThisLine = c.MarkLabel();
c.MoveBeforeLabels();

c.Emit(OpCodes.Dup);
c.Emit(OpCodes.Ldnull);
c.Emit(OpCodes.Ceq);
c.Emit(OpCodes.Brfalse, continueThisLine);
c.Emit(OpCodes.Pop);
c.Emit(OpCodes.Br, nextLine);
}
}
4 changes: 2 additions & 2 deletions PathfinderAPI/BaseGameFixes/HHBS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal static void FixPathCombineOrderIL(ILContext il)
var combine = AccessTools.Method(typeof(Path), nameof(Path.Combine), new Type[] { typeof(string), typeof(string) });

c.Emit(OpCodes.Ldloc_0);
c.Emit(OpCodes.Ldstr, "Hacknet");
c.Emit(OpCodes.Ldstr, "HacknetPathfinder");
c.Emit(OpCodes.Call, combine);
c.Emit(OpCodes.Ldstr, "Accounts");
c.Emit(OpCodes.Call, combine);
Expand All @@ -46,4 +46,4 @@ internal static void FixPathCombineOrderIL(ILContext il)

c.Next.Operand = "HHBS";
}
}
}
5 changes: 2 additions & 3 deletions PathfinderAPI/BaseGameFixes/Performance/NodeLookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,14 @@ internal static void ConnectILManipulator(ILContext il)
c.EmitDelegate<Func<string[], OS, int>>((args, os) =>
os.netMap.nodes.IndexOf(ComputerLookup.Find(args[1], SearchType.Ip | SearchType.Name))
);
c.Emit(OpCodes.Dup);
c.Emit(OpCodes.Stloc_1);

c.Emit(OpCodes.Ldloc_1);
c.Emit(OpCodes.Ldc_I4_M1);
c.Emit(OpCodes.Ceq);
// incrementLabel will be preserved but loop behavior removed
c.Emit(OpCodes.Brtrue, incrementLabel);

c.Emit(OpCodes.Stloc_1);

// Remove remaining loop behavior
c.GotoLabel(incrementLabel);
i = ++c.Index; // preserve label on nop
Expand Down
Loading

0 comments on commit bdb1bdd

Please sign in to comment.