'NetSlime' Initial port finished and working with 2 players (at least)

This commit is contained in:
Edward R. Gonzalez 2024-04-23 18:54:17 -04:00
parent ad41867dc5
commit 3a58e90802
25 changed files with 799 additions and 401 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,4 +1,5 @@
#include "EnemyCharacter.h" #include "EnemyCharacter.h"
#include "Networking/GasaNetLibrary_Inlines.h"
AEnemyCharacter::AEnemyCharacter() AEnemyCharacter::AEnemyCharacter()
{ {

View File

@ -11,13 +11,12 @@
#include "AbilitySystem/GasaAttributeSet.h" #include "AbilitySystem/GasaAttributeSet.h"
#include "Components/SkeletalMeshComponent.h" #include "Components/SkeletalMeshComponent.h"
#include "Engine/PostProcessVolume.h" #include "Engine/PostProcessVolume.h"
#include "Game/GasaGameInstance.h"
#include "Game/GasaLevelScriptActor.h" #include "Game/GasaLevelScriptActor.h"
#include "Game/GasaPlayerController.h"
#include "Materials/MaterialInstanceDynamic.h" #include "Materials/MaterialInstanceDynamic.h"
#include "Networking/GasaNetLibrary_Inlines.h"
void AGasaCharacter::SetHighlight(EHighlight Desired) using namespace Gasa;
{
HighlightState = Desired;
}
AGasaCharacter::AGasaCharacter() AGasaCharacter::AGasaCharacter()
{ {
@ -51,12 +50,111 @@ AGasaCharacter::AGasaCharacter()
Attributes = CreateDefaultSubobject<UGasaAttributeSet>("Attributes"); Attributes = CreateDefaultSubobject<UGasaAttributeSet>("Attributes");
} }
// Replication
bReplicates = false;
bNetLoadOnClient = true;
NetDormancy = DORM_Awake;
NetCullDistanceSquared = NetCullDist_Medium;
NetUpdateFrequency = 30.0f;
MinNetUpdateFrequency = 5.0f;
NetPriority = 2.0f;
ACharacter::SetReplicateMovement(true);
} }
#pragma region GameFramework
void AGasaCharacter::Controller_OnPawnPossessed()
{
NetLog("Controller confirmed possession.");
// Do stuff here that you needed to wait for the player controller be aware of you for.
BP_Controller_OnPawnPossessed();
if (Event_OnPawnReady.IsBound())
Event_OnPawnReady.Broadcast();
}
void AGasaCharacter::ServerRPC_R_NotifyClientPawnReady_Implementation()
{
Event_OnPawnReady.Broadcast();
}
#pragma endregion GameFramework
#pragma region Highlight
void AGasaCharacter::SetHighlight(EHighlight Desired)
{
HighlightState = Desired;
}
#pragma endregion Highlight
#pragma region Pawn #pragma region Pawn
void AGasaCharacter::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
}
void AGasaCharacter::PossessedBy(AController* NewController) void AGasaCharacter::PossessedBy(AController* NewController)
{ {
Super::PossessedBy(NewController); NetLog("Pawn possessed.");
AController* OldController;
// APawn::PossessedBy
{
SetOwner(NewController);
OldController = Controller;
Controller = NewController;
ForceNetUpdate();
#if UE_WITH_IRIS
// The owning connection depends on the Controller having the new value.
UpdateOwningNetConnection();
#endif
if (Controller->PlayerState != nullptr)
SetPlayerState(Controller->PlayerState);
if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
{
if (GetNetMode() != NM_Standalone)
{
SetReplicates(true);
SetAutonomousProxy(true);
}
}
else
CopyRemoteRoleFrom(GetDefault<APawn>());
}
if (AGasaPlayerController* PC = Cast<AGasaPlayerController>(NewController))
{
PC->Event_OnPawnPossessed.AddUniqueDynamic(this, & ThisClass::Controller_OnPawnPossessed);
}
else
{
NetLog("Controller assigned to GasaCharacter is not derived from GasaPlayerController.", ELogV::Warning);
NetLog("Controller: Name: " + NewController->GetName() + " Class: " + NewController->GetClass()->GetName(), ELogV::Warning);
}
// cont. APawn::PossessedBy
{
// Dispatch Blueprint event if necessary
if (OldController != NewController)
{
ReceivePossessed(Controller);
NotifyControllerChanged();
}
}
// ACharacter::PossessedBy
{
// If we are controlled remotely, set animation timing to be driven by client's network updates. So timing and events remain in sync.
if (GetMesh() && IsReplicatingMovement() && (GetRemoteRole() == ROLE_AutonomousProxy && GetNetConnection() != nullptr))
GetMesh()->bOnlyAllowAutonomousTickPose = true;
}
if (bAutoAbilitySystem) if (bAutoAbilitySystem)
{ {
@ -65,9 +163,14 @@ void AGasaCharacter::PossessedBy(AController* NewController)
} }
} }
void AGasaCharacter::OnRep_PlayerState() void AGasaCharacter::SetPlayerDefaults()
{ {
Super::OnRep_PlayerState(); Super::SetPlayerDefaults();
}
void AGasaCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
} }
#pragma endregion Pawn #pragma endregion Pawn

View File

@ -4,7 +4,7 @@
#include "GameFramework/Character.h" #include "GameFramework/Character.h"
#include "GasaCommon.h" #include "GasaCommon.h"
#include "Game/GasaPlayerState.h" #include "Game/GasaGameState.h"
#include "Networking/GasaNetLibrary.h" #include "Networking/GasaNetLibrary.h"
#include "GasaCharacter.generated.h" #include "GasaCharacter.generated.h"
@ -22,6 +22,9 @@ class GASA_API AGasaCharacter : public ACharacter
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
AGasaCharacter();
#pragma region Ability System #pragma region Ability System
UPROPERTY(EditAnywhere, Category="Ability System") UPROPERTY(EditAnywhere, Category="Ability System")
bool bAutoAbilitySystem = true; bool bAutoAbilitySystem = true;
@ -38,6 +41,20 @@ public:
TObjectPtr<USkeletalMeshComponent> Weapon; TObjectPtr<USkeletalMeshComponent> Weapon;
#pragma endregion Combat #pragma endregion Combat
#pragma region GameFramework
UPROPERTY(BlueprintAssignable)
FOnPawnSig Event_OnPawnReady;
UFUNCTION()
void Controller_OnPawnPossessed();
UFUNCTION(BlueprintImplementableEvent)
void BP_Controller_OnPawnPossessed();
UFUNCTION(Server, Reliable)
void ServerRPC_R_NotifyClientPawnReady();
#pragma endregion GameFramework
#pragma region Highlighting #pragma region Highlighting
static constexpr float HighlightStencilDepth = 256.0; static constexpr float HighlightStencilDepth = 256.0;
@ -57,10 +74,6 @@ public:
FORCEINLINE void Dehighlight() { SetHighlight(EHighlight::Disabled); }; FORCEINLINE void Dehighlight() { SetHighlight(EHighlight::Disabled); };
#pragma endregion Highlighting #pragma endregion Highlighting
AGasaCharacter();
FORCEINLINE AGasaPlayerState* GetGasaPlayerState() { return GetPlayerState<AGasaPlayerState>(); }
#pragma region NetSlime #pragma region NetSlime
// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp // NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); } FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); }
@ -89,14 +102,14 @@ public:
#pragma endregion IAbilitySystem #pragma endregion IAbilitySystem
#pragma region Pawn #pragma region Pawn
void PossessedBy(AController* NewController) override;
void OnRep_PlayerState() override; void OnRep_PlayerState() override;
void PossessedBy(AController* NewController) override;
void SetPlayerDefaults() override;
void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
#pragma endregion Pawn #pragma endregion Pawn
#pragma region Actor #pragma region Actor
void BeginPlay() override; void BeginPlay() override;
void Tick(float DeltaSeconds) override; void Tick(float DeltaSeconds) override;
#pragma endregion Actor #pragma endregion Actor
}; };
@ -108,3 +121,4 @@ namespace Gasa
// //
// } // }
} }

View File

@ -1,5 +1,6 @@
#include "PlayerCharacter.h" #include "PlayerCharacter.h"
#include "Networking/GasaNetLibrary_Inlines.h"
#include "AbilitySystemComponent.h" #include "AbilitySystemComponent.h"
#include "Game/GasaPlayerController.h" #include "Game/GasaPlayerController.h"
#include "UI/GasaHUD.h" #include "UI/GasaHUD.h"
@ -12,46 +13,12 @@ APlayerCharacter::APlayerCharacter()
bAutoAbilitySystem = false; bAutoAbilitySystem = false;
} }
// TODO(Ed): We need to setup Net Slime...
void APlayerCharacter::PossessedBy(AController* NewController) void APlayerCharacter::PossessedBy(AController* NewController)
{ {
Super::PossessedBy(NewController); Super::PossessedBy(NewController);
AGasaPlayerState* PS = GetGasaPlayerState();
// Server setup ability system (character side)
{
AbilitySystem = PS->AbilitySystem;
Attributes = PS->Attributes;
AbilitySystem->InitAbilityActorInfo(PS, this);
}
if (IsLocallyControlled())
{
AGasaPlayerController* PC = GetController<AGasaPlayerController>();
AGasaHUD* HUD = PC->GetHUD<AGasaHUD>();
FWidgetControllerData Data = { PC, PS, AbilitySystem, Attributes };
HUD->InitHostWidget(& Data);
}
} }
// TODO(Ed): We need to setup Net Slime...
void APlayerCharacter::OnRep_PlayerState() void APlayerCharacter::OnRep_PlayerState()
{ {
Super::OnRep_PlayerState(); Super::OnRep_PlayerState();
AGasaPlayerState* PS = GetGasaPlayerState();
// Client setup ability system
{
AbilitySystem = PS->AbilitySystem;
Attributes = PS->Attributes;
AbilitySystem->InitAbilityActorInfo(PS, this);
}
if (IsLocallyControlled())
{
AGasaPlayerController* PC = GetController<AGasaPlayerController>();
AGasaHUD* HUD = PC->GetHUD<AGasaHUD>();
FWidgetControllerData Data = { PC, PS, AbilitySystem, Attributes };
HUD->InitHostWidget(& Data);
}
} }

View File

@ -7,29 +7,34 @@ using namespace Gasa;
#pragma region GameFramework #pragma region GameFramework
// TODO(Ed): Make a NetLog // TODO(Ed): Make a NetLog
UGasaGameInstance::UGasaGameInstance()
{
GameFrameworkState = EGameFrameworkState::Uninitialized;
}
void UGasaGameInstance::NotifyGameFrameworkClassReady(EGameFrameworkClassFlag ClassReady) void UGasaGameInstance::NotifyGameFrameworkClassReady(EGameFrameworkClassFlag ClassReady)
{ {
switch (ClassReady) switch (ClassReady)
{ {
case EGameFrameworkClassFlag::GameMode: case EGameFrameworkClassFlag::GameMode:
GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::GameMode; GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::GameMode;
NetLog("Gameplay Framework class ready: Game State", ELogV::Log, LogGasaNet ); NetLog("Game Framework class ready: Game State", ELogV::Log, LogGasaNet );
break; break;
case EGameFrameworkClassFlag::GameState: case EGameFrameworkClassFlag::GameState:
GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::GameState; GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::GameState;
NetLog("Gameplay Framework class ready: Game State", ELogV::Log, LogGasaNet ); NetLog("Game Framework class ready: Game State", ELogV::Log, LogGasaNet );
break; break;
case EGameFrameworkClassFlag::PlayerController: case EGameFrameworkClassFlag::PlayerController:
GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::PlayerController; GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::PlayerController;
NetLog("Gameplay Framework class ready: Player Controller", ELogV::Log, LogGasaNet); NetLog("Game Framework class ready: Player Controller", ELogV::Log, LogGasaNet);
break; break;
case EGameFrameworkClassFlag::PlayerState: case EGameFrameworkClassFlag::PlayerState:
GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::PlayerState; GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::PlayerState;
NetLog("Gameplay Framework class ready: Player State", ELogV::Log, LogGasaNet); NetLog("Game Framework class ready: Player State", ELogV::Log, LogGasaNet);
break; break;
case EGameFrameworkClassFlag::Levels: case EGameFrameworkClassFlag::Levels:
GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::Levels; GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::Levels;
NetLog("Gameplay Framework class ready: Levels", ELogV::Log, LogGasaNet); NetLog("Game Framework class ready: Levels", ELogV::Log, LogGasaNet);
break; break;
} }
ProcessGameFrameworkState(); ProcessGameFrameworkState();
@ -68,7 +73,7 @@ void UGasaGameInstance::ProcessGameFrameworkState()
if (GameFrameworkClassesState == InitializedFlags) if (GameFrameworkClassesState == InitializedFlags)
{ {
GameFrameworkState = EGameFrameworkState::Initialized; GameFrameworkState = EGameFrameworkState::Initialized;
NetLog("Gameplay Framework initialized"); NetLog("Game Framework initialized");
Event_OnGameFrameworkInitialized.Broadcast(); Event_OnGameFrameworkInitialized.Broadcast();
} }
@ -84,8 +89,5 @@ void UGasaGameInstance::Init()
Super::Init(); Super::Init();
DevOptionsCache.CachedDevOptions(); DevOptionsCache.CachedDevOptions();
using namespace Gasa;
NetLog(FString::Printf(TEXT("UObject Size: %d RT: %d"), sizeof(UObject), UObject::StaticClass()->PropertiesSize ));
} }
#pragma region GameInstance #pragma endregion GameInstance

View File

@ -21,8 +21,8 @@ enum class EGameFrameworkClassFlag : uint8
UENUM(BlueprintType) UENUM(BlueprintType)
enum class EGameFrameworkState : uint8 enum class EGameFrameworkState : uint8
{ {
Initialized, Uninitialized,
Uninitialized Initialized
}; };
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnGameFrameworkInitializedSig); DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnGameFrameworkInitializedSig);
@ -33,6 +33,8 @@ class GASA_API UGasaGameInstance : public UGameInstance
GENERATED_BODY() GENERATED_BODY()
public: public:
UGasaGameInstance();
UPROPERTY(VisibleAnywhere, Category="Dev Cache") UPROPERTY(VisibleAnywhere, Category="Dev Cache")
FGasaDevOptionsCache DevOptionsCache; FGasaDevOptionsCache DevOptionsCache;

View File

