Files
ZMMO/Source/ZMMO/Game/UI/FrontEnd/UIFrontEndFlowSubsystem.h
Mateus Rodrigues bc07c47557 feat(frontend): esqueleto CommonUI de MainMenu (boot→login→lobby)
Estrutura principal de front-end estilo Lyra portada para C++ proprio do
ZMMO (sem CommonGame), seguindo o padrao C++ Abstract -> WBP concreto:

- EZMMOFrontEndState / EZMMOLobbyPage e GameplayTags UI.Layer.* nativos
- UUIActivatableScreen_Base: base de tela (input config, hook de tema,
  voltar) espelhando o padrao de UUIButton_Base
- UUIPrimaryGameLayout_Base: switch principal (4 stacks CommonUI/camada)
- UUIManagerSubsystem (LocalPlayer): dono do root layout, idempotente
- UUIFrontEndFlowSubsystem (GameInstance): maquina de estados + driver
  de rede (Boot->Connecting->Login->ServerSelect->Lobby->EnteringWorld
  ->InWorld); Lobby e o hub logado, paginas internas = EZMMOLobbyPage
- UUIFrontEndScreenSet (DataAsset): mapa estado->tela, forge-ready
- AZMMOFrontEndGameMode + AZMMOFrontEndPlayerController
- GameInstance: bAutoConnectOnStart=false (conexao dirigida pelo fluxo)
- Build.cs: +GameplayTags; ARQUITETURA.md PR-first (s2.1/2.2/3.3/4.8/5)
- Assets: L_FrontEnd (GameMode via World Settings), WBP_PrimaryGameLayout,
  DA_FrontEndScreenSet; Config wiring

WBPs de pagina (Boot/Login/...) virao do Zeus UMG Forge depois (s4.8).
Smoke test PIE OK: root layout no viewport, fluxo Boot->Connecting,
no-op+log para telas nao configuradas, sem crash.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 01:56:16 -03:00

110 lines
3.5 KiB
C++

#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "UI/FrontEndTypes.h"
#include "UIFrontEndFlowSubsystem.generated.h"
class UUIFrontEndScreenSet;
class UUIManagerSubsystem;
class UZeusNetworkSubsystem;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnZMMOFrontEndStateChanged, EZMMOFrontEndState, NewState);
/**
* Orquestrador do fluxo de front-end. UGameInstanceSubsystem porque o
* GameInstance persiste o travel boot→mundo (a máquina de estados não pode
* morrer no OpenLevel).
*
* Responsável por: (a) dirigir a conexão via UZeusNetworkSubsystem;
* (b) manter EZMMOFrontEndState; (c) resolver estado→tela pelo
* DA_FrontEndScreenSet e pedir ao UUIManagerSubsystem para empurrar na
* camada certa; (d) detectar a chegada ao mundo.
*
* As telas (WBP) ainda não existem — virão do Zeus UMG Forge (§4.8).
* Enquanto não registradas no DA, cada transição faz no-op + log.
*/
UCLASS(Config = Game)
class ZMMO_API UUIFrontEndFlowSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
// USubsystem
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
/**
* Ponto de entrada chamado pelo AZMMOFrontEndPlayerController::BeginPlay
* (garante que os subsistemas já existem — ver aviso no header do
* ZeusNetworkSubsystem sobre GameInstance::Init). Cria o root layout,
* liga os delegates de rede e dispara Boot→Connecting.
*/
UFUNCTION(BlueprintCallable, Category = "FrontEnd")
void StartFrontEnd();
UFUNCTION(BlueprintCallable, Category = "FrontEnd")
void SetState(EZMMOFrontEndState NewState);
UFUNCTION(BlueprintPure, Category = "FrontEnd")
EZMMOFrontEndState GetCurrentState() const { return CurrentState; }
/** Mostra uma página interna do Lobby ("switch principal"). */
UFUNCTION(BlueprintCallable, Category = "FrontEnd")
void ShowLobbyPage(EZMMOLobbyPage Page);
/** "Voltar". Retorna true se o fluxo consumiu (tela base encaminha aqui). */
UFUNCTION(BlueprintCallable, Category = "FrontEnd")
bool RequestBack();
UPROPERTY(BlueprintAssignable, Category = "FrontEnd")
FOnZMMOFrontEndStateChanged OnStateChanged;
protected:
/** DA com o mapa estado→tela. Config em DefaultGame.ini. */
UPROPERTY(Config, EditDefaultsOnly, Category = "FrontEnd")
TSoftObjectPtr<UUIFrontEndScreenSet> ScreenSetAsset;
private:
void BindNetwork();
void UnbindNetwork();
UZeusNetworkSubsystem* GetZeusNetwork() const;
UUIManagerSubsystem* GetUIManager() const;
UUIFrontEndScreenSet* GetScreenSet();
/** Resolve a soft class do estado e empurra na camada Menu (no-op+log se vazio). */
void ResolveAndPushScreen(EZMMOFrontEndState State);
UFUNCTION()
void HandleConnected();
UFUNCTION()
void HandleConnectionFailed(FString Reason);
UFUNCTION()
void HandleDisconnected();
UFUNCTION()
void HandleServerTravelRequested(const FString& MapName, const FString& MapPath);
void HandlePostLoadMap(UWorld* LoadedWorld);
/**
* Dívida técnica (D5): ServerHello traz ThemeId, mas o UZeusNetworkSubsystem
* ainda não expõe um delegate/getter dedicado. Quando expuser, ligar aqui
* → UZMMOThemeSubsystem::ApplyServerTheme. Sem isto, o tema resolve por
* calendário/Default (ARQUITETURA.md §1.10).
*/
void HandleServerHelloTheme(FName ThemeId);
UPROPERTY(Transient)
EZMMOFrontEndState CurrentState = EZMMOFrontEndState::None;
UPROPERTY(Transient)
TObjectPtr<UUIFrontEndScreenSet> ScreenSet;
bool bNetBound = false;
bool bTravelingToWorld = false;
FDelegateHandle PostLoadMapHandle;
};