Consolidar GameplayAbilitySystem na main (baseline cliente tudo funcionando 2026-06-16) #6
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "ZeusAOIComponent.h"
|
#include "ZeusAOIComponent.h"
|
||||||
|
|
||||||
#include "ZeusNetworkSubsystem.h" // plugin ZeusNetwork: OnDebugAoiInfo + SendDebugAoiRequest
|
#include "ZeusNetworkingClientSubsystem.h" // V1 canonico: OnDebugAoiInfo (6161) + EmitDebugAoiRequest (6160)
|
||||||
#include "ZMMONetLog.h" // Batch 2.5: LogZeusAOI (categoria do modulo ZMMO)
|
#include "ZMMONetLog.h" // Batch 2.5: LogZeusAOI (categoria do modulo ZMMO)
|
||||||
|
|
||||||
#include "DrawDebugHelpers.h"
|
#include "DrawDebugHelpers.h"
|
||||||
@@ -30,6 +30,14 @@ namespace
|
|||||||
const FColor kColorDespawn(255, 140, 90); // laranja — Zona de Despawn (externa)
|
const FColor kColorDespawn(255, 140, 90); // laranja — Zona de Despawn (externa)
|
||||||
const FColor kColorCell(232, 192, 96);
|
const FColor kColorCell(232, 192, 96);
|
||||||
const FColor kColorHandoff(255, 155, 190);
|
const FColor kColorHandoff(255, 155, 190);
|
||||||
|
|
||||||
|
// Resolucao das esferas de overlay. 32 segments deixavam a "bolha" facetada
|
||||||
|
// (poucas linhas) num raio de 60-80m; 48 deixa o circulo bem mais denso/legivel.
|
||||||
|
constexpr int32 kSphereSegments = 48;
|
||||||
|
// Clamp visual defensivo: se o raio vier absurdo (config corrompida), nao desenha
|
||||||
|
// uma esfera gigante que engole o mapa. 500m cobre qualquer AOI real (max=800m,
|
||||||
|
// mas overlay > 500m ja' nao ajuda a leitura). So' afeta o desenho, nao o gameplay.
|
||||||
|
constexpr float kMaxOverlayRadiusCm = 50000.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
UZeusAOIComponent::UZeusAOIComponent()
|
UZeusAOIComponent::UZeusAOIComponent()
|
||||||
@@ -43,14 +51,17 @@ void UZeusAOIComponent::BeginPlay()
|
|||||||
{
|
{
|
||||||
Super::BeginPlay();
|
Super::BeginPlay();
|
||||||
|
|
||||||
// Bind do feed de config de AOI (servidor -> cliente). Multicast plain C++.
|
// Bind do feed de config de AOI (servidor -> cliente) pelo transporte V1
|
||||||
|
// canonico. O legacy (UZeusNetworkSubsystem) esta desativado no V1 -> usava
|
||||||
|
// SendDebugAoiRequest que logava "ignorado: nao conectado" e o overlay nunca
|
||||||
|
// recebia a config. Agora via UZeusNetworkingClientSubsystem (OnDebugAoiInfo 6161).
|
||||||
if (UWorld* World = GetWorld())
|
if (UWorld* World = GetWorld())
|
||||||
{
|
{
|
||||||
if (UGameInstance* GI = World->GetGameInstance())
|
if (UGameInstance* GI = World->GetGameInstance())
|
||||||
{
|
{
|
||||||
if (UZeusNetworkSubsystem* Net = GI->GetSubsystem<UZeusNetworkSubsystem>())
|
if (UZeusNetworkingClientSubsystem* NetC = GI->GetSubsystem<UZeusNetworkingClientSubsystem>())
|
||||||
{
|
{
|
||||||
AoiConfigHandle_ = Net->OnDebugAoiInfo.AddUObject(this, &UZeusAOIComponent::HandleAoiConfig);
|
AoiConfigHandle_ = NetC->OnDebugAoiInfo.AddUObject(this, &UZeusAOIComponent::HandleAoiConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,9 +79,9 @@ void UZeusAOIComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
|||||||
{
|
{
|
||||||
if (UGameInstance* GI = World->GetGameInstance())
|
if (UGameInstance* GI = World->GetGameInstance())
|
||||||
{
|
{
|
||||||
if (UZeusNetworkSubsystem* Net = GI->GetSubsystem<UZeusNetworkSubsystem>())
|
if (UZeusNetworkingClientSubsystem* NetC = GI->GetSubsystem<UZeusNetworkingClientSubsystem>())
|
||||||
{
|
{
|
||||||
Net->OnDebugAoiInfo.Remove(AoiConfigHandle_);
|
NetC->OnDebugAoiInfo.Remove(AoiConfigHandle_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,9 +107,9 @@ void UZeusAOIComponent::RequestAoiConfig()
|
|||||||
{
|
{
|
||||||
if (UGameInstance* GI = World->GetGameInstance())
|
if (UGameInstance* GI = World->GetGameInstance())
|
||||||
{
|
{
|
||||||
if (UZeusNetworkSubsystem* Net = GI->GetSubsystem<UZeusNetworkSubsystem>())
|
if (UZeusNetworkingClientSubsystem* NetC = GI->GetSubsystem<UZeusNetworkingClientSubsystem>())
|
||||||
{
|
{
|
||||||
Net->SendDebugAoiRequest(); // no-op se nao conectado
|
NetC->EmitDebugAoiRequest(); // V1: no-op se ainda nao Accepted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,12 +163,14 @@ void UZeusAOIComponent::DrawOverlays()
|
|||||||
// ainda nao chegou a config: nao desenha (loading).
|
// ainda nao chegou a config: nao desenha (loading).
|
||||||
if (ResolveOverlay(EZeusAOIOverlay::AOIRadius) && InterestRadiusCm > 0.0f)
|
if (ResolveOverlay(EZeusAOIOverlay::AOIRadius) && InterestRadiusCm > 0.0f)
|
||||||
{
|
{
|
||||||
DrawDebugSphere(World, Loc, InterestRadiusCm, 32, kColorInterest, false, -1.0f, 0, LineThickness);
|
const float R = FMath::Min(InterestRadiusCm, kMaxOverlayRadiusCm);
|
||||||
|
DrawDebugSphere(World, Loc, R, kSphereSegments, kColorInterest, false, -1.0f, 0, LineThickness);
|
||||||
}
|
}
|
||||||
// Zona de Despawn (externa, > interesse = histerese) — raio real do servidor.
|
// Zona de Despawn (externa, > interesse = histerese) — raio real do servidor.
|
||||||
if (ResolveOverlay(EZeusAOIOverlay::DespawnZone) && DespawnRadiusCm > 0.0f)
|
if (ResolveOverlay(EZeusAOIOverlay::DespawnZone) && DespawnRadiusCm > 0.0f)
|
||||||
{
|
{
|
||||||
DrawDebugSphere(World, Loc, DespawnRadiusCm, 32, kColorDespawn, false, -1.0f, 0, LineThickness);
|
const float R = FMath::Min(DespawnRadiusCm, kMaxOverlayRadiusCm);
|
||||||
|
DrawDebugSphere(World, Loc, R, kSphereSegments, kColorDespawn, false, -1.0f, 0, LineThickness);
|
||||||
}
|
}
|
||||||
if (ResolveOverlay(EZeusAOIOverlay::CellBounds))
|
if (ResolveOverlay(EZeusAOIOverlay::CellBounds))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -56,7 +56,10 @@ void UZeusWorldSubsystem::OnWorldBeginPlay(UWorld& InWorld)
|
|||||||
Net->ForEachRemoteEntity(
|
Net->ForEachRemoteEntity(
|
||||||
[this, &ReplayCount](int64 EntityId, FVector PosCm, float YawDeg)
|
[this, &ReplayCount](int64 EntityId, FVector PosCm, float YawDeg)
|
||||||
{
|
{
|
||||||
OnNetEntitySpawned(EntityId, /*Kind=*/1 /*Player*/, PosCm, YawDeg);
|
// Catch-up local: ForEachRemoteEntity nao expoe vel/serverTimeMs ->
|
||||||
|
// ZeroVector + grounded + ts=0 (seed nao roda; o 1o delta ancora o relogio).
|
||||||
|
OnNetEntitySpawned(EntityId, /*Kind=*/1 /*Player*/, PosCm, YawDeg,
|
||||||
|
FVector::ZeroVector, /*bGrounded=*/true, /*ServerTimeMs=*/0);
|
||||||
++ReplayCount;
|
++ReplayCount;
|
||||||
});
|
});
|
||||||
if (ReplayCount > 0)
|
if (ReplayCount > 0)
|
||||||
@@ -450,13 +453,24 @@ void UZeusWorldSubsystem::HandlePlayerStateUpdate(const int64 EntityId, const in
|
|||||||
AsEntity->ApplyEntitySnapshot(Snapshot);
|
AsEntity->ApplyEntitySnapshot(Snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UZeusWorldSubsystem::OnNetEntitySpawned(int64 EntityId, int32 /*Kind*/, FVector PosCm, float YawDeg)
|
void UZeusWorldSubsystem::OnNetEntitySpawned(int64 EntityId, int32 /*Kind*/, FVector PosCm, float YawDeg,
|
||||||
|
FVector VelCmS, bool bGrounded, int64 ServerTimeMs)
|
||||||
{
|
{
|
||||||
// O sistema novo nao manda bIsLocal: derivamos do LocalEntityId (setado por
|
// O sistema novo nao manda bIsLocal: derivamos do LocalEntityId (setado por
|
||||||
// ENT_SELF). Se ainda for 0 e este ENT_SPAWN for do proprio char, o
|
// ENT_SELF). Se ainda for 0 e este ENT_SPAWN for do proprio char, o
|
||||||
// OnNetSelfEntityAssigned destruira o fantasma quando o ENT_SELF chegar.
|
// OnNetSelfEntityAssigned destruira o fantasma quando o ENT_SELF chegar.
|
||||||
const bool bIsLocal = (LocalEntityId != 0 && EntityId == LocalEntityId);
|
const bool bIsLocal = (LocalEntityId != 0 && EntityId == LocalEntityId);
|
||||||
HandlePlayerSpawned(EntityId, bIsLocal, PosCm, YawDeg, /*ServerTimeMs=*/0);
|
HandlePlayerSpawned(EntityId, bIsLocal, PosCm, YawDeg, ServerTimeMs);
|
||||||
|
|
||||||
|
// V1-SPAWN-KEYFRAME(-TS): o ENT_SPAWN carrega vel + grounded + serverTimeMs. Aplica
|
||||||
|
// esse keyframe INICIAL no proxy recem-criado pelo mesmo caminho do delta (semeia o
|
||||||
|
// SnapshotBuffer + ANCORA o ServerClockOffsetMs com o tempo CERTO). Antes o seed usava
|
||||||
|
// ServerTimeMs=0 -> bootstrap do relogio de interpolacao errado -> proxy preso/flutuando
|
||||||
|
// ate' o EMA convergir. Agora com o serverTimeMs real o proxy interpola desde o frame 1.
|
||||||
|
if (!bIsLocal && ServerTimeMs > 0)
|
||||||
|
{
|
||||||
|
HandlePlayerStateUpdate(EntityId, /*InputSeq=*/0, PosCm, VelCmS, bGrounded, ServerTimeMs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UZeusWorldSubsystem::OnNetEntityDespawned(int64 EntityId, int32 /*Reason*/)
|
void UZeusWorldSubsystem::OnNetEntityDespawned(int64 EntityId, int32 /*Reason*/)
|
||||||
|
|||||||
@@ -84,7 +84,8 @@ private:
|
|||||||
// Sistema de rede novo (canonico) -- recebe spawn/despawn/delta + self-entity.
|
// Sistema de rede novo (canonico) -- recebe spawn/despawn/delta + self-entity.
|
||||||
// Adaptam a assinatura nova para os handlers de spawn/despawn/delta acima.
|
// Adaptam a assinatura nova para os handlers de spawn/despawn/delta acima.
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void OnNetEntitySpawned(int64 EntityId, int32 Kind, FVector PosCm, float YawDeg);
|
void OnNetEntitySpawned(int64 EntityId, int32 Kind, FVector PosCm, float YawDeg,
|
||||||
|
FVector VelCmS, bool bGrounded, int64 ServerTimeMs);
|
||||||
|
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void OnNetEntityDespawned(int64 EntityId, int32 Reason);
|
void OnNetEntityDespawned(int64 EntityId, int32 Reason);
|
||||||
|
|||||||
Reference in New Issue
Block a user