diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml
index a21af02..0241080 100644
--- a/.github/workflows/pr-build.yml
+++ b/.github/workflows/pr-build.yml
@@ -9,6 +9,7 @@ on:
permissions:
pull-requests: write
contents: read
+ packages: read
jobs:
preview:
@@ -16,6 +17,7 @@ jobs:
env:
DOTNET_VERSION: 9.0
PROJECT: StarMapLoader/StarMapLoader.csproj
+ NUGET_SOURCE: "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json"
steps:
- uses: actions/checkout@v4
@@ -27,7 +29,9 @@ jobs:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Restore dependencies
- run: dotnet restore ${{ env.PROJECT }}
+ run: |
+ dotnet nuget add source --username "${{ github.actor }}" --password "${{ secrets.GITHUB_TOKEN }}" --store-password-in-clear-text --name github "${{ env.NUGET_SOURCE }}"
+ dotnet restore ${{ env.PROJECT }}
# - name: Run tests
# run: dotnet test --no-build --verbosity normal
diff --git a/.github/workflows/release-zip.yml b/.github/workflows/release-zip.yml
index b87734a..1255197 100644
--- a/.github/workflows/release-zip.yml
+++ b/.github/workflows/release-zip.yml
@@ -17,7 +17,7 @@ jobs:
PROJECT: StarMapLoader/StarMapLoader.csproj
OUTPUT_PATH: ./publish
NUGET_SOURCE: "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json"
- EXCLUDE: "*.pdb *.xml DummyProgram.deps.json DummyProgram.runtimeconfig.json DummyProgram.pdb DummyProgram.exe Tomlyn.dll"
+ EXCLUDE: "*.pdb *.xml"
steps:
- uses: actions/checkout@v4
@@ -73,6 +73,14 @@ jobs:
git tag "$NEW_VERSION"
git push origin "$NEW_VERSION"
+ - name: Setup Github NuGet
+ run: |
+ dotnet nuget add source \
+ --username ${{ github.actor }} \
+ --password ${{ secrets.GITHUB_TOKEN }} \
+ --store-password-in-clear-text \
+ --name github "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json"
+
- name: Build
run: dotnet publish ${{ env.PROJECT }} -c Release -o ${{ env.OUTPUT_PATH }}
diff --git a/DummyProgram/DummyProgram.csproj b/DummyProgram/DummyProgram.csproj
index 109581c..d2b3efd 100644
--- a/DummyProgram/DummyProgram.csproj
+++ b/DummyProgram/DummyProgram.csproj
@@ -5,6 +5,7 @@
net9.0
enable
enable
+ KSA
diff --git a/DummyProgram/Mod.cs b/DummyProgram/Mod.cs
index 2c8b746..1723feb 100644
--- a/DummyProgram/Mod.cs
+++ b/DummyProgram/Mod.cs
@@ -1,21 +1,21 @@
-using DummyProgram.Screens;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
+using System.Reflection;
-namespace DummyProgram
+namespace KSA
{
public class Mod
{
public required string DirectoryPath { get; init; }
public required AssemblyName Assembly { get; init; }
+ public required string Name { get; init; }
public Mod() { }
public void PrepareSystems()
{
}
+
+ public void DoSomething()
+ {
+ Console.WriteLine($"Mod {Name} is doing something!");
+ }
}
}
diff --git a/DummyProgram/ModLibrary.cs b/DummyProgram/ModLibrary.cs
index 567e79a..1b8d6d8 100644
--- a/DummyProgram/ModLibrary.cs
+++ b/DummyProgram/ModLibrary.cs
@@ -7,11 +7,11 @@
using Tomlyn.Model;
using Tomlyn;
-namespace DummyProgram
+namespace KSA
{
public class ModLibrary
{
- private List _mods = [];
+ public List Mods = [];
public ModLibrary() { }
public void LoadAll()
@@ -60,11 +60,12 @@ public void FetchMods()
var mod = new Mod
{
DirectoryPath = folder,
- Assembly = assemblyName
+ Assembly = assemblyName,
+ Name = assemblyName.Name
};
mod.PrepareSystems();
- _mods.Add(mod);
+ Mods.Add(mod);
}
}
diff --git a/DummyProgram/Program.cs b/DummyProgram/Program.cs
index 7a0692b..2c72879 100644
--- a/DummyProgram/Program.cs
+++ b/DummyProgram/Program.cs
@@ -1,15 +1,14 @@
-using DummyProgram.Screens;
-
-namespace DummyProgram
+namespace KSA
{
public class Program
{
+ public static ModLibrary ModLibrary = new ModLibrary();
+
private static IScreen _currentScreen = new MainScreen();
static void Main(string[] args)
{
- var library = new ModLibrary();
- library.LoadAll();
+ ModLibrary.LoadAll();
while (true)
{
diff --git a/DummyProgram/Screens/IScreen.cs b/DummyProgram/Screens/IScreen.cs
index b64fd77..16e0c5e 100644
--- a/DummyProgram/Screens/IScreen.cs
+++ b/DummyProgram/Screens/IScreen.cs
@@ -4,7 +4,7 @@
using System.Text;
using System.Threading.Tasks;
-namespace DummyProgram.Screens
+namespace KSA
{
public interface IScreen
{
diff --git a/DummyProgram/Screens/Screens.cs b/DummyProgram/Screens/Screens.cs
index 73db6d5..6d44e1c 100644
--- a/DummyProgram/Screens/Screens.cs
+++ b/DummyProgram/Screens/Screens.cs
@@ -4,11 +4,10 @@
using System.Text;
using System.Threading.Tasks;
-namespace DummyProgram.Screens
+namespace KSA
{
public class MainScreen : IScreen
{
-
public static IScreen[] Screens { get; set; } = [new GameScreen(), new ExitScreen()];
public string ScreenName => "Main";
@@ -59,6 +58,7 @@ public IScreen HandleInput(int input)
public void DoSomething()
{
+ Program.ModLibrary.Mods.ForEach((mod) => mod.DoSomething());
Console.WriteLine("GameScreen.DoSomething");
Console.ReadLine();
}
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..95d86e9
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 StarMap
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index 8c3b624..06a2880 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,29 @@
# StarMap
-A POC/test modloader primarly for Kitten Space Agency
-This was inspired by https://github.com/cheese3660/KsaLoader for me to learn about assemblyloading.
-It very heavily relies on AssemblyLoadContexts to load both the game and then the mods in the game.
-The advantage of this is that different mods can use different versions of the same dependencies.
-
-The main goal was to be able to unload the whole game and the modding, change the mods/dlls around and then load it again.
-This could result in a simular system to how Factory feels where the mod manager lives within the game.
-Sadly it did not work out in the current way it is implemented because Harmony does not play well ALC's and it keeps references to objects within the Assemblies.
-This results in the assemblies not unloading which means I can not swap the dll's (it locks them).
-A probable way forward is using a seperate process for the game itself so the whole process can shut down, however communication between processes forms a barrier to doing it this way.
+
+A POC/Prototype arbitrary code modloader for Kitten Space Agency.
+The idea is to get to a Factorio like experience where mods can be managed in game and mods can be synced by restarting the game.
+Currently this loader can be ran with this functionality in the background, or as a dumb loader just loading mods.
+It makes use of Assembly Load Contexts to ensure mod dependencies are managed seperatly, reducing conflicts
+
+## Installation
+
+- Download and unzip release from [Releases](https://github.com/StarMapLoader/StarMap/releases/latest).
+- Run StarMapLoader.exe, this will fail and create a StarMapLoader.json.
+- Open StarMapLoader.json and set the location of your KSA installation.
+- Run StarMapLoader.exe again, this should launch KSA and load your mods.
+
+## Running as dumb loader
+
+If you do not want the seperate process and mod manager functionality, StarMap.exe can also be ran seperatly, this will just load the installed mods
+
+## Mod location
+
+Mods should be installed in the mods folder in the KSA installation, any KSA mod that has a dll with the same name as the mod that impelements the IStarMapMod interface will be loaded.
+
+## Mod creation
+
+For more information on mod creation, check out the example mods: [StarMap-ExampleMods](https://github.com/StarMapLoader/StarMap-ExampleMods).
+
+## Credits
+
+- Lexi - [KSALoader](https://github.com/cheese3660/KsaLoader)
diff --git a/StarMap.Core/ModAssemblyLoadContext.cs b/StarMap.Core/ModAssemblyLoadContext.cs
index 16ee0f7..9217a8b 100644
--- a/StarMap.Core/ModAssemblyLoadContext.cs
+++ b/StarMap.Core/ModAssemblyLoadContext.cs
@@ -1,11 +1,6 @@
-using DummyProgram;
-using System;
-using System.Collections.Generic;
-using System.Linq;
+using KSA;
using System.Reflection;
using System.Runtime.Loader;
-using System.Text;
-using System.Threading.Tasks;
namespace StarMap.Core
{
@@ -20,29 +15,27 @@ public ModAssemblyLoadContext(Mod mod, AssemblyLoadContext coreAssemblyContext)
_coreAssemblyLoadContext = coreAssemblyContext;
_modDependencyResolver = new AssemblyDependencyResolver(
- Path.GetFullPath(Path.Combine(mod.DirectoryPath, mod.Assembly.Name + ".dll"))
+ Path.GetFullPath(Path.Combine(mod.DirectoryPath, mod.Name + ".dll"))
);
}
protected override Assembly? Load(AssemblyName assemblyName)
{
var existingInDefault = Default.Assemblies
- .FirstOrDefault(a => a.FullName == assemblyName.FullName);
+ .FirstOrDefault(a => string.Equals(a.GetName().Name, assemblyName.Name, StringComparison.OrdinalIgnoreCase));
if (existingInDefault != null)
return existingInDefault;
var existingInGameContext = _coreAssemblyLoadContext?.Assemblies
- .FirstOrDefault(a => a.FullName == assemblyName.FullName);
+ .FirstOrDefault(a => string.Equals(a.GetName().Name, assemblyName.Name, StringComparison.OrdinalIgnoreCase));
if (existingInGameContext != null)
return existingInGameContext;
var foundPath = _modDependencyResolver.ResolveAssemblyToPath(assemblyName);
-
if (foundPath is null)
return null;
var path = Path.GetFullPath(foundPath);
-
return path != null ? LoadFromAssemblyPath(path) : null;
}
}
diff --git a/StarMap.Core/ModLoaderPatcher.cs b/StarMap.Core/ModLoaderPatcher.cs
index ffc1425..ed20131 100644
--- a/StarMap.Core/ModLoaderPatcher.cs
+++ b/StarMap.Core/ModLoaderPatcher.cs
@@ -1,5 +1,4 @@
-using DummyProgram;
-using DummyProgram.Screens;
+using KSA;
using HarmonyLib;
namespace StarMap.Core
@@ -19,7 +18,7 @@ public static void Patch(ModManager modManager)
public static void Unload()
{
_modManager = null;
- MainScreen.Screens = [];
+ //MainScreen.Screens = [];
_harmony?.UnpatchAll();
}
@@ -35,10 +34,10 @@ public static void OnLoadMod(this Mod __instance)
public static void AfterLoad()
{
_modManager?.OnAllModsLoaded();
- var screens = MainScreen.Screens.ToList();
+ /*var screens = MainScreen.Screens.ToList();
screens.Insert(MainScreen.Screens.Length - 1, new ModManagerScreen(_modManager));
- MainScreen.Screens = screens.ToArray();
+ MainScreen.Screens = screens.ToArray();*/
_harmony?.UnpatchAll(_harmony.Id);
}
}
diff --git a/StarMap.Core/ModManager.cs b/StarMap.Core/ModManager.cs
index 77d4f57..cddeb65 100644
--- a/StarMap.Core/ModManager.cs
+++ b/StarMap.Core/ModManager.cs
@@ -1,7 +1,5 @@
-
-using DummyProgram;
-using Google.Protobuf.WellKnownTypes;
+using KSA;
using HarmonyLib;
using StarMap.Types;
using StarMap.Types.Mods;
@@ -16,7 +14,7 @@ internal class ModManager : IModManager
private readonly AssemblyLoadContext _coreAssemblyLoadContext;
private readonly IGameFacade _gameFacade;
- private readonly TaskCompletionSource _managedMods = new();
+ private readonly TaskCompletionSource _managedMods = new();
private readonly Dictionary _loadedMods = [];
public ModManager(AssemblyLoadContext coreAssemblyLoadContext, IGameFacade gameFacade)
@@ -28,6 +26,7 @@ public ModManager(AssemblyLoadContext coreAssemblyLoadContext, IGameFacade gameF
public void Init()
{
_ = RetrieveManagedMods();
+
ModLoaderPatcher.Patch(this);
}
@@ -47,7 +46,7 @@ public void LoadMod(Mod mod)
if (!Directory.Exists(mod.DirectoryPath)) return;
var modLoadContext = new ModAssemblyLoadContext(mod, _coreAssemblyLoadContext);
- var modAssembly = modLoadContext.LoadFromAssemblyName(mod.Assembly);
+ var modAssembly = modLoadContext.LoadFromAssemblyName(new AssemblyName() { Name = mod.Name });
var loadedMod = modAssembly.GetTypes().FirstOrDefault((type) => typeof(IStarMapMod).IsAssignableFrom(type) && !type.IsInterface).CreateInstance();
if (loadedMod is not IStarMapMod starMapMod) return;
@@ -60,6 +59,8 @@ public void LoadMod(Mod mod)
return;
}
+ Console.WriteLine($"Loaded mod: {mod.Name}");
+
_loadedMods[mod] = (starMapMod, modLoadContext);
return;
}
@@ -74,54 +75,53 @@ public void OnAllModsLoaded()
public async Task RetrieveManagedMods()
{
- var message = new ManagedModsRequest();
+ var message = new IPCGetCurrentManagedModsRequest();
var response = await _gameFacade.RequestData(message);
- if (!response.Is(ManagedModsResponse.Descriptor)) return;
+ if (!response.Is(IPCGetCurrentManagedModsResponse.Descriptor)) return;
- _managedMods.SetResult(response.Unpack());
+ _managedMods.SetResult(response.Unpack());
}
- public ManagedModsResponse GetManagedMods()
+ public IPCGetCurrentManagedModsResponse GetManagedMods()
{
- Console.WriteLine("GetManagedMods");
return _managedMods.Task.GetAwaiter().GetResult();
}
- public async Task GetManagedModsAsync()
+ public async Task GetAvailableModsAsync()
{
- var message = new AvailableModsRequest();
+ var message = new IPCGetModsRequest();
var response = await _gameFacade.RequestData(message);
- if (!response.Is(AvailableModsResponse.Descriptor)) return[];
+ if (!response.Is(IPCGetModsResponse.Descriptor)) return[];
- return [.. response.Unpack().Mods];
+ return [.. response.Unpack().Mods];
}
- public async Task GetModInformationAsync(string modName)
+ public async Task GetModInformationAsync(string id)
{
- var message = new ModInformationRequest()
+ var message = new IPCGetModDetailsRequest()
{
- Mod = modName
+ Id = id
};
var response = await _gameFacade.RequestData(message);
- if (!response.Is(ModInformationResponse.Descriptor)) return null;
+ if (!response.Is(IPCGetModDetailsResponse.Descriptor)) return null;
- return response.Unpack().Mod;
+ return response.Unpack().Mod;
}
- public AssemblyName[] GetLoadedMods()
+ public string[] GetLoadedMods()
{
if (_loadedMods is null) return [];
- return _loadedMods.Select(loadedMod => loadedMod.Key.Assembly).ToArray();
+ return _loadedMods.Select(loadedMod => loadedMod.Key.Name).ToArray();
}
- public async Task SetModUpdates(SetModUpdates update)
+ public async Task SetModUpdates(IPCSetManagedMods update)
{
await _gameFacade.RequestData(update);
}
diff --git a/StarMap.Core/ModManagerScreen.cs b/StarMap.Core/ModManagerScreen.cs
index 8105da4..d23490a 100644
--- a/StarMap.Core/ModManagerScreen.cs
+++ b/StarMap.Core/ModManagerScreen.cs
@@ -1,4 +1,4 @@
-using DummyProgram;
+/*using DummyProgram;
using DummyProgram.Screens;
using StarMap.Types.Mods;
using StarMap.Types.Proto.IPC;
@@ -15,12 +15,12 @@ internal sealed class ModManagerScreen : IScreen
{
private readonly ModManager _modManager;
- private List _managedMods = [];
- private List _unmanagedMods = [];
+ private List _managedMods = [];
+ private List _unmanagedMods = [];
- private List<(string modName, Version? before, Version after)> _changes = [];
+ private List _changes = [];
- private (string name, Version? version, bool unmanaged)? _currentMod;
+ private (IPCMod mod, bool unmanaged, bool fromStore)? _currentMod;
enum ManagerState
{
@@ -45,7 +45,8 @@ public ModManagerScreen(ModManager? modManager)
private void RetrieveModInfo()
{
_managedMods = [.. _modManager.GetManagedMods().Mods];
- _unmanagedMods = _modManager.GetLoadedMods().Where(loadedMod => !_managedMods.Any(managedMod => managedMod.Name == loadedMod.Name)).ToList();
+ _unmanagedMods = _modManager.GetLoadedMods().Where(loadedMod => !_managedMods.Any(managedMod => managedMod.Name == loadedMod.Name)).Select((loadedMod) => new IPCMod() { Name = loadedMod.Name}).ToList();
+
}
public string ScreenName => "Mod manager";
@@ -71,6 +72,11 @@ public void Render()
RenderModInfo();
break;
}
+ case ManagerState.MOD_STORE:
+ {
+ RenderModStore();
+ break;
+ }
}
}
@@ -96,10 +102,10 @@ private ModManagerScreen GoToStore()
return this;
}
- private ModManagerScreen GoToSpecificMod(string modName, Version? modVersion, bool unmanaged)
+ private ModManagerScreen GoToSpecificMod(IPCMod mod, bool unmanaged, bool fromStore)
{
_managerState = ManagerState.MOD_INFO;
- _currentMod = (modName, modVersion, unmanaged);
+ _currentMod = (mod, unmanaged, fromStore);
return this;
}
@@ -115,7 +121,7 @@ private void RenderMain()
{
var localMod = mod;
Console.WriteLine($"{index++}: {localMod.Name}:{localMod.Version}");
- _actions.Add(() => GoToSpecificMod(localMod.Name, Version.Parse(localMod.Version), false));
+ _actions.Add(() => GoToSpecificMod(localMod, false, false));
}
Console.WriteLine("Unmanaged mods: ");
@@ -123,7 +129,7 @@ private void RenderMain()
{
var localMod = mod;
Console.WriteLine($"{index++}: {localMod.Name}:{localMod.Version}");
- _actions.Add(() => GoToSpecificMod(localMod.Name ?? "", localMod.Version, true));
+ _actions.Add(() => GoToSpecificMod(mod, true, false));
}
Console.WriteLine($"");
@@ -131,12 +137,12 @@ private void RenderMain()
if (_changes.Count > 0)
{
Console.WriteLine($"Current changes");
- foreach (var (name, before, after) in _changes)
+ foreach (var modUpdate in _changes)
{
- if (before is not null)
- Console.WriteLine($"{name}: {before} => {after}");
+ if (modUpdate.BeforeVersion is IPCModVersion beforeVersion && !string.IsNullOrEmpty(beforeVersion.Version))
+ Console.WriteLine($"{modUpdate.Mod.Name}: {beforeVersion.Version} => {modUpdate.AfterVersion.Version}");
else
- Console.WriteLine($"{name}: {after}");
+ Console.WriteLine($"{modUpdate.Mod.Name}: {modUpdate.AfterVersion.Version}");
}
Console.WriteLine($"");
@@ -162,81 +168,102 @@ private void RenderMain()
private void RenderModInfo()
{
if (_currentMod is null) return;
- var modInformation = _modManager.GetModInformationAsync(_currentMod.Value.name).GetAwaiter().GetResult();
+ var modInformation = _modManager.GetModInformationAsync(_currentMod.Value.mod.Id).GetAwaiter().GetResult();
if (modInformation is null)
{
- Console.WriteLine($"Unable to retrieve information for mod: {_currentMod.Value.name}");
+ Console.WriteLine($"Unable to retrieve information for mod: {_currentMod.Value.mod.Name}");
Console.WriteLine($"Return");
_actions.Add(GoToModManager);
return;
}
- var modName = _currentMod.Value.name;
- var version = _currentMod.Value.version;
+ var mod = _currentMod.Value.mod;
var unmanaged = _currentMod.Value.unmanaged;
- Console.WriteLine($"Alter version for mod: {modName}");
+ Console.WriteLine($"Alter version for mod: {mod.Name}");
if (unmanaged)
Console.WriteLine($"Will remove the unmanaged mod and make it managed");
var index = 0;
- foreach (var possibleVersion in modInformation.AvailableVersions)
+ foreach (var possibleVersion in modInformation.Versions)
{
- if (!unmanaged && possibleVersion.Equals(version))
+ if (!unmanaged && possibleVersion.Equals(mod.Version))
{
- Console.WriteLine($"* {version}");
+ Console.WriteLine($"* {mod.Version}");
continue;
}
- var localName = modName;
- var localVersion = possibleVersion;
+ var localMod = mod;
+ var localversion = possibleVersion;
var localUnmanaged = unmanaged;
- Console.WriteLine($"{index++}: {possibleVersion}");
- _actions.Add(() => SetModVersion(localName, Version.Parse(localVersion), localUnmanaged));
+ Console.WriteLine($"{index++}: {possibleVersion.Version}");
+ _actions.Add(() => SetModVersion(localMod, localversion, localUnmanaged));
}
Console.WriteLine($"{index}: Return");
_actions.Add(GoToModManager);
}
- private ModManagerScreen SetModVersion(string modName, Version modVersion, bool unmanaged)
+ private void RenderModStore()
+ {
+ var availableMods = _modManager.GetAvailableModsAsync().GetAwaiter().GetResult();
+
+ var index = 0;
+
+ foreach (var availableMod in availableMods)
+ {
+ var localMod = availableMod;
+
+ Console.WriteLine($"{index++}: {availableMod.Name} by {availableMod.Author}");
+ _actions.Add(() => GoToSpecificMod(localMod, false, true));
+ }
+
+ Console.WriteLine($"{index}: Return");
+ _actions.Add(GoToModManager);
+ }
+
+ private ModManagerScreen SetModVersion(IPCMod mod, IPCModVersion version, bool unmanaged)
{
_managerState = ManagerState.MAIN;
- Version? previousVersion = null;
+ IPCModVersion? previousVersion = null;
if (unmanaged)
{
- var assembly = _unmanagedMods.FirstOrDefault((assembly) => string.Equals(assembly.Name, modName));
- if (assembly is not null)
+ var removedMod = _unmanagedMods.FirstOrDefault((unmanagedMod) => string.Equals(unmanagedMod.Name, mod.Name));
+ if (removedMod is not null)
{
- previousVersion = assembly.Version;
- _unmanagedMods.Remove(assembly);
+ previousVersion = new IPCModVersion() { Version = removedMod.Version };
+ _unmanagedMods.Remove(removedMod);
+ }
+ }
+ else
+ {
+ var oldModIndex = _managedMods.FindIndex(0, (modInfo) => modInfo.Id == mod.Id);
+ if (oldModIndex >= 0)
+ {
+ previousVersion = new IPCModVersion() { Version = _managedMods[oldModIndex].Version };
}
}
- var newModInformation = new ManagedModInformation()
+ var newModInformation = new IPCMod()
{
- Name = modName,
- Version = modVersion.ToString(),
+ Id = mod.Id,
+ Name = mod.Name,
+ Author = mod.Author,
};
- var index = _managedMods.FindIndex(0, (modInfo) => modInfo.Name == modName);
-
- if (index >= 0)
+ var changesIndex = _changes.FindIndex(0, (change) => change.Mod.Id == mod.Id);
+ var change = new IPCUpdateModInformation()
{
- previousVersion = Version.Parse(_managedMods[index].Version);
- _managedMods[index] = newModInformation;
- }
-
- else
- _managedMods.Add(newModInformation);
+ Mod = newModInformation,
+ BeforeVersion = new IPCModVersion() { Version = previousVersion?.ToString() ?? "" },
+ AfterVersion = version,
+ };
- var change = (modName, previousVersion, modVersion);
- var changesIndex = _changes.FindIndex(0, (change) => change.modName == modName);
- if (changesIndex > 0)
+ if (changesIndex >= 0)
_changes[changesIndex] = change;
else
_changes.Add(change);
@@ -246,15 +273,9 @@ private ModManagerScreen SetModVersion(string modName, Version modVersion, bool
private IScreen ApplyMods()
{
- var modUpdates = _changes.Select(change => new ManagedModUpdate()
- {
- Name = change.modName,
- BeforeVersion = change.before?.ToString() ?? "",
- AfterVersion = change.after.ToString(),
- });
- var message = new SetModUpdates();
- message.Updates.AddRange(modUpdates);
+ var message = new IPCSetManagedMods();
+ message.Updates.AddRange(_changes);
_modManager.SetModUpdates(message).GetAwaiter().GetResult();
@@ -262,3 +283,4 @@ private IScreen ApplyMods()
}
}
}
+*/
\ No newline at end of file
diff --git a/StarMap.Core/StarMap.Core.csproj b/StarMap.Core/StarMap.Core.csproj
index 1285696..1488325 100644
--- a/StarMap.Core/StarMap.Core.csproj
+++ b/StarMap.Core/StarMap.Core.csproj
@@ -8,10 +8,12 @@
+
+ runtime
+
-
diff --git a/StarMap.Types/LoaderConfig.cs b/StarMap.Types/LoaderConfig.cs
new file mode 100644
index 0000000..4ed0594
--- /dev/null
+++ b/StarMap.Types/LoaderConfig.cs
@@ -0,0 +1,43 @@
+using StarMap.Types.Proto.IPC;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+
+namespace StarMap.Types
+{
+ public class LoaderConfig
+ {
+
+ public bool TryLoadConfig()
+ {
+ if (!File.Exists("./StarMapConfig.json")) {
+ Console.WriteLine("Please fill the StarMapConfig.json and restart the program");
+ File.Create("./StarMapConfig.json").Dispose();
+ File.WriteAllText("./StarMapConfig.json", JsonSerializer.Serialize(new LoaderConfig()));
+ Console.ReadLine();
+ return false;
+ }
+
+ var jsonString = File.ReadAllText("./StarMapConfig.json");
+ var config = System.Text.Json.JsonSerializer.Deserialize(jsonString);
+
+ if (config is null) return false;
+
+ if (string.IsNullOrEmpty(config.GameLocation) || !File.Exists(config.GameLocation))
+ {
+ Console.WriteLine("The 'GameLocation' property in StarMapConfig.json is either empty or points to a non-existing file.");
+ Console.ReadLine();
+ return false;
+ }
+
+ GameLocation = config.GameLocation;
+ return true;
+ }
+
+ public string GameLocation { get; set; } = "";
+ public string RepositoryLocation { get; set; } = "";
+ }
+}
diff --git a/StarMap.Types/Proto/IPC.proto b/StarMap.Types/Proto/IPC.proto
index 45c8bb5..e29db6f 100644
--- a/StarMap.Types/Proto/IPC.proto
+++ b/StarMap.Types/Proto/IPC.proto
@@ -9,56 +9,65 @@ message PipeMessage {
google.protobuf.Any Payload = 2;
}
-message ConnectRequest{
+message IPCConnectRequest {
}
-message ConnectResponse{
+message IPCConnectResponse {
string game_location = 1;
}
-message ManagedModsRequest{
+message IPCGetCurrentManagedModsRequest {
}
-message ManagedModsResponse{
- repeated ManagedModInformation mods = 1;
+message IPCGetCurrentManagedModsResponse {
+ repeated IPCMod mods = 1;
}
-message ManagedModInformation{
- string name = 1;
- string version = 2;
+message IPCGetModsRequest{
+
}
-message AvailableModsRequest{
+message IPCGetModsResponse{
+ repeated IPCMod mods = 1;
+}
+message IPCGetModDetailsRequest{
+ string id = 1;
}
-message AvailableModsResponse{
- repeated string mods = 1;
+message IPCGetModDetailsResponse{
+ IPCModDetails mod = 1;
}
-message ModInformationRequest{
- string mod = 1;
+message IPCMod {
+ string id = 1;
+ string name = 2;
+ string version = 3;
+ string author = 4;
}
-message ModInformationResponse{
- ModInformation mod = 1;
+message IPCModDetails{
+ IPCMod mod = 1;
+ repeated IPCModVersion versions = 2;
+ string description = 3;
}
-message ModInformation{
- string name = 1;
- repeated string available_versions = 2;
+message IPCModVersion{
+ string id = 1;
+ string version = 2;
+ string download_location = 3;
}
-message ManagedModUpdate{
- string name = 1;
- string before_version = 2;
- string after_version = 3;
+message IPCUpdateModInformation{
+ IPCMod mod = 1;
+ IPCModVersion before_version = 2;
+ IPCModVersion after_version = 3;
}
-message SetModUpdates{
- repeated ManagedModUpdate updates = 1;
+message IPCSetManagedMods{
+ repeated IPCUpdateModInformation updates = 1;
}
-message ClosePipeMessage{}
\ No newline at end of file
+message IPCClosePipeMessage{}
\ No newline at end of file
diff --git a/StarMap.Types/StarMap.Types.csproj b/StarMap.Types/StarMap.Types.csproj
index 9357b8d..290fcc2 100644
--- a/StarMap.Types/StarMap.Types.csproj
+++ b/StarMap.Types/StarMap.Types.csproj
@@ -6,7 +6,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/StarMap/DumbGameFacade.cs b/StarMap/DumbGameFacade.cs
new file mode 100644
index 0000000..229cb58
--- /dev/null
+++ b/StarMap/DumbGameFacade.cs
@@ -0,0 +1,19 @@
+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 DumbGameFacade : IGameFacade
+ {
+ public Task RequestData(IMessage request)
+ {
+ return Task.FromResult(new Any());
+ }
+ }
+}
diff --git a/StarMap/GameAssemblyLoadContext.cs b/StarMap/GameAssemblyLoadContext.cs
index 9b7bb34..1786894 100644
--- a/StarMap/GameAssemblyLoadContext.cs
+++ b/StarMap/GameAssemblyLoadContext.cs
@@ -25,10 +25,10 @@ public GameAssemblyLoadContext(string gamePath)
protected override Assembly? Load(AssemblyName assemblyName)
{
- var existing = Default.Assemblies
- .FirstOrDefault(a => a.FullName == assemblyName.FullName);
- if (existing != null)
- return existing;
+ var existingInDefault = Default.Assemblies
+ .FirstOrDefault(a => string.Equals(a.GetName().Name, assemblyName.Name, StringComparison.OrdinalIgnoreCase));
+ if (existingInDefault != null)
+ return existingInDefault;
var path = _gameDependencyResolver.ResolveAssemblyToPath(assemblyName);
diff --git a/StarMap/GameFacade.cs b/StarMap/GameFacade.cs
index b2298fc..5953d92 100644
--- a/StarMap/GameFacade.cs
+++ b/StarMap/GameFacade.cs
@@ -22,16 +22,16 @@ public async Task Connect()
await _pipe.ConnectAsync(default);
_connected = true;
- var connectResponse = await RequestData(new ConnectRequest());
+ var connectResponse = await RequestData(new IPCConnectRequest());
- if (!connectResponse.Is(ConnectResponse.Descriptor)) return "";
+ if (!connectResponse.Is(IPCConnectResponse.Descriptor)) return "";
- return connectResponse.Unpack().GameLocation;
+ return connectResponse.Unpack().GameLocation;
}
public async ValueTask DisposeAsync()
{
- await RequestData(new ClosePipeMessage());
+ //await RequestData(new IPCClosePipeMessage());
_pipe.Dispose();
}
diff --git a/StarMap/GameSurveyer.cs b/StarMap/GameSurveyer.cs
index 6d92023..2e94dd8 100644
--- a/StarMap/GameSurveyer.cs
+++ b/StarMap/GameSurveyer.cs
@@ -8,14 +8,14 @@ namespace StarMap
{
internal class GameSurveyer : IDisposable
{
- private readonly GameFacade _facade;
+ private readonly IGameFacade _facade;
private readonly AssemblyLoadContext _gameAssemblyContext;
private readonly string _gameLocation;
private Assembly? _game;
private IModManager? _modManager;
- public GameSurveyer(GameFacade facade, AssemblyLoadContext alc, string location)
+ public GameSurveyer(IGameFacade facade, AssemblyLoadContext alc, string location)
{
_facade = facade;
_gameAssemblyContext = alc;
@@ -33,7 +33,7 @@ public bool TryLoadModManagerAndGame([NotNullWhen(true)] out IModManager? modMan
var createdModManager = Activator.CreateInstance(modManagerType, [_gameAssemblyContext, _facade]);
if (createdModManager is not IModManager manager) return false;
- _game = _gameAssemblyContext.LoadFromAssemblyPath(Path.Combine(_gameLocation, "DummyProgram.dll"));
+ _game = _gameAssemblyContext.LoadFromAssemblyPath(_gameLocation);
_modManager = manager;
manager.Init();
diff --git a/StarMap/Program.cs b/StarMap/Program.cs
index 5c6ff71..088b933 100644
--- a/StarMap/Program.cs
+++ b/StarMap/Program.cs
@@ -1,4 +1,6 @@
-using StarMap.Types.Pipes;
+using StarMap.Types;
+using StarMap.Types.Pipes;
+using StarMap.Types.Proto.IPC;
using System.Runtime.Loader;
namespace StarMap
@@ -9,15 +11,42 @@ static void Main(string[] args)
{
if (args.Length < 1)
{
- Console.WriteLine("Usage: StarMap ");
+ Console.WriteLine("Running Starmap in dumb mode!");
+ DumbModeInner();
return;
}
+ Console.WriteLine("Running Starmap normally.");
+
var pipeName = args[0];
+ Console.WriteLine($"Connection to pipe: {pipeName}");
MainInner(pipeName).GetAwaiter().GetResult();
}
+ static void DumbModeInner()
+ {
+ var gameConfig = new LoaderConfig();
+
+ if (!gameConfig.TryLoadConfig())
+ {
+ return;
+ }
+
+ AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.GetFullPath("./0Harmony.dll"));
+
+ var gameAssemblyContext = new GameAssemblyLoadContext(gameConfig.GameLocation);
+ var dumbFacade = new DumbGameFacade();
+ var gameSurveyer = new GameSurveyer(dumbFacade, gameAssemblyContext, gameConfig.GameLocation);
+ if (!gameSurveyer.TryLoadModManagerAndGame(out _))
+ {
+ Console.WriteLine("Unable to load mod manager and game in dumb mode.");
+ return;
+ }
+
+ gameSurveyer.RunGame();
+ }
+
static async Task MainInner(string pipeName)
{
AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.GetFullPath("./0Harmony.dll"));
diff --git a/StarMap/Properties/launchSettings.json b/StarMap/Properties/launchSettings.json
index 8a543f9..19a1027 100644
--- a/StarMap/Properties/launchSettings.json
+++ b/StarMap/Properties/launchSettings.json
@@ -1,8 +1,7 @@
{
"profiles": {
"StarMap": {
- "commandName": "Project",
- "commandLineArgs": "starmap_pipe"
+ "commandName": "Project"
}
}
}
\ No newline at end of file
diff --git a/StarMap/StarMap.csproj b/StarMap/StarMap.csproj
index 70dbfb6..fb71fb5 100644
--- a/StarMap/StarMap.csproj
+++ b/StarMap/StarMap.csproj
@@ -12,7 +12,6 @@
-
diff --git a/StarMapLoader/LoaderConfig.cs b/StarMapLoader/LoaderConfig.cs
deleted file mode 100644
index 5c246f2..0000000
--- a/StarMapLoader/LoaderConfig.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace StarMapLoader
-{
- internal class LoaderConfig
- {
- public string GameFolder { get; set; } = "C:\\data\\programming\\game-modding\\KSA\\StarMap\\StarMapLoader\\bin\\Debug\\net9.0";
- public string GamePath => Path.Combine(GameFolder, "StarMap.exe");
- public string ModPath => Path.Combine(GameFolder, "mods");
- }
-}
diff --git a/StarMapLoader/LoaderFacade.cs b/StarMapLoader/LoaderFacade.cs
index fdc5e27..2f9838d 100644
--- a/StarMapLoader/LoaderFacade.cs
+++ b/StarMapLoader/LoaderFacade.cs
@@ -1,5 +1,6 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
+using StarMap.Types;
using StarMap.Types.Pipes;
using StarMap.Types.Proto.IPC;
@@ -31,43 +32,74 @@ private void PipeServer_OnRequest(object? sender, Any pipeMessage)
IMessage? response = null;
- if (message.Is(ConnectRequest.Descriptor))
+ if (message.Is(IPCConnectRequest.Descriptor))
{
- response = new ConnectResponse()
+ response = new IPCConnectResponse()
{
- GameLocation = _config.GameFolder,
+ GameLocation = _config.GameLocation,
};
OnProcessStarted?.Invoke(this, EventArgs.Empty);
}
- if (message.Is(ManagedModsRequest.Descriptor))
+ if (message.Is(IPCGetCurrentManagedModsRequest.Descriptor))
{
- var modsRepsonse = new ManagedModsResponse();
+ var modsRepsonse = new IPCGetCurrentManagedModsResponse();
modsRepsonse.Mods.AddRange(_repository.LoadedModInformation);
response = modsRepsonse;
}
- if (message.Is(AvailableModsRequest.Descriptor))
+ if (message.Is(IPCGetModsRequest.Descriptor))
{
- var availableModsResponse = new AvailableModsResponse();
- availableModsResponse.Mods.AddRange(_repository.GetPossibleMods());
+ 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(ModInformationRequest.Descriptor))
+ if (message.Is(IPCGetModDetailsRequest.Descriptor))
{
- var modInformationRequest = message.Unpack();
+ var modDetailsRequest = message.Unpack();
- var modInformationResponse = new ModInformationResponse()
+ var modDetails = _repository.GetModInformation(modDetailsRequest.Id).GetAwaiter().GetResult();
+ if (modDetails is null)
{
- Mod = _repository.GetModInformation(modInformationRequest.Mod)
- };
- response = modInformationResponse;
+ 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(SetModUpdates.Descriptor))
+ if (message.Is(IPCSetManagedMods.Descriptor))
{
- var setModUpdates = message.Unpack();
+ var setModUpdates = message.Unpack();
_repository.SetModUpdates([.. setModUpdates.Updates]);
diff --git a/StarMapLoader/ModDownloader.cs b/StarMapLoader/ModDownloader.cs
index 56cf46e..160b3b2 100644
--- a/StarMapLoader/ModDownloader.cs
+++ b/StarMapLoader/ModDownloader.cs
@@ -10,44 +10,13 @@ namespace StarMapLoader
{
internal class ModDownloader
{
- private const string ModLocation = "C:\\data\\programming\\game-modding\\KSA\\Mods";
-
- public bool DownloadMod(string modName, string modVersion, string location)
+ public bool DownloadMod(IPCMod mod, IPCModVersion version, string location)
{
try
{
- var sourceFile = Path.Combine(ModLocation, $"{modName}-{modVersion}.zip");
- var destinationFile = Path.Combine(location, $"{modName}-{modVersion}.zip");
-
- if (!File.Exists(sourceFile)) return false;
-
- File.Copy(sourceFile, destinationFile, true);
-
- ZipFile.ExtractToDirectory(destinationFile, location);
- File.Delete(destinationFile);
-
return true;
}
catch { return false; }
}
-
- public Dictionary GetModsFromStore()
- {
- var mods = new Dictionary();
-
- mods["TestMod1"] = new ModInformation()
- {
- Name = "TestMod1"
- };
- mods["TestMod1"].AvailableVersions.AddRange(["1.0.0.0", "2.0.0.0", "3.0.0.0"]);
-
- mods["TestMod2"] = new ModInformation()
- {
- Name = "TestMod2"
- };
- mods["TestMod2"].AvailableVersions.AddRange(["1.0.0.0", "2.0.0.0", "3.0.0.0"]);
-
- return mods;
- }
}
}
diff --git a/StarMapLoader/ModRepository.cs b/StarMapLoader/ModRepository.cs
index 5a1bd7b..b118b00 100644
--- a/StarMapLoader/ModRepository.cs
+++ b/StarMapLoader/ModRepository.cs
@@ -1,59 +1,61 @@
-using System.Text.Json;
+using System.Collections;
+using System.Text.Json;
+using StarMap.Index.API;
using StarMap.Types.Proto.IPC;
namespace StarMapLoader
{
internal class ModRepository
{
- public List LoadedModInformation { get; private set; } = [];
+ 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 ManagedModUpdate[] _changes = [];
+ private IPCUpdateModInformation[] _changes = [];
- public ModRepository(string modsPath)
+ public ModRepository(string gameLocation, IModRespositoryClient foreignModRepository)
{
- _modsPath = modsPath;
+ var gameDirectory = Path.GetDirectoryName(gameLocation);
+ if (string.IsNullOrEmpty(gameDirectory))
+ {
+ throw new ArgumentException("Invalid game location provided, unable to determine game directory.");
+ }
- if (!Directory.Exists(modsPath))
+ _modsPath = Path.Combine(gameDirectory, "mods");
+ _foreignModRepository = foreignModRepository;
+
+ if (!Directory.Exists(_modsPath))
{
- Directory.CreateDirectory(modsPath);
+ Directory.CreateDirectory(_modsPath);
}
- var filePath = Path.Combine(modsPath, "starmap.json");
+ var filePath = Path.Combine(_modsPath, "starmap.json");
if (!File.Exists(filePath))
{
File.Create(filePath).Dispose();
- File.WriteAllText(filePath, JsonSerializer.Serialize(new List
- {
- new ManagedModInformation()
- {
- Name = "TestMod1",
- Version = "2.0.0.0"
- }
- }));
+ File.WriteAllText(filePath, JsonSerializer.Serialize(new List()));
}
- string jsonString = File.ReadAllText(Path.Combine(modsPath, "starmap.json"));
+ string jsonString = File.ReadAllText(Path.Combine(_modsPath, "starmap.json"));
- LoadedModInformation = JsonSerializer.Deserialize>(jsonString) ?? [];
+ LoadedModInformation = JsonSerializer.Deserialize>(jsonString) ?? [];
}
- public string[] GetPossibleMods()
+ public async Task GetPossibleMods()
{
- return [.. _downloader.GetModsFromStore().Keys];
+ return await _foreignModRepository.GetMods();
}
- public ModInformation GetModInformation(string modName)
+ public async Task GetModInformation(string modId)
{
-
- return _downloader.GetModsFromStore()[modName];
+ return await _foreignModRepository.GetModDetails(Guid.Parse(modId));
}
- public void SetModUpdates(ManagedModUpdate[] updates)
+ public void SetModUpdates(IPCUpdateModInformation[] updates)
{
_changes = updates;
HasChanges = true;
@@ -63,11 +65,11 @@ public void ApplyModUpdates()
{
HasChanges = false;
- foreach (var mod in _changes)
+ foreach (var modChange in _changes)
{
try
{
- var directoryPath = Path.Combine(_modsPath, mod.Name);
+ var directoryPath = Path.Combine(_modsPath, modChange.Mod.Name);
if (Directory.Exists(directoryPath))
{
@@ -76,21 +78,22 @@ public void ApplyModUpdates()
Directory.CreateDirectory(directoryPath);
- if (!_downloader.DownloadMod(mod.Name, mod.AfterVersion, directoryPath) && !string.IsNullOrEmpty(mod.BeforeVersion))
+ if (!_downloader.DownloadMod(modChange.Mod, modChange.AfterVersion, directoryPath) && modChange.BeforeVersion is not null)
{
Directory.Delete(directoryPath, true);
Directory.CreateDirectory(directoryPath);
- _downloader.DownloadMod(mod.Name, mod.BeforeVersion, directoryPath);
+ _downloader.DownloadMod(modChange.Mod, modChange.BeforeVersion, directoryPath);
}
else
{
- var newModInfo = new ManagedModInformation()
+ var newModInfo = new IPCMod()
{
- Version = mod.AfterVersion,
- Name = mod.Name
+ Id = modChange.Mod.Id,
+ Name = modChange.Mod.Name,
+ Version = modChange.AfterVersion.Version
};
- var index = LoadedModInformation.FindIndex(modInfo => modInfo.Name == mod.Name);
+ var index = LoadedModInformation.FindIndex(modInfo => modInfo.Id == newModInfo.Id);
if (index >= 0)
{
@@ -104,7 +107,7 @@ public void ApplyModUpdates()
}
catch (Exception ex)
{
- Console.WriteLine($"Unable to apply update for mod: {mod.Name} to version {mod.AfterVersion}: {ex}");
+ Console.WriteLine($"Unable to apply update for mod: {modChange.Mod.Name} to version {modChange.AfterVersion?.Version ?? ""}: {ex}");
}
}
diff --git a/StarMapLoader/Program.cs b/StarMapLoader/Program.cs
index e47fbe1..9ebe886 100644
--- a/StarMapLoader/Program.cs
+++ b/StarMapLoader/Program.cs
@@ -1,4 +1,6 @@
-using StarMap.Types.Pipes;
+using StarMap.Index.API;
+using StarMap.Types.Pipes;
+using StarMap.Types;
using System.Diagnostics;
namespace StarMapLoader
@@ -13,7 +15,10 @@ static void Main(string[] args)
static async Task MainInner()
{
var config = new LoaderConfig();
- var modRepository = new ModRepository(config.ModPath);
+ if (!config.TryLoadConfig()) return;
+
+ using var remoteModRepository = new ModRepositoryClient(config.RepositoryLocation);
+ var modRepository = new ModRepository(config.GameLocation, remoteModRepository);
var shouldReload = true;
@@ -25,7 +30,7 @@ static async Task MainInner()
{
CancellationTokenSource stopGameCancelationTokenSource = new();
- var gameSupervisor = new GameProcessSupervisor(config.GamePath, facade, pipeServer);
+ var gameSupervisor = new GameProcessSupervisor(config.GameLocation, facade, pipeServer);
await await gameSupervisor.TryStartGameAsync(stopGameCancelationTokenSource.Token);
diff --git a/StarMapLoader/StarMapLoader.csproj b/StarMapLoader/StarMapLoader.csproj
index 44126d0..955a821 100644
--- a/StarMapLoader/StarMapLoader.csproj
+++ b/StarMapLoader/StarMapLoader.csproj
@@ -8,7 +8,8 @@
-
+
+