Skip to content

Commit

Permalink
Restructured everything, added clientside modloading
Browse files Browse the repository at this point in the history
  • Loading branch information
Walaryne committed Apr 23, 2022
1 parent 699d9ea commit 747b769
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 50 deletions.
20 changes: 19 additions & 1 deletion TraumaWeaver.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TraumaWeaver", "TraumaWeaver.csproj", "{9531E183-CFA3-46DF-99A6-6D8311417709}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TraumaWeaverLoader", "TraumaWeaverLoader\TraumaWeaverLoader.csproj", "{9531E183-CFA3-46DF-99A6-6D8311417709}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TraumaWeaverClient", "TraumaWeaverClient\TraumaWeaverClient.csproj", "{C83B989B-F2AD-4456-831B-52BF88FDCF29}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TraumaWeaverServer", "TraumaWeaverServer\TraumaWeaverServer.csproj", "{F11A1C18-AF55-47B7-A0B1-43BAB201331D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TraumaWeaverLauncher", "TraumaWeaverLauncher\TraumaWeaverLauncher.csproj", "{7A3E98DA-CC7E-48F1-9EBF-909C46031E96}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -12,5 +18,17 @@ Global
{9531E183-CFA3-46DF-99A6-6D8311417709}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9531E183-CFA3-46DF-99A6-6D8311417709}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9531E183-CFA3-46DF-99A6-6D8311417709}.Release|Any CPU.Build.0 = Release|Any CPU
{C83B989B-F2AD-4456-831B-52BF88FDCF29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C83B989B-F2AD-4456-831B-52BF88FDCF29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C83B989B-F2AD-4456-831B-52BF88FDCF29}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C83B989B-F2AD-4456-831B-52BF88FDCF29}.Release|Any CPU.Build.0 = Release|Any CPU
{F11A1C18-AF55-47B7-A0B1-43BAB201331D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F11A1C18-AF55-47B7-A0B1-43BAB201331D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F11A1C18-AF55-47B7-A0B1-43BAB201331D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F11A1C18-AF55-47B7-A0B1-43BAB201331D}.Release|Any CPU.Build.0 = Release|Any CPU
{7A3E98DA-CC7E-48F1-9EBF-909C46031E96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7A3E98DA-CC7E-48F1-9EBF-909C46031E96}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7A3E98DA-CC7E-48F1-9EBF-909C46031E96}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7A3E98DA-CC7E-48F1-9EBF-909C46031E96}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
112 changes: 112 additions & 0 deletions TraumaWeaverClient/TraumaWeaverClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using Barotrauma;
using HarmonyLib;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

[assembly: IgnoresAccessChecksTo("Barotrauma")]
namespace TraumaWeaverClient
{

public static class MainPatcher
{
public static void doHarmony()
{
AppDomain.CurrentDomain.AssemblyResolve += ResolveHandler;
var harmony = new Harmony("TraumaWeaverClient");


harmony.Patch(AccessTools.Method(typeof(Program), nameof(Program.Main)),
transpiler: new HarmonyMethod(typeof(Patches), nameof(Patches.MainTranspiler)));
harmony.Patch(AccessTools.Method(typeof(MainMenuScreen), nameof(MainMenuScreen.Draw)),
transpiler: new HarmonyMethod(typeof(Patches), nameof(Patches.MainMenuScreenTranspiler)));
}

private static Assembly ResolveHandler(object o, ResolveEventArgs args)
{
if (args.Name == "MonoGame.Framework.Linux.NetStandard, Version=3.7.0.0, Culture=neutral, PublicKeyToken=null")
{
return Array.Find(AppDomain.CurrentDomain.GetAssemblies(),
assembly => assembly.GetName().FullName == "MonoGame.Framework.Windows.NetStandard, Version=3.7.0.0, Culture=neutral, PublicKeyToken=null");
}
return null;
}
}

public class Hooks
{
public static void onMain()
{
Console.WriteLine("TraumaWeaverClient " + Assembly.GetExecutingAssembly().GetName().Version + " Loaded");
Console.WriteLine("Loading mods...");
DirectoryInfo clientDllMods = Directory.CreateDirectory("ClientDllMods");
var mods = clientDllMods.EnumerateFiles();
foreach (FileInfo mod in mods)
{
Console.WriteLine($"Loading {mod.Name}");
try
{
Assembly modAssembly = Assembly.LoadFrom(mod.FullName);
modAssembly.GetTypes().Find(e => e.Name == "Mod").GetMethod("ModMain")?.Invoke(null, null);
}
catch (Exception e)
{
Console.WriteLine($"Could not load {mod.FullName}\nException:\n{e}");
}
}
}

public static void onMainMenuScreenDraw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
String versionString = $"TraumaWeaverClient {Assembly.GetExecutingAssembly().GetName().Version} Loaded";
GUIStyle.SmallFont.DrawString(spriteBatch, versionString, new Vector2(HUDLayoutSettings.Padding, GameMain.GraphicsHeight - GUIStyle.SmallFont.LineHeight * 3f - HUDLayoutSettings.Padding * 0.75f), Color.Teal);
}
}

