WIP: Boostrapping NetSlime
- Just a old name for a set of changes to make the game framework hardened for multiplayer as well as some ease of use functionality.
This commit is contained in:
1 parent
cc1636b687
commit
ad41867dc5
55 files changed
+2122
-123
No files matched your search
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -301,10 +301,6 @@
|
||||
"Name": "VisualStudioSourceCodeAccess",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Name": "GitSourceControl",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Name": "SlateInsights",
|
||||
"Enabled": true
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
|
||||
<bUsePCHFiles>false</bUsePCHFiles>
|
||||
|
||||
</Configuration>
|
||||
@@ -8,34 +8,31 @@
|
||||
|
||||
UGasaAttributeSet::UGasaAttributeSet()
|
||||
{
|
||||
InitHealth( 50.f );
|
||||
InitHealth( 100.f );
|
||||
InitMaxHealth( 100.f );
|
||||
InitMana( 50.f );
|
||||
InitMaxMana( 50.f );
|
||||
}
|
||||
#pragma region Rep Notifies
|
||||
|
||||
#pragma region Rep Notifies
|
||||
void UGasaAttributeSet::Client_OnRep_Health( FGameplayAttributeData& PrevHealth )
|
||||
{
|
||||
// From GAMEPLAYATTRIBUTE_REPNOTIFY
|
||||
static FProperty* UGasaAttributeSetProperty = FindFieldChecked<FProperty>( StaticClass(), GET_MEMBER_NAME_CHECKED( UGasaAttributeSet, Health ) );
|
||||
GetOwningAbilitySystemComponentChecked()->SetBaseAttributeValueFromReplication( FGameplayAttribute( UGasaAttributeSetProperty ), Health, PrevHealth );
|
||||
}
|
||||
|
||||
void UGasaAttributeSet::Client_OnRep_MaxHealth( FGameplayAttributeData& PrevMaxHealth )
|
||||
{
|
||||
// From GAMEPLAYATTRIBUTE_REPNOTIFY
|
||||
static FProperty* UGasaAttributeSetProperty = FindFieldChecked<FProperty>( StaticClass(), GET_MEMBER_NAME_CHECKED( UGasaAttributeSet, MaxHealth ) );
|
||||
GetOwningAbilitySystemComponentChecked()->SetBaseAttributeValueFromReplication( FGameplayAttribute( UGasaAttributeSetProperty ), MaxHealth, PrevMaxHealth );
|
||||
}
|
||||
|
||||
void UGasaAttributeSet::Client_OnRep_Mana( FGameplayAttributeData& PrevMana )
|
||||
{
|
||||
// From GAMEPLAYATTRIBUTE_REPNOTIFY
|
||||
static FProperty* UGasaAttributeSetProperty = FindFieldChecked<FProperty>( StaticClass(), GET_MEMBER_NAME_CHECKED( UGasaAttributeSet, Mana ) );
|
||||
GetOwningAbilitySystemComponentChecked()->SetBaseAttributeValueFromReplication( FGameplayAttribute( UGasaAttributeSetProperty ), Mana, PrevMana );
|
||||
}
|
||||
|
||||
void UGasaAttributeSet::Client_OnRep_MaxMana( FGameplayAttributeData& PrevMaxMana )
|
||||
{
|
||||
// From GAMEPLAYATTRIBUTE_REPNOTIFY
|
||||
@@ -43,6 +40,7 @@ void UGasaAttributeSet::Client_OnRep_MaxMana( FGameplayAttributeData& PrevMaxMan
|
||||
GetOwningAbilitySystemComponentChecked()->SetBaseAttributeValueFromReplication( FGameplayAttribute( UGasaAttributeSetProperty ), MaxMana, PrevMaxMana );
|
||||
}
|
||||
#pragma endregion Rep Notifies
|
||||
|
||||
void UGasaAttributeSet::GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps ) const
|
||||
{
|
||||
Super::GetLifetimeReplicatedProps( OutLifetimeProps );
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
|
||||
UGasaAttributeSet();
|
||||
|
||||
|
||||
UFUNCTION()
|
||||
void Client_OnRep_Health( FGameplayAttributeData& PrevHealth );
|
||||
UFUNCTION()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "GasaAttributeSet.h"
|
||||
#include "AbilitySystemComponent.h"
|
||||
|
||||
#pragma region Attribute Setters
|
||||
FORCEINLINE
|
||||
void UGasaAttributeSet::SetHealth( float NewVal )
|
||||
{
|
||||
@@ -40,6 +41,7 @@ void UGasaAttributeSet::SetMaxMana( float NewVal )
|
||||
AbilityComp->SetNumericAttributeBase( GetMaxManaAttribute(), NewVal );
|
||||
};
|
||||
}
|
||||
#pragma endregion Attribute Setters
|
||||
|
||||
namespace Gasa
|
||||
{
|
||||
|
||||
@@ -10,13 +10,13 @@ AGasaEffectActor::AGasaEffectActor()
|
||||
RootComponent = CreateDefaultSubobject<USceneComponent>("Root");
|
||||
}
|
||||
|
||||
void AGasaEffectActor::ApplyEffectToTarget(AActor* Target, TSubclassOf<UGameplayEffect> EffectClass)
|
||||
void AGasaEffectActor::ApplyEffectToActor(AActor* Actor, TSubclassOf<UGameplayEffect> EffectClass)
|
||||
{
|
||||
UGasaAbilitySystemComp* AS = GetAbilitySystem(Target, true);
|
||||
UGasaAbilitySystemComp* AS = GetAbilitySystem(Actor, true);
|
||||
|
||||
FGameplayEffectContextHandle
|
||||
Context = AS->MakeEffectContext();
|
||||
Context.AddSourceObject(Target);
|
||||
Context.AddSourceObject(Actor);
|
||||
|
||||
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( EffectClass, 1.0f, Context );
|
||||
AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Actors/GasaActor.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
|
||||
#include "GasaEffectActor.generated.h"
|
||||
|
||||
|
||||
UCLASS()
|
||||
class GASA_API AGasaEffectActor : public AActor
|
||||
class GASA_API AGasaEffectActor : public AGasaActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Applied Effects")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
|
||||
TSoftClassPtr<UGameplayEffect> InstantEffectClass;
|
||||
|
||||
AGasaEffectActor();
|
||||
|
||||
void ApplyEffectToTarget(AActor* Target, TSubclassOf<UGameplayEffect> EffectClass );
|
||||
UFUNCTION(BlueprintCallable, Category = "Gameplay Effects")
|
||||
void ApplyEffectToActor(AActor* Actor, TSubclassOf<UGameplayEffect> EffectClass );
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "GasaAttributeSet.h"
|
||||
#include "GasaAttributeSet_Inlines.h"
|
||||
#include "Components/SphereComponent.h"
|
||||
#include "Components/StaticMeshComponent.h"
|
||||
|
||||
|
||||
AGasaEffectActorDemo::AGasaEffectActorDemo()
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Actors/GasaActor.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
|
||||
#include "GasaEffectActorDemo.generated.h"
|
||||
|
||||
// Old demonstration code used before part 37.
|
||||
UCLASS()
|
||||
class GASA_API AGasaEffectActorDemo : public AActor
|
||||
class GASA_API AGasaEffectActorDemo : public AGasaActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "GasaActor.h"
|
||||
#include "GasaCommon.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "CameraMount.generated.h"
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class GASA_API ACameraMount : public AActor
|
||||
class GASA_API ACameraMount : public AGasaActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
Whitespace-only changes.
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include "Networking/GasaNetLibrary.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
|
||||
#include "GasaActor.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class GASA_API AGasaActor : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
#pragma region NetSlime
|
||||
// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
|
||||
FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); }
|
||||
FORCEINLINE bool IsClient() const { return Gasa::IsClient( this ); }
|
||||
FORCEINLINE bool IsListenServer() const { return Gasa::IsListenServer( this ); }
|
||||
FORCEINLINE bool IsNetOwner() const { return Gasa::IsNetOwner( this ); }
|
||||
FORCEINLINE bool IsServer() const { return Gasa::IsServer( this ); }
|
||||
FORCEINLINE bool IsSimulatedProxy() const { return Gasa::IsSimulatedProxy( this ); }
|
||||
FORCEINLINE void NetLog(
|
||||
FString Message,
|
||||
EGasaVerbosity Verbosity = EGasaVerbosity::Log,
|
||||
FLogCategoryBase& Category = LogGasaNet,
|
||||
bool DumpStack = false,
|
||||
int32 Line = __builtin_LINE(),
|
||||
ANSICHAR const* File = __builtin_FILE(),
|
||||
ANSICHAR const* Func = __builtin_FUNCTION()
|
||||
)
|
||||
{
|
||||
Gasa::NetLog( this, Message, Verbosity, Category, DumpStack, Line, File, Func );
|
||||
}
|
||||
#pragma endregion NetSlime
|
||||
};
|
||||
@@ -9,7 +9,10 @@
|
||||
|
||||
#include "AbilitySystem/GasaAbilitySystemComponent.h"
|
||||
#include "AbilitySystem/GasaAttributeSet.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "Engine/PostProcessVolume.h"
|
||||
#include "Game/GasaLevelScriptActor.h"
|
||||
#include "Materials/MaterialInstanceDynamic.h"
|
||||
|
||||
void AGasaCharacter::SetHighlight(EHighlight Desired)
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Game/GasaPlayerState.h"
|
||||
#include "Networking/GasaNetLibrary.h"
|
||||
|
||||
#include "GasaCharacter.generated.h"
|
||||
|
||||
@@ -59,6 +60,28 @@ public:
|
||||
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 ); }
|
||||
FORCEINLINE bool IsClient() const { return Gasa::IsClient( this ); }
|
||||
FORCEINLINE bool IsListenServer() const { return Gasa::IsListenServer( this ); }
|
||||
FORCEINLINE bool IsNetOwner() const { return Gasa::IsNetOwner( this ); }
|
||||
FORCEINLINE bool IsServer() const { return Gasa::IsServer( this ); }
|
||||
FORCEINLINE bool IsSimulatedProxy() const { return Gasa::IsSimulatedProxy( this ); }
|
||||
FORCEINLINE void NetLog(
|
||||
FString Message,
|
||||
EGasaVerbosity Verbosity = EGasaVerbosity::Log,
|
||||
FLogCategoryBase& Category = LogGasaNet,
|
||||
bool DumpStack = false,
|
||||
int32 Line = __builtin_LINE(),
|
||||
ANSICHAR const* File = __builtin_FILE(),
|
||||
ANSICHAR const* Func = __builtin_FUNCTION()
|
||||
)
|
||||
{
|
||||
Gasa::NetLog( this, Message, Verbosity, Category, DumpStack, Line, File, Func );
|
||||
}
|
||||
#pragma endregion NetSlime
|
||||
|
||||
#pragma region IAbilitySystem
|
||||
FORCEINLINE UAttributeSet* GetAttributes() { return Attributes; }
|
||||
|
||||
@@ -25,10 +25,13 @@ void APlayerCharacter::PossessedBy(AController* NewController)
|
||||
AbilitySystem->InitAbilityActorInfo(PS, this);
|
||||
}
|
||||
|
||||
AGasaPlayerController* PC = GetController<AGasaPlayerController>();
|
||||
AGasaHUD* HUD = PC->GetHUD<AGasaHUD>();
|
||||
FWidgetControllerData Data = { PC, PS, AbilitySystem, Attributes };
|
||||
HUD->InitHostWidget(& Data);
|
||||
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...
|
||||
|
||||
@@ -1,5 +1,84 @@
|
||||
#include "GasaGameInstance.h"
|
||||
|
||||
#include "Engine/NetDriver.h"
|
||||
#include "Engine/World.h"
|
||||
using namespace Gasa;
|
||||
|
||||
#pragma region GameFramework
|
||||
// TODO(Ed): Make a NetLog
|
||||
|
||||
void UGasaGameInstance::NotifyGameFrameworkClassReady(EGameFrameworkClassFlag ClassReady)
|
||||
{
|
||||
switch (ClassReady)
|
||||
{
|
||||
case EGameFrameworkClassFlag::GameMode:
|
||||
GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::GameMode;
|
||||
NetLog("Gameplay 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 );
|
||||
break;
|
||||
case EGameFrameworkClassFlag::PlayerController:
|
||||
GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::PlayerController;
|
||||
NetLog("Gameplay 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);
|
||||
break;
|
||||
case EGameFrameworkClassFlag::Levels:
|
||||
GameFrameworkClassesState |= (uint32)EGameFrameworkClassFlag::Levels;
|
||||
NetLog("Gameplay Framework class ready: Levels", ELogV::Log, LogGasaNet);
|
||||
break;
|
||||
}
|
||||
ProcessGameFrameworkState();
|
||||
}
|
||||
|
||||
void UGasaGameInstance::ProcessGameFrameworkState()
|
||||
{
|
||||
switch (GameFrameworkState)
|
||||
{
|
||||
case EGameFrameworkState::Uninitialized:
|
||||
{
|
||||
uint32 InitializedFlags =
|
||||
(uint32)EGameFrameworkClassFlag::GameState |
|
||||
(uint32)EGameFrameworkClassFlag::PlayerController |
|
||||
(uint32)EGameFrameworkClassFlag::PlayerState |
|
||||
(uint32)EGameFrameworkClassFlag::Levels
|
||||
;
|
||||
|
||||
if (GetWorld()->NetDriver == nullptr || GetWorld()->NetDriver->IsServer())
|
||||
{
|
||||
InitializedFlags |= (uint32)EGameFrameworkClassFlag::GameMode;
|
||||
}
|
||||
|
||||
FString MsgGM = "GameMode : " + FString::FromInt( Bitfield_IsSet( GameFrameworkClassesState, scast(uint32, EGameFrameworkClassFlag::GameMode )) );
|
||||
FString MsgGS = "GameState : " + FString::FromInt( Bitfield_IsSet( GameFrameworkClassesState, scast(uint32, EGameFrameworkClassFlag::GameState )) );
|
||||
FString MsgPC = "PlayerController: " + FString::FromInt( Bitfield_IsSet( GameFrameworkClassesState, scast(uint32, EGameFrameworkClassFlag::PlayerController ) ));
|
||||
FString MsgPS = "PlayerState : " + FString::FromInt( Bitfield_IsSet( GameFrameworkClassesState, scast(uint32, EGameFrameworkClassFlag::PlayerState ) ));
|
||||
FString MsgL = "Levels : " + FString::FromInt( Bitfield_IsSet( GameFrameworkClassesState, scast(uint32, EGameFrameworkClassFlag::Levels ) ));
|
||||
|
||||
NetLog(MsgGM, ELogV::Log, LogGasaNet);
|
||||
NetLog(MsgGS, ELogV::Log, LogGasaNet);
|
||||
NetLog(MsgPC, ELogV::Log, LogGasaNet);
|
||||
NetLog(MsgPS, ELogV::Log, LogGasaNet);
|
||||
NetLog(MsgL, ELogV::Log, LogGasaNet);
|
||||
|
||||
if (GameFrameworkClassesState == InitializedFlags)
|
||||
{
|
||||
GameFrameworkState = EGameFrameworkState::Initialized;
|
||||
NetLog("Gameplay Framework initialized");
|
||||
|
||||
Event_OnGameFrameworkInitialized.Broadcast();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma endregion GameFramework
|
||||
|
||||
#pragma region GameInstance
|
||||
void UGasaGameInstance::Init()
|
||||
{
|
||||
Super::Init();
|
||||
@@ -7,5 +86,6 @@ void UGasaGameInstance::Init()
|
||||
DevOptionsCache.CachedDevOptions();
|
||||
|
||||
using namespace Gasa;
|
||||
Log(FString::Printf(TEXT("UObject Size: %d RT: %d"), sizeof(UObject), UObject::StaticClass()->PropertiesSize ));
|
||||
NetLog(FString::Printf(TEXT("UObject Size: %d RT: %d"), sizeof(UObject), UObject::StaticClass()->PropertiesSize ));
|
||||
}
|
||||
#pragma region GameInstance
|
||||
@@ -1,10 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Networking/GasaNetLibrary.h"
|
||||
#include "GasaDevOptionsCache.h"
|
||||
#include "Engine/Engine.h"
|
||||
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "GasaGameInstance.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EGameFrameworkClassFlag : uint8
|
||||
{
|
||||
None = 0 UMETA(Hidden),
|
||||
GameMode = 1 << 0,
|
||||
GameState = 1 << 1,
|
||||
PlayerController = 1 << 2,
|
||||
PlayerState = 1 << 3,
|
||||
Levels = 1 << 4
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EGameFrameworkState : uint8
|
||||
{
|
||||
Initialized,
|
||||
Uninitialized
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnGameFrameworkInitializedSig);
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class GASA_API UGasaGameInstance : public UGameInstance
|
||||
{
|
||||
@@ -14,6 +36,55 @@ public:
|
||||
UPROPERTY(VisibleAnywhere, Category="Dev Cache")
|
||||
FGasaDevOptionsCache DevOptionsCache;
|
||||
|
||||
#pragma region GameFramework
|
||||
UPROPERTY(BlueprintAssignable, Category = "GameFramework")
|
||||
FOnGameFrameworkInitializedSig Event_OnGameFrameworkInitialized;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GameFramework")
|
||||
EGameFrameworkState GameFrameworkState;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GameFramework", meta=(Bitmask, BitmaskEnum = EGameFrameworkClassFlag))
|
||||
int32 GameFrameworkClassesState;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="GameFramework")
|
||||
void ClearGameplayFrameworkState() {
|
||||
Gasa::Log("Clearing game framework state", EGasaVerbosity::Log, LogGasaNet ); // TODO(Ed): Make a default NetLog
|
||||
GameFrameworkClassesState = scast(int32, EGameFrameworkClassFlag::None);
|
||||
GameFrameworkState = EGameFrameworkState::Uninitialized;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GameFramework")
|
||||
FORCEINLINE bool IsGameFrameworkInitialized() { return GameFrameworkState == EGameFrameworkState::Initialized; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="GameFramework")
|
||||
void NotifyGameFrameworkClassReady(EGameFrameworkClassFlag ClassReady);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "GameFramework", meta=(BlueprintProtected))
|
||||
void ProcessGameFrameworkState();
|
||||
#pragma endregion GameFramework
|
||||
|
||||
#pragma region NetSlime
|
||||
// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
|
||||
FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); }
|
||||
FORCEINLINE bool IsClient() const { return Gasa::IsClient( this ); }
|
||||
FORCEINLINE bool IsListenServer() const { return Gasa::IsListenServer( this ); }
|
||||
FORCEINLINE bool IsNetOwner() const { return Gasa::IsNetOwner( this ); }
|
||||
FORCEINLINE bool IsServer() const { return Gasa::IsServer( this ); }
|
||||
FORCEINLINE bool IsSimulatedProxy() const { return Gasa::IsSimulatedProxy( this ); }
|
||||
FORCEINLINE void NetLog(
|
||||
FString Message,
|
||||
EGasaVerbosity Verbosity = EGasaVerbosity::Log,
|
||||
FLogCategoryBase& Category = LogGasaNet,
|
||||
bool DumpStack = false,
|
||||
int32 Line = __builtin_LINE(),
|
||||
ANSICHAR const* File = __builtin_FILE(),
|
||||
ANSICHAR const* Func = __builtin_FUNCTION()
|
||||
)
|
||||
{
|
||||
Gasa::NetLog( this, Message, Verbosity, Category, DumpStack, Line, File, Func );
|
||||
}
|
||||
#pragma endregion NetSlime
|
||||
|
||||
#pragma region GameInstance
|
||||
void Init() override;
|
||||
#pragma endregion GameInstance
|
||||
|
||||
@@ -1,2 +1,454 @@
|
||||
#include "GasaGameMode.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"
|
||||
#include "GameFramework/PlayerState.h"
|
||||
#include "OnlineSubsystem.h"
|
||||
using namespace Gasa;
|
||||
|
||||
#pragma region Game Framework
|
||||
void AGasaGameMode::OnGameFrameworkInitialized()
|
||||
{
|
||||
NetLog("OnGameFrameworkInitialized");
|
||||
|
||||
BP_OnGameFrameworkInitialized();
|
||||
if (MatchState == MatchState::WaitingToStart && ReadyToStartMatch())
|
||||
StartMatch();
|
||||
}
|
||||
|
||||
void AGasaGameMode::OwningClient_OnGameFrameworkInitialized(AGasaPlayerController* PC)
|
||||
{
|
||||
NetLog("OwningClient_OnGameFrameworkInitialized");
|
||||
HandleStartingNewPlayer(PC);
|
||||
}
|
||||
#pragma endregion Game Framework
|
||||
|
||||
#pragma region GameMode
|
||||
void AGasaGameMode::HandleStartingNewPlayer_Implementation(APlayerController* NewPlayer)
|
||||
{
|
||||
Super::HandleStartingNewPlayer_Implementation(NewPlayer);
|
||||
if (NewPlayer)
|
||||
NewPlayer->bBlockInput = false;
|
||||
}
|
||||
|
||||
bool AGasaGameMode::ReadyToStartMatch_Implementation()
|
||||
{
|
||||
if ( ! GetGameInstance<UGasaGameInstance>()->IsGameFrameworkInitialized())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Super::ReadyToStartMatch();
|
||||
{
|
||||
// If bDelayed Start is set, wait for a manual match start
|
||||
if (bDelayedStart)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// By default start when we have > 0 players
|
||||
if (GetMatchState() == MatchState::WaitingToStart)
|
||||
{
|
||||
if (NumPlayers + NumBots > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#pragma endregion GameMode
|
||||
|
||||
#pragma region GameModeBase
|
||||
void AGasaGameMode::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
Super::EndPlay(EndPlayReason);
|
||||
NetLog("EndPlay");
|
||||
}
|
||||
|
||||
void AGasaGameMode::GenericPlayerInitialization(AController* C)
|
||||
{
|
||||
NetLog("GenericPlayerInitialization: " + C->GetName());
|
||||
|
||||
// AGameMode::GenericPlayerInitialization(C);
|
||||
{
|
||||
APlayerController* PC = Cast<APlayerController>(C);
|
||||
if (PC != nullptr)
|
||||
{
|
||||
// Moved to: void AGasaGameMode::SetPlayerDefaults(APawn* PlayerPawn)
|
||||
// InitializeHUDForPlayer(Cast<APlayerController>(C));
|
||||
|
||||
// Notify the game that we can now be muted and mute others
|
||||
UpdateGameplayMuteList(PC);
|
||||
|
||||
if (GameSession != nullptr)
|
||||
{
|
||||
// Tell the player to enable voice by default or use the push to talk method
|
||||
PC->ClientEnableNetworkVoice(!GameSession->RequiresPushToTalk());
|
||||
}
|
||||
|
||||
ReplicateStreamingStatus(PC);
|
||||
|
||||
bool HidePlayer = false, HideHUD = false, DisableMovement = false, DisableTurning = false;
|
||||
|
||||
// Check to see if we should start in cinematic mode (matinee movie capture)
|
||||
if (ShouldStartInCinematicMode(PC, HidePlayer, HideHUD, DisableMovement, DisableTurning))
|
||||
{
|
||||
PC->SetCinematicMode(true, HidePlayer, HideHUD, DisableMovement, DisableTurning);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TSubclassOf<APlayerController> AGasaGameMode::GetPlayerControllerClassToSpawnForSeamlessTravel(APlayerController* PreviousPlayerController)
|
||||
{
|
||||
NetLog("GetPlayerControllerClassToSpawnForSeamlessTravel: " + PreviousPlayerController->GetName());
|
||||
return Super::GetPlayerControllerClassToSpawnForSeamlessTravel(PreviousPlayerController);
|
||||
}
|
||||
|
||||
void AGasaGameMode::HandleSeamlessTravelPlayer(AController*& Controller)
|
||||
{
|
||||
NetLog("HandleSeamlessTravelPlayer: " + Controller->GetName());
|
||||
|
||||
// Super::HandleSeamlessTravelPlayer( C );
|
||||
|
||||
UE_LOG(LogGameMode, Log, TEXT(">> GameMode::HandleSeamlessTravelPlayer: %s "), * Controller->GetName());
|
||||
|
||||
APlayerController* PC = Cast<APlayerController>(Controller);
|
||||
UClass* PCClassToSpawn = GetPlayerControllerClassToSpawnForSeamlessTravel(PC);
|
||||
// FUniqueNetIdRepl StoredNativePlatformUniqueNetId = C->GetPlayerState<AGasaPlayerState>()->NativePlatformUniqueNetId;
|
||||
|
||||
if (PC && PC->GetClass() != PCClassToSpawn)
|
||||
{
|
||||
if (PC->Player != nullptr)
|
||||
{
|
||||
// We need to spawn a new PlayerController to replace the old one
|
||||
APlayerController* const NewPC = SpawnPlayerControllerCommon(PC->IsLocalPlayerController()
|
||||
? ROLE_SimulatedProxy
|
||||
: ROLE_AutonomousProxy, PC->GetFocalLocation(), PC->GetControlRotation(), PCClassToSpawn);
|
||||
if (NewPC == nullptr)
|
||||
{
|
||||
NetLog(FString::Printf(
|
||||
TEXT("Failed to spawn new PlayerController for %s (old class %s)"), *PC->GetHumanReadableName(), *PC->GetClass()->GetName())
|
||||
, ELogV::Warning
|
||||
);
|
||||
PC->Destroy();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
PC->SeamlessTravelTo(NewPC);
|
||||
NewPC->SeamlessTravelFrom(PC);
|
||||
SwapPlayerControllers(PC, NewPC);
|
||||
PC = NewPC;
|
||||
Controller = NewPC;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PC->Destroy();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// clear out data that was only for the previous game
|
||||
Controller->PlayerState->Reset();
|
||||
// create a new PlayerState and copy over info; this is necessary because the old GameMode may have used a different PlayerState class
|
||||
APlayerState* OldPlayerState = Controller->PlayerState;
|
||||
Controller->InitPlayerState();
|
||||
OldPlayerState->SeamlessTravelTo( Controller->PlayerState);
|
||||
// we don"t need the old PlayerState anymore
|
||||
//@fixme: need a way to replace PlayerStates that doesn't cause incorrect "player left the game"/"player entered the game" messages
|
||||
OldPlayerState->Destroy();
|
||||
}
|
||||
|
||||
InitSeamlessTravelPlayer(Controller);
|
||||
|
||||
// Initialize hud and other player details, shared with PostLogin
|
||||
GenericPlayerInitialization(Controller);
|
||||
|
||||
if (AGasaGameState* GS = GetGameState<AGasaGameState>())
|
||||
{
|
||||
#if 0
|
||||
UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>();
|
||||
int32 NumConnections = GI->SessionSettings.bPublicGame
|
||||
? GI->SessionSettings.PublicConnections
|
||||
: GI->SessionSettings.PrivateConnections;
|
||||
if (GS->OnlinePlayers.Num() < NumConnections)
|
||||
GS->OnlinePlayers.Init( nullptr, NumConnections );
|
||||
|
||||
for (AGasaPlayerState* & PS : GS->OnlinePlayers)
|
||||
{
|
||||
if (PS == nullptr)
|
||||
{
|
||||
PS = C->GetPlayerState<ASlipgatePlayerState>();
|
||||
PS->SgID = GS->OnlinePlayers.Find( PS );
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Controller->GetPlayerState<AGasaPlayerState>()->NativePlatformUniqueNetId = StoredNativePlatformUniqueNetId;
|
||||
NetLog(FString::Printf(TEXT("HandleSeamlessTravelPlayer: %s"), * Controller->GetName()) );
|
||||
|
||||
#if 0
|
||||
if (PC)
|
||||
PC->Event_NetOwner_OnGameplayFrameworkInitialized.AddDynamic(this, &ThisClass::OwningClient_OnGameFrameworkInitialized);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AGasaGameMode::InitializeHUDForPlayer_Implementation(APlayerController* NewPlayer)
|
||||
{
|
||||
// Super::InitializeHUDForPlayer_Implementation(NewPlayer);
|
||||
NewPlayer->ClientSetHUD(HUDClass);
|
||||
}
|
||||
|
||||
void AGasaGameMode::InitSeamlessTravelPlayer(AController* NewController)
|
||||
{
|
||||
if (NewController)
|
||||
NewController->bBlockInput = true;
|
||||
|
||||
// GameMode::InitSeamlessTravelPlayer(NewController);
|
||||
{
|
||||
// AGameModeBase::InitSeamlessTravelPlayer(NewController);
|
||||
{
|
||||
APlayerController* NewPC = Cast<APlayerController>(NewController);
|
||||
|
||||
FString ErrorMessage;
|
||||
if (!UpdatePlayerStartSpot(NewController, TEXT(""), ErrorMessage))
|
||||
NetLog(FString::Printf( TEXT("InitSeamlessTravelPlayer: %s"), *ErrorMessage), ELogV::Warning);
|
||||
|
||||
if (NewPC != nullptr)
|
||||
{
|
||||
NewPC->PostSeamlessTravel();
|
||||
|
||||
if (MustSpectate(NewPC))
|
||||
{
|
||||
NewPC->StartSpectatingOnly();
|
||||
}
|
||||
else
|
||||
{
|
||||
NewPC->bPlayerIsWaiting = true;
|
||||
NewPC->ChangeState(NAME_Spectating);
|
||||
NewPC->ClientGotoState(NAME_Spectating);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
APlayerController* NewPC = Cast<APlayerController>(NewController);
|
||||
|
||||
if (NewPC != nullptr)
|
||||
{
|
||||
SetSeamlessTravelViewTarget(NewPC);
|
||||
|
||||
if (!MustSpectate(NewPC))
|
||||
{
|
||||
NumPlayers++;
|
||||
NumTravellingPlayers--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NumBots++;
|
||||
}
|
||||
}
|
||||
NetLog("InitSeamlessTravelPlayer: " + NewController->GetName());
|
||||
}
|
||||
|
||||
void AGasaGameMode::HandleMatchAborted()
|
||||
{
|
||||
Super::HandleMatchAborted();
|
||||
NetLog("HandleMatchAborted");
|
||||
}
|
||||
|
||||
void AGasaGameMode::Logout(AController* Exiting)
|
||||
{
|
||||
Super::Logout(Exiting);
|
||||
|
||||
Event_OnLogout.Broadcast(Cast<AGasaPlayerController>(Exiting));
|
||||
NetLog("User Logged out: " + Exiting->GetName());
|
||||
|
||||
if (AGasaGameState* GS = Cast<AGasaGameState>(GetWorld()->GetGameState()))
|
||||
{
|
||||
#if 0
|
||||
int32 Index = GS->OnlinePlayers.Find(Exiting->GetPlayerState<AGasaGameState>());
|
||||
if (Index == INDEX_NONE)
|
||||
{
|
||||
NetLog("Could not find exiting player state in online players!", ELogV::Error);
|
||||
return;
|
||||
}
|
||||
GS->OnlinePlayers[Index] = nullptr;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
IOnlineSessionPtr const SessionInterface = Online::GetSessionInterface(GetWorld());
|
||||
if ( ! SessionInterface.IsValid())
|
||||
{
|
||||
NetLog("DestoryCurrentSession: Could not get the session interface.", ELogV::Warning);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void AGasaGameMode::PreLogin(const FString& Options, const FString& Address, const FUniqueNetIdRepl& UniqueId, FString& ErrorMessage)
|
||||
{
|
||||
Super::PreLogin(Options, Address, UniqueId, ErrorMessage);
|
||||
// TODO(Ed): Refuse players if the server is full.
|
||||
}
|
||||
|
||||
void AGasaGameMode::PostLogin(APlayerController* NewPlayer)
|
||||
{
|
||||
// AGameMode::PostLogin(NewPlayer);
|
||||
{
|
||||
UWorld* World = GetWorld();
|
||||
|
||||
// Update player count
|
||||
if (MustSpectate(NewPlayer))
|
||||
NumSpectators++;
|
||||
else if (World->IsInSeamlessTravel() || NewPlayer->HasClientLoadedCurrentWorld())
|
||||
NumPlayers++;
|
||||
else
|
||||
NumTravellingPlayers++;
|
||||
|
||||
// Save network address for re-associating with reconnecting player, after stripping out port number
|
||||
FString Address = NewPlayer->GetPlayerNetworkAddress();
|
||||
int32 Pos = Address.Find(TEXT(":"), ESearchCase::CaseSensitive);
|
||||
|
||||
NewPlayer->PlayerState->SavedNetworkAddress = (Pos > 0) ? Address.Left(Pos) : Address;
|
||||
|
||||
// Check if this player is reconnecting and already has PlayerState
|
||||
FindInactivePlayer(NewPlayer);
|
||||
}
|
||||
|
||||
// AGameModeBase::PostLogin(NewPlayer)
|
||||
{
|
||||
// Runs shared initialization that can happen during seamless travel as well
|
||||
GenericPlayerInitialization(NewPlayer);
|
||||
|
||||
// Perform initialization that only happens on initially joining a server
|
||||
NewPlayer->ClientCapBandwidth(NewPlayer->Player->CurrentNetSpeed);
|
||||
|
||||
if (MustSpectate(NewPlayer))
|
||||
{
|
||||
NewPlayer->ClientGotoState(NAME_Spectating);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If NewPlayer is not only a spectator and has a valid ID, add him as a user to the replay.
|
||||
FUniqueNetIdRepl const&
|
||||
NewPlayerStateUniqueId = NewPlayer->PlayerState->GetUniqueId();
|
||||
if (NewPlayerStateUniqueId.IsValid())
|
||||
{
|
||||
GetGameInstance()->AddUserToReplay(NewPlayerStateUniqueId.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
if (GameSession)
|
||||
{
|
||||
GameSession->PostLogin(NewPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
if (AGasaGameState* GS = GetGameState<AGasaGameState>())
|
||||
{
|
||||
UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>();
|
||||
|
||||
// int32 numconnections = gi->sessionsettings.bpublicgame
|
||||
// ? GI->SessionSettings.PublicConnections : GI->SessionSettings.PrivateConnections;
|
||||
|
||||
#if 0
|
||||
if (GS->OnlinePlayers.Num() < NumConnections)
|
||||
{
|
||||
GS->OnlinePlayers.Init( nullptr, NumConnections );
|
||||
}
|
||||
|
||||
for (AGasaPlayerState* & PS : GS->OnlinePlayers)
|
||||
{
|
||||
if (PS == nullptr)
|
||||
{
|
||||
PS = NewPlayer->GetPlayerState<AGasaPlayerState>();
|
||||
PS->GasaID = GS->OnlinePlayers.Find( PS );
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// cont. AGameModeBase::PostLogin(NewPlayer)
|
||||
{
|
||||
// Notify Blueprints that a new player has logged in. Calling it here, because this is the first time that the PlayerController can take RPCs
|
||||
DispatchPostLogin(NewPlayer);
|
||||
}
|
||||
|
||||
AGasaPlayerController* PC = Cast<AGasaPlayerController>(NewPlayer);
|
||||
// if (PC)
|
||||
// PC->Event_OnNetOwner_GameplayFrameworkInitialized.AddDynamic(this, &ThisClass::OwningClient_OnGameFrameworkInitialized);
|
||||
}
|
||||
|
||||
void AGasaGameMode::PostSeamlessTravel()
|
||||
{
|
||||
Super::PostSeamlessTravel();
|
||||
NetLog("PostSeamlessTravel");
|
||||
}
|
||||
|
||||
void AGasaGameMode::SetPlayerDefaults(APawn* PlayerPawn)
|
||||
{
|
||||
InitializeHUDForPlayer(Cast<APlayerController>(PlayerPawn->GetController()));
|
||||
|
||||
// Super::SetPlayerDefaults(PlayerPawn);
|
||||
{
|
||||
PlayerPawn->SetPlayerDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
void AGasaGameMode::SetSeamlessTravelViewTarget(APlayerController* PC)
|
||||
{
|
||||
Super::SetSeamlessTravelViewTarget(PC);
|
||||
NetLog("SetSeamlessTravelViewTarget");
|
||||
}
|
||||
|
||||
void AGasaGameMode::StartPlay()
|
||||
{
|
||||
if (MatchState == MatchState::EnteringMap)
|
||||
SetMatchState(MatchState::WaitingToStart);
|
||||
|
||||
// Start match is deferred until the framework is considered initialized.
|
||||
NetLog("StartPlay");
|
||||
|
||||
UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>();
|
||||
GI->Event_OnGameFrameworkInitialized.AddDynamic(this, &ThisClass::OnGameFrameworkInitialized);
|
||||
GI->NotifyGameFrameworkClassReady(EGameFrameworkClassFlag::GameMode);
|
||||
|
||||
// Not called yet, will wait for initialization of the framework.
|
||||
//Super::StartPlay();
|
||||
}
|
||||
|
||||
void AGasaGameMode::StartToLeaveMap()
|
||||
{
|
||||
NetLog("StartToLeaveMap");
|
||||
Super::StartToLeaveMap();
|
||||
}
|
||||
|
||||
void AGasaGameMode::SwapPlayerControllers(APlayerController* OldPC, APlayerController* NewPC)
|
||||
{
|
||||
NetLog("SwapPlayerControllers");
|
||||
NetLog("Old: " + OldPC->GetName());
|
||||
NetLog("New: " + NewPC->GetName());
|
||||
|
||||
Super::SwapPlayerControllers(OldPC, NewPC);
|
||||
}
|
||||
|
||||
APlayerController* AGasaGameMode::SpawnPlayerControllerCommon(ENetRole InRemoteRole, FVector const& SpawnLocation, FRotator const& SpawnRotation,
|
||||
TSubclassOf<APlayerController> InPlayerControllerClass)
|
||||
{
|
||||
NetLog("SpawnPlayerControllerCommon");
|
||||
return Super::SpawnPlayerControllerCommon(InRemoteRole, SpawnLocation, SpawnRotation, InPlayerControllerClass);
|
||||
}
|
||||
#pragma endregion GameModeBase
|
||||
@@ -1,28 +1,102 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include "GameFramework/GameMode.h"
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Networking/GasaNetLibrary_Inlines.h"
|
||||
#include "Engine/Engine.h"
|
||||
|
||||
#include "GasaGameMode.generated.h"
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLogoutSig, AGasaPlayerController*, PC);
|
||||
|
||||
UCLASS( Blueprintable )
|
||||
class GASA_API AGasaGameMode : public AGameMode
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintAssignable)
|
||||
FOnLogoutSig Event_OnLogout;
|
||||
|
||||
#pragma region GameFramework
|
||||
UFUNCTION()
|
||||
void OnGameFrameworkInitialized();
|
||||
|
||||
UFUNCTION()
|
||||
void OwningClient_OnGameFrameworkInitialized(AGasaPlayerController* PC);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta=(DisplayName = "On Game Framework Initialized"))
|
||||
void BP_OnGameFrameworkInitialized();
|
||||
#pragma endregion GameFramework
|
||||
|
||||
#pragma region NetSlime
|
||||
// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
|
||||
FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); }
|
||||
FORCEINLINE bool IsClient() const { return Gasa::IsClient( this ); }
|
||||
FORCEINLINE bool IsListenServer() const { return Gasa::IsListenServer( this ); }
|
||||
FORCEINLINE bool IsNetOwner() const { return Gasa::IsNetOwner( this ); }
|
||||
FORCEINLINE bool IsServer() const { return Gasa::IsServer( this ); }
|
||||
FORCEINLINE bool IsSimulatedProxy() const { return Gasa::IsSimulatedProxy( this ); }
|
||||
FORCEINLINE void NetLog(
|
||||
FString Message,
|
||||
EGasaVerbosity Verbosity = EGasaVerbosity::Log,
|
||||
FLogCategoryBase& Category = LogGasaNet,
|
||||
bool DumpStack = false,
|
||||
int32 Line = __builtin_LINE(),
|
||||
ANSICHAR const* File = __builtin_FILE(),
|
||||
ANSICHAR const* Func = __builtin_FUNCTION()
|
||||
)
|
||||
{
|
||||
Gasa::NetLog( this, Message, Verbosity, Category, DumpStack, Line, File, Func );
|
||||
}
|
||||
#pragma endregion NetSlime
|
||||
|
||||
#pragma region GameMode
|
||||
void HandleMatchAborted() override;
|
||||
void HandleStartingNewPlayer_Implementation(APlayerController* NewPlayer) override;
|
||||
|
||||
bool ReadyToStartMatch_Implementation() override;
|
||||
#pragma endregion GameMode
|
||||
|
||||
#pragma region GameModeBase
|
||||
void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
|
||||
void GenericPlayerInitialization(AController* C) override;
|
||||
|
||||
TSubclassOf<APlayerController> GetPlayerControllerClassToSpawnForSeamlessTravel(APlayerController* PreviousPlayerController) override;
|
||||
|
||||
void HandleSeamlessTravelPlayer(AController*& C) override;
|
||||
|
||||
void InitializeHUDForPlayer_Implementation(APlayerController* NewPlayer) override;
|
||||
void InitSeamlessTravelPlayer(AController* NewController) override;
|
||||
|
||||
void Logout(AController* Exiting) override;
|
||||
|
||||
void PreLogin(const FString& Options, const FString& Address, const FUniqueNetIdRepl& UniqueId, FString& ErrorMessage) override;
|
||||
void PostLogin(APlayerController* NewPlayer) override;
|
||||
void PostSeamlessTravel() override;
|
||||
|
||||
void SetPlayerDefaults(APawn* PlayerPawn) override;
|
||||
void SetSeamlessTravelViewTarget(APlayerController* PC) override;
|
||||
|
||||
void StartPlay() override;
|
||||
void StartToLeaveMap() override;
|
||||
|
||||
void SwapPlayerControllers(APlayerController* OldPC, APlayerController* NewPC) override;
|
||||
|
||||
APlayerController* SpawnPlayerControllerCommon(ENetRole InRemoteRole, FVector const& SpawnLocation, FRotator const& SpawnRotation, TSubclassOf<APlayerController> InPlayerControllerClass) override;
|
||||
#pragma endregion GameModeBase
|
||||
};
|
||||
|
||||
namespace Gasa
|
||||
{
|
||||
inline
|
||||
AGasaGameMode* GetGameMode(UObject* Context)
|
||||
inline AGasaGameMode* GetGameMode( UObject* Context )
|
||||
{
|
||||
UWorld* World = GEngine->GetWorldFromContextObject(Context, EGetWorldErrorMode::LogAndReturnNull);
|
||||
if (World == nullptr)
|
||||
UWorld* World = GEngine->GetWorldFromContextObject( Context, EGetWorldErrorMode::LogAndReturnNull );
|
||||
if ( World == nullptr )
|
||||
{
|
||||
Log("World is null... are you running in a proper context?", ELogV::Error);
|
||||
Log( "World is null... are you running in a proper context?", ELogV::Error );
|
||||
return nullptr;
|
||||
}
|
||||
return Cast<AGasaGameMode>(World->GetAuthGameMode());
|
||||
return Cast<AGasaGameMode>( World->GetAuthGameMode() );
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
#include "CogAll.h"
|
||||
#include "CogWindowManager.h"
|
||||
#include "GasaPlayerState.h"
|
||||
#include "GasaGameInstance.h"
|
||||
#include "Net/UnrealNetwork.h"
|
||||
using namespace Gasa;
|
||||
|
||||
AGasaGameState::AGasaGameState()
|
||||
{
|
||||
@@ -9,11 +13,92 @@ AGasaGameState::AGasaGameState()
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
PrimaryActorTick.SetTickFunctionEnable(true);
|
||||
PrimaryActorTick.bStartWithTickEnabled = true;
|
||||
|
||||
// Replication
|
||||
|
||||
bReplicates = true;
|
||||
bNetLoadOnClient = false;
|
||||
NetDormancy = DORM_Awake;
|
||||
NetCullDistanceSquared = NetCullDist_Default;
|
||||
NetUpdateFrequency = 10.0f;
|
||||
MinNetUpdateFrequency = 1.0f;
|
||||
NetPriority = 5.0f;
|
||||
}
|
||||
|
||||
#pragma region GameState
|
||||
#pragma region GameFramework
|
||||
void AGasaGameState::OnGameFrameworkInitialized()
|
||||
{
|
||||
NetLog("Received gameplay framework initialization.");
|
||||
|
||||
if (IsServer())
|
||||
{
|
||||
if (PlayerArray.Num() > 0)
|
||||
{
|
||||
ListenServerHost = Cast<AGasaPlayerState>(PlayerArray[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NetLog("Was not able to assign HostingPlayer!", ELogV::Error);
|
||||
}
|
||||
}
|
||||
|
||||
BP_OnGameFrameworkInitialized();
|
||||
}
|
||||
#pragma endregion GameFramework
|
||||
|
||||
#pragma region Networking
|
||||
void AGasaGameState::Client_OnRep_OnlinePlayers()
|
||||
{
|
||||
}
|
||||
#pragma endregion Networking
|
||||
|
||||
#pragma region Seamless Travel
|
||||
void AGasaGameState::Multicast_R_NotifySeamlessTravelEnd_Implementation()
|
||||
{
|
||||
NetLog("Multicast_R_NotifySeamlessTravelEnd_Implementation");
|
||||
BP_Event_OnSeamlessTravelEnd.Broadcast();
|
||||
Event_OnSeamlessTravelEnd.Broadcast();
|
||||
}
|
||||
#pragma endregion Seamless Travel
|
||||
|
||||
#pragma region GameStateBase
|
||||
void AGasaGameState::HandleBeginPlay()
|
||||
{
|
||||
Super::HandleBeginPlay();
|
||||
NetLog("HandleBeginPlay: Directly called from GM");
|
||||
}
|
||||
|
||||
void AGasaGameState::SeamlessTravelTransitionCheckpoint(bool bToTransitionMap)
|
||||
{
|
||||
Super::SeamlessTravelTransitionCheckpoint(bToTransitionMap);
|
||||
|
||||
NetLog("SeamlessTravelTransitionCheckpoint");
|
||||
NetLog(FString("ToTransitionMap: ") + FString(bToTransitionMap ? "true" : "false"));
|
||||
|
||||
if (bToTransitionMap)
|
||||
{
|
||||
Event_OnSeamlessTravelStart.Broadcast();
|
||||
}
|
||||
else
|
||||
{
|
||||
Multicast_R_NotifySeamlessTravelEnd();
|
||||
}
|
||||
}
|
||||
#pragma endregion GameStateBase
|
||||
|
||||
#pragma region Actor
|
||||
void AGasaGameState::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
NetLog("BeginPlay");
|
||||
|
||||
// Notified as initialized here as any possible components should also be initialized by this point.
|
||||
UGasaGameInstance*
|
||||
GI = GetGameInstance<UGasaGameInstance>();
|
||||
GI->Event_OnGameFrameworkInitialized.AddDynamic(this, & ThisClass::OnGameFrameworkInitialized);
|
||||
GI->NotifyGameFrameworkClassReady(EGameFrameworkClassFlag::GameState);
|
||||
|
||||
#if ENABLE_COG
|
||||
CogWindowManager = NewObject<UCogWindowManager>(this);
|
||||
CogWindowManagerRef = CogWindowManager;
|
||||
@@ -23,6 +108,28 @@ void AGasaGameState::BeginPlay()
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
void AGasaGameState::PostInitializeComponents()
|
||||
{
|
||||
NetLog("PostInitializeComponents");
|
||||
|
||||
Super::PostInitializeComponents();
|
||||
|
||||
if ( ! GetWorld()->IsEditorWorld() && IsServer())
|
||||
{
|
||||
OnlinePlayers.Empty();
|
||||
#if 0
|
||||
const auto GI = Cast<UGasaGameInstance>(GetGameInstance());
|
||||
if (GI != nullptr)
|
||||
{
|
||||
int32 NumConnections = GI->SessionSettings.bPublicGame
|
||||
? GI->SessionSettings.PublicConnections
|
||||
: GI->SessionSettings.PrivateConnections;
|
||||
OnlinePlayers.Init(nullptr, NumConnections);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void AGasaGameState::Tick(float DeltaSeconds)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
@@ -31,4 +138,14 @@ void AGasaGameState::Tick(float DeltaSeconds)
|
||||
CogWindowManager->Tick(DeltaSeconds);
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
#pragma endregion GameState
|
||||
#pragma endregion Actor
|
||||
|
||||
#pragma region UObject
|
||||
void AGasaGameState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||
{
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
|
||||
DOREPLIFETIME(AGasaGameState, ListenServerHost);
|
||||
DOREPLIFETIME(AGasaGameState, OnlinePlayers);
|
||||
}
|
||||
#pragma endregion UObject
|
||||
@@ -1,46 +1,116 @@
|
||||
#pragma once
|
||||
|
||||
#include "GameFramework/GameState.h"
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "Networking/GasaNetLibrary.h"
|
||||
|
||||
#include "GasaGameState.generated.h"
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
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
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
#pragma region Cog
|
||||
// To make sure it doesn't get garbage collected.
|
||||
UPROPERTY()
|
||||
TObjectPtr<UObject> CogWindowManagerRef;
|
||||
|
||||
// To make sure it doesn't get garbage collected.
|
||||
UPROPERTY()
|
||||
TObjectPtr<UObject> CogWindowManagerRef;
|
||||
|
||||
#if ENABLE_COG
|
||||
TObjectPtr<UCogWindowManager> CogWindowManager;
|
||||
#endif // ENABLE_COG
|
||||
#endif
|
||||
// ENABLE_COG
|
||||
#pragma endregion Cog
|
||||
|
||||
AGasaGameState();
|
||||
|
||||
#pragma region GameFramework
|
||||
UFUNCTION()
|
||||
void OnGameFrameworkInitialized();
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta=(DisplayName = "Game Framework Initialized"))
|
||||
void BP_OnGameFrameworkInitialized();
|
||||
#pragma endregion GameFramework
|
||||
|
||||
#pragma region Networking
|
||||
UPROPERTY(Replicated, BlueprintReadOnly)
|
||||
AGasaPlayerState* ListenServerHost;
|
||||
|
||||
UPROPERTY(ReplicatedUsing = "Client_OnRep_OnlinePlayers", BlueprintReadOnly)
|
||||
TArray<AGasaPlayerState> OnlinePlayers;
|
||||
|
||||
UFUNCTION()
|
||||
void Client_OnRep_OnlinePlayers();
|
||||
#pragma endregion Networking
|
||||
|
||||
#pragma region Seamless Travel
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnTravelSig Event_OnSeamlessTravelStart;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, meta=(DisplayName="Event: On Seamless Travel End"))
|
||||
FOnTravelSig BP_Event_OnSeamlessTravelEnd;
|
||||
|
||||
FOnTravelDelegate Event_OnSeamlessTravelEnd;
|
||||
|
||||
UFUNCTION(NetMulticast, Reliable)
|
||||
void Multicast_R_NotifySeamlessTravelEnd();
|
||||
#pragma endregion Seamless Travel
|
||||
|
||||
#pragma region NetSlime
|
||||
// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
|
||||
FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); }
|
||||
FORCEINLINE bool IsClient() const { return Gasa::IsClient( this ); }
|
||||
FORCEINLINE bool IsListenServer() const { return Gasa::IsListenServer( this ); }
|
||||
FORCEINLINE bool IsNetOwner() const { return Gasa::IsNetOwner( this ); }
|
||||
FORCEINLINE bool IsServer() const { return Gasa::IsServer( this ); }
|
||||
FORCEINLINE bool IsSimulatedProxy() const { return Gasa::IsSimulatedProxy( this ); }
|
||||
FORCEINLINE void NetLog(
|
||||
FString Message,
|
||||
EGasaVerbosity Verbosity = EGasaVerbosity::Log,
|
||||
FLogCategoryBase& Category = LogGasaNet,
|
||||
bool DumpStack = false,
|
||||
int32 Line = __builtin_LINE(),
|
||||
ANSICHAR const* File = __builtin_FILE(),
|
||||
ANSICHAR const* Func = __builtin_FUNCTION()
|
||||
)
|
||||
{
|
||||
Gasa::NetLog( this, Message, Verbosity, Category, DumpStack, Line, File, Func );
|
||||
}
|
||||
#pragma endregion NetSlime
|
||||
|
||||
#pragma region GameState
|
||||
void BeginPlay() override;
|
||||
void HandleBeginPlay() override;
|
||||
#pragma endregion GameState
|
||||
|
||||
void Tick(float DeltaSeconds) override;
|
||||
#pragma endregion GameState
|
||||
#pragma region GameStateBase
|
||||
void SeamlessTravelTransitionCheckpoint(bool bToTransitionMap) override;
|
||||
#pragma endregion GameStateBase
|
||||
|
||||
#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
|
||||
{
|
||||
inline
|
||||
AGasaGameState* GetGameState(UObject* Context)
|
||||
inline AGasaGameState* GetGameState( UObject* Context )
|
||||
{
|
||||
UWorld* World = GEngine->GetWorldFromContextObject(Context, EGetWorldErrorMode::LogAndReturnNull);
|
||||
if (World == nullptr)
|
||||
UWorld* World = GEngine->GetWorldFromContextObject( Context, EGetWorldErrorMode::LogAndReturnNull );
|
||||
if ( World == nullptr )
|
||||
{
|
||||
Log("World is null... are you running in a proper context?", ELogV::Error);
|
||||
Log( "World is null... are you running in a proper context?", ELogV::Error );
|
||||
return nullptr;
|
||||
}
|
||||
return Cast<AGasaGameState>(World->GetGameState());
|
||||
return Cast<AGasaGameState>( World->GetGameState() );
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,39 @@
|
||||
#include "GasaLevelScriptActor.h"
|
||||
|
||||
#include "GasaDevOptions.h"
|
||||
#include "GasaGameInstance.h"
|
||||
#include "Engine/PostProcessVolume.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Materials/MaterialInstance.h"
|
||||
#include "Materials/MaterialInstanceDynamic.h"
|
||||
using namespace Gasa;
|
||||
|
||||
#pragma region Game Framework
|
||||
AGasaLevelScriptActor::AGasaLevelScriptActor()
|
||||
{
|
||||
// Replication
|
||||
|
||||
bReplicates = true;
|
||||
bNetLoadOnClient = true;
|
||||
NetDormancy = DORM_Awake;
|
||||
NetCullDistanceSquared = NetCullDist_Default;
|
||||
NetUpdateFrequency = 10.0f;
|
||||
MinNetUpdateFrequency = 1.0f;
|
||||
NetPriority = 1.0f;
|
||||
}
|
||||
|
||||
void AGasaLevelScriptActor::OnGameFrameworkInitialized()
|
||||
{
|
||||
NetLog("Received game framework initialization.");
|
||||
BP_OnGameFrameworkInitialized();
|
||||
}
|
||||
#pragma endregion Game Framework
|
||||
|
||||
#pragma region Actor
|
||||
void AGasaLevelScriptActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
NetLog("BeginPlay");
|
||||
|
||||
using namespace Gasa;
|
||||
|
||||
@@ -21,4 +49,12 @@ void AGasaLevelScriptActor::BeginPlay()
|
||||
PPV->Settings.WeightedBlendables.Array[0].Object = MID;
|
||||
break;
|
||||
}
|
||||
|
||||
UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>();
|
||||
if(GI)
|
||||
GI->Event_OnGameFrameworkInitialized.AddUniqueDynamic(this, & ThisClass::OnGameFrameworkInitialized);
|
||||
|
||||
if (!bOverrideGameplayFrameworkReady)
|
||||
GI->NotifyGameFrameworkClassReady(EGameFrameworkClassFlag::Levels);
|
||||
}
|
||||
#pragma endregion Actor
|
||||
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
#include "GasaCommon.h"
|
||||
#include "Engine/Engine.h"
|
||||
|
||||
#include "Engine/LevelScriptActor.h"
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Networking/GasaNetLibrary.h"
|
||||
|
||||
#include "GasaLevelScriptActor.generated.h"
|
||||
|
||||
@@ -14,6 +15,41 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Post Process")
|
||||
TObjectPtr<APostProcessVolume> GlobalPPV;
|
||||
|
||||
AGasaLevelScriptActor();
|
||||
|
||||
#pragma region GameFramework
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
bool bOverrideGameplayFrameworkReady = false;
|
||||
|
||||
UFUNCTION()
|
||||
void OnGameFrameworkInitialized();
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta=(DisplayName="On Game Framework Initialized"))
|
||||
void BP_OnGameFrameworkInitialized();
|
||||
#pragma endregion GameFramework
|
||||
|
||||
#pragma region NetSlime
|
||||
// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
|
||||
FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); }
|
||||
FORCEINLINE bool IsClient() const { return Gasa::IsClient( this ); }
|
||||
FORCEINLINE bool IsListenServer() const { return Gasa::IsListenServer( this ); }
|
||||
FORCEINLINE bool IsNetOwner() const { return Gasa::IsNetOwner( this ); }
|
||||
FORCEINLINE bool IsServer() const { return Gasa::IsServer( this ); }
|
||||
FORCEINLINE bool IsSimulatedProxy() const { return Gasa::IsSimulatedProxy( this ); }
|
||||
FORCEINLINE void NetLog(
|
||||
FString Message,
|
||||
EGasaVerbosity Verbosity = EGasaVerbosity::Log,
|
||||
FLogCategoryBase& Category = LogGasaNet,
|
||||
bool DumpStack = false,
|
||||
int32 Line = __builtin_LINE(),
|
||||
ANSICHAR const* File = __builtin_FILE(),
|
||||
ANSICHAR const* Func = __builtin_FUNCTION()
|
||||
)
|
||||
{
|
||||
Gasa::NetLog( this, Message, Verbosity, Category, DumpStack, Line, File, Func );
|
||||
}
|
||||
#pragma endregion NetSlime
|
||||
|
||||
#pragma region Actor
|
||||
void BeginPlay() override;
|
||||
#pragma region endActor
|
||||
|
||||
@@ -155,19 +155,22 @@ void AGasaPlayerController::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
check(IMC);
|
||||
|
||||
UEnhancedInputLocalPlayerSubsystem*
|
||||
EILP_Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());
|
||||
check(EILP_Subsystem);
|
||||
EILP_Subsystem->AddMappingContext(IMC, 0);
|
||||
if (IsLocalController())
|
||||
{
|
||||
bShowMouseCursor = true;
|
||||
DefaultMouseCursor = EMouseCursor::Default;
|
||||
FInputModeGameAndUI MouseMode;
|
||||
MouseMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
|
||||
MouseMode.SetHideCursorDuringCapture(false);
|
||||
SetInputMode(MouseMode);
|
||||
check(IMC);
|
||||
|
||||
UEnhancedInputLocalPlayerSubsystem*
|
||||
EILP_Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());
|
||||
check(EILP_Subsystem);
|
||||
EILP_Subsystem->AddMappingContext(IMC, 0);
|
||||
{
|
||||
bShowMouseCursor = true;
|
||||
DefaultMouseCursor = EMouseCursor::Default;
|
||||
FInputModeGameAndUI MouseMode;
|
||||
MouseMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
|
||||
MouseMode.SetHideCursorDuringCapture(false);
|
||||
SetInputMode(MouseMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "Networking/GasaNetLibrary.h"
|
||||
|
||||
#include "GasaPlayerController.generated.h"
|
||||
|
||||
@@ -51,12 +53,33 @@ public:
|
||||
AGasaPlayerController();
|
||||
|
||||
inline AGasaPlayerState* GetPlayerState();
|
||||
|
||||
#pragma region NetSlime
|
||||
// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
|
||||
FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); }
|
||||
FORCEINLINE bool IsClient() const { return Gasa::IsClient( this ); }
|
||||
FORCEINLINE bool IsListenServer() const { return Gasa::IsListenServer( this ); }
|
||||
FORCEINLINE bool IsNetOwner() const { return Gasa::IsNetOwner( this ); }
|
||||
FORCEINLINE bool IsServer() const { return Gasa::IsServer( this ); }
|
||||
FORCEINLINE bool IsSimulatedProxy() const { return Gasa::IsSimulatedProxy( this ); }
|
||||
FORCEINLINE void NetLog(
|
||||
FString Message,
|
||||
EGasaVerbosity Verbosity = EGasaVerbosity::Log,
|
||||
FLogCategoryBase& Category = LogGasaNet,
|
||||
bool DumpStack = false,
|
||||
int32 Line = __builtin_LINE(),
|
||||
ANSICHAR const* File = __builtin_FILE(),
|
||||
ANSICHAR const* Func = __builtin_FUNCTION()
|
||||
)
|
||||
{
|
||||
Gasa::NetLog( this, Message, Verbosity, Category, DumpStack, Line, File, Func );
|
||||
}
|
||||
#pragma endregion NetSlime
|
||||
|
||||
#pragma region PlayerController
|
||||
void SpawnDefaultHUD() override;
|
||||
|
||||
void OnPossess(APawn* InPawn) override;
|
||||
|
||||
void OnUnPossess() override;
|
||||
|
||||
void PlayerTick(float DeltaTime) override;
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
AGasaPlayerState::AGasaPlayerState()
|
||||
{
|
||||
bAutoAbilitySystem = true;
|
||||
|
||||
AbilitySystem = CreateDefaultSubobject<UGasaAbilitySystemComp>("Ability System");
|
||||
AbilitySystem->SetIsReplicated(true);
|
||||
AbilitySystem->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "GameFramework/PlayerState.h"
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Networking/GasaNetLibrary.h"
|
||||
|
||||
#include "GasaPlayerState.generated.h"
|
||||
|
||||
@@ -16,7 +17,7 @@ class GASA_API AGasaPlayerState : public APlayerState
|
||||
public:
|
||||
#pragma region Ability System
|
||||
UPROPERTY(EditAnywhere, Category="Ability System")
|
||||
bool bAutoAbilitySystem = true;
|
||||
bool bAutoAbilitySystem;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="Ability System")
|
||||
TObjectPtr<UAbilitySystemComponent> AbilitySystem;
|
||||
@@ -27,6 +28,28 @@ public:
|
||||
|
||||
AGasaPlayerState();
|
||||
|
||||
#pragma region NetSlime
|
||||
// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
|
||||
FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); }
|
||||
FORCEINLINE bool IsClient() const { return Gasa::IsClient( this ); }
|
||||
FORCEINLINE bool IsListenServer() const { return Gasa::IsListenServer( this ); }
|
||||
FORCEINLINE bool IsNetOwner() const { return Gasa::IsNetOwner( this ); }
|
||||
FORCEINLINE bool IsServer() const { return Gasa::IsServer( this ); }
|
||||
FORCEINLINE bool IsSimulatedProxy() const { return Gasa::IsSimulatedProxy( this ); }
|
||||
FORCEINLINE void NetLog(
|
||||
FString Message,
|
||||
EGasaVerbosity Verbosity = EGasaVerbosity::Log,
|
||||
FLogCategoryBase& Category = LogGasaNet,
|
||||
bool DumpStack = false,
|
||||
int32 Line = __builtin_LINE(),
|
||||
ANSICHAR const* File = __builtin_FILE(),
|
||||
ANSICHAR const* Func = __builtin_FUNCTION()
|
||||
)
|
||||
{
|
||||
Gasa::NetLog( this, Message, Verbosity, Category, DumpStack, Line, File, Func );
|
||||
}
|
||||
#pragma endregion NetSlime
|
||||
|
||||
#pragma region IAbilitySystem
|
||||
FORCEINLINE UAttributeSet* GetAttributes() { return Attributes; }
|
||||
FORCEINLINE UAbilitySystemComponent* GetAbilitySystemComponent() const override { return AbilitySystem; }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using UnrealBuildTool;
|
||||
using ModuleRules = UnrealBuildTool.ModuleRules;
|
||||
using ReadOnlyTargetRules = UnrealBuildTool.ReadOnlyTargetRules;
|
||||
using TargetRules = UnrealBuildTool.TargetRules;
|
||||
@@ -10,7 +10,33 @@ public class Gasa : ModuleRules
|
||||
{
|
||||
public Gasa(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
bUseUnity = false;
|
||||
bUseUnity = false;
|
||||
bMergeUnityFiles = false;
|
||||
IWYUSupport = IWYUSupport.None;
|
||||
PCHUsage = PCHUsageMode.NoPCHs;
|
||||
OptimizeCode = CodeOptimization.Never;
|
||||
MinCpuArchX64 = MinimumCpuArchitectureX64.AVX512;
|
||||
IncludeOrderVersion = EngineIncludeOrderVersion.Latest;
|
||||
|
||||
bCodeCoverage = false;
|
||||
bDisableStaticAnalysis = true;
|
||||
bValidateCircularDependencies = true;
|
||||
bValidateFormatStrings = false;
|
||||
bValidateInternalApi = false;
|
||||
bEnableExceptions = false;
|
||||
bEnableBufferSecurityChecks = false;
|
||||
bEnableNonInlinedGenCppWarnings = false;
|
||||
bEnableUndefinedIdentifierWarnings = false;
|
||||
bIgnoreUnresolvedSymbols = false;
|
||||
|
||||
bEnableObjCAutomaticReferenceCounting = false;
|
||||
bEnableObjCExceptions = false;
|
||||
|
||||
var Kilobyte = 1024;
|
||||
NumIncludedBytesPerUnityCPPOverride = Kilobyte * 32;
|
||||
MinFilesUsingPrecompiledHeaderOverride = 1;
|
||||
|
||||
PrivatePCHHeaderFile = "GasaColdHeadersPCH.h";
|
||||
|
||||
#region Engine
|
||||
PrivateIncludePathModuleNames.AddRange(new string[] {
|
||||
@@ -32,6 +58,7 @@ public class Gasa : ModuleRules
|
||||
"InputCore",
|
||||
"NetCore",
|
||||
"Niagara",
|
||||
"OnlineSubsystem",
|
||||
"SlateCore",
|
||||
"UMG",
|
||||
});
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include "GasaEngineMinimal.h"
|
||||
#include "GasaCommon.h"
|
||||
#include "GasaGameplayTags.h"
|
||||
#include "GasaLibrary.h"
|
||||
#include "GasaModule.h"
|
||||
#include "GasaViewportSubsystem.h"
|
||||
#include "GasaDevOptions.h"
|
||||
#include "GasaDevOptionsCache.h"
|
||||
|
||||
// Ability System
|
||||
// #include "AbilitySystem/"
|
||||
#include "AbilitySystem/GasaAbilitySystem.h"
|
||||
// #include "AbilitySystem/GasaAbilitySystemComponent.h"
|
||||
// #include "AbilitySystem/GasaAttributeSet.h"
|
||||
// #include "GasaEffectActor.h"
|
||||
|
||||
// Actors
|
||||
#include "Actors/CameraMount.h"
|
||||
|
||||
// Characters
|
||||
// #include "Characters/GasaCharacter.h"
|
||||
// #include "Characters/EnemyCharacter.h"
|
||||
// #include "Characters/PlayerCharacter.h"
|
||||
|
||||
// Game
|
||||
// #include "Game/GasaGameInstance.h"
|
||||
// #include "Game/GasaGameMode.h"
|
||||
// #include "Game/GasaGameState.h"
|
||||
// #include "Game/GasaLevelScriptActor.h"
|
||||
// #include "Game/GasaPlayerController.h"
|
||||
// #include "Game/GasaPlayerController_Inlines.h"
|
||||
// #include "Game/GasaPlayerState.h"
|
||||
#include "Game/GasaViewport.h"
|
||||
|
||||
// Networking
|
||||
// #include "Networking/GasaNetLibrary.h"
|
||||
// #include "Networking/GasaNetLibrary_Inlines.h"
|
||||
|
||||
// UI
|
||||
// #include "UI/GasaCanvas.h"
|
||||
// #include "UI/GasaCanvasPanel.h"
|
||||
// #include "UI/GasaHUD.h"
|
||||
// #include "UI/GasaHUD_Inlines.h"
|
||||
// #include "UI/GasaImage.h"
|
||||
// #include "UI/GasaOverlay.h"
|
||||
// #include "UI/GasaProgressBar.h"
|
||||
// #include "UI/GasaSizeBox.h"
|
||||
// #include "UI/GasaUserWidget.h"
|
||||
// #include "UI/HostWidgetController.h"
|
||||
// #include "UI/HUDHostWidget.h"
|
||||
// #include "UI/WidgetController.h"
|
||||
@@ -1,13 +1,16 @@
|
||||
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
// #define private protected
|
||||
#include "GasaEngineMinimal.h"
|
||||
|
||||
#define global
|
||||
#define internal static
|
||||
#define local_persist static
|
||||
|
||||
#define ccast( Type, Value ) ( *const_cast<(Type)*>( &( Value ) ) )
|
||||
#define pcast( Type, Value ) ( *reinterpret_cast<(Type)*>( &( Value ) ) )
|
||||
#define rcast( Type, Value ) reinterpret_cast<Type>( Value )
|
||||
#define scast( Type, Value ) static_cast<Type>( Value )
|
||||
|
||||
#pragma region Math
|
||||
#define m_pow2( value ) (value * value)
|
||||
#pragma endregion Math
|
||||
@@ -16,6 +19,9 @@
|
||||
struct FInputActionValue;
|
||||
struct FOnAttributeChangeData;
|
||||
|
||||
class AActor;
|
||||
class APostProcessVolume;
|
||||
|
||||
class IAbilitySystemInterface;
|
||||
|
||||
class UAbilitySystemComponent;
|
||||
@@ -45,11 +51,13 @@ class AGasaGameState;
|
||||
class AGasaLevelScriptActor;
|
||||
class AGasaPlayerController;
|
||||
class AGasaPlayerState;
|
||||
class APlayerCharacter;
|
||||
|
||||
class UGasaAbilitySystemComp;
|
||||
class UGasaAttributeSet;
|
||||
class UGasaDevOptions;
|
||||
class UGasaImage;
|
||||
class UGasaObject;
|
||||
class UGasaOverlay;
|
||||
class UGasaProgressBar;
|
||||
class UGasaSizeBox;
|
||||
@@ -58,6 +66,21 @@ class UHUDHostWidget;
|
||||
class UWidgetController;
|
||||
#pragma endregion Forwards
|
||||
|
||||
#pragma region Bitfields
|
||||
namespace Gasa
|
||||
{
|
||||
inline
|
||||
bool Bitfield_IsSet(int32 Bitfield, int32 Bitmask) {
|
||||
int32 Result = Bitmask == (Bitfield & Bitmask);
|
||||
return scast(bool, Result);
|
||||
}
|
||||
|
||||
inline void Bitfield_Set ( int32& Bitfield, int32 BitsToAdd ) { Bitfield |= BitsToAdd; }
|
||||
inline void Bitfield_Remove( int32& Bitfield, int32 BitsToRemove ) { Bitfield &= (! BitsToRemove); }
|
||||
inline void Bitfield_Toggle( int32& Bitfield, int32 Bitmask ) { Bitfield ^= Bitmask; }
|
||||
}
|
||||
#pragma endregion Bitfields
|
||||
|
||||
#pragma region Logging
|
||||
// Straight from the Engine
|
||||
UENUM(BlueprintType)
|
||||
@@ -107,7 +130,6 @@ namespace Gasa
|
||||
{
|
||||
using ELogV = EGasaVerbosity;
|
||||
|
||||
//◞ ‸ ◟//
|
||||
// Works for Unreal 5.4, Win64 MSVC (untested in other scenarios, for now)
|
||||
inline
|
||||
void Log( FString Message, EGasaVerbosity Verbosity = EGasaVerbosity::Log
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
#pragma once
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Low level includes.
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CoreTypes.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Forward declarations
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CoreFwd.h"
|
||||
#include "UObject/UObjectHierarchyFwd.h"
|
||||
#include "Containers/ContainersFwd.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Commonly used headers
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#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"
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Game/GasaGameState.h"
|
||||
#include "Game/GasaPlayerController.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "Misc/ConfigCacheIni.h"
|
||||
|
||||
#pragma region Game
|
||||
UGasaDevOptions* UGasaLib::GetGasaDevOptions(UObject* Context) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
|
||||
#include "GasaLibrary.Generated.h"
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Modules/ModuleInterface.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class GASA_API FGasaModule : public IModuleInterface
|
||||
{
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "GasaObject.h"
|
||||
|
||||
#include "Engine/ActorChannel.h"
|
||||
#include "Engine/BlueprintGeneratedClass.h"
|
||||
#include "Engine/NetDriver.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
using namespace Gasa;
|
||||
|
||||
UGasaObject::UGasaObject()
|
||||
{
|
||||
bReplicates = false;
|
||||
bDisconnectOnBadReplication = false;
|
||||
}
|
||||
|
||||
void UGasaObject::Destroy()
|
||||
{
|
||||
if ( ! IsValid(this))
|
||||
{
|
||||
checkf(GetOwningActor()->HasAuthority() == true, TEXT("Destroy:: Object does not have authority to destroy itself!"));
|
||||
OnDestroyed();
|
||||
Event_OnDestroyed.Broadcast();
|
||||
ConditionalBeginDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
void UGasaObject::OnDestroyed()
|
||||
{
|
||||
}
|
||||
|
||||
bool UGasaObject::ReplicateAsSubobject(AActor* ActorResponsible, UActorChannel* Channel, FOutBunch* Bunch, FReplicationFlags* RepFlags)
|
||||
{
|
||||
if (!ActorResponsible)
|
||||
{
|
||||
NetLog("Actor reponsible is null", ELogV::Error);
|
||||
return false;
|
||||
}
|
||||
if (!bDisconnectOnBadReplication && ActorResponsible != GetOuter())
|
||||
{
|
||||
NetLog("Attempted to replicate whose outer was not set to the actor whose responsible for replicating it as a subobject", ELogV::Error);
|
||||
return false;
|
||||
}
|
||||
return Channel->ReplicateSubobject(this, *Bunch, *RepFlags);
|
||||
}
|
||||
|
||||
bool UGasaObject::CallRemoteFunction(UFunction* Function, void* Parms, FOutParmRec* OutParms, FFrame* Stack)
|
||||
{
|
||||
check(! HasAnyFlags(RF_ClassDefaultObject));
|
||||
AActor* Owner = GetOwningActor();
|
||||
UNetDriver* NetDriver = Owner->GetNetDriver();
|
||||
if (NetDriver)
|
||||
{
|
||||
NetDriver->ProcessRemoteFunction(Owner, Function, Parms, OutParms, Stack, this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 UGasaObject::GetFunctionCallspace(UFunction* Function, FFrame* Stack)
|
||||
{
|
||||
check(GetOuter() != nullptr);
|
||||
return GetOuter()->GetFunctionCallspace(Function, Stack);
|
||||
}
|
||||
|
||||
void UGasaObject::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||
{
|
||||
// Add any Blueprint properties
|
||||
// This is not required if you do not want the class to be "Blueprintable"
|
||||
if (const UBlueprintGeneratedClass* BP = Cast<UBlueprintGeneratedClass>(GetClass()))
|
||||
{
|
||||
BP->GetLifetimeBlueprintReplicationList(OutLifetimeProps);
|
||||
}
|
||||
}
|
||||
|
||||
bool UGasaObject::IsSupportedForNetworking() const
|
||||
{
|
||||
return bReplicates;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Networking/GasaNetLibrary.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "GasaObject.generated.h"
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGasaObjectEventSig);
|
||||
|
||||
// A UObject which supports replication and other features.
|
||||
UCLASS( Blueprintable )
|
||||
class GASA_API UGasaObject : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UGasaObject();
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
FORCEINLINE AActor* GetOwningActor() const { return GetTypedOuter<AActor>(); };
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="Lifetime")
|
||||
FGasaObjectEventSig Event_OnDestroyed;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="Lifetime")
|
||||
virtual void Destroy();
|
||||
|
||||
virtual void OnDestroyed();
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName = "On Destroyed"))
|
||||
void BP_OnDestroyed();
|
||||
|
||||
#pragma region Replication
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Replication")
|
||||
bool bReplicates;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Replication")
|
||||
bool bDisconnectOnBadReplication ;
|
||||
|
||||
virtual bool ReplicateAsSubobject(AActor* ActorResponsible, UActorChannel* Channel, FOutBunch* Bunch, FReplicationFlags* RepFlags);
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void SetIsReplicated(bool DesiredValue)
|
||||
{
|
||||
bReplicates = DesiredValue;
|
||||
}
|
||||
#pragma endregion Replication
|
||||
|
||||
#pragma region NetSlime
|
||||
// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
|
||||
FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); }
|
||||
FORCEINLINE bool IsClient() const { return Gasa::IsClient( this ); }
|
||||
FORCEINLINE bool IsListenServer() const { return Gasa::IsListenServer( this ); }
|
||||
FORCEINLINE bool IsNetOwner() const { return Gasa::IsNetOwner( this ); }
|
||||
FORCEINLINE bool IsServer() const { return Gasa::IsServer( this ); }
|
||||
FORCEINLINE bool IsSimulatedProxy() const { return Gasa::IsSimulatedProxy( this ); }
|
||||
FORCEINLINE void NetLog(
|
||||
FString Message,
|
||||
EGasaVerbosity Verbosity = EGasaVerbosity::Log,
|
||||
FLogCategoryBase& Category = LogGasaNet,
|
||||
bool DumpStack = false,
|
||||
int32 Line = __builtin_LINE(),
|
||||
ANSICHAR const* File = __builtin_FILE(),
|
||||
ANSICHAR const* Func = __builtin_FUNCTION()
|
||||
)
|
||||
{
|
||||
Gasa::NetLog( this, Message, Verbosity, Category, DumpStack, Line, File, Func );
|
||||
}
|
||||
#pragma endregion NetSlime
|
||||
|
||||
#pragma region UObject
|
||||
bool CallRemoteFunction(UFunction* Function, void* Parms, FOutParmRec* OutParms, FFrame* Stack) override;
|
||||
|
||||
int32 GetFunctionCallspace(UFunction* Function, FFrame* Stack) override;
|
||||
|
||||
void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
|
||||
bool IsSupportedForNetworking() const override;
|
||||
#pragma endregion UObject
|
||||
};
|
||||
@@ -1,2 +1,67 @@
|
||||
#include "GasaNetLibrary.h"
|
||||
#include "GasaNetLibrary_Inlines.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() )
|
||||
{
|
||||
#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;
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
SET_WARN_COLOR(COLOR_PURPLE)
|
||||
|
||||
if (DumpStack)
|
||||
FDebug::DumpStackTraceToLog(EngineVerbosity);
|
||||
BasicLog(Category, &LOG_Static, * FullMsg, File, Func, Line);
|
||||
|
||||
CLEAR_WARN_COLOR()
|
||||
#endif
|
||||
}
|
||||
@@ -1,4 +1,22 @@
|
||||
#pragma once
|
||||
// NetSlime: Ol'Reliable
|
||||
#pragma once
|
||||
|
||||
#include "GasaCommon.h"
|
||||
|
||||
#define DOREPLIFETIME_DEFAULT_GAS(Class, ReplicatedVar) \
|
||||
DOREPLIFETIME_CONDITION_NOTIFY(Class, ReplicatedVar, COND_None, REPNOTIFY_Always)
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogGasaNet, Log, All);
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class ENetworkMode : uint8
|
||||
{
|
||||
Standalone,
|
||||
DedicatedServer,
|
||||
ListenServer,
|
||||
Client,
|
||||
MAX,
|
||||
};
|
||||
|
||||
namespace Gasa
|
||||
{
|
||||
@@ -12,6 +30,32 @@ namespace Gasa
|
||||
constexpr float NetCullDist_VeryFar = 10000.0f * 10000.0f;
|
||||
constexpr float NetCullDist_VisualMax = 15000.0f * 15000.0f;
|
||||
|
||||
#define DOREPLIFETIME_DEFAULT_GAS(Class, ReplicatedVar) \
|
||||
DOREPLIFETIME_CONDITION_NOTIFY(Class, ReplicatedVar, COND_None, REPNOTIFY_Always)
|
||||
void DrawNetCullingSphere(UObject const* Context, float Duration, float Thickness);
|
||||
|
||||
ENetworkMode GetNetworkMode(UObject const* Context);
|
||||
FString GetNetworkModeStr(UObject const* Context);
|
||||
|
||||
bool IsClient(UObject const* Context);
|
||||
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
|
||||
, FLogCategoryBase& Category = LogGasaNet
|
||||
, bool DumpStack = false
|
||||
, int32 Line = __builtin_LINE()
|
||||
, const ANSICHAR* File = __builtin_FILE()
|
||||
, const ANSICHAR* Func = __builtin_FUNCTION() );
|
||||
|
||||
bool ServerAuthorized(UObject const* Context);
|
||||
bool ServerAuthorized(UGasaObject const* Context);
|
||||
bool ServerAuthorized(AActor const* Context);
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
#include "GasaNetLibrary.h"
|
||||
#include "GasaObject.h"
|
||||
#include "Engine/NetDriver.h"
|
||||
#include "Game/GasaGameMode.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
#include "Kismet/KismetSystemLibrary.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)
|
||||
{
|
||||
if (Context == nullptr)
|
||||
{
|
||||
Log("Context is null...", ELogV::Error);
|
||||
return scast(ENetworkMode, ENetMode::NM_MAX);
|
||||
}
|
||||
UWorld* World = Context->GetWorld();
|
||||
if (World == nullptr) {
|
||||
Log("World is null... are you running in a proper context?", ELogV::Error);
|
||||
return scast(ENetworkMode, ENetMode::NM_MAX);
|
||||
}
|
||||
|
||||
if (IsValid(World) == false)
|
||||
return ENetworkMode::Standalone;
|
||||
|
||||
ENetworkMode NetMode = scast(ENetworkMode, World->GetNetMode());
|
||||
return NetMode;
|
||||
}
|
||||
|
||||
inline
|
||||
FString GetNetworkModeStr(UObject const* Context)
|
||||
{
|
||||
FString Str;
|
||||
if (Context == nullptr)
|
||||
return Str;
|
||||
switch (GetNetworkMode(Context))
|
||||
{
|
||||
case ENetworkMode::Standalone:
|
||||
Str = TEXT("Standalone");
|
||||
break;
|
||||
case ENetworkMode::ListenServer:
|
||||
Str = TEXT("ListenServer");
|
||||
break;
|
||||
case ENetworkMode::DedicatedServer:
|
||||
Str = TEXT("DedicatedServer");
|
||||
break;
|
||||
case ENetworkMode::Client:
|
||||
Str = TEXT("Client");
|
||||
break;
|
||||
}
|
||||
return Str;
|
||||
}
|
||||
|
||||
inline
|
||||
bool IsClient(UObject const* Context)
|
||||
{
|
||||
if (Context == nullptr || Context->GetWorld() == nullptr)
|
||||
return false;
|
||||
|
||||
UNetDriver* NetDriver = Context->GetWorld()->NetDriver;
|
||||
bool Result = NetDriver && ! NetDriver->IsServer();
|
||||
return Result;
|
||||
}
|
||||
|
||||
inline
|
||||
bool IsListenServer(UObject const* Context)
|
||||
{
|
||||
if (Context == nullptr || Context->GetWorld() == nullptr)
|
||||
return false;
|
||||
|
||||
UNetDriver* NetDriver = Context->GetWorld()->NetDriver;
|
||||
bool Result = NetDriver && NetDriver->GetNetMode() == ENetMode::NM_ListenServer;
|
||||
return Result;
|
||||
}
|
||||
|
||||
inline
|
||||
bool IsNetOwner(UObject const* Context)
|
||||
{
|
||||
if (Context == nullptr || Context->GetWorld() == nullptr)
|
||||
return false;
|
||||
|
||||
AActor const* Actor = nullptr;
|
||||
|
||||
if (Context->IsA(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());
|
||||
else
|
||||
{
|
||||
UObject const* Outermost = Context->GetOutermostObject();
|
||||
if (Outermost->IsA(AActor::StaticClass()))
|
||||
Actor = Cast<AActor>(Outermost);
|
||||
}
|
||||
|
||||
if (Actor == nullptr)
|
||||
{
|
||||
Log("Could not get actor reference", ELogV::Warning, LogGasaNet);
|
||||
return false;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (Actor == nullptr || Actor->GetWorld() == nullptr)
|
||||
return false;
|
||||
bool Result = Actor->HasLocalNetOwner();
|
||||
return Result;
|
||||
}
|
||||
|
||||
inline
|
||||
bool IsServer(UObject const* Context)
|
||||
{
|
||||
if (Context == nullptr || Context->GetWorld() == nullptr)
|
||||
return false;
|
||||
|
||||
UNetDriver* NetDriver = Context->GetWorld()->NetDriver;
|
||||
bool Result = NetDriver && NetDriver->IsServer();
|
||||
return Result;
|
||||
}
|
||||
|
||||
inline
|
||||
bool IsSimulatedProxy(UObject const* Context)
|
||||
{
|
||||
if (Context == nullptr || Context->GetWorld() == nullptr)
|
||||
return false;
|
||||
|
||||
AActor const* Actor = nullptr;
|
||||
|
||||
if (Context->IsA(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());
|
||||
else
|
||||
{
|
||||
UObject const* Outermost = Context->GetOutermostObject();
|
||||
if (Outermost->IsA(AActor::StaticClass()))
|
||||
Actor = Cast<AActor>(Outermost);
|
||||
}
|
||||
|
||||
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(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)
|
||||
{
|
||||
if (Actor == nullptr || Actor->GetWorld() == nullptr)
|
||||
return false;
|
||||
bool Result = Actor->GetLocalRole() == ENetRole::ROLE_SimulatedProxy;
|
||||
return Result;
|
||||
}
|
||||
|
||||
inline
|
||||
bool ServerAuthorized(UObject const* Context)
|
||||
{
|
||||
if (Context == nullptr || Context->GetWorld() == nullptr)
|
||||
return false;
|
||||
|
||||
AActor const* Actor = nullptr;
|
||||
|
||||
if (Context->IsA(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());
|
||||
else
|
||||
{
|
||||
UObject const* Outermost = Context->GetOutermostObject();
|
||||
if (Outermost->IsA(AActor::StaticClass()))
|
||||
Actor = Cast<AActor>(Outermost);
|
||||
}
|
||||
|
||||
if (Actor == nullptr)
|
||||
{
|
||||
Log("Could not get actor reference", ELogV::Warning, LogGasaNet);
|
||||
return false;
|
||||
}
|
||||
bool Result = Actor->HasAuthority();
|
||||
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)
|
||||
{
|
||||
if (Actor == nullptr || Actor->GetWorld() == nullptr)
|
||||
return false;
|
||||
bool Result = Actor->HasAuthority();
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,10 @@ using namespace Gasa;
|
||||
|
||||
void AGasaHUD::InitHostWidget(FWidgetControllerData const* WidgetControllerData)
|
||||
{
|
||||
HostWidget = CreateWidget<UHUDHostWidget>( GetWorld()
|
||||
HostWidget = CreateWidget<UHUDHostWidget>( GetWorld()
|
||||
, GetDevOptions()->Template_HUD_HostUI.LoadSynchronous() );
|
||||
|
||||
HostWidgetController = NewObject<UHostWidgetController>(this, GetDevOptions()->Template_HostWidgetController.Get());
|
||||
HostWidgetController = NewObject<UHostWidgetController>(this, GetDevOptions()->Template_HostWidgetController.Get());
|
||||
HostWidgetController->Data = (* WidgetControllerData);
|
||||
HostWidget->SetWidgetController(HostWidgetController);
|
||||
HostWidgetController->BindCallbacksToDependencies();
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#include "AbilitySystem/GasaAttributeSet.h"
|
||||
#include "GameplayEffectTypes.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma region Attribute Changed Callbacks
|
||||
// Attribute Changed Callbacks are generated by GasaGen/GasaGen_HostWidgetController.cpp
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime;
|
||||
using UnrealBuildTool;
|
||||
using BuildSettingsVersion = UnrealBuildTool.BuildSettingsVersion;
|
||||
using TargetInfo = UnrealBuildTool.TargetInfo;
|
||||
using TargetRules = UnrealBuildTool.TargetRules;
|
||||
@@ -17,6 +18,7 @@ public class GasaEditorTarget : TargetRules
|
||||
|
||||
bUseUnityBuild = true;
|
||||
// bUseXGEController = false;
|
||||
LinkType = TargetLinkType.Modular;
|
||||
|
||||
ExtraModuleNames.Add("Gasa");
|
||||
ExtraModuleNames.Add("GasaEditor");
|
||||
|
||||
@@ -18,6 +18,7 @@ using namespace gen;
|
||||
#include "GasaGen_ChangeBPActionMenu.cpp"
|
||||
#include "GasaGen_DevOptionsCache.cpp"
|
||||
#include "GasaGen_HostWidgetController.cpp"
|
||||
#include "GasaGen_NetSlime.cpp"
|
||||
|
||||
int gen_main()
|
||||
{
|
||||
@@ -80,6 +81,7 @@ int gen_main()
|
||||
gen_UGasaAttributeSet();
|
||||
gen_FGasaDevOptionsCache();
|
||||
gen_UHostWidgetController();
|
||||
// gen_netslime_interfaces();
|
||||
|
||||
// One offs
|
||||
if (0)
|
||||
|
||||
@@ -13,6 +13,9 @@ using namespace gen;
|
||||
#define path_config path_source "Config/"
|
||||
#define path_module_gasa path_source "Gasa/"
|
||||
#define path_gasa_ability_system path_module_gasa "AbilitySystem/"
|
||||
#define path_gasa_actors path_module_gasa "Actors/"
|
||||
#define path_gasa_characters path_module_gasa "Characters/"
|
||||
#define path_gasa_game path_module_gasa "Game/"
|
||||
#define path_gasa_ui path_module_gasa "UI/"
|
||||
|
||||
constexpr StrC str_DECLARE_CLASS = txt("DECLARE_CLASS(");
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
// Used in the GasaGen.cpp translation unit
|
||||
#if GASA_INTELLISENSE_DIRECTIVES
|
||||
#pragma once
|
||||
#define GEN_EXPOSE_BACKEND
|
||||
#include "gen.hpp"
|
||||
#include "gen.builder.hpp"
|
||||
#include "GasaGenCommon.cpp"
|
||||
#endif
|
||||
|
||||
void gen_netslime_interface(CodeClass aclass)
|
||||
{
|
||||
CodeBody net_slime_class_interface = def_body(ECode::Class_Body);
|
||||
{
|
||||
#pragma push_macro("FORCEINLINE")
|
||||
#undef FORCEINLINE
|
||||
CodeFn DrawNetCullingSphere = parse_function( code(
|
||||
FORCEINLINE void DrawNetCullingSphere(float Duration, float Thickness) const final { Gasa::DrawNetCullingSphere(this, Duration, Thickness); }
|
||||
));
|
||||
CodeFn GetNetworkMode = parse_function( code( FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode(this); } ));
|
||||
CodeFn IsClient = parse_function( code( FORCEINLINE bool IsClient() const { return Gasa::IsClient(this); } ));
|
||||
CodeFn IsListenServer = parse_function( code( FORCEINLINE bool IsListenServer() const { return Gasa::IsListenServer(this); } ));
|
||||
CodeFn IsNetOwner = parse_function( code( FORCEINLINE bool IsNetOwner() const { return Gasa::IsNetOwner(this); } ));
|
||||
CodeFn IsServer = parse_function( code( FORCEINLINE bool IsServer() const { return Gasa::IsServer(this); } ));
|
||||
CodeFn IsSimulatedProxy = parse_function( code( FORCEINLINE bool IsSimulatedProxy() const { return Gasa::IsSimulatedProxy(this); } ));
|
||||
CodeFn NetLog = parse_function( code(
|
||||
FORCEINLINE void NetLog( 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() )
|
||||
{
|
||||
Gasa::NetLog(this, Message, Verbosity, Category, DumpStack, Line, File, Func );
|
||||
}
|
||||
));
|
||||
CodeFn ServerAuthorized = parse_function( code( FORCEINLINE bool ServerAuthorized() const { return Gasa::ServerAuthorized(this); } ));
|
||||
#pragma pop_macro("FORCEINLINE")
|
||||
net_slime_class_interface.append(GetNetworkMode);
|
||||
net_slime_class_interface.append(IsClient);
|
||||
net_slime_class_interface.append(IsListenServer);
|
||||
net_slime_class_interface.append(IsNetOwner);
|
||||
net_slime_class_interface.append(IsServer);
|
||||
net_slime_class_interface.append(IsSimulatedProxy);
|
||||
net_slime_class_interface.append(NetLog);
|
||||
}
|
||||
|
||||
CodeBody new_body = def_body(ECode::Class_Body);
|
||||
for(Code code = aclass->Body.begin(); code != aclass->Body.end(); ++ code )
|
||||
{
|
||||
switch (code->Type)
|
||||
{
|
||||
default:
|
||||
new_body.append(code);
|
||||
break;
|
||||
|
||||
// TODO(Ed): Could this be turned into a singly? void find_and_swap_region_pragma(CodeClass, StrC region)
|
||||
// IT could return void if its assumed that the Code passed will have destructive edits to the body.
|
||||
case ECode::Preprocess_Pragma:
|
||||
{
|
||||
local_persist bool found = false;
|
||||
if (found || ! code->Content.starts_with( txt("region NetSlime")))
|
||||
{
|
||||
new_body.append(code);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add pragma
|
||||
new_body.append(code);
|
||||
++ code;
|
||||
|
||||
new_body.append( def_comment( txt("NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp")));
|
||||
new_body.append(net_slime_class_interface);
|
||||
|
||||
while (code->Type != ECode::Preprocess_Pragma
|
||||
|| ! code->Content.starts_with(txt("endregion NetSlime")))
|
||||
++ code;
|
||||
|
||||
new_body.append(code);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
aclass->Body = new_body;
|
||||
}
|
||||
|
||||
void gen_netslime_interfaces()
|
||||
{
|
||||
Array<StringCached> header_paths = Array<StringCached>::init_reserve(GlobalAllocator, 32);
|
||||
// header_paths.append(get_cached_string(txt( path_module_gasa "GasaObject.h")));
|
||||
// header_paths.append(get_cached_string(txt( path_gasa_actors "GasaActor.h")));
|
||||
// header_paths.append(get_cached_string(txt( path_gasa_characters "GasaCharacter.h")));
|
||||
// header_paths.append(get_cached_string(txt( path_gasa_game "GasaGameMode.h")));
|
||||
// header_paths.append(get_cached_string(txt( path_gasa_game "GasaGameState.h")));
|
||||
|
||||
for (StringCached path : header_paths)
|
||||
{
|
||||
CodeBody original_header = parse_file(path);
|
||||
CodeBody header_body = def_body(ECode::Global_Body);
|
||||
for (Code code : original_header)
|
||||
{
|
||||
switch (code->Type) {
|
||||
case ECode::Class:
|
||||
{
|
||||
CodeClass aclass = code.cast<CodeClass>();
|
||||
gen_netslime_interface(aclass);
|
||||
header_body.append(aclass);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
header_body.append(code);
|
||||
}
|
||||
}
|
||||
Builder header = Builder::open(path);
|
||||
header.print(header_body);
|
||||
header.write();
|
||||
format_file(path);
|
||||
}
|
||||
}
|
||||
@@ -272,6 +272,7 @@ void def_attribute_field_value_setters( CodeBody body, Array<StringCached> prope
|
||||
|
||||
void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name, Array<StringCached> properties )
|
||||
{
|
||||
body.append(def_pragma( txt("region Attribute Setters")));
|
||||
for ( String property : properties )
|
||||
{
|
||||
CodeFn generated_get_attribute = parse_function(
|
||||
@@ -288,6 +289,7 @@ void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name
|
||||
)));
|
||||
body.append( generated_get_attribute );
|
||||
}
|
||||
body.append(def_pragma( txt("endregion Attribute Setters")));
|
||||
}
|
||||
|
||||
void def_attribute_field_initers ( CodeBody body, Array<StringCached> properties )
|
||||
@@ -307,11 +309,10 @@ void def_attribute_field_initers ( CodeBody body, Array<StringCached> properties
|
||||
|
||||
void impl_attribute_fields( CodeBody body, StrC class_name, Array<StringCached> properties )
|
||||
{
|
||||
body.append(fmt_newline);
|
||||
body.append(def_pragma( txt("region Rep Notifies")));
|
||||
for ( String property : properties )
|
||||
{
|
||||
body.append(fmt_newline);
|
||||
|
||||
CodeFn field_impl = parse_function( token_fmt(
|
||||
"class_name", class_name, "property", (StrC)property, "from_notice", txt("\n// From GAMEPLAYATTRIBUTE_REPNOTIFY\n"),
|
||||
stringize(
|
||||
@@ -326,6 +327,7 @@ void impl_attribute_fields( CodeBody body, StrC class_name, Array<StringCached>
|
||||
body.append( field_impl );
|
||||
}
|
||||
body.append( def_pragma( txt("endregion Rep Notifies")));
|
||||
body.append(fmt_newline);
|
||||
}
|
||||
|
||||
inline
|
||||
|
||||
@@ -1610,7 +1610,7 @@ void CodeConstructor::to_string_fwd( String& result )
|
||||
if ( ast->InlineCmt )
|
||||
result.append_fmt( "; // %S\n", ast->InlineCmt->Content );
|
||||
else
|
||||
result.append( ";" );
|
||||
result.append( ";\n" );
|
||||
}
|
||||
|
||||
String CodeClass::to_string()
|
||||
@@ -6278,6 +6278,16 @@ namespace parser
|
||||
move_forward();
|
||||
preprocess_content.Length++;
|
||||
|
||||
if ( current == '\r' && scanner[1] == '\n' )
|
||||
{
|
||||
move_forward();
|
||||
move_forward();
|
||||
}
|
||||
else if ( current == '\n' )
|
||||
{
|
||||
move_forward();
|
||||
}
|
||||
|
||||
Tokens.append( preprocess_content );
|
||||
return Lex_Continue; // Skip found token, its all handled here.
|
||||
}
|
||||
@@ -7262,7 +7272,7 @@ namespace parser
|
||||
Tokens = Array<Token>::init_reserve( LexArena, ( LexAllocator_Size - sizeof( Array<Token>::Header ) ) / sizeof( Token ) );
|
||||
|
||||
defines_map_arena = Arena_256KB::init();
|
||||
defines = HashTable<StrC>::init( defines_map_arena );
|
||||
defines = HashTable<StrC>::init_reserve( defines_map_arena, 256 );
|
||||
}
|
||||
|
||||
internal void deinit()
|
||||
|
||||
@@ -1663,7 +1663,7 @@ struct Array
|
||||
{
|
||||
Header& header = *get_header();
|
||||
|
||||
if ( begin < 0 || end >= header.Num )
|
||||
if ( begin < 0 || end > header.Num )
|
||||
return false;
|
||||
|
||||
for ( sw idx = begin; idx < end; idx++ )
|
||||
@@ -1820,13 +1820,11 @@ struct HashTable
|
||||
Type Value;
|
||||
};
|
||||
|
||||
static constexpr f32 CriticalLoadScale = 0.7f;
|
||||
|
||||
static HashTable init( AllocatorInfo allocator )
|
||||
{
|
||||
HashTable<Type> result = { { nullptr }, { nullptr } };
|
||||
|
||||
result.Hashes = Array<sw>::init( allocator );
|
||||
result.Entries = Array<Entry>::init( allocator );
|
||||
|
||||
HashTable<Type> result = init_reserve(allocator, 8);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1834,21 +1832,19 @@ struct HashTable
|
||||
{
|
||||
HashTable<Type> result = { { nullptr }, { nullptr } };
|
||||
|
||||
result.Hashes = Array<sw>::init_reserve( allocator, num );
|
||||
result.Hashes = Array<sw>::init_reserve( allocator, num );
|
||||
result.Hashes.get_header()->Num = num;
|
||||
result.Hashes.resize( num );
|
||||
result.Hashes.fill( 0, num, -1);
|
||||
|
||||
result.Entries = Array<Entry>::init_reserve( allocator, num );
|
||||
|
||||
result.Entries = Array<Entry>::init_reserve( allocator, num );
|
||||
return result;
|
||||
}
|
||||
|
||||
void clear( void )
|
||||
{
|
||||
for ( sw idx = 0; idx < Hashes.num(); idx++ )
|
||||
Hashes[idx] = -1;
|
||||
|
||||
Hashes.clear();
|
||||
Entries.clear();
|
||||
Hashes.fill( 0, Hashes.num(), -1);
|
||||
}
|
||||
|
||||
void destroy( void )
|
||||
@@ -1901,32 +1897,19 @@ struct HashTable
|
||||
|
||||
void rehash( sw new_num )
|
||||
{
|
||||
sw idx;
|
||||
sw last_added_index;
|
||||
|
||||
HashTable<Type> new_ht = init_reserve( Hashes.get_header()->Allocator, new_num );
|
||||
|
||||
Array<sw>::Header* hash_header = new_ht.Hashes.get_header();
|
||||
|
||||
for ( idx = 0; idx < new_ht.Hashes.num(); ++idx )
|
||||
new_ht.Hashes[idx] = -1;
|
||||
|
||||
for ( idx = 0; idx < Entries.num(); ++idx )
|
||||
HashTable<Type> new_ht = init_reserve( Hashes.get_header()->Allocator, new_num );
|
||||
for ( sw idx = 0; idx < Entries.num(); ++idx )
|
||||
{
|
||||
Entry& entry = Entries[idx];
|
||||
|
||||
FindResult find_result;
|
||||
|
||||
if ( new_ht.Hashes.num() == 0 )
|
||||
new_ht.grow();
|
||||
|
||||
entry = Entries[idx];
|
||||
Entry& entry = Entries[idx];
|
||||
find_result = new_ht.find( entry.Key );
|
||||
last_added_index = new_ht.add_entry( entry.Key );
|
||||
|
||||
if ( find_result.PrevIndex < 0 )
|
||||
new_ht.Hashes[find_result.HashIndex] = last_added_index;
|
||||
|
||||
else
|
||||
new_ht.Entries[find_result.PrevIndex].Next = last_added_index;
|
||||
|
||||
@@ -1984,11 +1967,10 @@ struct HashTable
|
||||
sw idx;
|
||||
FindResult find_result;
|
||||
|
||||
if ( Hashes.num() == 0 )
|
||||
if ( full() )
|
||||
grow();
|
||||
|
||||
find_result = find( key );
|
||||
|
||||
if ( find_result.EntryIndex >= 0 )
|
||||
{
|
||||
idx = find_result.EntryIndex;
|
||||
@@ -2060,7 +2042,9 @@ protected:
|
||||
|
||||
b32 full()
|
||||
{
|
||||
return 0.75f * Hashes.num() < Entries.num();
|
||||
uw critical_load = uw( CriticalLoadScale * f32(Hashes.num()) );
|
||||
b32 result = Entries.num() > critical_load;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2096,7 +2080,7 @@ struct StrC
|
||||
#define txt( text ) \
|
||||
StrC \
|
||||
{ \
|
||||
sizeof( text ) - 1, text \
|
||||
sizeof( (text) ) - 1, (text) \
|
||||
}
|
||||
|
||||
StrC to_str( char const* str )
|
||||
|
||||
Reference in new issue
Block a user