feat(gas): SM6 client EntityId u64 + M8 cue assets + UI/data tweaks (sessao 1+2)

This commit is contained in:
2026-06-03 18:18:02 -03:00
parent d5402216a2
commit 8d73cc9df8
45 changed files with 74 additions and 0 deletions

View File

@@ -2,10 +2,13 @@
#include "Engine/GameInstance.h"
#include "Engine/World.h"
#include "GameFramework/GameStateBase.h"
#include "ZMMO.h"
#include "ZeusEntity.h"
#include "ZeusEntityInterface.h"
#include "ZeusGASComponent.h"
#include "ZeusPlayerProxy.h"
#include "ZeusPlayerState.h"
#include "ZeusNetworkSubsystem.h"
void UZeusWorldSubsystem::Initialize(FSubsystemCollectionBase& Collection)
@@ -160,6 +163,54 @@ void UZeusWorldSubsystem::HandlePlayerSpawned(const int64 EntityId, const bool b
AsEntity->SetEntityRelevant(true);
}
// === PlayerState pra proxies (Batch 2.5+) ===
//
// Sem PlayerState, o proxy fica fora do GameState->PlayerArray. Daqui pra
// cima, qualquer sistema que itera PlayerArray (UZeusGASNetworkHandler::
// FindGASComponentForEntity, HUD, chat, friend list) NAO consegue achar o
// proxy -> fallback ao local player -> efeito apareceria no char errado
// (bug do cue do Dash). Criar PS replicado-fake permite que o pipeline GAS
// trate proxies igual a local players.
//
// PlayerState tem o UZeusGASComponent via DefaultGame.ini Component Registry,
// entao GASComp e' auto-instanciado. So' precisamos seed o EntityId.
if (APawn* ProxyPawn = Cast<APawn>(SpawnedActor))
{
FActorSpawnParameters PSParams;
PSParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
PSParams.Owner = ProxyPawn;
AZeusPlayerState* ProxyPS = World->SpawnActor<AZeusPlayerState>(
AZeusPlayerState::StaticClass(), FVector::ZeroVector, FRotator::ZeroRotator, PSParams);
if (ProxyPS)
{
ProxyPawn->SetPlayerState(ProxyPS); // tambem chama ProxyPS->SetPawn(ProxyPawn)
// Add ao PlayerArray do GameState (replicacao UE faria isso automatico,
// mas no nosso pipeline custom o PS local-fake precisa ser inserido).
if (AGameStateBase* GS = World->GetGameState())
{
GS->AddPlayerState(ProxyPS);
}
// Seed EntityId no GASComp do PS (criado via Component Registry).
// FindGASComponentForEntity vai resolver via PS->FindComponentByClass.
if (UZeusGASComponent* GASComp = ProxyPS->FindComponentByClass<UZeusGASComponent>())
{
GASComp->SeedEntityId(EntityId);
}
UE_LOG(LogZMMO, Log,
TEXT("ZeusWorldSubsystem: PlayerState criado p/ proxy EntityId=%lld PS=%s"),
EntityId, *ProxyPS->GetName());
}
else
{
UE_LOG(LogZMMO, Warning,
TEXT("ZeusWorldSubsystem: SpawnActor<AZeusPlayerState> falhou pra proxy EntityId=%lld"),
EntityId);
}
}
RemoteEntities.Add(EntityId, TWeakObjectPtr<AActor>(SpawnedActor));
UE_LOG(LogZMMO, Log, TEXT("ZeusWorldSubsystem: spawned remote EntityId=%d at (%s) yaw=%.1f t=%lld"),
EntityId, *PosCm.ToString(), YawDeg, ServerTimeMs);
@@ -185,6 +236,22 @@ void UZeusWorldSubsystem::HandlePlayerDespawned(const int64 EntityId)
{
AsEntity->SetEntityRelevant(false);
}
// Destrui PS proxy linkado (Batch 2.5+). Sem isso o GameState->PlayerArray
// fica com PS orfa apos o proxy ser destruido.
if (APawn* Pawn = Cast<APawn>(Actor))
{
if (APlayerState* PS = Pawn->GetPlayerState())
{
if (UWorld* World = GetWorld())
{
if (AGameStateBase* GS = World->GetGameState())
{
GS->RemovePlayerState(PS);
}
}
PS->Destroy();
}
}
Actor->Destroy();
}
RemoteEntities.Remove(EntityId);