74 lines
1.9 KiB
C#
74 lines
1.9 KiB
C#
using Godot;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text.Json;
|
|
|
|
public partial class PackManager : Node
|
|
{
|
|
public record PackManifest(int schema, string id, string name, string version, int priority);
|
|
|
|
private readonly List<(string Root, PackManifest Manifest)> _packs = new();
|
|
|
|
public override void _Ready()
|
|
{
|
|
LoadPacks("res://packs");
|
|
GD.Print($"Loaded packs: {string.Join(", ", _packs.Select(p => $"{p.Manifest.id}(prio={p.Manifest.priority})"))}");
|
|
}
|
|
|
|
public void LoadPacks(string packsRoot)
|
|
{
|
|
_packs.Clear();
|
|
|
|
if (!DirAccess.DirExistsAbsolute(packsRoot))
|
|
{
|
|
GD.PrintErr($"Packs root missing: {packsRoot}");
|
|
return;
|
|
}
|
|
|
|
using var dir = DirAccess.Open(packsRoot);
|
|
dir.ListDirBegin();
|
|
while (true)
|
|
{
|
|
var entry = dir.GetNext();
|
|
if (entry == "") break;
|
|
if (entry.StartsWith(".")) continue;
|
|
|
|
var packPath = $"{packsRoot}/{entry}";
|
|
if (!dir.CurrentIsDir()) continue;
|
|
|
|
var manifestPath = $"{packPath}/pack.json";
|
|
if (!FileAccess.FileExists(manifestPath))
|
|
continue;
|
|
|
|
var json = FileAccess.GetFileAsString(manifestPath);
|
|
var manifest = JsonSerializer.Deserialize<PackManifest>(json);
|
|
if (manifest == null)
|
|
{
|
|
GD.PrintErr($"Invalid pack.json: {manifestPath}");
|
|
continue;
|
|
}
|
|
|
|
_packs.Add((packPath, manifest));
|
|
}
|
|
dir.ListDirEnd();
|
|
|
|
// Sort bottom->top by priority (low first, high last)
|
|
_packs.Sort((a, b) => a.Manifest.priority.CompareTo(b.Manifest.priority));
|
|
}
|
|
|
|
/// Returns the best (topmost) existing file path for a relative path inside a pack.
|
|
public string? Resolve(string relativePath)
|
|
{
|
|
relativePath = relativePath.TrimStart('/');
|
|
|
|
// Highest priority pack wins -> iterate from end
|
|
for (int i = _packs.Count - 1; i >= 0; i--)
|
|
{
|
|
var candidate = $"{_packs[i].Root}/{relativePath}";
|
|
if (FileAccess.FileExists(candidate))
|
|
return candidate;
|
|
}
|
|
return null;
|
|
}
|
|
}
|