Files
ZMMO/Source/ZMMO/Game/Entity/ZeusPlayerProxy.h
Mateus Rodrigues 6a6a28a086 refactor: prefixo ZMMO -> Zeus em classes/módulos C++ do cliente
- 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>
2026-06-02 17:24:38 -03:00

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();
};