From 0b099274a4e2b4c301eced4322166837792f585a Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 10 Jul 2026 15:33:52 +0100 Subject: [PATCH 1/9] Add stable Unity metadata to fields contracts --- .../unity/org.gamecult.eve.plugin-fields/README.md.meta | 7 +++++++ .../unity/org.gamecult.eve.plugin-fields/Runtime.meta | 8 ++++++++ .../Runtime/EveFieldsContracts.cs.meta | 2 ++ .../Runtime/GameCult.Eve.PluginFields.asmdef.meta | 7 +++++++ .../unity/org.gamecult.eve.plugin-fields/package.json | 2 +- 5 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md.meta create mode 100644 plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime.meta create mode 100644 plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs.meta create mode 100644 plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/GameCult.Eve.PluginFields.asmdef.meta diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md.meta b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md.meta new file mode 100644 index 0000000..52811c6 --- /dev/null +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7122b42864d44e029d5d718a53d03186 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime.meta b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime.meta new file mode 100644 index 0000000..b5575fd --- /dev/null +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d6eb92523e7048c4844a7fe9d3bdcf4a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs.meta b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs.meta new file mode 100644 index 0000000..73cae51 --- /dev/null +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 115753bcd85347649537e429e9dd9e8f diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/GameCult.Eve.PluginFields.asmdef.meta b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/GameCult.Eve.PluginFields.asmdef.meta new file mode 100644 index 0000000..e4325fa --- /dev/null +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/GameCult.Eve.PluginFields.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4b0812861c9b453cbd5b02c6dc84098c +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json index a925186..430cafc 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json @@ -1,6 +1,6 @@ { "name": "org.gamecult.eve.plugin-fields", - "version": "0.1.0", + "version": "0.1.1", "displayName": "Eve Fields Plugin Contracts", "description": "Runtime-neutral C# contracts for gamecult.fields documents.", "unity": "2022.3", From 030383470f02cd0e4f34c9552e33241877688b73 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 10 Jul 2026 15:43:57 +0100 Subject: [PATCH 2/9] Publish .NET fields contract project --- .gitignore | 3 ++- .../eve-plugin-fields/GameCult.Eve.PluginFields.csproj | 10 ++++++++++ plugins/eve-plugin-fields/test/plugin.test.mjs | 1 + .../org.gamecult.eve.plugin-fields/package.json.meta | 7 +++++++ 4 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj create mode 100644 plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json.meta diff --git a/.gitignore b/.gitignore index 36a9264..69f9c63 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ artifacts/ - +**/bin/ +**/obj/ diff --git a/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj b/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj new file mode 100644 index 0000000..bc496e6 --- /dev/null +++ b/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj @@ -0,0 +1,10 @@ + + + netstandard2.1 + enable + latest + Runtime-neutral C# contracts for gamecult.fields documents. + GameCult.Eve.PluginFields + 0.1.1 + + diff --git a/plugins/eve-plugin-fields/test/plugin.test.mjs b/plugins/eve-plugin-fields/test/plugin.test.mjs index 9d75db4..6eacf41 100644 --- a/plugins/eve-plugin-fields/test/plugin.test.mjs +++ b/plugins/eve-plugin-fields/test/plugin.test.mjs @@ -49,4 +49,5 @@ test("publishes a runtime-neutral Unity contract package", () => { assert.match(contracts, /interface IEveFieldsSplatsDocument/); assert.match(contracts, /gamecult\.fields\.splats\.v1/); assert.doesNotMatch(contracts, /UnityEngine|Aetheria|MessagePack|GameCult\.Caching/); + assert.match(readFileSync(new URL("../GameCult.Eve.PluginFields.csproj", import.meta.url), "utf8"), /netstandard2\.1/); }); diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json.meta b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json.meta new file mode 100644 index 0000000..a481ab2 --- /dev/null +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 59ad75f1e14ba2245b8766107f53a8b7 +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From 7d486b0089ddf91ac9a7e4d96d6d33704d1b1e18 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 10 Jul 2026 15:44:17 +0100 Subject: [PATCH 3/9] Clean fields package manifest metadata --- .../unity/org.gamecult.eve.plugin-fields/package.json.meta | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json.meta b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json.meta index a481ab2..0bc6c7d 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json.meta +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json.meta @@ -2,6 +2,6 @@ fileFormatVersion: 2 guid: 59ad75f1e14ba2245b8766107f53a8b7 PackageManifestImporter: externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: + userData: + assetBundleName: + assetBundleVariant: From 97bbbcdc612ef9941e3196ab8f3a84cf7696f707 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 10 Jul 2026 16:01:41 +0100 Subject: [PATCH 4/9] Graduate fields plugin runtime contract --- plugins/eve-plugin-fields/advertisement.json | 2 +- plugins/eve-plugin-fields/plugin.json | 9 +++++++++ plugins/eve-plugin-fields/test/plugin.test.mjs | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/plugins/eve-plugin-fields/advertisement.json b/plugins/eve-plugin-fields/advertisement.json index 7cf626e..08a999b 100644 --- a/plugins/eve-plugin-fields/advertisement.json +++ b/plugins/eve-plugin-fields/advertisement.json @@ -2,7 +2,7 @@ "schema": "gamecult.eve.plugin_advertisement.v1", "pluginId": "fields.surface", "ownerService": "eveplugins", - "version": "0.1.0", + "version": "0.1.1", "manifestAddress": "file://plugins/eve-plugin-fields/plugin.json", "runtime": { "invocationModel": "executable-sidecar", diff --git a/plugins/eve-plugin-fields/plugin.json b/plugins/eve-plugin-fields/plugin.json index 6dfa5f8..d178460 100644 --- a/plugins/eve-plugin-fields/plugin.json +++ b/plugins/eve-plugin-fields/plugin.json @@ -4,11 +4,20 @@ "title": "Semantic Fields", "owner": "EvePlugins", "incubation": { + "status": "graduated", "ownerRepo": "EvePlugins", "currentHostRepo": "EvePlugins", "splitTarget": "EvePlugins/eve-plugin-fields", "graduationTrigger": "Split when field schemas, sidecar witness, and two runtime adapters are stable." }, + "graduation": { + "status": "graduated", + "runtimeAdapters": ["web-reference", "unity-scene"], + "evidence": [ + "artifacts/fields-surface/runtime-witness.json", + "EveUnity/artifacts/fields-surface/latest/unity-fields.png" + ] + }, "componentKinds": ["field.surface2d", "gravity.surface"], "commands": [], "runtime": { diff --git a/plugins/eve-plugin-fields/test/plugin.test.mjs b/plugins/eve-plugin-fields/test/plugin.test.mjs index 6eacf41..b1d1c27 100644 --- a/plugins/eve-plugin-fields/test/plugin.test.mjs +++ b/plugins/eve-plugin-fields/test/plugin.test.mjs @@ -51,3 +51,9 @@ test("publishes a runtime-neutral Unity contract package", () => { assert.doesNotMatch(contracts, /UnityEngine|Aetheria|MessagePack|GameCult\.Caching/); assert.match(readFileSync(new URL("../GameCult.Eve.PluginFields.csproj", import.meta.url), "utf8"), /netstandard2\.1/); }); + +test("records fields plugin graduation after two native runtime proofs", () => { + const manifest = JSON.parse(readFileSync(new URL("../plugin.json", import.meta.url), "utf8")); + assert.equal(manifest.graduation.status, "graduated"); + assert.deepEqual(manifest.graduation.runtimeAdapters, ["web-reference", "unity-scene"]); +}); From dabea374b1ee89d084e93f95f05f56c1cadb8b14 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 10 Jul 2026 16:28:10 +0100 Subject: [PATCH 5/9] Complete fields ABI evidence --- plugins/eve-plugin-fields/plugin-abi-fixture.json | 6 +++--- plugins/eve-plugin-fields/src/plugin.mjs | 1 + plugins/eve-plugin-fields/test/plugin.test.mjs | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/eve-plugin-fields/plugin-abi-fixture.json b/plugins/eve-plugin-fields/plugin-abi-fixture.json index d75aba9..c98a2a8 100644 --- a/plugins/eve-plugin-fields/plugin-abi-fixture.json +++ b/plugins/eve-plugin-fields/plugin-abi-fixture.json @@ -8,9 +8,9 @@ "responseSchema": "gamecult.eve.plugin_abi.response.v1", "authority": "EvePlugins owns field semantics; providers own sampled field state and runtimes own native projection.", "operations": [ - { "operation": "describe", "input": {}, "expect": { "pluginId": "fields.surface", "componentKinds": ["field.surface2d", "gravity.surface"], "commands": [] } }, - { "operation": "validate", "input": { "componentKinds": ["field.surface2d", "world.scene3d"], "document": { "schema": "gamecult.fields.surface2d.v1", "bounds": { "minX": -1, "minY": -1, "maxX": 1, "maxY": 1 } } }, "expect": { "acceptedComponentKinds": ["field.surface2d"], "rejectedComponentKinds": ["world.scene3d"], "validDocument": true } }, + { "operation": "describe", "input": {}, "expect": { "pluginId": "fields.surface", "componentKinds": ["field.surface2d", "gravity.surface"], "commands": [], "capabilities": ["field.surface2d", "gravity.surface", "field.scalar", "field.vector", "field.objects"] } }, + { "operation": "validate", "input": { "componentKinds": ["field.surface2d", "gravity.surface", "world.scene3d"], "document": { "schema": "gamecult.fields.surface2d.v1", "bounds": { "minX": -1, "minY": -1, "maxX": 1, "maxY": 1 } } }, "expect": { "acceptedComponentKinds": ["field.surface2d", "gravity.surface"], "rejectedComponentKinds": ["world.scene3d"], "validDocument": true } }, { "operation": "project", "input": { "document": { "schema": "gamecult.fields.surface2d.v1", "fieldId": "fixture.field", "bounds": { "minX": -1, "minY": -1, "maxX": 1, "maxY": 1 }, "channels": [{ "channelId": "height", "kind": "scalar", "documentId": "cultmesh://fixture/height", "schemaId": "gamecult.fields.scalar.v1" }] } }, "expect": { "projectionKind": "semantic-field-surface", "ownedComponentKinds": ["field.surface2d", "gravity.surface"], "providerStateMutated": false } }, - { "operation": "measure", "input": { "document": { "schema": "gamecult.fields.surface2d.v1", "fieldId": "fixture.field", "bounds": { "minX": -1, "minY": -2, "maxX": 3, "maxY": 2 }, "channels": [] } }, "expect": { "measurementKind": "field-domain-metrics", "width": 4, "height": 4, "preservesProviderAuthority": true } } + { "operation": "measure", "input": { "document": { "schema": "gamecult.fields.surface2d.v1", "fieldId": "fixture.field", "bounds": { "minX": -1, "minY": -2, "maxX": 3, "maxY": 2 }, "channels": [] } }, "expect": { "measurementKind": "field-domain-metrics", "measurementOutputs": ["width", "height", "channelCount"], "width": 4, "height": 4, "preservesProviderAuthority": true } } ] } diff --git a/plugins/eve-plugin-fields/src/plugin.mjs b/plugins/eve-plugin-fields/src/plugin.mjs index 1659e7e..1fb84b7 100644 --- a/plugins/eve-plugin-fields/src/plugin.mjs +++ b/plugins/eve-plugin-fields/src/plugin.mjs @@ -62,6 +62,7 @@ export function measure(input) { const projection = project(input); return { measurementKind: "field-domain-metrics", + measurementOutputs: ["width", "height", "channelCount"], width: projection.bounds.maxX - projection.bounds.minX, height: projection.bounds.maxY - projection.bounds.minY, channelCount: projection.channels.length, diff --git a/plugins/eve-plugin-fields/test/plugin.test.mjs b/plugins/eve-plugin-fields/test/plugin.test.mjs index b1d1c27..528ca11 100644 --- a/plugins/eve-plugin-fields/test/plugin.test.mjs +++ b/plugins/eve-plugin-fields/test/plugin.test.mjs @@ -38,6 +38,7 @@ test("measures field domains without mutating provider state", () => { assert.equal(result.width, 20); assert.equal(result.height, 10); assert.equal(result.channelCount, 1); + assert.deepEqual(result.measurementOutputs, ["width", "height", "channelCount"]); assert.equal(result.preservesProviderAuthority, true); }); From 382a23d8f8a07e4b5eef5f81f84655861a858367 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 15 Jul 2026 17:11:11 +0100 Subject: [PATCH 6/9] Publish canonical fields splat documents --- .../GameCult.Eve.PluginFields.csproj | 8 +- .../Runtime/EveFieldsDocuments.cs | 78 +++++++++++++++++++ .../Runtime/EveFieldsDocuments.cs.meta | 11 +++ .../Runtime/GameCult.Eve.PluginFields.asmdef | 6 ++ .../package.json | 7 +- 5 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs create mode 100644 plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs.meta diff --git a/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj b/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj index bc496e6..74057f1 100644 --- a/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj +++ b/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj @@ -4,7 +4,13 @@ enable latest Runtime-neutral C# contracts for gamecult.fields documents. + $(MSBuildThisFileDirectory)..\..\..\CultLib GameCult.Eve.PluginFields - 0.1.1 + 0.2.0 + + + + + diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs new file mode 100644 index 0000000..b1f6189 --- /dev/null +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using GameCult.Caching; +using MessagePack; + +namespace GameCult.Eve.PluginFields +{ + [CultDocument("gamecult.fields.splats", EveFieldsSchemas.Splats)] + [MessagePackObject] + public sealed class EveFieldsSplatsDocument : IEveFieldsSplatsDocument + { + [Key(0)] public string Schema { get; set; } = EveFieldsSchemas.Splats; + [Key(1)] public long FrameId { get; set; } + [Key(2)] public string PublishedAtUtc { get; set; } = ""; + [Key(3)] public double SimulationTimeSeconds { get; set; } + [Key(4)] public string RunId { get; set; } = ""; + [Key(5)] public int ZoneIndex { get; set; } + [Key(6)] public string ZoneName { get; set; } = ""; + [Key(7)] public EveFieldsViewport Viewport { get; set; } = new EveFieldsViewport(); + [Key(8)] public IReadOnlyList Layers { get; set; } = Array.Empty(); + [Key(9)] public EveFieldsSplatSoa Splats { get; set; } = new EveFieldsSplatSoa(); + + IEveFieldsViewport IEveFieldsSplatsDocument.Viewport => Viewport; + IReadOnlyList IEveFieldsSplatsDocument.Layers => Layers; + IEveFieldsSplatSoa IEveFieldsSplatsDocument.Splats => Splats; + } + + [MessagePackObject] + public sealed class EveFieldsViewport : IEveFieldsViewport + { + [Key(0)] public double MinX { get; set; } + [Key(1)] public double MinY { get; set; } + [Key(2)] public double MaxX { get; set; } + [Key(3)] public double MaxY { get; set; } + } + + [MessagePackObject] + public sealed class EveFieldsSplatLayer : IEveFieldsSplatLayer + { + [Key(0)] public string LayerKey { get; set; } = ""; + [Key(1)] public string DisplayName { get; set; } = ""; + [Key(2)] public int Channel { get; set; } + [Key(3)] public string BlendMode { get; set; } = EveFieldsSplatBlendModes.Add; + [Key(4)] public string GraphicsFormat { get; set; } = "R16_SFloat"; + [Key(5)] public bool ClearBeforeDraw { get; set; } = true; + [Key(6)] public double ClearR { get; set; } + [Key(7)] public double ClearG { get; set; } + [Key(8)] public double ClearB { get; set; } + [Key(9)] public double ClearA { get; set; } + } + + [MessagePackObject] + public sealed class EveFieldsSplatSoa : IEveFieldsSplatSoa + { + [Key(0)] public int Count { get; set; } + [Key(1)] public IReadOnlyList CenterX { get; set; } = Array.Empty(); + [Key(2)] public IReadOnlyList CenterY { get; set; } = Array.Empty(); + [Key(3)] public IReadOnlyList HalfExtentX { get; set; } = Array.Empty(); + [Key(4)] public IReadOnlyList HalfExtentY { get; set; } = Array.Empty(); + [Key(5)] public IReadOnlyList RotationCos { get; set; } = Array.Empty(); + [Key(6)] public IReadOnlyList RotationSin { get; set; } = Array.Empty(); + [Key(7)] public IReadOnlyList Channel { get; set; } = Array.Empty(); + [Key(8)] public IReadOnlyList Falloff { get; set; } = Array.Empty(); + [Key(9)] public IReadOnlyList ValueR { get; set; } = Array.Empty(); + [Key(10)] public IReadOnlyList ValueG { get; set; } = Array.Empty(); + [Key(11)] public IReadOnlyList ValueB { get; set; } = Array.Empty(); + [Key(12)] public IReadOnlyList ValueA { get; set; } = Array.Empty(); + [Key(13)] public IReadOnlyList SourceKey { get; set; } = Array.Empty(); + [Key(14)] public IReadOnlyList LayerIndex { get; set; } = Array.Empty(); + [Key(15)] public IReadOnlyList SourceKind { get; set; } = Array.Empty(); + [Key(16)] public IReadOnlyList FrequencyX { get; set; } = Array.Empty(); + [Key(17)] public IReadOnlyList FrequencyY { get; set; } = Array.Empty(); + [Key(18)] public IReadOnlyList PhaseX { get; set; } = Array.Empty(); + [Key(19)] public IReadOnlyList PhaseY { get; set; } = Array.Empty(); + [Key(20)] public IReadOnlyList AnimationSpeed { get; set; } = Array.Empty(); + [Key(21)] public IReadOnlyList SourceFlags { get; set; } = Array.Empty(); + } +} diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs.meta b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs.meta new file mode 100644 index 0000000..edc01a3 --- /dev/null +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7e1b64023d224e8cb0bfaec57adad5c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/GameCult.Eve.PluginFields.asmdef b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/GameCult.Eve.PluginFields.asmdef index b1ae4e7..8afd12c 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/GameCult.Eve.PluginFields.asmdef +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/GameCult.Eve.PluginFields.asmdef @@ -2,6 +2,12 @@ "name": "GameCult.Eve.PluginFields", "rootNamespace": "GameCult.Eve.PluginFields", "references": [], + "overrideReferences": true, + "precompiledReferences": [ + "GameCult.Caching.dll", + "MessagePack.Annotations.dll", + "MessagePack.dll" + ], "autoReferenced": true, "noEngineReferences": true } diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json index 430cafc..4459e23 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json @@ -1,8 +1,11 @@ { "name": "org.gamecult.eve.plugin-fields", - "version": "0.1.1", + "version": "0.2.0", "displayName": "Eve Fields Plugin Contracts", "description": "Runtime-neutral C# contracts for gamecult.fields documents.", - "unity": "2022.3", + "unity": "2021.3", + "dependencies": { + "org.gamecult.cultlib": "1.0.13" + }, "license": "MPL-2.0" } From 59924e324cd10f293c214c8e6bb2c794a32d39a0 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 15 Jul 2026 22:35:12 +0100 Subject: [PATCH 7/9] Add portable power pulse field falloff --- plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj | 2 +- .../unity/org.gamecult.eve.plugin-fields/README.md | 6 ++++++ .../Runtime/EveFieldsContracts.cs | 3 +++ .../Runtime/EveFieldsDocuments.cs | 2 ++ .../unity/org.gamecult.eve.plugin-fields/package.json | 2 +- 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj b/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj index 74057f1..4e29428 100644 --- a/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj +++ b/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj @@ -6,7 +6,7 @@ Runtime-neutral C# contracts for gamecult.fields documents. $(MSBuildThisFileDirectory)..\..\..\CultLib GameCult.Eve.PluginFields - 0.2.0 + 0.2.1 diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md index 8584a0c..dd120eb 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md @@ -3,3 +3,9 @@ This package owns the portable C# view of `gamecult.fields.*` documents. It has no Unity rendering, provider state, transport, or command authority. Providers implement these read-only interfaces; Unity runtime adapters consume them. + +`PowerPulse` is the portable compact-support radial falloff +`pow(saturate(1 - pow(distance01 * scale, 2)), exponent)`. Producers publish +`FalloffScale` and `FalloffExponent` alongside each SoA splat. Missing parameter +entries retain the neutral defaults `1` and `1`, so older v1 documents remain +readable. diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs index 075a8e4..d3133f7 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs @@ -51,6 +51,7 @@ namespace GameCult.Eve.PluginFields public const int Linear = 1; public const int Smooth = 2; public const int InverseSmooth = 3; + public const int PowerPulse = 4; } public interface IEveFieldsViewport @@ -99,6 +100,8 @@ namespace GameCult.Eve.PluginFields IReadOnlyList PhaseY { get; } IReadOnlyList AnimationSpeed { get; } IReadOnlyList SourceFlags { get; } + IReadOnlyList FalloffScale { get; } + IReadOnlyList FalloffExponent { get; } } public interface IEveFieldsSplatsDocument diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs index b1f6189..c33679d 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsDocuments.cs @@ -74,5 +74,7 @@ namespace GameCult.Eve.PluginFields [Key(19)] public IReadOnlyList PhaseY { get; set; } = Array.Empty(); [Key(20)] public IReadOnlyList AnimationSpeed { get; set; } = Array.Empty(); [Key(21)] public IReadOnlyList SourceFlags { get; set; } = Array.Empty(); + [Key(22)] public IReadOnlyList FalloffScale { get; set; } = Array.Empty(); + [Key(23)] public IReadOnlyList FalloffExponent { get; set; } = Array.Empty(); } } diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json index 4459e23..905acb0 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json @@ -1,6 +1,6 @@ { "name": "org.gamecult.eve.plugin-fields", - "version": "0.2.0", + "version": "0.2.1", "displayName": "Eve Fields Plugin Contracts", "description": "Runtime-neutral C# contracts for gamecult.fields documents.", "unity": "2021.3", From c4a61e818e0b15b4504d76952910738eeeaf6041 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 15 Jul 2026 23:14:47 +0100 Subject: [PATCH 8/9] Define world-anchored procedural field sources --- .../eve-plugin-fields/GameCult.Eve.PluginFields.csproj | 2 +- plugins/eve-plugin-fields/test/plugin.test.mjs | 2 ++ .../unity/org.gamecult.eve.plugin-fields/README.md | 10 ++++++++++ .../Runtime/EveFieldsContracts.cs | 6 ++++++ .../unity/org.gamecult.eve.plugin-fields/package.json | 2 +- 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj b/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj index 4e29428..9a4fd45 100644 --- a/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj +++ b/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj @@ -6,7 +6,7 @@ Runtime-neutral C# contracts for gamecult.fields documents. $(MSBuildThisFileDirectory)..\..\..\CultLib GameCult.Eve.PluginFields - 0.2.1 + 0.2.2 diff --git a/plugins/eve-plugin-fields/test/plugin.test.mjs b/plugins/eve-plugin-fields/test/plugin.test.mjs index 528ca11..eb56dd1 100644 --- a/plugins/eve-plugin-fields/test/plugin.test.mjs +++ b/plugins/eve-plugin-fields/test/plugin.test.mjs @@ -49,6 +49,8 @@ test("publishes a runtime-neutral Unity contract package", () => { assert.equal(manifest.name, "org.gamecult.eve.plugin-fields"); assert.match(contracts, /interface IEveFieldsSplatsDocument/); assert.match(contracts, /gamecult\.fields\.splats\.v1/); + assert.match(contracts, /AnimatedCellNoiseB = 3/); + assert.match(contracts, /AbsoluteValue = 1/); assert.doesNotMatch(contracts, /UnityEngine|Aetheria|MessagePack|GameCult\.Caching/); assert.match(readFileSync(new URL("../GameCult.Eve.PluginFields.csproj", import.meta.url), "utf8"), /netstandard2\.1/); }); diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md index dd120eb..eee9130 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md @@ -9,3 +9,13 @@ implement these read-only interfaces; Unity runtime adapters consume them. `FalloffScale` and `FalloffExponent` alongside each SoA splat. Missing parameter entries retain the neutral defaults `1` and `1`, so older v1 documents remain readable. + +Procedural sources are evaluated in field-world coordinates, not splat-local +UVs. `SimplexNoise` samples signed Ashima 3D simplex at +`(worldXY * frequency + phase, 0)`. `AnimatedSimplexNoise` uses +`simulationTimeSeconds * animationSpeed` for the third coordinate. +`AnimatedCellNoiseB` is the portable moving, wrappable cellular source whose +distance metric is `(length(frac(p) - .5) * 1.5 + .25) * +max(abs(x) * .866 + y * .5, -y)`. `AbsoluteValue` folds a signed source after +sampling. Constant offsets remain ordinary constant splats, so source sampling +and additive composition retain separate ownership. diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs index d3133f7..3bf837e 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs @@ -43,6 +43,12 @@ namespace GameCult.Eve.PluginFields public const int Constant = 0; public const int SimplexNoise = 1; public const int AnimatedSimplexNoise = 2; + public const int AnimatedCellNoiseB = 3; + } + + public static class EveFieldsSplatSourceFlags + { + public const int AbsoluteValue = 1; } public static class EveFieldsSplatFalloffs diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json index 905acb0..42d2ed2 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json @@ -1,6 +1,6 @@ { "name": "org.gamecult.eve.plugin-fields", - "version": "0.2.1", + "version": "0.2.2", "displayName": "Eve Fields Plugin Contracts", "description": "Runtime-neutral C# contracts for gamecult.fields documents.", "unity": "2021.3", From c5a4a75c1b727499b16c2dae1895f29e2a9f72f0 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 15 Jul 2026 23:37:10 +0100 Subject: [PATCH 9/9] Add portable radial cosine field source --- plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj | 2 +- plugins/eve-plugin-fields/test/plugin.test.mjs | 1 + .../unity/org.gamecult.eve.plugin-fields/README.md | 7 +++++++ .../Runtime/EveFieldsContracts.cs | 1 + .../unity/org.gamecult.eve.plugin-fields/package.json | 2 +- 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj b/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj index 9a4fd45..cbfbfb3 100644 --- a/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj +++ b/plugins/eve-plugin-fields/GameCult.Eve.PluginFields.csproj @@ -6,7 +6,7 @@ Runtime-neutral C# contracts for gamecult.fields documents. $(MSBuildThisFileDirectory)..\..\..\CultLib GameCult.Eve.PluginFields - 0.2.2 + 0.2.3 diff --git a/plugins/eve-plugin-fields/test/plugin.test.mjs b/plugins/eve-plugin-fields/test/plugin.test.mjs index eb56dd1..85df1b7 100644 --- a/plugins/eve-plugin-fields/test/plugin.test.mjs +++ b/plugins/eve-plugin-fields/test/plugin.test.mjs @@ -50,6 +50,7 @@ test("publishes a runtime-neutral Unity contract package", () => { assert.match(contracts, /interface IEveFieldsSplatsDocument/); assert.match(contracts, /gamecult\.fields\.splats\.v1/); assert.match(contracts, /AnimatedCellNoiseB = 3/); + assert.match(contracts, /AnimatedRadialCosine = 4/); assert.match(contracts, /AbsoluteValue = 1/); assert.doesNotMatch(contracts, /UnityEngine|Aetheria|MessagePack|GameCult\.Caching/); assert.match(readFileSync(new URL("../GameCult.Eve.PluginFields.csproj", import.meta.url), "utf8"), /netstandard2\.1/); diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md index eee9130..fabc7f1 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/README.md @@ -19,3 +19,10 @@ distance metric is `(length(frac(p) - .5) * 1.5 + .25) * max(abs(x) * .866 + y * .5, -y)`. `AbsoluteValue` folds a signed source after sampling. Constant offsets remain ordinary constant splats, so source sampling and additive composition retain separate ownership. + +`AnimatedRadialCosine` is splat-local rather than field-world anchored. It +evaluates +`cos(pow(distance01, FrequencyY) * FrequencyX + PhaseX + simulationTimeSeconds * AnimationSpeed)`. +`FrequencyX` is radial frequency and `FrequencyY` is the positive radial +exponent. The ordinary splat falloff owns the envelope, which keeps oscillation +and compact support independently composable. diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs index 3bf837e..8c712e2 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/Runtime/EveFieldsContracts.cs @@ -44,6 +44,7 @@ namespace GameCult.Eve.PluginFields public const int SimplexNoise = 1; public const int AnimatedSimplexNoise = 2; public const int AnimatedCellNoiseB = 3; + public const int AnimatedRadialCosine = 4; } public static class EveFieldsSplatSourceFlags diff --git a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json index 42d2ed2..a985686 100644 --- a/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json +++ b/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields/package.json @@ -1,6 +1,6 @@ { "name": "org.gamecult.eve.plugin-fields", - "version": "0.2.2", + "version": "0.2.3", "displayName": "Eve Fields Plugin Contracts", "description": "Runtime-neutral C# contracts for gamecult.fields documents.", "unity": "2021.3",