- Renomeia ~50 classes UCLASS/USTRUCT/UENUM/UINTERFACE pra Zeus* (AZeusGameMode, AZeusCharacter, UZeusGameInstance, IZeusEntityInterface, UZeusWorldSubsystem, FZeusEntitySnapshot, etc.) - Encurta AZMMOPlayerCharacter -> AZeusCharacter - Renomeia módulos satélite ZMMOAttributes -> ZeusAttributes e ZMMOJobs -> ZeusJobs (pasta + .Build.cs + .uproject) - Mantém módulo principal ZMMO (renomeia depois quando jogo ganhar nome) - DefaultEngine.ini: ActiveClassRedirects ZMMOX -> ZeusX (preserva BPs/assets) - DefaultGame.ini: sections atualizadas pra ZeusThemeSubsystem/ZeusPlayerState - Category="ZMMO|..." -> "Zeus|..." em UPROPERTYs - Preserva LogZMMO, ZMMO_API, /Script/ZMMO., /Game/ZMMO/, classes Target Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
440 lines
15 KiB
C++
440 lines
15 KiB
C++
#include "UIUserLobbyScreen_Base.h"
|
|
|
|
#include "ZMMO.h"
|
|
#include "CharServerOpcodes.h"
|
|
#include "UIFrontEndFlowSubsystem.h"
|
|
#include "UICharCard_Base.h"
|
|
#include "UICharacterCreatePage_Base.h"
|
|
#include "WireHelpers.h"
|
|
#include "ZeusCharServerSubsystem.h"
|
|
#include "ZeusNetworkSubsystem.h"
|
|
#include "CommonTextBlock.h"
|
|
#include "Components/PanelWidget.h"
|
|
#include "Components/WidgetSwitcher.h"
|
|
#include "Engine/GameInstance.h"
|
|
#include "UI/Widgets/UIButton_Base.h"
|
|
|
|
using ZeusWire::ReadU8;
|
|
using ZeusWire::ReadU16;
|
|
using ZeusWire::ReadU32;
|
|
using ZeusWire::ReadU64;
|
|
using ZeusWire::ReadFloat;
|
|
using ZeusWire::ReadStringUtf8;
|
|
using ZeusWire::ReadUuid16;
|
|
using ZeusWire::WriteUuid16;
|
|
|
|
void UUIUserLobbyScreen_Base::NativeOnActivated()
|
|
{
|
|
Super::NativeOnActivated();
|
|
UE_LOG(LogZMMO, Log, TEXT("Lobby: ativada."));
|
|
|
|
if (UZeusCharServerSubsystem* Char = GetCharServer())
|
|
{
|
|
if (!bSubscribed)
|
|
{
|
|
Char->OnRawMessage.AddDynamic(this, &UUIUserLobbyScreen_Base::HandleCharRawMessage);
|
|
bSubscribed = true;
|
|
}
|
|
}
|
|
|
|
if (!bButtonsBound)
|
|
{
|
|
if (Btn_Back) Btn_Back->OnClicked().AddUObject(this, &UUIUserLobbyScreen_Base::BackToServerSelect);
|
|
if (Btn_Create) Btn_Create->OnClicked().AddUObject(this, &UUIUserLobbyScreen_Base::ShowCharCreatePage);
|
|
bButtonsBound = true;
|
|
}
|
|
|
|
ShowCharSelectPage();
|
|
RequestCharList();
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::NativeOnDeactivated()
|
|
{
|
|
if (bSubscribed)
|
|
{
|
|
if (UZeusCharServerSubsystem* Char = GetCharServer())
|
|
{
|
|
Char->OnRawMessage.RemoveDynamic(this, &UUIUserLobbyScreen_Base::HandleCharRawMessage);
|
|
}
|
|
bSubscribed = false;
|
|
}
|
|
Super::NativeOnDeactivated();
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::RequestCharList()
|
|
{
|
|
UZeusCharServerSubsystem* Char = GetCharServer();
|
|
if (!Char || !Char->IsConnected()) return;
|
|
|
|
FString RealmId;
|
|
if (UGameInstance* GI = GetGameInstance())
|
|
{
|
|
if (UUIFrontEndFlowSubsystem* Flow = GI->GetSubsystem<UUIFrontEndFlowSubsystem>())
|
|
{
|
|
RealmId = Flow->GetSelectedRealmId();
|
|
}
|
|
}
|
|
|
|
// Wire: uint8 hasFilter + (uint8[16] realmId se hasFilter==1)
|
|
TArray<uint8> Payload;
|
|
if (RealmId.IsEmpty())
|
|
{
|
|
Payload.Add(0);
|
|
}
|
|
else
|
|
{
|
|
Payload.Add(1);
|
|
if (!WriteUuid16(Payload, RealmId))
|
|
{
|
|
UE_LOG(LogZMMO, Warning, TEXT("Lobby: SelectedRealmId invalido (%s) — pedindo sem filtro"), *RealmId);
|
|
Payload.Reset();
|
|
Payload.Add(0);
|
|
}
|
|
}
|
|
Char->SendCharRequest(ZeusCharOp::C_CHAR_LIST_REQUEST, Payload);
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::ShowCharSelectPage()
|
|
{
|
|
if (PageSwitcher) PageSwitcher->SetActiveWidgetIndex(0);
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::ShowCharCreatePage()
|
|
{
|
|
if (PageSwitcher) PageSwitcher->SetActiveWidgetIndex(1);
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::BackToServerSelect()
|
|
{
|
|
UGameInstance* GI = GetGameInstance();
|
|
if (!GI) return;
|
|
if (UUIFrontEndFlowSubsystem* Flow = GI->GetSubsystem<UUIFrontEndFlowSubsystem>())
|
|
{
|
|
Flow->ClearSelectedRealm();
|
|
Flow->SetState(EZeusFrontEndState::ServerSelect);
|
|
}
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCharRawMessage(int32 Opcode, const TArray<uint8>& Payload)
|
|
{
|
|
switch (Opcode)
|
|
{
|
|
case ZeusCharOp::S_CHAR_LIST: ParseCharList(Payload); break;
|
|
case ZeusCharOp::S_CHAR_SELECT_OK: HandleCharSelectOk(Payload); break;
|
|
case ZeusCharOp::S_CHAR_SELECT_REJECT: HandleCharSelectReject(Payload); break;
|
|
case ZeusCharOp::S_CHAR_CREATE_OK: HandleCharCreateOk(Payload); break;
|
|
case ZeusCharOp::S_CHAR_CREATE_REJECT: HandleCharCreateReject(Payload); break;
|
|
case ZeusCharOp::S_CHAR_DELETE_ACK: HandleCharDeleteAck(Payload); break;
|
|
case ZeusCharOp::S_CHAR_DELETE_ACCEPT_ACK: HandleCharDeleteAcceptAck(Payload); break;
|
|
case ZeusCharOp::S_CHAR_DELETE_CANCEL_ACK: HandleCharDeleteCancelAck(Payload); break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::ParseCharList(const TArray<uint8>& Payload)
|
|
{
|
|
int32 Pos = 0;
|
|
uint16 Count = 0;
|
|
if (!ReadU16(Payload, Pos, Count))
|
|
{
|
|
UE_LOG(LogZMMO, Warning, TEXT("Lobby: S_CHAR_LIST malformado (sem count)"));
|
|
return;
|
|
}
|
|
|
|
TArray<FZeusCharSummary> New;
|
|
New.Reserve(Count);
|
|
|
|
for (uint16 i = 0; i < Count; ++i)
|
|
{
|
|
FZeusCharSummary E;
|
|
uint64 charId64 = 0;
|
|
uint8 slot = 0;
|
|
uint16 classId = 0;
|
|
uint32 baseLvl = 0, baseExp = 0, jobLvl = 0, jobExp = 0;
|
|
uint16 s = 0, a = 0, v = 0, in_ = 0, d = 0, l = 0;
|
|
uint32 hp = 0, maxHp = 0, sp = 0, maxSp = 0, money = 0;
|
|
uint16 mapId16 = 0;
|
|
float px = 0, py = 0, pz = 0, yaw = 0;
|
|
uint32 hair = 0, hairColor = 0, skinColor = 0;
|
|
uint8 bodyType = 0;
|
|
uint64 deleteAt = 0;
|
|
|
|
if (!ReadU64(Payload, Pos, charId64)
|
|
|| !ReadUuid16(Payload, Pos, E.RealmId)
|
|
|| !ReadU8(Payload, Pos, slot)
|
|
|| !ReadStringUtf8(Payload, Pos, E.Name)
|
|
|| !ReadU16(Payload, Pos, classId)
|
|
|| !ReadU32(Payload, Pos, baseLvl)
|
|
|| !ReadU32(Payload, Pos, baseExp)
|
|
|| !ReadU32(Payload, Pos, jobLvl)
|
|
|| !ReadU32(Payload, Pos, jobExp)
|
|
|| !ReadU16(Payload, Pos, s) || !ReadU16(Payload, Pos, a) || !ReadU16(Payload, Pos, v)
|
|
|| !ReadU16(Payload, Pos, in_) || !ReadU16(Payload, Pos, d) || !ReadU16(Payload, Pos, l)
|
|
|| !ReadU32(Payload, Pos, hp) || !ReadU32(Payload, Pos, maxHp)
|
|
|| !ReadU32(Payload, Pos, sp) || !ReadU32(Payload, Pos, maxSp)
|
|
|| !ReadU32(Payload, Pos, money)
|
|
|| !ReadU16(Payload, Pos, mapId16)
|
|
|| !ReadFloat(Payload, Pos, px) || !ReadFloat(Payload, Pos, py) || !ReadFloat(Payload, Pos, pz)
|
|
|| !ReadFloat(Payload, Pos, yaw)
|
|
|| !ReadU32(Payload, Pos, hair) || !ReadU32(Payload, Pos, hairColor) || !ReadU32(Payload, Pos, skinColor)
|
|
|| !ReadU8(Payload, Pos, bodyType)
|
|
|| !ReadU64(Payload, Pos, deleteAt))
|
|
{
|
|
UE_LOG(LogZMMO, Warning, TEXT("Lobby: S_CHAR_LIST malformado (entry %d)"), i);
|
|
return;
|
|
}
|
|
E.CharId = FString::Printf(TEXT("%llu"), static_cast<unsigned long long>(charId64));
|
|
E.Slot = slot; E.ClassId = classId;
|
|
E.BaseLevel = baseLvl; E.BaseExp = static_cast<int32>(baseExp);
|
|
E.JobLevel = jobLvl; E.JobExp = static_cast<int32>(jobExp);
|
|
E.Stats.Str = s; E.Stats.Agi = a; E.Stats.Vit = v;
|
|
E.Stats.Int = in_; E.Stats.Dex = d; E.Stats.Luk = l;
|
|
E.Hp = hp; E.MaxHp = maxHp; E.Sp = sp; E.MaxSp = maxSp;
|
|
E.Money = static_cast<int32>(money);
|
|
E.MapId = static_cast<int32>(mapId16);
|
|
E.Position = FVector(px, py, pz); E.YawDeg = yaw;
|
|
E.Appearance.Hair = hair; E.Appearance.HairColor = hairColor;
|
|
E.Appearance.SkinColor = skinColor; E.Appearance.BodyType = bodyType;
|
|
E.DeleteScheduledAtMs = static_cast<int64>(deleteAt);
|
|
New.Add(MoveTemp(E));
|
|
}
|
|
|
|
Chars = MoveTemp(New);
|
|
UE_LOG(LogZMMO, Log, TEXT("Lobby: recebidos %d chars"), Chars.Num());
|
|
RebuildCards();
|
|
OnCharListReceived();
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::RebuildCards()
|
|
{
|
|
if (!CardContainer || !CharCardClass) return;
|
|
|
|
for (UUICharCard_Base* Old : SpawnedCards)
|
|
{
|
|
if (Old)
|
|
{
|
|
Old->OnCardSelected.RemoveDynamic(this, &UUIUserLobbyScreen_Base::HandleCardSelected);
|
|
Old->OnCardDeleteRequest.RemoveDynamic(this, &UUIUserLobbyScreen_Base::HandleCardDeleteRequest);
|
|
Old->OnCardDeleteAccept.RemoveDynamic(this, &UUIUserLobbyScreen_Base::HandleCardAcceptDeleteRequest);
|
|
Old->OnCardDeleteCancel.RemoveDynamic(this, &UUIUserLobbyScreen_Base::HandleCardCancelDeleteRequest);
|
|
}
|
|
}
|
|
SpawnedCards.Reset();
|
|
CardContainer->ClearChildren();
|
|
|
|
for (const FZeusCharSummary& C : Chars)
|
|
{
|
|
UUICharCard_Base* Card = CreateWidget<UUICharCard_Base>(this, CharCardClass);
|
|
if (!Card) continue;
|
|
Card->SetFromSummary(C);
|
|
Card->OnCardSelected.AddDynamic(this, &UUIUserLobbyScreen_Base::HandleCardSelected);
|
|
Card->OnCardDeleteRequest.AddDynamic(this, &UUIUserLobbyScreen_Base::HandleCardDeleteRequest);
|
|
Card->OnCardDeleteAccept.AddDynamic(this, &UUIUserLobbyScreen_Base::HandleCardAcceptDeleteRequest);
|
|
Card->OnCardDeleteCancel.AddDynamic(this, &UUIUserLobbyScreen_Base::HandleCardCancelDeleteRequest);
|
|
CardContainer->AddChild(Card);
|
|
SpawnedCards.Add(Card);
|
|
}
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCardSelected(FString CharId)
|
|
{
|
|
UE_LOG(LogZMMO, Log, TEXT("Lobby: char %s selecionado — enviando C_CHAR_SELECT"), *CharId);
|
|
UZeusCharServerSubsystem* Char = GetCharServer();
|
|
if (!Char) return;
|
|
uint64 CharId64 = 0;
|
|
LexFromString(CharId64, *CharId);
|
|
// Wire: uint64 charId
|
|
TArray<uint8> Payload;
|
|
for (int32 i = 0; i < 8; ++i) Payload.Add(static_cast<uint8>((CharId64 >> (8 * i)) & 0xFF));
|
|
Char->SendCharRequest(ZeusCharOp::C_CHAR_SELECT, Payload);
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCardDeleteRequest(FString CharId)
|
|
{
|
|
UE_LOG(LogZMMO, Log, TEXT("Lobby: DELETE_REQUEST char %s"), *CharId);
|
|
SendCharIdOpcode(ZeusCharOp::C_CHAR_DELETE_REQUEST, CharId);
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCardAcceptDeleteRequest(FString CharId)
|
|
{
|
|
UE_LOG(LogZMMO, Log, TEXT("Lobby: DELETE_ACCEPT char %s"), *CharId);
|
|
SendCharIdOpcode(ZeusCharOp::C_CHAR_DELETE_ACCEPT, CharId);
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCardCancelDeleteRequest(FString CharId)
|
|
{
|
|
UE_LOG(LogZMMO, Log, TEXT("Lobby: DELETE_CANCEL char %s"), *CharId);
|
|
SendCharIdOpcode(ZeusCharOp::C_CHAR_DELETE_CANCEL, CharId);
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::SendCharIdOpcode(int32 Opcode, const FString& CharId)
|
|
{
|
|
UZeusCharServerSubsystem* Char = GetCharServer();
|
|
if (!Char) return;
|
|
uint64 CharId64 = 0;
|
|
LexFromString(CharId64, *CharId);
|
|
TArray<uint8> Payload;
|
|
for (int32 i = 0; i < 8; ++i) Payload.Add(static_cast<uint8>((CharId64 >> (8 * i)) & 0xFF));
|
|
Char->SendCharRequest(Opcode, Payload);
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCharDeleteAck(const TArray<uint8>& Payload)
|
|
{
|
|
// Wire: uint64 charId + uint16 reason + uint64 effectiveAtMs
|
|
int32 Pos = 0; uint64 CharId64 = 0; uint16 Reason = 0; uint64 EffectiveAtMs = 0;
|
|
if (!ReadU64(Payload, Pos, CharId64) || !ReadU16(Payload, Pos, Reason) || !ReadU64(Payload, Pos, EffectiveAtMs))
|
|
{
|
|
UE_LOG(LogZMMO, Warning, TEXT("Lobby: S_CHAR_DELETE_ACK malformado"));
|
|
return;
|
|
}
|
|
if (Reason == 0)
|
|
{
|
|
UE_LOG(LogZMMO, Log, TEXT("Lobby: delete agendado char=%llu (effective=%llu)"),
|
|
static_cast<unsigned long long>(CharId64), static_cast<unsigned long long>(EffectiveAtMs));
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogZMMO, Warning, TEXT("Lobby: DELETE_ACK rejeitado (reason=%d)"), Reason);
|
|
}
|
|
RequestCharList();
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCharDeleteAcceptAck(const TArray<uint8>& Payload)
|
|
{
|
|
int32 Pos = 0; uint64 CharId64 = 0; uint16 Reason = 0;
|
|
ReadU64(Payload, Pos, CharId64); ReadU16(Payload, Pos, Reason);
|
|
if (Reason == 0)
|
|
{
|
|
UE_LOG(LogZMMO, Log, TEXT("Lobby: char %llu DELETADO"), static_cast<unsigned long long>(CharId64));
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogZMMO, Warning, TEXT("Lobby: DELETE_ACCEPT rejeitado (reason=%d)"), Reason);
|
|
}
|
|
RequestCharList();
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCharDeleteCancelAck(const TArray<uint8>& Payload)
|
|
{
|
|
int32 Pos = 0; uint64 CharId64 = 0; uint16 Reason = 0;
|
|
ReadU64(Payload, Pos, CharId64); ReadU16(Payload, Pos, Reason);
|
|
if (Reason == 0)
|
|
{
|
|
UE_LOG(LogZMMO, Log, TEXT("Lobby: delete cancelado char %llu"), static_cast<unsigned long long>(CharId64));
|
|
}
|
|
RequestCharList();
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCharSelectOk(const TArray<uint8>& Payload)
|
|
{
|
|
// Wire: uint64 charId + uint16 mapId + float x/y/z + float yaw +
|
|
// string gatewayEndpoint + string handoffToken + string region
|
|
// gatewayEndpoint = "host:port" (UMA single string — refator R4 unificou
|
|
// host+port). Server-side: char-select.service.ts.
|
|
int32 Pos = 0;
|
|
uint64 CharId64 = 0; FString GatewayEndpoint, HandoffToken, Region;
|
|
uint16 MapId16 = 0;
|
|
float Px=0, Py=0, Pz=0, Yaw=0;
|
|
if (!ReadU64(Payload, Pos, CharId64)
|
|
|| !ReadU16(Payload, Pos, MapId16)
|
|
|| !ReadFloat(Payload, Pos, Px) || !ReadFloat(Payload, Pos, Py) || !ReadFloat(Payload, Pos, Pz)
|
|
|| !ReadFloat(Payload, Pos, Yaw)
|
|
|| !ReadStringUtf8(Payload, Pos, GatewayEndpoint)
|
|
|| !ReadStringUtf8(Payload, Pos, HandoffToken)
|
|
|| !ReadStringUtf8(Payload, Pos, Region))
|
|
{
|
|
UE_LOG(LogZMMO, Warning, TEXT("Lobby: S_CHAR_SELECT_OK malformado"));
|
|
return;
|
|
}
|
|
UE_LOG(LogZMMO, Log, TEXT("Lobby: handoff -> realm gateway=%s mapId=%u token=%s..."),
|
|
*GatewayEndpoint, static_cast<uint32>(MapId16), *HandoffToken.Left(8));
|
|
|
|
// Split "host:port" para a API legada do ZeusNetworkSubsystem que ainda
|
|
// recebe os dois separados. Defensivo: se o server mandar string vazia
|
|
// ou sem ':' a gente loga e aborta o handoff em vez de tentar conectar
|
|
// em endereco invalido.
|
|
FString GwHost;
|
|
FString GwPortStr;
|
|
if (!GatewayEndpoint.Split(TEXT(":"), &GwHost, &GwPortStr, ESearchCase::CaseSensitive, ESearchDir::FromEnd))
|
|
{
|
|
UE_LOG(LogZMMO, Error, TEXT("Lobby: gatewayEndpoint malformado (sem ':') = %s"), *GatewayEndpoint);
|
|
return;
|
|
}
|
|
int32 GwPort = 0;
|
|
LexFromString(GwPort, *GwPortStr);
|
|
if (GwHost.IsEmpty() || GwPort <= 0)
|
|
{
|
|
UE_LOG(LogZMMO, Error, TEXT("Lobby: gatewayEndpoint invalido host=%s port=%d"), *GwHost, GwPort);
|
|
return;
|
|
}
|
|
|
|
UGameInstance* GI = GetGameInstance();
|
|
if (!GI) return;
|
|
UUIFrontEndFlowSubsystem* Flow = GI->GetSubsystem<UUIFrontEndFlowSubsystem>();
|
|
if (Flow)
|
|
{
|
|
Flow->SetState(EZeusFrontEndState::EnteringWorld);
|
|
// Memoriza pose pra `AZeusCharacter::BeginPlay` reposicionar
|
|
// o pawn local na pos salva no DB (em vez do PlayerStart default).
|
|
Flow->SetPendingSpawnPose(FVector(Px, Py, Pz), Yaw);
|
|
}
|
|
|
|
// Fase 3: handoff UDP — apresenta o ticket no `C_CONNECT_REQUEST`. O
|
|
// Gateway/ZeusServer valida via GETDEL no Valkey regional. Server envia
|
|
// `S_CONNECT_OK` (sucesso) ou `S_CONNECT_REJECT` (ticket invalido/expirado).
|
|
// Disparamos PRIMEIRO o connect (nao-bloqueante), depois o OpenLevel —
|
|
// ZeusNetworkSubsystem e per-GameInstance e persiste cross-travel.
|
|
if (UZeusNetworkSubsystem* ZeusNet = GI->GetSubsystem<UZeusNetworkSubsystem>())
|
|
{
|
|
ZeusNet->ConnectToZeusServerWithTicket(GwHost, GwPort, HandoffToken);
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogZMMO, Error, TEXT("Lobby: ZeusNetworkSubsystem ausente — handoff abortado"));
|
|
}
|
|
|
|
// Fase 4: lookup mapId no DT_Maps e dispara OpenLevel pro level certo.
|
|
// Se DT_Maps nao tem entrada (ou ainda nao foi criada no editor),
|
|
// caimos no fallback do S_TRAVEL_TO_MAP do server (mapName/mapPath string).
|
|
if (Flow && MapId16 != 0)
|
|
{
|
|
if (!Flow->TravelToMapById(static_cast<int32>(MapId16)))
|
|
{
|
|
UE_LOG(LogZMMO, Warning, TEXT("Lobby: mapId=%u nao resolvido no DT_Maps — esperando S_TRAVEL_TO_MAP do server."),
|
|
static_cast<uint32>(MapId16));
|
|
}
|
|
}
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCharSelectReject(const TArray<uint8>& Payload)
|
|
{
|
|
int32 Pos = 0;
|
|
uint16 Reason = 0;
|
|
ReadU16(Payload, Pos, Reason);
|
|
UE_LOG(LogZMMO, Warning, TEXT("Lobby: S_CHAR_SELECT_REJECT reason=%d"), Reason);
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCharCreateOk(const TArray<uint8>& /*Payload*/)
|
|
{
|
|
UE_LOG(LogZMMO, Log, TEXT("Lobby: S_CHAR_CREATE_OK — refresh lista"));
|
|
ShowCharSelectPage();
|
|
RequestCharList();
|
|
}
|
|
|
|
void UUIUserLobbyScreen_Base::HandleCharCreateReject(const TArray<uint8>& Payload)
|
|
{
|
|
int32 Pos = 0;
|
|
uint16 Reason = 0;
|
|
ReadU16(Payload, Pos, Reason);
|
|
UE_LOG(LogZMMO, Warning, TEXT("Lobby: S_CHAR_CREATE_REJECT reason=%d"), Reason);
|
|
}
|
|
|
|
UZeusCharServerSubsystem* UUIUserLobbyScreen_Base::GetCharServer() const
|
|
{
|
|
if (const UGameInstance* GI = GetGameInstance())
|
|
{
|
|
return GI->GetSubsystem<UZeusCharServerSubsystem>();
|
|
}
|
|
return nullptr;
|
|
}
|