Use generic Starbridge seat documents
This commit is contained in:
parent
624ab397c0
commit
f093b422d1
4 changed files with 92 additions and 17 deletions
|
|
@ -8129,9 +8129,7 @@ static void RequireAetheriaManagedStateAccessorsCoverDomainDocuments(string root
|
|||
"public Task<TDocument> LatestAsync<TDocument>()",
|
||||
"public TDocument Latest<TDocument>()",
|
||||
"public Task<CultMeshReactiveDocument<TDocument>> ReactiveAsync<TDocument>(",
|
||||
"public CultMeshReactiveDocument<TDocument> Reactive<TDocument>(",
|
||||
"public AetheriaRuntimeStarbridgePlayerSeatDocument LatestPlayerSeat(string seatId)",
|
||||
"public CultMeshReactiveDocument<AetheriaRuntimeStarbridgePlayerSeatDocument> ReactivePlayerSeat("
|
||||
"public CultMeshReactiveDocument<TDocument> Reactive<TDocument>("
|
||||
};
|
||||
var missingClientSymbols = requiredClientSymbols
|
||||
.Where(symbol => !clientState.Contains(symbol, StringComparison.Ordinal))
|
||||
|
|
@ -8314,6 +8312,46 @@ static void RequireAetheriaManagedStateAccessorsCoverDomainDocuments(string root
|
|||
string.Join(", ", survivingCurrentConvenienceWrappers));
|
||||
}
|
||||
|
||||
var starbridgeState = clientState.Split(
|
||||
"public sealed class AetheriaClientStarbridgeState",
|
||||
StringSplitOptions.None).Last();
|
||||
var compactStarbridgeState = CompactSource(starbridgeState);
|
||||
var requiredStarbridgeParameterizedSymbols = new[]
|
||||
{
|
||||
"publicboolTryGetDocument<TDocument>(stringseatId,outCultMeshDocumentHandle<TDocument>document)",
|
||||
"publicCultMeshDocumentHandle<TDocument>Document<TDocument>(stringseatId)",
|
||||
"publicTask<TDocument>LatestAsync<TDocument>(stringseatId)",
|
||||
"publicTDocumentLatest<TDocument>(stringseatId)",
|
||||
"publicTask<CultMeshReactiveDocument<TDocument>>ReactiveAsync<TDocument>(stringseatId,",
|
||||
"publicCultMeshReactiveDocument<TDocument>Reactive<TDocument>(stringseatId,"
|
||||
};
|
||||
var missingStarbridgeParameterizedSymbols = requiredStarbridgeParameterizedSymbols
|
||||
.Where(symbol => !compactStarbridgeState.Contains(symbol, StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
if (missingStarbridgeParameterizedSymbols.Length > 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"AetheriaClientStarbridgeState must expose generic parameterized document access for player-seat state: " +
|
||||
string.Join(", ", missingStarbridgeParameterizedSymbols));
|
||||
}
|
||||
|
||||
var forbiddenStarbridgeConvenienceWrappers = new[]
|
||||
{
|
||||
"LatestPlayerSeat(",
|
||||
"LatestPlayerSeatAsync(",
|
||||
"ReactivePlayerSeat(",
|
||||
"ReactivePlayerSeatAsync("
|
||||
};
|
||||
var survivingStarbridgeConvenienceWrappers = forbiddenStarbridgeConvenienceWrappers
|
||||
.Where(symbol => starbridgeState.Contains(symbol, StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
if (survivingStarbridgeConvenienceWrappers.Length > 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"AetheriaClientStarbridgeState must use generic parameterized document access instead of named player-seat latest/reactive wrappers: " +
|
||||
string.Join(", ", survivingStarbridgeConvenienceWrappers));
|
||||
}
|
||||
|
||||
var observedDaemonState = File.ReadAllText(observedDaemonStatePath);
|
||||
if (!observedDaemonState.Contains("public static bool TryCreateCurrent(", StringComparison.Ordinal) ||
|
||||
!observedDaemonState.Contains("new AetheriaRuntimeObservedDaemonState(currentFrame, currentSoaView, currentZoneRender)", StringComparison.Ordinal))
|
||||
|
|
@ -8432,14 +8470,17 @@ static void RequireAetheriaManagedStateAccessorsCoverDomainDocuments(string root
|
|||
}
|
||||
|
||||
if (!checkedSources["StarbridgePlayerSeatDocumentTests.cs"].Contains(
|
||||
".ReactivePlayerSeat(seat.SeatId)",
|
||||
".Reactive<AetheriaRuntimeStarbridgePlayerSeatDocument>(seat.SeatId)",
|
||||
StringComparison.Ordinal) ||
|
||||
!checkedSources["StarbridgePlayerSeatDocumentTests.cs"].Contains(
|
||||
".Latest<AetheriaRuntimeStarbridgePlayerSeatDocument>(seat.SeatId)",
|
||||
StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Starbridge player-seat examples must use the named managed reactive accessor instead of fetching the raw document handle.");
|
||||
"Starbridge player-seat examples must use generic parameterized managed document access instead of named wrappers or raw handle walks.");
|
||||
}
|
||||
|
||||
Console.WriteLine("Domain document accessors: managed Aetheria state uses generic fixed-document reads plus named parameterized viewport/detail/Starbridge handles");
|
||||
Console.WriteLine("Domain document accessors: managed Aetheria state uses generic fixed-document reads plus generic parameterized viewport/detail/Starbridge access");
|
||||
}
|
||||
|
||||
static void RequireVerseHostSettingsAuthority(string root)
|
||||
|
|
|
|||
|
|
@ -82,10 +82,15 @@ public class StarbridgePlayerSeatDocumentTests
|
|||
.State
|
||||
.Starbridge;
|
||||
using var reactive = handle.Reactive();
|
||||
using var aetheriaSeat = aetheriaStarbridge.ReactivePlayerSeat(seat.SeatId);
|
||||
using var aetheriaSeat = aetheriaStarbridge
|
||||
.Reactive<AetheriaRuntimeStarbridgePlayerSeatDocument>(seat.SeatId);
|
||||
|
||||
Assert.AreEqual("seat-support", handle.Latest().SeatId);
|
||||
Assert.AreEqual("seat-support", client.State.Starbridge.LatestPlayerSeat(seat.SeatId).SeatId);
|
||||
Assert.AreEqual(
|
||||
"seat-support",
|
||||
client.State.Starbridge
|
||||
.Latest<AetheriaRuntimeStarbridgePlayerSeatDocument>(seat.SeatId)
|
||||
.SeatId);
|
||||
Assert.AreEqual("item:cockpit:support", reactive.Current.CockpitItemKey);
|
||||
Assert.AreEqual("item:cockpit:support", aetheriaSeat.Current.CockpitItemKey);
|
||||
Assert.AreEqual("entity:pod:support", reactive.Current.EscapePodEntityKey);
|
||||
|
|
|
|||
|
|
@ -797,28 +797,57 @@ namespace GameCult.Aetheria.State.Verse
|
|||
return _playerSeat(seatId);
|
||||
}
|
||||
|
||||
public Task<AetheriaRuntimeStarbridgePlayerSeatDocument> LatestPlayerSeatAsync(string seatId)
|
||||
public bool TryGetDocument<TDocument>(
|
||||
string seatId,
|
||||
out CultMeshDocumentHandle<TDocument> document)
|
||||
where TDocument : class
|
||||
{
|
||||
return PlayerSeat(seatId).LatestAsync();
|
||||
if (typeof(TDocument) == typeof(AetheriaRuntimeStarbridgePlayerSeatDocument))
|
||||
{
|
||||
document = (CultMeshDocumentHandle<TDocument>)(object)PlayerSeat(seatId);
|
||||
return true;
|
||||
}
|
||||
|
||||
document = null!;
|
||||
return false;
|
||||
}
|
||||
|
||||
public AetheriaRuntimeStarbridgePlayerSeatDocument LatestPlayerSeat(string seatId)
|
||||
public CultMeshDocumentHandle<TDocument> Document<TDocument>(string seatId)
|
||||
where TDocument : class
|
||||
{
|
||||
return LatestPlayerSeatAsync(seatId).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
if (TryGetDocument<TDocument>(seatId, out var document))
|
||||
return document;
|
||||
|
||||
throw new NotSupportedException(
|
||||
$"Aetheria Starbridge state does not expose a parameterized document for {typeof(TDocument).FullName}.");
|
||||
}
|
||||
|
||||
public Task<CultMeshReactiveDocument<AetheriaRuntimeStarbridgePlayerSeatDocument>> ReactivePlayerSeatAsync(
|
||||
public Task<TDocument> LatestAsync<TDocument>(string seatId)
|
||||
where TDocument : class
|
||||
{
|
||||
return Document<TDocument>(seatId).LatestAsync();
|
||||
}
|
||||
|
||||
public TDocument Latest<TDocument>(string seatId)
|
||||
where TDocument : class
|
||||
{
|
||||
return LatestAsync<TDocument>(seatId).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public Task<CultMeshReactiveDocument<TDocument>> ReactiveAsync<TDocument>(
|
||||
string seatId,
|
||||
CultMeshReactiveDocumentOptions? options = null)
|
||||
where TDocument : class
|
||||
{
|
||||
return PlayerSeat(seatId).ReactiveAsync(options);
|
||||
return Document<TDocument>(seatId).ReactiveAsync(options);
|
||||
}
|
||||
|
||||
public CultMeshReactiveDocument<AetheriaRuntimeStarbridgePlayerSeatDocument> ReactivePlayerSeat(
|
||||
public CultMeshReactiveDocument<TDocument> Reactive<TDocument>(
|
||||
string seatId,
|
||||
CultMeshReactiveDocumentOptions? options = null)
|
||||
where TDocument : class
|
||||
{
|
||||
return PlayerSeat(seatId).Reactive(options);
|
||||
return Document<TDocument>(seatId).Reactive(options);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Aetheria Verse Client Contract
|
||||
|
||||
Aetheria clients should enter the runtime through CultMesh typed state, not through
|
||||
Aetheria clients should enter the runtime through CultMesh typed Verse records, not through
|
||||
daemon internals. The daemon owns simulation authority over canonical shared
|
||||
documents; it does not own a separate private truth that is then copied into
|
||||
client state. Unity, tools, test harnesses, and later non-Unity clients open the
|
||||
|
|
|
|||
Loading…
Reference in a new issue