Pass explicit grounded/airborne contact bytes from MovementResult into MoveToState and AutonomousPosition, and add ACDREAM_DUMP_MOVE_TRUTH logging for outbound movement plus player UpdatePosition echoes. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
d4c3f947d2
commit
3be0c8b7c7
5 changed files with 166 additions and 56 deletions
|
|
@ -409,6 +409,8 @@ public sealed class GameWindow : IDisposable
|
|||
private AcDream.UI.Abstractions.Panels.Debug.DebugVM? _debugVm;
|
||||
private static readonly bool DevToolsEnabled =
|
||||
Environment.GetEnvironmentVariable("ACDREAM_DEVTOOLS") == "1";
|
||||
private static readonly bool DumpMoveTruthEnabled =
|
||||
Environment.GetEnvironmentVariable("ACDREAM_DUMP_MOVE_TRUTH") == "1";
|
||||
|
||||
// Phase I.3 — real ICommandBus for live sessions. Constructed when
|
||||
// the live session spins up (so SendChatCmd handlers can close over
|
||||
|
|
@ -464,6 +466,19 @@ public sealed class GameWindow : IDisposable
|
|||
private uint? _playerCurrentAnimCommand;
|
||||
private float _playerCurrentAnimSpeed = 1f;
|
||||
private uint? _playerMotionTableId; // server-sent MotionTable override for the player's character
|
||||
private MovementTruthOutbound? _lastMovementTruthOutbound;
|
||||
|
||||
private readonly record struct MovementTruthOutbound(
|
||||
string Kind,
|
||||
uint Sequence,
|
||||
System.DateTime TimeUtc,
|
||||
System.Numerics.Vector3 LocalWorldPosition,
|
||||
uint LocalCellId,
|
||||
System.Numerics.Vector3 WirePosition,
|
||||
uint WireCellId,
|
||||
bool IsOnGround,
|
||||
byte ContactByte,
|
||||
System.Numerics.Vector3 Velocity);
|
||||
|
||||
// K-fix7 (2026-04-26): server-authoritative Run + Jump skill values
|
||||
// received from PlayerDescription. -1 = "not yet received, fall back
|
||||
|
|
@ -3076,6 +3091,7 @@ public sealed class GameWindow : IDisposable
|
|||
0f);
|
||||
var worldPos = new System.Numerics.Vector3(p.PositionX, p.PositionY, p.PositionZ) + origin;
|
||||
var rot = new System.Numerics.Quaternion(p.RotationX, p.RotationY, p.RotationZ, p.RotationW);
|
||||
DumpMovementTruthServerEcho(update, worldPos);
|
||||
|
||||
// Capture the pre-update render position for the soft-snap residual
|
||||
// calculation below. Assign entity.Position to the server truth up
|
||||
|
|
@ -4853,6 +4869,7 @@ public sealed class GameWindow : IDisposable
|
|||
uint wireCellId = ((uint)lbX << 24) | ((uint)lbY << 16) | (result.CellId & 0xFFFFu);
|
||||
var wirePos = new System.Numerics.Vector3(localX, localY, result.Position.Z);
|
||||
var wireRot = YawToAcQuaternion(_playerController.Yaw);
|
||||
byte contactByte = result.IsOnGround ? (byte)1 : (byte)0;
|
||||
|
||||
if (result.MotionStateChanged)
|
||||
{
|
||||
|
|
@ -4885,7 +4902,10 @@ public sealed class GameWindow : IDisposable
|
|||
instanceSequence: _liveSession.InstanceSequence,
|
||||
serverControlSequence: _liveSession.ServerControlSequence,
|
||||
teleportSequence: _liveSession.TeleportSequence,
|
||||
forcePositionSequence: _liveSession.ForcePositionSequence);
|
||||
forcePositionSequence: _liveSession.ForcePositionSequence,
|
||||
contactLongJump: contactByte);
|
||||
DumpMovementTruthOutbound(
|
||||
"MTS", seq, result, wirePos, wireCellId, contactByte);
|
||||
_liveSession.SendGameAction(body);
|
||||
}
|
||||
|
||||
|
|
@ -4900,7 +4920,10 @@ public sealed class GameWindow : IDisposable
|
|||
instanceSequence: _liveSession.InstanceSequence,
|
||||
serverControlSequence: _liveSession.ServerControlSequence,
|
||||
teleportSequence: _liveSession.TeleportSequence,
|
||||
forcePositionSequence: _liveSession.ForcePositionSequence);
|
||||
forcePositionSequence: _liveSession.ForcePositionSequence,
|
||||
lastContact: contactByte);
|
||||
DumpMovementTruthOutbound(
|
||||
"AP", seq, result, wirePos, wireCellId, contactByte);
|
||||
_liveSession.SendGameAction(body);
|
||||
}
|
||||
|
||||
|
|
@ -4924,6 +4947,76 @@ public sealed class GameWindow : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
private void DumpMovementTruthOutbound(
|
||||
string kind,
|
||||
uint sequence,
|
||||
AcDream.App.Input.MovementResult result,
|
||||
System.Numerics.Vector3 wirePosition,
|
||||
uint wireCellId,
|
||||
byte contactByte)
|
||||
{
|
||||
if (!DumpMoveTruthEnabled) return;
|
||||
|
||||
var velocity = _playerController?.BodyVelocity ?? System.Numerics.Vector3.Zero;
|
||||
_lastMovementTruthOutbound = new MovementTruthOutbound(
|
||||
kind,
|
||||
sequence,
|
||||
System.DateTime.UtcNow,
|
||||
result.Position,
|
||||
result.CellId,
|
||||
wirePosition,
|
||||
wireCellId,
|
||||
result.IsOnGround,
|
||||
contactByte,
|
||||
velocity);
|
||||
|
||||
Console.WriteLine(System.FormattableString.Invariant($"move-truth OUT kind={kind} seq={sequence} local={Fmt(result.Position)} localCell=0x{result.CellId:X8} wire={Fmt(wirePosition)} wireCell=0x{wireCellId:X8} grounded={result.IsOnGround} contact={contactByte} vel={Fmt(velocity)} f={FmtCmd(result.ForwardCommand)} s={FmtCmd(result.SidestepCommand)} t={FmtCmd(result.TurnCommand)}"));
|
||||
}
|
||||
|
||||
private void DumpMovementTruthServerEcho(
|
||||
AcDream.Core.Net.WorldSession.EntityPositionUpdate update,
|
||||
System.Numerics.Vector3 serverWorldPosition)
|
||||
{
|
||||
if (!DumpMoveTruthEnabled || update.Guid != _playerServerGuid) return;
|
||||
|
||||
var now = System.DateTime.UtcNow;
|
||||
var localPosition = _playerController?.Position;
|
||||
var localCellId = _playerController?.CellId;
|
||||
var deltaLocal = localPosition.HasValue
|
||||
? serverWorldPosition - localPosition.Value
|
||||
: (System.Numerics.Vector3?)null;
|
||||
|
||||
string localText = localPosition.HasValue ? Fmt(localPosition.Value) : "-";
|
||||
string localCellText = localCellId.HasValue
|
||||
? System.FormattableString.Invariant($"0x{localCellId.Value:X8}")
|
||||
: "-";
|
||||
string deltaLocalText = deltaLocal.HasValue ? Fmt(deltaLocal.Value) : "-";
|
||||
string deltaLocalLen = deltaLocal.HasValue
|
||||
? System.FormattableString.Invariant($"{deltaLocal.Value.Length():F3}")
|
||||
: "-";
|
||||
|
||||
string lastText = "-";
|
||||
if (_lastMovementTruthOutbound is { } last)
|
||||
{
|
||||
var deltaOut = serverWorldPosition - last.LocalWorldPosition;
|
||||
var ageMs = (now - last.TimeUtc).TotalMilliseconds;
|
||||
lastText = System.FormattableString.Invariant($"{last.Kind}:{last.Sequence} ageMs={ageMs:F0} outGrounded={last.IsOnGround} outContact={last.ContactByte} outCell=0x{last.WireCellId:X8} deltaOut={Fmt(deltaOut)} distOut={deltaOut.Length():F3}");
|
||||
}
|
||||
|
||||
string state = _playerController?.State.ToString() ?? "-";
|
||||
string velocityText = update.Velocity.HasValue ? Fmt(update.Velocity.Value) : "-";
|
||||
|
||||
Console.WriteLine(System.FormattableString.Invariant($"move-truth ECHO guid=0x{update.Guid:X8} server={Fmt(serverWorldPosition)} serverCell=0x{update.Position.LandblockId:X8} local={localText} localCell={localCellText} deltaLocal={deltaLocalText} distLocal={deltaLocalLen} serverVel={velocityText} state={state} lastOut={lastText}"));
|
||||
}
|
||||
|
||||
private static string Fmt(System.Numerics.Vector3 v) =>
|
||||
System.FormattableString.Invariant($"({v.X:F3},{v.Y:F3},{v.Z:F3})");
|
||||
|
||||
private static string FmtCmd(uint? command) =>
|
||||
command.HasValue
|
||||
? System.FormattableString.Invariant($"0x{command.Value:X8}")
|
||||
: "-";
|
||||
|
||||
/// <summary>
|
||||
/// Convert our internal yaw (math convention: 0=+X East, PI/2=+Y North)
|
||||
/// to AC's quaternion heading convention.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue