'NetSlime' Initial port finished and working with 2 players (at least)
This commit is contained in:
		| @@ -1,4 +1,5 @@ | ||||
| #include "EnemyCharacter.h" | ||||
| #include "Networking/GasaNetLibrary_Inlines.h" | ||||
|  | ||||
| AEnemyCharacter::AEnemyCharacter() | ||||
| { | ||||
|   | ||||
| @@ -11,13 +11,12 @@ | ||||
| #include "AbilitySystem/GasaAttributeSet.h" | ||||
| #include "Components/SkeletalMeshComponent.h" | ||||
| #include "Engine/PostProcessVolume.h" | ||||
| #include "Game/GasaGameInstance.h" | ||||
| #include "Game/GasaLevelScriptActor.h" | ||||
| #include "Game/GasaPlayerController.h" | ||||
| #include "Materials/MaterialInstanceDynamic.h" | ||||
|  | ||||
| void AGasaCharacter::SetHighlight(EHighlight Desired) | ||||
| { | ||||
| 	HighlightState = Desired; | ||||
| } | ||||
| #include "Networking/GasaNetLibrary_Inlines.h" | ||||
| using namespace Gasa; | ||||
|  | ||||
| AGasaCharacter::AGasaCharacter() | ||||
| { | ||||
| @@ -51,13 +50,112 @@ AGasaCharacter::AGasaCharacter() | ||||
| 		 | ||||
| 		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 | ||||
| void AGasaCharacter::OnRep_PlayerState() | ||||
| { | ||||
| 	Super::OnRep_PlayerState(); | ||||
| } | ||||
|  | ||||
| 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) | ||||
| 	{ | ||||
| 		// TODO(Ed): Do we need to do this for enemies? | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
| #include "GameFramework/Character.h" | ||||
|  | ||||
| #include "GasaCommon.h" | ||||
| #include "Game/GasaPlayerState.h" | ||||
| #include "Game/GasaGameState.h" | ||||
| #include "Networking/GasaNetLibrary.h" | ||||
|  | ||||
| #include "GasaCharacter.generated.h" | ||||
| @@ -22,6 +22,9 @@ class GASA_API AGasaCharacter : public ACharacter | ||||
| { | ||||
| 	GENERATED_BODY() | ||||
| public: | ||||
| 	 | ||||
| 	AGasaCharacter(); | ||||
|  | ||||
| #pragma region Ability System | ||||
| 	UPROPERTY(EditAnywhere, Category="Ability System") | ||||
| 	bool bAutoAbilitySystem = true; | ||||
| @@ -38,6 +41,20 @@ public: | ||||
| 	TObjectPtr<USkeletalMeshComponent> Weapon; | ||||
| #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 | ||||
| 	static constexpr float HighlightStencilDepth = 256.0; | ||||
| 	 | ||||
| @@ -57,10 +74,6 @@ public: | ||||
| 	FORCEINLINE void Dehighlight() { SetHighlight(EHighlight::Disabled); }; | ||||
| #pragma endregion Highlighting | ||||
|  | ||||
| 	AGasaCharacter(); | ||||
|  | ||||
| 	FORCEINLINE AGasaPlayerState* GetGasaPlayerState() { return GetPlayerState<AGasaPlayerState>(); } | ||||
|  | ||||
| #pragma region NetSlime | ||||
| 	// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp | ||||
| 	FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); } | ||||
| @@ -89,14 +102,14 @@ public: | ||||
| #pragma endregion IAbilitySystem | ||||
|  | ||||
| #pragma region Pawn | ||||
| 	void PossessedBy(AController* NewController) override; | ||||
|  | ||||
| 	void OnRep_PlayerState() override; | ||||
| 	void PossessedBy(AController* NewController) override; | ||||
| 	void SetPlayerDefaults() override; | ||||
| 	void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override; | ||||
| #pragma endregion Pawn | ||||
| 	 | ||||
| #pragma region Actor | ||||
| 	void BeginPlay() override; | ||||
|  | ||||
| 	void Tick(float DeltaSeconds) override; | ||||
| #pragma endregion Actor | ||||
| }; | ||||
| @@ -108,3 +121,4 @@ namespace Gasa | ||||
| 	// 	 | ||||
| 	// } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "PlayerCharacter.h" | ||||
|  | ||||
| #include "Networking/GasaNetLibrary_Inlines.h" | ||||
| #include "AbilitySystemComponent.h" | ||||
| #include "Game/GasaPlayerController.h" | ||||
| #include "UI/GasaHUD.h" | ||||
| @@ -12,46 +13,12 @@ APlayerCharacter::APlayerCharacter() | ||||
| 	bAutoAbilitySystem = false; | ||||
| } | ||||
|  | ||||
| // TODO(Ed): We need to setup Net Slime... | ||||
| void APlayerCharacter::PossessedBy(AController* 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() | ||||
| { | ||||
| 	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); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -7,29 +7,34 @@ using namespace Gasa; | ||||
| #pragma region GameFramework | ||||
| // TODO(Ed): Make a NetLog | ||||
|  | ||||
| UGasaGameInstance::UGasaGameInstance() | ||||
| { | ||||
| 	GameFrameworkState = EGameFrameworkState::Uninitialized; | ||||
| } | ||||
|  | ||||
| void UGasaGameInstance::NotifyGameFrameworkClassReady(EGameFrameworkClassFlag ClassReady) | ||||
| { | ||||
| 	switch (ClassReady) | ||||
| 	{ | ||||
| 		case 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; | ||||
| 		case 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; | ||||
| 		case 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; | ||||
| 		case 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; | ||||
| 		case 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; | ||||
| 	} | ||||
| 	ProcessGameFrameworkState(); | ||||
| @@ -68,7 +73,7 @@ void UGasaGameInstance::ProcessGameFrameworkState() | ||||
| 			if (GameFrameworkClassesState == InitializedFlags) | ||||
| 			{ | ||||
| 				GameFrameworkState = EGameFrameworkState::Initialized; | ||||
| 				NetLog("Gameplay Framework initialized"); | ||||
| 				NetLog("Game Framework initialized"); | ||||
| 				 | ||||
| 				Event_OnGameFrameworkInitialized.Broadcast(); | ||||
| 			} | ||||
| @@ -84,8 +89,5 @@ void UGasaGameInstance::Init() | ||||
| 	Super::Init(); | ||||
|  | ||||
| 	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 | ||||
|   | ||||
| @@ -21,8 +21,8 @@ enum class EGameFrameworkClassFlag : uint8 | ||||
| UENUM(BlueprintType) | ||||
| enum class EGameFrameworkState : uint8 | ||||
| { | ||||
| 	Initialized, | ||||
| 	Uninitialized | ||||
| 	Uninitialized, | ||||
| 	Initialized | ||||
| }; | ||||
|  | ||||
| DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnGameFrameworkInitializedSig); | ||||
| @@ -33,6 +33,8 @@ class GASA_API UGasaGameInstance : public UGameInstance | ||||
| 	GENERATED_BODY() | ||||
| public: | ||||
|  | ||||
| 	UGasaGameInstance(); | ||||
|  | ||||
| 	UPROPERTY(VisibleAnywhere, Category="Dev Cache") | ||||
| 	FGasaDevOptionsCache DevOptionsCache; | ||||
|  | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| #include "GasaGameMode.h" | ||||
|  | ||||
| #include "Online/CoreOnline.h" | ||||
| #include "GasaGameInstance.h" | ||||
| #include "GasaGameState.h" | ||||
| #include "GasaPlayerController.h" | ||||
| #include "GasaPlayerState.h" | ||||
| #include "Engine/Player.h" | ||||
| #include "GameFramework/GameSession.h" | ||||
| #include "GameFramework/GameState.h" | ||||
| @@ -71,6 +71,33 @@ void AGasaGameMode::EndPlay(const EEndPlayReason::Type EndPlayReason) | ||||
| 	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) | ||||
| { | ||||
| 	NetLog("GenericPlayerInitialization: " + C->GetName()); | ||||
| @@ -360,10 +387,10 @@ void AGasaGameMode::PostLogin(APlayerController* NewPlayer) | ||||
| 	{ | ||||
| 		UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>(); | ||||
| 		 | ||||
| 		// int32 numconnections = gi->sessionsettings.bpublicgame | ||||
| 			// ? GI->SessionSettings.PublicConnections : GI->SessionSettings.PrivateConnections; | ||||
|  | ||||
| #if 0 | ||||
| 		int32 numconnections = GI->sessionsettings.bPublicGame | ||||
| 			? GI->SessionSettings.PublicConnections : GI->SessionSettings.PrivateConnections; | ||||
| 		 | ||||
| 		if (GS->OnlinePlayers.Num() < NumConnections) | ||||
| 		{ | ||||
| 			GS->OnlinePlayers.Init( nullptr, NumConnections ); | ||||
| @@ -388,8 +415,8 @@ void AGasaGameMode::PostLogin(APlayerController* NewPlayer) | ||||
| 	} | ||||
|  | ||||
| 	AGasaPlayerController* PC = Cast<AGasaPlayerController>(NewPlayer); | ||||
| 	// if (PC) | ||||
| 	// 	PC->Event_OnNetOwner_GameplayFrameworkInitialized.AddDynamic(this, &ThisClass::OwningClient_OnGameFrameworkInitialized); | ||||
| 	if (PC) | ||||
| 		PC->Event_NetOwner_OnGameFrameworkInitialized.AddDynamic(this, &ThisClass::OwningClient_OnGameFrameworkInitialized); | ||||
| } | ||||
|  | ||||
| void AGasaGameMode::PostSeamlessTravel() | ||||
| @@ -401,11 +428,7 @@ void AGasaGameMode::PostSeamlessTravel() | ||||
| void AGasaGameMode::SetPlayerDefaults(APawn* PlayerPawn) | ||||
| { | ||||
| 	InitializeHUDForPlayer(Cast<APlayerController>(PlayerPawn->GetController())); | ||||
| 	 | ||||
| 	// Super::SetPlayerDefaults(PlayerPawn); | ||||
| 	{ | ||||
| 		PlayerPawn->SetPlayerDefaults(); | ||||
| 	} | ||||
| 	Super::SetPlayerDefaults(PlayerPawn); | ||||
| } | ||||
|  | ||||
| void AGasaGameMode::SetSeamlessTravelViewTarget(APlayerController* PC) | ||||
|   | ||||
| @@ -24,7 +24,7 @@ public: | ||||
| 	UFUNCTION() | ||||
| 	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(); | ||||
| #pragma endregion GameFramework | ||||
| 	 | ||||
| @@ -60,6 +60,8 @@ public: | ||||
| #pragma region GameModeBase | ||||
| 	void EndPlay(const EEndPlayReason::Type EndPlayReason) override; | ||||
|  | ||||
| 	void FinishRestartPlayer(AController* NewPlayer, const FRotator& StartRotation) override; | ||||
|  | ||||
| 	void GenericPlayerInitialization(AController* C) override; | ||||
|  | ||||
| 	TSubclassOf<APlayerController> GetPlayerControllerClassToSpawnForSeamlessTravel(APlayerController* PreviousPlayerController) override; | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| #include "GasaPlayerState.h" | ||||
| #include "GasaGameInstance.h" | ||||
| #include "Net/UnrealNetwork.h" | ||||
| #include "Networking/GasaNetLibrary_Inlines.h" | ||||
| using namespace Gasa; | ||||
|  | ||||
| AGasaGameState::AGasaGameState() | ||||
| @@ -15,7 +16,6 @@ AGasaGameState::AGasaGameState() | ||||
|     PrimaryActorTick.bStartWithTickEnabled = true; | ||||
|  | ||||
| 	// Replication | ||||
| 	 | ||||
| 	bReplicates            = true; | ||||
| 	bNetLoadOnClient       = false; | ||||
| 	NetDormancy            = DORM_Awake; | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| #pragma once | ||||
| #include "GameFramework/GameState.h" | ||||
|  | ||||
| #include "GasaCommon.h" | ||||
| @@ -6,10 +7,6 @@ | ||||
|  | ||||
| #include "GasaGameState.generated.h" | ||||
|  | ||||
| DECLARE_MULTICAST_DELEGATE( FOnTravelDelegate ); | ||||
| DECLARE_DYNAMIC_MULTICAST_DELEGATE( FOnTravelSig ); | ||||
| DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerCharacterReadySig, APlayerCharacter*, Character); | ||||
|  | ||||
| UCLASS( Blueprintable ) | ||||
| class GASA_API AGasaGameState : public AGameState | ||||
| { | ||||
| @@ -29,11 +26,21 @@ public: | ||||
| 	AGasaGameState(); | ||||
|  | ||||
| #pragma region GameFramework | ||||
| 	UPROPERTY(BlueprintAssignable) | ||||
| 	FOnPawnReadySig Event_OnPlayerPawnReady; | ||||
| 	 | ||||
| 	UFUNCTION() | ||||
| 	void OnGameFrameworkInitialized(); | ||||
|  | ||||
| 	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta=(DisplayName = "Game Framework Initialized")) | ||||
| 	void BP_OnGameFrameworkInitialized(); | ||||
|  | ||||
| 	UFUNCTION() | ||||
| 	void NotifyPlayerPawnReady(APawn* Pawn) | ||||
| 	{ | ||||
| 		if (Event_OnPlayerPawnReady.IsBound()) | ||||
| 			Event_OnPlayerPawnReady.Broadcast(Pawn); | ||||
| 	} | ||||
| #pragma endregion GameFramework | ||||
|  | ||||
| #pragma region Networking | ||||
| @@ -41,7 +48,7 @@ public: | ||||
| 	AGasaPlayerState* ListenServerHost; | ||||
|  | ||||
| 	UPROPERTY(ReplicatedUsing = "Client_OnRep_OnlinePlayers", BlueprintReadOnly) | ||||
| 	TArray<AGasaPlayerState> OnlinePlayers; | ||||
| 	TArray<AGasaPlayerState*> OnlinePlayers; | ||||
|  | ||||
| 	UFUNCTION() | ||||
| 	void Client_OnRep_OnlinePlayers(); | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include "Kismet/GameplayStatics.h" | ||||
| #include "Materials/MaterialInstance.h" | ||||
| #include "Materials/MaterialInstanceDynamic.h" | ||||
| #include "Networking/GasaNetLibrary_Inlines.h" | ||||
| using namespace Gasa; | ||||
|  | ||||
| #pragma region Game Framework | ||||
| @@ -54,7 +55,7 @@ void AGasaLevelScriptActor::BeginPlay() | ||||
| 	if(GI) | ||||
| 		GI->Event_OnGameFrameworkInitialized.AddUniqueDynamic(this, & ThisClass::OnGameFrameworkInitialized); | ||||
|  | ||||
| 	if (!bOverrideGameplayFrameworkReady) | ||||
| 	if (!bOverrideGameFrameworkReady) | ||||
| 		GI->NotifyGameFrameworkClassReady(EGameFrameworkClassFlag::Levels); | ||||
| } | ||||
| #pragma endregion Actor | ||||
|   | ||||
| @@ -19,7 +19,7 @@ public: | ||||
|  | ||||
| #pragma region GameFramework | ||||
| 	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) | ||||
| 	bool bOverrideGameplayFrameworkReady = false; | ||||
| 	bool bOverrideGameFrameworkReady = false; | ||||
|  | ||||
| 	UFUNCTION() | ||||
| 	void OnGameFrameworkInitialized(); | ||||
|   | ||||
| @@ -1,18 +1,26 @@ | ||||
| #include "GasaPlayerController.h" | ||||
| #include "GasaPlayerController_Inlines.h" | ||||
| #include "Networking/GasaNetLibrary_Inlines.h" | ||||
|  | ||||
| #include "AbilitySystemComponent.h" | ||||
| #include "Engine/LocalPlayer.h" | ||||
| #include "EnhancedInputComponent.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 "GasaGameInstance.h" | ||||
| #include "GasaGameState.h" | ||||
| #include "GasaPlayerState.h" | ||||
| #include "Actors/CameraMount.h" | ||||
| #include "Camera/CameraComponent.h" | ||||
| #include "Characters/GasaCharacter.h" | ||||
| #include "Components/CapsuleComponent.h" | ||||
| #include "GameFramework/SpringArmComponent.h" | ||||
| #include "Kismet/KismetSystemLibrary.h" | ||||
| #include "UI/GasaHUD.h" | ||||
| #include "UI/WidgetController.h" | ||||
| using namespace Gasa; | ||||
|  | ||||
| AGasaPlayerController::AGasaPlayerController() | ||||
| @@ -24,7 +32,143 @@ AGasaPlayerController::AGasaPlayerController() | ||||
| 	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 | ||||
| void AGasaPlayerController::Move(FInputActionValue const& ActionValue) | ||||
| @@ -72,29 +216,109 @@ void AGasaPlayerController::Move(FInputActionValue const& ActionValue) | ||||
| #pragma endregion Input | ||||
|  | ||||
| #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... | ||||
| void AGasaPlayerController::OnPossess(APawn* InPawn) | ||||
| void AGasaPlayerController::OnPossess(APawn* PawnPossesed) | ||||
| { | ||||
| 	Super::OnPossess(InPawn); | ||||
|  | ||||
| 	Cam->AttachToActor(InPawn, FAttachmentTransformRules::KeepRelativeTransform); | ||||
|  | ||||
| 	AGasaPlayerState* PS      = GetPlayerState(); | ||||
| 	AGasaCharacter* character = Cast<AGasaCharacter>(InPawn); | ||||
| 	// Net Owner setup ability system | ||||
| 	if (0) | ||||
| 	// Super::OnPossess(PawnPossesed); | ||||
| 	{ | ||||
| 		character->AbilitySystem = PS->AbilitySystem; | ||||
| 		character->Attributes    = PS->Attributes; | ||||
| 		character->AbilitySystem->InitAbilityActorInfo(PS, character); | ||||
| 		if (PawnPossesed && (PlayerState == NULL || !PlayerState->IsOnlyASpectator()) ) | ||||
| 		{ | ||||
| 			// ====================================================================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() | ||||
| { | ||||
| 	Super::OnUnPossess(); | ||||
| @@ -138,6 +362,11 @@ void AGasaPlayerController::PlayerTick(float DeltaTime) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void AGasaPlayerController::PostSeamlessTravel() | ||||
| { | ||||
| 	Super::PostSeamlessTravel(); | ||||
| } | ||||
|  | ||||
| void AGasaPlayerController::SetupInputComponent() | ||||
| { | ||||
| 	Super::SetupInputComponent(); | ||||
| @@ -148,12 +377,22 @@ void AGasaPlayerController::SetupInputComponent() | ||||
| 		EIC->BindAction(IA_Move, ETriggerEvent::Triggered, this, &ThisClass::Move);	 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void AGasaPlayerController::SpawnDefaultHUD() | ||||
| { | ||||
| 	Super::SpawnDefaultHUD(); | ||||
| } | ||||
| #pragma endregion PlayerController | ||||
|  | ||||
| #pragma region Actor | ||||
| void AGasaPlayerController::BeginPlay() | ||||
| { | ||||
| 	Super::BeginPlay(); | ||||
| 	NetLog("BeginPlay"); | ||||
|  | ||||
| 	UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>(); | ||||
| 	GI->Event_OnGameFrameworkInitialized.AddUniqueDynamic(this, & AGasaPlayerController::OnGameFrameworkInitialized); | ||||
| 	GI->NotifyGameFrameworkClassReady(EGameFrameworkClassFlag::PlayerController); | ||||
|  | ||||
| 	if (IsLocalController()) | ||||
| 	{ | ||||
| @@ -209,4 +448,11 @@ void AGasaPlayerController::Tick(float DeltaSeconds) | ||||
| 	} | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void AGasaPlayerController::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const | ||||
| { | ||||
| 	Super::GetLifetimeReplicatedProps(OutLifetimeProps); | ||||
|  | ||||
| 	DOREPLIFETIME(AGasaPlayerController, bNetOwner_GameFrameworkInitialized); | ||||
| } | ||||
| #pragma endregion Actor | ||||
|   | ||||
| @@ -1,17 +1,26 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "GasaCommon.h" | ||||
| #include "GasaPlayerState.h" | ||||
| #include "Networking/GasaNetLibrary.h" | ||||
| #include "Engine/Engine.h" | ||||
| #include "GameFramework/PlayerController.h" | ||||
| #include "Networking/GasaNetLibrary.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<ACameraMount> Cam; | ||||
| @@ -33,6 +42,55 @@ public: | ||||
| 	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) | ||||
| @@ -50,10 +108,6 @@ public: | ||||
| 	void Move(FInputActionValue const& ActionValue); | ||||
| #pragma endregion Input | ||||
| 	 | ||||
| 	AGasaPlayerController(); | ||||
|  | ||||
| 	inline AGasaPlayerState* GetPlayerState(); | ||||
|  | ||||
| #pragma region NetSlime | ||||
| 	// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp | ||||
| 	FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); } | ||||
| @@ -76,24 +130,35 @@ public: | ||||
| 	} | ||||
| #pragma endregion NetSlime | ||||
| 	 | ||||
| 	AGasaPlayerController(); | ||||
|  | ||||
| 	inline AGasaPlayerState* GetPlayerState(); | ||||
| 	 | ||||
| #pragma region PlayerController | ||||
| 	void SpawnDefaultHUD() override; | ||||
| 	 | ||||
| 	void OnPossess(APawn* InPawn) override; | ||||
| 	void OnUnPossess() override; | ||||
| 	 | ||||
| 	bool CanRestartPlayer() override; | ||||
| 	void ClientSetHUD_Implementation(TSubclassOf<AHUD> 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<FLifetimeProperty>& OutLifetimeProps) const override; | ||||
| #pragma endregion UObject | ||||
| }; | ||||
|  | ||||
| namespace Gasa | ||||
|   | ||||
| @@ -1,5 +1,8 @@ | ||||
| #include "GasaPlayerState.h" | ||||
|  | ||||
| #include "Networking/GasaNetLibrary_Inlines.h" | ||||
| #include "GasaGameInstance.h" | ||||
| #include "GasaPlayerController.h" | ||||
| #include "AbilitySystem/GasaAbilitySystemComponent.h" | ||||
| #include "AbilitySystem/GasaAttributeSet.h" | ||||
|  | ||||
| @@ -16,3 +19,74 @@ AGasaPlayerState::AGasaPlayerState() | ||||
| 	// Replication | ||||
| 	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 | ||||
|   | ||||
| @@ -15,6 +15,8 @@ class GASA_API AGasaPlayerState : public APlayerState | ||||
| { | ||||
| 	GENERATED_BODY() | ||||
| public: | ||||
| 	AGasaPlayerState(); | ||||
| 	 | ||||
| #pragma region Ability System | ||||
| 	UPROPERTY(EditAnywhere, Category="Ability System") | ||||
| 	bool bAutoAbilitySystem; | ||||
| @@ -25,9 +27,31 @@ public: | ||||
| 	UPROPERTY(EditAnywhere, Category="Ability System") | ||||
| 	TObjectPtr<UAttributeSet> Attributes; | ||||
| #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 | ||||
| 	// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp | ||||
| 	FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); } | ||||
| @@ -55,7 +79,18 @@ public: | ||||
| 	FORCEINLINE UAbilitySystemComponent* GetAbilitySystemComponent() const override { return AbilitySystem; } | ||||
| #pragma endregion IAbilitySystem | ||||
|  | ||||
| // #pragma region | ||||
| // 	 | ||||
| // #pragma endregion  | ||||
| #pragma region PlayerState | ||||
| 	void ClientInitialize(AController* C) override; | ||||
| #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 | ||||
| }; | ||||
|   | ||||
| @@ -48,6 +48,7 @@ public class Gasa : ModuleRules | ||||
|             "Core", | ||||
|              | ||||
|             "AIModule", | ||||
|             "CoreOnline", | ||||
|             "CoreUObject",  | ||||
|             "DeveloperSettings", | ||||
|             "Engine",  | ||||
|   | ||||
| @@ -35,8 +35,8 @@ | ||||
| #include "Game/GasaViewport.h" | ||||
|  | ||||
| // Networking | ||||
| // #include "Networking/GasaNetLibrary.h" | ||||
| // #include "Networking/GasaNetLibrary_Inlines.h" | ||||
| #include "Networking/GasaNetLibrary.h" | ||||
| #include "Networking/GasaNetLibrary_Inlines.h" | ||||
|  | ||||
| // UI | ||||
| // #include "UI/GasaCanvas.h" | ||||
|   | ||||
| @@ -2,6 +2,8 @@ | ||||
|  | ||||
| #include "GasaEngineMinimal.h" | ||||
|  | ||||
| #include "GasaCommon.generated.h" | ||||
|  | ||||
| #define global         | ||||
| #define internal      static | ||||
| #define local_persist static | ||||
| @@ -18,14 +20,19 @@ | ||||
| #pragma region Engine Forwards | ||||
| struct FInputActionValue; | ||||
| struct FOnAttributeChangeData; | ||||
| struct FReplicationFlags; | ||||
|  | ||||
| class AActor; | ||||
| class APawn; | ||||
| class APostProcessVolume; | ||||
|  | ||||
| class FOutBunch; | ||||
|  | ||||
| class IAbilitySystemInterface; | ||||
|  | ||||
| class UAbilitySystemComponent; | ||||
| class UAbilitySystemInterface; | ||||
| class UActorChannel; | ||||
| class UAttributeSet; | ||||
| class UCameraComponent; | ||||
| class UGameplayEffect; | ||||
| @@ -189,3 +196,12 @@ namespace Gasa | ||||
| 	constexpr float _480Hz = .002f; | ||||
| } | ||||
| #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 | ||||
|  | ||||
|   | ||||
| @@ -21,140 +21,5 @@ | ||||
| #include "Misc/VarArgs.h" | ||||
| #include "Logging/LogVerbosity.h" | ||||
| #include "UObject/ObjectMacros.h" | ||||
|  | ||||
| // #include "Misc/OutputDevice.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" | ||||
| #include "Delegates/Delegate.h" | ||||
| #include "Delegates/DelegateCombinations.h" | ||||
|   | ||||
| @@ -1,67 +1,94 @@ | ||||
| #include "GasaNetLibrary.h" | ||||
| #include "GasaNetLibrary_Inlines.h" | ||||
| #include "GasaObject.h" | ||||
|  | ||||
| #include "Kismet/KismetMathLibrary.h" | ||||
| #include "Kismet/KismetSystemLibrary.h" | ||||
|  | ||||
| DEFINE_LOG_CATEGORY(LogGasaNet); | ||||
|  | ||||
| void NetLog( UObject const* Context, FString Message, EGasaVerbosity Verbosity = EGasaVerbosity::Log | ||||
| 		, FLogCategoryBase& Category  = LogGasaNet | ||||
| 		, bool              DumpStack = false | ||||
| 		, int32             Line      = __builtin_LINE() | ||||
| 		, const ANSICHAR*   File      = __builtin_FILE() | ||||
| 		, const ANSICHAR*   Func      = __builtin_FUNCTION() ) | ||||
| namespace Gasa | ||||
| { | ||||
| #if !UE_BUILD_SHIPPING && !NO_LOGGING | ||||
| 	ELogVerbosity::Type EngineVerbosity = (ELogVerbosity::Type) Verbosity; | ||||
| 	if ((EngineVerbosity & ELogVerbosity::VerbosityMask) > ELogVerbosity::COMPILED_IN_MINIMUM_VERBOSITY) | ||||
| 		return; | ||||
| 	if ((EngineVerbosity & ELogVerbosity::VerbosityMask) > Category.GetVerbosity()) | ||||
| 		return; | ||||
| 	if ( Category.IsSuppressed(EngineVerbosity)) | ||||
| 		return; | ||||
|  | ||||
| 	AActor const* Actor = nullptr; | ||||
| 	FString       ActorLevel; | ||||
| 	void DrawNetCullingSphere(const UObject* Context, float Duration, float Thickness) | ||||
| 	{ | ||||
| 		if (Context != nullptr) | ||||
| 		{ | ||||
| 			if (Context->GetClass()->IsChildOf(AActor::StaticClass())) | ||||
| 				Actor = Cast<AActor>(Context); | ||||
| 			else if (Context->GetClass()->IsChildOf(UActorComponent::StaticClass())) | ||||
| 				Actor = Cast<UActorComponent>(Context)->GetOwner(); | ||||
| 			// Its assumed that all GasaObjects have an outer actor | ||||
| 			else if (Context->IsA(UGasaObject::StaticClass())) | ||||
| 				Actor = Cast<AActor>(Context->GetOuter()); | ||||
| 		} | ||||
| 		if (Actor) | ||||
| 		{ | ||||
| 			if (Actor->HasLocalNetOwner()) | ||||
| 				ActorLevel = TEXT("Net Owner"); | ||||
| 			 | ||||
| 			else if (Actor->HasAuthority()) | ||||
| 				ActorLevel = TEXT("Server Authorized"); | ||||
| 				 | ||||
| 			else | ||||
| 				ActorLevel = TEXT("No Authority"); | ||||
| 		} | ||||
| 		else | ||||
| 			ActorLevel = TEXT("Local"); | ||||
| 		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 | ||||
| 		ELogVerbosity::Type EngineVerbosity = (ELogVerbosity::Type) Verbosity; | ||||
| 		if ((EngineVerbosity & ELogVerbosity::VerbosityMask) > ELogVerbosity::COMPILED_IN_MINIMUM_VERBOSITY) | ||||
| 			return; | ||||
| 		if ((EngineVerbosity & ELogVerbosity::VerbosityMask) > Category.GetVerbosity()) | ||||
| 			return; | ||||
| 		if ( Category.IsSuppressed(EngineVerbosity)) | ||||
| 			return; | ||||
|  | ||||
| 	FString NetMode = FString::Printf(TEXT("%-16s"), * GetNetworkModeStr(Context)); | ||||
| 	ActorLevel      = FString::Printf(TEXT("%-18s"), * ActorLevel); | ||||
| 	FString Name    = FString::Printf(TEXT("%-40s"), * Context->GetName()); | ||||
| 	FString FullMsg = NetMode + " " + ActorLevel + " " + Name + " : " + Message; | ||||
| 	 | ||||
| 	static UE::Logging::Private::FStaticBasicLogDynamicData LOG_Dynamic; | ||||
| 	static UE::Logging::Private::FStaticBasicLogRecord | ||||
| 	LOG_Static(TEXT("%s -- %hs %hs(%d)"), File, Line, EngineVerbosity, LOG_Dynamic); | ||||
| 		AActor const* Actor = nullptr; | ||||
| 		FString       ActorLevel; | ||||
| 		{ | ||||
| 			if (Context != nullptr) | ||||
| 			{ | ||||
| 				if (Context->GetClass()->IsChildOf(AActor::StaticClass())) | ||||
| 					Actor = Cast<AActor>(Context); | ||||
| 				else if (Context->GetClass()->IsChildOf(UActorComponent::StaticClass())) | ||||
| 					Actor = Cast<UActorComponent>(Context)->GetOwner(); | ||||
| 				// Its assumed that all GasaObjects have an outer actor | ||||
| 				else if (Context->IsA(UGasaObject::StaticClass())) | ||||
| 					Actor = Cast<AActor>(Context->GetOuter()); | ||||
| 			} | ||||
| 			if (Actor) | ||||
| 			{ | ||||
| 				if (Actor->HasLocalNetOwner()) | ||||
| 					ActorLevel = TEXT("Net Owner"); | ||||
| 			 | ||||
| 				else if (Actor->HasAuthority()) | ||||
| 					ActorLevel = TEXT("Server Authorized"); | ||||
| 				 | ||||
| 				else | ||||
| 					ActorLevel = TEXT("No Authority"); | ||||
| 			} | ||||
| 			else | ||||
| 				ActorLevel = TEXT("Local"); | ||||
| 		} | ||||
|  | ||||
| 	SET_WARN_COLOR(COLOR_PURPLE) | ||||
| 		FString NetMode = FString::Printf(TEXT("%-16s"), * GetNetworkModeStr(Context)); | ||||
| 		ActorLevel      = FString::Printf(TEXT("%-18s"), * ActorLevel); | ||||
| 		FString Name    = FString::Printf(TEXT("%-40s"), * Context->GetName()); | ||||
| 		FString FullMsg = NetMode + " " + ActorLevel + " " + Name + " : " + Message; | ||||
| 	 | ||||
| 	if (DumpStack) | ||||
| 		FDebug::DumpStackTraceToLog(EngineVerbosity); | ||||
| 	BasicLog(Category, &LOG_Static, * FullMsg, File, Func, Line); | ||||
| 		static UE::Logging::Private::FStaticBasicLogDynamicData LOG_Dynamic; | ||||
| 		static UE::Logging::Private::FStaticBasicLogRecord | ||||
| 		LOG_Static(TEXT("%s -- %hs %hs(%d)"), File, Line, EngineVerbosity, LOG_Dynamic); | ||||
|  | ||||
| 		// SET_WARN_COLOR(COLOR_PURPLE) | ||||
| 	 | ||||
| 	CLEAR_WARN_COLOR() | ||||
| #endif | ||||
| } | ||||
| 		if (DumpStack) | ||||
| 			FDebug::DumpStackTraceToLog(EngineVerbosity); | ||||
| 		BasicLog(Category, &LOG_Static, * FullMsg, File, Func, Line); | ||||
| 	 | ||||
| 		// CLEAR_WARN_COLOR() | ||||
| 	#endif | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -8,6 +8,34 @@ | ||||
|  | ||||
| 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) | ||||
| enum class ENetworkMode : uint8 | ||||
| { | ||||
| @@ -39,13 +67,11 @@ namespace Gasa | ||||
| 	bool IsListenServer(UObject const* Context); | ||||
|  | ||||
| 	bool IsNetOwner(UObject const* Context); | ||||
| 	bool IsNetOwner(UGasaObject const* Context); | ||||
| 	bool IsNetOwner(AActor const* Context); | ||||
|  | ||||
| 	bool IsServer(UObject const* Context); | ||||
| 	 | ||||
| 	bool IsSimulatedProxy(UObject const* Context); | ||||
| 	bool IsSimulatedProxy(UGasaObject const* Context); | ||||
| 	bool IsSimulatedProxy(AActor const* Context); | ||||
| 	 | ||||
| 	void NetLog( UObject const* Context, FString Message, EGasaVerbosity Verbosity = EGasaVerbosity::Log | ||||
| @@ -56,6 +82,7 @@ namespace Gasa | ||||
| 		, const ANSICHAR*   Func      = __builtin_FUNCTION() ); | ||||
| 	 | ||||
| 	bool ServerAuthorized(UObject const* Context); | ||||
| 	bool ServerAuthorized(UGasaObject const* Context); | ||||
| 	bool ServerAuthorized(AActor const* Context); | ||||
| } | ||||
|  | ||||
| #include "GasaNetLibrary_Inlines.h" | ||||
|   | ||||
| @@ -1,35 +1,12 @@ | ||||
| #include "GasaNetLibrary.h" | ||||
| #include "GasaObject.h" | ||||
| #pragma once | ||||
| #include "GasaNetLibrary.h" | ||||
| #include "Engine/NetDriver.h" | ||||
| #include "Game/GasaGameMode.h" | ||||
| #include "Kismet/KismetMathLibrary.h" | ||||
| #include "Kismet/KismetSystemLibrary.h" | ||||
| #include "Engine/World.h" | ||||
|  | ||||
| namespace Gasa | ||||
| { | ||||
| 	// 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 | ||||
| 	ENetworkMode GetNetworkMode(UObject const* Context) | ||||
| 	{ | ||||
| @@ -110,8 +87,6 @@ namespace Gasa | ||||
| 		else if (Context->GetClass()->IsChildOf(UActorComponent::StaticClass())) | ||||
| 			Actor = Cast<UActorComponent>(Context)->GetOwner(); | ||||
| 		// Its assumed that all GasaObjects have an outer actor | ||||
| 		else if (Context->IsA(UGasaObject::StaticClass())) | ||||
| 			Actor = Cast<AActor>(Context->GetOuter()); | ||||
| 		else | ||||
| 		{ | ||||
| 			UObject const* Outermost = Context->GetOutermostObject(); | ||||
| @@ -127,23 +102,7 @@ namespace Gasa | ||||
| 		bool Result = Actor->HasLocalNetOwner(); | ||||
| 		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 | ||||
| 	bool IsNetOwner(AActor const* Actor) | ||||
| 	{ | ||||
| @@ -177,8 +136,6 @@ namespace Gasa | ||||
| 		else if (Context->GetClass()->IsChildOf(UActorComponent::StaticClass())) | ||||
| 			Actor = Cast<UActorComponent>(Context)->GetOwner(); | ||||
| 		// Its assumed that all GasaObjects have an outer actor | ||||
| 		else if (Context->IsA(UGasaObject::StaticClass())) | ||||
| 			Actor = Cast<AActor>(Context->GetOuter()); | ||||
| 		else | ||||
| 		{ | ||||
| 			UObject const* Outermost = Context->GetOutermostObject(); | ||||
| @@ -194,22 +151,6 @@ namespace Gasa | ||||
| 		bool Result = Actor->GetLocalRole() == ENetRole::ROLE_SimulatedProxy; | ||||
| 		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 | ||||
| 	bool IsSimulatedProxy(AActor const* Actor) | ||||
| @@ -233,8 +174,6 @@ namespace Gasa | ||||
| 		else if (Context->GetClass()->IsChildOf(UActorComponent::StaticClass())) | ||||
| 			Actor = Cast<UActorComponent>(Context)->GetOwner(); | ||||
| 		// Its assumed that all GasaObjects have an outer actor | ||||
| 		else if (Context->IsA(UGasaObject::StaticClass())) | ||||
| 			Actor = Cast<AActor>(Context->GetOuter()); | ||||
| 		else | ||||
| 		{ | ||||
| 			UObject const* Outermost = Context->GetOutermostObject(); | ||||
| @@ -251,22 +190,6 @@ namespace Gasa | ||||
| 		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 | ||||
| 	bool ServerAuthorized(AActor const* Actor) | ||||
| 	{ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user