Skip to content

Commit

Permalink
WIP table for content tag additions. Add custom thunks for the accura…
Browse files Browse the repository at this point in the history
…te script callstack info, untested.
  • Loading branch information
budak7273 committed Aug 8, 2024
1 parent 25beaa7 commit 45b07d8
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 16 deletions.
9 changes: 9 additions & 0 deletions Mods/SML/Source/SML/Private/Module/GameWorldModule.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "Module/GameWorldModule.h"
#include "Command/ChatCommandLibrary.h"
#include "Registry/ModContentRegistry.h"
#include "Registry/ContentTagRegistry.h"
#include "Subsystem/SubsystemActorManager.h"

#if WITH_EDITOR
Expand Down Expand Up @@ -53,7 +54,9 @@ void UGameWorldModule::RegisterDefaultContent() {
UWorld* WorldObject = GetWorld();
UModContentRegistry* ModContentRegistry = UModContentRegistry::Get(WorldObject);
AChatCommandSubsystem* ChatCommandSubsystem = AChatCommandSubsystem::Get(WorldObject);
UContentTagRegistry* ContentTagRegistry = UContentTagRegistry::Get(WorldObject);
check(ModContentRegistry);
check(ContentTagRegistry);

auto ModReference = GetOwnerModReference();

Expand All @@ -77,6 +80,12 @@ void UGameWorldModule::RegisterDefaultContent() {
ModContentRegistry->RegisterResourceSinkItemPointTable(ModReference, ModExplorationResourceSinkPointsTable, EResourceSinkTrack::RST_Exploration);
}

//Register tag additions
UDataTable* ContentTagAdditionsTable = mContentTagAdditionsTable.LoadSynchronous();
if (ContentTagAdditionsTable != NULL) {
ContentTagRegistry->RegisterTagAdditionTable(ModReference, ContentTagAdditionsTable);
}

//Register chat commands (on server side only)
if (ChatCommandSubsystem != NULL) {
for (const TSubclassOf<AChatCommandInstance>& ChatCommand : mChatCommands) {
Expand Down
50 changes: 36 additions & 14 deletions Mods/SML/Source/SML/Private/Registry/ContentTagRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

DEFINE_LOG_CATEGORY(LogContentTagRegistry);

FFrame* UContentTagRegistry::ActiveScriptFramePtr{};

/** Makes sure provided object instance is valid, crashes with both script call stack and native stack trace if it's not */
#define NOTIFY_INVALID_REGISTRATION(Context) \
{ \
Expand Down Expand Up @@ -113,22 +111,14 @@ void UContentTagRegistry::RegisterTagAdditionTable(FName ModReference, UDataTabl
return;
}

if (!IsValid(PointTable->RowStruct) || !PointTable->RowStruct->IsChildOf(FResourceSinkPointsData::StaticStruct())) {
const FString Context = FString::Printf(TEXT("Invalid AWESOME Sink item points table in mod %s (%s): Row Type should be Resource Sink Points Data"),
*ModReference.ToString(), *PointTable->GetPathName());
if (!IsValid(TagTable->RowStruct) || !TagTable->RowStruct->IsChildOf(FContentTagRegistryAddition::StaticStruct())) {
const FString Context = FString::Printf(TEXT("Invalid Content Tag Addition table in mod %s (%s): Row Type should be FContentTagRegistryAddition"),
*ModReference.ToString(), *TagTable->GetPathName());
NOTIFY_INVALID_REGISTRATION(*Context);
return;
}

FPendingResourceSinkRegistration Registration;
Registration.Track = Track;
Registration.ModReference = ModReference;
Registration.PointTable = PointTable;

PendingItemSinkPointsRegistrations.Add(Registration);
if (AFGResourceSinkSubsystem* ResourceSinkSubsystem = AFGResourceSinkSubsystem::Get(GetWorld())) {
FlushPendingResourceSinkRegistrations(ResourceSinkSubsystem);
}
UE_LOG(LogContentTagRegistry, Verbose, TEXT("TODO Registering tag addition table '%s' from mod %s"), *TagTable->GetPathName(), *ModReference.ToString());
}

void UContentTagRegistry::FreezeRegistry() {
Expand Down Expand Up @@ -177,3 +167,35 @@ FString UContentTagRegistry::GetCallStackContext() {
}
return FString::Printf(TEXT("%hs:%d"), NativeStackTrace[FirstExternalFrameIndex].Filename, NativeStackTrace[FirstExternalFrameIndex].LineNumber);
}

FFrame* UContentTagRegistry::ActiveScriptFramePtr{};

DEFINE_FUNCTION(UContentTagRegistry::execAddGameplayTagsTo) {
P_GET_OBJECT(UClass, Z_Param_Content);
P_GET_STRUCT(FGameplayTagContainer, Z_Param_TagContainer)
P_FINISH;
P_NATIVE_BEGIN;
TGuardValue ScopedFrameOverride(ActiveScriptFramePtr, &Stack);
P_THIS->AddGameplayTagsTo(Z_Param_Content, Z_Param_TagContainer);
P_NATIVE_END;
}

DEFINE_FUNCTION(UContentTagRegistry::execRemoveGameplayTagsFrom) {
P_GET_OBJECT(UClass, Z_Param_Content);
P_GET_STRUCT(FGameplayTagContainer, Z_Param_TagContainer)
P_FINISH;
P_NATIVE_BEGIN;
TGuardValue ScopedFrameOverride(ActiveScriptFramePtr, &Stack);
P_THIS->RemoveGameplayTagsFrom(Z_Param_Content, Z_Param_TagContainer);
P_NATIVE_END;
}

DEFINE_FUNCTION(UContentTagRegistry::execRegisterTagAdditionTable) {
P_GET_PROPERTY(FNameProperty, ModReference);
P_GET_OBJECT(UDataTable, PointTable);
P_FINISH;
P_NATIVE_BEGIN;
TGuardValue ScopedFrameOverride(ActiveScriptFramePtr, &Stack);
P_THIS->RegisterTagAdditionTable(ModReference, PointTable);
P_NATIVE_END;
}
8 changes: 8 additions & 0 deletions Mods/SML/Source/SML/Public/Module/GameWorldModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ class SML_API UGameWorldModule : public UWorldModule {
UPROPERTY(EditDefaultsOnly, Category = Advanced)
TSoftObjectPtr<class UDataTable> mExplorationResourceSinkItemPointsTable;

/**
* Table to use for Content Tag Registry additions.
* Useful for adding tags to content you don't control, for example,
* items from the base game and other mods.
*/
UPROPERTY(EditDefaultsOnly, Category = Advanced)
TSoftObjectPtr<class UDataTable> mContentTagAdditionsTable;

/** Mod subsystem actors to be registered automatically during construction phase */
UPROPERTY(EditDefaultsOnly, Category= Advanced)
TArray<TSubclassOf<class AModSubsystem>> ModSubsystems;
Expand Down
31 changes: 29 additions & 2 deletions Mods/SML/Source/SML/Public/Registry/ContentTagRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@

DECLARE_LOG_CATEGORY_EXTERN(LogContentTagRegistry, All, All); // TODO set arg2 to Log once done with feature

/**
* Row struct for the data table tag assignment registration approach
*/
USTRUCT(BlueprintType)
struct SML_API FContentTagRegistryAddition : public FTableRowBase {
GENERATED_BODY()

FContentTagRegistryAddition() :
ItemClass(nullptr),
TagContainer(FGameplayTagContainer::EmptyContainer)
{}

UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSubclassOf<UObject> ItemClass;

UPROPERTY(EditAnywhere, BlueprintReadWrite)
FGameplayTagContainer TagContainer;
};

/**
* Manages Gameplay Tag Containers for content classes.
* Enables any mod to apply Unreal Gameplay Tags to any mod's content,
Expand Down Expand Up @@ -43,16 +62,19 @@ class SML_API UContentTagRegistry : public UWorldSubsystem
* Register gameplay tags from the passed container to the passed class
* TODO do we want arg FName InRegistrationPluginName?
*/
UFUNCTION(BlueprintCallable, Category = "Content Tag Registry")
UFUNCTION(BlueprintCallable, Category = "Content Tag Registry", CustomThunk)
void AddGameplayTagsTo(UClass* content, const FGameplayTagContainer tags);

/**
* Remove gameplay tags in passed container from the passed class if they were present
* TODO do we want arg FName InRegistrationPluginName?
*/
UFUNCTION(BlueprintCallable, Category = "Content Tag Registry")
UFUNCTION(BlueprintCallable, Category = "Content Tag Registry", CustomThunk)
void RemoveGameplayTagsFrom(UClass* content, const FGameplayTagContainer tags);

UFUNCTION(BlueprintCallable, Category = "Content Tag Registry", CustomThunk)
void RegisterTagAdditionTable(FName ModReference, UDataTable* TagTable);

// Freezes the registry. No new registrations are accepted past this point.
void FreezeRegistry();

Expand Down Expand Up @@ -91,4 +113,9 @@ class SML_API UContentTagRegistry : public UWorldSubsystem
// Gets tags offered via SML Extended Attribute Provider
FGameplayTagContainer GetTagsFromExtendedAttributeProvider(UClass* content);

//Custom Thunks for calling Register functions through Reflection, primary point of which
//is providing FFrame callstack context to the registration methods for debugging in seamless manner
DECLARE_FUNCTION(execAddGameplayTagsTo);
DECLARE_FUNCTION(execRemoveGameplayTagsFrom);
DECLARE_FUNCTION(execRegisterTagAdditionTable);
};

0 comments on commit 45b07d8

Please sign in to comment.