- Renomeia ~50 classes UCLASS/USTRUCT/UENUM/UINTERFACE pra Zeus* (AZeusGameMode, AZeusCharacter, UZeusGameInstance, IZeusEntityInterface, UZeusWorldSubsystem, FZeusEntitySnapshot, etc.) - Encurta AZMMOPlayerCharacter -> AZeusCharacter - Renomeia módulos satélite ZMMOAttributes -> ZeusAttributes e ZMMOJobs -> ZeusJobs (pasta + .Build.cs + .uproject) - Mantém módulo principal ZMMO (renomeia depois quando jogo ganhar nome) - DefaultEngine.ini: ActiveClassRedirects ZMMOX -> ZeusX (preserva BPs/assets) - DefaultGame.ini: sections atualizadas pra ZeusThemeSubsystem/ZeusPlayerState - Category="ZMMO|..." -> "Zeus|..." em UPROPERTYs - Preserva LogZMMO, ZMMO_API, /Script/ZMMO., /Game/ZMMO/, classes Target Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
165 lines
6.2 KiB
C++
165 lines
6.2 KiB
C++
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "GameFramework/Character.h"
|
|
#include "ZeusEntityInterface.h"
|
|
#include "ZeusEntityTypes.h"
|
|
#include "ZeusPlayerProxy.generated.h"
|
|
|
|
/**
|
|
* AZeusPlayerProxy
|
|
*
|
|
* Proxy visual para jogadores remotos (e, no futuro, mobs com locomotion
|
|
* por capsula) cuja posicao vem 100% do servidor via snapshots
|
|
* (`UZeusNetworkSubsystem::OnPlayerStateUpdate`).
|
|
*
|
|
* Diferencas chave vs. `AZeusCharacter` (jogador local):
|
|
* - SEM `EnhancedInput`, sem envio de `C_INPUT_AXIS`.
|
|
* - SEM buffer de pending inputs nem reconciliacao.
|
|
* - Posicao aplicada por snapshot (`ApplyEntitySnapshot`); a `ACharacter`
|
|
* continua a existir para preservar capsula + skeletal mesh + AnimBP,
|
|
* mas o CMC fica em modo "kinematic-ish" (nao integra fisica).
|
|
*
|
|
* Animacao no AnimBP do Quinn (`ABP_Unarmed`): a formula `ShouldMove` exige
|
|
* `Acceleration != 0`. Como proxies nao tem input, adoptamos a estrategia
|
|
* de CMC custom (`UZeusProxyMovementComponent`) com escrita externa de
|
|
* `Acceleration`, alimentada pela derivada da velocidade entre snapshots.
|
|
* Tick do proxy roda **antes** do mesh tick para que Velocity+Acceleration
|
|
* estejam populados quando o `NativeUpdateAnimation` do AnimBP os ler.
|
|
*/
|
|
/**
|
|
* Snapshot bruto guardado no buffer de interpolacao. Mantido como struct privada
|
|
* ao .h porque so o proxy (e debugging local) precisa olhar para ele.
|
|
*/
|
|
USTRUCT()
|
|
struct FZeusProxySnapshot
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
UPROPERTY()
|
|
FVector PosCm = FVector::ZeroVector;
|
|
|
|
UPROPERTY()
|
|
FVector VelCmS = FVector::ZeroVector;
|
|
|
|
UPROPERTY()
|
|
bool bGrounded = true;
|
|
|
|
/** Timestamp do servidor que produziu o snapshot (ms desde Unix epoch). */
|
|
UPROPERTY()
|
|
int64 ServerTimeMs = 0;
|
|
};
|
|
|
|
UCLASS(Blueprintable, BlueprintType)
|
|
class ZMMO_API AZeusPlayerProxy : public ACharacter, public IZeusEntityInterface
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
AZeusPlayerProxy(const FObjectInitializer& ObjectInitializer);
|
|
|
|
virtual void BeginPlay() override;
|
|
virtual void Tick(float DeltaSeconds) override;
|
|
|
|
// --- IZeusEntityInterface ---
|
|
virtual int64 GetZeusEntityId() const override { return EntityId; }
|
|
virtual EZeusEntityType GetZeusEntityType() const override { return EntityType; }
|
|
virtual void ApplyEntitySnapshot(const FZeusEntitySnapshot& Snapshot) override;
|
|
virtual void SetEntityRelevant(bool bRelevant) override;
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Zeus|Entity")
|
|
void SetZeusIdentity(int64 InEntityId, EZeusEntityType InEntityType);
|
|
|
|
protected:
|
|
UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = "Zeus|Entity")
|
|
int64 EntityId = 0;
|
|
|
|
UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = "Zeus|Entity")
|
|
EZeusEntityType EntityType = EZeusEntityType::Player;
|
|
|
|
UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = "Zeus|Entity")
|
|
bool bIsZeusRelevant = true;
|
|
|
|
/** True apos o primeiro snapshot ser aplicado — antes disso o ator pode ficar oculto. */
|
|
UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = "Zeus|Entity")
|
|
bool bHasFirstSnapshot = false;
|
|
|
|
/**
|
|
* Ultima posicao **autoritativa** recebida do servidor (cm, mundo). Difere
|
|
* de `InterpolatedPosCm` (visual) — separar os dois e essencial para
|
|
* comparar drift autoritativo vs visual via debug overlay/logs.
|
|
*/
|
|
UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = "Zeus|Entity")
|
|
FVector AuthoritativePosCm = FVector::ZeroVector;
|
|
|
|
/** Posicao **visual** atual (resultado da interpolacao do tick). */
|
|
UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = "Zeus|Entity")
|
|
FVector InterpolatedPosCm = FVector::ZeroVector;
|
|
|
|
/** Compat: alias para `AuthoritativePosCm` (preserva binding de Blueprint, se houver). */
|
|
UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = "Zeus|Entity")
|
|
FVector LastSnapshotPosition = FVector::ZeroVector;
|
|
|
|
/**
|
|
* Velocidade visual derivada para o AnimBP. Espelha a velocidade
|
|
* *interpolada* (nao o snapshot bruto) e e re-imposta no `CMC->Velocity`
|
|
* em cada `Tick` para manter os drivers de animacao alimentados entre
|
|
* updates de rede.
|
|
*/
|
|
UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = "Zeus|Entity")
|
|
FVector VisualVelocity = FVector::ZeroVector;
|
|
|
|
/**
|
|
* Atraso de interpolacao em ms. Render-time = wall_now - InterpolationDelayMs,
|
|
* expresso no dominio do tempo do servidor. Padrao 100 ms (~3 snapshots a 30 Hz)
|
|
* cobre 1 perda + 1 jitter sem extrapolar.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Zeus|Network",
|
|
meta = (ClampMin = "0.0", ClampMax = "500.0"))
|
|
double InterpolationDelayMs = 100.0;
|
|
|
|
/** Tamanho maximo do buffer (em snapshots). Cobre ~270 ms a 30 Hz. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Zeus|Network",
|
|
meta = (ClampMin = "2", ClampMax = "32"))
|
|
int32 SnapshotBufferCapacity = 8;
|
|
|
|
/** Limite duro de extrapolacao (s) quando nao ha snapshot futuro. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Zeus|Network",
|
|
meta = (ClampMin = "0.0", ClampMax = "0.5"))
|
|
float MaxExtrapolationSeconds = 0.1f;
|
|
|
|
/** Buffer ordenado por `ServerTimeMs` ascendente. */
|
|
UPROPERTY()
|
|
TArray<FZeusProxySnapshot> SnapshotBuffer;
|
|
|
|
/**
|
|
* Offset entre o relogio local (`FPlatformTime::Seconds * 1000`) e o
|
|
* relogio do servidor (`ServerTimeMs` do snapshot). Estimado pela primeira
|
|
* amostra como `local_now_ms - server_time_ms`. Subtraindo este offset do
|
|
* relogio local obtemos o tempo do servidor estimado.
|
|
*/
|
|
int64 ServerClockOffsetMs = 0;
|
|
|
|
/** Aceleracao derivada (com smoothing) escrita no CMC custom para alimentar
|
|
* o AnimBP (`ShouldMove`/`Jump_Start` exigem Acceleration!=0). */
|
|
FVector LastDerivedAccelerationCmS2 = FVector::ZeroVector;
|
|
|
|
/** Velocidade visual do tick anterior (para a derivada `Acceleration = dV/dt`). */
|
|
FVector PreviousVisualVelocity = FVector::ZeroVector;
|
|
|
|
bool bHasPreviousSnapshot = false;
|
|
|
|
/** Ultimo log de diagnostico (s, monotonic). Log emitido 1x/s no Tick. */
|
|
double LastDiagLogSec = 0.0;
|
|
|
|
private:
|
|
/** Reaplica `CMC->Velocity` (com clamp de Z em walking) e injeta a
|
|
* aceleracao derivada no CMC custom. Chamado em `Tick` (pre-mesh) e em
|
|
* `ApplyEntitySnapshot` (para refletir a chegada de novo snapshot
|
|
* imediatamente). */
|
|
void RefreshAnimationDrivers();
|
|
|
|
/** Liga/desliga colisao da capsula consoante a relevancia + visual ready. */
|
|
void ApplyCollisionPolicy();
|
|
};
|