Skip to content

Commit

Permalink
adding linux client support
Browse files Browse the repository at this point in the history
  • Loading branch information
Ventilador committed Jan 14, 2023
1 parent f409568 commit 13b3935
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 10 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,27 @@
**Current status:** Available for early testing.<br>

## 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)
Expand Down
63 changes: 53 additions & 10 deletions Source/Stationeers.Addons.Patcher/Core/Patchers/MonoPatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);

Expand Down Expand Up @@ -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();
}
Expand All @@ -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!");

Expand Down Expand Up @@ -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),
Expand All @@ -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));
Expand All @@ -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));
Expand All @@ -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);
}
}
}
}
}

0 comments on commit 13b3935

Please sign in to comment.