refactor(runtime): own magic and player state
Move the coupled Spellbook and LocalPlayerState into one Runtime-owned character graph, route content, live-session, retained UI, reset, and shutdown through that exact owner, and delete the duplicate desired-component snapshot from inventory state. Preserve synchronous retail update and reset ordering while adding independent-instance and retryable-failure coverage. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
d362172620
commit
d02a12ceac
16 changed files with 418 additions and 96 deletions
|
|
@ -15,6 +15,7 @@ using AcDream.Core.Physics;
|
|||
using AcDream.Core.Rendering;
|
||||
using AcDream.Core.Spells;
|
||||
using AcDream.Core.Vfx;
|
||||
using AcDream.Runtime.Gameplay;
|
||||
using DatReaderWriter.DBObjs;
|
||||
using Silk.NET.Input;
|
||||
using Silk.NET.OpenAL;
|
||||
|
|
@ -257,7 +258,7 @@ public sealed class ContentEffectsAudioCompositionTests
|
|||
ResidencyBudgetOptions.Default,
|
||||
new PhysicsDataCache(),
|
||||
false,
|
||||
new Spellbook(),
|
||||
new RuntimeCharacterState(),
|
||||
Router,
|
||||
Poses,
|
||||
new DeferredEntityEffectAdvanceSource(),
|
||||
|
|
@ -289,7 +290,11 @@ public sealed class ContentEffectsAudioCompositionTests
|
|||
throw new InvalidOperationException($"fault at {point}");
|
||||
});
|
||||
|
||||
public void Dispose() => Publication.Dispose();
|
||||
public void Dispose()
|
||||
{
|
||||
Publication.Dispose();
|
||||
Dependencies.Character.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class Publication :
|
||||
|
|
@ -386,7 +391,9 @@ public sealed class ContentEffectsAudioCompositionTests
|
|||
return _preparedAssets;
|
||||
}
|
||||
public MagicCatalog LoadMagicCatalog(IDatReaderWriter dats) => _magic;
|
||||
public void InstallSpellMetadata(Spellbook spellBook, MagicCatalog catalog) { }
|
||||
public void InstallSpellMetadata(
|
||||
RuntimeCharacterState character,
|
||||
MagicCatalog catalog) { }
|
||||
public int GetSpellCount(MagicCatalog catalog) => 0;
|
||||
public IAnimationLoader CreateAnimationLoader(
|
||||
IDatReaderWriter dats,
|
||||
|
|
|
|||
|
|
@ -191,9 +191,8 @@ public sealed class InteractionRetainedUiCompositionTests
|
|||
Selection: null!,
|
||||
Inventory: null!,
|
||||
MagicCatalog: null!,
|
||||
Spellbook: null!,
|
||||
Character: null!,
|
||||
Communication: null!,
|
||||
LocalPlayer: null!,
|
||||
StackSplitQuantity: null!,
|
||||
UiRegistry: null,
|
||||
CombatModeCommands: null!,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
namespace AcDream.App.Tests.Runtime;
|
||||
|
||||
public sealed class RuntimeCharacterOwnershipTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProductionConstructsOnlyTheRuntimeCharacterOwner()
|
||||
{
|
||||
string source = ReadSource("Rendering", "GameWindow.cs");
|
||||
|
||||
Assert.Contains(
|
||||
"_runtimeCharacter = new RuntimeCharacterState();",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
Assert.DoesNotContain(
|
||||
"new AcDream.Core.Spells.Spellbook",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
Assert.DoesNotContain(
|
||||
"new AcDream.Core.Player.LocalPlayerState",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"SpellBook =>\n _runtimeCharacter.Spellbook;",
|
||||
Normalize(source),
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"LocalPlayer =>\n _runtimeCharacter.LocalPlayer;",
|
||||
Normalize(source),
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SessionRoutingAndShutdownBorrowTheExactRuntimeOwner()
|
||||
{
|
||||
string session = ReadSource("Net", "LiveSessionRuntimeFactory.cs");
|
||||
string router = ReadRuntimeSource(
|
||||
"Session",
|
||||
"LiveSessionEventRouter.cs");
|
||||
string content = ReadSource(
|
||||
"Composition",
|
||||
"ContentEffectsAudioComposition.cs");
|
||||
string ui = ReadSource(
|
||||
"Composition",
|
||||
"InteractionRetainedUiComposition.cs");
|
||||
string inventory = ReadRuntimeSource(
|
||||
"Gameplay",
|
||||
"RuntimeInventoryState.cs");
|
||||
string shutdown = ReadSource("Rendering", "GameWindowLifetime.cs");
|
||||
|
||||
Assert.Contains(
|
||||
"RuntimeCharacterState Character",
|
||||
session,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"character.Character.Spellbook",
|
||||
router,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"character.Character.LocalPlayer",
|
||||
router,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"_factory.InstallSpellMetadata(_dependencies.Character, magic)",
|
||||
content,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"d.Character.Spellbook",
|
||||
ui,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"d.Character.LocalPlayer",
|
||||
ui,
|
||||
StringComparison.Ordinal);
|
||||
Assert.DoesNotContain(
|
||||
"DesiredComponentState",
|
||||
inventory,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"\"runtime character state\"",
|
||||
shutdown,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static string ReadSource(params string[] relative) =>
|
||||
File.ReadAllText(Path.Combine(
|
||||
[FindRepositoryRoot(), "src", "AcDream.App", .. relative]));
|
||||
|
||||
private static string ReadRuntimeSource(params string[] relative) =>
|
||||
File.ReadAllText(Path.Combine(
|
||||
[FindRepositoryRoot(), "src", "AcDream.Runtime", .. relative]));
|
||||
|
||||
private static string Normalize(string source) =>
|
||||
source.Replace("\r\n", "\n", StringComparison.Ordinal);
|
||||
|
||||
private static string FindRepositoryRoot()
|
||||
{
|
||||
var current = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
while (current is not null)
|
||||
{
|
||||
if (File.Exists(Path.Combine(current.FullName, "AcDream.slnx")))
|
||||
return current.FullName;
|
||||
current = current.Parent;
|
||||
}
|
||||
throw new DirectoryNotFoundException("AcDream.slnx was not found.");
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,10 @@ public sealed class RuntimeInventoryOwnershipTests
|
|||
"new AcDream.Core.Items.ExternalContainerState",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
Assert.DoesNotContain(
|
||||
"DesiredComponentState",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -50,8 +54,8 @@ public sealed class RuntimeInventoryOwnershipTests
|
|||
"_domain.Inventory.Transactions.CompleteUse(error)",
|
||||
session,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"OnDesiredComponents: _domain.Inventory.DesiredComponents.Replace",
|
||||
Assert.DoesNotContain(
|
||||
"_domain.Inventory.DesiredComponents",
|
||||
session,
|
||||
StringComparison.Ordinal);
|
||||
AssertAppearsInOrder(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue