diff --git a/Content/ZMMO/Data/World/DT_Maps.uasset b/Content/ZMMO/Data/World/DT_Maps.uasset index fd76096..be9dffc 100644 Binary files a/Content/ZMMO/Data/World/DT_Maps.uasset and b/Content/ZMMO/Data/World/DT_Maps.uasset differ diff --git a/Content/__ExternalActors__/ZMMO/Maps/World/L_TestWorld/2/BR/38W34OMKW0W3L1PGS3Y98G.uasset b/Content/__ExternalActors__/ZMMO/Maps/World/L_TestWorld/2/BR/38W34OMKW0W3L1PGS3Y98G.uasset deleted file mode 100644 index 3e4faf3..0000000 Binary files a/Content/__ExternalActors__/ZMMO/Maps/World/L_TestWorld/2/BR/38W34OMKW0W3L1PGS3Y98G.uasset and /dev/null differ diff --git a/Content/__ExternalActors__/ZMMO/Maps/World/L_TestWorld/4/8L/X3PMRJRGAACIU1WG1P1KJ0.uasset b/Content/__ExternalActors__/ZMMO/Maps/World/L_TestWorld/4/8L/X3PMRJRGAACIU1WG1P1KJ0.uasset deleted file mode 100644 index 2552681..0000000 Binary files a/Content/__ExternalActors__/ZMMO/Maps/World/L_TestWorld/4/8L/X3PMRJRGAACIU1WG1P1KJ0.uasset and /dev/null differ diff --git a/Content/__ExternalActors__/ZMMO/Maps/World/L_TestWorld/8/L1/C6M65Q91PG5E7ML91VQZX3.uasset b/Content/__ExternalActors__/ZMMO/Maps/World/L_TestWorld/8/L1/C6M65Q91PG5E7ML91VQZX3.uasset deleted file mode 100644 index 059ff5a..0000000 Binary files a/Content/__ExternalActors__/ZMMO/Maps/World/L_TestWorld/8/L1/C6M65Q91PG5E7ML91VQZX3.uasset and /dev/null differ diff --git a/Source/ZMMO/Game/Entity/ZeusPlayerProxy.cpp b/Source/ZMMO/Game/Entity/ZeusPlayerProxy.cpp index 574cb68..eb1ed6d 100644 --- a/Source/ZMMO/Game/Entity/ZeusPlayerProxy.cpp +++ b/Source/ZMMO/Game/Entity/ZeusPlayerProxy.cpp @@ -222,13 +222,33 @@ void AZeusPlayerProxy::SetZeusIdentity(const int64 InEntityId, const EZeusEntity void AZeusPlayerProxy::ApplyEntitySnapshot(const FZeusEntitySnapshot& Snapshot) { - // Estabiliza o offset de relogio na primeira amostra. Subsequente nao - // re-sincroniza para evitar saltos visuais; um esquema mais sofisticado - // (ema do offset) cabe quando tivermos ping/RTT estabilizado por sessao. + // 2026-06-06 H3 fix — disciplina o ServerClockOffsetMs via EMA com clamp. + // Antes: offset congelado na 1a amostra. Em cross-server handoff a fonte + // do ServerTimeMs muda (publisher antigo -> novo) e o offset fica + // permanentemente skewed, alimentando tremor pos-handoff e drift cumulativo + // de clock cliente vs server. Agora cada amostra recalcula candidato e + // suaviza (alpha=0.02, ~50 amostras pra convergir) com clamp max 2ms/snapshot + // pra evitar salto visual durante transicao. + const int64 LocalNowMs = static_cast(FPlatformTime::Seconds() * 1000.0); + const int64 OffsetCandidate = LocalNowMs - Snapshot.ServerTimeMs; if (SnapshotBuffer.Num() == 0) { - const int64 LocalNowMs = static_cast(FPlatformTime::Seconds() * 1000.0); - ServerClockOffsetMs = LocalNowMs - Snapshot.ServerTimeMs; + // Primeira amostra: bootstrap direto (nao tem baseline pra suavizar). + ServerClockOffsetMs = OffsetCandidate; + } + else + { + const double Alpha = 0.02; + const int64 RawTarget = static_cast( + static_cast(ServerClockOffsetMs) * (1.0 - Alpha) + + static_cast(OffsetCandidate) * Alpha); + // Clamp max 2ms por amostra — em 30Hz isso converge a 60ms/s, mais que + // o suficiente pra absorver drift normal sem causar tremor visual. + const int64 Delta = RawTarget - ServerClockOffsetMs; + const int64 ClampedDelta = (Delta > 2) ? 2 + : (Delta < -2) ? -2 + : Delta; + ServerClockOffsetMs += ClampedDelta; } FZeusProxySnapshot S;