From 754be7e5157295a326dc4a1f245d46a95ddbefec Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 17 Aug 2026 21:21:13 +0200 Subject: [PATCH] Consume Eve-owned surface contracts --- TestProject/Packages/manifest.json | 2 +- TestProject/Packages/packages-lock.json | 10 +- .../Directory.Build.props | 7 - .../GameCult.Eve.Surface.csproj | 15 - .../GameCult.Eve.Surface.csproj.meta | 7 - packages/org.gamecult.eve.surface/README.md | 29 - .../org.gamecult.eve.surface/README.md.meta | 7 - .../org.gamecult.eve.surface/Runtime.meta | 8 - .../Runtime/EveAssetCatalogDocument.cs | 144 --- .../Runtime/EveAssetCatalogDocument.cs.meta | 2 - .../Runtime/EveEntitySoaViewDocument.cs | 96 -- .../Runtime/EveEntitySoaViewDocument.cs.meta | 11 - .../Runtime/EveInputCapabilityDocument.cs | 75 -- .../EveInputCapabilityDocument.cs.meta | 2 - .../Runtime/EveInputDeviceLayouts.cs | 55 -- .../Runtime/EveInputDeviceLayouts.cs.meta | 2 - .../Runtime/EveInputGestures.cs | 82 -- .../Runtime/EveInputGestures.cs.meta | 2 - .../Runtime/EveInventoryInteraction.cs | 82 -- .../Runtime/EveInventoryInteraction.cs.meta | 2 - .../Runtime/EveProviderDocuments.cs | 414 --------- .../Runtime/EveProviderDocuments.cs.meta | 2 - .../Runtime/EveSurfaceBuilder.cs | 874 ------------------ .../Runtime/EveSurfaceBuilder.cs.meta | 2 - .../Runtime/EveSurfaceDocument.cs | 538 ----------- .../Runtime/EveSurfaceDocument.cs.meta | 2 - .../Runtime/GameCult.Eve.Surface.asmdef | 21 - .../Runtime/GameCult.Eve.Surface.asmdef.meta | 7 - .../org.gamecult.eve.surface/package.json | 29 - .../package.json.meta | 7 - .../eve-runtime-capability.json | 8 +- .../org.gamecult.eve.unity-scene/package.json | 4 +- .../eve-runtime-capability.json | 6 +- .../package.json | 4 +- scripts/run-package-tests.ps1 | 10 + .../.gitignore | 1 - ...eSurfaceSerializationCompatibilityTests.cs | 262 ------ ...ult.Eve.Surface.Serialization.Tests.csproj | 20 - 38 files changed, 27 insertions(+), 2824 deletions(-) delete mode 100644 packages/org.gamecult.eve.surface/Directory.Build.props delete mode 100644 packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj delete mode 100644 packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj.meta delete mode 100644 packages/org.gamecult.eve.surface/README.md delete mode 100644 packages/org.gamecult.eve.surface/README.md.meta delete mode 100644 packages/org.gamecult.eve.surface/Runtime.meta delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveAssetCatalogDocument.cs delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveAssetCatalogDocument.cs.meta delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveEntitySoaViewDocument.cs delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveEntitySoaViewDocument.cs.meta delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveInputCapabilityDocument.cs delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveInputCapabilityDocument.cs.meta delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveInputDeviceLayouts.cs delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveInputDeviceLayouts.cs.meta delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveInputGestures.cs delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveInputGestures.cs.meta delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveInventoryInteraction.cs delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveInventoryInteraction.cs.meta delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs.meta delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveSurfaceBuilder.cs delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveSurfaceBuilder.cs.meta delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs delete mode 100644 packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs.meta delete mode 100644 packages/org.gamecult.eve.surface/Runtime/GameCult.Eve.Surface.asmdef delete mode 100644 packages/org.gamecult.eve.surface/Runtime/GameCult.Eve.Surface.asmdef.meta delete mode 100644 packages/org.gamecult.eve.surface/package.json delete mode 100644 packages/org.gamecult.eve.surface/package.json.meta delete mode 100644 tests/GameCult.Eve.Surface.Serialization.Tests/.gitignore delete mode 100644 tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs delete mode 100644 tests/GameCult.Eve.Surface.Serialization.Tests/GameCult.Eve.Surface.Serialization.Tests.csproj diff --git a/TestProject/Packages/manifest.json b/TestProject/Packages/manifest.json index 1f31a7a..157057e 100644 --- a/TestProject/Packages/manifest.json +++ b/TestProject/Packages/manifest.json @@ -7,7 +7,7 @@ "com.unity.modules.uielements": "1.0.0", "org.gamecult.cultlib": "file:../../artifacts/test-dependencies/org.gamecult.cultlib", "org.gamecult.eve.plugin-fields": "file:../../../EvePlugins/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields", - "org.gamecult.eve.surface": "file:../../packages/org.gamecult.eve.surface", + "org.gamecult.eve.surface": "file:../../../Eve/packages/org.gamecult.eve.surface", "org.gamecult.eve.unity-scene": "file:../../packages/org.gamecult.eve.unity-scene", "org.gamecult.eve.unity-uitoolkit": "file:../../packages/org.gamecult.eve.unity-uitoolkit" }, diff --git a/TestProject/Packages/packages-lock.json b/TestProject/Packages/packages-lock.json index 7b602ba..8046efd 100644 --- a/TestProject/Packages/packages-lock.json +++ b/TestProject/Packages/packages-lock.json @@ -133,11 +133,11 @@ } }, "org.gamecult.eve.surface": { - "version": "file:../../packages/org.gamecult.eve.surface", + "version": "file:../../../Eve/packages/org.gamecult.eve.surface", "depth": 0, "source": "local", "dependencies": { - "org.gamecult.cultlib": "1.0.8" + "org.gamecult.cultlib": "1.0.43" } }, "org.gamecult.eve.unity-scene": { @@ -147,8 +147,8 @@ "dependencies": { "org.gamecult.cultlib": "1.0.43", "org.gamecult.eve.plugin-fields": "0.2.3", - "org.gamecult.eve.surface": "0.2.4", - "org.gamecult.eve.unity-uitoolkit": "0.1.2", + "org.gamecult.eve.surface": "0.3.0", + "org.gamecult.eve.unity-uitoolkit": "0.1.3", "com.unity.mathematics": "1.3.2", "com.unity.render-pipelines.universal": "17.4.0", "com.unity.modules.particlesystem": "1.0.0" @@ -159,7 +159,7 @@ "depth": 0, "source": "local", "dependencies": { - "org.gamecult.eve.surface": "0.2.4" + "org.gamecult.eve.surface": "0.3.0" } }, "com.unity.modules.assetbundle": { diff --git a/packages/org.gamecult.eve.surface/Directory.Build.props b/packages/org.gamecult.eve.surface/Directory.Build.props deleted file mode 100644 index 994fcb6..0000000 --- a/packages/org.gamecult.eve.surface/Directory.Build.props +++ /dev/null @@ -1,7 +0,0 @@ - - - $(MSBuildThisFileDirectory)bin~\ - $(MSBuildThisFileDirectory)obj~\ - $(MSBuildThisFileDirectory)obj~\ - - diff --git a/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj b/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj deleted file mode 100644 index f07f7e8..0000000 --- a/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - netstandard2.1 - enable - latest - enable - Portable Eve surface and provider contracts. - $(MSBuildThisFileDirectory)..\..\..\CultLib - - - - - - - diff --git a/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj.meta b/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj.meta deleted file mode 100644 index 751910b..0000000 --- a/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: ce2d4913d64690c44ae68935014fd79d -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/packages/org.gamecult.eve.surface/README.md b/packages/org.gamecult.eve.surface/README.md deleted file mode 100644 index eb65c17..0000000 --- a/packages/org.gamecult.eve.surface/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Eve Surface Contract - -This package defines the retained CultUI surface document that every Eve -runtime lowers. - -Components own normal child layout through `Children`, live CultMesh value -bindings through `StateBindings`, and nested synced document regions through -`EmbeddedDocuments`. An embedded document slot names the child document id, -schema, presentation kind, and route hint; renderers resolve that child through -CultMesh instead of rebuilding it with runtime-local projection code. - -See `../../docs/surface-contract-v1.md` for the full contract and -`../../web/fixtures/cultui-embedded-surface.json` for the parity fixture. -Runtime discovery and required feature coverage live in -`../../tools/parity/parity-manifest.json`; active GUI runtimes must list -`embeddedDocuments` as a supported feature and require the `embedded-surface` -fixture. - -Verification entrypoints: - -- Browser/TypeScript: `node --test web\eve-dsl.test.mjs` -- Semantic runtime matrix: `powershell -ExecutionPolicy Bypass -File .\scripts\run-parity-harness.ps1` -- Flutter GUI contract, when Flutter is installed: `flutter test --plain-name embedded_surface_fixture_contract` -- Rust/CultMesh document sync: run `cargo test rust_preserves_cultui_embedded_surface_slots_through_typed_document_sync` from `E:/Projects/CultLib/packages/cultnet-rs` - -The parity manifest is the discovery source for web, Flutter desktop/Linux/Android, -iOS/UIKit, Android/Kotlin, Unity UI Toolkit, and Rust contract coverage. Do not -add a new renderer claim without adding its nested-surface fixture requirement -there. diff --git a/packages/org.gamecult.eve.surface/README.md.meta b/packages/org.gamecult.eve.surface/README.md.meta deleted file mode 100644 index 4bc751a..0000000 --- a/packages/org.gamecult.eve.surface/README.md.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: fe5aa27636bead047b2aecb14fdc59f2 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/packages/org.gamecult.eve.surface/Runtime.meta b/packages/org.gamecult.eve.surface/Runtime.meta deleted file mode 100644 index f150917..0000000 --- a/packages/org.gamecult.eve.surface/Runtime.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2164f6fea1216214d895e7dc99c46ecf -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/packages/org.gamecult.eve.surface/Runtime/EveAssetCatalogDocument.cs b/packages/org.gamecult.eve.surface/Runtime/EveAssetCatalogDocument.cs deleted file mode 100644 index eba3b44..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveAssetCatalogDocument.cs +++ /dev/null @@ -1,144 +0,0 @@ -using System; -using System.Collections.Generic; -using GameCult.Caching; -using MessagePack; - -#nullable enable - -namespace GameCult.Eve.Surface -{ - [CultDocument("gamecult.eve.asset_catalog", SchemaId)] - [MessagePackObject] - public sealed class EveAssetCatalogDocument - { - public const string SchemaId = "gamecult.eve.asset_catalog.v1"; - - [SerializationConstructor] - public EveAssetCatalogDocument( - string schema, - string providerId, - string catalogId, - long version, - string updatedAtUtc, - EveAssetCatalogEntry[] assets) - { - Schema = string.IsNullOrWhiteSpace(schema) ? SchemaId : schema; - ProviderId = providerId ?? ""; - CatalogId = catalogId ?? ""; - Version = version; - UpdatedAtUtc = updatedAtUtc ?? ""; - Assets = assets ?? Array.Empty(); - } - - public EveAssetCatalogDocument( - string providerId, - string catalogId, - long version, - string updatedAtUtc, - EveAssetCatalogEntry[] assets) - : this(SchemaId, providerId, catalogId, version, updatedAtUtc, assets) - { - } - - [Key(0)] public string Schema { get; } - [Key(1)] public string ProviderId { get; } - [Key(2)] public string CatalogId { get; } - [Key(3)] public long Version { get; } - [Key(4)] public string UpdatedAtUtc { get; } - [Key(5)] public EveAssetCatalogEntry[] Assets { get; } - } - - [MessagePackObject] - public sealed class EveAssetCatalogEntry - { - [SerializationConstructor] - public EveAssetCatalogEntry( - string assetRef, - string assetKind, - EveAssetVariant[] variants, - Dictionary metadata) - { - AssetRef = assetRef ?? ""; - AssetKind = assetKind ?? ""; - Variants = variants ?? Array.Empty(); - Metadata = metadata == null - ? new Dictionary(StringComparer.Ordinal) - : new Dictionary(metadata, StringComparer.Ordinal); - } - - public EveAssetCatalogEntry( - string assetRef, - string assetKind, - EveAssetVariant[] variants, - IReadOnlyDictionary? metadata = null) - : this( - assetRef, - assetKind, - variants, - metadata == null ? new Dictionary() : new Dictionary(metadata)) - { - } - - [Key(0)] public string AssetRef { get; } - [Key(1)] public string AssetKind { get; } - [Key(2)] public EveAssetVariant[] Variants { get; } - [Key(3)] public Dictionary Metadata { get; } - } - - [MessagePackObject] - public sealed class EveAssetVariant - { - [SerializationConstructor] - public EveAssetVariant( - string runtimeId, - string platform, - string format, - string uri, - string contentHash, - long sizeBytes, - string assetKey, - Dictionary metadata) - { - RuntimeId = runtimeId ?? ""; - Platform = platform ?? ""; - Format = format ?? ""; - Uri = uri ?? ""; - ContentHash = contentHash ?? ""; - SizeBytes = sizeBytes; - AssetKey = assetKey ?? ""; - Metadata = metadata == null - ? new Dictionary(StringComparer.Ordinal) - : new Dictionary(metadata, StringComparer.Ordinal); - } - - public EveAssetVariant( - string runtimeId, - string platform, - string format, - string uri, - string contentHash, - long sizeBytes, - string assetKey, - IReadOnlyDictionary? metadata = null) - : this( - runtimeId, - platform, - format, - uri, - contentHash, - sizeBytes, - assetKey, - metadata == null ? new Dictionary() : new Dictionary(metadata)) - { - } - - [Key(0)] public string RuntimeId { get; } - [Key(1)] public string Platform { get; } - [Key(2)] public string Format { get; } - [Key(3)] public string Uri { get; } - [Key(4)] public string ContentHash { get; } - [Key(5)] public long SizeBytes { get; } - [Key(6)] public string AssetKey { get; } - [Key(7)] public Dictionary Metadata { get; } - } -} diff --git a/packages/org.gamecult.eve.surface/Runtime/EveAssetCatalogDocument.cs.meta b/packages/org.gamecult.eve.surface/Runtime/EveAssetCatalogDocument.cs.meta deleted file mode 100644 index 0af6487..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveAssetCatalogDocument.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 8f53654f7c98d894588127ba001f11b4 \ No newline at end of file diff --git a/packages/org.gamecult.eve.surface/Runtime/EveEntitySoaViewDocument.cs b/packages/org.gamecult.eve.surface/Runtime/EveEntitySoaViewDocument.cs deleted file mode 100644 index d5148f1..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveEntitySoaViewDocument.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using GameCult.Caching; -using MessagePack; - -#nullable enable - -namespace GameCult.Eve.Surface -{ - [CultDocument("gamecult.eve.entity_soa_view", SchemaId)] - [MessagePackObject] - public sealed class EveEntitySoaViewDocument - { - public const string SchemaId = "gamecult.eve.entity_soa_view.v2"; - - [Key(0)] public string Schema { get; set; } = SchemaId; - [Key(1)] public string ProviderId { get; set; } = ""; - [Key(2)] public string ViewId { get; set; } = ""; - [Key(3)] public string PublishedAtUtc { get; set; } = ""; - [Key(4)] public string BodySchemaId { get; set; } = ""; - [Key(5)] public int LayoutVersion { get; set; } - [Key(6)] public long ProducerEpoch { get; set; } - [Key(7)] public long Sequence { get; set; } - [Key(8)] public int Capacity { get; set; } - [Key(9)] public EveEntitySoaBuffer[] Buffers { get; set; } = Array.Empty(); - [Key(10)] public EveEntitySoaColumn[] Columns { get; set; } = Array.Empty(); - [Key(11)] public EveEntitySoaDirtyRange[] DirtyRanges { get; set; } = Array.Empty(); - [Key(12)] public EveEntityRenderGroup[] RenderGroups { get; set; } = Array.Empty(); - [Key(13)] public EveEntityIdentity[] Identities { get; set; } = Array.Empty(); - [Key(14)] public long FrameId { get; set; } - } - - [MessagePackObject] - public sealed class EveEntitySoaBuffer - { - [Key(0)] public string BufferId { get; set; } = ""; - [Key(1)] public long ByteOffset { get; set; } - [Key(2)] public long ByteLength { get; set; } - } - - [MessagePackObject] - public sealed class EveEntitySoaColumn - { - [Key(0)] public string ColumnId { get; set; } = ""; - [Key(1)] public string Semantic { get; set; } = ""; - [Key(2)] public string BufferId { get; set; } = ""; - [Key(3)] public string ScalarType { get; set; } = ""; - [Key(4)] public long ByteOffset { get; set; } - [Key(5)] public int ElementStride { get; set; } - [Key(6)] public int ElementCount { get; set; } - [Key(7)] public string Unit { get; set; } = ""; - [Key(8)] public string CoordinateSpace { get; set; } = ""; - } - - [MessagePackObject] - public sealed class EveEntitySoaDirtyRange - { - [Key(0)] public string ColumnId { get; set; } = ""; - [Key(1)] public int StartIndex { get; set; } - [Key(2)] public int Count { get; set; } - [Key(3)] public long Sequence { get; set; } - } - - [MessagePackObject] - public sealed class EveEntityIdentity - { - [Key(0)] public int Index { get; set; } - [Key(1)] public string EntityId { get; set; } = ""; - [Key(2)] public string EntityKind { get; set; } = ""; - [Key(3)] public string Label { get; set; } = ""; - [Key(4)] public string Faction { get; set; } = ""; - [Key(5)] public bool Selectable { get; set; } - [Key(6)] public bool Controllable { get; set; } - [Key(7)] public string AssetRef { get; set; } = ""; - } - - [MessagePackObject] - public sealed class EveEntityRenderGroup - { - [Key(0)] public int GroupId { get; set; } - [Key(1)] public string MeshAssetRef { get; set; } = ""; - [Key(2)] public string MaterialAssetRef { get; set; } = ""; - [Key(3)] public int SubMeshIndex { get; set; } - [Key(4)] public int Layer { get; set; } - [Key(5)] public int InstanceCount { get; set; } - [Key(6)] public float DefaultScale { get; set; } = 1f; - [Key(7)] public float BoundsCenterX { get; set; } - [Key(8)] public float BoundsCenterY { get; set; } - [Key(9)] public float BoundsCenterZ { get; set; } - [Key(10)] public float BoundsSizeX { get; set; } - [Key(11)] public float BoundsSizeY { get; set; } - [Key(12)] public float BoundsSizeZ { get; set; } - [Key(13)] public string ShadowMode { get; set; } = "on"; - [Key(14)] public bool ReceiveShadows { get; set; } = true; - [Key(15)] public int Lod { get; set; } = -1; - } -} diff --git a/packages/org.gamecult.eve.surface/Runtime/EveEntitySoaViewDocument.cs.meta b/packages/org.gamecult.eve.surface/Runtime/EveEntitySoaViewDocument.cs.meta deleted file mode 100644 index b2882e9..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveEntitySoaViewDocument.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8e87e1be783846508efea45787f2d45c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/packages/org.gamecult.eve.surface/Runtime/EveInputCapabilityDocument.cs b/packages/org.gamecult.eve.surface/Runtime/EveInputCapabilityDocument.cs deleted file mode 100644 index ed8b486..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveInputCapabilityDocument.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections.Generic; -using GameCult.Caching; -using MessagePack; - -namespace GameCult.Eve.Surface -{ - [CultDocument("gamecult.eve.input_capability", SchemaId)] - [MessagePackObject] - public sealed class EveInputCapabilityDocument - { - public const string SchemaId = "gamecult.eve.input_capability.v1"; - [Key(0)] public string Schema { get; set; } = SchemaId; - [Key(1)] public string ProviderId { get; set; } = ""; - [Key(2)] public string CapabilityId { get; set; } = ""; - [Key(3)] public long Version { get; set; } - [Key(4)] public EveInputActionDocument[] Actions { get; set; } = Array.Empty(); - [Key(5)] public EveInputProfileDocument[] DefaultProfiles { get; set; } = Array.Empty(); - } - - [MessagePackObject] - public sealed class EveInputActionDocument - { - [Key(0)] public string ActionId { get; set; } = ""; - [Key(1)] public string Label { get; set; } = ""; - [Key(2)] public string Operation { get; set; } = ""; - [Key(3)] public string Context { get; set; } = "pilot"; - [Key(4)] public string Category { get; set; } = "ship"; - [Key(5)] public string Availability { get; set; } = "available"; - [Key(6)] public string SourceRef { get; set; } = ""; - [Key(7)] public Dictionary Payload { get; set; } = new Dictionary(StringComparer.Ordinal); - [Key(8)] public EveInputValueDocument? InputValue { get; set; } - [Key(9)] public string IconRef { get; set; } = ""; - [Key(10)] public bool ActionBar { get; set; } - } - - [MessagePackObject] - public sealed class EveInputValueDocument - { - [Key(0)] public string Model { get; set; } = ""; - [Key(1)] public string PayloadKey { get; set; } = ""; - [Key(2)] public string[] PayloadKeys { get; set; } = Array.Empty(); - [Key(3)] public double? CurrentValue { get; set; } - [Key(4)] public double? MinimumValue { get; set; } - [Key(5)] public double? MaximumValue { get; set; } - [Key(6)] public double? StepValue { get; set; } - [Key(7)] public string Unit { get; set; } = ""; - } - - [MessagePackObject] - public sealed class EveInputProfileDocument - { - [Key(0)] public string ProfileId { get; set; } = ""; - [Key(1)] public string DeviceClass { get; set; } = ""; - [Key(2)] public EveInputBindingDocument[] Bindings { get; set; } = Array.Empty(); - } - - [MessagePackObject] - public sealed class EveInputBindingDocument - { - [Key(0)] public string BindingId { get; set; } = ""; - [Key(1)] public string ActionId { get; set; } = ""; - [Key(2)] public EveInputGestureDocument Gesture { get; set; } = new EveInputGestureDocument(); - [Key(3)] public bool ActionBar { get; set; } - } - - [MessagePackObject] - public sealed class EveInputGestureDocument - { - [Key(0)] public string Kind { get; set; } = "direct"; - [Key(1)] public string[] Controls { get; set; } = Array.Empty(); - [Key(2)] public int MaxStepIntervalMs { get; set; } = 650; - [Key(3)] public string CompletionControl { get; set; } = ""; - } -} diff --git a/packages/org.gamecult.eve.surface/Runtime/EveInputCapabilityDocument.cs.meta b/packages/org.gamecult.eve.surface/Runtime/EveInputCapabilityDocument.cs.meta deleted file mode 100644 index f13f766..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveInputCapabilityDocument.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 4c297c7dbb64a0f49a7f805e770c5e55 diff --git a/packages/org.gamecult.eve.surface/Runtime/EveInputDeviceLayouts.cs b/packages/org.gamecult.eve.surface/Runtime/EveInputDeviceLayouts.cs deleted file mode 100644 index 35425a3..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveInputDeviceLayouts.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace GameCult.Eve.Surface -{ - public sealed class EveInputDeviceLayout - { - public string LayoutId { get; set; } = ""; - public string DeviceClass { get; set; } = ""; - public IReadOnlyList Controls { get; set; } = Array.Empty(); - public bool SupportsDirectionalStrings { get; set; } - - public static EveInputDeviceLayout AnsiKeyboardMouse() => new EveInputDeviceLayout - { - LayoutId = "keyboard.ansi-104+mouse.standard", - DeviceClass = "keyboard-mouse", - Controls = new[] - { - Key("keyboard.escape", "Esc", 0, 0, 1.25f), Key("keyboard.f1", "F1", 2, 0), Key("keyboard.f2", "F2", 3, 0), - Key("keyboard.1", "1", 1, 1), Key("keyboard.2", "2", 2, 1), Key("keyboard.3", "3", 3, 1), Key("keyboard.4", "4", 4, 1), Key("keyboard.5", "5", 5, 1), - Key("keyboard.tab", "Tab", 0, 2, 1.5f), Key("keyboard.q", "Q", 1.5f, 2), Key("keyboard.w", "W", 2.5f, 2), Key("keyboard.e", "E", 3.5f, 2), Key("keyboard.r", "R", 4.5f, 2), - Key("keyboard.a", "A", 1.75f, 3), Key("keyboard.s", "S", 2.75f, 3), Key("keyboard.d", "D", 3.75f, 3), Key("keyboard.f", "F", 4.75f, 3), - Key("keyboard.leftShift", "Shift", 0, 4, 2.25f), Key("keyboard.space", "Space", 3.75f, 5, 6.25f), - Key("mouse.primary", "Mouse 1", 18, 1), Key("mouse.secondary", "Mouse 2", 19, 1), Key("mouse.middle", "Mouse 3", 18.5f, 2) - } - }; - - public static EveInputDeviceLayout StandardGamepad() => new EveInputDeviceLayout - { - LayoutId = "gamepad.standard", - DeviceClass = "gamepad", - SupportsDirectionalStrings = true, - Controls = new[] - { - Key("gamepad.leftStick", "Left Stick", 2, 3, 2), Key("gamepad.rightStick", "Right Stick", 8, 4, 2), - Key("gamepad.dpad.up", "Up", 1, 1), Key("gamepad.dpad.left", "Left", 0, 2), Key("gamepad.dpad.right", "Right", 2, 2), Key("gamepad.dpad.down", "Down", 1, 3), - Key("gamepad.buttonSouth", "A / Cross", 10, 3), Key("gamepad.buttonEast", "B / Circle", 11, 2), Key("gamepad.buttonWest", "X / Square", 9, 2), Key("gamepad.buttonNorth", "Y / Triangle", 10, 1), - Key("gamepad.leftTrigger", "LT / L2", 2, 0, 2), Key("gamepad.rightTrigger", "RT / R2", 9, 0, 2) - } - }; - - private static EveInputLayoutControl Key(string id, string label, float x, float y, float width = 1) => - new EveInputLayoutControl { Control = id, Label = label, X = x, Y = y, Width = width, Height = 1 }; - } - - public sealed class EveInputLayoutControl - { - public string Control { get; set; } = ""; - public string Label { get; set; } = ""; - public float X { get; set; } - public float Y { get; set; } - public float Width { get; set; } = 1; - public float Height { get; set; } = 1; - } -} diff --git a/packages/org.gamecult.eve.surface/Runtime/EveInputDeviceLayouts.cs.meta b/packages/org.gamecult.eve.surface/Runtime/EveInputDeviceLayouts.cs.meta deleted file mode 100644 index 0d7a9a2..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveInputDeviceLayouts.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 8a2a1258551e42a9831a3e4f9483d928 diff --git a/packages/org.gamecult.eve.surface/Runtime/EveInputGestures.cs b/packages/org.gamecult.eve.surface/Runtime/EveInputGestures.cs deleted file mode 100644 index a318066..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveInputGestures.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace GameCult.Eve.Surface -{ - public sealed class EveInputGesture - { - public string Kind { get; set; } = "direct"; - public IReadOnlyList Controls { get; set; } = Array.Empty(); - public int MaxStepIntervalMs { get; set; } = 650; - public string CompletionControl { get; set; } = ""; - } - - public sealed class EveInputBinding - { - public string BindingId { get; set; } = ""; - public string ActionId { get; set; } = ""; - public EveInputGesture Gesture { get; set; } = new EveInputGesture(); - public bool ActionBar { get; set; } - } - - public sealed class EveInputGestureResolver - { - private readonly IReadOnlyList _bindings; - private readonly HashSet _pressed = new HashSet(StringComparer.Ordinal); - private readonly Dictionary _sequences = new Dictionary(StringComparer.Ordinal); - - public EveInputGestureResolver(IEnumerable bindings) - { - _bindings = (bindings ?? Array.Empty()).Where(binding => binding != null).ToArray(); - } - - public IReadOnlyList Press(string control, long timestampMs) - { - _pressed.Add(control ?? ""); - var actions = new HashSet(StringComparer.Ordinal); - foreach (var binding in _bindings) - { - var gesture = binding.Gesture ?? new EveInputGesture(); - if (gesture.Kind == "direct" && gesture.Controls.FirstOrDefault() == control) - actions.Add(binding.ActionId); - else if (gesture.Kind == "chord" && gesture.Controls.Count > 0 && gesture.Controls.All(_pressed.Contains)) - actions.Add(binding.ActionId); - else if (gesture.Kind == "sequence" && Advance(binding, control ?? "", timestampMs)) - actions.Add(binding.ActionId); - } - return actions.ToArray(); - } - - public void Release(string control) => _pressed.Remove(control ?? ""); - - public void Reset() - { - _pressed.Clear(); - _sequences.Clear(); - } - - private bool Advance(EveInputBinding binding, string control, long timestampMs) - { - var controls = binding.Gesture.Controls; - if (controls.Count == 0) return false; - _sequences.TryGetValue(binding.BindingId, out var previous); - var index = previous.Index > 0 && timestampMs - previous.TimestampMs <= Math.Max(50, binding.Gesture.MaxStepIntervalMs) ? previous.Index : 0; - var next = controls[index] == control ? index + 1 : controls[0] == control ? 1 : 0; - if (next == controls.Count) - { - _sequences.Remove(binding.BindingId); - return string.IsNullOrWhiteSpace(binding.Gesture.CompletionControl); - } - _sequences[binding.BindingId] = new SequenceState(next, timestampMs); - return false; - } - - private readonly struct SequenceState - { - public SequenceState(int index, long timestampMs) { Index = index; TimestampMs = timestampMs; } - public int Index { get; } - public long TimestampMs { get; } - } - } -} diff --git a/packages/org.gamecult.eve.surface/Runtime/EveInputGestures.cs.meta b/packages/org.gamecult.eve.surface/Runtime/EveInputGestures.cs.meta deleted file mode 100644 index 3abaaab..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveInputGestures.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: e3c2941be243a754092ac2543d1e6bf7 \ No newline at end of file diff --git a/packages/org.gamecult.eve.surface/Runtime/EveInventoryInteraction.cs b/packages/org.gamecult.eve.surface/Runtime/EveInventoryInteraction.cs deleted file mode 100644 index c8c53e9..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveInventoryInteraction.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using GameCult.Mesh; - -#nullable enable - -namespace GameCult.Eve.Surface -{ - public static class EveInventoryInteraction - { - public const string GridKind = "inventory.grid"; - public const string ItemKind = "inventory.item"; - public const string DragSessionKind = "inventory.drag_session"; - - public static bool TryCreateDropRequest( - EveSurfaceDocument document, - EveSurfaceComponent source, - EveSurfaceComponent target, - int destinationX, - int destinationY, - string clientId, - out EveSurfaceCommandRequest? request) - { - request = null; - if (document == null || source == null || target == null || - !string.Equals(source.Kind, ItemKind, StringComparison.Ordinal) || - !string.Equals(target.Kind, GridKind, StringComparison.Ordinal)) - { - return false; - } - - var sourceKind = source.GetProp("sourceKind", source.GetProp("source")); - var command = target.GetProp($"dropCommand.{sourceKind}", target.GetProp("dropCommand")); - if (string.IsNullOrWhiteSpace(sourceKind) || string.IsNullOrWhiteSpace(command)) - return false; - - var sourceIndex = Int(source.GetProp("sourceIndex"), -1); - var targetIndex = Int(target.GetProp("targetIndex"), -1); - var targetKind = target.GetProp("targetKind"); - var payload = new Dictionary(StringComparer.Ordinal) - { - ["sourceKind"] = sourceKind, - ["originEntityKey"] = source.GetProp("sourceEntityKey", source.GetProp("entityKey")), - ["originIndex"] = sourceIndex.ToString(CultureInfo.InvariantCulture), - ["originCargoIndex"] = (string.Equals(sourceKind, "cargo", StringComparison.Ordinal) ? sourceIndex : -1) - .ToString(CultureInfo.InvariantCulture), - ["itemKey"] = source.GetProp("itemKey"), - ["quantity"] = Math.Max(1, Int(source.GetProp("quantity"), 1)).ToString(CultureInfo.InvariantCulture), - ["sourceX"] = Int(source.GetProp("x"), int.MinValue).ToString(CultureInfo.InvariantCulture), - ["sourceY"] = Int(source.GetProp("y"), int.MinValue).ToString(CultureInfo.InvariantCulture), - ["destinationKind"] = targetKind, - ["destinationEntityKey"] = target.GetProp("targetEntityKey", target.GetProp("entityKey")), - ["destinationIndex"] = targetIndex.ToString(CultureInfo.InvariantCulture), - ["destinationCargoIndex"] = (string.Equals(targetKind, "cargo", StringComparison.Ordinal) ? targetIndex : -1) - .ToString(CultureInfo.InvariantCulture), - ["destinationX"] = destinationX.ToString(CultureInfo.InvariantCulture), - ["destinationY"] = destinationY.ToString(CultureInfo.InvariantCulture), - ["hasDestinationPosition"] = "true" - }; - var template = document.Commands.FirstOrDefault(candidate => - string.Equals(candidate.Command, command, StringComparison.Ordinal)); - var operation = template == null - ? CultMesh.OperationInvocation(command) - : CultMesh.OperationInvocation(template.Operation); - request = new EveSurfaceCommandRequest( - document.ProviderId, - document.Surface.Id, - operation, - CultMesh.OperationPayload(payload), - DateTimeOffset.UtcNow, - string.IsNullOrWhiteSpace(clientId) ? "unity-uitoolkit" : clientId); - return true; - } - - private static int Int(string value, int fallback) => - int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsed) - ? parsed - : fallback; - } -} diff --git a/packages/org.gamecult.eve.surface/Runtime/EveInventoryInteraction.cs.meta b/packages/org.gamecult.eve.surface/Runtime/EveInventoryInteraction.cs.meta deleted file mode 100644 index 57cb330..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveInventoryInteraction.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 17fd4173e6e44b4b9c503d343021ffcb diff --git a/packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs b/packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs deleted file mode 100644 index a52d436..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs +++ /dev/null @@ -1,414 +0,0 @@ -using System; -using System.Collections.Generic; -using GameCult.Caching; -using MessagePack; -using MessagePack.Formatters; - -#nullable enable - -namespace GameCult.Eve.Surface -{ - [CultDocument("gamecult.eve.provider_advertisement", SchemaId)] - [MessagePackObject] - [MessagePackFormatter(typeof(EveProviderAdvertisementCompatibilityFormatter))] - public sealed class EveProviderAdvertisementDocument - { - public const string SchemaId = "gamecult.eve.provider_advertisement.v1"; - - public EveProviderAdvertisementDocument( - string providerId, - string serviceId, - string verseId, - string title, - string kind, - string cultMeshAddress, - string updatedAtUtc, - EveProviderFreshness freshness, - IReadOnlyList schemas, - IReadOnlyList witnesses, - IReadOnlyList surfaces, - IReadOnlyList commands, - IReadOnlyList? authorizedBodyProducerIds = null) - : this(SchemaId, providerId, serviceId, verseId, title, kind, cultMeshAddress, updatedAtUtc, freshness, schemas, witnesses, surfaces, commands, authorizedBodyProducerIds) - { - } - - [SerializationConstructor] - public EveProviderAdvertisementDocument( - string schema, - string providerId, - string serviceId, - string verseId, - string title, - string kind, - string cultMeshAddress, - string updatedAtUtc, - EveProviderFreshness freshness, - IReadOnlyList schemas, - IReadOnlyList witnesses, - IReadOnlyList surfaces, - IReadOnlyList commands, - IReadOnlyList? authorizedBodyProducerIds = null) - { - Schema = string.IsNullOrWhiteSpace(schema) ? SchemaId : schema; - ProviderId = providerId ?? ""; - ServiceId = serviceId ?? ""; - VerseId = verseId ?? ""; - Title = title ?? ""; - Kind = kind ?? ""; - CultMeshAddress = cultMeshAddress ?? ""; - UpdatedAtUtc = updatedAtUtc ?? ""; - Freshness = freshness ?? new EveProviderFreshness("unknown", "", 0); - Schemas = schemas ?? Array.Empty(); - Witnesses = witnesses ?? Array.Empty(); - Surfaces = surfaces ?? Array.Empty(); - Commands = commands ?? Array.Empty(); - AuthorizedBodyProducerIds = authorizedBodyProducerIds ?? Array.Empty(); - } - - [Key(0)] public string Schema { get; } - [Key(1)] public string ProviderId { get; } - [Key(2)] public string ServiceId { get; } - [Key(3)] public string VerseId { get; } - [Key(4)] public string Title { get; } - [Key(5)] public string Kind { get; } - [Key(6)] public string CultMeshAddress { get; } - [Key(7)] public string UpdatedAtUtc { get; } - [Key(8)] public EveProviderFreshness Freshness { get; } - [Key(9)] public IReadOnlyList Schemas { get; } - [Key(10)] public IReadOnlyList Witnesses { get; } - [Key(11)] public IReadOnlyList Surfaces { get; } - [Key(12)] public IReadOnlyList Commands { get; } - [Key(13)] public IReadOnlyList AuthorizedBodyProducerIds { get; } - } - - /// - /// Reads canonical provider advertisements and the original Aetheria-expanded v1 layout. - /// - public sealed class EveProviderAdvertisementCompatibilityFormatter : - IMessagePackFormatter - { - private const int CurrentFieldCount = 14; - private const int LegacyFieldCount = 16; - - public void Serialize( - ref MessagePackWriter writer, - EveProviderAdvertisementDocument? value, - MessagePackSerializerOptions options) - { - if (value == null) { writer.WriteNil(); return; } - writer.WriteArrayHeader(CurrentFieldCount); - writer.Write(value.Schema); - writer.Write(value.ProviderId); - writer.Write(value.ServiceId); - writer.Write(value.VerseId); - writer.Write(value.Title); - writer.Write(value.Kind); - writer.Write(value.CultMeshAddress); - writer.Write(value.UpdatedAtUtc); - Formatter(options).Serialize(ref writer, value.Freshness, options); - Formatter>(options).Serialize(ref writer, value.Schemas, options); - Formatter>(options).Serialize(ref writer, value.Witnesses, options); - Formatter>(options).Serialize(ref writer, value.Surfaces, options); - Formatter>(options).Serialize(ref writer, value.Commands, options); - Formatter>(options).Serialize(ref writer, value.AuthorizedBodyProducerIds, options); - } - - public EveProviderAdvertisementDocument? Deserialize( - ref MessagePackReader reader, - MessagePackSerializerOptions options) - { - if (reader.TryReadNil()) return null; - if (reader.NextMessagePackType != MessagePackType.Array) - throw new MessagePackSerializationException("Eve provider advertisement must be an array."); - - options.Security.DepthStep(ref reader); - try - { - var fields = reader.ReadArrayHeader(); - if (fields == LegacyFieldCount) - return ReadLegacy(ref reader, options); - - var schema = ReadString(ref reader, fields, 0); - var providerId = ReadString(ref reader, fields, 1); - var serviceId = ReadString(ref reader, fields, 2); - var verseId = ReadString(ref reader, fields, 3); - var title = ReadString(ref reader, fields, 4); - var kind = ReadString(ref reader, fields, 5); - var address = ReadString(ref reader, fields, 6); - var updatedAtUtc = ReadString(ref reader, fields, 7); - var freshness = fields > 8 ? Formatter(options).Deserialize(ref reader, options) : null; - var schemas = fields > 9 ? Formatter>(options).Deserialize(ref reader, options) : null; - var witnesses = fields > 10 ? Formatter>(options).Deserialize(ref reader, options) : null; - var surfaces = fields > 11 ? Formatter>(options).Deserialize(ref reader, options) : null; - var commands = fields > 12 ? Formatter>(options).Deserialize(ref reader, options) : null; - var authorizedBodyProducerIds = fields > 13 ? Formatter>(options).Deserialize(ref reader, options) : null; - for (var index = CurrentFieldCount; index < fields; index++) reader.Skip(); - return new EveProviderAdvertisementDocument( - schema, providerId, serviceId, verseId, title, kind, address, updatedAtUtc, - freshness ?? new EveProviderFreshness("unknown", "", 0), - schemas ?? Array.Empty(), - witnesses ?? Array.Empty(), - surfaces ?? Array.Empty(), - commands ?? Array.Empty(), - authorizedBodyProducerIds ?? Array.Empty()); - } - finally { reader.Depth--; } - } - - private static EveProviderAdvertisementDocument ReadLegacy( - ref MessagePackReader reader, - MessagePackSerializerOptions options) - { - var schema = ReadString(ref reader); - var providerId = ReadString(ref reader); - var serviceId = ReadString(ref reader); - var verseId = ReadString(ref reader); - reader.Skip(); // RootVerse remains provider-owned settings, not portable advertisement state. - reader.Skip(); // CanonicalService - reader.Skip(); // LocatedService - var address = ReadString(ref reader); - var title = ReadString(ref reader); - var kind = ReadString(ref reader); - var updatedAtUtc = ReadString(ref reader); - var freshness = Formatter(options).Deserialize(ref reader, options) - ?? new EveProviderFreshness("unknown", "", 0); - var schemas = Formatter>(options).Deserialize(ref reader, options) - ?? Array.Empty(); - var witnesses = Formatter>(options).Deserialize(ref reader, options) - ?? Array.Empty(); - var surfaces = ReadLegacySurfaces(ref reader); - var commands = ReadLegacyCommands(ref reader); - return new EveProviderAdvertisementDocument( - schema, providerId, serviceId, verseId, title, kind, address, updatedAtUtc, - freshness, schemas, witnesses, surfaces, commands); - } - - private static EveAdvertisedSurface[] ReadLegacySurfaces(ref MessagePackReader reader) - { - var count = reader.ReadArrayHeader(); - var values = new EveAdvertisedSurface[count]; - for (var index = 0; index < count; index++) - { - var fields = reader.ReadArrayHeader(); - var schema = ReadString(ref reader, fields, 0); - var surfaceId = ReadString(ref reader, fields, 1); - var recordRef = ReadString(ref reader, fields, 2); - var transport = ReadString(ref reader, fields, 3); - var status = ReadString(ref reader, fields, 4); - for (var field = 5; field < fields; field++) reader.Skip(); - values[index] = new EveAdvertisedSurface( - surfaceId, schema, recordRef, transport, status, "", null); - } - return values; - } - - private static EveAdvertisedCommand[] ReadLegacyCommands(ref MessagePackReader reader) - { - var count = reader.ReadArrayHeader(); - var values = new EveAdvertisedCommand[count]; - for (var index = 0; index < count; index++) - { - var fields = reader.ReadArrayHeader(); - var command = ReadString(ref reader, fields, 0); - var transport = ReadString(ref reader, fields, 1); - var summary = ReadString(ref reader, fields, 2); - for (var field = 3; field < fields; field++) reader.Skip(); - values[index] = new EveAdvertisedCommand(command, "", transport, summary); - } - return values; - } - - private static IMessagePackFormatter Formatter(MessagePackSerializerOptions options) => - options.Resolver.GetFormatter() - ?? throw new MessagePackSerializationException($"No formatter is registered for {typeof(T).FullName}."); - - private static string ReadString(ref MessagePackReader reader) => reader.ReadString() ?? ""; - private static string ReadString(ref MessagePackReader reader, int fields, int index) => - index < fields ? ReadString(ref reader) : ""; - } - - - [MessagePackObject] - public sealed class EveProviderFreshness - { - [SerializationConstructor] - public EveProviderFreshness(string state, string lastSeenAtUtc, long maxAgeMs) - { - State = state ?? ""; - LastSeenAtUtc = lastSeenAtUtc ?? ""; - MaxAgeMs = maxAgeMs; - } - - [Key(0)] public string State { get; } - [Key(1)] public string LastSeenAtUtc { get; } - [Key(2)] public long MaxAgeMs { get; } - } - - [MessagePackObject] - public sealed class EveProviderWitness - { - [SerializationConstructor] - public EveProviderWitness(string kind, string reference, string summary) - { - Kind = kind ?? ""; - Reference = reference ?? ""; - Summary = summary ?? ""; - } - - [Key(0)] public string Kind { get; } - [Key(1)] public string Reference { get; } - [Key(2)] public string Summary { get; } - } - - [MessagePackObject] - public sealed class EveAdvertisedSurface - { - [SerializationConstructor] - public EveAdvertisedSurface( - string surfaceId, - string schema, - string recordRef, - string transport, - string status, - string surfaceKind, - EveWorldInteractionAdvertisement? worldInteraction = null) - { - SurfaceId = surfaceId ?? ""; - Schema = schema ?? ""; - RecordRef = recordRef ?? ""; - Transport = transport ?? ""; - Status = status ?? ""; - SurfaceKind = surfaceKind ?? ""; - WorldInteraction = worldInteraction; - } - - [Key(0)] public string SurfaceId { get; } - [Key(1)] public string Schema { get; } - [Key(2)] public string RecordRef { get; } - [Key(3)] public string Transport { get; } - [Key(4)] public string Status { get; } - [Key(5)] public string SurfaceKind { get; } - [Key(6)] public EveWorldInteractionAdvertisement? WorldInteraction { get; } - } - - [MessagePackObject] - public sealed class EveWorldInteractionAdvertisement - { - [SerializationConstructor] - public EveWorldInteractionAdvertisement( - string projectionKind, - IReadOnlyList stateSchemas, - string commandBoundary, - string commandRecordRef, - string receiptSchema, - string receiptRecordRef, - string assetManifestRecordRef, - IReadOnlyList loweringTargets, - string ownership) - { - ProjectionKind = projectionKind ?? ""; - StateSchemas = stateSchemas ?? Array.Empty(); - CommandBoundary = commandBoundary ?? ""; - CommandRecordRef = commandRecordRef ?? ""; - ReceiptSchema = receiptSchema ?? ""; - ReceiptRecordRef = receiptRecordRef ?? ""; - AssetManifestRecordRef = assetManifestRecordRef ?? ""; - LoweringTargets = loweringTargets ?? Array.Empty(); - Ownership = ownership ?? ""; - } - - [Key(0)] public string ProjectionKind { get; } - [Key(1)] public IReadOnlyList StateSchemas { get; } - [Key(2)] public string CommandBoundary { get; } - [Key(3)] public string CommandRecordRef { get; } - [Key(4)] public string ReceiptSchema { get; } - [Key(5)] public string ReceiptRecordRef { get; } - [Key(6)] public string AssetManifestRecordRef { get; } - [Key(7)] public IReadOnlyList LoweringTargets { get; } - [Key(8)] public string Ownership { get; } - } - - [MessagePackObject] - public sealed class EveAdvertisedCommand - { - [SerializationConstructor] - public EveAdvertisedCommand(string command, string surfaceId, string transport, string summary) - { - Command = command ?? ""; - SurfaceId = surfaceId ?? ""; - Transport = transport ?? ""; - Summary = summary ?? ""; - } - - [Key(0)] public string Command { get; } - [Key(1)] public string SurfaceId { get; } - [Key(2)] public string Transport { get; } - [Key(3)] public string Summary { get; } - } - - [CultDocument("gamecult.eve.command_receipt", SchemaId)] - [MessagePackObject] - public sealed class EveCommandReceiptDocument - { - public const string SchemaId = "gamecult.eve.command_receipt.v1"; - - public EveCommandReceiptDocument( - string receiptId, - string commandId, - string command, - string state, - string ownerRepo, - string authority, - string providerId, - string surfaceId, - string message, - string issuedAtUtc, - long sourceVersion) - : this(SchemaId, receiptId, commandId, command, state, ownerRepo, authority, providerId, surfaceId, message, issuedAtUtc, sourceVersion) - { - } - - [SerializationConstructor] - public EveCommandReceiptDocument( - string schema, - string receiptId, - string commandId, - string command, - string state, - string ownerRepo, - string authority, - string providerId, - string surfaceId, - string message, - string issuedAtUtc, - long sourceVersion) - { - Schema = string.IsNullOrWhiteSpace(schema) ? SchemaId : schema; - ReceiptId = receiptId ?? ""; - CommandId = commandId ?? ""; - Command = command ?? ""; - State = state ?? ""; - OwnerRepo = ownerRepo ?? ""; - Authority = authority ?? ""; - ProviderId = providerId ?? ""; - SurfaceId = surfaceId ?? ""; - Message = message ?? ""; - IssuedAtUtc = issuedAtUtc ?? ""; - SourceVersion = sourceVersion; - } - - [Key(0)] public string Schema { get; } - [Key(1)] public string ReceiptId { get; } - [Key(2)] public string CommandId { get; } - [Key(3)] public string Command { get; } - [Key(4)] public string State { get; } - [Key(5)] public string OwnerRepo { get; } - [Key(6)] public string Authority { get; } - [Key(7)] public string ProviderId { get; } - [Key(8)] public string SurfaceId { get; } - [Key(9)] public string Message { get; } - [Key(10)] public string IssuedAtUtc { get; } - [Key(11)] public long SourceVersion { get; } - } -} diff --git a/packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs.meta b/packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs.meta deleted file mode 100644 index f29c875..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveProviderDocuments.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: f7ea0cd07c4d5da4099b5acf8d44ca2e \ No newline at end of file diff --git a/packages/org.gamecult.eve.surface/Runtime/EveSurfaceBuilder.cs b/packages/org.gamecult.eve.surface/Runtime/EveSurfaceBuilder.cs deleted file mode 100644 index 2d88eb5..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveSurfaceBuilder.cs +++ /dev/null @@ -1,874 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using GameCult.Mesh; - -#nullable enable - -namespace GameCult.Eve.Surface -{ - /// - /// Fluent CultUI/Eve surface builder. Eve owns the surface document; CultMesh only supplies typed binding descriptors. - /// - public sealed class EveSurfaceBuilder - { - private readonly string _surfaceId; - private readonly List _children = new(); - private readonly List _styles = new(); - private readonly List _commands = new(); - private EveSurfaceComponent? _root; - private long _version = 1; - private string _providerId = "gamecult"; - private string _providerKind = "cultui.surface"; - private string _title = ""; - private string _updatedAtUtc = ""; - - public EveSurfaceBuilder(string surfaceId) - { - _surfaceId = RequireNonEmpty(surfaceId, nameof(surfaceId)); - } - - public EveSurfaceBuilder Provider(string providerId, string providerKind) - { - _providerId = providerId ?? ""; - _providerKind = providerKind ?? ""; - return this; - } - - public EveSurfaceBuilder Title(string title) - { - _title = title ?? ""; - _children.Add(Text($"{_surfaceId}.title", _title, "text.title")); - return this; - } - - public EveSurfaceBuilder TitleSubtitle(string title, string subtitle) - { - _title = string.IsNullOrWhiteSpace(subtitle) ? title ?? "" : $"{title} {subtitle}"; - _children.Add(Text($"{_surfaceId}.title", title ?? "", "text.title")); - _children.Add(Text($"{_surfaceId}.subtitle", subtitle ?? "", "text.subtitle")); - return this; - } - - public EveSurfaceBuilder Text(string text, string? id = null) - { - _children.Add(Text(id ?? $"{_surfaceId}.text.{_children.Count}", text, "text")); - return this; - } - - public EveSurfaceBuilder Button(string label, string command) - { - var operation = CultMesh.OperationBinding(command, label); - _commands.Add(new EveCommandTemplate(operation)); - _children.Add(ButtonComponent($"{_surfaceId}.button.{Slug(label)}", label, operation)); - return this; - } - - public EveSurfaceBuilder Button(string label, CultMeshOperationBindingDescriptor operation) - { - if (operation == null) throw new ArgumentNullException(nameof(operation)); - _commands.Add(new EveCommandTemplate(operation)); - _children.Add(ButtonComponent($"{_surfaceId}.button.{Slug(label)}", label, operation)); - return this; - } - - public EveSurfaceBuilder ButtonColumn(string id, Action build) - { - return Group(id, "column", build); - } - - public EveSurfaceBuilder ButtonRow(string id, Action build) - { - return Group(id, "row", build); - } - - public EveSurfaceBuilder Form(string id, Action build) - { - if (build == null) throw new ArgumentNullException(nameof(build)); - var form = new EveSurfaceFormBuilder(id, AddCommand); - build(form); - _children.Add(form.Build()); - return this; - } - - public EveSurfaceBuilder RootColumn(string id, Action build) - { - _root = BuildContainer(id, "partition", Props(("split", "y")), build); - return this; - } - - public EveSurfaceBuilder RootRow(string id, Action build) - { - _root = BuildContainer(id, "partition", Props(("split", "x")), build); - return this; - } - - public EveSurfaceBuilder RootGrid( - string id, - int columns, - int rows, - Action build) - { - _root = BuildContainer( - id, - "grid", - Props( - ("columns", columns.ToString(System.Globalization.CultureInfo.InvariantCulture)), - ("rows", rows.ToString(System.Globalization.CultureInfo.InvariantCulture))), - build); - return this; - } - - public EveSurfaceBuilder Row(string id, Action build) - { - _children.Add(BuildContainer(id, "partition", Props(("split", "x")), build)); - return this; - } - - public EveSurfaceBuilder Column(string id, Action build) - { - _children.Add(BuildContainer(id, "partition", Props(("split", "y")), build)); - return this; - } - - public EveSurfaceBuilder Grid(string id, int columns, int rows, Action build) - { - _children.Add(BuildContainer( - id, - "grid", - Props( - ("columns", columns.ToString(System.Globalization.CultureInfo.InvariantCulture)), - ("rows", rows.ToString(System.Globalization.CultureInfo.InvariantCulture))), - build)); - return this; - } - - public EveSurfaceBuilder Modal(string id, string title, Action build) - { - _children.Add(BuildContainer(id, "modal", Props(("title", title ?? "")), build)); - return this; - } - - public EveSurfaceBuilder EmbeddedDocument( - string slotId, - string documentId, - string schemaId, - string presentationKind, - CultMeshRouteHint? routeHint = null) - { - _children.Add(new EveSurfaceComponent( - $"{_surfaceId}.slot.{Slug(slotId)}", - "surface.slot", - new Dictionary(StringComparer.Ordinal) - { - ["slotId"] = slotId ?? "", - ["documentId"] = documentId ?? "", - ["schemaId"] = schemaId ?? "", - ["presentationKind"] = presentationKind ?? "" - }, - Array.Empty(), - Array.Empty(), - new[] - { - new EveEmbeddedDocumentSlot( - slotId ?? "", - documentId ?? "", - schemaId ?? "", - presentationKind ?? "", - routeHint) - })); - return this; - } - - public EveSurfaceBuilder Style(string name, string value) - { - _styles.Add(new EveStyleToken(name, value)); - return this; - } - - public EveSurfaceBuilder Version(long version) - { - _version = version; - return this; - } - - public EveSurfaceBuilder UpdatedAtUtc(string updatedAtUtc) - { - _updatedAtUtc = updatedAtUtc ?? ""; - return this; - } - - public EveSurfaceDocument Build() - { - return new EveSurfaceDocument( - _providerId, - _providerKind, - _title, - _version, - string.IsNullOrWhiteSpace(_updatedAtUtc) ? DateTime.UtcNow.ToString("O") : _updatedAtUtc, - new EveSurfaceTree( - _surfaceId, - _root ?? new EveSurfaceComponent( - $"{_surfaceId}.root", - "surface", - EmptyProps(), - _children.ToArray()), - _styles.ToArray()), - _commands.ToArray()); - } - - private EveSurfaceBuilder Group(string id, string kind, Action build) - { - if (build == null) throw new ArgumentNullException(nameof(build)); - var group = new EveSurfaceGroupBuilder(id, kind, AddCommand); - build(group); - _children.Add(group.Build()); - return this; - } - - private EveSurfaceComponent BuildContainer( - string id, - string kind, - IReadOnlyDictionary props, - Action build) - { - if (build == null) throw new ArgumentNullException(nameof(build)); - var container = new EveSurfaceContainerBuilder(id, kind, props, AddCommand); - build(container); - return container.Build(); - } - - private void AddCommand(EveCommandTemplate command) - { - if (command != null) - _commands.Add(command); - } - - internal static EveSurfaceComponent Text(string id, string value, string kind) - { - return new EveSurfaceComponent( - id, - kind, - new Dictionary(StringComparer.Ordinal) - { - ["value"] = value ?? "" - }, - Array.Empty()); - } - - internal static EveSurfaceComponent ButtonComponent( - string id, - string label, - CultMeshOperationBindingDescriptor operation) - { - return new EveSurfaceComponent( - id, - "control.button", - new Dictionary(StringComparer.Ordinal) - { - ["label"] = label ?? operation.Label, - ["command"] = operation.OperationId, - ["operationId"] = operation.OperationId, - ["schemaId"] = operation.SchemaId - }, - Array.Empty()); - } - - internal static Dictionary EmptyProps() - { - return new Dictionary(StringComparer.Ordinal); - } - - internal static Dictionary Props(params (string Key, string Value)[] values) - { - return (values ?? Array.Empty<(string Key, string Value)>()) - .ToDictionary(value => value.Key, value => value.Value ?? "", StringComparer.Ordinal); - } - - internal static string Slug(string? value) - { - if (string.IsNullOrWhiteSpace(value)) - return "unnamed"; - - var chars = value - .Select(character => char.IsLetterOrDigit(character) ? char.ToLowerInvariant(character) : '.') - .ToArray(); - var slug = new string(chars).Trim('.'); - while (slug.Contains("..", StringComparison.Ordinal)) - slug = slug.Replace("..", ".", StringComparison.Ordinal); - return string.IsNullOrWhiteSpace(slug) ? "unnamed" : slug; - } - - private static string RequireNonEmpty(string value, string paramName) - { - return string.IsNullOrWhiteSpace(value) - ? throw new ArgumentException("Value must be non-empty.", paramName) - : value; - } - } - - public sealed class EveSurfaceContainerBuilder - { - private readonly string _id; - private readonly string _kind; - private readonly Dictionary _props; - private readonly Action _addCommand; - private readonly List _children = new(); - private readonly List _stateBindings = new(); - private readonly List _embeddedDocuments = new(); - - internal EveSurfaceContainerBuilder( - string id, - string kind, - IReadOnlyDictionary props, - Action addCommand) - { - _id = id ?? ""; - _kind = kind ?? "partition"; - _props = new Dictionary(props ?? EveSurfaceBuilder.EmptyProps(), StringComparer.Ordinal); - _addCommand = addCommand ?? throw new ArgumentNullException(nameof(addCommand)); - } - - public EveSurfaceContainerBuilder Gap(int value) => Prop("gap", value); - - public EveSurfaceContainerBuilder Padding(int value) => Prop("padding", value); - - public EveSurfaceContainerBuilder Size(string value) => Prop("size", value); - - public EveSurfaceContainerBuilder Min(string value) => Prop("min", value); - - public EveSurfaceContainerBuilder Max(string value) => Prop("max", value); - - public EveSurfaceContainerBuilder Align(string value) => Prop("align", value); - - public EveSurfaceContainerBuilder Clip(string value = "hidden") => Prop("clip", value); - - public EveSurfaceContainerBuilder Scroll(string value = "y") => Prop("scroll", value); - - public EveSurfaceContainerBuilder Region(string value) => Prop("region", value); - - public EveSurfaceContainerBuilder Bind(CultMeshStateBindingDescriptor binding) - { - if (binding != null) - _stateBindings.Add(binding); - return this; - } - - public EveSurfaceContainerBuilder Row(string id, Action build) - { - _children.Add(BuildContainer(id, "partition", EveSurfaceBuilder.Props(("split", "x")), build)); - return this; - } - - public EveSurfaceContainerBuilder Column(string id, Action build) - { - _children.Add(BuildContainer(id, "partition", EveSurfaceBuilder.Props(("split", "y")), build)); - return this; - } - - public EveSurfaceContainerBuilder Grid( - string id, - int columns, - int rows, - Action build) - { - _children.Add(BuildContainer( - id, - "grid", - EveSurfaceBuilder.Props( - ("columns", columns.ToString(System.Globalization.CultureInfo.InvariantCulture)), - ("rows", rows.ToString(System.Globalization.CultureInfo.InvariantCulture))), - build)); - return this; - } - - public EveSurfaceContainerBuilder Pane(string id, string title, Action build) - { - _children.Add(BuildContainer(id, "pane", EveSurfaceBuilder.Props(("title", title ?? "")), build)); - return this; - } - - public EveSurfaceContainerBuilder Card(string id, string title, Action build) - { - _children.Add(BuildContainer(id, "card", EveSurfaceBuilder.Props(("title", title ?? "")), build)); - return this; - } - - public EveSurfaceContainerBuilder Modal(string id, string title, Action build) - { - _children.Add(BuildContainer(id, "modal", EveSurfaceBuilder.Props(("title", title ?? "")), build)); - return this; - } - - public EveSurfaceContainerBuilder FieldRow( - string id, - string label, - Action build) - { - return Row(id, row => row - .Gap(8) - .Label($"{id}.label", label, labelPart => labelPart.Size("12rem")) - .Column($"{id}.field", field => - { - field.Size("1fr"); - build(field); - })); - } - - public EveSurfaceContainerBuilder Label( - string id, - string text, - Action? configure = null) - { - return Leaf(id, "label", EveSurfaceBuilder.Props(("value", text ?? "")), null, null, configure); - } - - public EveSurfaceContainerBuilder Text(string id, string text) - { - return Leaf(id, "text", EveSurfaceBuilder.Props(("value", text ?? ""))); - } - - public EveSurfaceContainerBuilder Title(string id, string text) - { - return Leaf(id, "text.title", EveSurfaceBuilder.Props(("value", text ?? ""))); - } - - public EveSurfaceContainerBuilder Metric( - string id, - string label, - string value, - CultMeshStateBindingDescriptor? binding = null) - { - return Leaf( - id, - "metric", - EveSurfaceBuilder.Props(("label", label ?? ""), ("value", value ?? "")), - binding); - } - - public EveSurfaceContainerBuilder Progress( - string id, - string label, - string value, - string min, - string max, - CultMeshStateBindingDescriptor? binding = null) - { - return Leaf( - id, - "progress", - EveSurfaceBuilder.Props( - ("label", label ?? ""), - ("value", value ?? ""), - ("min", min ?? ""), - ("max", max ?? "")), - binding); - } - - public EveSurfaceContainerBuilder Button(string id, string label, string command) - { - return Button(id, label, CultMesh.OperationBinding(command, label)); - } - - public EveSurfaceContainerBuilder Button( - string id, - string label, - CultMeshOperationBindingDescriptor operation) - { - if (operation == null) throw new ArgumentNullException(nameof(operation)); - _addCommand(new EveCommandTemplate(operation)); - _children.Add(EveSurfaceBuilder.ButtonComponent(id, label, operation)); - return this; - } - - public EveSurfaceContainerBuilder PopupButton( - string id, - string label, - string title, - Action build, - string anchor = "viewport", - string placement = "center", - int offsetX = 0, - int offsetY = 0) - { - if (build == null) throw new ArgumentNullException(nameof(build)); - var popup = BuildContainer( - $"{id}.popup", - "modal", - EveSurfaceBuilder.Props( - ("title", title ?? label ?? ""), - ("anchor", anchor ?? "viewport"), - ("placement", placement ?? "center"), - ("offsetX", offsetX.ToString(System.Globalization.CultureInfo.InvariantCulture)), - ("offsetY", offsetY.ToString(System.Globalization.CultureInfo.InvariantCulture)), - ("presentation", "popover")), - build); - _children.Add(new EveSurfaceComponent( - id ?? "", - "control.popup", - EveSurfaceBuilder.Props( - ("label", label ?? ""), - ("title", title ?? label ?? ""), - ("anchor", anchor ?? "viewport"), - ("placement", placement ?? "center"), - ("offsetX", offsetX.ToString(System.Globalization.CultureInfo.InvariantCulture)), - ("offsetY", offsetY.ToString(System.Globalization.CultureInfo.InvariantCulture))), - new[] { popup })); - return this; - } - - public EveSurfaceContainerBuilder EnumField( - string id, - string label, - string value, - CultMeshStateBindingDescriptor optionsBinding, - CultMeshOperationBindingDescriptor setValue, - string anchor = "trigger", - string placement = "right-down") - { - return FieldRow(id, label, field => field.PopupButton( - $"{id}.dropdown", - value, - label, - popup => popup.OptionList($"{id}.options", label, optionsBinding, setValue), - anchor, - placement)); - } - - public EveSurfaceContainerBuilder OptionList( - string id, - string label, - CultMeshStateBindingDescriptor itemsBinding, - CultMeshOperationBindingDescriptor operation) - { - if (itemsBinding == null) throw new ArgumentNullException(nameof(itemsBinding)); - if (operation == null) throw new ArgumentNullException(nameof(operation)); - _addCommand(new EveCommandTemplate(operation)); - _children.Add(new EveSurfaceComponent( - id ?? "", - "options", - EveSurfaceBuilder.Props( - ("label", label ?? ""), - ("command", operation.OperationId), - ("operationId", operation.OperationId), - ("schemaId", operation.SchemaId)), - Array.Empty(), - new[] { itemsBinding })); - return this; - } - - public EveSurfaceContainerBuilder TextInput( - string id, - string label, - string value, - CultMeshOperationBindingDescriptor operation, - CultMeshStateBindingDescriptor? binding = null) - { - return Control("control.input.text", id, label, value, operation, binding); - } - - public EveSurfaceContainerBuilder Toggle( - string id, - string label, - bool value, - CultMeshOperationBindingDescriptor operation, - CultMeshStateBindingDescriptor? binding = null) - { - return Control("control.toggle", id, label, value ? "true" : "false", operation, binding); - } - - public EveSurfaceContainerBuilder Slider( - string id, - string label, - string value, - string min, - string max, - string step, - CultMeshOperationBindingDescriptor operation, - CultMeshStateBindingDescriptor? binding = null) - { - return Control( - "control.slider", - id, - label, - value, - operation, - binding, - ("min", min ?? ""), - ("max", max ?? ""), - ("step", step ?? "")); - } - - public EveSurfaceContainerBuilder Select( - string id, - string label, - string value, - CultMeshOperationBindingDescriptor operation, - CultMeshStateBindingDescriptor? binding = null) - { - return Control("control.select", id, label, value, operation, binding); - } - - public EveSurfaceContainerBuilder EmbeddedDocument( - string id, - string slotId, - string documentId, - string schemaId, - string presentationKind, - CultMeshRouteHint? routeHint = null) - { - _children.Add(new EveSurfaceComponent( - id ?? "", - "surface.slot", - EveSurfaceBuilder.Props( - ("slotId", slotId ?? ""), - ("documentId", documentId ?? ""), - ("schemaId", schemaId ?? ""), - ("presentationKind", presentationKind ?? "")), - Array.Empty(), - Array.Empty(), - new[] - { - new EveEmbeddedDocumentSlot( - slotId ?? "", - documentId ?? "", - schemaId ?? "", - presentationKind ?? "", - routeHint) - })); - return this; - } - - internal EveSurfaceComponent Build() - { - return new EveSurfaceComponent( - _id, - _kind, - _props, - _children.ToArray(), - _stateBindings.ToArray(), - _embeddedDocuments.ToArray()); - } - - private EveSurfaceContainerBuilder Prop(string key, int value) - { - _props[key] = value.ToString(System.Globalization.CultureInfo.InvariantCulture); - return this; - } - - private EveSurfaceContainerBuilder Prop(string key, string value) - { - _props[key] = value ?? ""; - return this; - } - - private EveSurfaceContainerBuilder Leaf( - string id, - string kind, - IReadOnlyDictionary props, - CultMeshStateBindingDescriptor? binding = null, - IReadOnlyList? children = null, - Action? configure = null) - { - var builder = new EveSurfaceContainerBuilder(id, kind, props, _addCommand); - configure?.Invoke(builder); - var component = new EveSurfaceComponent( - id ?? "", - kind ?? "", - new Dictionary(props ?? EveSurfaceBuilder.EmptyProps(), StringComparer.Ordinal), - children ?? Array.Empty(), - binding == null ? Array.Empty() : new[] { binding }); - if (builder._props.Count != (props?.Count ?? 0)) - { - component = new EveSurfaceComponent( - id ?? "", - kind ?? "", - new Dictionary(builder._props, StringComparer.Ordinal), - children ?? Array.Empty(), - binding == null ? Array.Empty() : new[] { binding }); - } - _children.Add(component); - return this; - } - - private EveSurfaceContainerBuilder Control( - string kind, - string id, - string label, - string value, - CultMeshOperationBindingDescriptor operation, - CultMeshStateBindingDescriptor? binding, - params (string Key, string Value)[] extraProps) - { - if (operation == null) throw new ArgumentNullException(nameof(operation)); - _addCommand(new EveCommandTemplate(operation)); - var props = EveSurfaceBuilder.Props( - new[] - { - ("label", label ?? ""), - ("value", value ?? ""), - ("command", operation.OperationId), - ("operationId", operation.OperationId), - ("schemaId", operation.SchemaId) - }.Concat(extraProps ?? Array.Empty<(string Key, string Value)>()).ToArray()); - return Leaf(kind: kind, id: id, props: props, binding: binding); - } - - private EveSurfaceComponent BuildContainer( - string id, - string kind, - IReadOnlyDictionary props, - Action build) - { - if (build == null) throw new ArgumentNullException(nameof(build)); - var container = new EveSurfaceContainerBuilder(id, kind, props, _addCommand); - build(container); - return container.Build(); - } - } - - public sealed class EveSurfaceGroupBuilder - { - private readonly string _id; - private readonly string _kind; - private readonly Action _addCommand; - private readonly List _children = new(); - - internal EveSurfaceGroupBuilder( - string id, - string kind, - Action addCommand) - { - _id = id ?? ""; - _kind = kind ?? "column"; - _addCommand = addCommand ?? throw new ArgumentNullException(nameof(addCommand)); - } - - public EveSurfaceGroupBuilder Button(string label, string command) - { - var operation = CultMesh.OperationBinding(command, label); - _addCommand(new EveCommandTemplate(operation)); - _children.Add(EveSurfaceBuilder.ButtonComponent($"{_id}.button.{EveSurfaceBuilder.Slug(label)}", label, operation)); - return this; - } - - public EveSurfaceGroupBuilder Button(string label, CultMeshOperationBindingDescriptor operation) - { - if (operation == null) throw new ArgumentNullException(nameof(operation)); - _addCommand(new EveCommandTemplate(operation)); - _children.Add(EveSurfaceBuilder.ButtonComponent($"{_id}.button.{EveSurfaceBuilder.Slug(label)}", label, operation)); - return this; - } - - internal EveSurfaceComponent Build() - { - return new EveSurfaceComponent(_id, _kind, EveSurfaceBuilder.EmptyProps(), _children.ToArray()); - } - } - - public sealed class EveSurfaceFormBuilder - { - private readonly string _id; - private readonly Action _addCommand; - private readonly List _children = new(); - - internal EveSurfaceFormBuilder(string id, Action addCommand) - { - _id = id ?? ""; - _addCommand = addCommand ?? throw new ArgumentNullException(nameof(addCommand)); - } - - public EveSurfaceFormBuilder Text( - string label, - string value, - CultMeshOperationBindingDescriptor operation, - CultMeshStateBindingDescriptor? binding = null) - { - if (operation == null) throw new ArgumentNullException(nameof(operation)); - _addCommand(new EveCommandTemplate(operation)); - _children.Add(Control( - "control.text", - label, - value, - operation, - binding)); - return this; - } - - public EveSurfaceFormBuilder Toggle( - string label, - bool value, - CultMeshOperationBindingDescriptor operation, - CultMeshStateBindingDescriptor? binding = null) - { - if (operation == null) throw new ArgumentNullException(nameof(operation)); - _addCommand(new EveCommandTemplate(operation)); - _children.Add(Control( - "control.toggle", - label, - value ? "true" : "false", - operation, - binding)); - return this; - } - - public EveSurfaceFormBuilder Metric( - string label, - string value, - CultMeshStateBindingDescriptor? binding = null) - { - var bindings = binding == null - ? Array.Empty() - : new[] { binding }; - _children.Add(new EveSurfaceComponent( - $"{_id}.metric.{EveSurfaceBuilder.Slug(label)}", - "metric", - new Dictionary(StringComparer.Ordinal) - { - ["label"] = label ?? "", - ["value"] = value ?? "" - }, - Array.Empty(), - bindings)); - return this; - } - - internal EveSurfaceComponent Build() - { - return new EveSurfaceComponent(_id, "form", EveSurfaceBuilder.EmptyProps(), _children.ToArray()); - } - - private EveSurfaceComponent Control( - string kind, - string label, - string value, - CultMeshOperationBindingDescriptor operation, - CultMeshStateBindingDescriptor? binding) - { - var bindings = binding == null - ? Array.Empty() - : new[] { binding }; - return new EveSurfaceComponent( - $"{_id}.{EveSurfaceBuilder.Slug(label)}", - kind, - new Dictionary(StringComparer.Ordinal) - { - ["label"] = label ?? "", - ["value"] = value ?? "", - ["command"] = operation.OperationId, - ["operationId"] = operation.OperationId, - ["schemaId"] = operation.SchemaId - }, - Array.Empty(), - bindings); - } - } - - public static class EveSurface - { - public static EveSurfaceBuilder Create(string surfaceId) - { - return new EveSurfaceBuilder(surfaceId); - } - } -} diff --git a/packages/org.gamecult.eve.surface/Runtime/EveSurfaceBuilder.cs.meta b/packages/org.gamecult.eve.surface/Runtime/EveSurfaceBuilder.cs.meta deleted file mode 100644 index adc41da..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveSurfaceBuilder.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 97ac7f757692aef4db64d75d0df6fe51 \ No newline at end of file diff --git a/packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs b/packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs deleted file mode 100644 index 9eed51f..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs +++ /dev/null @@ -1,538 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using GameCult.Caching; -using GameCult.Mesh; -using MessagePack; -using MessagePack.Formatters; - -#nullable enable - -namespace GameCult.Eve.Surface -{ - [CultDocument("gamecult.eve.surface", "gamecult.eve.surface.v1")] - [MessagePackObject] - [MessagePackFormatter(typeof(EveSurfaceDocumentCompatibilityFormatter))] - public sealed class EveSurfaceDocument - { - public const string DefaultType = "surface-state"; - public const string SchemaId = "gamecult.eve.surface.v1"; - - public EveSurfaceDocument( - string providerId, - string providerKind, - string title, - long version, - string updatedAtUtc, - EveSurfaceTree surface, - IReadOnlyList commands) - : this(DefaultType, SchemaId, providerId, providerKind, title, version, updatedAtUtc, surface, commands) - { - } - - [SerializationConstructor] - public EveSurfaceDocument( - string type, - string schema, - string providerId, - string providerKind, - string title, - long version, - string updatedAtUtc, - EveSurfaceTree surface, - IReadOnlyList commands) - { - Type = string.IsNullOrWhiteSpace(type) ? DefaultType : type; - Schema = string.IsNullOrWhiteSpace(schema) ? SchemaId : schema; - ProviderId = providerId ?? ""; - ProviderKind = providerKind ?? ""; - Title = title ?? ""; - Version = version; - UpdatedAtUtc = updatedAtUtc ?? ""; - Surface = surface ?? throw new ArgumentNullException(nameof(surface)); - Commands = commands ?? Array.Empty(); - } - - [Key(0)] - public string Type { get; } - - [Key(1)] - public string Schema { get; } - - [Key(2)] - public string ProviderId { get; } - - [Key(3)] - public string ProviderKind { get; } - - [Key(4)] - public string Title { get; } - - [Key(5)] - public long Version { get; } - - [Key(6)] - public string UpdatedAtUtc { get; } - - [Key(7)] - public EveSurfaceTree Surface { get; } - - [Key(8)] - public IReadOnlyList Commands { get; } - } - - [MessagePackObject] - public sealed class EveSurfaceTree - { - [SerializationConstructor] - public EveSurfaceTree(string id, EveSurfaceComponent root, IReadOnlyList styles) - { - Id = id ?? ""; - Root = root ?? throw new ArgumentNullException(nameof(root)); - Styles = styles ?? Array.Empty(); - } - - [Key(0)] - public string Id { get; } - - [Key(1)] - public EveSurfaceComponent Root { get; } - - [Key(2)] - public IReadOnlyList Styles { get; } - } - - [MessagePackObject] - public sealed class EveSurfaceComponent - { - public EveSurfaceComponent( - string id, - string kind, - IReadOnlyDictionary props, - IReadOnlyList children) - : this(id, kind, props, children, StateBindingsFromProps(props)) - { - } - - public EveSurfaceComponent( - string id, - string kind, - IReadOnlyDictionary props, - IReadOnlyList children, - IReadOnlyList stateBindings) - : this(id, kind, props, children, stateBindings, Array.Empty()) - { - } - - public EveSurfaceComponent( - string id, - string kind, - IReadOnlyDictionary props, - IReadOnlyList children, - IReadOnlyList stateBindings, - IReadOnlyList embeddedDocuments, - IReadOnlyDictionary? layout = null, - IReadOnlyDictionary? style = null) - : this( - id, - kind, - props, - children, - (stateBindings ?? Array.Empty()) - .Select(CultMeshStateBindingRecord.FromBinding) - .ToArray(), - embeddedDocuments, - layout, - style) - { - } - - [SerializationConstructor] - public EveSurfaceComponent( - string id, - string kind, - IReadOnlyDictionary props, - IReadOnlyList children, - CultMeshStateBindingRecord[] stateBindingRecords, - IReadOnlyList embeddedDocuments, - IReadOnlyDictionary? layout = null, - IReadOnlyDictionary? style = null) - { - Id = id ?? ""; - Kind = kind ?? ""; - Props = props ?? new Dictionary(StringComparer.Ordinal); - Children = children ?? Array.Empty(); - StateBindingRecords = stateBindingRecords ?? Array.Empty(); - EmbeddedDocuments = embeddedDocuments ?? Array.Empty(); - Layout = layout ?? new Dictionary(StringComparer.Ordinal); - Style = style ?? new Dictionary(StringComparer.Ordinal); - } - - [Key(0)] - public string Id { get; } - - [Key(1)] - public string Kind { get; } - - [Key(2)] - public IReadOnlyDictionary Props { get; } - - [Key(3)] - public IReadOnlyList Children { get; } - - [Key(4)] - public CultMeshStateBindingRecord[] StateBindingRecords { get; } - - [IgnoreMember] - public IReadOnlyList StateBindings => - StateBindingRecords.Select(record => record.ToBinding()).ToArray(); - - [Key(5)] - public IReadOnlyList EmbeddedDocuments { get; } - - [Key(6)] - public IReadOnlyDictionary Layout { get; } - - [Key(7)] - public IReadOnlyDictionary Style { get; } - - public string GetProp(string key, string fallback = "") - { - return Props.TryGetValue(key, out var value) ? value : fallback; - } - - private static IReadOnlyList StateBindingsFromProps( - IReadOnlyDictionary? props) - { - if (props == null || props.Count == 0) - return Array.Empty(); - - var bindings = new List(); - foreach (var prop in props) - { - if (string.IsNullOrWhiteSpace(prop.Value) || - !prop.Key.EndsWith("PointerId", StringComparison.Ordinal)) - { - continue; - } - - var targetProp = prop.Key.Substring(0, prop.Key.Length - "PointerId".Length); - if (targetProp.Length == 0) - targetProp = "value"; - bindings.Add(new CultMeshStateBindingDescriptor(targetProp, prop.Value)); - } - - return bindings; - } - } - - [MessagePackObject] - public sealed class EveEmbeddedDocumentSlot - { - public EveEmbeddedDocumentSlot( - string slotId, - string documentId, - string schemaId, - string presentationKind, - CultMeshRouteHint? routeHint = null) - : this(slotId, documentId, schemaId, presentationKind, CultMeshRouteRecord.FromRoute(routeHint)) - { - } - - [SerializationConstructor] - public EveEmbeddedDocumentSlot( - string slotId, - string documentId, - string schemaId, - string presentationKind, - CultMeshRouteRecord route) - { - SlotId = slotId ?? ""; - DocumentId = documentId ?? ""; - SchemaId = schemaId ?? ""; - PresentationKind = presentationKind ?? ""; - Route = route ?? CultMeshRouteRecord.FromRoute(CultMeshRouteHint.Automatic); - } - - [Key(0)] - public string SlotId { get; } - - [Key(1)] - public string DocumentId { get; } - - [Key(2)] - public string SchemaId { get; } - - [Key(3)] - public string PresentationKind { get; } - - [Key(4)] - public CultMeshRouteRecord Route { get; } - - [IgnoreMember] - public CultMeshRouteHint RouteHint => Route.ToRoute(); - } - - [MessagePackObject] - public sealed class EveStyleToken - { - [SerializationConstructor] - public EveStyleToken(string name, string value) - { - Name = name ?? ""; - Value = value ?? ""; - } - - [Key(0)] - public string Name { get; } - - [Key(1)] - public string Value { get; } - } - - [MessagePackObject] - [MessagePackFormatter(typeof(EveCommandTemplateCompatibilityFormatter))] - public sealed class EveCommandTemplate - { - public EveCommandTemplate(CultMeshOperationBindingDescriptor operation) - : this(CultMeshOperationBindingRecord.FromBinding(operation)) - { - } - - [SerializationConstructor] - public EveCommandTemplate(CultMeshOperationBindingRecord operationRecord) - { - OperationRecord = operationRecord ?? throw new ArgumentNullException(nameof(operationRecord)); - } - - [Key(0)] - public CultMeshOperationBindingRecord OperationRecord { get; } - - [IgnoreMember] - public CultMeshOperationBindingDescriptor Operation => OperationRecord.ToBinding(); - - [IgnoreMember] - public string Command => Operation.OperationId; - - [IgnoreMember] - public string Label => Operation.Label; - - [IgnoreMember] - public string Transport => Operation.RouteHint.Description ?? ""; - } - - [CultDocument("gamecult.eve.command_invocation", SchemaId)] - [MessagePackObject] - public sealed class EveSurfaceCommandRequest - { - public const string SchemaId = "gamecult.eve.command_invocation.v1"; - - public EveSurfaceCommandRequest( - string providerId, - string surfaceId, - CultMeshOperationInvocationDescriptor operation, - CultMeshOperationPayload payload, - DateTimeOffset issuedAt, - string clientId, - string commandBoundary = "", - string receiptSchema = "") - : this( - SchemaId, - providerId, - surfaceId, - CultMeshOperationInvocationRecord.FromInvocation(operation), - payload?.ToDictionary(entry => entry.Key, entry => entry.Value, StringComparer.Ordinal) - ?? new Dictionary(StringComparer.Ordinal), - issuedAt, - clientId, - commandBoundary, - receiptSchema) - { - } - - [SerializationConstructor] - public EveSurfaceCommandRequest( - string schema, - string providerId, - string surfaceId, - CultMeshOperationInvocationRecord operation, - Dictionary payload, - DateTimeOffset issuedAt, - string clientId, - string commandBoundary, - string receiptSchema) - { - Schema = string.IsNullOrWhiteSpace(schema) ? SchemaId : schema; - ProviderId = providerId; - SurfaceId = surfaceId; - OperationRecord = operation ?? throw new ArgumentNullException(nameof(operation)); - PayloadFields = payload == null - ? new Dictionary(StringComparer.Ordinal) - : new Dictionary(payload, StringComparer.Ordinal); - IssuedAt = issuedAt; - ClientId = clientId; - CommandBoundary = commandBoundary ?? ""; - ReceiptSchema = receiptSchema ?? ""; - } - - [Key(0)] - public string Schema { get; } - - [Key(1)] - public string ProviderId { get; } - - [Key(2)] - public string SurfaceId { get; } - - [Key(3)] - public CultMeshOperationInvocationRecord OperationRecord { get; } - - [IgnoreMember] - public CultMeshOperationInvocationDescriptor Operation => OperationRecord.ToInvocation(); - - [IgnoreMember] - public string Command => Operation.OperationId; - - [Key(4)] - public Dictionary PayloadFields { get; } - - [IgnoreMember] - public CultMeshOperationPayload Payload => new CultMeshOperationPayload(PayloadFields); - - [Key(5)] - public DateTimeOffset IssuedAt { get; } - - [Key(6)] - public string ClientId { get; } - - [Key(7)] - public string CommandBoundary { get; } - - [Key(8)] - public string ReceiptSchema { get; } - - [IgnoreMember] - public string CommandId => Operation.IdempotencyKey ?? ""; - } - - /// - /// Reads the current Eve surface envelope and the original seven-field v1 envelope. - /// - public sealed class EveSurfaceDocumentCompatibilityFormatter : IMessagePackFormatter - { - private const int LegacyFieldCount = 7; - private const int CurrentFieldCount = 9; - - public void Serialize(ref MessagePackWriter writer, EveSurfaceDocument? value, MessagePackSerializerOptions options) - { - if (value == null) { writer.WriteNil(); return; } - writer.WriteArrayHeader(CurrentFieldCount); - writer.Write(value.Type); - writer.Write(value.Schema); - writer.Write(value.ProviderId); - writer.Write(value.ProviderKind); - writer.Write(value.Title); - writer.Write(value.Version); - writer.Write(value.UpdatedAtUtc); - Formatter(options).Serialize(ref writer, value.Surface, options); - Formatter>(options).Serialize(ref writer, value.Commands, options); - } - - public EveSurfaceDocument? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) - { - if (reader.TryReadNil()) return null; - if (reader.NextMessagePackType != MessagePackType.Array) - throw new MessagePackSerializationException("Eve surface document must be an array."); - - options.Security.DepthStep(ref reader); - try - { - var fields = reader.ReadArrayHeader(); - if (fields == LegacyFieldCount) - { - return new EveSurfaceDocument( - ReadString(ref reader), ReadString(ref reader), ReadString(ref reader), - reader.ReadInt64(), ReadString(ref reader), - Formatter(options).Deserialize(ref reader, options)!, - Formatter>(options).Deserialize(ref reader, options) - ?? Array.Empty()); - } - - var type = ReadString(ref reader, fields, 0); - var schema = ReadString(ref reader, fields, 1); - var providerId = ReadString(ref reader, fields, 2); - var providerKind = ReadString(ref reader, fields, 3); - var title = ReadString(ref reader, fields, 4); - var version = fields > 5 ? reader.ReadInt64() : 0; - var updatedAtUtc = ReadString(ref reader, fields, 6); - var surface = fields > 7 ? Formatter(options).Deserialize(ref reader, options) : null; - var commands = fields > 8 ? Formatter>(options).Deserialize(ref reader, options) : null; - for (var index = CurrentFieldCount; index < fields; index++) reader.Skip(); - return new EveSurfaceDocument( - type, schema, providerId, providerKind, title, version, updatedAtUtc, - surface ?? throw new MessagePackSerializationException("Eve surface tree is required."), - commands ?? Array.Empty()); - } - finally { reader.Depth--; } - } - - private static IMessagePackFormatter Formatter(MessagePackSerializerOptions options) => - options.Resolver.GetFormatter() - ?? throw new MessagePackSerializationException($"No formatter is registered for {typeof(T).FullName}."); - - private static string ReadString(ref MessagePackReader reader) => reader.ReadString() ?? ""; - private static string ReadString(ref MessagePackReader reader, int fields, int index) => - index < fields ? ReadString(ref reader) : ""; - } - - /// - /// Reads both direct legacy command fields and the current wrapped binding record. - /// - public sealed class EveCommandTemplateCompatibilityFormatter : IMessagePackFormatter - { - public void Serialize(ref MessagePackWriter writer, EveCommandTemplate? value, MessagePackSerializerOptions options) - { - if (value == null) { writer.WriteNil(); return; } - writer.WriteArrayHeader(1); - BindingFormatter(options).Serialize(ref writer, value.OperationRecord, options); - } - - public EveCommandTemplate? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) - { - if (reader.TryReadNil()) return null; - if (reader.NextMessagePackType != MessagePackType.Array) - throw new MessagePackSerializationException("Eve command template must be an array."); - - options.Security.DepthStep(ref reader); - try - { - var fields = reader.ReadArrayHeader(); - if (fields == 1 && reader.NextMessagePackType == MessagePackType.Array) - { - return new EveCommandTemplate( - BindingFormatter(options).Deserialize(ref reader, options) - ?? new CultMeshOperationBindingRecord()); - } - - var operationId = ReadString(ref reader, fields, 0); - var label = ReadString(ref reader, fields, 1); - var schemaId = ReadString(ref reader, fields, 2); - var routeKind = ReadString(ref reader, fields, 3); - var routeDescription = ReadString(ref reader, fields, 4); - for (var index = 5; index < fields; index++) reader.Skip(); - return new EveCommandTemplate(new CultMeshOperationBindingRecord( - operationId, label, schemaId, routeKind, routeDescription)); - } - finally { reader.Depth--; } - } - - private static IMessagePackFormatter BindingFormatter( - MessagePackSerializerOptions options) => - options.Resolver.GetFormatter() - ?? throw new MessagePackSerializationException("No CultMesh operation binding formatter is registered."); - - private static string ReadString(ref MessagePackReader reader, int fields, int index) => - index < fields ? reader.ReadString() ?? "" : ""; - } - -} diff --git a/packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs.meta b/packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs.meta deleted file mode 100644 index ebd5f02..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 6516c42104b235f42b15efeb4639bb73 \ No newline at end of file diff --git a/packages/org.gamecult.eve.surface/Runtime/GameCult.Eve.Surface.asmdef b/packages/org.gamecult.eve.surface/Runtime/GameCult.Eve.Surface.asmdef deleted file mode 100644 index 7f19662..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/GameCult.Eve.Surface.asmdef +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "GameCult.Eve.Surface", - "rootNamespace": "GameCult.Eve.Surface", - "references": [ - "GameCult.Mesh" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": true, - "precompiledReferences": [ - "GameCult.Caching.dll", - "GameCult.Mesh.dll", - "MessagePack.Annotations.dll", - "MessagePack.dll" - ], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": true -} diff --git a/packages/org.gamecult.eve.surface/Runtime/GameCult.Eve.Surface.asmdef.meta b/packages/org.gamecult.eve.surface/Runtime/GameCult.Eve.Surface.asmdef.meta deleted file mode 100644 index d8f543e..0000000 --- a/packages/org.gamecult.eve.surface/Runtime/GameCult.Eve.Surface.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: a9004278c14816345941af2f2ce673ca -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/packages/org.gamecult.eve.surface/package.json b/packages/org.gamecult.eve.surface/package.json deleted file mode 100644 index 36fd3b6..0000000 --- a/packages/org.gamecult.eve.surface/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "org.gamecult.eve.surface", - "displayName": "Eve Surface Contract", - "version": "0.2.4", - "unity": "2021.3", - "description": "Unity-compatible DTOs for gamecult.eve.surface.v1 documents.", - "dependencies": { - "org.gamecult.cultlib": "1.0.8" - }, - "files": [ - "Runtime", - "Runtime.meta", - "README.md", - "README.md.meta", - "Directory.Build.props", - "Directory.Build.props.meta", - "GameCult.Eve.Surface.csproj", - "GameCult.Eve.Surface.csproj.meta", - "package.json.meta" - ], - "keywords": [ - "Eve", - "CultUI", - "CultMesh", - "Surface" - ], - "license": "MPL-2.0", - "category": "Scripting" -} diff --git a/packages/org.gamecult.eve.surface/package.json.meta b/packages/org.gamecult.eve.surface/package.json.meta deleted file mode 100644 index 8e89223..0000000 --- a/packages/org.gamecult.eve.surface/package.json.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 49f1738bd94075e489c82190cf660b1d -PackageManifestImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/packages/org.gamecult.eve.unity-scene/eve-runtime-capability.json b/packages/org.gamecult.eve.unity-scene/eve-runtime-capability.json index 4e07fed..244999a 100644 --- a/packages/org.gamecult.eve.unity-scene/eve-runtime-capability.json +++ b/packages/org.gamecult.eve.unity-scene/eve-runtime-capability.json @@ -160,14 +160,14 @@ "requiredPackageDependencies": [ { "packageName": "org.gamecult.eve.surface", - "version": "0.2.4", + "version": "0.3.0", "packageManager": "upm", - "ownerRepo": "EveUnity", - "purpose": "Shared Unity DTOs for gamecult.eve.surface.v1 documents." + "ownerRepo": "Eve", + "purpose": "Renderer-neutral contracts and builders for gamecult.eve.surface.v1 documents." }, { "packageName": "org.gamecult.eve.unity-uitoolkit", - "version": "0.1.2", + "version": "0.1.3", "packageManager": "upm", "ownerRepo": "EveUnity", "purpose": "Generic UI Toolkit lowering for provider-owned Eve panes, metrics, progress, text, and controls." diff --git a/packages/org.gamecult.eve.unity-scene/package.json b/packages/org.gamecult.eve.unity-scene/package.json index 980c07b..e85eac9 100644 --- a/packages/org.gamecult.eve.unity-scene/package.json +++ b/packages/org.gamecult.eve.unity-scene/package.json @@ -7,8 +7,8 @@ "dependencies": { "org.gamecult.cultlib": "1.0.43", "org.gamecult.eve.plugin-fields": "0.2.3", - "org.gamecult.eve.surface": "0.2.4", - "org.gamecult.eve.unity-uitoolkit": "0.1.2", + "org.gamecult.eve.surface": "0.3.0", + "org.gamecult.eve.unity-uitoolkit": "0.1.3", "com.unity.mathematics": "1.3.2", "com.unity.render-pipelines.universal": "17.4.0", "com.unity.modules.particlesystem": "1.0.0" diff --git a/packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json b/packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json index 7d59ddf..de1b373 100644 --- a/packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json +++ b/packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json @@ -83,10 +83,10 @@ "requiredPackageDependencies": [ { "packageName": "org.gamecult.eve.surface", - "version": "0.1.0", + "version": "0.3.0", "packageManager": "upm", - "ownerRepo": "EveUnity", - "purpose": "Shared Unity DTOs for gamecult.eve.surface.v1 documents." + "ownerRepo": "Eve", + "purpose": "Renderer-neutral contracts and builders for gamecult.eve.surface.v1 documents." } ] }, diff --git a/packages/org.gamecult.eve.unity-uitoolkit/package.json b/packages/org.gamecult.eve.unity-uitoolkit/package.json index ddfcd4d..e28b919 100644 --- a/packages/org.gamecult.eve.unity-uitoolkit/package.json +++ b/packages/org.gamecult.eve.unity-uitoolkit/package.json @@ -1,11 +1,11 @@ { "name": "org.gamecult.eve.unity-uitoolkit", "displayName": "Eve UI Toolkit Lowering", - "version": "0.1.2", + "version": "0.1.3", "unity": "2021.3", "description": "Unity UI Toolkit lowering for gamecult.eve.surface.v1 documents.", "dependencies": { - "org.gamecult.eve.surface": "0.2.4" + "org.gamecult.eve.surface": "0.3.0" }, "keywords": [ "Eve", diff --git a/scripts/run-package-tests.ps1 b/scripts/run-package-tests.ps1 index b7f4b36..2c9b78f 100644 --- a/scripts/run-package-tests.ps1 +++ b/scripts/run-package-tests.ps1 @@ -10,6 +10,16 @@ $repoRoot = Split-Path -Parent $PSScriptRoot $projectPath = if ([IO.Path]::IsPathRooted($ProjectRoot)) { $ProjectRoot } else { Join-Path $repoRoot $ProjectRoot } $output = if ([IO.Path]::IsPathRooted($OutputRoot)) { $OutputRoot } else { Join-Path $repoRoot $OutputRoot } $cultLibBuilder = Join-Path $CultLibRoot "scripts\build-unity-package.ps1" +$obsoleteSurfacePackage = Join-Path $repoRoot "packages\org.gamecult.eve.surface" +$testManifestPath = Join-Path $projectPath "Packages\manifest.json" +if (Test-Path -LiteralPath $obsoleteSurfacePackage) { + throw "EveUnity must consume the Eve-owned surface package; duplicate source exists at $obsoleteSurfacePackage" +} +$testManifest = Get-Content -LiteralPath $testManifestPath -Raw | ConvertFrom-Json +$surfaceDependency = [string]$testManifest.dependencies."org.gamecult.eve.surface" +if ($surfaceDependency -notmatch '(?i)Eve/packages/org\.gamecult\.eve\.surface$') { + throw "EveUnity test consumer must resolve org.gamecult.eve.surface from Eve; found '$surfaceDependency'." +} foreach ($required in @($UnityExe, $projectPath, $cultLibBuilder)) { if (-not (Test-Path -LiteralPath $required)) { throw "Required EveUnity package-test path not found: $required" } } diff --git a/tests/GameCult.Eve.Surface.Serialization.Tests/.gitignore b/tests/GameCult.Eve.Surface.Serialization.Tests/.gitignore deleted file mode 100644 index 296b87c..0000000 --- a/tests/GameCult.Eve.Surface.Serialization.Tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!GameCult.Eve.Surface.Serialization.Tests.csproj diff --git a/tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs b/tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs deleted file mode 100644 index a756e74..0000000 --- a/tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs +++ /dev/null @@ -1,262 +0,0 @@ -using System.Buffers; -using GameCult.Eve.Surface; -using GameCult.Mesh; -using MessagePack; -using NUnit.Framework; - -namespace GameCult.Eve.Surface.Tests; - -[TestFixture] -public sealed class EveSurfaceSerializationCompatibilityTests -{ - [Test] - public void EntitySoaV2SerializesLogicalLayoutWithoutTransportFields() - { - var document = new EveEntitySoaViewDocument - { - ProviderId = "provider", - ViewId = "entities", - BodySchemaId = "entity.slab.v1", - LayoutVersion = 2, - ProducerEpoch = 3, - Sequence = 4, - Capacity = 8, - FrameId = 91, - Buffers = new[] { new EveEntitySoaBuffer { BufferId = "entity-hot", ByteLength = 64 } }, - Identities = new[] - { - new EveEntityIdentity - { - Index = 0, - EntityId = "player", - EntityKind = "ship", - Label = "Vanguard", - Faction = "alliance", - Selectable = true, - Controllable = true, - AssetRef = "cultmesh://assets/player" - } - } - }; - - var bytes = MessagePackSerializer.Serialize(document, Options); - var reader = new MessagePackReader(bytes); - var restored = MessagePackSerializer.Deserialize(bytes, Options); - - Assert.That(reader.ReadArrayHeader(), Is.EqualTo(15)); - Assert.That(restored.Schema, Is.EqualTo(EveEntitySoaViewDocument.SchemaId)); - Assert.That(restored.Buffers[0].BufferId, Is.EqualTo("entity-hot")); - Assert.That(restored.FrameId, Is.EqualTo(91)); - Assert.That(restored.Identities[0].Label, Is.EqualTo("Vanguard")); - Assert.That(restored.Identities[0].Faction, Is.EqualTo("alliance")); - Assert.That(restored.Identities[0].Selectable, Is.True); - Assert.That(restored.Identities[0].Controllable, Is.True); - Assert.That(restored.Identities[0].AssetRef, Is.EqualTo("cultmesh://assets/player")); - } - - [Test] - public void EntitySoaContractsExposeNoTransportAuthorityFields() - { - var forbidden = new[] { "Backend", "Location", "CapabilityToken", "Synchronization", "SynchronizationMode", "Descriptor" }; - var exposed = new[] { typeof(EveEntitySoaViewDocument), typeof(EveEntitySoaBuffer), typeof(EveEntitySoaColumn) } - .SelectMany(type => type.GetProperties()) - .Select(property => property.Name); - - Assert.That(exposed, Has.None.Matches(name => forbidden.Contains(name, StringComparer.Ordinal))); - } - - private static readonly MessagePackSerializerOptions Options = MessagePackSerializerOptions.Standard; - - [Test] - public void LegacySevenFieldSurfaceDocumentDeserializes() - { - var bytes = WriteLegacySurfaceDocument(); - - var document = MessagePackSerializer.Deserialize(bytes, Options); - - Assert.Multiple(() => - { - Assert.That(document.Type, Is.EqualTo(EveSurfaceDocument.DefaultType)); - Assert.That(document.Schema, Is.EqualTo(EveSurfaceDocument.SchemaId)); - Assert.That(document.ProviderId, Is.EqualTo("legacy-provider")); - Assert.That(document.ProviderKind, Is.EqualTo("legacy-kind")); - Assert.That(document.Title, Is.EqualTo("Legacy surface")); - Assert.That(document.Version, Is.EqualTo(17)); - Assert.That(document.UpdatedAtUtc, Is.EqualTo("2026-07-13T12:00:00Z")); - Assert.That(document.Surface.Id, Is.EqualTo("legacy-surface")); - Assert.That(document.Commands, Has.Count.EqualTo(1)); - Assert.That(document.Commands[0].Command, Is.EqualTo("legacy.execute")); - }); - } - - [Test] - public void LegacyDirectFiveStringCommandTemplateDeserializes() - { - var bytes = WriteLegacyCommandTemplate(); - - var command = MessagePackSerializer.Deserialize(bytes, Options); - - Assert.Multiple(() => - { - Assert.That(command.Command, Is.EqualTo("legacy.execute")); - Assert.That(command.Label, Is.EqualTo("Execute legacy command")); - Assert.That(command.Operation.SchemaId, Is.EqualTo("gamecult.legacy.command.v1")); - Assert.That(command.OperationRecord.RouteKind, Is.EqualTo("cultmesh")); - Assert.That(command.OperationRecord.RouteDescription, Is.EqualTo("legacy.commands")); - Assert.That(command.Transport, Is.EqualTo("legacy.commands")); - }); - } - - [Test] - public void CurrentSerializationWritesNineFieldSurfaceAndWrappedStructuredCommandBinding() - { - var document = CreateCurrentDocument(); - - var bytes = MessagePackSerializer.Serialize(document, Options); - var reader = new MessagePackReader(bytes); - - Assert.That(reader.ReadArrayHeader(), Is.EqualTo(9)); - for (var field = 0; field < 8; field++) - reader.Skip(); - Assert.That(reader.ReadArrayHeader(), Is.EqualTo(1), "commands collection"); - Assert.That(reader.ReadArrayHeader(), Is.EqualTo(1), "command template wrapper"); - Assert.That(reader.NextMessagePackType, Is.EqualTo(MessagePackType.Array), "structured operation binding"); - - var roundTrip = MessagePackSerializer.Deserialize(bytes, Options); - Assert.That(roundTrip.Commands[0].Command, Is.EqualTo("current.execute")); - } - - [Test] - public void LegacyExpandedProviderAdvertisementDeserializesAsCanonicalContract() - { - var document = MessagePackSerializer.Deserialize( - WriteLegacyProviderAdvertisement(), - Options); - - Assert.Multiple(() => - { - Assert.That(document.ProviderId, Is.EqualTo("aetheria")); - Assert.That(document.ServiceId, Is.EqualTo("aetheria-daemon")); - Assert.That(document.VerseId, Is.EqualTo("aetheria.local")); - Assert.That(document.Title, Is.EqualTo("Aetheria")); - Assert.That(document.CultMeshAddress, Is.EqualTo("cultmesh://aetheria.local/aetheria")); - Assert.That(document.Surfaces[0].SurfaceId, Is.EqualTo("aetheria.pilot")); - Assert.That(document.Surfaces[0].Schema, Is.EqualTo(EveSurfaceDocument.SchemaId)); - Assert.That(document.Commands[0].Command, Is.EqualTo("aetheria.pilot.move")); - Assert.That(document.Commands[0].SurfaceId, Is.Empty); - }); - } - - [Test] - public void CurrentProviderAdvertisementSerializationWritesCanonicalThirteenFields() - { - var document = new EveProviderAdvertisementDocument( - "provider", "service", "verse", "Title", "game.runtime", "cultmesh://verse/provider", - "2026-07-13T14:00:00Z", new EveProviderFreshness("fresh", "2026-07-13T14:00:00Z", 15000), - new[] { EveSurfaceDocument.SchemaId }, Array.Empty(), - Array.Empty(), Array.Empty()); - - var bytes = MessagePackSerializer.Serialize(document, Options); - var reader = new MessagePackReader(bytes); - - Assert.That(reader.ReadArrayHeader(), Is.EqualTo(13)); - Assert.That(MessagePackSerializer.Deserialize(bytes, Options).Title, - Is.EqualTo("Title")); - } - - private static EveSurfaceDocument CreateCurrentDocument() => new( - "current-provider", - "current-kind", - "Current surface", - 23, - "2026-07-13T13:00:00Z", - CreateSurfaceTree("current-surface"), - new[] - { - new EveCommandTemplate(new CultMeshOperationBindingRecord( - "current.execute", - "Execute current command", - "gamecult.current.command.v1", - "cultmesh", - "current.commands")) - }); - - private static EveSurfaceTree CreateSurfaceTree(string id) => new( - id, - new EveSurfaceComponent( - "root", - "column", - new Dictionary(), - Array.Empty()), - Array.Empty()); - - private static byte[] WriteLegacySurfaceDocument() - { - var buffer = new ArrayBufferWriter(); - var writer = new MessagePackWriter(buffer); - writer.WriteArrayHeader(7); - writer.Write("legacy-provider"); - writer.Write("legacy-kind"); - writer.Write("Legacy surface"); - writer.Write(17L); - writer.Write("2026-07-13T12:00:00Z"); - writer.WriteRaw(MessagePackSerializer.Serialize(CreateSurfaceTree("legacy-surface"), Options)); - writer.WriteArrayHeader(1); - writer.WriteRaw(WriteLegacyCommandTemplate()); - writer.Flush(); - return buffer.WrittenSpan.ToArray(); - } - - private static byte[] WriteLegacyCommandTemplate() - { - var buffer = new ArrayBufferWriter(); - var writer = new MessagePackWriter(buffer); - writer.WriteArrayHeader(5); - writer.Write("legacy.execute"); - writer.Write("Execute legacy command"); - writer.Write("gamecult.legacy.command.v1"); - writer.Write("cultmesh"); - writer.Write("legacy.commands"); - writer.Flush(); - return buffer.WrittenSpan.ToArray(); - } - - private static byte[] WriteLegacyProviderAdvertisement() - { - var buffer = new ArrayBufferWriter(); - var writer = new MessagePackWriter(buffer); - writer.WriteArrayHeader(16); - writer.Write(EveProviderAdvertisementDocument.SchemaId); - writer.Write("aetheria"); - writer.Write("aetheria-daemon"); - writer.Write("aetheria.local"); - writer.Write("asgard"); - writer.Write("aetheria"); - writer.Write("aetheria.local/aetheria"); - writer.Write("cultmesh://aetheria.local/aetheria"); - writer.Write("Aetheria"); - writer.Write("game.runtime"); - writer.Write("2026-07-13T14:00:00Z"); - writer.WriteArrayHeader(3); - writer.Write("fresh"); - writer.Write("2026-07-13T14:00:00Z"); - writer.Write(15000); - writer.WriteArrayHeader(1); - writer.Write(EveSurfaceDocument.SchemaId); - writer.WriteArrayHeader(0); - writer.WriteArrayHeader(1); - writer.WriteArrayHeader(5); - writer.Write(EveSurfaceDocument.SchemaId); - writer.Write("aetheria.pilot"); - writer.Write("eve:surface:aetheria.pilot"); - writer.Write("cultmesh"); - writer.Write("available"); - writer.WriteArrayHeader(1); - writer.WriteArrayHeader(3); - writer.Write("aetheria.pilot.move"); - writer.Write("cultmesh"); - writer.Write("Move the pilot ship"); - writer.Flush(); - return buffer.WrittenSpan.ToArray(); - } -} diff --git a/tests/GameCult.Eve.Surface.Serialization.Tests/GameCult.Eve.Surface.Serialization.Tests.csproj b/tests/GameCult.Eve.Surface.Serialization.Tests/GameCult.Eve.Surface.Serialization.Tests.csproj deleted file mode 100644 index e3c947a..0000000 --- a/tests/GameCult.Eve.Surface.Serialization.Tests/GameCult.Eve.Surface.Serialization.Tests.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - net10.0 - enable - enable - false - true - obj\bin\ - - - - - - - - - - - -