Files
ZMMO/Source/ZMMO/Game/Modes/ZMMOPlayerState.h
Mateus Rodrigues 90484876f0 feat(player): CharName do DB no PlayerState + header do Status Window
- PlayerState ganha CharName (Replicated) + SetCharInfo(CharName, GuildName)
- ZMMOPlayerCharacter assina FZeusOnCharInfoReceived; TryApplyCachedCharInfo
  resolve race se S_CHAR_INFO chega antes do pawn possuir
- UIPlayerStatus_Window header le PlayerState->CharName (fallback p/ GetPlayerName)
  em vez do "Mateuus-61E9B19A4FB2" generico

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 02:24:29 -03:00

125 lines
4.7 KiB
C++

#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerState.h"
#include "Templates/SubclassOf.h"
#include "ZMMOPlayerState.generated.h"
class FLifetimeProperty;
class UActorComponent;
/**
* PlayerState do MMO. Pattern UE5 idiomatico: o GameMode atribui
* `PlayerStateClass`, engine cria 1 instancia por PlayerController.
*
* Responsabilidade — estado **publico** do jogador (visivel pra outros):
* - Identidade: charId, entityId, name, guild
* - Progressao publica: baseLevel, classId
* - Estado: alive/dead, in-combat (futuro)
*
* Dados PRIVADOS (HP/SP atuais, stats brutos, inventory, hotbar) vivem
* em componentes anexados via Component Registry (vide abaixo).
*
* Por que componentes no PlayerState e nao no Pawn:
* - **Sobrevive ao despawn** (morte/respawn — Pawn destrui, PlayerState
* mantem). Padrao MMO classico (rathena, TrinityCore).
* - **Spectator-friendly**: dados acessiveis sem ter pawn.
* - **1:1 com player** (Pawn pode trocar — vehicle, mount, possession).
*
* ## Component Registry (Open-Closed)
*
* Cada modulo (ZMMOAttributes, ZMMOInventory, ZMMOSkills futuros) declara
* sua component class em DefaultGame.ini:
*
* [/Script/ZMMO.ZMMOPlayerState]
* +ComponentClasses=/Script/ZMMOAttributes.ZMMOAttributeComponent
* +ComponentClasses=/Script/ZMMOInventory.ZMMOInventoryComponent
* +ComponentClasses=/Script/ZMMOSkills.ZMMOSkillComponent
*
* O construtor de AZMMOPlayerState le essa lista (Config) e instancia
* cada classe como subobject. PlayerState fica fechado pra modificacao,
* modulos abertos pra extensao — adicionar Inventory NAO requer
* recompilar/editar AZMMOPlayerState.
*
* Acesso: `PlayerState->FindComponentByClass<UZMMOAttributeComponent>()`
* ou o helper `GetZMMOComponent<T>()`.
*/
UCLASS(Config = Game, BlueprintType)
class ZMMO_API AZMMOPlayerState : public APlayerState
{
GENERATED_BODY()
public:
AZMMOPlayerState();
// === Identidade publica ===
//
// Todos os campos publicos sao Replicated — hoje o cliente UE5 roda em
// Standalone (servidor C++ standalone, sem replicacao UE5 ativa), entao
// a marca nao tem efeito em runtime; deixa a classe pronta caso o projeto
// passe a usar dedicated UE5 no futuro.
/** EntityId autoritativo do server. 0 ate o spawn local confirmar. */
UPROPERTY(Replicated, VisibleInstanceOnly, BlueprintReadOnly, Category = "ZMMO|Identity")
int64 ZMMOEntityId = 0;
/** CharId (BIGINT no DB; FString pra preservar 64 bits em Blueprint). */
UPROPERTY(Replicated, VisibleInstanceOnly, BlueprintReadOnly, Category = "ZMMO|Identity")
FString CharId;
/** Nome do char vindo do DB (`characters.name`). Setado por
* AZMMOPlayerCharacter::HandleLocalSpawnReady com o payload do
* S_SPAWN_PLAYER. UI prefere isto a APlayerState::GetPlayerName(). */
UPROPERTY(Replicated, VisibleInstanceOnly, BlueprintReadOnly, Category = "ZMMO|Identity")
FString CharName;
// === Progressao publica ===
UPROPERTY(Replicated, VisibleInstanceOnly, BlueprintReadOnly, Category = "ZMMO|Progress")
int32 BaseLevel = 1;
UPROPERTY(Replicated, VisibleInstanceOnly, BlueprintReadOnly, Category = "ZMMO|Progress")
int32 ClassId = 0;
// === Guild (futuro) ===
UPROPERTY(Replicated, VisibleInstanceOnly, BlueprintReadOnly, Category = "ZMMO|Guild")
FString GuildName;
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
// === Helpers ===
/// Setado por AZMMOPlayerCharacter::HandleLocalSpawnReady (pose/EntityId)
/// e atualizado por handlers de snapshot/level up para refletir dados
/// publicos do char no PlayerState.
UFUNCTION(BlueprintCallable, Category = "ZMMO|Identity")
void SetPublicIdentity(int64 InEntityId, const FString& InCharId,
int32 InBaseLevel, int32 InClassId);
/// Setado pelo handler do S_CHAR_INFO (chega antes de S_SPAWN_PLAYER) —
/// metadados publicos do char vindos do servidor.
UFUNCTION(BlueprintCallable, Category = "ZMMO|Identity")
void SetCharInfo(const FString& InCharName, const FString& InGuildName);
/// Template helper: PS->GetZMMOComponent<UZMMOAttributeComponent>()
template <typename T>
T* GetZMMOComponent() const
{
return Cast<T>(FindComponentByClass(T::StaticClass()));
}
protected:
/**
* Component Registry — config-driven. Modulos registram suas classes
* via DefaultGame.ini com prefix `+`. Construtor instancia cada uma
* como CreateDefaultSubobject.
*
* TSubclassOf (nao TSoftClassPtr): config UE resolve classes nativas
* diretamente. Modulos C++ precisam estar carregados antes do CDO ser
* instanciado — garantido por LoadingPhase=PreDefault no .uproject.
*/
UPROPERTY(Config, EditDefaultsOnly, Category = "ZMMO|Components")
TArray<TSubclassOf<UActorComponent>> ComponentClasses;
};