diff --git a/Aetheria.State.Daemon.Smoke/Program.cs b/Aetheria.State.Daemon.Smoke/Program.cs index c122cb709..a7f29b36b 100644 --- a/Aetheria.State.Daemon.Smoke/Program.cs +++ b/Aetheria.State.Daemon.Smoke/Program.cs @@ -1635,6 +1635,10 @@ internal sealed class AetheriaDaemonYmirSmokeChecks var pickupAsset = AetheriaRuntimeAssets.ProjectManifest(null).Assets.Single(asset => asset.Ref.AssetKey == "prefab.entity.pickup"); Require(pickupAsset.Ref.Metadata.TryGetValue("unityAssetPath", out var pickupPath) && pickupPath == "Assets/Prefabs/RPG/Pickups/Tetrahedron.prefab", "provider asset manifest must advertise the pickup visual used by Eve"); + var assets = AetheriaRuntimeAssets.ProjectManifest(null).Assets; + var playerAsset = assets.Single(asset => asset.Ref.AssetKey == "prefab.entity.player"); + RequireEqual("player", playerAsset.Ref.Metadata["presentationRole"], + "entity prefab fallback must use a specific presentation role instead of the generic world tag"); } private static void PickupIsCapacityCheckedExactlyOnceAndExpires() diff --git a/Packages/org.gamecult.aetheria.eve-runtime/Runtime/AetheriaEveUnitySceneProviderBridge.cs b/Packages/org.gamecult.aetheria.eve-runtime/Runtime/AetheriaEveUnitySceneProviderBridge.cs index 2a782c401..e3115dd3b 100644 --- a/Packages/org.gamecult.aetheria.eve-runtime/Runtime/AetheriaEveUnitySceneProviderBridge.cs +++ b/Packages/org.gamecult.aetheria.eve-runtime/Runtime/AetheriaEveUnitySceneProviderBridge.cs @@ -379,6 +379,11 @@ namespace GameCult.Aetheria.EveRuntime private static string EntityKind(AetheriaRuntimeAssetManifestEntry entry) { + if (entry.Ref.Metadata != null && + entry.Ref.Metadata.TryGetValue("presentationRole", out var role) && + !string.IsNullOrWhiteSpace(role)) + return role; + return (entry.Tags ?? Array.Empty()) .FirstOrDefault(tag => !string.IsNullOrWhiteSpace(tag) && !string.Equals(tag, "map", StringComparison.OrdinalIgnoreCase) && !string.Equals(tag, "icon", StringComparison.OrdinalIgnoreCase)) ?? ""; diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeAssets.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeAssets.cs index 1cc30578d..6de6d8c92 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeAssets.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeAssets.cs @@ -22,11 +22,10 @@ namespace GameCult.Aetheria.State.Verse Add(entries, MapIcon("body.planet", "Planet", "Sprites/Icons/Stroked/Planet")); Add(entries, MapIcon("body.sun", "Sun", "Sprites/Icons/Stroked/Sun")); Add(entries, MapIcon("body.asteroid", "Asteroid", "Sprites/Icons/Stroked/Planet")); - Add(entries, MapPrefab("prefab.entity.player", "Player Ship", "Prefabs/Ships/Djinni")); - Add(entries, MapPrefab("prefab.entity.ship", "Ship", "Prefabs/Ships/Djinni")); - Add(entries, MapPrefab("prefab.entity.station", "Station", "Prefabs/Stations/AsteroidOutpost")); - Add(entries, MapPrefab("prefab.entity.orbital", "Orbital", "Prefabs/Stations/Zenith")); - Add(entries, MapPrefab("prefab.entity.projectile", "Projectile", "Prefabs/Lightning")); + Add(entries, MapPrefab("prefab.entity.player", "Player Ship", "Prefabs/Ships/Djinni", "player")); + Add(entries, MapPrefab("prefab.entity.ship", "Ship", "Prefabs/Ships/Djinni", "ship")); + Add(entries, MapPrefab("prefab.entity.station", "Station", "Prefabs/Stations/AsteroidOutpost", "station")); + Add(entries, MapPrefab("prefab.entity.orbital", "Orbital", "Prefabs/Stations/Zenith", "orbital")); Add(entries, MapProjectPrefab("prefab.entity.pickup", "Pickup", "Assets/Prefabs/RPG/Pickups/Tetrahedron.prefab")); foreach (var inventoryAsset in InventoryUiAssets()) Add(entries, inventoryAsset); @@ -164,11 +163,16 @@ namespace GameCult.Aetheria.State.Verse private static AetheriaRuntimeAssetManifestEntry MapPrefab( string key, string label, - string resourcePath) + string resourcePath, + string presentationRole) { + var asset = Prefab(key, resourcePath); + asset.Metadata = asset.Metadata + .Concat(new[] { new KeyValuePair("presentationRole", presentationRole ?? "") }) + .ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.Ordinal); return new AetheriaRuntimeAssetManifestEntry { - Ref = Prefab(key, resourcePath), + Ref = asset, Tags = new[] { "world", "prefab", label } }; } diff --git a/docs/aetheria-current-codebase-model.md b/docs/aetheria-current-codebase-model.md index 4f980a884..f71baac6c 100644 --- a/docs/aetheria-current-codebase-model.md +++ b/docs/aetheria-current-codebase-model.md @@ -138,6 +138,13 @@ presentation objects only where GameObject views are still unavoidable. Unity physics is already fenced as forbidden gameplay authority by `Aetheria.State.Verify`. +The fossil `Assets/Resources/Prefabs/Lightning.prefab` is not yet a portable +effect asset: it embeds the Aetheria-owned `LightningCompute` component and its +compute/material dependencies. The component and shader bundle must graduate +to EveUnity together before Aetheria advertises that prefab under an +`effect.shot.*` presentation role. CultMesh transport does not erase serialized +code dependencies. + Current Ymir control flow: - The daemon projects ships, pickups, fields, and explicitly physical payloads