Skip to content
This repository was archived by the owner on Jun 27, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using OpenMod.Installer.RocketMod.Jobs;

namespace OpenMod.Installer.RocketMod
Expand All @@ -19,5 +20,14 @@ public static string[] GetPreventionCommands(this Type type)
var attributes = type.GetCustomAttributes<PreventAttribute>();
return attributes.Select(x => x.CommandToPrevent).ToArray();
}

private static readonly Regex VersionRegex = new Regex("Version=(?<version>.+?), ", RegexOptions.Compiled);

public static string GetVersionIndependentName(string fullAssemblyName, out string extractedVersion)
{
var match = VersionRegex.Match(fullAssemblyName);
extractedVersion = match.Groups[1].Value;
return VersionRegex.Replace(fullAssemblyName, string.Empty);
}
}
}
14 changes: 14 additions & 0 deletions src/Helpers/AsyncHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Nito.AsyncEx;
using System;
using System.Threading.Tasks;

namespace OpenMod.Installer.RocketMod.Helpers
{
public static class AsyncHelper
{
public static void RunSync(Func<Task> func)
{
AsyncContext.Run(func);
}
}
}
36 changes: 36 additions & 0 deletions src/Helpers/NuGetHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using OpenMod.NuGet;
using System;

namespace OpenMod.Installer.RocketMod.Helpers
{
public static class NuGetHelper
{
private static NuGetPackageManager NuGetPackageManager { get; set; }
public static NuGetPackageManager GetNuGetPackageManager()
{
if (NuGetPackageManager != null)
{
return NuGetPackageManager;
}

var path = OpenModInstallerPlugin.Instance.OpenModManager.PackagesDirectory;
Environment.SetEnvironmentVariable("NUGET_COMMON_APPLICATION_DATA", path);

// NuGetPackageManager should auto create directory
NuGetPackageManager = new NuGetPackageManager(path)
{
Logger = new NuGetConsoleLogger()
};

// these dependencies do not exist on NuGet and create warnings
// they are not required
NuGetPackageManager.IgnoreDependencies(
"Microsoft.NETCore.Platforms",
"Microsoft.Packaging.Tools",
"NETStandard.Library",
"System.IO.FileSystem.Watcher");

return NuGetPackageManager;
}
}
}
59 changes: 59 additions & 0 deletions src/Jobs/AssemblyLoadJob.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace OpenMod.Installer.RocketMod.Jobs
{
public class AssemblyLoadJob : IJob, IRevertable
{
private static bool _assemblyResolveInstalled;
private static readonly Dictionary<string, Assembly> _loadedAssembles = new Dictionary<string, Assembly>();

public void ExecuteMigration()
{
if (!_assemblyResolveInstalled)
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
_assemblyResolveInstalled = true;
}

foreach (var file in Directory.GetFiles(OpenModInstallerPlugin.Instance.OpenModManager.WorkingDirectory))
{
if (file.EndsWith(".dll"))
{
var dllPath = Path.Combine(OpenModInstallerPlugin.Instance.OpenModManager.WorkingDirectory, file);
var asm = Assembly.Load(File.ReadAllBytes(dllPath));

var name = Extensions.GetVersionIndependentName(asm.FullName, out _);
if (_loadedAssembles.ContainsKey(name))
{
continue;
}

_loadedAssembles.Add(name, asm);
}
}
}

private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var name = Extensions.GetVersionIndependentName(args.Name, out _);
if (_loadedAssembles.ContainsKey(name))
{
return _loadedAssembles[name];
}
return null;
}

public void Revert()
{
if (_assemblyResolveInstalled)
{
_loadedAssembles.Clear();
AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
_assemblyResolveInstalled = false;
}
}
}
}
48 changes: 45 additions & 3 deletions src/Jobs/NuGetInstallJob.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
namespace OpenMod.Installer.RocketMod.Jobs
using OpenMod.Installer.RocketMod.Helpers;
using OpenMod.NuGet;
using Rocket.Core.Logging;
using System;
using System.IO;
using System.Threading.Tasks;

