ocker/scripts/core/PackManager.cs

80 lines
2.1 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 _EnterTree()
{
LoadPacks("res://packs");
GD.Print($"Loaded packs: {string.Join(", ", _packs.Select(p => $"{p.Manifest.id}(prio={p.Manifest.priority})"))}");
}
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;
}
}