@ -1,9 +1,9 @@
#include "GasaGameMode.h" #include "GasaGameMode.h"
#include "Online/CoreOnline.h"
#include "GasaGameInstance.h" #include "GasaGameInstance.h"
#include "GasaGameState.h" #include "GasaGameState.h"
#include "GasaPlayerController.h" #include "GasaPlayerController.h"
#include "GasaPlayerState.h"
#include "Engine/Player.h" #include "Engine/Player.h"
#include "GameFramework/GameSession.h" #include "GameFramework/GameSession.h"
#include "GameFramework/GameState.h" #include "GameFramework/GameState.h"
@ -71,6 +71,33 @@ void AGasaGameMode::EndPlay(const EEndPlayReason::Type EndPlayReason)
NetLog("EndPlay"); NetLog("EndPlay");
} }
void AGasaGameMode::FinishRestartPlayer(AController* NewPlayer, const FRotator& StartRotation)
{
// Super::FinishRestartPlayer(NewPlayer, StartRotation);
{
NewPlayer->Possess(NewPlayer->GetPawn());
// If the Pawn is destroyed as part of possession we have to abort
if (!IsValid(NewPlayer->GetPawn()))
{
FailedToRestartPlayer(NewPlayer);
}
else
{
// Set initial control rotation to starting rotation rotation
NewPlayer->ClientSetRotation(NewPlayer->GetPawn()->GetActorRotation(), true);
FRotator NewControllerRot = StartRotation;
NewControllerRot.Roll = 0.f;
NewPlayer->SetControlRotation(NewControllerRot);
SetPlayerDefaults(NewPlayer->GetPawn());
K2_OnRestartPlayer(NewPlayer);
}
}
}
void AGasaGameMode::GenericPlayerInitialization(AController* C) void AGasaGameMode::GenericPlayerInitialization(AController* C)
{ {
NetLog("GenericPlayerInitialization: " + C->GetName()); NetLog("GenericPlayerInitialization: " + C->GetName());
@ -360,10 +387,10 @@ void AGasaGameMode::PostLogin(APlayerController* NewPlayer)
{ {
UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>(); UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>();
// int32 numconnections = gi->sessionsettings.bpublicgame
// ? GI->SessionSettings.PublicConnections : GI->SessionSettings.PrivateConnections;
#if 0 #if 0
int32 numconnections = GI->sessionsettings.bPublicGame
? GI->SessionSettings.PublicConnections : GI->SessionSettings.PrivateConnections;
if (GS->OnlinePlayers.Num() < NumConnections) if (GS->OnlinePlayers.Num() < NumConnections)
{ {
GS->OnlinePlayers.Init( nullptr, NumConnections ); GS->OnlinePlayers.Init( nullptr, NumConnections );
@ -388,8 +415,8 @@ void AGasaGameMode::PostLogin(APlayerController* NewPlayer)
} }
AGasaPlayerController* PC = Cast<AGasaPlayerController>(NewPlayer); AGasaPlayerController* PC = Cast<AGasaPlayerController>(NewPlayer);
// if (PC) if (PC)
// PC->Event_OnNetOwner_GameplayFrameworkInitialized.AddDynamic(this, &ThisClass::OwningClient_OnGameFrameworkInitialized); PC->Event_NetOwner_OnGameFrameworkInitialized.AddDynamic(this, &ThisClass::OwningClient_OnGameFrameworkInitialized);
} }
void AGasaGameMode::PostSeamlessTravel() void AGasaGameMode::PostSeamlessTravel()
@ -401,11 +428,7 @@ void AGasaGameMode::PostSeamlessTravel()
void AGasaGameMode::SetPlayerDefaults(APawn* PlayerPawn) void AGasaGameMode::SetPlayerDefaults(APawn* PlayerPawn)
{ {
InitializeHUDForPlayer(Cast<APlayerController>(PlayerPawn->GetController())); InitializeHUDForPlayer(Cast<APlayerController>(PlayerPawn->GetController()));
Super::SetPlayerDefaults(PlayerPawn);
// Super::SetPlayerDefaults(PlayerPawn);
{
PlayerPawn->SetPlayerDefaults();
}
} }
void AGasaGameMode::SetSeamlessTravelViewTarget(APlayerController* PC) void AGasaGameMode::SetSeamlessTravelViewTarget(APlayerController* PC)

View File

@ -24,7 +24,7 @@ public:
UFUNCTION() UFUNCTION()
void OwningClient_OnGameFrameworkInitialized(AGasaPlayerController* PC); void OwningClient_OnGameFrameworkInitialized(AGasaPlayerController* PC);
UFUNCTION(BlueprintCallable, meta=(DisplayName = "On Game Framework Initialized")) UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta=(DisplayName = "On Game Framework Initialized"))
void BP_OnGameFrameworkInitialized(); void BP_OnGameFrameworkInitialized();
#pragma endregion GameFramework #pragma endregion GameFramework
@ -60,6 +60,8 @@ public:
#pragma region GameModeBase #pragma region GameModeBase
void EndPlay(const EEndPlayReason::Type EndPlayReason) override; void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
void FinishRestartPlayer(AController* NewPlayer, const FRotator& StartRotation) override;
void GenericPlayerInitialization(AController* C) override; void GenericPlayerInitialization(AController* C) override;
TSubclassOf<APlayerController> GetPlayerControllerClassToSpawnForSeamlessTravel(APlayerController* PreviousPlayerController) override; TSubclassOf<APlayerController> GetPlayerControllerClassToSpawnForSeamlessTravel(APlayerController* PreviousPlayerController) override;

View File

@ -5,6 +5,7 @@
#include "GasaPlayerState.h" #include "GasaPlayerState.h"
#include "GasaGameInstance.h" #include "GasaGameInstance.h"
#include "Net/UnrealNetwork.h" #include "Net/UnrealNetwork.h"
#include "Networking/GasaNetLibrary_Inlines.h"
using namespace Gasa; using namespace Gasa;
AGasaGameState::AGasaGameState() AGasaGameState::AGasaGameState()
@ -15,7 +16,6 @@ AGasaGameState::AGasaGameState()
PrimaryActorTick.bStartWithTickEnabled = true; PrimaryActorTick.bStartWithTickEnabled = true;
// Replication // Replication
bReplicates = true; bReplicates = true;
bNetLoadOnClient = false; bNetLoadOnClient = false;
NetDormancy = DORM_Awake; NetDormancy = DORM_Awake;

View File

@ -1,3 +1,4 @@
#pragma once
#include "GameFramework/GameState.h" #include "GameFramework/GameState.h"
#include "GasaCommon.h" #include "GasaCommon.h"
@ -6,10 +7,6 @@
#include "GasaGameState.generated.h" #include "GasaGameState.generated.h"
DECLARE_MULTICAST_DELEGATE( FOnTravelDelegate );
DECLARE_DYNAMIC_MULTICAST_DELEGATE( FOnTravelSig );
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerCharacterReadySig, APlayerCharacter*, Character);
UCLASS( Blueprintable ) UCLASS( Blueprintable )
class GASA_API AGasaGameState : public AGameState class GASA_API AGasaGameState : public AGameState
{ {
@ -29,11 +26,21 @@ public:
AGasaGameState(); AGasaGameState();
#pragma region GameFramework #pragma region GameFramework
UPROPERTY(BlueprintAssignable)
FOnPawnReadySig Event_OnPlayerPawnReady;
UFUNCTION() UFUNCTION()
void OnGameFrameworkInitialized(); void OnGameFrameworkInitialized();
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta=(DisplayName = "Game Framework Initialized")) UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta=(DisplayName = "Game Framework Initialized"))
void BP_OnGameFrameworkInitialized(); void BP_OnGameFrameworkInitialized();
UFUNCTION()
void NotifyPlayerPawnReady(APawn* Pawn)
{
if (Event_OnPlayerPawnReady.IsBound())
Event_OnPlayerPawnReady.Broadcast(Pawn);
}
#pragma endregion GameFramework #pragma endregion GameFramework
#pragma region Networking #pragma region Networking
@ -41,7 +48,7 @@ public:
AGasaPlayerState* ListenServerHost; AGasaPlayerState* ListenServerHost;
UPROPERTY(ReplicatedUsing = "Client_OnRep_OnlinePlayers", BlueprintReadOnly) UPROPERTY(ReplicatedUsing = "Client_OnRep_OnlinePlayers", BlueprintReadOnly)
TArray<AGasaPlayerState> OnlinePlayers; TArray<AGasaPlayerState*> OnlinePlayers;
UFUNCTION() UFUNCTION()
void Client_OnRep_OnlinePlayers(); void Client_OnRep_OnlinePlayers();

View File

@ -6,6 +6,7 @@
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "Materials/MaterialInstance.h" #include "Materials/MaterialInstance.h"
#include "Materials/MaterialInstanceDynamic.h" #include "Materials/MaterialInstanceDynamic.h"
#include "Networking/GasaNetLibrary_Inlines.h"
using namespace Gasa; using namespace Gasa;
#pragma region Game Framework #pragma region Game Framework
@ -54,7 +55,7 @@ void AGasaLevelScriptActor::BeginPlay()
if(GI) if(GI)
GI->Event_OnGameFrameworkInitialized.AddUniqueDynamic(this, & ThisClass::OnGameFrameworkInitialized); GI->Event_OnGameFrameworkInitialized.AddUniqueDynamic(this, & ThisClass::OnGameFrameworkInitialized);
if (!bOverrideGameplayFrameworkReady) if (!bOverrideGameFrameworkReady)
GI->NotifyGameFrameworkClassReady(EGameFrameworkClassFlag::Levels); GI->NotifyGameFrameworkClassReady(EGameFrameworkClassFlag::Levels);
} }
#pragma endregion Actor #pragma endregion Actor

View File

@ -19,7 +19,7 @@ public:
#pragma region GameFramework #pragma region GameFramework
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
bool bOverrideGameplayFrameworkReady = false; bool bOverrideGameFrameworkReady = false;
UFUNCTION() UFUNCTION()
void OnGameFrameworkInitialized(); void OnGameFrameworkInitialized();

View File

