#pragma once #include "GasaCommon.h" #include "GasaPlayerState.h" #include "Networking/GasaNetLibrary.h" #include "Engine/Engine.h" #include "GameFramework/PlayerController.h" #include "GasaPlayerController.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnGasaPlayerControllerSig, AGasaPlayerController*, PC); UCLASS(Blueprintable) class GASA_API AGasaPlayerController : public APlayerController { GENERATED_BODY() protected: friend void AGasaPlayerState::ClientInitialize(AController* NewOwner); public: UFUNCTION() void OnSeamlessTravelStart(); #pragma region Camera UPROPERTY(EditAnywhere, BlueprintReadWrite) TObjectPtr Cam; #pragma endregion Camera // This will be implemented in the base until it needs to be lifted into an abstraction. #if 0 #pragma region Highlighting UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Highlighting") EHighlight HighlightState; UFUNCTION(BlueprintCallable, Category="Highlighting") void SetHighlight( EHighlight Desired ); UFUNCTION(BlueprintCallable, Category="Highlighting") FORCEINLINE void Highlight() { SetHighlight(EHighlight::Enabled); }; UFUNCTION(BlueprintCallable, Category="Highlighting") FORCEINLINE void Dehighlight() { SetHighlight(EHighlight::Disabled); }; #pragma endregion Highlighting #endif #pragma region GameFramework UPROPERTY(BlueprintAssignable) FOnGasaPlayerControllerSig Event_NetOwner_OnGameFrameworkInitialized; UPROPERTY(BlueprintAssignable) FOnGasaPlayerControllerSig Event_NetOwner_OnReady; UPROPERTY(BlueprintAssignable) FOnPawnSig Event_OnPawnPossessed; UPROPERTY(Replicated, VisibleAnywhere) bool bNetOwner_GameFrameworkInitialized = false; UPROPERTY(VisibleAnywhere, Category = "Game Framework") bool bNetOwnerReady = false; void Client_CheckIfOwnerReady(); UFUNCTION() void NetOwner_OnReady(); UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta = (DisplayName = "NetOwner: On Ready")) void BP_NetOwner_OnReady(); UFUNCTION() void OnGameFrameworkInitialized(); UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta=(DisplayName = "On Game Framework Initialized")) void BP_OnGameFrameworkInitialized(); UFUNCTION() void OnPawnReady(); UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta=(DisplayName = "On Pawn Ready")) void BP_OnPawnReady(); UFUNCTION() void Server_SetupOnPawnReadyBinds(APawn* PawnToBindTo); UFUNCTION() void Server_SetNetOwner_GameFrameworkInitialized(); UFUNCTION(Server, Reliable) void ServerRPC_R_NotifyOwningClientReady(); UFUNCTION(Server, Reliable) void ServerRPC_R_SetNetOwner_GameFrameworkInitialized(); #pragma endregion GameFramework #pragma region Input UPROPERTY(VisibleAnywhere, BlueprintReadOnly) TObjectPtr HoverPrev; UPROPERTY(VisibleAnywhere, BlueprintReadOnly) TObjectPtr HoverCurr; UPROPERTY(EditAnywhere, Category="Input") TObjectPtr IMC; UPROPERTY(EditAnywhere, Category="Input") TObjectPtr IA_Move; void Move(FInputActionValue const& ActionValue); #pragma endregion Input #pragma region NetSlime // NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); } FORCEINLINE bool IsClient() const { return Gasa::IsClient( this ); } FORCEINLINE bool IsListenServer() const { return Gasa::IsListenServer( this ); } FORCEINLINE bool IsNetOwner() const { return Gasa::IsNetOwner( this ); } FORCEINLINE bool IsServer() const { return Gasa::IsServer( this ); } FORCEINLINE bool IsSimulatedProxy() const { return Gasa::IsSimulatedProxy( this ); } FORCEINLINE void NetLog( FString Message, EGasaVerbosity Verbosity = EGasaVerbosity::Log, FLogCategoryBase& Category = LogGasaNet, bool DumpStack = false, int32 Line = __builtin_LINE(), ANSICHAR const* File = __builtin_FILE(), ANSICHAR const* Func = __builtin_FUNCTION() ) { Gasa::NetLog( this, Message, Verbosity, Category, DumpStack, Line, File, Func ); } #pragma endregion NetSlime AGasaPlayerController(); inline AGasaPlayerState* GetPlayerState(); #pragma region PlayerController bool CanRestartPlayer() override; void ClientSetHUD_Implementation(TSubclassOf NewHUDClass) override; void ClientUpdateLevelStreamingStatus_Implementation(FName PackageName, bool bNewShouldBeLoaded, bool bNewShouldBeVisible, bool bNewShouldBlockOnLoad, int32 LODIndex, FNetLevelVisibilityTransactionId TransactionId, bool bNewShouldBlockOnUnload) override; void PlayerTick(float DeltaTime) override; void PostSeamlessTravel() override; void SetupInputComponent() override; void SpawnDefaultHUD() override; #pragma endregion PlayerController #pragma region Controller void OnPossess(APawn* InPawn) override; void OnRep_Pawn() override; void OnUnPossess() override; #pragma endregion Controller #pragma region Actor void BeginPlay() override; void PostInitializeComponents() override; void Tick(float DeltaSeconds) override; #pragma endregion Actor #pragma region UObject void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override; #pragma endregion UObject }; namespace Gasa { inline AGasaPlayerController* GetPrimaryPlayerController(UObject* Context) { UWorld* World = GEngine->GetWorldFromContextObject(Context, EGetWorldErrorMode::LogAndReturnNull); if (World == nullptr) { Log("World is null... are you running in a proper context?", ELogV::Error); return nullptr; } return Cast(World->GetFirstPlayerController()); } }