From 1fe5109c0dcf53911ee5f416f0ac1bc227f28c73 Mon Sep 17 00:00:00 2001 From: Mateus Rodrigues Date: Sat, 9 May 2026 03:32:36 -0300 Subject: [PATCH] feat(client): consumir yaw do snapshot quantizado v3 (Etapa 7) Etapa 7 do refactor de networking server-side bumpou o protocolo para v3 e passou a enviar yaw no S_PLAYER_STATE (campo novo no payload). Cliente agora consome esse yaw via TryGetLastPlayerStateExtended do plugin ZeusNetwork (cache local com YawDeg + Flags). Antes (v2): - S_PLAYER_STATE nao tinha yaw. Comentario do codigo dizia exatamente "Yaw nao chega no opcode S_PLAYER_STATE actual; derivamos do XY da velocidade quando significativo, caso contrario mantemos rotacao do ator." Resultado: proxy parado nao girava, e proxy em movimento ficava com yaw inferido (impreciso quando vel pequena). Depois (v3): - HandlePlayerStateUpdate consulta TryGetLastPlayerStateExtended para pegar YawDeg + Flags do cache do plugin (populado pelo parser v3). - Se PSF_HasYaw esta set, usa o YawDeg autoritativo do servidor. - Caso contrario, fallback antigo (atan2 da vel ou rotacao do ator), preservando comportamento se algum dia o flag vier desligado. Validacao runtime (~5 min, 2 clients UE conectados ao server v3): - Connected sessionId=1 e =2 (handshake v3 OK). - parseRej=0 no servidor (cliente fala v3). - Proxies giram conforme yaw autoritativo (visual; nao tem metrica numerica para isso). Depende de: - ZeusNetwork plugin v3 (commit 3b97500 no repo ZeusServerEngine). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ZMMO/Game/Network/ZMMOWorldSubsystem.cpp | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/Source/ZMMO/Game/Network/ZMMOWorldSubsystem.cpp b/Source/ZMMO/Game/Network/ZMMOWorldSubsystem.cpp index b65fa04..f5ce148 100644 --- a/Source/ZMMO/Game/Network/ZMMOWorldSubsystem.cpp +++ b/Source/ZMMO/Game/Network/ZMMOWorldSubsystem.cpp @@ -195,15 +195,45 @@ void UZMMOWorldSubsystem::HandlePlayerStateUpdate(const int32 EntityId, const in Snapshot.LastProcessedInputSeq = InputSeq; Snapshot.PositionCm = PosCm; Snapshot.VelocityCmS = VelCmS; - // Yaw nao chega no opcode S_PLAYER_STATE actual; derivamos do XY da - // velocidade quando significativo, caso contrario mantemos rotacao do ator. - if (!FVector(VelCmS.X, VelCmS.Y, 0.0f).IsNearlyZero(1.0f)) + + // Etapa 7 (server-side networking refactor): yaw agora chega no + // snapshot quantizado v3. Buscamos via TryGetLastPlayerStateExtended + // (cache local do plugin). Se PSF_HasYaw nao estiver set ou se o cache + // nao tiver entrada, caimos no fallback antigo (derivar do XY da + // velocidade ou manter rotacao do ator). + bool bYawFromSnapshot = false; + if (UZeusNetworkSubsystem* ZeusNet = ResolveZeusNetworkSubsystem()) { - Snapshot.YawDeg = FMath::RadiansToDegrees(FMath::Atan2(VelCmS.Y, VelCmS.X)); + int32 CachedInputSeq = 0; + FVector CachedPos = FVector::ZeroVector; + FVector CachedVel = FVector::ZeroVector; + float CachedYawDeg = 0.f; + int32 CachedFlags = 0; + int64 CachedServerTimeMs = 0; + if (ZeusNet->TryGetLastPlayerStateExtended( + EntityId, CachedInputSeq, CachedPos, CachedVel, + CachedYawDeg, CachedFlags, CachedServerTimeMs)) + { + constexpr int32 PSF_HasYaw = 1 << 5; + if ((CachedFlags & PSF_HasYaw) != 0) + { + Snapshot.YawDeg = CachedYawDeg; + bYawFromSnapshot = true; + } + } } - else + if (!bYawFromSnapshot) { - Snapshot.YawDeg = Actor->GetActorRotation().Yaw; + // Fallback: deriva yaw do XY da velocidade quando significativo; + // caso contrario mantem rotacao do ator (comportamento pre-Etapa 7). + if (!FVector(VelCmS.X, VelCmS.Y, 0.0f).IsNearlyZero(1.0f)) + { + Snapshot.YawDeg = FMath::RadiansToDegrees(FMath::Atan2(VelCmS.Y, VelCmS.X)); + } + else + { + Snapshot.YawDeg = Actor->GetActorRotation().Yaw; + } } Snapshot.bGrounded = bGrounded; Snapshot.ServerTimeMs = ServerTimeMs;