@ -1,18 +1,26 @@
#include "GasaPlayerController.h" #include "GasaPlayerController.h"
#include "GasaPlayerController_Inlines.h" #include "GasaPlayerController_Inlines.h"
#include "Networking/GasaNetLibrary_Inlines.h"
#include "AbilitySystemComponent.h" #include "AbilitySystemComponent.h"
#include "Engine/LocalPlayer.h" #include "Engine/LocalPlayer.h"
#include "EnhancedInputComponent.h" #include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h" #include "EnhancedInputSubsystems.h"
#include "Characters/GasaCharacter.h"
#include "Characters/PlayerCharacter.h"
#include "Components/CapsuleComponent.h"
#include "Interfaces/NetworkPredictionInterface.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Net/UnrealNetwork.h"
#include "GameFramework/PawnMovementComponent.h"
#include "GasaDevOptions.h" #include "GasaDevOptions.h"
#include "GasaGameInstance.h"
#include "GasaGameState.h"
#include "GasaPlayerState.h" #include "GasaPlayerState.h"
#include "Actors/CameraMount.h" #include "Actors/CameraMount.h"
#include "Camera/CameraComponent.h" #include "UI/GasaHUD.h"
#include "Characters/GasaCharacter.h" #include "UI/WidgetController.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "Kismet/KismetSystemLibrary.h"
using namespace Gasa; using namespace Gasa;
AGasaPlayerController::AGasaPlayerController() AGasaPlayerController::AGasaPlayerController()
@ -24,7 +32,143 @@ AGasaPlayerController::AGasaPlayerController()
bReplicates = true; bReplicates = true;
} }
void AGasaPlayerController::OnSeamlessTravelStart()
{
}
#pragma region GameFramework
void AGasaPlayerController::Client_CheckIfOwnerReady()
{
if (IsServer())
return;
UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>();
if ( ! GI->IsGameFrameworkInitialized() || PlayerState == NULL || ! IsValid(GetPawn()))
return;
NetOwner_OnReady();
}
void AGasaPlayerController::NetOwner_OnReady()
{
NetLog("Net Owner of controller is ready to play.");
if ( ! IsNetOwner() || bNetOwnerReady)
return;
BP_NetOwner_OnReady();
Event_NetOwner_OnReady.Broadcast(this);
bNetOwnerReady = true;
AGasaGameState* GS = Cast<AGasaGameState>(GetWorld()->GetGameState());
if (GS)
GS->NotifyPlayerPawnReady(GetPawn());
if (IsClient())
ServerRPC_R_NotifyOwningClientReady();
AGasaPlayerState* PS = GetPlayerState();
APlayerCharacter* PlayerChar = GetPawn<APlayerCharacter>();
{
PlayerChar->AbilitySystem = PS->AbilitySystem;
PlayerChar->Attributes = PS->Attributes;
PlayerChar->AbilitySystem->InitAbilityActorInfo(PS, this);
Cam->AttachToActor(PlayerChar, FAttachmentTransformRules::KeepRelativeTransform);
}
}
void AGasaPlayerController::OnGameFrameworkInitialized()
{
NetLog("Received game framework initialization.");
if (IsNetOwner())
{
Server_SetNetOwner_GameFrameworkInitialized();
Client_CheckIfOwnerReady();
}
AGasaGameState* GS = GetGameState(this);
NullGuard_DEV(GS, Log, "OnGameFrameworkInitialized: GS is null");
GS->Event_OnSeamlessTravelStart.AddDynamic( this, & ThisClass::OnSeamlessTravelStart );
BP_OnGameFrameworkInitialized();
}
void AGasaPlayerController::OnPawnReady()
{
NetLog("Player is ready.");
// Originally: Super::OnPossess(PawnToPossess);
{
ChangeState(NAME_Playing);
if (bAutoManageActiveCameraTarget)
{
AutoManageActiveCameraTarget(GetPawn());
ResetCameraMode();
}
}
// Override this and add your own conditions...
BP_OnPawnReady();
if (IsServer() && IsNetOwner())
{
// The server host doesn't have to wait for the player state to replicate.
NetOwner_OnReady();
}
}
void AGasaPlayerController::Server_SetupOnPawnReadyBinds(APawn* PawnToBindTo)
{
if (IsClient())
return;
#if 0
if (PawnToBindTo->IsA(AGasaPawn::StaticClass()))
{
Cast<AGasaPawn>(PawnToBindTo)->Event_OnPawnReady.AddUniqueDynamic(this, & ThisClass::OnPawnReady);
}
else
#endif
if (PawnToBindTo->IsA(AGasaCharacter::StaticClass()))
{
Cast<AGasaCharacter>(PawnToBindTo)->Event_OnPawnReady.AddUniqueDynamic(this, & ThisClass::OnPawnReady);
}
}
void AGasaPlayerController::Server_SetNetOwner_GameFrameworkInitialized()
{
if (IsClient())
{
ServerRPC_R_SetNetOwner_GameFrameworkInitialized();
return;
}
bNetOwner_GameFrameworkInitialized = true;
if (Event_NetOwner_OnGameFrameworkInitialized.IsBound())
{
Event_NetOwner_OnGameFrameworkInitialized.Broadcast(this);
Event_NetOwner_OnGameFrameworkInitialized.Clear();
}
}
void AGasaPlayerController::ServerRPC_R_NotifyOwningClientReady_Implementation()
{
NetLog("Net Owner Ready: Notified via RPC.");
BP_NetOwner_OnReady();
bNetOwnerReady = true;
Event_NetOwner_OnReady.Broadcast(this);
Event_NetOwner_OnReady.Clear();
AGasaGameState* GS = GetGameState(this);
if (GS)
GS->NotifyPlayerPawnReady(GetPawn());
}
void AGasaPlayerController::ServerRPC_R_SetNetOwner_GameFrameworkInitialized_Implementation()
{
Server_SetNetOwner_GameFrameworkInitialized();
}
#pragma endregion GameFramework
#pragma region Input #pragma region Input
void AGasaPlayerController::Move(FInputActionValue const& ActionValue) void AGasaPlayerController::Move(FInputActionValue const& ActionValue)
@ -72,27 +216,107 @@ void AGasaPlayerController::Move(FInputActionValue const& ActionValue)
#pragma endregion Input #pragma endregion Input
#pragma region PlayerController #pragma region PlayerController
void AGasaPlayerController::SpawnDefaultHUD() bool AGasaPlayerController::CanRestartPlayer()
{ {
Super::SpawnDefaultHUD(); bool BaseCheck =
PlayerState &&
!PlayerState->IsOnlyASpectator() &&
HasClientLoadedCurrentWorld() &&
PendingSwapConnection == NULL
;
return BaseCheck && bNetOwner_GameFrameworkInitialized;
}
void AGasaPlayerController::ClientSetHUD_Implementation(TSubclassOf<AHUD> NewHUDClass)
{
Super::ClientSetHUD_Implementation(NewHUDClass);
AGasaPlayerState* PS = GetPlayerState();
AGasaHUD* HUD = GetHUD<AGasaHUD>();
FWidgetControllerData Data = { this, PS, PS->AbilitySystem, PS->Attributes };
HUD->InitHostWidget(& Data);
}
void AGasaPlayerController::ClientUpdateLevelStreamingStatus_Implementation(FName PackageName, bool bNewShouldBeLoaded, bool bNewShouldBeVisible,
bool bNewShouldBlockOnLoad, int32 LODIndex, FNetLevelVisibilityTransactionId TransactionId, bool bNewShouldBlockOnUnload)
{
Super::ClientUpdateLevelStreamingStatus_Implementation(PackageName, bNewShouldBeLoaded, bNewShouldBeVisible, bNewShouldBlockOnLoad, LODIndex,
TransactionId, bNewShouldBlockOnUnload);
NetLog("ClientUpdateLevelStreamingStatus");
NetLog(FString("PackageName : ") + PackageName.ToString());
NetLog(FString("NewShouldBeLoaded : ") + FString(bNewShouldBeLoaded ? "true" : "false"));
NetLog(FString("NewShouldBeVisible : ") + FString(bNewShouldBeVisible ? "true" : "false"));
NetLog(FString("bNewShouldBlockOnLoad : ") + FString(bNewShouldBlockOnLoad ? "true" : "false"));
NetLog(FString("bNewShouldBlockOnUnload: ") + FString(bNewShouldBlockOnUnload ? "true" : "false"));
NetLog(FString("LODIndex : ") + FString::FromInt( LODIndex ));
} }
// TODO(Ed): We need to setup Net Slime... // TODO(Ed): We need to setup Net Slime...
void AGasaPlayerController::OnPossess(APawn* InPawn) void AGasaPlayerController::OnPossess(APawn* PawnPossesed)
{ {
Super::OnPossess(InPawn); // Super::OnPossess(PawnPossesed);
Cam->AttachToActor(InPawn, FAttachmentTransformRules::KeepRelativeTransform);
AGasaPlayerState* PS = GetPlayerState();
AGasaCharacter* character = Cast<AGasaCharacter>(InPawn);
// Net Owner setup ability system
if (0)
{ {
character->AbilitySystem = PS->AbilitySystem; if (PawnPossesed && (PlayerState == NULL || !PlayerState->IsOnlyASpectator()) )
character->Attributes = PS->Attributes; {
character->AbilitySystem->InitAbilityActorInfo(PS, character); // ====================================================================Originally: Super::OnPossess(PawnToPossess);
const bool bNewPawn = (GetPawn() != PawnPossesed);
if (GetPawn() && bNewPawn)
UnPossess();
if (PawnPossesed->Controller != NULL)
PawnPossesed->Controller->UnPossess();
PawnPossesed->PossessedBy(this);
// update rotation to match possessed pawn's rotation
SetControlRotation( PawnPossesed->GetActorRotation() );
SetPawn(PawnPossesed);
check(GetPawn() != NULL);
if (GetPawn() && GetPawn()->PrimaryActorTick.bStartWithTickEnabled)
GetPawn()->SetActorTickEnabled(true);
INetworkPredictionInterface* NetworkPredictionInterface = GetPawn()
? Cast<INetworkPredictionInterface>(GetPawn()->GetMovementComponent())
: nullptr;
if (NetworkPredictionInterface)
NetworkPredictionInterface->ResetPredictionData_Server();
AcknowledgedPawn = NULL;
// Local PCs will have the Restart() triggered right away in ClientRestart (via PawnClientRestart()), but the server should call Restart() locally for remote PCs.
// We're really just trying to avoid calling Restart() multiple times.
if (!IsLocalPlayerController())
GetPawn()->Restart();
ClientRestart(GetPawn());
// Moved to: void AGasaPlayerController::OnPawnReady
#if 0
ChangeState( NAME_Playing );
if (bAutoManageActiveCameraTarget)
{
AutoManageActiveCameraTarget(GetPawn());
ResetCameraMode();
} }
#endif
//==========================================================End of=================== Originally: Super::OnPossess(PawnToPossess);
NetLog("OnPossess");
Server_SetupOnPawnReadyBinds(PawnPossesed);
Event_OnPawnPossessed.Broadcast();
}
}
}
void AGasaPlayerController::OnRep_Pawn()
{
Super::OnRep_Pawn();
NetLog("OnRep_Pawn");
Client_CheckIfOwnerReady();
} }
void AGasaPlayerController::OnUnPossess() void AGasaPlayerController::OnUnPossess()
@ -138,6 +362,11 @@ void AGasaPlayerController::PlayerTick(float DeltaTime)
} }
} }
void AGasaPlayerController::PostSeamlessTravel()
{
Super::PostSeamlessTravel();
}
void AGasaPlayerController::SetupInputComponent() void AGasaPlayerController::SetupInputComponent()
{ {
Super::SetupInputComponent(); Super::SetupInputComponent();
@ -148,12 +377,22 @@ void AGasaPlayerController::SetupInputComponent()
EIC->BindAction(IA_Move, ETriggerEvent::Triggered, this, &ThisClass::Move); EIC->BindAction(IA_Move, ETriggerEvent::Triggered, this, &ThisClass::Move);
} }
} }
void AGasaPlayerController::SpawnDefaultHUD()
{
Super::SpawnDefaultHUD();
}
#pragma endregion PlayerController #pragma endregion PlayerController
#pragma region Actor #pragma region Actor
void AGasaPlayerController::BeginPlay() void AGasaPlayerController::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
NetLog("BeginPlay");
UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>();
GI->Event_OnGameFrameworkInitialized.AddUniqueDynamic(this, & AGasaPlayerController::OnGameFrameworkInitialized);
GI->NotifyGameFrameworkClassReady(EGameFrameworkClassFlag::PlayerController);
if (IsLocalController()) if (IsLocalController())
{ {
@ -209,4 +448,11 @@ void AGasaPlayerController::Tick(float DeltaSeconds)
} }
#endif #endif
} }
void AGasaPlayerController::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AGasaPlayerController, bNetOwner_GameFrameworkInitialized);
}
#pragma endregion Actor #pragma endregion Actor

