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:
parent
cc1636b687
commit
ad41867dc5
BIN
Project/Binaries/Win64/UnrealEditor-Gasa.dll
(Stored with Git LFS)
BIN
Project/Binaries/Win64/UnrealEditor-Gasa.dll
(Stored with Git LFS)
Binary file not shown.
BIN
Project/Binaries/Win64/UnrealEditor-GasaEditor.dll
(Stored with Git LFS)
BIN
Project/Binaries/Win64/UnrealEditor-GasaEditor.dll
(Stored with Git LFS)
Binary file not shown.
BIN
Project/Content/Core/AbilitySystem/GE_PotionHealth.uasset
(Stored with Git LFS)
Normal file
BIN
Project/Content/Core/AbilitySystem/GE_PotionHealth.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Project/Content/Core/AbilitySystem/GE_PotionMana.uasset
(Stored with Git LFS)
Normal file
BIN
Project/Content/Core/AbilitySystem/GE_PotionMana.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Project/Content/Core/Pickups/BP_HealthPotion_RawEffect.uasset
(Stored with Git LFS)
BIN
Project/Content/Core/Pickups/BP_HealthPotion_RawEffect.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Project/Content/Core/Pickups/BP_ManaPotion_RawEffect.uasset
(Stored with Git LFS)
Normal file
BIN
Project/Content/Core/Pickups/BP_ManaPotion_RawEffect.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Project/Content/Levels/StartupMap.umap
(Stored with Git LFS)
BIN
Project/Content/Levels/StartupMap.umap
(Stored with Git LFS)
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:
|
||||
|
0
Project/Source/Gasa/Actors/GasaActor.cpp
Normal file
0
Project/Source/Gasa/Actors/GasaActor.cpp
Normal file
33
Project/Source/Gasa/Actors/GasaActor.h
Normal file
33
Project/Source/Gasa/Actors/GasaActor.h
Normal file
@ -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"
|
||||
|
||||
@ -60,6 +61,28 @@ public:
|
||||
|
||||
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; }
|
||||
FORCEINLINE UAbilitySystemComponent* GetAbilitySystemComponent() const override { return AbilitySystem; }
|
||||
|
@ -25,10 +25,13 @@ void APlayerCharacter::PossessedBy(AController* NewController)
|
||||
AbilitySystem->InitAbilityActorInfo(PS, this);
|
||||
}
|
||||
|
||||
if (IsLocallyControlled())
|
||||
{
|
||||
AGasaPlayerController* PC = GetController<AGasaPlayerController>();
|
||||
AGasaHUD* HUD = PC->GetHUD<AGasaHUD>();
|
||||
FWidgetControllerData Data = { PC, PS, AbilitySystem, Attributes };
|
||||
HUD->InitHostWidget(& Data);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(Ed): We need to setup Net Slime...
|
||||
|
@ -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,12 +1,16 @@
|
||||
#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()
|
||||
@ -18,29 +22,95 @@ public:
|
||||
|
||||
#if ENABLE_COG
|
||||
TObjectPtr<UCogWindowManager> CogWindowManager;
|
||||
#endif // ENABLE_COG
|
||||
#endif
|
||||
// ENABLE_COG
|
||||
#pragma endregion Cog
|
||||
|
||||
AGasaGameState();
|
||||
|
||||
#pragma region GameState
|
||||
void BeginPlay() override;
|
||||
#pragma region GameFramework
|
||||
UFUNCTION()
|
||||
void OnGameFrameworkInitialized();
|
||||
|
||||
void Tick(float DeltaSeconds) override;
|
||||
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 HandleBeginPlay() 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,6 +155,8 @@ void AGasaPlayerController::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
if (IsLocalController())
|
||||
{
|
||||
check(IMC);
|
||||
|
||||
UEnhancedInputLocalPlayerSubsystem*
|
||||
@ -169,6 +171,7 @@ void AGasaPlayerController::BeginPlay()
|
||||
MouseMode.SetHideCursorDuringCapture(false);
|
||||
SetInputMode(MouseMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGasaPlayerController::PostInitializeComponents()
|
||||
|
@ -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"
|
||||
|
||||
@ -52,11 +54,32 @@ public:
|
||||
|
||||
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;
|
||||
@ -11,6 +11,32 @@ public class Gasa : ModuleRules
|
||||
public Gasa(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
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",
|
||||
});
|
||||
|
53
Project/Source/Gasa/GasaColdHeadersPCH.h
Normal file
53
Project/Source/Gasa/GasaColdHeadersPCH.h
Normal file
@ -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
|
||||
|
160
Project/Source/Gasa/GasaEngineMinimal.h
Normal file
160
Project/Source/Gasa/GasaEngineMinimal.h
Normal file
@ -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
|
||||
{
|
||||
|
77
Project/Source/Gasa/GasaObject.cpp
Normal file
77
Project/Source/Gasa/GasaObject.cpp
Normal file
@ -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;
|
||||
}
|
80
Project/Source/Gasa/GasaObject.h
Normal file
80
Project/Source/Gasa/GasaObject.h
Normal file
@ -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);
|
||||
}
|
||||
|
278
Project/Source/Gasa/Networking/GasaNetLibrary_Inlines.h
Normal file
278
Project/Source/Gasa/Networking/GasaNetLibrary_Inlines.h
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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(");
|
||||
|
118
Project/Source/GasaGen/GasaGen_NetSlime.cpp
Normal file
118
Project/Source/GasaGen/GasaGen_NetSlime.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
||||
@ -1836,19 +1834,17 @@ struct HashTable
|
||||
|
||||
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 );
|
||||
|
||||
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 )
|
||||
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 )
|
||||
|
Loading…
Reference in New Issue
Block a user