-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #280 from SpaceWarpDev/preload-and-restart
Added preloader and restarter
- Loading branch information
Showing
15 changed files
with
392 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project> | ||
<Import Project="$(SolutionDir)/Directory.Build.props"/> | ||
|
||
<!-- Build configuration --> | ||
<PropertyGroup> | ||
<GenerateDocumentationFile>false</GenerateDocumentationFile> | ||
<BaseOutputPath>$(PreloaderBinPath)/$(MSBuildProjectName)</BaseOutputPath> | ||
<BaseIntermediateOutputPath>$(PreloaderObjPath)/$(MSBuildProjectName)</BaseIntermediateOutputPath> | ||
</PropertyGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
using System.Reflection; | ||
using JetBrains.Annotations; | ||
using Newtonsoft.Json.Linq; | ||
|
||
namespace SpaceWarp.Preloader; | ||
|
||
internal static class Entrypoint | ||
{ | ||
private static readonly List<string> PreloadAssemblyPaths = | ||
[ | ||
Path.Combine("KSP2_x64_Data", "Managed", "Newtonsoft.Json.dll"), | ||
Path.Combine("BepInEx", "core", "BepInEx.Preloader.dll"), | ||
]; | ||
|
||
private static string _gameFolder; | ||
private static Logger _logger; | ||
|
||
[UsedImplicitly] | ||
public static void Main(string[] args) | ||
{ | ||
_gameFolder = Path.GetDirectoryName(Environment.GetCommandLineArgs()[0])!; | ||
_logger = new Logger(_gameFolder); | ||
|
||
PreloadAssemblies(); | ||
ProcessAllPatchers(); | ||
StartBepinex(); | ||
} | ||
|
||
private static void PreloadAssemblies() | ||
{ | ||
foreach (var fullPath in PreloadAssemblyPaths.Select(assemblyPath => Path.Combine(_gameFolder, assemblyPath))) | ||
{ | ||
try | ||
{ | ||
_logger.LogDebug($"Preloading {fullPath}..."); | ||
Assembly.LoadFile(fullPath); | ||
} | ||
catch (Exception ex) | ||
{ | ||
_logger.LogException(ex, $"An error occurred while preloading the assembly {fullPath}:"); | ||
} | ||
} | ||
} | ||
|
||
private static void StartBepinex() | ||
{ | ||
BepInEx.Preloader.Entrypoint.Main(); | ||
} | ||
|
||
#region Disabling patchers of disabled plugins | ||
|
||
private static void ProcessAllPatchers() | ||
{ | ||
var disabledPluginGuids = GetDisabledPluginGuids(); | ||
|
||
var swinfoPaths = Directory | ||
.EnumerateFiles( | ||
Path.Combine(_gameFolder, "BepInEx", "plugins"), | ||
"swinfo.json", | ||
SearchOption.AllDirectories | ||
); | ||
|
||
var enablePatchers = new List<string>(); | ||
var disablePatchers = new List<string>(); | ||
|
||
foreach (var swinfoPath in swinfoPaths) | ||
{ | ||
try | ||
{ | ||
var (guid, patchers) = ReadSwinfo(swinfoPath); | ||
|
||
if (patchers == null) | ||
{ | ||
continue; | ||
} | ||
|
||
if (!disabledPluginGuids.Contains(guid)) | ||
{ | ||
enablePatchers.AddRange(patchers.Select(StripExtension)); | ||
} | ||
else | ||
{ | ||
disablePatchers.AddRange(patchers.Select(StripExtension)); | ||
} | ||
} | ||
catch (Exception ex) | ||
{ | ||
_logger.LogException(ex, $"An error occurred while processing {swinfoPath}:"); | ||
} | ||
} | ||
|
||
RenameAllPatchers(enablePatchers, disablePatchers); | ||
} | ||
|
||
private static string[] GetDisabledPluginGuids() | ||
{ | ||
var disabledPluginsPath = Path.Combine(_gameFolder, "BepInEx", "disabled_plugins.cfg"); | ||
|
||
return File.Exists(disabledPluginsPath) | ||
? File.ReadAllLines(disabledPluginsPath) | ||
: []; | ||
} | ||
|
||
private static (string guid, List<string> patchers) ReadSwinfo(string swinfoPath) | ||
{ | ||
_logger.LogDebug($"Reading {swinfoPath}..."); | ||
|
||
var swinfo = JObject.Parse(File.ReadAllText(swinfoPath)); | ||
|
||
var guid = swinfo["mod_id"]?.Value<string>(); | ||
if (guid == null) | ||
{ | ||
throw new Exception($"{swinfoPath} does not contain a mod_id."); | ||
} | ||
|
||
var patchers = swinfo["patchers"]?.Values<string>().ToList(); | ||
if (patchers == null) | ||
{ | ||
_logger.LogInfo($"{guid} does not contain patchers, skipping."); | ||
} | ||
|
||
return (guid, patchers); | ||
} | ||
|
||
private static void RenameAllPatchers(ICollection<string> enablePatchers, ICollection<string> disablePatchers) | ||
{ | ||
var patchers = Directory | ||
.EnumerateFiles(Path.Combine(_gameFolder, "BepInEx", "patchers"), "*", SearchOption.AllDirectories) | ||
.Where(file => file.EndsWith(".dll") || file.EndsWith(".dll.disabled")); | ||
|
||
foreach (var patcher in patchers) | ||
{ | ||
var patcherName = StripExtension(Path.GetFileName(patcher)); | ||
|
||
if (enablePatchers.Contains(patcherName) && patcher.EndsWith(".dll.disabled")) | ||
{ | ||
_logger.LogDebug($"Enabling {patcherName}..."); | ||
File.Move(patcher, patcher.Replace(".dll.disabled", ".dll")); | ||
} | ||
else if (disablePatchers.Contains(patcherName) && patcher.EndsWith(".dll")) | ||
{ | ||
_logger.LogDebug($"Disabling {patcherName}..."); | ||
File.Move(patcher, patcher.Replace(".dll", ".dll.disabled")); | ||
} | ||
else | ||
{ | ||
_logger.LogDebug($"Skipping {patcherName}..."); | ||
} | ||
} | ||
} | ||
|
||
private static string StripExtension(string filename) | ||
{ | ||
return filename.Replace(".disabled", "").Replace(".dll", ""); | ||
} | ||
|
||
#endregion | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
using System.ComponentModel; | ||
|
||
namespace SpaceWarp.Preloader; | ||
|
||
internal enum LogLevel | ||
{ | ||
Debug, | ||
Info, | ||
Warning, | ||
Error | ||
} | ||
|
||
internal static class LogLevelExtensions | ||
{ | ||
public static string ToLogString(this LogLevel logLevel) | ||
{ | ||
return logLevel switch | ||
{ | ||
LogLevel.Debug => "DEBUG", | ||
LogLevel.Info => "INFO ", | ||
LogLevel.Warning => "WARN ", | ||
LogLevel.Error => "ERR ", | ||
_ => throw new InvalidEnumArgumentException(nameof(logLevel), (int)logLevel, typeof(LogLevel)) | ||
}; | ||
} | ||
} | ||
|
||
internal class Logger | ||
{ | ||
private readonly string _logPath; | ||
|
||
public Logger(string gamePath) | ||
{ | ||
_logPath = Path.Combine(gamePath, "BepInEx", "SpaceWarp.Preload.log"); | ||
|
||
if (File.Exists(_logPath)) | ||
{ | ||
File.Delete(_logPath); | ||
} | ||
} | ||
|
||
private void Log(object message, LogLevel logLevel = LogLevel.Info) | ||
{ | ||
var logMessage = | ||
$"[{logLevel.ToLogString()}: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}{Environment.NewLine}"; | ||
File.AppendAllText(_logPath, logMessage); | ||
} | ||
|
||
public void LogDebug(object message) | ||
{ | ||
Log(message, LogLevel.Debug); | ||
} | ||
|
||
public void LogInfo(object message) | ||
{ | ||
Log(message, LogLevel.Info); | ||
} | ||
|
||
public void LogWarning(object message) | ||
{ | ||
Log(message, LogLevel.Warning); | ||
} | ||
|
||
public void LogError(object message) | ||
{ | ||
Log(message, LogLevel.Error); | ||
} | ||
|
||
public void LogException(Exception ex, string message = null) | ||
{ | ||
var logMessage = $"{ex.Message}{Environment.NewLine}{ex.StackTrace}"; | ||
if (message != null) | ||
{ | ||
logMessage = $"{message}{Environment.NewLine}{logMessage}"; | ||
} | ||
|
||
LogError(logMessage); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<!-- References --> | ||
<ItemGroup Label="NuGet package references"> | ||
<PackageReference Include="BepInEx.AssemblyPublicizer.MSBuild" Version="0.4.1" Private="false"/> | ||
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" Private="false"/> | ||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" Private="false"/> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<Reference Include="BepInEx.Preloader" Publicize="true" PrivateAssets="all" Private="false"> | ||
<HintPath>$(SolutionDir)/plugin_template/BepInEx/core/BepInEx.Preloader.dll</HintPath> | ||
</Reference> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project> | ||
<Import Project="$(SolutionDir)/Directory.Build.props"/> | ||
|
||
<!-- Build configuration --> | ||
<PropertyGroup> | ||
<GenerateDocumentationFile>false</GenerateDocumentationFile> | ||
<BaseOutputPath>$(RestarterBinPath)/$(MSBuildProjectName)</BaseOutputPath> | ||
<BaseIntermediateOutputPath>$(RestarterObjPath)/$(MSBuildProjectName)</BaseIntermediateOutputPath> | ||
</PropertyGroup> | ||
</Project> |
Oops, something went wrong.