View File

@ -1,17 +1,26 @@
#pragma once #pragma once
#include "GasaCommon.h" #include "GasaCommon.h"
#include "GasaPlayerState.h"
#include "Networking/GasaNetLibrary.h"
#include "Engine/Engine.h" #include "Engine/Engine.h"
#include "GameFramework/PlayerController.h" #include "GameFramework/PlayerController.h"
#include "Networking/GasaNetLibrary.h"
#include "GasaPlayerController.generated.h" #include "GasaPlayerController.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnGasaPlayerControllerSig, AGasaPlayerController*, PC);
UCLASS(Blueprintable) UCLASS(Blueprintable)
class GASA_API AGasaPlayerController : public APlayerController class GASA_API AGasaPlayerController : public APlayerController
{ {
GENERATED_BODY() GENERATED_BODY()
protected:
friend void AGasaPlayerState::ClientInitialize(AController* NewOwner);
public: public:
UFUNCTION()
void OnSeamlessTravelStart();
#pragma region Camera #pragma region Camera
UPROPERTY(EditAnywhere, BlueprintReadWrite) UPROPERTY(EditAnywhere, BlueprintReadWrite)
TObjectPtr<ACameraMount> Cam; TObjectPtr<ACameraMount> Cam;
@ -34,6 +43,55 @@ public:
#pragma endregion Highlighting #pragma endregion Highlighting
#endif #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 #pragma region Input
UPROPERTY(VisibleAnywhere, BlueprintReadOnly) UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
TObjectPtr<AGasaCharacter> HoverPrev; TObjectPtr<AGasaCharacter> HoverPrev;
@ -50,10 +108,6 @@ public:
void Move(FInputActionValue const& ActionValue); void Move(FInputActionValue const& ActionValue);
#pragma endregion Input #pragma endregion Input
AGasaPlayerController();
inline AGasaPlayerState* GetPlayerState();
#pragma region NetSlime #pragma region NetSlime
// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp // NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); } FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); }
@ -76,24 +130,35 @@ public:
} }
#pragma endregion NetSlime #pragma endregion NetSlime
AGasaPlayerController();
inline AGasaPlayerState* GetPlayerState();
#pragma region PlayerController #pragma region PlayerController
void SpawnDefaultHUD() override; bool CanRestartPlayer() override;
void ClientSetHUD_Implementation(TSubclassOf<AHUD> NewHUDClass) override;
void OnPossess(APawn* InPawn) override; void ClientUpdateLevelStreamingStatus_Implementation(FName PackageName, bool bNewShouldBeLoaded, bool bNewShouldBeVisible, bool bNewShouldBlockOnLoad, int32 LODIndex, FNetLevelVisibilityTransactionId TransactionId, bool bNewShouldBlockOnUnload) override;
void OnUnPossess() override;
void PlayerTick(float DeltaTime) override; void PlayerTick(float DeltaTime) override;
void PostSeamlessTravel() override;
void SetupInputComponent() override; void SetupInputComponent() override;
void SpawnDefaultHUD() override;
#pragma endregion PlayerController #pragma endregion PlayerController
#pragma region Controller
void OnPossess(APawn* InPawn) override;
void OnRep_Pawn() override;
void OnUnPossess() override;
#pragma endregion Controller
#pragma region Actor #pragma region Actor
void BeginPlay() override; void BeginPlay() override;
void PostInitializeComponents() override; void PostInitializeComponents() override;
void Tick(float DeltaSeconds) override; void Tick(float DeltaSeconds) override;
#pragma endregion Actor #pragma endregion Actor
#pragma region UObject
void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
#pragma endregion UObject
}; };
namespace Gasa namespace Gasa