public class Patches
{
public static IEnumerable<CodeInstruction> MainTranspiler(IEnumerable<CodeInstruction> instructions)
{
var found = false;
foreach (CodeInstruction instruction in instructions)
{
if (instruction.Calls(AccessTools.Method(typeof(AppDomain), "get_CurrentDomain")) && !found)
{
yield return new CodeInstruction(OpCodes.Call, typeof(Hooks).GetMethod(nameof(Hooks.onMain)));
found = true;
}
yield return instruction;
}
if (!found)
{
Console.WriteLine("Cannot find Program.Main");
}
}

public static IEnumerable<CodeInstruction> MainMenuScreenTranspiler(IEnumerable<CodeInstruction> instructions)
{
var found = false;
foreach (CodeInstruction instruction in instructions)
{
if (instruction.LoadsField(typeof(GameMain).GetField("Version")))
{
yield return new CodeInstruction(OpCodes.Ldarg_1);
yield return new CodeInstruction(OpCodes.Ldarg_2);
yield return new CodeInstruction(OpCodes.Ldarg_3);
yield return new CodeInstruction(OpCodes.Call, typeof(Hooks).GetMethod(nameof(Hooks.onMainMenuScreenDraw)));
found = true;
}
yield return instruction;
}
if (!found)
{
Console.WriteLine("Cannot find String.Concat");
}
}
}
}
26 changes: 26 additions & 0 deletions TraumaWeaverClient/TraumaWeaverClient.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Reference Include="Barotrauma, Version=0.17.12.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\..\..\.steam\steam\steamapps\common\Barotrauma\Barotrauma-nstrip.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="MonoGame.Framework.Linux.NetStandard, Version=3.7.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\..\..\.steam\steam\steamapps\common\Barotrauma\MonoGame.Framework.Linux.NetStandard.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="XNATypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\..\..\.steam\steam\steamapps\common\Barotrauma\XNATypes.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>

<ItemGroup>
<PackageReference Include="HarmonyX" Version="2.10.0" />
</ItemGroup>

</Project>
26 changes: 26 additions & 0 deletions TraumaWeaverLauncher/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Diagnostics;
using System.IO;

namespace TraumaWeaverLauncher
{
public static class Program
{
public static void Main(string[] args)
{
ProcessStartInfo pProcess = new ProcessStartInfo
{
EnvironmentVariables =
{
["DOTNET_STARTUP_HOOKS"] = $"{Directory.GetCurrentDirectory()}/TraumaWeaverLoader.dll"
},
UseShellExecute = false,
CreateNoWindow = true,
FileName = "dotnet",
ArgumentList = { "Barotrauma.dll" }
};

Process.Start(pProcess);

}
}
}
8 changes: 8 additions & 0 deletions TraumaWeaverLauncher/TraumaWeaverLauncher.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

</Project>
File renamed without changes.
94 changes: 94 additions & 0 deletions TraumaWeaverLoader/Loader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Runtime.Loader;


[SuppressMessage("ReSharper", "UnusedType.Global")]
[SuppressMessage("ReSharper", "CheckNamespace")]
[SuppressMessage("ReSharper", "UnusedMember.Global")]
internal class StartupHook
{
enum LaunchType
{
CLIENT,
SERVER
}

public static void Initialize()
{

LaunchType launch;

switch (Assembly.GetEntryAssembly()?.GetName().Name)
{
case "DedicatedServer":
{
launch = LaunchType.SERVER;
break;
}
case "Barotrauma":
{
launch = LaunchType.CLIENT;
break;
}
default:
{
return;
}
}

AssemblyLoadContext.Default.Resolving += SharedHostPolicy.SharedAssemblyResolver.LoadAssemblyFromSharedLocation;
TraumaWeaverLoader.Utils.AssemblyLoadPathHelper("0Harmony.dll");
TraumaWeaverLoader.Utils.AssemblyLoadPathHelper("Mono.Cecil.dll");
TraumaWeaverLoader.Utils.AssemblyLoadPathHelper("MonoMod.RuntimeDetour.dll");
TraumaWeaverLoader.Utils.AssemblyLoadPathHelper("MonoMod.Utils.dll");

Assembly assembly = null;

switch (launch)
{
case LaunchType.CLIENT:
{
assembly = Assembly.LoadFile(Directory.GetCurrentDirectory() + "/TraumaWeaverClient.dll");
break;
}
case LaunchType.SERVER:
{
assembly = Assembly.LoadFile(Directory.GetCurrentDirectory() + "/TraumaWeaverServer.dll");
break;
}
}


if (assembly != null)
{
Array.Find(assembly.GetTypes(), e => e.Name == "MainPatcher")?.GetMethod("doHarmony")?.Invoke(null, null);
}
}
}

namespace TraumaWeaverLoader
{
public static class Utils
{
public static Assembly AssemblyLoadPathHelper(string assemblyName)
{
return AssemblyLoadContext.Default.LoadFromAssemblyPath(Directory.GetCurrentDirectory() + "/" + assemblyName);
}
}
}

namespace SharedHostPolicy
{
internal static class SharedAssemblyResolver
{
public static Assembly LoadAssemblyFromSharedLocation(AssemblyLoadContext context, AssemblyName assemblyName)
{
string sharedAssemblyPath = Directory.GetCurrentDirectory(); // find assemblyName in shared location...
return sharedAssemblyPath != null ? AssemblyLoadContext.Default.LoadFromAssemblyPath(sharedAssemblyPath) : null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@
<OutputType>Library</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<RootNamespace>TraumaWeaver</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="HarmonyX" Version="2.8.0" />
<PackageReference Include="HarmonyX" Version="2.10.0" />
<PackageReference Include="Mono.Cecil" Version="0.11.4" />
</ItemGroup>

<ItemGroup>
<Reference Include="DedicatedServer, Version=0.15.23.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\HolyTraumaGrail\bin\Debug\netcoreapp3.1\DedicatedServer-nstrip.dll</HintPath>
<Private>False</Private>
</Reference>
<ProjectReference Include="..\TraumaWeaverClient\TraumaWeaverClient.csproj" />
<ProjectReference Include="..\TraumaWeaverServer\TraumaWeaverServer.csproj" />
</ItemGroup>

</Project>
Loading

0 comments on commit 747b769

Please sign in to comment.