Add IScriptProvider + Sys4ScriptProvider (call-script id -> Script)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
20
engine/Age.Engine.Tests/Sys4ScriptProviderTests.cs
Normal file
20
engine/Age.Engine.Tests/Sys4ScriptProviderTests.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Age.Engine.Sys4;
|
||||
using Xunit;
|
||||
|
||||
public class Sys4ScriptProviderTests
|
||||
{
|
||||
[Fact]
|
||||
public void ResolvesKnownIdsToTheirScripts()
|
||||
{
|
||||
var table = OpcodeTableJson.Load(Paths.OpcodesJson);
|
||||
var provider = Sys4ScriptProvider.Load(table);
|
||||
|
||||
var additem = provider.GetById(0x1ab); // ADDITEM.BIN
|
||||
var mes = provider.GetById(0x2ae7); // MES.BIN
|
||||
Assert.NotNull(additem);
|
||||
Assert.NotNull(mes);
|
||||
Assert.True(additem!.Instructions.Count > 0);
|
||||
Assert.Same(additem, provider.GetById(0x1ab)); // cached: same instance
|
||||
Assert.Null(provider.GetById(long.MaxValue)); // unknown id
|
||||
}
|
||||
}
|
||||
10
engine/Age.Engine/Hosting/IScriptProvider.cs
Normal file
10
engine/Age.Engine/Hosting/IScriptProvider.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using Age.Engine.Model;
|
||||
namespace Age.Engine.Hosting;
|
||||
|
||||
/// <summary>Resolves a call-script id (a raw SYS4INI file index) to a loaded <see cref="Script"/>.
|
||||
/// Implemented in Sys4; injected into the VM so the Vm layer never references Sys4.</summary>
|
||||
public interface IScriptProvider
|
||||
{
|
||||
/// <summary>The script for this id, or null if the id maps to no known script.</summary>
|
||||
Script? GetById(long id);
|
||||
}
|
||||
@@ -10,6 +10,7 @@ public static class Paths
|
||||
public static string OpcodesJson => Path.Combine(Build, "opcodes.json");
|
||||
public static string AssetSectionsJson => Path.Combine(Build, "asset-sections.json");
|
||||
public static string AssetIndexJson => Path.Combine(Build, "asset-index.json");
|
||||
public static string CallscriptNamesJson => Path.Combine(Build, "callscript-names.json");
|
||||
public static string Textures => Path.Combine(Build, "textures");
|
||||
|
||||
private static string FindRepo()
|
||||
|
||||
39
engine/Age.Engine/Sys4/Sys4ScriptProvider.cs
Normal file
39
engine/Age.Engine/Sys4/Sys4ScriptProvider.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System.Text.Json;
|
||||
using Age.Engine.Hosting;
|
||||
using Age.Engine.Model;
|
||||
namespace Age.Engine.Sys4;
|
||||
|
||||
/// <summary>Resolves call-script ids (raw SYS4INI file indices) to loaded scripts, using
|
||||
/// build/callscript-names.json (id→name) + Paths.Scripts() (name→path). Cached per id.
|
||||
/// The native resolver prefers a loose override before the archive; Paths.Scripts() already
|
||||
/// shadows extracted/DATA1 with root overrides, so that behavior is preserved.</summary>
|
||||
public sealed class Sys4ScriptProvider : IScriptProvider
|
||||
{
|
||||
private readonly OpcodeTable _table;
|
||||
private readonly IReadOnlyDictionary<long, string> _idToName;
|
||||
private readonly Dictionary<string, string> _byName; // NAME(UPPER) -> path
|
||||
private readonly Dictionary<long, Script?> _cache = new();
|
||||
|
||||
public Sys4ScriptProvider(OpcodeTable table, IReadOnlyDictionary<long, string> idToName,
|
||||
Dictionary<string, string> byName)
|
||||
{ _table = table; _idToName = idToName; _byName = byName; }
|
||||
|
||||
public static Sys4ScriptProvider Load(OpcodeTable table)
|
||||
{
|
||||
var raw = JsonSerializer.Deserialize<Dictionary<string, string>>(
|
||||
File.ReadAllText(Paths.CallscriptNamesJson)) ?? new();
|
||||
var idToName = raw.ToDictionary(kv => long.Parse(kv.Key), kv => kv.Value);
|
||||
return new Sys4ScriptProvider(table, idToName, Paths.Scripts());
|
||||
}
|
||||
|
||||
public Script? GetById(long id)
|
||||
{
|
||||
if (_cache.TryGetValue(id, out var cached)) return cached;
|
||||
Script? s = null;
|
||||
if (_idToName.TryGetValue(id, out var name) &&
|
||||
_byName.TryGetValue(name.ToUpperInvariant(), out var path))
|
||||
s = Sys4Loader.Load(path, _table);
|
||||
_cache[id] = s;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user