Skip to content

Commit

Permalink
2.0.7
Browse files Browse the repository at this point in the history
  • Loading branch information
NotNite committed Oct 24, 2024
1 parent f9a69bc commit 4421bae
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 17 deletions.
2 changes: 1 addition & 1 deletion GDWeave/GDWeave.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>2.0.6.0</Version>
<Version>2.0.7.0</Version>

<!-- required for loader -->
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
Expand Down
2 changes: 2 additions & 0 deletions GDWeave/Loader/LoadedMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

internal class LoadedMod {
public required ModManifest Manifest;
public required string Directory;
public IMod? AssemblyMod;
public string? AssemblyPath;
public string? PackPath;
}
56 changes: 40 additions & 16 deletions GDWeave/Loader/ModLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,40 @@ internal class ModLoader {
private readonly Dictionary<string, List<IScriptMod>> scriptMods = new();

public ModLoader() {
this.Load();
this.Register();
this.Sort();
this.LoadAssemblies();
this.logger.Information("Loaded {Count} mods: {ModIds}", this.LoadedMods.Count,
this.LoadedMods.Select(x => x.Manifest.Id));
}

public void Load() {
private void Register() {
var modsDir = Path.Combine(GDWeave.GDWeaveDir, "mods");
if (!Directory.Exists(modsDir)) return;

foreach (var modDir in Directory.GetDirectories(modsDir)) {
try {
var manifestPath = Path.Combine(modDir, "manifest.json");
if (!File.Exists(manifestPath)) {
logger.Warning("Mod at {ModDir} does not have a manifest.json", modDir);
this.logger.Warning("Mod at {ModDir} does not have a manifest.json", modDir);
continue;
}

var manifest = JsonSerializer.Deserialize<ModManifest>(File.ReadAllText(manifestPath))!;
if (manifest.Id != Path.GetFileName(modDir)) {
logger.Warning("Mod at {ModDir} has an incorrect ID in its manifest", modDir);
if (this.LoadedMods.Any(x => x.Manifest.Id == manifest.Id)) {
this.logger.Warning("Duplicate mod ID: {ModId}", manifest.Id);
continue;
}

var mod = manifest.AssemblyPath is { } assemblyPath
? this.LoadAssembly(manifest.Id, Path.Combine(modDir, assemblyPath))
: null;
this.logger.Debug("Loading mod {ModId} from {ModDir}", manifest.Id, modDir);

var loadedMod = new LoadedMod {
Manifest = manifest,
AssemblyMod = mod,
Directory = modDir,
AssemblyMod = null,
AssemblyPath = manifest.AssemblyPath is { } assemblyPath
? Path.Combine(modDir, assemblyPath)
: null,
PackPath = manifest.PackPath is { } packPath
? Path.Combine(modDir, packPath)
: null
Expand All @@ -55,15 +60,19 @@ public void Load() {
}

private void Sort() {
var dependencyGraph = this.LoadedMods.ToDictionary(x => x.Manifest.Id, x => x.Manifest.Dependencies);
foreach (var (modId, dependencies) in dependencyGraph) {
foreach (var dependency in dependencies.ToList()
.Where(dependency => !dependencyGraph.ContainsKey(dependency))) {
this.logger.Warning("Mod {ModId} depends on missing mod {Dependency}", modId, dependency);
break;
while (true) {
var invalidMods = this.LoadedMods
.Where(x => x.Manifest.Dependencies.Any(d => !this.LoadedMods.Any(m => m.Manifest.Id == d))).ToList();
if (invalidMods.Count == 0) break;

foreach (var invalidMod in invalidMods) {
this.logger.Warning("Mod {ModId} has missing/invalid dependencies: {InvalidDependencies}",
invalidMod.Manifest.Id, invalidMod.Manifest.Dependencies);
this.LoadedMods.Remove(invalidMod);
}
}

var dependencyGraph = this.LoadedMods.ToDictionary(x => x.Manifest.Id, x => x.Manifest.Dependencies);
var resolvedOrder = new List<string>();
while (dependencyGraph.Count > 0) {
var noDependencies = dependencyGraph.Where(x => x.Value.Count == 0).ToList();
Expand All @@ -88,6 +97,21 @@ private void Sort() {
this.LoadedMods = this.LoadedMods.OrderBy(x => resolvedOrder.IndexOf(x.Manifest.Id)).ToList();
}

private void LoadAssemblies() {
foreach (var loadedMod in this.LoadedMods) {
if (loadedMod.AssemblyPath is not { } assemblyPath) continue;

try {
this.logger.Debug("Loading assembly for mod {ModId} from {AssemblyPath}", loadedMod.Manifest.Id,
assemblyPath);
var assemblyMod = this.LoadAssembly(loadedMod.Manifest.Id, assemblyPath);
loadedMod.AssemblyMod = assemblyMod;
} catch (Exception e) {
this.logger.Warning(e, "Failed to load assembly for mod {ModId}", loadedMod.Manifest.Id);
}
}
}

private IMod? LoadAssembly(string id, string assemblyPath) {
var fullAssemblyPath = Path.GetFullPath(assemblyPath);
var context = new ModLoadContext(fullAssemblyPath);
Expand All @@ -96,7 +120,7 @@ private void Sort() {
t.GetInterfaces().FirstOrDefault(t => t.FullName == typeof(IMod).FullName) != null);

if (modType == null) {
logger.Warning("Assembly at {AssemblyPath} does not contain a mod", assemblyPath);
this.logger.Warning("Assembly at {AssemblyPath} does not contain a mod", assemblyPath);
return null;
}

Expand Down

0 comments on commit 4421bae

Please sign in to comment.