ZMMO: CHAR_INFO via V1 (Fase A) + fix loading travado
- ZeusWorldSubsystem consome ENT_CHAR_INFO (delegate OnCharInfo): aplica nome/guild no PlayerState do entityId certo (self ou proxy), com cache porque o CHAR_INFO chega antes do ator existir (server emite antes do ENT_SPAWN). - FIX loading travado: a etapa "Spawn" do loading dependia do legacy OnPlayerSpawned, que não dispara mais com V1 -> loading eterno. Agora a etapa é marcada pelo sinal V1 OnSelfEntityAssigned (ENT_SELF); bind legacy removido. Travel ainda passa por OnServerTravelRequested (ponte legacy) até a Fase D. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,7 @@ void UZeusWorldSubsystem::OnWorldBeginPlay(UWorld& InWorld)
|
||||
Net->OnEntityDespawned.AddDynamic(this, &UZeusWorldSubsystem::OnNetEntityDespawned);
|
||||
Net->OnEntityDeltaApplied.AddDynamic(this, &UZeusWorldSubsystem::OnNetEntityDelta);
|
||||
Net->OnSelfEntityAssigned.AddDynamic(this, &UZeusWorldSubsystem::OnNetSelfEntityAssigned);
|
||||
Net->OnCharInfo.AddDynamic(this, &UZeusWorldSubsystem::OnNetCharInfo);
|
||||
UE_LOG(LogZMMO, Log, TEXT("ZeusWorldSubsystem bound to network client subsystem delegates."));
|
||||
|
||||
// O subsystem de rede e' per-GameInstance e sobrevive ao OpenLevel, entao
|
||||
@@ -77,9 +78,11 @@ void UZeusWorldSubsystem::Deinitialize()
|
||||
Net->OnEntityDespawned.RemoveDynamic(this, &UZeusWorldSubsystem::OnNetEntityDespawned);
|
||||
Net->OnEntityDeltaApplied.RemoveDynamic(this, &UZeusWorldSubsystem::OnNetEntityDelta);
|
||||
Net->OnSelfEntityAssigned.RemoveDynamic(this, &UZeusWorldSubsystem::OnNetSelfEntityAssigned);
|
||||
Net->OnCharInfo.RemoveDynamic(this, &UZeusWorldSubsystem::OnNetCharInfo);
|
||||
}
|
||||
|
||||
RemoteEntities.Reset();
|
||||
PendingCharInfo.Reset();
|
||||
LocalEntityId = 0;
|
||||
Super::Deinitialize();
|
||||
}
|
||||
@@ -112,6 +115,9 @@ void UZeusWorldSubsystem::RegisterLocalEntity(const int64 EntityId, AActor* Loca
|
||||
}
|
||||
|
||||
RemoteEntities.Add(EntityId, TWeakObjectPtr<AActor>(LocalActor));
|
||||
// V1-CHARINFO: o nome do proprio char pode ter chegado antes do pawn local
|
||||
// existir (CHAR_INFO vem logo apos ENT_SELF); aplica agora.
|
||||
FlushPendingCharInfo(EntityId);
|
||||
UE_LOG(LogZMMO, Log, TEXT("ZeusWorldSubsystem: local entity registered EntityId=%lld actor=%s"),
|
||||
EntityId, *GetNameSafe(LocalActor));
|
||||
}
|
||||
@@ -255,10 +261,63 @@ void UZeusWorldSubsystem::HandlePlayerSpawned(const int64 EntityId, const bool b
|
||||
}
|
||||
|
||||
RemoteEntities.Add(EntityId, TWeakObjectPtr<AActor>(SpawnedActor));
|
||||
// V1-CHARINFO: o nome chega ANTES do ator (server emite ENT_CHAR_INFO antes
|
||||
// do ENT_SPAWN); aplica agora que o proxy + PlayerState ja existem.
|
||||
FlushPendingCharInfo(EntityId);
|
||||
UE_LOG(LogZMMO, Log, TEXT("ZeusWorldSubsystem: spawned remote EntityId=%d at (%s) yaw=%.1f t=%lld"),
|
||||
EntityId, *PosCm.ToString(), YawDeg, ServerTimeMs);
|
||||
}
|
||||
|
||||
void UZeusWorldSubsystem::OnNetCharInfo(const int64 EntityId, const FString& CharName, const FString& GuildName)
|
||||
{
|
||||
if (EntityId == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Aplica direto se o ator/PlayerState ja existe; senao guarda pra aplicar no spawn.
|
||||
if (!ApplyCharInfoToEntity(EntityId, CharName, GuildName))
|
||||
{
|
||||
PendingCharInfo.Add(EntityId, FZeusPendingCharInfo{ CharName, GuildName });
|
||||
}
|
||||
}
|
||||
|
||||
bool UZeusWorldSubsystem::ApplyCharInfoToEntity(const int64 EntityId, const FString& CharName, const FString& GuildName)
|
||||
{
|
||||
const TWeakObjectPtr<AActor>* Found = RemoteEntities.Find(EntityId);
|
||||
if (!Found || !Found->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
APawn* Pawn = Cast<APawn>(Found->Get());
|
||||
if (!Pawn)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AZeusPlayerState* PS = Pawn->GetPlayerState<AZeusPlayerState>();
|
||||
if (!PS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
PS->SetCharInfo(CharName, GuildName);
|
||||
UE_LOG(LogZMMO, Log,
|
||||
TEXT("ZeusWorldSubsystem: CHAR_INFO aplicado EntityId=%lld name='%s' guild='%s'"),
|
||||
EntityId, *CharName, *GuildName);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UZeusWorldSubsystem::FlushPendingCharInfo(const int64 EntityId)
|
||||
{
|
||||
const FZeusPendingCharInfo* Pending = PendingCharInfo.Find(EntityId);
|
||||
if (!Pending)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (ApplyCharInfoToEntity(EntityId, Pending->CharName, Pending->GuildName))
|
||||
{
|
||||
PendingCharInfo.Remove(EntityId);
|
||||
}
|
||||
}
|
||||
|
||||
void UZeusWorldSubsystem::HandlePlayerDespawned(const int64 EntityId)
|
||||
{
|
||||
const TWeakObjectPtr<AActor>* Entry = RemoteEntities.Find(EntityId);
|
||||
|
||||
Reference in New Issue
Block a user