Skip to content

Commit 1a80136

Browse files
committed
Added the 'Meta Cheat Manager' plugin to allow customize command names by 'CheatName =' meta for the functions in the Meta Cheat Manager subclass
1 parent cebc813 commit 1a80136

16 files changed

+452
-36
lines changed

Diff for: .gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -421,4 +421,7 @@ Saved/*
421421
**/Intermediate/*
422422

423423
# Cache files for the editor to use
424-
DerivedDataCache/*
424+
DerivedDataCache
425+
426+
# Bomber specific
427+
Config/DefaultMetaCheatManager.ini
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"BuildId": "23058290",
3+
"Modules":
4+
{
5+
"MetaCheatManager": "UnrealEditor-MetaCheatManager.dll"
6+
}
7+
}

Diff for: Plugins/MetaCheatManager/MetaCheatManager.uplugin

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"FileVersion": 3,
3+
"Version": 1,
4+
"VersionName": "1.0",
5+
"FriendlyName": "Meta Cheat Manager",
6+
"Description": "Plugin allows customize command names by 'CheatName =' meta for the functions in the Meta Cheat Manager subclass",
7+
"Category": "My Plugins",
8+
"CreatedBy": "Yevhenii Selivanov",
9+
"CreatedByURL": "https://github.com/JanSeliv/Bomber",
10+
"DocsURL": "",
11+
"MarketplaceURL": "",
12+
"SupportURL": "mailto:[email protected]",
13+
"EngineVersion": "5.1.0",
14+
"EnabledByDefault": true,
15+
"CanContainContent": false,
16+
"IsBetaVersion": true,
17+
"Installed": false,
18+
"Modules": [
19+
{
20+
"Name": "MetaCheatManager",
21+
"Type": "Runtime",
22+
"LoadingPhase": "Default"
23+
}
24+
]
25+
}

Diff for: Plugins/MetaCheatManager/Resources/Icon128.png

21.5 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright Epic Games, Inc. All Rights Reserved.
2+
3+
using UnrealBuildTool;
4+
5+
public class MetaCheatManager : ModuleRules
6+
{
7+
public MetaCheatManager(ReadOnlyTargetRules Target) : base(Target)
8+
{
9+
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
10+
CppStandard = CppStandardVersion.Latest;
11+
12+
PublicDependencyModuleNames.AddRange(new[]
13+
{
14+
"Core"
15+
}
16+
);
17+
18+
PrivateDependencyModuleNames.AddRange(new[]
19+
{
20+
"CoreUObject", "Engine", "Slate", "SlateCore" // Core
21+
, "EngineSettings" // UConsoleSettings
22+
}
23+
);
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright (c) Yevhenii Selivanov
2+
3+
#include "MetaCheatCommand.h"
4+
//---
5+
#include "ConsoleSettings.h"
6+
7+
// Contains empty cheat command
8+
const FMetaCheatCommand FMetaCheatCommand::EmptyCommand = FMetaCheatCommand();
9+
10+
// Returns the Auto Complete Command from this structure object
11+
FAutoCompleteCommand FMetaCheatCommand::ToAutoCompleteCommand() const
12+
{
13+
FAutoCompleteCommand AutoCompleteCommand;
14+
AutoCompleteCommand.Command = CheatName.ToString();
15+
AutoCompleteCommand.Desc = CheatDescription.ToString();
16+
static FColor AutoCompleteCommandColor = GetDefault<UConsoleSettings>()->AutoCompleteCommandColor;
17+
AutoCompleteCommand.Color = AutoCompleteCommandColor;
18+
return AutoCompleteCommand;
19+
}
20+
21+
#if WITH_EDITOR
22+
// Builds all the data for this command by function ptr
23+
FMetaCheatCommand FMetaCheatCommand::Create(const UFunction* InFunction)
24+
{
25+
if (!InFunction)
26+
{
27+
return EmptyCommand;
28+
}
29+
30+
FMetaCheatCommand CheatCommand;
31+
CheatCommand.CheatName = FindCheatMetaData(InFunction);
32+
if (CheatCommand.CheatName.IsNone())
33+
{
34+
// No cheat name, so this is not a cheat command
35+
return EmptyCommand;
36+
}
37+
38+
CheatCommand.FunctionName = InFunction->GetFName();
39+
CheatCommand.CheatDescription = FindCheatDescription(InFunction);
40+
return CheatCommand;
41+
}
42+
43+
// Finds a value of the 'CheatName' meta data for the specified function, none if CheatName is not set
44+
FName FMetaCheatCommand::FindCheatMetaData(const UFunction* InFunction)
45+
{
46+
static const FName CheatNameMetaKey = TEXT("CheatName");
47+
checkf(InFunction, TEXT("%s: 'InFunction' is null"), *FString(__FUNCTION__));
48+
const FString* FoundMetaData = InFunction->FindMetaData(CheatNameMetaKey);
49+
return FoundMetaData ? FName(*FoundMetaData) : NAME_None;
50+
}
51+
52+
// Finds the description for the specified function
53+
FName FMetaCheatCommand::FindCheatDescription(const UFunction* InFunction)
54+
{
55+
checkf(InFunction, TEXT("%s: 'InFunction' is null"), *FString(__FUNCTION__));
56+
57+
FString Description = TEXT("");
58+
59+
// Start with description of function param: Name[Type]. E.x: NewLevel[int32]
60+
for (TFieldIterator<FProperty> PropIt(InFunction); PropIt && PropIt->PropertyFlags & CPF_Parm; ++PropIt)
61+
{
62+
if (const FProperty* Prop = *PropIt)
63+
{
64+
Description += FString::Printf(TEXT("%s[%s] "), *Prop->GetName(), *Prop->GetCPPType());
65+
}
66+
}
67+
68+
// Get the first line of the function tooltip
69+
static const FString Delimiter = TEXT("\n");
70+
FString FunctionToolTip = InFunction->GetToolTipText().ToString();
71+
TArray<FString> SeparatedStrings;
72+
FunctionToolTip.ParseIntoArray(SeparatedStrings, *Delimiter);
73+
if (!FunctionToolTip.IsEmpty())
74+
{
75+
FunctionToolTip = SeparatedStrings[0];
76+
}
77+
78+
// Add function tooltip to the total description
79+
Description.Append(FunctionToolTip);
80+
return FName(*Description);
81+
}
82+
#endif // WITH_EDITOR
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright (c) Yevhenii Selivanov
2+
3+
#include "MetaCheatManager.h"
4+
//---
5+
#include "Engine/Console.h"
6+
7+
// Returns the cheat command associated with specified CheatName meta value
8+
const FMetaCheatCommand& UMetaCheatManager::GetCheatCommandByCheatName(const FName& CheatName) const
9+
{
10+
for (const FMetaCheatCommand& CheatCommandIt : AllCheatCommands)
11+
{
12+
if (CheatCommandIt.CheatName.IsEqual(CheatName))
13+
{
14+
return CheatCommandIt;
15+
}
16+
}
17+
18+
return FMetaCheatCommand::EmptyCommand;
19+
}
20+
21+
// Is overridden to initialize all cheat commands on editor startup
22+
void UMetaCheatManager::PostInitProperties()
23+
{
24+
Super::PostInitProperties();
25+
26+
InitAllCheatCommands();
27+
}
28+
29+
// Called when CheatManager is created to allow any needed initialization
30+
void UMetaCheatManager::InitCheatManager()
31+
{
32+
Super::InitCheatManager();
33+
34+
if (!UConsole::RegisterConsoleAutoCompleteEntries.IsBoundToObject(this))
35+
{
36+
UConsole::RegisterConsoleAutoCompleteEntries.AddUObject(this, &ThisClass::RegisterAutoCompleteEntries);
37+
}
38+
}
39+
40+
// Is overridden to convert meta CheatName Your.Cheat.Name to the function name YourCheatFunction whenever user enters the command
41+
bool UMetaCheatManager::ProcessConsoleExec(const TCHAR* Cmd, FOutputDevice& Ar, UObject* Executor)
42+
{
43+
constexpr bool bUseEscape = true;
44+
const FString OriginalCmd = Cmd;
45+
FString CommandName = TEXT("");
46+
if (FParse::Token(/*InOut*/Cmd, /*Out*/CommandName, bUseEscape))
47+
{
48+
// CommandName: is the CheatName (Your.Cheat.Name)
49+
// Cmd: is the value (if any) that was passed to the cheat
50+
const FMetaCheatCommand& CheatCommand = GetCheatCommandByCheatName(*CommandName);
51+
if (CheatCommand.IsValid())
52+
{
53+
// Get the function name (YourCheatFunction) from the CheatName (Your.Cheat.Name)
54+
// and append it with the value that was passed to the cheat to process the call
55+
// YourFunctionCheat Value
56+
constexpr bool bForceCallWithNonExec = true;
57+
const FString CmdString = CheatCommand.FunctionName.ToString() + Cmd;
58+
return CallFunctionByNameWithArguments(*CmdString, Ar, Executor, bForceCallWithNonExec);
59+
}
60+
}
61+
62+
return Super::ProcessConsoleExec(*OriginalCmd, Ar, Executor);
63+
}
64+
65+
// Garbage things before destroying the Cheat Manager
66+
void UMetaCheatManager::BeginDestroy()
67+
{
68+
UConsole::RegisterConsoleAutoCompleteEntries.RemoveAll(this);
69+
70+
Super::BeginDestroy();
71+
}
72+
73+
// Is bound to return all initialized meta cheat commands to see them in the console
74+
void UMetaCheatManager::RegisterAutoCompleteEntries(TArray<FAutoCompleteCommand>& Commands) const
75+
{
76+
for (const FMetaCheatCommand& CheatCommandIt : AllCheatCommands)
77+
{
78+
Commands.Emplace(CheatCommandIt.ToAutoCompleteCommand());
79+
}
80+
}
81+
82+
// Finds and saves all cheat commands marked with 'CheatName' metadata
83+
void UMetaCheatManager::InitAllCheatCommands()
84+
{
85+
#if WITH_EDITOR
86+
// It automatically adds DefaultMetaCheatManager.ini config on the editor startup to the Config folder on your project
87+
// to have your cheat commands with custom Cheat Names in the packaged build as well, you don't need to do anything specific about it.
88+
// Such solution is used because any metadata can be obtained only in the Editor, so we store it in the config file for the build.
89+
90+
if (!HasAllFlags(RF_ClassDefaultObject))
91+
{
92+
// Do not init cheat commands for instances since we save them as default values into config file
93+
return;
94+
}
95+
96+
if (!AllCheatCommands.IsEmpty())
97+
{
98+
AllCheatCommands.Empty();
99+
}
100+
101+
// Find all cheat commands
102+
for (TFieldIterator<UFunction> FunctionIt(GetClass(), EFieldIteratorFlags::ExcludeSuper); FunctionIt; ++FunctionIt)
103+
{
104+
FMetaCheatCommand CheatCommand = FMetaCheatCommand::Create(*FunctionIt);
105+
if (CheatCommand.IsValid())
106+
{
107+
AllCheatCommands.Emplace(MoveTemp(CheatCommand));
108+
}
109+
}
110+
111+
TryUpdateDefaultConfigFile();
112+
#endif // WITH_EDITOR
113+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright Epic Games, Inc. All Rights Reserved.
2+
3+
#include "MetaCheatManagerModule.h"
4+
5+
#define LOCTEXT_NAMESPACE "FMetaCheatManagerModule"
6+
7+
// Called right after the module DLL has been loaded and the module object has been created
8+
void FMetaCheatManagerModule::StartupModule()
9+
{
10+
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
11+
}
12+
13+
// Called before the module is unloaded, right before the module object is destroyed
14+
void FMetaCheatManagerModule::ShutdownModule()
15+
{
16+
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
17+
// we call this function before unloading the module.
18+
}
19+
20+
#undef LOCTEXT_NAMESPACE
21+
22+
IMPLEMENT_MODULE(FMetaCheatManagerModule, MetaCheatManager)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) Yevhenii Selivanov
2+
3+
#pragma once
4+
5+
#include "CoreMinimal.h"
6+
#include "MetaCheatCommand.generated.h"
7+
8+
struct FAutoCompleteCommand;
9+
10+
/**
11+
* Describes a cheat command.
12+
*/
13+
USTRUCT(BlueprintType)
14+
struct METACHEATMANAGER_API FMetaCheatCommand
15+
{
16+
GENERATED_BODY()
17+
18+
/** Contains empty cheat command. */
19+
static const FMetaCheatCommand EmptyCommand;
20+
21+
/** The name of command that will be displayed in console. */
22+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "C++")
23+
FName CheatName = NAME_None;
24+
25+
/** The original name of function. */
26+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "C++")
27+
FName FunctionName = NAME_None;
28+
29+
/** The description of the command. */
30+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "C++")
31+
FName CheatDescription = NAME_None;
32+
33+
/** Returns true if this command contains correct data */
34+
FORCEINLINE bool IsValid() const
35+
{
36+
return CheatName != NAME_None
37+
&& CheatDescription != NAME_None
38+
&& FunctionName != NAME_None;
39+
}
40+
41+
/** Returns the Auto Complete Command from this structure object. */
42+
FAutoCompleteCommand ToAutoCompleteCommand() const;
43+
44+
#if WITH_EDITOR
45+
/** Builds all the data for this command by function ptr.
46+
* Is editor-only since the meta data is not available in the build.*/
47+
static FMetaCheatCommand Create(const UFunction* InFunction);
48+
49+
/** Finds a value of the 'CheatName' meta data for the specified function, none if CheatName is not set.
50+
* Is editor-only since the meta data is not available in the build.*/
51+
static FName FindCheatMetaData(const UFunction* InFunction);
52+
53+
/** Finds the description for the specified function.
54+
* Is editor-only since the meta data is not available in the build.*/
55+
static FName FindCheatDescription(const UFunction* InFunction);
56+
#endif // WITH_EDITOR
57+
};

0 commit comments

Comments
 (0)