View File

@ -1,5 +1,8 @@
#include "GasaPlayerState.h" #include "GasaPlayerState.h"
#include "Networking/GasaNetLibrary_Inlines.h"
#include "GasaGameInstance.h"
#include "GasaPlayerController.h"
#include "AbilitySystem/GasaAbilitySystemComponent.h" #include "AbilitySystem/GasaAbilitySystemComponent.h"
#include "AbilitySystem/GasaAttributeSet.h" #include "AbilitySystem/GasaAttributeSet.h"
@ -16,3 +19,74 @@ AGasaPlayerState::AGasaPlayerState()
// Replication // Replication
NetUpdateFrequency = 100.f; NetUpdateFrequency = 100.f;
} }
#pragma region GameFramework
void AGasaPlayerState::OnGameFrameworkInitialized()
{
NetLog("Received game framework initialization.");
BP_OnGameFrameworkInitialized();
}
void AGasaPlayerState::OnNetOwnerReady(AGasaPlayerController* PC)
{
BP_OnNetOwnerReady();
}
void AGasaPlayerState::Reset()
{
Super::Reset();
NetLog("Reset");
}
#pragma endregion GameFramework
#pragma region PlayerState
void AGasaPlayerState::ClientInitialize(AController* NewOwner)
{
Super::ClientInitialize(NewOwner);
NetLog("Client Initialization: This is the OnRep for player state.");
AGasaPlayerController* GasaPC = Cast<AGasaPlayerController>(NewOwner);
if (GasaPC)
GasaPC->Client_CheckIfOwnerReady();
}
#pragma endregion PlayerState
#pragma region Actor
void AGasaPlayerState::BeginPlay()
{
NetLog("Begin Play");
Super::BeginPlay();
UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>();
GI->Event_OnGameFrameworkInitialized.AddDynamic(this, & ThisClass::OnGameFrameworkInitialized);
GI->NotifyGameFrameworkClassReady(EGameFrameworkClassFlag::PlayerState);
}
void AGasaPlayerState::PostInitializeComponents()
{
Super::PostInitializeComponents();
NetLog("Post Initialization");
}
void AGasaPlayerState::RegisterPlayerWithSession(bool bWasFromInvite)
{
Super::RegisterPlayerWithSession(bWasFromInvite);
NetLog("RegisterPlayerWithSession");
if (IsServer() && GetInstigatorController())
{
AGasaPlayerController* PC = Cast<AGasaPlayerController>(GetInstigatorController());
PC->Event_NetOwner_OnReady.AddDynamic(this, & ThisClass::OnNetOwnerReady);
}
}
#pragma endregion Actor
#pragma region UObject
void AGasaPlayerState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
}
#pragma endregion UObject

View File

@ -15,6 +15,8 @@ class GASA_API AGasaPlayerState : public APlayerState
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
AGasaPlayerState();
#pragma region Ability System #pragma region Ability System
UPROPERTY(EditAnywhere, Category="Ability System") UPROPERTY(EditAnywhere, Category="Ability System")
bool bAutoAbilitySystem; bool bAutoAbilitySystem;
@ -26,7 +28,29 @@ public:
TObjectPtr<UAttributeSet> Attributes; TObjectPtr<UAttributeSet> Attributes;
#pragma endregion Ability System #pragma endregion Ability System
AGasaPlayerState(); #pragma region GameFramework
UFUNCTION()
void OnGameFrameworkInitialized();
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta = (DisplayName = "On Game Framework Initialized"))
void BP_OnGameFrameworkInitialized();
UFUNCTION()
void OnNetOwnerReady(AGasaPlayerController* PC);
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta = (DisplayName = "On Net Owner Ready"))
void BP_OnNetOwnerReady();
#pragma endregion GameFramework
#pragma region Networking
#if 0
UPROPERTY(ReplicatedUsing = Client_OnRep_GasaID)
int32 GasaID = INDEX_NONE;
UFUNCTION()
void Client_OnRep_GasaID;
#endif
#pragma endregion Networking
#pragma region NetSlime #pragma region NetSlime
// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp // NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
@ -55,7 +79,18 @@ public:
FORCEINLINE UAbilitySystemComponent* GetAbilitySystemComponent() const override { return AbilitySystem; } FORCEINLINE UAbilitySystemComponent* GetAbilitySystemComponent() const override { return AbilitySystem; }
#pragma endregion IAbilitySystem #pragma endregion IAbilitySystem
// #pragma region #pragma region PlayerState
// void ClientInitialize(AController* C) override;
// #pragma endregion #pragma endregion PlayerState
#pragma region Actor
void BeginPlay() override;
void PostInitializeComponents() override;
void RegisterPlayerWithSession(bool bWasFromInvite) override;
void Reset() override;
#pragma endregion Actor
#pragma region UObject
void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
#pragma endregion UObject
}; };

View File

@ -48,6 +48,7 @@ public class Gasa : ModuleRules
"Core", "Core",
"AIModule", "AIModule",
"CoreOnline",
"CoreUObject", "CoreUObject",
"DeveloperSettings", "DeveloperSettings",
"Engine", "Engine",

View File

@ -35,8 +35,8 @@
#include "Game/GasaViewport.h" #include "Game/GasaViewport.h"
// Networking // Networking
// #include "Networking/GasaNetLibrary.h" #include "Networking/GasaNetLibrary.h"
// #include "Networking/GasaNetLibrary_Inlines.h" #include "Networking/GasaNetLibrary_Inlines.h"
// UI // UI
// #include "UI/GasaCanvas.h" // #include "UI/GasaCanvas.h"

View File

@ -2,6 +2,8 @@
#include "GasaEngineMinimal.h" #include "GasaEngineMinimal.h"
#include "GasaCommon.generated.h"
#define global #define global
#define internal static #define internal static
#define local_persist static #define local_persist static
@ -18,14 +20,19 @@
#pragma region Engine Forwards #pragma region Engine Forwards
struct FInputActionValue; struct FInputActionValue;
struct FOnAttributeChangeData; struct FOnAttributeChangeData;
struct FReplicationFlags;
class AActor; class AActor;
class APawn;
class APostProcessVolume; class APostProcessVolume;
class FOutBunch;
class IAbilitySystemInterface; class IAbilitySystemInterface;
class UAbilitySystemComponent; class UAbilitySystemComponent;
class UAbilitySystemInterface; class UAbilitySystemInterface;
class UActorChannel;
class UAttributeSet; class UAttributeSet;
class UCameraComponent; class UCameraComponent;
class UGameplayEffect; class UGameplayEffect;
@ -189,3 +196,12 @@ namespace Gasa
constexpr float _480Hz = .002f; constexpr float _480Hz = .002f;
} }
#pragma endregion Timing #pragma endregion Timing
#pragma region Delegates
DECLARE_MULTICAST_DELEGATE(FOnTravelDelegate);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnTravelSig);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnPawnSig);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerCharacterReadySig, APlayerCharacter*, Character);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPawnReadySig, APawn*, Pawn);
#pragma endregion Delegates

View File

@ -21,140 +21,5 @@
#include "Misc/VarArgs.h" #include "Misc/VarArgs.h"
#include "Logging/LogVerbosity.h" #include "Logging/LogVerbosity.h"
#include "UObject/ObjectMacros.h" #include "UObject/ObjectMacros.h"
#include "Delegates/Delegate.h"
// #include "Misc/OutputDevice.h" #include "Delegates/DelegateCombinations.h"
// #include "HAL/PlatformCrt.h"
// #include "HAL/PlatformMisc.h"
// #include "Misc/AssertionMacros.h"
// #include "Templates/IsPointer.h"
// #include "HAL/PlatformMemory.h"
// #include "HAL/PlatformAtomics.h"
// #include "Misc/Exec.h"
// #include "HAL/MemoryBase.h"
// #include "HAL/UnrealMemory.h"
// #include "Templates/IsArithmetic.h"
// #include "Templates/AndOrNot.h"
// #include "Templates/IsPODType.h"
// #include "Templates/IsUECoreType.h"
// #include "Templates/IsTriviallyCopyConstructible.h"
// #include "Templates/UnrealTypeTraits.h"
// #include "Templates/EnableIf.h"
// #include "Templates/RemoveReference.h"
// #include "Templates/IntegralConstant.h"
// #include "Templates/IsClass.h"
// #include "Templates/TypeCompatibleBytes.h"
// #include "Traits/IsContiguousContainer.h"
// #include "Templates/UnrealTemplate.h"
// #include "Math/NumericLimits.h"
// #include "HAL/PlatformMath.h"
// #include "Templates/IsTriviallyCopyAssignable.h"
// #include "Templates/IsTriviallyDestructible.h"
// #include "Templates/MemoryOps.h"
// #include "Containers/ContainerAllocationPolicies.h"
// #include "Templates/IsEnumClass.h"
// #include "HAL/PlatformProperties.h"
// #include "Misc/EngineVersionBase.h"
// #include "Internationalization/TextNamespaceFwd.h"
// #include "Serialization/Archive.h"
// #include "Templates/Less.h"
// #include "Templates/Sorting.h"
// #include "Misc/Char.h"
// #include "GenericPlatform/GenericPlatformStricmp.h"
// #include "GenericPlatform/GenericPlatformString.h"
// #include "HAL/PlatformString.h"
// #include "Misc/CString.h"
// #include "Misc/Crc.h"
// #include "Math/UnrealMathUtility.h"
// #include "Containers/UnrealString.h"
// #include "Containers/Array.h"
// #include "Misc/FrameNumber.h"
// #include "Misc/Timespan.h"
// #include "Containers/StringConv.h"
// #include "UObject/UnrealNames.h"
// #include "UObject/NameTypes.h"
// #include "Misc/Parse.h"
// #include "Templates/AlignmentTemplates.h"
// #include "Misc/StructBuilder.h"
// #include "Templates/Decay.h"
// #include "Templates/PointerIsConvertibleFromTo.h"
// #include "Templates/Invoke.h"
// #include "Templates/Function.h"
// #include "Templates/TypeHash.h"
// #include "Containers/ScriptArray.h"
// #include "Containers/BitArray.h"
// #include "Containers/SparseArray.h"
// #include "Containers/Set.h"
// #include "Algo/Reverse.h"
// #include "Containers/Map.h"
// #include "Math/IntPoint.h"
// #include "Math/IntVector.h"
// #include "Logging/LogCategory.h"
// #include "Logging/LogMacros.h"
// #include "Math/Vector2D.h"
// #include "Math/IntRect.h"
// #include "Misc/ByteSwap.h"
// #include "Containers/EnumAsByte.h"
// #include "HAL/PlatformTLS.h"
// #include "CoreGlobals.h"
// #include "Templates/SharedPointer.h"
// #include "Internationalization/CulturePointer.h"
// #include "UObject/WeakObjectPtrTemplates.h"
// #include "Delegates/DelegateSettings.h"
// #include "Delegates/IDelegateInstance.h"
// #include "Delegates/DelegateBase.h"
// #include "Delegates/MulticastDelegateBase.h"
// #include "Delegates/IntegerSequence.h"
// #include "Templates/Tuple.h"
// #include "UObject/ScriptDelegates.h"
// #include "Delegates/Delegate.h"
// #include "Internationalization/TextLocalizationManager.h"
// #include "Misc/Optional.h"
// #include "Templates/IsArray.h"
// #include "Templates/RemoveExtent.h"
// #include "Templates/UniquePtr.h"
// #include "Internationalization/Text.h"
// #include "Templates/UniqueObj.h"
// #include "Internationalization/Internationalization.h"
// #include "Math/Vector.h"
// #include "Math/Vector4.h"
// #include "Math/VectorRegister.h"
// #include "Math/TwoVectors.h"
// #include "Math/Edge.h"
// #include "UObject/ObjectVersion.h"
// #include "Math/CapsuleShape.h"
// #include "Math/Rotator.h"
// #include "Misc/DateTime.h"
// #include "Math/RangeBound.h"
// #include "Misc/AutomationEvent.h"
// #include "Math/Range.h"
// #include "Math/RangeSet.h"
// #include "Math/Interval.h"
// #include "Math/Box.h"
// #include "Math/Box2D.h"
// #include "Math/BoxSphereBounds.h"
// #include "Math/OrientedBox.h"
// #include "Math/Axis.h"
// #include "Math/Matrix.h"
// #include "Math/RotationTranslationMatrix.h"
// #include "Math/RotationAboutPointMatrix.h"
// #include "Math/ScaleRotationTranslationMatrix.h"
// #include "Math/RotationMatrix.h"
// #include "Math/Quat.h"
// #include "Math/PerspectiveMatrix.h"
// #include "Math/OrthoMatrix.h"
// #include "Math/TranslationMatrix.h"
// #include "Math/QuatRotationTranslationMatrix.h"
// #include "Math/InverseRotationMatrix.h"
// #include "Math/ScaleMatrix.h"
// #include "Math/MirrorMatrix.h"
// #include "Math/ClipProjectionMatrix.h"
// #include "Math/Float32.h"
// #include "Math/Float16.h"
// #include "Math/Transform.h"
// #include "Math/ConvexHull2d.h"
// #include "Math/UnrealMath.h"

View File

