diff --git a/README.md b/README.md index c0d14a7..c8f1e50 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,27 @@ **Current status:** Available for early testing.
## Download & Installation +### Windows If you have already installed the Addons, make sure to run file verification through Steam before installing a new version (go to Steam, click RMB on the game, open **Properties**, go to **Local Files** and click on **Verify integrity of game files...**)! Go to [Releases](https://github.com/Erdroy/Stationeers.Addons/releases), select latest release and download zip file named 'Stationeers.Addons-vX.X-X.zip'. Now go to Steam, click RMB on the game, open **Properties**, go to **Local Files** and click on **BROWSE LOCAL FILES**. It should open new window for you. Next, you have to open the downloaded zip and drag all of its contents into the game folder (`AddonManager` folder and `version.dll`). And that's it! Enjoy your mods! ***Note:** After you've subscribed to an addon on the workshop, you have to restart the game. This will be improved in the future.* +### Linux (client, not tested for servers) +*(this is in beta, might not work)* +Installing: +1) Do the same unzipping as in windows (extract all zip content on the game installation root folder) +2) In a shell, navigate to the Addons folder you've just extracted +3) Run `mono Stationeers.Addons.Patcher.exe` +4) Enjoy (hopefully) + +Updating: +1) Like in windows, verify the files from steam +2) Extract new version of this package +3) Run the exe (step 3 of `Installing`) + + ## Links * [Discord](https://discord.gg/b6kFrUATdm) * [Trello](https://trello.com/b/zSHKh2XO/stationeersaddons) diff --git a/Source/Stationeers.Addons.Patcher/Core/Patchers/MonoPatcher.cs b/Source/Stationeers.Addons.Patcher/Core/Patchers/MonoPatcher.cs index 9f0b881..3e7c322 100644 --- a/Source/Stationeers.Addons.Patcher/Core/Patchers/MonoPatcher.cs +++ b/Source/Stationeers.Addons.Patcher/Core/Patchers/MonoPatcher.cs @@ -28,6 +28,7 @@ public class MonoPatcher : IGamePatcher private AssemblyDefinition _assembly; private ModuleDefinition _module; private TypeDefinition _type; + private string _installResourcesDir; public string AssemblyFileName; public string TemporaryAssemblyFileName; @@ -39,7 +40,7 @@ public void Load(string instanceExe) if (!File.Exists(AssemblyFileName)) Logger.Current.LogFatal($"Could not find game/server assembly '{AssemblyFileName}'."); - + // Copy the assembly into temporary file File.Copy(AssemblyFileName, TemporaryAssemblyFileName, true); @@ -101,6 +102,9 @@ public void Patch() // Backup the assembly first Backup(); + // Copy dlls to the Managed folder, required for linux to be auto loaded + CopyRequiredAssemblies(); + // We are clear here, go ahead and patch the game Inject(); } @@ -121,14 +125,13 @@ public bool IsPatched() private void GetInstanceAssemblies(string installInstance) { // This is kind of verbose, might need to be rewritten in a more concise manner - string installResourcesDir = null; - if(installInstance == Constants.GameExe) + if (installInstance == Constants.GameExe) { - installResourcesDir = Constants.GameResourcesDir; + _installResourcesDir = Constants.GameResourcesDir; } - else if(installInstance == Constants.ServerExe) + else if (installInstance == Constants.ServerExe) { - installResourcesDir = Constants.ServerResourcesDir; + _installResourcesDir = Constants.ServerResourcesDir; } System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(installResourcesDir), "Invalid install dir!"); @@ -210,6 +213,15 @@ private void CreateLoaderMethodBody(ref ILProcessor processor, ref MethodDefinit typeof(Type) })); + // Get Environment.CurrentDirectory in the runtime + var curDir = _module.ImportReference(typeof(Environment).GetMethod("get_CurrentDirectory")); + // Path combine for joining the assembly full path + var pathCombine = _module.ImportReference(typeof(Path).GetMethod("Combine", new[] + { + typeof(string), + typeof(string) + })); + var invokeMember = _module.ImportReference(typeof(Type).GetMethod("InvokeMember", new[] { typeof(string), @@ -226,8 +238,11 @@ private void CreateLoaderMethodBody(ref ILProcessor processor, ref MethodDefinit method.Body.Variables.Add(new VariableDefinition(_module.ImportReference(typeof(object)))); // Create instructions - processor.Append(processor.Create(OpCodes.Ldstr, Constants.LoaderAssemblyFileName)); - processor.Append(processor.Create(OpCodes.Call, loadFile)); + processor.Append(processor.Create(OpCodes.Nop)); + processor.Append(processor.Create(OpCodes.Call, curDir)); // load current dir + processor.Append(processor.Create(OpCodes.Ldstr, Constants.LoaderAssemblyFileName)); // load assembly path + processor.Append(processor.Create(OpCodes.Call, pathCombine)); // call Path.Combine + processor.Append(processor.Create(OpCodes.Call, loadFile)); // call Assembly.LoadFile(resultingPath) processor.Append(processor.Create(OpCodes.Ldstr, Constants.LoaderTypeName)); processor.Append(processor.Create(OpCodes.Callvirt, getType)); @@ -239,7 +254,7 @@ private void CreateLoaderMethodBody(ref ILProcessor processor, ref MethodDefinit processor.Append(processor.Create(OpCodes.Ldloc_0)); processor.Append(processor.Create(OpCodes.Ldstr, Constants.LoaderFunctionName)); - processor.Append(processor.Create(OpCodes.Ldc_I4, (int) BindingFlags.InvokeMethod)); + processor.Append(processor.Create(OpCodes.Ldc_I4, (int)BindingFlags.InvokeMethod)); processor.Append(processor.Create(OpCodes.Ldnull)); processor.Append(processor.Create(OpCodes.Ldloc_1)); @@ -250,5 +265,33 @@ private void CreateLoaderMethodBody(ref ILProcessor processor, ref MethodDefinit processor.Append(processor.Create(OpCodes.Pop)); processor.Append(processor.Create(OpCodes.Ret)); } + + private void CopyRequiredAssemblies() + { + // This was taken from Stationeers.Addons csproj + // Perhaps it could be "cecilled" in a PreBuild Script? + // Copies required runtime assemblies to the Managed folder which seems to load them + // (without doing this, you get filenotfoundexceptions in the game runtime console for 0harmony, etc) + var assemblies = new[] + { + "0Harmony", + "Microsoft.CodeAnalysis", + "Microsoft.CodeAnalysis.CSharp", + "System.Buffers", + "System.Collections.Immutable", + "System.Memory", + "System.Numerics.Vectors", + "System.Reflection.Metadata", + "System.Runtime.CompilerServices.Unsafe", + "System.Text.Encoding.CodePages", + "System.Threading.Tasks.Extensions" + }; + foreach (var assemblyFile in assemblies.Select(i => i + ".dll")) + { + var from = Path.Combine(Environment.CurrentDirectory, assemblyFile); + var to = Path.Combine(Environment.CurrentDirectory, _installResourcesDir, AssemblyDir, assemblyFile); + File.Copy(from, to, true); + } + } } -} \ No newline at end of file +}