Restore authoritative continuous pilot aim

This commit is contained in:
Meta Vens 2026-07-15 05:57:17 +01:00
commit 947c591ebd
6 changed files with 50 additions and 6 deletions

View file

@ -504,6 +504,15 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
new AetheriaRuntimeDaemonHealthDocument(),
AetheriaRuntimeDaemonCommandBoundaryDocument.Create("daemon"));
var combat = Flatten(surface.Surface.Root).Single(node => node.Kind == "combat.presentation");
var world = Flatten(surface.Surface.Root).Single(node => node.Kind == "world.scene3d");
var aim = Flatten(surface.Surface.Root).Single(node => node.Kind == "aim.presentation");
Require(!string.IsNullOrWhiteSpace(world.Props["lookCommand"]) &&
world.Props["lookSensitivityRadians"] == "-0.001",
"playable world must advertise the daemon-owned continuous look command and fossil pointer response");
Require(aim.Props["controlledEntityIndex"] == "0" &&
aim.Props["convergenceTargetEntityId"] == run.EntityRecordKey(0, 1) &&
aim.Props["minimumConvergenceDistance"] == "50",
"Eve aim presentation must bind the controlled body direction to the fossil convergence semantic");
Require(combat.Props["controlledEntityIndex"] == "0" &&
combat.Props["selectedTargetEntityIndex"] == "1" &&
combat.Props["targetVisible"] == "true" &&

View file

@ -9,6 +9,6 @@
"org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13",
"org.gamecult.eve.plugin-fields": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.1.1",
"org.gamecult.eve.surface": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.2.1",
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.23"
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.24"
}
}

View file

@ -142,7 +142,7 @@
"hash": "d0aa50d31f3b6da96bffc194fdc3aa358f37e332"
},
"org.gamecult.eve.unity-scene": {
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.23",
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.24",
"depth": 0,
"source": "git",
"dependencies": {

View file

@ -3771,8 +3771,8 @@ public class DaemonRuntimeDocumentTests
var player = run.Zones[0].Entities[0];
Assert.AreEqual(3, result.AppliedCommandIds.Count);
Assert.AreEqual(0, result.RejectedCommandIds.Count);
Assert.AreEqual(0.25, player.DirectionX, 0.0001);
Assert.AreEqual(-0.75, player.DirectionY, 0.0001);
Assert.AreEqual(0.316227766, player.DirectionX, 0.0001);
Assert.AreEqual(-0.948683298, player.DirectionY, 0.0001);
Assert.AreEqual(0.8, player.TractorPower, 0.0001);
Assert.IsTrue(player.HeatsinksEnabled);
}

View file

@ -608,6 +608,8 @@ namespace GameCult.Aetheria.State.Verse
["movementEnabled"] = isDocked ? "false" : "true",
["presentationMode"] = isDocked ? "docked" : "world",
["movementCommand"] = CommandName(AetheriaRuntimeDaemonCommandKinds.SetMoveVector),
["lookCommand"] = CommandName(AetheriaRuntimeDaemonCommandKinds.SetLookDirection),
["lookSensitivityRadians"] = "-0.001",
["focusCommand"] = CommandName(AetheriaRuntimeDaemonCommandKinds.TargetNearest),
["targetCommand"] = CommandName(AetheriaRuntimeDaemonCommandKinds.SetTarget),
["actionCommand"] = CommandName(AetheriaRuntimeDaemonCommandKinds.FireWeaponGroup),
@ -625,6 +627,9 @@ namespace GameCult.Aetheria.State.Verse
var combatPresentation = CombatPresentation(run, zone, playerEntityId, simulationSettings);
if (combatPresentation != null)
presentationChildren.Insert(0, combatPresentation);
var aimPresentation = AimPresentation(run, zone, playerEntityId);
if (aimPresentation != null)
presentationChildren.Insert(0, aimPresentation);
return new AetheriaRuntimeSurfaceComponent(
id,
@ -647,6 +652,30 @@ namespace GameCult.Aetheria.State.Verse
});
}
private static AetheriaRuntimeSurfaceComponent? AimPresentation(
AetheriaRuntimeRunCheckpointCommit run,
AetheriaRuntimeZoneSnapshotCommit zone,
string playerEntityId)
{
var player = FindCurrentEntity(run, zone);
if (player == null)
return null;
var target = FindTargetEntity(zone, player);
var props = new Dictionary<string, string>(StringComparer.Ordinal)
{
["controlledEntityId"] = playerEntityId,
["controlledEntityIndex"] = player.EntityIndex.ToString(CultureInfo.InvariantCulture),
["convergenceTargetEntityId"] = target == null
? ""
: run.EntityRecordKey(zone.ZoneIndex, target.EntityIndex),
["viewDotRole"] = "aim.marker.view-direction",
["minimumConvergenceDistance"] = "50",
["viewDotRadius"] = "0.8"
};
return Node("aetheria.daemon.game.world.aim", "aim.presentation", props.Select(value => (value.Key, value.Value)).ToArray());
}
private static AetheriaRuntimeSurfaceComponent? CombatPresentation(
AetheriaRuntimeRunCheckpointCommit run,
AetheriaRuntimeZoneSnapshotCommit zone,

View file

@ -529,10 +529,16 @@ namespace GameCult.Aetheria.State.Verse
AetheriaRuntimeRunCheckpointCommit run,
AetheriaRuntimeDaemonCommandDocument command)
{
if (!IsFinite(command.DirectionX) || !IsFinite(command.PositionZ))
return false;
var length = Math.Sqrt(command.DirectionX * command.DirectionX + command.PositionZ * command.PositionZ);
if (length <= 0.000001)
return false;
return ApplyCurrentEntity(run, command, entity =>
{
entity.DirectionX = command.DirectionX;
entity.DirectionY = command.PositionZ;
entity.DirectionX = command.DirectionX / length;
entity.DirectionY = command.PositionZ / length;
});
}