namespace OpenMod.Installer.RocketMod.Jobs
{
public abstract class NuGetInstallJob : IJob
public abstract class NuGetInstallJob : IJob, IRevertable
{
private readonly string _packageId;
private string _packageDirectory;

protected NuGetInstallJob(string packageId)
{
Expand All @@ -11,7 +19,41 @@ protected NuGetInstallJob(string packageId)

public void ExecuteMigration()
{
throw new System.NotImplementedException();
AsyncHelper.RunSync(DownloadPackage);
}

private async Task DownloadPackage()
{
var nuGetPackageManager = NuGetHelper.GetNuGetPackageManager();

const bool allowPrereleaseVersions = false;

var pluginPackage = await nuGetPackageManager.QueryPackageExactAsync(_packageId, includePreRelease: allowPrereleaseVersions);
if (pluginPackage == null)
{
Logger.Log($"Downloading has failed for {_packageId}: {NuGetInstallCode.PackageOrVersionNotFound}");
return;
}
var installResult = await nuGetPackageManager.InstallAsync(pluginPackage.Identity, allowPrereleaseVersions);
if (installResult.Code == NuGetInstallCode.Success)
{
_packageDirectory = Path.Combine(OpenModInstallerPlugin.Instance.OpenModManager.PackagesDirectory,
installResult.Identity.ToString());
Logger.Log($"Finished downloading \"{_packageId}\".");
}
else
{
Logger.Log($"Downloading has failed for {pluginPackage.Identity.Id} v{pluginPackage.Identity.Version.OriginalVersion}: {installResult.Code}");
}
}

public void Revert()
{
if (string.IsNullOrEmpty(_packageDirectory) || !Directory.Exists(_packageDirectory))
{
return;
}
Directory.Delete(_packageDirectory, true);
}
}
}
53 changes: 26 additions & 27 deletions src/Jobs/OpenModModuleInstallJob.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Newtonsoft.Json;
using Newtonsoft.Json;
using OpenMod.Installer.RocketMod.Models;
using Rocket.Core.Logging;
using SDG.Unturned;
using System;
using System.IO;
using System.IO.Compression;
Expand All @@ -13,46 +12,46 @@ public class OpenModModuleInstallJob : IJob, IRevertable
{
public void ExecuteMigration()
{
var webClient = new WebClient();
using var webClient = new WebClient();
webClient.Headers.Add("User-Agent", "request");

var releaseData = webClient.DownloadString("https://api.github.com/repos/openmod/openmod/releases/latest");
if (string.IsNullOrEmpty(releaseData))
{
throw new NullReferenceException("GitHub API returns empty request");
}

var release = JsonConvert.DeserializeObject<LatestRelease>(releaseData);
var downloadLink = release.Assets.Find(x => x.BrowserDownloadUrl.Contains("OpenMod.Unturned.Module"))?.BrowserDownloadUrl;
if (downloadLink == null)

//this can never be empty UNLESS troja posts a release without Module
var moduleAsset = release.Assets.Find(x => x.BrowserDownloadUrl.Contains("OpenMod.Unturned.Module"));
Logger.Log($"Downloading {moduleAsset.AssetName}");
var dataZip = webClient.DownloadData(moduleAsset.BrowserDownloadUrl);
Logger.Log("Extracting..");
var modulesDirectory = OpenModInstallerPlugin.Instance.OpenModManager.WorkingDirectory;
ExtractArchive(dataZip, modulesDirectory);
Logger.Log("Successfully installed OpenMod module.");
}

//There can be a long talk about this made to be universal while actually not being universal.
public void ExtractArchive(byte[] archive, string directory)
{
if (!Directory.Exists(directory))
{
throw new NullReferenceException(nameof(downloadLink));
Directory.CreateDirectory(directory);
}

Logger.Log($"Downloading OpenMod.Unturned.Module..");
var dataZip = webClient.DownloadData(downloadLink);

Logger.Log("Extracting..");
using MemoryStream stream = new MemoryStream(dataZip);
// ZipStorer dispose is broken, so using instead memoryStream dispose
using var stream = new MemoryStream(archive);
var zip = ZipStorer.Create(stream);
foreach (var file in zip.ReadCentralDir())
{
var path = Path.Combine(OpenModInstallerPlugin.Instance.OpenModManager.WorkingDirectory,
Path.GetFileName(file.FilenameInZip));
//We dont want to leave the readme in the Modules folder do we?
if (file.FilenameInZip == "Readme.txt")
continue;
var path = Path.Combine(directory, Path.GetFileName(file.FilenameInZip));
zip.ExtractFile(file, path);
}

var rocketModulePath = Path.Combine(ReadWrite.PATH, "Modules", "Rocket.Unturned", "Rocket.Unturned.module");
var renamedRocketModulePath = Path.Combine(ReadWrite.PATH, "Modules", "Rocket.Unturned", "Rocket.Unturned.module.bak");
if(File.Exists(rocketModulePath))
{
File.Move(rocketModulePath, renamedRocketModulePath);
}
Logger.Log("Successfully installed OpenMod module.");
}

public void Revert()
{
if (Directory.Exists(OpenModInstallerPlugin.Instance.OpenModManager.WorkingDirectory))
Directory.Delete(OpenModInstallerPlugin.Instance.OpenModManager.WorkingDirectory, true);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OpenMod.Installer.RocketMod.Jobs.OpenModPackagesInstallJobs
{
public class OpenModUnityEngineInstallJob : NuGetInstallJob
{
public OpenModUnityEngineInstallJob() : base("OpenMod.UnityEngine")
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace OpenMod.Installer.RocketMod.Jobs.OpenModPackagesInstallJobs
{
public class OpenModUnturnedInstallJob : NuGetInstallJob
{
public OpenModUnturnedInstallJob() : base("OpenMod.Unturned")
{
}
}
}
2 changes: 1 addition & 1 deletion src/Jobs/OpenModUconomyToOpenModInstallJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[Prevent("--no-uconomy-link")]
public class OpenModUconomyToOpenModInstallJob : NuGetInstallJob
{
public OpenModUconomyToOpenModInstallJob() : base("OpenMod.Unturned.UconomyToOpenMod")
public OpenModUconomyToOpenModInstallJob() : base("OpenMod.UconomyToOpenMod")
{
}
}
Expand Down
5 changes: 0 additions & 5 deletions src/Jobs/RocketModUninstallJob.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
using SDG.Unturned;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OpenMod.Installer.RocketMod.Jobs
{
Expand Down
2 changes: 2 additions & 0 deletions src/OpenMod.Installer.RocketMod.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Nito.AsyncEx" Version="5.1.0" />
<PackageReference Include="OpenMod.NuGet" Version="2.3.8" />
<PackageReference Include="OpenMod.UnityEngine.Redist" Version="2019.4.10" />
<PackageReference Include="OpenMod.Unturned.Redist" Version="3.20.14" />
</ItemGroup>
Expand Down
19 changes: 11 additions & 8 deletions src/OpenModInstallerPlugin.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
using System;
using System.IO;
using System.Linq;
using OpenMod.Installer.RocketMod.Jobs;
using OpenMod.Installer.RocketMod.Jobs;
using OpenMod.Installer.RocketMod.Jobs.OpenModPackagesInstallJobs;
using Rocket.Core.Plugins;
using SDG.Unturned;
using UnityEngine;
using System;
using System.IO;
using System.Linq;

// todo: main command logs
// NuGetInstallJob implementation by using OpenMod.NuGet
// OpenModRocketModUninstallJob (rename RocketMod module to module.bak and rename OpenMod to .bak)
// OpenModPermissionsMigrationJob (migrate permissions, only if PermissionLink will get installed)
// OpenModUconomyMigrationJob (execute /migrate of OpenMod.Economy after next restart)
Expand All @@ -28,11 +27,15 @@ protected override void Load()
Instance = this;

var openmodPath = Path.Combine(ReadWrite.PATH, "Modules", "OpenMod.Unturned");
OpenModManager = new OpenModManager(openmodPath);
var packagesPath = Path.Combine(ReadWrite.PATH, "Servers", Provider.serverID, "OpenMod", "packages");
OpenModManager = new OpenModManager(openmodPath, packagesPath);
JobsManager = new JobsManager();

JobsManager.RegisterJob(new OpenModModuleInstallJob());
JobsManager.RegisterJob(new OpenModRocketModUninstallJob());
JobsManager.RegisterJob(new RocketModUninstallJob());
JobsManager.RegisterJob(new AssemblyLoadJob());
JobsManager.RegisterJob(new OpenModUnturnedInstallJob());
JobsManager.RegisterJob(new OpenModUnityEngineInstallJob());
JobsManager.RegisterJob(new OpenModCooldownsInstallJob());
JobsManager.RegisterJob(new OpenModEconomyInstallJob());
JobsManager.RegisterJob(new OpenModPermissionLinkInstallJob());
Expand Down
4 changes: 3 additions & 1 deletion src/OpenModManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
{
public class OpenModManager
{
public OpenModManager(string workingDirectory)
public OpenModManager(string workingDirectory, string packagesDirectory)
{
WorkingDirectory = workingDirectory;
PackagesDirectory = packagesDirectory;
}

public string WorkingDirectory { get; } // gets the openmod directory
public string PackagesDirectory { get; }
}
}