Files
ZMMO/Source/ZMMO/Game/Modes/ZMMOPlayerState.cpp
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

101 lines
3.1 KiB
C++

#include "ZMMOPlayerState.h"
#include "Components/ActorComponent.h"
#include "Misc/ConfigCacheIni.h"
#include "Net/UnrealNetwork.h"
#include "ZMMO.h"
AZMMOPlayerState::AZMMOPlayerState()
{
// Component Registry: instancia cada classe declarada em
// DefaultGame.ini::[/Script/ZMMO.ZMMOPlayerState]+ComponentClasses=...
//
// Le manualmente via GConfig para evitar timing do UPROPERTY(Config),
// que requer LoadConfig() ja ter rodado no CDO antes da instance ser
// construida. Pra propriedades em arrays config com `+` syntax, lendo
// direto e mais previsivel.
if (ComponentClasses.Num() == 0 && GConfig)
{
TArray<FString> ClassPaths;
GConfig->GetArray(TEXT("/Script/ZMMO.ZMMOPlayerState"),
TEXT("ComponentClasses"),
ClassPaths,
GGameIni);
for (const FString& Path : ClassPaths)
{
if (UClass* C = LoadClass<UActorComponent>(nullptr, *Path))
{
ComponentClasses.Add(C);
}
else
{
UE_LOG(LogZMMO, Warning,
TEXT("ZMMOPlayerState: ComponentClasses path nao resolveu: %s"), *Path);
}
}
}
UE_LOG(LogZMMO, Log,
TEXT("AZMMOPlayerState ctor: %d componente(s) no registry (instance=%s)"),
ComponentClasses.Num(), *GetName());
int32 SubobjectIndex = 0;
for (const TSubclassOf<UActorComponent>& CompClassRef : ComponentClasses)
{
UClass* CompClass = CompClassRef.Get();
if (!CompClass)
{
UE_LOG(LogZMMO, Warning,
TEXT("ZMMOPlayerState: ComponentClass null em ComponentClasses[%d]"),
SubobjectIndex);
++SubobjectIndex;
continue;
}
const FName CompName = MakeUniqueObjectName(this, CompClass,
FName(*FString::Printf(TEXT("ZMMOComp_%d_%s"), SubobjectIndex, *CompClass->GetName())));
// Overload runtime de CreateDefaultSubobject retorna UObject* (sem template) —
// precisa cast para UActorComponent.
UActorComponent* Comp = Cast<UActorComponent>(CreateDefaultSubobject(CompName, CompClass, CompClass,
/*bIsRequired*/ false, /*bIsTransient*/ false));
if (Comp)
{
UE_LOG(LogZMMO, Log,
TEXT("ZMMOPlayerState: componente registrado [%d] %s"),
SubobjectIndex, *CompClass->GetName());
}
else
{
UE_LOG(LogZMMO, Warning,
TEXT("ZMMOPlayerState: CreateDefaultSubobject falhou para %s"),
*CompClass->GetName());
}
++SubobjectIndex;
}
}
void AZMMOPlayerState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AZMMOPlayerState, ZMMOEntityId);
DOREPLIFETIME(AZMMOPlayerState, CharId);
DOREPLIFETIME(AZMMOPlayerState, CharName);
DOREPLIFETIME(AZMMOPlayerState, BaseLevel);
DOREPLIFETIME(AZMMOPlayerState, ClassId);
DOREPLIFETIME(AZMMOPlayerState, GuildName);
}
void AZMMOPlayerState::SetPublicIdentity(int64 InEntityId, const FString& InCharId,
int32 InBaseLevel, int32 InClassId)
{
ZMMOEntityId = InEntityId;
CharId = InCharId;
BaseLevel = InBaseLevel;
ClassId = InClassId;
}
void AZMMOPlayerState::SetCharInfo(const FString& InCharName, const FString& InGuildName)
{
CharName = InCharName;
GuildName = InGuildName;
}