refactor(runtime): cut graphical host over to canonical root
Make every App composition phase borrow one GameRuntime, retire the duplicate view/event adapters, and dispose the root only after its graphical borrowers release. This preserves synchronous UI commands while giving shutdown one exact ownership ledger. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
ecb9f79444
commit
ce41efb9e5
29 changed files with 613 additions and 778 deletions
|
|
@ -13,18 +13,22 @@ public sealed class GameWindowLiveSessionOwnershipTests
|
|||
BindingFlags.Instance | BindingFlags.NonPublic;
|
||||
|
||||
[Fact]
|
||||
public void GameWindowRetainsControllerAndFocusedHostButNoMirroredSession()
|
||||
public void GameWindowRetainsCanonicalRuntimeAndFocusedHostButNoMirroredSession()
|
||||
{
|
||||
FieldInfo[] fields = typeof(GameWindow).GetFields(PrivateInstance);
|
||||
|
||||
Assert.Contains(
|
||||
fields,
|
||||
field => field.Name == "_liveSessionController"
|
||||
&& field.FieldType == typeof(LiveSessionController));
|
||||
field => field.Name == "_runtime"
|
||||
&& field.FieldType == typeof(GameRuntime));
|
||||
Assert.Contains(
|
||||
fields,
|
||||
field => field.Name == "_liveSessionHost"
|
||||
&& field.FieldType == typeof(LiveSessionHost));
|
||||
Assert.DoesNotContain(
|
||||
fields,
|
||||
field => field.Name == "_liveSessionController"
|
||||
|| field.FieldType == typeof(LiveSessionController));
|
||||
Assert.DoesNotContain(fields, field => field.Name == "_liveSession");
|
||||
Assert.DoesNotContain(fields, field => field.FieldType == typeof(WorldSession));
|
||||
Assert.DoesNotContain(fields, field => field.FieldType == typeof(LiveSessionResetPlan));
|
||||
|
|
@ -54,6 +58,48 @@ public sealed class GameWindowLiveSessionOwnershipTests
|
|||
|| field.FieldType == typeof(ulong));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProductionWindowConstructsOnlyTheCanonicalRuntimeRoot()
|
||||
{
|
||||
string root = FindRepositoryRoot();
|
||||
string source = File.ReadAllText(Path.Combine(
|
||||
root,
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Rendering",
|
||||
"GameWindow.cs"));
|
||||
|
||||
Assert.Equal(
|
||||
1,
|
||||
CountOccurrences(source, "new GameRuntime("));
|
||||
Assert.Contains(
|
||||
"private readonly GameRuntime _runtime;",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"_runtimeHostLease = _runtime.AcquireHostLease(",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
string[] forbidden =
|
||||
[
|
||||
"new RuntimeEntityObjectLifetime(",
|
||||
"new RuntimeInventoryState(",
|
||||
"new RuntimeCharacterState(",
|
||||
"new RuntimeCommunicationState(",
|
||||
"new RuntimeActionState(",
|
||||
"new RuntimeLocalPlayerMovementState(",
|
||||
"new RuntimeWorldTransitState(",
|
||||
"new LiveSessionController(",
|
||||
"new GameRuntimeClock(",
|
||||
];
|
||||
Assert.All(
|
||||
forbidden,
|
||||
value => Assert.DoesNotContain(
|
||||
value,
|
||||
source,
|
||||
StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("TryStartLiveSession")]
|
||||
[InlineData("ClearInboundEntityState")]
|
||||
|
|
@ -66,4 +112,32 @@ public sealed class GameWindowLiveSessionOwnershipTests
|
|||
{
|
||||
Assert.Null(typeof(GameWindow).GetMethod(methodName, PrivateInstance));
|
||||
}
|
||||
|
||||
private static int CountOccurrences(string source, string value)
|
||||
{
|
||||
int count = 0;
|
||||
int cursor = 0;
|
||||
while ((cursor = source.IndexOf(
|
||||
value,
|
||||
cursor,
|
||||
StringComparison.Ordinal)) >= 0)
|
||||
{
|
||||
count++;
|
||||
cursor += value.Length;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue