diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index c8ac194..36ee228 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest env: DOTNET_VERSION: 9.0 - PROJECT: StarMap.Launcher/StarMap.Launcher.csproj + PROJECT: StarMap/StarMap.csproj NUGET_SOURCE: "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" steps: diff --git a/.github/workflows/rc-build.yml b/.github/workflows/rc-build.yml index 7498361..42ce53e 100644 --- a/.github/workflows/rc-build.yml +++ b/.github/workflows/rc-build.yml @@ -6,11 +6,8 @@ on: env: DOTNET_VERSION: 10.0 - STANDALONE_PROJECT: StarMap.Loader/StarMap.Loader.csproj - LAUNCHER_PROJECT: StarMap.Launcher/StarMap.Launcher.csproj + PROJECT: StarMap/StarMap.csproj API_PROJECT: StarMap.API/StarMap.API.csproj - STANDALONE_OUTPUT_PATH: ./publish/standalone - LAUNCHER_OUTPUT_PATH: ./publish/launcher OUTPUT_PATH: ./publish NUGET_SOURCE: "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" EXCLUDE: "*.pdb *.xml" @@ -75,11 +72,11 @@ jobs: --store-password-in-clear-text \ --name github "${{ env.NUGET_SOURCE }}" - - name: Build launcher + - name: Build run: | - dotnet publish ${{ env.LAUNCHER_PROJECT }} \ + dotnet publish ${{ env.PROJECT }} \ -c Release \ - -o ${{ env.LAUNCHER_OUTPUT_PATH }} \ + -o ${{ env.OUTPUT_PATH }} \ -r win-x64 \ --self-contained false \ /p:PackageVersion=${{ steps.version.outputs.hash_version }} \ @@ -87,23 +84,6 @@ jobs: /p:AssemblyVersion=${{ steps.version.outputs.new_version }} \ /p:FileVersion=${{ steps.version.outputs.new_version }} - - name: Build standalone - run: | - dotnet publish ${{ env.STANDALONE_PROJECT }} \ - -c Release \ - -o ${{ env.STANDALONE_OUTPUT_PATH }} \ - -r win-x64 \ - --self-contained false \ - /p:PackageVersion=${{ steps.version.outputs.hash_version }} \ - /p:Version=${{ steps.version.outputs.new_version }} \ - /p:AssemblyVersion=${{ steps.version.outputs.new_version }} \ - /p:FileVersion=${{ steps.version.outputs.new_version }} - - - name: Rename executables - run: | - mv ${{ env.LAUNCHER_OUTPUT_PATH }}/StarMap.Launcher.exe ${{ env.LAUNCHER_OUTPUT_PATH }}/StarMap.exe - mv ${{ env.STANDALONE_OUTPUT_PATH }}/StarMap.Loader.exe ${{ env.STANDALONE_OUTPUT_PATH }}/StarMap.exe - - name: Write version file run: echo "${{ steps.version.outputs.hash_version }}" > version.txt @@ -112,8 +92,7 @@ jobs: with: name: rc-build path: | - ${{ env.LAUNCHER_OUTPUT_PATH }} - ${{ env.STANDALONE_OUTPUT_PATH }} + ${{ env.OUTPUT_PATH }} version.txt retention-days: 1 @@ -176,16 +155,10 @@ jobs: sudo apt-get update -y sudo apt-get install -y zip - - name: Package launcher ZIP - run: | - cd ./build_artifacts/${{ env.LAUNCHER_OUTPUT_PATH }} - zip -r $GITHUB_WORKSPACE/StarMapLauncher-RC.zip . -x ${{ env.EXCLUDE }} - cd - - - - name: Package standalone ZIP + - name: Package ZIP run: | - cd ./build_artifacts/${{ env.STANDALONE_OUTPUT_PATH }} - zip -r $GITHUB_WORKSPACE/StarMapStandalone-RC.zip . -x ${{ env.EXCLUDE }} + cd ./build_artifacts/${{ env.OUTPUT_PATH }} + zip -r $GITHUB_WORKSPACE/StarMap-RC.zip . -x ${{ env.EXCLUDE }} cd - - name: Update RC GitHub release @@ -195,8 +168,7 @@ jobs: name: Release Candidate prerelease: true files: | - StarMapLauncher-RC.zip - StarMapStandalone-RC.zip + StarMap-RC.zip ./build_artifacts/version.txt env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6c184d4..5841bea 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,11 +7,8 @@ on: env: DOTNET_VERSION: 10.0 - STANDALONE_PROJECT: StarMap.Loader/StarMap.Loader.csproj - LAUNCHER_PROJECT: StarMap.Launcher/StarMap.Launcher.csproj + PROJECT: StarMap/StarMap.csproj API_PROJECT: StarMap.API/StarMap.API.csproj - STANDALONE_OUTPUT_PATH: ./publish/standalone - LAUNCHER_OUTPUT_PATH: ./publish/launcher OUTPUT_PATH: ./publish NUGET_SOURCE: "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" EXCLUDE: "*.pdb *.xml" @@ -86,23 +83,11 @@ jobs: --store-password-in-clear-text \ --name github "${{ env.NUGET_SOURCE }}" - - name: Build launcher - run: | - dotnet publish ${{ env.LAUNCHER_PROJECT }} \ - -c Release \ - -o ${{ env.LAUNCHER_OUTPUT_PATH }} \ - -r win-x64 \ - --self-contained false \ - /p:PackageVersion=${{ steps.version.outputs.new_version }} \ - /p:Version=${{ steps.version.outputs.new_version }} \ - /p:AssemblyVersion=${{ steps.version.outputs.new_version }} \ - /p:FileVersion=${{ steps.version.outputs.new_version }} - - name: Build standalone run: | - dotnet publish ${{ env.STANDALONE_PROJECT }} \ + dotnet publish ${{ env.PROJECT }} \ -c Release \ - -o ${{ env.STANDALONE_OUTPUT_PATH }} \ + -o ${{ env.OUTPUT_PATH }} \ -r win-x64 \ --self-contained false \ /p:PackageVersion=${{ steps.version.outputs.new_version }} \ @@ -110,18 +95,12 @@ jobs: /p:AssemblyVersion=${{ steps.version.outputs.new_version }} \ /p:FileVersion=${{ steps.version.outputs.new_version }} - - name: Rename executables - run: | - mv ${{ env.LAUNCHER_OUTPUT_PATH }}/StarMap.Launcher.exe ${{ env.LAUNCHER_OUTPUT_PATH }}/StarMap.exe - mv ${{ env.STANDALONE_OUTPUT_PATH }}/StarMap.Loader.exe ${{ env.STANDALONE_OUTPUT_PATH }}/StarMap.exe - - name: Upload build artifacts uses: actions/upload-artifact@v4 with: name: publish path: | - ${{ env.LAUNCHER_OUTPUT_PATH }} - ${{ env.STANDALONE_OUTPUT_PATH }} + ${{ env.OUTPUT_PATH }} version.txt retention-days: 1 @@ -216,16 +195,10 @@ jobs: sudo apt-get update -y sudo apt-get install -y zip - - name: Package launcher ZIP - run: | - cd ./build_artifacts/${{ env.LAUNCHER_OUTPUT_PATH }} - zip -r $GITHUB_WORKSPACE/StarMapLauncher-${{ needs.build.outputs.new_version }}.zip . -x ${{ env.EXCLUDE }} - cd - - - - name: Package standalone ZIP + - name: Package ZIP run: | - cd ./build_artifacts/${{ env.STANDALONE_OUTPUT_PATH }} - zip -r $GITHUB_WORKSPACE/StarMapStandalone-${{ needs.build.outputs.new_version }}.zip . -x ${{ env.EXCLUDE }} + cd ./build_artifacts/${{ env.OUTPUT_PATH }} + zip -r $GITHUB_WORKSPACE/StarMap-${{ needs.build.outputs.new_version }}.zip . -x ${{ env.EXCLUDE }} cd - - name: Create GitHub Release @@ -237,8 +210,7 @@ jobs: Automated release for version ${{ needs.build.outputs.new_version }} Triggered by PR #${{ github.event.pull_request.number }} files: | - StarMapLauncher-${{ needs.build.outputs.new_version }}.zip - StarMapStandalone-${{ needs.build.outputs.new_version }}.zip + StarMap-${{ needs.build.outputs.new_version }}.zip build-release-installer: runs-on: windows-latest diff --git a/StarMap.API/StarMap.API.csproj b/StarMap.API/StarMap.API.csproj index 8d55bad..62c4121 100644 --- a/StarMap.API/StarMap.API.csproj +++ b/StarMap.API/StarMap.API.csproj @@ -5,22 +5,31 @@ enable enable true - 1591 + 1591;CS1734 README.md + Debug;Release;SourceNuget - - - + + + + - - - compile; build; analyzers - all - - + + + compile; build; analyzers + all + + + + + + compile; build; analyzers + all + + \ No newline at end of file diff --git a/StarMap.Core/ModRepository/ModLoader.cs b/StarMap.Core/ModRepository/ModLoader.cs index 5c8714d..caa743c 100644 --- a/StarMap.Core/ModRepository/ModLoader.cs +++ b/StarMap.Core/ModRepository/ModLoader.cs @@ -60,7 +60,7 @@ private void PrepareMods() { if (!mod.Enabled) { - Console.WriteLine($"StarMap - Nod loading mod: {mod.Id} because it is disable in manifest"); + Console.WriteLine($"StarMap - Not loading mod: {mod.Id} because it is disable in manifest"); continue; } diff --git a/StarMap.Core/Patches/ModLibraryPatches.cs b/StarMap.Core/Patches/ModLibraryPatches.cs index ab5fcea..0cd5e31 100644 --- a/StarMap.Core/Patches/ModLibraryPatches.cs +++ b/StarMap.Core/Patches/ModLibraryPatches.cs @@ -1,7 +1,13 @@ -using HarmonyLib; +using Brutal.Collections; +using HarmonyLib; using KSA; using StarMap.API; using StarMap.Core.ModRepository; +using StarMap.Core.UI; +using StarMap.Core.UI.ConfirmRestart; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Reflection; namespace StarMap.Core.Patches { @@ -20,5 +26,53 @@ public static void AfterLoad() method.Invoke(@object, []); } } + + [HarmonyPatch(nameof(ModLibrary.PrepareAll))] + [HarmonyPrefix] + public static void BeforePrepareAll() + { + static bool wereNewModsEnabled() + { + foreach (var mod in ModLibrary.Manifest.Mods) + { + if (mod.New && mod.Enabled) + return true; + } + return false; + } + + if (ModLibrary.HasNewMods() && wereNewModsEnabled()) + { + var confirmRestart = new ConfirmRestart(); + while(confirmRestart.Show) + { + confirmRestart.OnFrame(); + } + + if (confirmRestart.Restart) + { + Console.WriteLine("StarMap - RESTARTING"); + Console.WriteLine("======================================"); + + var mainModule = Process.GetCurrentProcess().MainModule; + if (mainModule is null || Path.GetDirectoryName(mainModule.FileName) is not string starMapInstallLocation) + { + Console.WriteLine("Unable to get StarMap install location for restart."); + } + else { + var startInfo = new ProcessStartInfo + { + FileName = mainModule.FileName, + Arguments = "--restarted", + WorkingDirectory = starMapInstallLocation, + }; + + Process.Start(startInfo); + } + + Environment.Exit(0); + } + } + } } } diff --git a/StarMap.Core/StarMap.Core.csproj b/StarMap.Core/StarMap.Core.csproj index 3859eda..7abfbb0 100644 --- a/StarMap.Core/StarMap.Core.csproj +++ b/StarMap.Core/StarMap.Core.csproj @@ -1,29 +1,37 @@  + + net10.0 + enable + enable + Debug;Release;SourceNuget + true + - - net10.0 - enable - enable - - - - - - runtime - - + + + + runtime + + - - - - + + + + + + + + + + runtime + - - + + runtime diff --git a/StarMap.Core/StarMapCore.cs b/StarMap.Core/StarMapCore.cs index 828dbfd..8cc1411 100644 --- a/StarMap.Core/StarMapCore.cs +++ b/StarMap.Core/StarMapCore.cs @@ -1,6 +1,6 @@ using HarmonyLib; using StarMap.Core.ModRepository; -using StarMap.Types.Mods; +using StarMap.Types; using System.Runtime.Loader; namespace StarMap.Core @@ -34,62 +34,4 @@ public void DeInit() _loader.Dispose(); } } -} - -/*public async Task RetrieveManagedMods() -{ - var message = new IPCGetCurrentManagedModsRequest(); - - var response = await _gameFacade.RequestData(message); - - if (!response.Is(IPCGetCurrentManagedModsResponse.Descriptor)) return; - - _managedMods.SetResult(response.Unpack()); -} - -public IPCGetCurrentManagedModsResponse GetManagedMods() -{ - return _managedMods.Task.GetAwaiter().GetResult(); -} - -public async Task GetAvailableModsAsync() -{ - var message = new IPCGetModsRequest(); - - var response = await _gameFacade.RequestData(message); - - if (!response.Is(IPCGetModsResponse.Descriptor)) return []; - - return [.. response.Unpack().Mods]; -} - -public async Task GetModInformationAsync(string id) -{ - var message = new IPCGetModDetailsRequest() - { - Id = id - }; - - var response = await _gameFacade.RequestData(message); - - if (!response.Is(IPCGetModDetailsResponse.Descriptor)) return null; - - return response.Unpack().Mod; -} - -public string[] GetLoadedMods() -{ - if (_loadedMods is null) return []; - - return _loadedMods.Select(loadedMod => loadedMod.Key.Name).ToArray(); -} - -public async Task SetModUpdates(IPCSetManagedMods update) -{ - await _gameFacade.RequestData(update); -} - - //private readonly IGameFacade _gameFacade; - - //private readonly TaskCompletionSource _managedMods = new(); -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/StarMap.Core/UI/ConfirmRestart/ConfirmRestart.cs b/StarMap.Core/UI/ConfirmRestart/ConfirmRestart.cs new file mode 100644 index 0000000..339f8c1 --- /dev/null +++ b/StarMap.Core/UI/ConfirmRestart/ConfirmRestart.cs @@ -0,0 +1,100 @@ +using Brutal.GlfwApi; +using Brutal.ImGuiApi; +using Brutal.VulkanApi; +using Brutal.VulkanApi.Abstractions; +using Core; +using KSA; +using RenderCore; + +namespace StarMap.Core.UI.ConfirmRestart +{ + internal class ConfirmRestart : SetupTaskBase + { + private readonly Renderer _renderer; + private readonly ConfirmRestartPopup _popup; + + public bool Show { get; set; } + public bool Restart { get; set; } + + public static ConfirmRestart? Current { get; private set; } + + public ConfirmRestart() + { + this._renderer = Program.GetRenderer(); + Show = true; + OnFrame(); + Current = this; + + _popup = ConfirmRestartPopup.Create(this); + } + + public void DrawUi() + { + if (!Show) + return; + ImGuiHelper.BlankBackground(); + Popup.DrawAll(); + } + + public unsafe void OnFrame() + { + if (!Program.IsMainThread()) + return; + Glfw.PollEvents(); + if (Program.GetWindow().ShouldClose) + { + Environment.Exit(0); + } + else + { + ImGuiBackend.NewFrame(); + ImGui.NewFrame(); + ImGuiHelper.StartFrame(); + DrawUi(); + ImGui.Render(); + if (EnumEx.IsSet((int)ImGui.GetIO().ConfigFlags, 1024 /*0x0400*/)) + { + ImGui.UpdatePlatformWindows(); + ImGui.RenderPlatformWindowsDefault(); + } + (FrameResult result, AcquiredFrame acquiredFrame1) = _renderer.TryAcquireNextFrame(); + AcquiredFrame acquiredFrame2 = acquiredFrame1; + if (result != 0) + { + PartialRebuild(); + } + else + { + acquiredFrame1 = acquiredFrame2; + (FrameResources resources, CommandBuffer commandBuffer) = acquiredFrame1; + VkSubpassContents contents = VkSubpassContents.Inline; + VkRenderPassBeginInfo pRenderPassBegin = new VkRenderPassBeginInfo() + { + RenderPass = Program.MainPass.Pass, + Framebuffer = resources.Framebuffer, + RenderArea = new VkRect2D(this._renderer.Extent), + ClearValues = (VkClearValue*)Program.MainPass.ClearValues.Ptr, + ClearValueCount = 2 + }; + commandBuffer.Reset(); + commandBuffer.Begin(VkCommandBufferUsageFlags.OneTimeSubmitBit); + commandBuffer.BeginRenderPass(in pRenderPassBegin, contents); + ImGuiBackend.Vulkan.RenderDrawData(commandBuffer); + commandBuffer.EndRenderPass(); + commandBuffer.End(); + if (_renderer.TrySubmitFrame() == 0) + return; + PartialRebuild(); + } + } + } + + public void PartialRebuild() + { + _renderer.Rebuild(GameSettings.GetPresentMode()); + _renderer.Device.WaitIdle(); + Program.MainPass.Pass = _renderer.MainRenderPass; + Program.ScheduleRendererRebuild(); + } + } +} diff --git a/StarMap.Core/UI/ConfirmRestart/ConfirmRestartPopup.cs b/StarMap.Core/UI/ConfirmRestart/ConfirmRestartPopup.cs new file mode 100644 index 0000000..03b22eb --- /dev/null +++ b/StarMap.Core/UI/ConfirmRestart/ConfirmRestartPopup.cs @@ -0,0 +1,49 @@ +using Brutal.ImGuiApi; +using KSA; + +namespace StarMap.Core.UI.ConfirmRestart +{ + internal class ConfirmRestartPopup : Popup + { + private readonly string _title; + public ConfirmRestart UI { get; } + private static readonly PopupButton PopupButtonContinue = CreateButton("Continue", (Action)(popup => + { + popup.Active = false; + popup.UI.Restart = false; + popup.UI.Show = false; + })); + private static readonly PopupButton PopupButtonRestart = CreateButton("Restart", (Action)(popup => + { + popup.Active = false; + popup.UI.Restart = true; + popup.UI.Show = false; + })); + + private static readonly IPopupWidget[] ButtonMatrix = [ + PopupButtonContinue, + PopupButtonRestart + ]; + + private ConfirmRestartPopup(ConfirmRestart ui) + { + _title = "Game requires restart"; + UI = ui; + } + + public static ConfirmRestartPopup Create(ConfirmRestart ui) => new(ui); + + protected override void OnDrawUi() + { + ImGui.OpenPopup((ImString)_title); + ImGui.BeginPopup((ImString)_title, ImGuiWindowFlags.NoMove | ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.Popup); + ImGuiHelper.SetCurrentWindowToCenter(); + var text1 = new ImString(60, 1); + text1.AppendLiteral("New mods have been enabled after starting KSA.\nThe game needs to be restarted for these mods to be loaded in StarMap.".AsSpan()); + ImGui.TextWrapped(text1); + ImGui.Separator(); + DrawUi(this, ButtonMatrix); + ImGui.EndPopup(); + } + } +} diff --git a/StarMap.Launcher/GameProcessSupervisor.cs b/StarMap.Launcher/GameProcessSupervisor.cs deleted file mode 100644 index 1a6806d..0000000 --- a/StarMap.Launcher/GameProcessSupervisor.cs +++ /dev/null @@ -1,90 +0,0 @@ -/*using StarMap.Types.Pipes; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; - -namespace StarMapLoader -{ - internal class GameProcessSupervisor - { - private readonly string _gamePath; - private readonly LoaderFacade _facade; - private readonly PipeServer _pipeServer; - - private Process? _game; - - - public GameProcessSupervisor(string gamePath, LoaderFacade facade, PipeServer pipeServer) - { - _gamePath = gamePath; - _facade = facade; - _pipeServer = pipeServer; - } - - public async Task> TryStartGameAsync(CancellationToken cancellationToken) - { - var processExitedTsc = new TaskCompletionSource(); - - var psi = new ProcessStartInfo - { - FileName = _gamePath, - Arguments = $"{_pipeServer.PipeName}", - UseShellExecute = true, // Use the operating system shell to start the process - CreateNoWindow = false, // Create a new window for the process - RedirectStandardOutput = false, - RedirectStandardError = false, - }; - - var pipeConntection = _pipeServer.StartListening(cancellationToken); - - if (Debugger.IsAttached) - { - _game = FindProcess(); - } - - if (_game is null) - { - _game = new Process - { - StartInfo = psi, - EnableRaisingEvents = true - }; - _game.Start(); - } - - await pipeConntection; - - if (cancellationToken.IsCancellationRequested) - return Task.FromResult(false); - - var processStartedTcs = new TaskCompletionSource(); - - void OnPrcessStarted(object? sender, EventArgs args) - { - _facade.OnProcessStarted -= OnPrcessStarted; - processStartedTcs.TrySetResult(); - } - - _facade.OnProcessStarted += OnPrcessStarted; - await processStartedTcs.Task; - - _game.EnableRaisingEvents = true; - _game.Exited += (s, e) => - { - processExitedTsc.TrySetResult(true); - _pipeServer.Stop(); - }; - - return processExitedTsc.Task; - } - - private static Process? FindProcess() - { - string processName = "StarMap"; - Process[] processes = Process.GetProcessesByName(processName); - return processes.FirstOrDefault(); - } - } -} -*/ \ No newline at end of file diff --git a/StarMap.Launcher/LoaderFacade.cs b/StarMap.Launcher/LoaderFacade.cs deleted file mode 100644 index f9b8153..0000000 --- a/StarMap.Launcher/LoaderFacade.cs +++ /dev/null @@ -1,125 +0,0 @@ -/*using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; -using StarMap.Types; -using StarMap.Types.Pipes; -using StarMap.Types.Proto.IPC; - -namespace StarMapLoader -{ - internal class LoaderFacade : IDisposable - { - private readonly PipeServer _pipeServer; - private readonly LoaderConfig _config; - private readonly ModRepository _repository; - - public event EventHandler? OnProcessStarted; - - public LoaderFacade(PipeServer pipeServer, LoaderConfig config, ModRepository repository) - { - _pipeServer = pipeServer; - _config = config; - _repository = repository; - - _pipeServer.OnMessage += PipeServer_OnRequest; - } - - private void PipeServer_OnRequest(object? sender, Any pipeMessage) - { - if (!pipeMessage.Is(PipeMessage.Descriptor)) return; - - var unpackedPipeMessage = pipeMessage.Unpack(); - var message = unpackedPipeMessage.Payload; - - IMessage? response = null; - - if (message.Is(IPCConnectRequest.Descriptor)) - { - response = new IPCConnectResponse() - { - GameLocation = _config.GameLocation, - }; - - OnProcessStarted?.Invoke(this, EventArgs.Empty); - } - if (message.Is(IPCGetCurrentManagedModsRequest.Descriptor)) - { - var modsRepsonse = new IPCGetCurrentManagedModsResponse(); - modsRepsonse.Mods.AddRange(_repository.LoadedModInformation); - response = modsRepsonse; - } - - if (message.Is(IPCGetModsRequest.Descriptor)) - { - var availableModsResponse = new IPCGetModsResponse(); - var availableMods = _repository.GetPossibleMods().GetAwaiter().GetResult().Select(repositoryMod => new IPCMod() - { - Id = repositoryMod.Id, - Name = repositoryMod.Name, - Author = repositoryMod.Author, - }); - - availableModsResponse.Mods.AddRange(availableMods); - response = availableModsResponse; - } - - if (message.Is(IPCGetModDetailsRequest.Descriptor)) - { - var modDetailsRequest = message.Unpack(); - - var modDetails = _repository.GetModInformation(modDetailsRequest.Id).GetAwaiter().GetResult(); - if (modDetails is null) - { - response = new IPCGetModDetailsResponse(); - } - else - { - var mod = new IPCModDetails() - { - Mod = new IPCMod() - { - Id = modDetails.Mod.Id, - Name = modDetails.Mod.Name, - Author = modDetails.Mod.Author, - }, - Description = modDetails.Description, - }; - mod.Versions.AddRange(modDetails.Versions.Select((version) => new IPCModVersion() - { - Id = version.Id, - Version = version.Version, - DownloadLocation = version.DownloadLocation, - })); - - response = new IPCGetModDetailsResponse() - { - Mod = mod - }; - } - } - - if (message.Is(IPCSetManagedMods.Descriptor)) - { - var setModUpdates = message.Unpack(); - - _repository.SetModUpdates([.. setModUpdates.Updates]); - - response = new Any(); - } - - if (response is not null) - { - _pipeServer.SendResponseAsync(Any.Pack(new PipeMessage() - { - RequestId = unpackedPipeMessage.RequestId, - Payload = Any.Pack(response) - })).GetAwaiter().GetResult(); - } - } - - public void Dispose() - { - _pipeServer.OnMessage -= PipeServer_OnRequest; - } - } -} -*/ \ No newline at end of file diff --git a/StarMap.Launcher/ModDownloader.cs b/StarMap.Launcher/ModDownloader.cs deleted file mode 100644 index 160b3b2..0000000 --- a/StarMap.Launcher/ModDownloader.cs +++ /dev/null @@ -1,22 +0,0 @@ -using StarMap.Types.Proto.IPC; -using System; -using System.Collections.Generic; -using System.IO.Compression; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace StarMapLoader -{ - internal class ModDownloader - { - public bool DownloadMod(IPCMod mod, IPCModVersion version, string location) - { - try - { - return true; - } - catch { return false; } - } - } -} diff --git a/StarMap.Launcher/ModRepository.cs b/StarMap.Launcher/ModRepository.cs deleted file mode 100644 index e735c73..0000000 --- a/StarMap.Launcher/ModRepository.cs +++ /dev/null @@ -1,117 +0,0 @@ -/*//using StarMap.Index.API; -using StarMap.Types.Proto.IPC; -using System.Text.Json; - -namespace StarMapLoader -{ - internal class ModRepository - { - public List LoadedModInformation { get; private set; } = []; - public bool HasChanges { get; private set; } - - private readonly string _modsPath; - //private readonly IModRespositoryClient _foreignModRepository; - private readonly ModDownloader _downloader = new(); - - private IPCUpdateModInformation[] _changes = []; - - - public ModRepository(string gameLocation, IModRespositoryClient foreignModRepository) - { - var gameDirectory = Path.GetDirectoryName(gameLocation); - if (string.IsNullOrEmpty(gameDirectory)) - { - throw new ArgumentException("Invalid game location provided, unable to determine game directory."); - } - - _modsPath = Path.Combine(gameDirectory, "mods"); - _foreignModRepository = foreignModRepository; - - if (!Directory.Exists(_modsPath)) - { - Directory.CreateDirectory(_modsPath); - } - - var filePath = Path.Combine(_modsPath, "starmap.json"); - if (!File.Exists(filePath)) - { - File.Create(filePath).Dispose(); - File.WriteAllText(filePath, JsonSerializer.Serialize(new List())); - } - - string jsonString = File.ReadAllText(Path.Combine(_modsPath, "starmap.json")); - - LoadedModInformation = JsonSerializer.Deserialize>(jsonString) ?? []; - } - - public async Task GetPossibleMods() - { - return await _foreignModRepository.GetMods(); - } - - public async Task GetModInformation(string modId) - { - return await _foreignModRepository.GetModDetails(Guid.Parse(modId)); - } - - public void SetModUpdates(IPCUpdateModInformation[] updates) - { - _changes = updates; - HasChanges = true; - } - - public void ApplyModUpdates() - { - HasChanges = false; - - foreach (var modChange in _changes) - { - try - { - var directoryPath = Path.Combine(_modsPath, modChange.Mod.Name); - - if (Directory.Exists(directoryPath)) - { - Directory.Delete(directoryPath, true); - } - - Directory.CreateDirectory(directoryPath); - - if (!_downloader.DownloadMod(modChange.Mod, modChange.AfterVersion, directoryPath) && modChange.BeforeVersion is not null) - { - Directory.Delete(directoryPath, true); - Directory.CreateDirectory(directoryPath); - _downloader.DownloadMod(modChange.Mod, modChange.BeforeVersion, directoryPath); - } - else - { - var newModInfo = new IPCMod() - { - Id = modChange.Mod.Id, - Name = modChange.Mod.Name, - Version = modChange.AfterVersion.Version - }; - - var index = LoadedModInformation.FindIndex(modInfo => modInfo.Id == newModInfo.Id); - - if (index >= 0) - { - LoadedModInformation[index] = newModInfo; - } - else - { - LoadedModInformation.Add(newModInfo); - } - } - } - catch (Exception ex) - { - Console.WriteLine($"StarMap - Unable to apply update for mod: {modChange.Mod.Name} to version {modChange.AfterVersion?.Version ?? ""}: {ex}"); - } - } - - File.WriteAllText(Path.Combine(_modsPath, "starmap.json"), JsonSerializer.Serialize(LoadedModInformation)); - } - } -} -*/ \ No newline at end of file diff --git a/StarMap.Launcher/Program.cs b/StarMap.Launcher/Program.cs deleted file mode 100644 index 9ec9de2..0000000 --- a/StarMap.Launcher/Program.cs +++ /dev/null @@ -1,46 +0,0 @@ -//using StarMap.Index.API; -using StarMap.Types.Pipes; -using StarMap.Types; -using System.Diagnostics; - -namespace StarMapLoader -{ - internal class Program - { - static void Main(string[] args) - { - Console.WriteLine("Currently WIP, please use the standalone version or launch 'StarMap.Loader.exe'"); - //MainInner().GetAwaiter().GetResult(); - } - - static async Task MainInner() - { - var config = new LoaderConfig(); - if (!config.TryLoadConfig()) return; - - //using var remoteModRepository = new ModRepositoryClient(config.RepositoryLocation); - //var modRepository = new ModRepository(config.GameLocation, remoteModRepository); - - var shouldReload = true; - - var pipeName = Debugger.IsAttached ? "starmap_pipe" : $"starmap_pipe_{Guid.NewGuid()}"; - using var pipeServer = new PipeServer(pipeName); - //using var facade = new LoaderFacade(pipeServer, config, modRepository); - - while (shouldReload) - { - CancellationTokenSource stopGameCancelationTokenSource = new(); - - //var gameSupervisor = new GameProcessSupervisor(config.GameLocation, facade, pipeServer); - - //await await gameSupervisor.TryStartGameAsync(stopGameCancelationTokenSource.Token); - - /*shouldReload = modRepository.HasChanges; - if (shouldReload) - { - modRepository.ApplyModUpdates(); - }*/ - } - } - } -} diff --git a/StarMap.Launcher/StarMap.Launcher.csproj b/StarMap.Launcher/StarMap.Launcher.csproj deleted file mode 100644 index ceec7aa..0000000 --- a/StarMap.Launcher/StarMap.Launcher.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - - - - - - - - - - \ No newline at end of file diff --git a/StarMap.Loader/GameFacade.cs b/StarMap.Loader/GameFacade.cs deleted file mode 100644 index 5953d92..0000000 --- a/StarMap.Loader/GameFacade.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; -using StarMap.Types.Mods; -using StarMap.Types.Pipes; -using StarMap.Types.Proto.IPC; - -namespace StarMap -{ - internal class GameFacade : IGameFacade, IAsyncDisposable - { - private readonly PipeClient _pipe; - - private bool _connected = false; - - public GameFacade(PipeClient pipe) - { - _pipe = pipe; - } - - public async Task Connect() - { - await _pipe.ConnectAsync(default); - _connected = true; - - var connectResponse = await RequestData(new IPCConnectRequest()); - - if (!connectResponse.Is(IPCConnectResponse.Descriptor)) return ""; - - return connectResponse.Unpack().GameLocation; - } - - public async ValueTask DisposeAsync() - { - //await RequestData(new IPCClosePipeMessage()); - _pipe.Dispose(); - } - - public async Task RequestData(IMessage request) - { - if (_pipe is null || !_connected) - throw new InvalidOperationException("Pipe is not connected."); - - var messageReceived = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - var requestId = Guid.NewGuid().ToString(); - - void Handler(object? sender, Any message) - { - if (!message.Is(PipeMessage.Descriptor)) return; - - var responseWrapper = message.Unpack(); - if (responseWrapper.RequestId != requestId) return; - - messageReceived.SetResult(responseWrapper.Payload); - _pipe.OnMessage -= Handler; - } - - _pipe.OnMessage += Handler; - await _pipe.SendMessageAsync(Any.Pack(new PipeMessage() - { - RequestId = requestId, - Payload = Any.Pack(request) - })); - return await messageReceived.Task; - } - } -} diff --git a/StarMap.Loader/Program.cs b/StarMap.Loader/Program.cs deleted file mode 100644 index 63b75c7..0000000 --- a/StarMap.Loader/Program.cs +++ /dev/null @@ -1,66 +0,0 @@ -using StarMap.Types; -using StarMap.Types.Pipes; -using System.Runtime.Loader; - -namespace StarMap -{ - internal class Program - { - static void Main(string[] args) - { - if (args.Length < 1) - { - Console.WriteLine("StarMap - Running Starmap in solo mode!"); - SoleModeInner(); - return; - } - - Console.WriteLine("StarMap - Running Starmap in loader mode."); - - var pipeName = args[0]; - Console.WriteLine($"StarMap - Connection to pipe: {pipeName}"); - - MainInner(pipeName).GetAwaiter().GetResult(); - } - - static void SoleModeInner() - { - var gameConfig = new LoaderConfig(); - - if (!gameConfig.TryLoadConfig()) - { - return; - } - - AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.GetFullPath("./0Harmony.dll")); - - var gameAssemblyContext = new GameAssemblyLoadContext(gameConfig.GameLocation); - var dumbFacade = new SoloGameFacade(); - using var gameSurveyer = new GameSurveyer(dumbFacade, gameAssemblyContext, gameConfig.GameLocation, gameConfig.GameArguments); - if (!gameSurveyer.TryLoadCoreAndGame()) - { - Console.WriteLine("StarMap - Unable to load mod manager and game in solo mode."); - return; - } - - gameSurveyer.RunGame(); - } - - static async Task MainInner(string pipeName) - { - AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.GetFullPath("./0Harmony.dll")); - - var pipeClient = new PipeClient(pipeName); - var facade = new GameFacade(pipeClient); - - var gameLocation = await facade.Connect(); - var gameAssemblyContext = new GameAssemblyLoadContext(Path.GetFullPath(gameLocation)); - var gameSurveyer = new GameSurveyer(facade, gameAssemblyContext, gameLocation, []); - if (!gameSurveyer.TryLoadCoreAndGame()) return; - - gameSurveyer.RunGame(); - - await facade.DisposeAsync(); - } - } -} diff --git a/StarMap.Loader/Properties/launchSettings.json b/StarMap.Loader/Properties/launchSettings.json deleted file mode 100644 index 19a1027..0000000 --- a/StarMap.Loader/Properties/launchSettings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "profiles": { - "StarMap": { - "commandName": "Project" - } - } -} \ No newline at end of file diff --git a/StarMap.Loader/SoloGameFacade.cs b/StarMap.Loader/SoloGameFacade.cs deleted file mode 100644 index eb3438a..0000000 --- a/StarMap.Loader/SoloGameFacade.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; -using StarMap.Types.Mods; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace StarMap -{ - internal class SoloGameFacade : IGameFacade - { - public Task RequestData(IMessage request) - { - return Task.FromResult(new Any()); - } - } -} diff --git a/StarMap.Loader/StarMap.Loader.csproj b/StarMap.Loader/StarMap.Loader.csproj deleted file mode 100644 index b268f94..0000000 --- a/StarMap.Loader/StarMap.Loader.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - - - - - - - - - - diff --git a/StarMap.Types/Mods/IStarMapCore.cs b/StarMap.Types/IStarMapCore.cs similarity index 60% rename from StarMap.Types/Mods/IStarMapCore.cs rename to StarMap.Types/IStarMapCore.cs index 8eac83e..e205ec7 100644 --- a/StarMap.Types/Mods/IStarMapCore.cs +++ b/StarMap.Types/IStarMapCore.cs @@ -1,6 +1,4 @@ -using System.Runtime.Loader; - -namespace StarMap.Types.Mods +namespace StarMap.Types { public interface IStarMapCore { diff --git a/StarMap.Types/Mods/IGameFacade.cs b/StarMap.Types/Mods/IGameFacade.cs deleted file mode 100644 index 8016b75..0000000 --- a/StarMap.Types/Mods/IGameFacade.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; - -namespace StarMap.Types.Mods -{ - public interface IGameFacade - { - Task RequestData(IMessage request); - } -} diff --git a/StarMap.Types/Pipes/PipeClient.cs b/StarMap.Types/Pipes/PipeClient.cs deleted file mode 100644 index 6941bde..0000000 --- a/StarMap.Types/Pipes/PipeClient.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; -using System.IO.Pipes; - -namespace StarMap.Types.Pipes -{ - public class PipeClient - { - private readonly string _pipeName; - private NamedPipeClientStream? _client; - - private Task? _readingTask; - private CancellationTokenSource? _readingCts; - - public event EventHandler? OnMessage; - - public PipeClient(string pipeName) - { - _pipeName = pipeName; - } - - public async Task ConnectAsync(CancellationToken cancellationToken) - { - _client = new NamedPipeClientStream( - serverName: ".", - pipeName: _pipeName, - direction: PipeDirection.InOut, - options: PipeOptions.Asynchronous); - - - Console.WriteLine($"StarMap - Connecting to pipe {_pipeName}..."); - await _client.ConnectAsync(cancellationToken); - - _readingCts = new CancellationTokenSource(); - _readingTask = Task.Run(() => MessageReaderThread(_readingCts.Token), cancellationToken); - } - - private async Task MessageReaderThread(CancellationToken cancellationToken) - { - while (!cancellationToken.IsCancellationRequested) - { - try - { - if (_client is null) - break; - - var message = await _client.ReadProtoAsync(cancellationToken); - - _ = Task.Run(() => OnMessage?.Invoke(this, message), cancellationToken); - } - catch (OperationCanceledException e) { } - } - } - - public async Task SendMessageAsync(IMessage message, CancellationToken cancellationToken = default) - { - if (_client is null) - return; - - await _client.WriteProtoAsync(message, cancellationToken); - } - - public void Dispose() - { - _readingCts?.Cancel(); - _readingTask?.Wait(TimeSpan.FromSeconds(5)); - _client?.Dispose(); - } - } -} diff --git a/StarMap.Types/Pipes/PipeServer.cs b/StarMap.Types/Pipes/PipeServer.cs deleted file mode 100644 index d030f52..0000000 --- a/StarMap.Types/Pipes/PipeServer.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; -using System.IO.Pipes; - -namespace StarMap.Types.Pipes -{ - public sealed class PipeServer : IDisposable - { - public string PipeName { get; } - private NamedPipeServerStream? _server; - - private Task? _readingTask; - private CancellationTokenSource? _readingCts; - public event EventHandler? OnMessage; - - public PipeServer(string pipeName) - { - PipeName = pipeName; - } - - public async Task StartListening(CancellationToken cancellationToken) - { - // Create a named pipe server with bidirectional capability - _server = new NamedPipeServerStream( - PipeName, - PipeDirection.InOut, - maxNumberOfServerInstances: 1, - PipeTransmissionMode.Byte, - PipeOptions.Asynchronous); - - await _server.WaitForConnectionAsync(cancellationToken); - - _readingCts = new CancellationTokenSource(); - _readingTask = Task.Run(() => MessageReaderThread(_readingCts.Token), cancellationToken); - } - - private async Task MessageReaderThread(CancellationToken cancellationToken) - { - while (!cancellationToken.IsCancellationRequested) - { - if (_server is null) - break; - - Any? message = null; - - try - { - message = await _server.ReadProtoAsync(cancellationToken); - } - catch {} - - if (cancellationToken.IsCancellationRequested) - return; - - if (message is null) - continue; - - _ = Task.Run(() => OnMessage?.Invoke(this, message), cancellationToken); - } - } - - public async Task SendResponseAsync(IMessage message, CancellationToken cancellationToken = default) - { - if (_server is null) - return; - - await _server.WriteProtoAsync(message, cancellationToken); - } - - public void Stop() - { - _readingCts?.Cancel(); - _readingTask?.Wait(TimeSpan.FromSeconds(5)); - _server?.Dispose(); - _server = null; - } - - public void Dispose() - { - Stop(); - } - } -} diff --git a/StarMap.Types/Pipes/PipeStreamExtensions.cs b/StarMap.Types/Pipes/PipeStreamExtensions.cs deleted file mode 100644 index 44917d9..0000000 --- a/StarMap.Types/Pipes/PipeStreamExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; -using System.IO.Pipes; - -namespace StarMap.Types.Pipes -{ - internal static class PipeStreamExtensions - { - public static async Task ReadProtoAsync(this PipeStream pipeStream, CancellationToken cancellationToken = default) - { - // Read length prefix - byte[] lengthPrefix = new byte[4]; - int read = await pipeStream.ReadAsync(lengthPrefix, 0, 4, cancellationToken); - if (read != 4) - throw new Exception("Failed to read message length"); - - int messageLength = BitConverter.ToInt32(lengthPrefix, 0); - - // Read the actual message bytes - byte[] buffer = new byte[messageLength]; - int totalRead = 0; - while (totalRead < messageLength) - { - int bytesRead = await pipeStream.ReadAsync(buffer, totalRead, messageLength - totalRead, cancellationToken); - if (cancellationToken.IsCancellationRequested) - return new Any(); - if (bytesRead == 0) - throw new Exception("Pipe closed before reading full message"); - totalRead += bytesRead; - } - - return Any.Parser.ParseFrom(buffer); - } - - public static async Task WriteProtoAsync(this PipeStream pipeStream, IMessage message, CancellationToken cancellationToken = default) - { - byte[] data = message.ToByteArray(); - - byte[] lengthPrefix = BitConverter.GetBytes(data.Length); - await pipeStream.WriteAsync(lengthPrefix, 0, lengthPrefix.Length, cancellationToken); - - await pipeStream.WriteAsync(data, 0, data.Length, cancellationToken); - pipeStream.Flush(); - } - } -} diff --git a/StarMap.Types/Proto/IPC.proto b/StarMap.Types/Proto/IPC.proto deleted file mode 100644 index e29db6f..0000000 --- a/StarMap.Types/Proto/IPC.proto +++ /dev/null @@ -1,73 +0,0 @@ -syntax = "proto3"; - -package StarMap.Types.Proto.IPC; - -import "google/protobuf/any.proto"; - -message PipeMessage { - string RequestId = 1; - google.protobuf.Any Payload = 2; -} - -message IPCConnectRequest { - -} - -message IPCConnectResponse { - string game_location = 1; -} - -message IPCGetCurrentManagedModsRequest { - -} - -message IPCGetCurrentManagedModsResponse { - repeated IPCMod mods = 1; -} - -message IPCGetModsRequest{ - -} - -message IPCGetModsResponse{ - repeated IPCMod mods = 1; -} - -message IPCGetModDetailsRequest{ - string id = 1; -} - -message IPCGetModDetailsResponse{ - IPCModDetails mod = 1; -} - -message IPCMod { - string id = 1; - string name = 2; - string version = 3; - string author = 4; -} - -message IPCModDetails{ - IPCMod mod = 1; - repeated IPCModVersion versions = 2; - string description = 3; -} - -message IPCModVersion{ - string id = 1; - string version = 2; - string download_location = 3; -} - -message IPCUpdateModInformation{ - IPCMod mod = 1; - IPCModVersion before_version = 2; - IPCModVersion after_version = 3; -} - -message IPCSetManagedMods{ - repeated IPCUpdateModInformation updates = 1; -} - -message IPCClosePipeMessage{} \ No newline at end of file diff --git a/StarMap.Types/StarMap.Types.csproj b/StarMap.Types/StarMap.Types.csproj index 2105e2d..00ec6e1 100644 --- a/StarMap.Types/StarMap.Types.csproj +++ b/StarMap.Types/StarMap.Types.csproj @@ -3,18 +3,6 @@ net10.0 enable enable + Debug;Release;SourceNuget - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - diff --git a/StarMap.slnx b/StarMap.slnx index 17e57e4..9e59a21 100644 --- a/StarMap.slnx +++ b/StarMap.slnx @@ -1,13 +1,15 @@ + + + + - - \ No newline at end of file diff --git a/StarMap.Loader/GameAssemblyLoadContext.cs b/StarMap/CoreAssemblyLoadContext.cs similarity index 65% rename from StarMap.Loader/GameAssemblyLoadContext.cs rename to StarMap/CoreAssemblyLoadContext.cs index 3f62f47..06d5452 100644 --- a/StarMap.Loader/GameAssemblyLoadContext.cs +++ b/StarMap/CoreAssemblyLoadContext.cs @@ -1,24 +1,19 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; +using System.Reflection; using System.Runtime.Loader; -using System.Text; -using System.Threading.Tasks; namespace StarMap { - internal class GameAssemblyLoadContext : AssemblyLoadContext + internal class CoreAssemblyLoadContext : AssemblyLoadContext { private readonly AssemblyDependencyResolver _gameDependencyResolver; - private readonly AssemblyDependencyResolver _starMapDepdencyResolver; + private readonly AssemblyDependencyResolver _starMapDependencyResolver; - public GameAssemblyLoadContext(string gamePath) + public CoreAssemblyLoadContext(string gamePath) : base() { _gameDependencyResolver = new AssemblyDependencyResolver(gamePath); - _starMapDepdencyResolver = new AssemblyDependencyResolver( + _starMapDependencyResolver = new AssemblyDependencyResolver( Path.GetFullPath("./StarMap.Core.dll") ); } @@ -35,7 +30,7 @@ public GameAssemblyLoadContext(string gamePath) if (path is not null) return LoadFromAssemblyPath(path); - path = _starMapDepdencyResolver.ResolveAssemblyToPath(assemblyName); + path = _starMapDependencyResolver.ResolveAssemblyToPath(assemblyName); return path != null ? LoadFromAssemblyPath(path) : null; } diff --git a/StarMap.Loader/GameSurveyer.cs b/StarMap/GameSurveyer.cs similarity index 90% rename from StarMap.Loader/GameSurveyer.cs rename to StarMap/GameSurveyer.cs index 2500aa1..3e224a1 100644 --- a/StarMap.Loader/GameSurveyer.cs +++ b/StarMap/GameSurveyer.cs @@ -1,4 +1,4 @@ -using StarMap.Types.Mods; +using StarMap.Types; using System.Diagnostics; using System.Reflection; using System.Runtime.Loader; @@ -7,7 +7,6 @@ namespace StarMap { internal class GameSurveyer : IDisposable { - private readonly IGameFacade _facade; private readonly AssemblyLoadContext _gameAssemblyContext; private readonly string _gameLocation; private readonly string[] _args; @@ -15,9 +14,9 @@ internal class GameSurveyer : IDisposable private Assembly? _game; private IStarMapCore? _core; - public GameSurveyer(IGameFacade facade, AssemblyLoadContext alc, string location, string[] args) + + public GameSurveyer(AssemblyLoadContext alc, string location, string[] args) { - _facade = facade; _gameAssemblyContext = alc; _gameLocation = location; _args = args; diff --git a/StarMap.Types/LoaderConfig.cs b/StarMap/LoaderConfig.cs similarity index 96% rename from StarMap.Types/LoaderConfig.cs rename to StarMap/LoaderConfig.cs index 4f4309e..8037a09 100644 --- a/StarMap.Types/LoaderConfig.cs +++ b/StarMap/LoaderConfig.cs @@ -4,7 +4,6 @@ namespace StarMap.Types { public class LoaderConfig { - public bool TryLoadConfig() { if (!File.Exists("./StarMapConfig.json")) @@ -21,7 +20,8 @@ public bool TryLoadConfig() if (string.IsNullOrEmpty(config.GameLocation)) { - Console.WriteLine("StarMap - The 'GameLocation' property in StarMapConfig.json is either empty or points to a non-existing file."); + + Console.WriteLine("StarMap - The 'GameLocation' property in StarMapConfig.json is either empty or points to a non-existing file." + Path.GetFullPath("./StarMapConfig.json")); return false; } diff --git a/StarMap/Program.cs b/StarMap/Program.cs new file mode 100644 index 0000000..05f51f7 --- /dev/null +++ b/StarMap/Program.cs @@ -0,0 +1,31 @@ +using StarMap.Types; +using System.Diagnostics; +using System.Runtime.Loader; + +namespace StarMap +{ + internal class Program + { + static async Task Main(string[] args) + { + var gameConfig = new LoaderConfig(); + + if (!gameConfig.TryLoadConfig()) + { + return; + } + + AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.GetFullPath("./0Harmony.dll")); + + var gameAssemblyContext = new CoreAssemblyLoadContext(gameConfig.GameLocation); + using var gameSurveyer = new GameSurveyer(gameAssemblyContext, gameConfig.GameLocation, args); + if (!gameSurveyer.TryLoadCoreAndGame()) + { + Console.WriteLine("StarMap - Unable to load mod manager and game."); + return; + } + + gameSurveyer.RunGame(); + } + } +} diff --git a/StarMap/StarMap.csproj b/StarMap/StarMap.csproj new file mode 100644 index 0000000..7e38f7b --- /dev/null +++ b/StarMap/StarMap.csproj @@ -0,0 +1,18 @@ + + + Exe + net10.0 + enable + enable + Debug;Release;SourceNuget + + + + + + + + + + +