Merge eureka/aetheria-release-sim-speed: one SimClock steps the zone, presenters draw ahead by Lead

AetherDrive.cs: master deleted the behaviour (2cfdc728); the branch only added a
TurnRate line to it. Deletion kept. Thruster remains the one rotation actuator
and feeds Entity.TurnRate. No sim stepping outside the clock on master
(mines presenter, Pirates AI, lot-product all step through Zone.Update).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-09 02:29:37 +02:00
commit f28d4b4b12
10 changed files with 508 additions and 38 deletions

View file

@ -177,8 +177,6 @@ public class ActionGameManager : MonoBehaviour
public Sprite ShieldIcon;
public Sprite NoShieldIcon;
public float IntroDuration;
//public PlayerInput Input;
// private CinemachineFramingTransposer _transposer;
@ -231,6 +229,8 @@ public class ActionGameManager : MonoBehaviour
public ItemManager ItemManager { get; private set; }
public Zone Zone { get; private set; }
public static SimClock Clock { get; } = new SimClock(1f / 60f);
private bool _zoneEntered;
private readonly (float2 direction, string name)[] _directions = {
(float2(0, 1), "Front"),
@ -728,6 +728,7 @@ public class ActionGameManager : MonoBehaviour
galaxyZone.Contents = new Zone(ItemManager, Settings.PlanetSettings, galaxyZone.PackedContents, galaxyZone, CurrentGalaxy);
}
Zone = galaxyZone.Contents;
_zoneEntered = true; // the clock forgets its lead between frames, never inside a step
PlayMusic(MusicType.Overworld);
Zone.Log = s => Debug.Log($"Zone: {s}");
@ -818,7 +819,6 @@ public class ActionGameManager : MonoBehaviour
}
else
{
//StartCoroutine(IntroCutscene(targetEntity as Ship));
BindToEntity(targetEntity);
}
@ -866,35 +866,6 @@ public class ActionGameManager : MonoBehaviour
BindToEntity(staged.Player);
}
private IEnumerator IntroCutscene(Ship ship)
{
ZoneRenderer.PerspectiveEntity = ship;
var entityPosition = ship.Position.xz;
var followOrbit = Zone.Orbits.Keys.MinBy(o => lengthsq(Zone.GetOrbitPosition(o) - entityPosition));
var followPlanet = ZoneRenderer.Planets[Zone.Planets.FirstOrDefault(p => p.Value.Orbit.Key.Equals(followOrbit)).Key];
DockCamera.Follow = followPlanet.Body.transform;
var rootOrbit = followOrbit;
while (Zone.Orbits[rootOrbit].Data.Parent.IsSet())
rootOrbit = Zone.Orbits[rootOrbit].Data.Parent.Key;
var rootPlanet = ZoneRenderer.Planets[Zone.Planets.FirstOrDefault(p => p.Value.Orbit.Key.Equals(rootOrbit)).Key];
DockCamera.LookAt = rootPlanet.Body.transform;
var shipVelocity = ship.GetBehavior<VelocityLimit>().Limit;
var followOrbitPosition = Zone.GetOrbitPosition(followOrbit);
var shipDirection = normalize(Zone.GetOrbitPosition(rootOrbit) - followOrbitPosition);
ship.Position.xz = followOrbitPosition - shipDirection * shipVelocity * IntroDuration;
var startTime = Time.time;
while (Time.time - startTime < IntroDuration)
{
ship.Direction = shipDirection;
ship.Velocity = shipDirection * shipVelocity;
yield return null;
}
BindToEntity(ship);
}
public void Dock()
{
if (CurrentEntity.Parent != null) return;
@ -1356,8 +1327,14 @@ public class ActionGameManager : MonoBehaviour
CurrentEntity.TractorPower =
saturate(CurrentEntity.TractorPower + sign(tractorPower - CurrentEntity.TractorPower) * Time.deltaTime * 2);
}
Zone.Update(Time.deltaTime);
}
// One clock steps the zone, paused or not: a paused frame feeds it no real time.
// A zone entered inside a step (a wormhole) ends this frame's stepping: the rest of its steps are the old zone's.
void EnterNewZone() { if (_zoneEntered) { Clock.Reset(); _zoneEntered = false; } }
EnterNewZone();
var steppedZone = Zone;
Clock.Advance(_paused ? 0f : Time.deltaTime, delta => { if (Zone == steppedZone) steppedZone.Update(delta); });
EnterNewZone();
}
private static string ResultLabel(ShotResult result) => result switch

View file

@ -416,9 +416,10 @@ public class EntityInstance : MonoBehaviour
var direction = FireControl.Solution(weapon, Entity, Entity.Target.Value).Direction;
group.Value.position = barrel + new Vector3(direction.x, 0, direction.y) * aimDistance;
}
LocalSpace.localPosition = transform.position = Entity.Position.ToUnity();
var drawn = DrawAhead.Position(Entity, ActionGameManager.Clock.Lead);
LocalSpace.localPosition = transform.position = drawn.ToUnity();
if (_influenceInstance)
_influenceInstance.position = new Vector3(Entity.Position.x, 0, Entity.Position.z);
_influenceInstance.position = new Vector3(drawn.x, 0, drawn.z);
}
public virtual void OnDestroy()

View file

@ -102,6 +102,6 @@ public class ShipInstance : EntityInstance
emissionModule.rateOverTimeMultiplier = thrusterInstance.BaseEmission * thrusterInstance.Thruster.Axis * thrusterInstance.Thruster.Condition;
}
transform.rotation = Ship.Rotation.ToUnity();
transform.rotation = DrawAhead.Rotation(Ship, ActionGameManager.Clock.Lead).ToUnity();
}
}