@ -1,15 +1,41 @@
#include "GasaNetLibrary.h" #include "GasaNetLibrary.h"
#include "GasaNetLibrary_Inlines.h" #include "GasaNetLibrary_Inlines.h"
#include "GasaObject.h"
#include "Kismet/KismetMathLibrary.h"
#include "Kismet/KismetSystemLibrary.h"
DEFINE_LOG_CATEGORY(LogGasaNet); DEFINE_LOG_CATEGORY(LogGasaNet);
void NetLog( UObject const* Context, FString Message, EGasaVerbosity Verbosity = EGasaVerbosity::Log namespace Gasa
, FLogCategoryBase& Category = LogGasaNet
, bool DumpStack = false
, int32 Line = __builtin_LINE()
, const ANSICHAR* File = __builtin_FILE()
, const ANSICHAR* Func = __builtin_FUNCTION() )
{ {
void DrawNetCullingSphere(const UObject* Context, float Duration, float Thickness)
{
const AActor* actor = nullptr;
if (Context->IsA(UGasaObject::StaticClass()))
actor = Cast<AActor>(Context->GetOuter());
else if (Context->IsA(AActor::StaticClass()))
actor = Cast<AActor>(Context);
if (actor)
UKismetSystemLibrary::DrawDebugSphere(actor
, actor->GetActorLocation()
, UKismetMathLibrary::Sqrt(actor->NetCullDistanceSquared) * 2
, 12
, FLinearColor(FColor::Emerald)
, Duration
, Thickness);
}
void NetLog( UObject const* Context, FString Message, EGasaVerbosity Verbosity
, FLogCategoryBase& Category
, bool DumpStack
, int32 Line
, const ANSICHAR* File
, const ANSICHAR* Func )
{
#if !UE_BUILD_SHIPPING && !NO_LOGGING #if !UE_BUILD_SHIPPING && !NO_LOGGING
ELogVerbosity::Type EngineVerbosity = (ELogVerbosity::Type) Verbosity; ELogVerbosity::Type EngineVerbosity = (ELogVerbosity::Type) Verbosity;
if ((EngineVerbosity & ELogVerbosity::VerbosityMask) > ELogVerbosity::COMPILED_IN_MINIMUM_VERBOSITY) if ((EngineVerbosity & ELogVerbosity::VerbosityMask) > ELogVerbosity::COMPILED_IN_MINIMUM_VERBOSITY)
@ -56,12 +82,13 @@ void NetLog( UObject const* Context, FString Message, EGasaVerbosity Verbosity =
static UE::Logging::Private::FStaticBasicLogRecord static UE::Logging::Private::FStaticBasicLogRecord
LOG_Static(TEXT("%s -- %hs %hs(%d)"), File, Line, EngineVerbosity, LOG_Dynamic); LOG_Static(TEXT("%s -- %hs %hs(%d)"), File, Line, EngineVerbosity, LOG_Dynamic);
SET_WARN_COLOR(COLOR_PURPLE) // SET_WARN_COLOR(COLOR_PURPLE)
if (DumpStack) if (DumpStack)
FDebug::DumpStackTraceToLog(EngineVerbosity); FDebug::DumpStackTraceToLog(EngineVerbosity);
BasicLog(Category, &LOG_Static, * FullMsg, File, Func, Line); BasicLog(Category, &LOG_Static, * FullMsg, File, Func, Line);
CLEAR_WARN_COLOR() // CLEAR_WARN_COLOR()
#endif #endif
}
} }

View File

@ -8,6 +8,34 @@
DECLARE_LOG_CATEGORY_EXTERN(LogGasaNet, Log, All); DECLARE_LOG_CATEGORY_EXTERN(LogGasaNet, Log, All);
#define NullGuard( Object_, Logger_, Message_ ) \
do { \
if ( ! IsValid(Object_) ) \
{ \
Logger_( (Message_) , ELogV::Error ); \
ensure( IsValid(Object_) ); \
return; \
} \
} while (0)
#define NetGuard( Condition_, Logger_, Message_ ) \
do { \
if ( Condition_ ) \
{ \
Logger_( (Message_) , ELogV::Error ); \
ensure( Condition_ ); \
return; \
} \
} while (0)
#if UE_BUILD_DEVELOPMENT
# define NullGuard_DEV NullGuard
# define NetGuard_DEV NetGuard
#else
# define NullGuard_DEV( Object_, Logger_, Message_)
# define NetGuard_DEV( Object_, Logger_, Message_)
#endif
UENUM(BlueprintType) UENUM(BlueprintType)
enum class ENetworkMode : uint8 enum class ENetworkMode : uint8
{ {
@ -39,13 +67,11 @@ namespace Gasa
bool IsListenServer(UObject const* Context); bool IsListenServer(UObject const* Context);
bool IsNetOwner(UObject const* Context); bool IsNetOwner(UObject const* Context);
bool IsNetOwner(UGasaObject const* Context);
bool IsNetOwner(AActor const* Context); bool IsNetOwner(AActor const* Context);
bool IsServer(UObject const* Context); bool IsServer(UObject const* Context);
bool IsSimulatedProxy(UObject const* Context); bool IsSimulatedProxy(UObject const* Context);
bool IsSimulatedProxy(UGasaObject const* Context);
bool IsSimulatedProxy(AActor const* Context); bool IsSimulatedProxy(AActor const* Context);
void NetLog( UObject const* Context, FString Message, EGasaVerbosity Verbosity = EGasaVerbosity::Log void NetLog( UObject const* Context, FString Message, EGasaVerbosity Verbosity = EGasaVerbosity::Log
@ -56,6 +82,7 @@ namespace Gasa
, const ANSICHAR* Func = __builtin_FUNCTION() ); , const ANSICHAR* Func = __builtin_FUNCTION() );
bool ServerAuthorized(UObject const* Context); bool ServerAuthorized(UObject const* Context);
bool ServerAuthorized(UGasaObject const* Context);
bool ServerAuthorized(AActor const* Context); bool ServerAuthorized(AActor const* Context);
} }
#include "GasaNetLibrary_Inlines.h"

View File

@ -1,35 +1,12 @@
#include "GasaNetLibrary.h" #pragma once
#include "GasaObject.h" #include "GasaNetLibrary.h"
#include "Engine/NetDriver.h" #include "Engine/NetDriver.h"
#include "Game/GasaGameMode.h" #include "Engine/World.h"
#include "Kismet/KismetMathLibrary.h"
#include "Kismet/KismetSystemLibrary.h"
namespace Gasa namespace Gasa
{ {
// TODO(Ed): Profile these... // TODO(Ed): Profile these...
inline
void DrawNetCullingSphere(const UObject* Context, float Duration, float Thickness)
{
const AActor* actor = nullptr;
if (Context->IsA(UGasaObject::StaticClass()))
actor = Cast<AActor>(Context->GetOuter());
else if (Context->IsA(AActor::StaticClass()))
actor = Cast<AActor>(Context);
if (actor)
UKismetSystemLibrary::DrawDebugSphere(actor
, actor->GetActorLocation()
, UKismetMathLibrary::Sqrt(actor->NetCullDistanceSquared) * 2
, 12
, FLinearColor(FColor::Emerald)
, Duration
, Thickness);
}
inline inline
ENetworkMode GetNetworkMode(UObject const* Context) ENetworkMode GetNetworkMode(UObject const* Context)
{ {
@ -110,8 +87,6 @@ namespace Gasa
else if (Context->GetClass()->IsChildOf(UActorComponent::StaticClass())) else if (Context->GetClass()->IsChildOf(UActorComponent::StaticClass()))
Actor = Cast<UActorComponent>(Context)->GetOwner(); Actor = Cast<UActorComponent>(Context)->GetOwner();
// Its assumed that all GasaObjects have an outer actor // Its assumed that all GasaObjects have an outer actor
else if (Context->IsA(UGasaObject::StaticClass()))
Actor = Cast<AActor>(Context->GetOuter());
else else
{ {
UObject const* Outermost = Context->GetOutermostObject(); UObject const* Outermost = Context->GetOutermostObject();
@ -128,22 +103,6 @@ namespace Gasa
return Result; return Result;
} }
inline
bool IsNetOwner(UGasaObject const* Context)
{
if (Context == nullptr || Context->GetWorld() == nullptr)
return false;
AActor const* Actor = Cast<AActor>(Context->GetOuter());
if (Actor == nullptr)
{
Log("Could not get actor reference", ELogV::Warning, LogGasaNet);
return false;
}
bool Result = Actor->HasLocalNetOwner();
return Result;
}
inline inline
bool IsNetOwner(AActor const* Actor) bool IsNetOwner(AActor const* Actor)
{ {
@ -177,8 +136,6 @@ namespace Gasa
else if (Context->GetClass()->IsChildOf(UActorComponent::StaticClass())) else if (Context->GetClass()->IsChildOf(UActorComponent::StaticClass()))
Actor = Cast<UActorComponent>(Context)->GetOwner(); Actor = Cast<UActorComponent>(Context)->GetOwner();
// Its assumed that all GasaObjects have an outer actor // Its assumed that all GasaObjects have an outer actor
else if (Context->IsA(UGasaObject::StaticClass()))
Actor = Cast<AActor>(Context->GetOuter());
else else
{ {
UObject const* Outermost = Context->GetOutermostObject(); UObject const* Outermost = Context->GetOutermostObject();
@ -195,22 +152,6 @@ namespace Gasa
return Result; return Result;
} }
inline
bool IsSimulatedProxy(UGasaObject const* Context)
{
if (Context == nullptr || Context->GetWorld() == nullptr)
return false;
AActor const* Actor = Cast<AActor>(Context->GetOuter());
if (Actor == nullptr)
{
Log("Could not get actor reference", ELogV::Warning, LogGasaNet);
return false;
}
bool Result = Actor->GetLocalRole() == ENetRole::ROLE_SimulatedProxy;
return Result;
}
inline inline
bool IsSimulatedProxy(AActor const* Actor) bool IsSimulatedProxy(AActor const* Actor)
{ {
@ -233,8 +174,6 @@ namespace Gasa
else if (Context->GetClass()->IsChildOf(UActorComponent::StaticClass())) else if (Context->GetClass()->IsChildOf(UActorComponent::StaticClass()))
Actor = Cast<UActorComponent>(Context)->GetOwner(); Actor = Cast<UActorComponent>(Context)->GetOwner();
// Its assumed that all GasaObjects have an outer actor // Its assumed that all GasaObjects have an outer actor
else if (Context->IsA(UGasaObject::StaticClass()))
Actor = Cast<AActor>(Context->GetOuter());
else else
{ {
UObject const* Outermost = Context->GetOutermostObject(); UObject const* Outermost = Context->GetOutermostObject();
@ -251,22 +190,6 @@ namespace Gasa
return Result; return Result;
} }
inline
bool ServerAuthorized(UGasaObject const* Context)
{
if (Context == nullptr || Context->GetWorld() == nullptr)
return false;
AActor const* Actor = Cast<AActor>(Context->GetOuter());
if (Actor == nullptr)
{
Log("Could not get actor reference", ELogV::Warning, LogGasaNet);
return false;
}
bool Result = Actor->HasAuthority();
return Result;
}
inline inline
bool ServerAuthorized(AActor const* Actor) bool ServerAuthorized(AActor const* Actor)
{ {