Reject receipts for different Eve invocations

This commit is contained in:
Meta Vens 2026-08-19 04:25:32 +02:00
commit 6fe5a789fe
4 changed files with 49 additions and 6 deletions

View file

@ -1626,6 +1626,7 @@ namespace GameCult.Eve.UnityScene
string.Equals(receipt.ProviderId, request.ProviderId, StringComparison.Ordinal) &&
string.Equals(receipt.SurfaceId, request.SurfaceId, StringComparison.Ordinal) &&
string.Equals(receipt.Authority, _target.AuthorityRuntimeId, StringComparison.Ordinal) &&
string.Equals(receipt.InvocationHash, EveCommandInvocationHash.Compute(request), StringComparison.Ordinal) &&
IsKnownReceiptState(receipt.State);
private static bool IsKnownReceiptState(string state) =>

View file

@ -187,6 +187,47 @@ namespace GameCult.Eve.UnityScene.Tests
Assert.That(observed.Select(value => value.State), Is.EqualTo(new[] { "pending", "accepted" }));
}
[Test]
public void ReceiptForAnotherInvocationCannotRetireTheCommand()
{
using var transport = new EveUnityCultMeshLiveProviderTransport(
"test-cache",
"cultnet+tcp://127.0.0.1:1",
"test.verse",
"test.runtime",
"test.provider",
"test.surface");
var request = Request("launch-1", "launch");
var pendingField = typeof(EveUnityCultMeshLiveProviderTransport).GetField(
"_pendingCommands",
BindingFlags.NonPublic | BindingFlags.Instance);
var publish = typeof(EveUnityCultMeshLiveProviderTransport).GetMethod(
"PublishReceipt",
BindingFlags.NonPublic | BindingFlags.Instance);
var pending = (IDictionary<string, EveSurfaceCommandRequest>)pendingField!.GetValue(transport)!;
pending.Add(request.CommandId, request);
var observed = new List<EveUnitySceneCommandReceipt>();
transport.CommandReceiptAvailable += observed.Add;
var collision = new EveCommandReceiptDocument(
"receipt-collision",
request.CommandId,
request.Command,
"accepted",
"AetheriaEve",
"test.runtime",
request.ProviderId,
request.SurfaceId,
"",
DateTimeOffset.UtcNow.ToString("O"),
1,
invocationHash: EveCommandInvocationHash.Compute(Request(request.CommandId, "another-payload")));
publish!.Invoke(transport, new object[] { collision });
Assert.That(pending.ContainsKey(request.CommandId), Is.True);
Assert.That(observed, Is.Empty);
}
[Test]
public void ProviderSelectionCarriesStableIdentityWithoutExposingAPhysicalRoute()
{
@ -248,7 +289,8 @@ namespace GameCult.Eve.UnityScene.Tests
request.SurfaceId,
"",
DateTimeOffset.UtcNow.ToString("O"),
1);
1,
invocationHash: EveCommandInvocationHash.Compute(request));
private static async Task AwaitOrCancel(Task task, CancellationToken cancellationToken)
{

View file

@ -1,14 +1,14 @@
{
"name": "org.gamecult.eve.unity-scene",
"displayName": "Eve Unity Scene Lowering",
"version": "0.3.122",
"version": "0.3.124",
"unity": "6000.0",
"description": "Provider-agnostic Unity scene shell for gamecult.eve.surface.v1 interactive world surfaces.",
"dependencies": {
"org.gamecult.cultlib": "1.0.56",
"org.gamecult.eve.plugin-fields": "0.2.3",
"org.gamecult.eve.surface": "0.3.3",
"org.gamecult.eve.unity-uitoolkit": "0.1.7",
"org.gamecult.eve.surface": "0.3.5",
"org.gamecult.eve.unity-uitoolkit": "0.1.9",
"com.unity.mathematics": "1.3.2",
"com.unity.render-pipelines.universal": "17.4.0",
"com.unity.modules.particlesystem": "1.0.0"

View file

@ -1,11 +1,11 @@
{
"name": "org.gamecult.eve.unity-uitoolkit",
"displayName": "Eve UI Toolkit Lowering",
"version": "0.1.7",
"version": "0.1.9",
"unity": "2021.3",
"description": "Unity UI Toolkit lowering for gamecult.eve.surface.v1 documents.",
"dependencies": {
"org.gamecult.eve.surface": "0.3.3"
"org.gamecult.eve.surface": "0.3.5"
},
"keywords": [
"Eve",