diff --git a/packages/eve-contracts/dist/generated/command-receipt.d.ts b/packages/eve-contracts/dist/generated/command-receipt.d.ts
index 1ee105b..735cc2f 100644
--- a/packages/eve-contracts/dist/generated/command-receipt.d.ts
+++ b/packages/eve-contracts/dist/generated/command-receipt.d.ts
@@ -13,7 +13,14 @@ export interface EveCommandReceipt {
[k: string]: any;
}[];
issuedAtUtc?: string;
+ /**
+ * Provider-state generation that causally owns this result. It is not implicitly an Eve surface version.
+ */
sourceVersion: number;
+ /**
+ * Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality.
+ */
+ presentationSurfaceVersion?: number;
/**
* Canonical digest of the immutable invocation envelope finalized by this receipt.
*/
diff --git a/packages/eve-contracts/dist/generated/schemas.d.ts b/packages/eve-contracts/dist/generated/schemas.d.ts
index 8ea315a..a75705f 100644
--- a/packages/eve-contracts/dist/generated/schemas.d.ts
+++ b/packages/eve-contracts/dist/generated/schemas.d.ts
@@ -640,6 +640,12 @@ export declare const eveContractSchemas: {
readonly sourceVersion: {
readonly type: "integer";
readonly minimum: 0;
+ readonly description: "Provider-state generation that causally owns this result. It is not implicitly an Eve surface version.";
+ };
+ readonly presentationSurfaceVersion: {
+ readonly type: "integer";
+ readonly minimum: 1;
+ readonly description: "Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality.";
};
readonly invocationHash: {
readonly type: "string";
diff --git a/packages/eve-contracts/dist/generated/schemas.js b/packages/eve-contracts/dist/generated/schemas.js
index c036cf9..4695090 100644
--- a/packages/eve-contracts/dist/generated/schemas.js
+++ b/packages/eve-contracts/dist/generated/schemas.js
@@ -767,7 +767,13 @@ export const eveContractSchemas = {
},
"sourceVersion": {
"type": "integer",
- "minimum": 0
+ "minimum": 0,
+ "description": "Provider-state generation that causally owns this result. It is not implicitly an Eve surface version."
+ },
+ "presentationSurfaceVersion": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality."
},
"invocationHash": {
"type": "string",
diff --git a/packages/eve-contracts/src/generated/command-receipt.ts b/packages/eve-contracts/src/generated/command-receipt.ts
index 58fba85..7b95536 100644
--- a/packages/eve-contracts/src/generated/command-receipt.ts
+++ b/packages/eve-contracts/src/generated/command-receipt.ts
@@ -15,7 +15,14 @@ diagnostics?: {
[k: string]: any
}[]
issuedAtUtc?: string
+/**
+ * Provider-state generation that causally owns this result. It is not implicitly an Eve surface version.
+ */
sourceVersion: number
+/**
+ * Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality.
+ */
+presentationSurfaceVersion?: number
/**
* Canonical digest of the immutable invocation envelope finalized by this receipt.
*/
diff --git a/packages/eve-contracts/src/generated/schemas.ts b/packages/eve-contracts/src/generated/schemas.ts
index 18c877e..4716939 100644
--- a/packages/eve-contracts/src/generated/schemas.ts
+++ b/packages/eve-contracts/src/generated/schemas.ts
@@ -767,7 +767,13 @@ export const eveContractSchemas = {
},
"sourceVersion": {
"type": "integer",
- "minimum": 0
+ "minimum": 0,
+ "description": "Provider-state generation that causally owns this result. It is not implicitly an Eve surface version."
+ },
+ "presentationSurfaceVersion": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality."
},
"invocationHash": {
"type": "string",
diff --git a/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj b/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj
index b74ed1f..c821cfb 100644
--- a/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj
+++ b/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj
@@ -6,7 +6,7 @@
enable
Portable Eve surface and provider contracts.
GameCult.Eve.Surface
- 0.3.5
+ 0.3.6
GameCult
MPL-2.0
https://github.com/GameCult/Eve
diff --git a/packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs b/packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs
index e924a8d..31705be 100644
--- a/packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs
+++ b/packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs
@@ -367,8 +367,9 @@ namespace GameCult.Eve.Surface
string issuedAtUtc,
long sourceVersion,
EveSurfaceNavigationTarget? navigation = null,
- string invocationHash = "")
- : this(SchemaId, receiptId, commandId, command, state, ownerRepo, authority, providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash)
+ string invocationHash = "",
+ long presentationSurfaceVersion = 0)
+ : this(SchemaId, receiptId, commandId, command, state, ownerRepo, authority, providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash, presentationSurfaceVersion)
{
}
@@ -387,7 +388,8 @@ namespace GameCult.Eve.Surface
string issuedAtUtc,
long sourceVersion,
EveSurfaceNavigationTarget? navigation = null,
- string invocationHash = "")
+ string invocationHash = "",
+ long presentationSurfaceVersion = 0)
{
Schema = string.IsNullOrWhiteSpace(schema) ? SchemaId : schema;
ReceiptId = receiptId ?? "";
@@ -403,6 +405,7 @@ namespace GameCult.Eve.Surface
SourceVersion = sourceVersion;
Navigation = navigation;
InvocationHash = invocationHash ?? "";
+ PresentationSurfaceVersion = presentationSurfaceVersion;
}
[Key(0)] public string Schema { get; }
@@ -419,6 +422,7 @@ namespace GameCult.Eve.Surface
[Key(11)] public long SourceVersion { get; }
[Key(12)] public EveSurfaceNavigationTarget? Navigation { get; }
[Key(13)] public string InvocationHash { get; }
+ [Key(14)] public long PresentationSurfaceVersion { get; }
}
///
@@ -428,7 +432,7 @@ namespace GameCult.Eve.Surface
public sealed class EveCommandReceiptCompatibilityFormatter :
IMessagePackFormatter
{
- private const int LegacyFieldCount = 14;
+ private const int LegacyFieldCount = 15;
private const int RequiredAndScalarFieldCount = 12;
public void Serialize(
@@ -439,7 +443,8 @@ namespace GameCult.Eve.Surface
if (value == null) { writer.WriteNil(); return; }
var optionalFields = (value.Navigation == null ? 0 : 1) +
- (string.IsNullOrWhiteSpace(value.InvocationHash) ? 0 : 1);
+ (string.IsNullOrWhiteSpace(value.InvocationHash) ? 0 : 1) +
+ (value.PresentationSurfaceVersion <= 0 ? 0 : 1);
writer.WriteMapHeader(RequiredAndScalarFieldCount + optionalFields);
Write(ref writer, "schema", value.Schema);
Write(ref writer, "receiptId", value.ReceiptId);
@@ -460,6 +465,11 @@ namespace GameCult.Eve.Surface
}
if (!string.IsNullOrWhiteSpace(value.InvocationHash))
Write(ref writer, "invocationHash", value.InvocationHash);
+ if (value.PresentationSurfaceVersion > 0)
+ {
+ writer.Write("presentationSurfaceVersion");
+ writer.Write(value.PresentationSurfaceVersion);
+ }
}
public EveCommandReceiptDocument? Deserialize(
@@ -490,10 +500,12 @@ namespace GameCult.Eve.Surface
var sourceVersion = fields > 11 ? reader.ReadInt64() : 0;
var navigation = fields > 12 ? ReadNavigation(ref reader, options) : null;
var invocationHash = ReadString(ref reader, fields, 13);
+ var presentationSurfaceVersion = fields > 14 ? reader.ReadInt64() : 0;
for (var index = LegacyFieldCount; index < fields; index++) reader.Skip();
return new EveCommandReceiptDocument(
schema, receiptId, commandId, command, state, ownerRepo, authority,
- providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash);
+ providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash,
+ presentationSurfaceVersion);
}
finally { reader.Depth--; }
}
@@ -519,6 +531,7 @@ namespace GameCult.Eve.Surface
long sourceVersion = 0;
EveSurfaceNavigationTarget? navigation = null;
var invocationHash = "";
+ long presentationSurfaceVersion = 0;
var fields = reader.ReadMapHeader();
for (var index = 0; index < fields; index++)
{
@@ -538,13 +551,15 @@ namespace GameCult.Eve.Surface
case "sourceVersion": sourceVersion = reader.ReadInt64(); break;
case "navigation": navigation = ReadNavigation(ref reader, options); break;
case "invocationHash": invocationHash = ReadString(ref reader); break;
+ case "presentationSurfaceVersion": presentationSurfaceVersion = reader.ReadInt64(); break;
default: reader.Skip(); break;
}
}
return new EveCommandReceiptDocument(
schema, receiptId, commandId, command, state, ownerRepo, authority,
- providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash);
+ providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash,
+ presentationSurfaceVersion);
}
finally { reader.Depth--; }
}
diff --git a/packages/org.gamecult.eve.surface/package.json b/packages/org.gamecult.eve.surface/package.json
index 378f218..fdbc322 100644
--- a/packages/org.gamecult.eve.surface/package.json
+++ b/packages/org.gamecult.eve.surface/package.json
@@ -1,7 +1,7 @@
{
"name": "org.gamecult.eve.surface",
"displayName": "Eve Surface Contract",
- "version": "0.3.5",
+ "version": "0.3.6",
"unity": "2021.3",
"description": "Renderer-neutral C# contracts and builders for gamecult.eve.surface.v1 documents.",
"dependencies": {
diff --git a/schemas/gamecult.eve.command_receipt.v1.schema.json b/schemas/gamecult.eve.command_receipt.v1.schema.json
index b668e95..d862a90 100644
--- a/schemas/gamecult.eve.command_receipt.v1.schema.json
+++ b/schemas/gamecult.eve.command_receipt.v1.schema.json
@@ -67,7 +67,13 @@
},
"sourceVersion": {
"type": "integer",
- "minimum": 0
+ "minimum": 0,
+ "description": "Provider-state generation that causally owns this result. It is not implicitly an Eve surface version."
+ },
+ "presentationSurfaceVersion": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality."
},
"invocationHash": {
"type": "string",
diff --git a/tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs b/tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs
index be11714..c756359 100644
--- a/tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs
+++ b/tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs
@@ -266,7 +266,8 @@ public sealed class EveSurfaceSerializationCompatibilityTests
"interactive-world",
new[] { "cultnet+tcp://odin.gamecult.example:3076" },
"commander-daemon"),
- "sha256:launch-envelope");
+ "sha256:launch-envelope",
+ presentationSurfaceVersion: 77);
var bytes = MessagePackSerializer.Serialize(document, Options);
var reader = new MessagePackReader(bytes);
@@ -274,7 +275,7 @@ public sealed class EveSurfaceSerializationCompatibilityTests
var restored = MessagePackSerializer.Deserialize(bytes, Options);
Assert.That(reader.NextMessagePackType, Is.EqualTo(MessagePackType.Map));
- Assert.That(reader.ReadMapHeader(), Is.EqualTo(14));
+ Assert.That(reader.ReadMapHeader(), Is.EqualTo(15));
Assert.That(wireJson.RootElement.GetProperty("navigation").ValueKind, Is.EqualTo(JsonValueKind.Object));
Assert.That(restored.Navigation, Is.Not.Null);
Assert.That(restored.Navigation!.VerseId, Is.EqualTo("gamecult.aetheria"));
@@ -283,6 +284,7 @@ public sealed class EveSurfaceSerializationCompatibilityTests
Assert.That(restored.Navigation.SurfaceKind, Is.EqualTo("interactive-world"));
Assert.That(restored.Navigation.RendezvousEndpoints, Is.EqualTo(new[] { "cultnet+tcp://odin.gamecult.example:3076" }));
Assert.That(restored.InvocationHash, Is.EqualTo("sha256:launch-envelope"));
+ Assert.That(restored.PresentationSurfaceVersion, Is.EqualTo(77));
}
[Test]
@@ -322,6 +324,7 @@ public sealed class EveSurfaceSerializationCompatibilityTests
Assert.That(restored.Navigation!.SurfaceId, Is.EqualTo("aetheria.pilot"));
Assert.That(restored.Navigation.AuthorityRuntimeId, Is.Empty);
Assert.That(restored.InvocationHash, Is.Empty);
+ Assert.That(restored.PresentationSurfaceVersion, Is.Zero);
});
}
@@ -349,8 +352,10 @@ public sealed class EveSurfaceSerializationCompatibilityTests
{
Assert.That(wireJson.RootElement.TryGetProperty("navigation", out _), Is.False);
Assert.That(wireJson.RootElement.TryGetProperty("invocationHash", out _), Is.False);
+ Assert.That(wireJson.RootElement.TryGetProperty("presentationSurfaceVersion", out _), Is.False);
Assert.That(restored.Navigation, Is.Null);
Assert.That(restored.InvocationHash, Is.Empty);
+ Assert.That(restored.PresentationSurfaceVersion, Is.Zero);
});
}