Skip to content

Commit

Permalink
Merge pull request #3 from JanSeliv/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
JanSeliv authored Jan 14, 2024
2 parents b160fe7 + ff29643 commit 37ce84d
Show file tree
Hide file tree
Showing 13 changed files with 299 additions and 99 deletions.
Binary file modified Binaries/Win64/UnrealEditor-MetaCheatManager.dll
Binary file not shown.
Binary file modified Binaries/Win64/UnrealEditor-MetaCheatManager.pdb
Binary file not shown.
2 changes: 1 addition & 1 deletion Binaries/Win64/UnrealEditor.modules
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"BuildId": "25360045",
"BuildId": "27405482",
"Modules":
{
"MetaCheatManager": "UnrealEditor-MetaCheatManager.dll"
Expand Down
2 changes: 1 addition & 1 deletion MetaCheatManager.uplugin
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "mailto:[email protected]",
"EngineVersion": "5.2.0",
"EngineVersion": "5.3.0",
"EnabledByDefault": true,
"CanContainContent": false,
"IsBetaVersion": false,
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ Visit our [Release](https://github.com/JanSeliv/MetaCheatManager/releases) page
Also, explore this [game project repository](https://github.com/JanSeliv/Bomber) to see the Meta Cheat Manager in action.

## 📅 Changelog
#### 2024-01-14
- Updated to **Unreal Engine 5.3**.
- Added 'Cheat Manager Extensions' support, useful for plugins and Game Feature modules populating their own cheats.
#### 2023-05-31
- 🎉 Initial public release on Unreal Engine 5.2

## 📫 Feedback & Contribution

This is an open-source project and we encourage you to contribute. If you encounter any bugs or if you have any feature requests, please file an issue in the GitHub repository.
Feedback and contributions from the community are highly appreciated!

If you'd like to contribute, please fork the project and create a pull request targeting the `develop` branch.

If you've found a bug or have an idea for a new feature, please open a new issue on GitHub. Thank you!

## 📜 License

Expand Down
1 change: 1 addition & 0 deletions Source/MetaCheatManager/MetaCheatManager.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public MetaCheatManager(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
CppStandard = CppStandardVersion.Latest;
bEnableNonInlinedGenCppWarnings = true;

PublicDependencyModuleNames.AddRange(new[]
{
Expand Down
86 changes: 7 additions & 79 deletions Source/MetaCheatManager/Private/MetaCheatManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,18 @@

#include "MetaCheatManager.h"
//---
#include "MetaCheatManagerUtils.h"
//---
#include "Engine/Console.h"
//---
#include UE_INLINE_GENERATED_CPP_BY_NAME(MetaCheatManager)

// Returns the cheat command associated with specified CheatName meta value
const FMetaCheatCommand& UMetaCheatManager::GetCheatCommandByCheatName(const FName& CheatName) const
{
for (const FMetaCheatCommand& CheatCommandIt : AllCheatCommands)
{
if (CheatCommandIt.CheatName.IsEqual(CheatName))
{
return CheatCommandIt;
}
}

return FMetaCheatCommand::EmptyCommand;
}

// Is overridden to initialize all cheat commands on editor startup
void UMetaCheatManager::PostInitProperties()
{
Super::PostInitProperties();

InitAllCheatCommands();
}

// Called when CheatManager is created to allow any needed initialization
void UMetaCheatManager::InitCheatManager()
{
Super::InitCheatManager();
UMetaCheatManagerUtils::InitAllCheatCommands(this, /*Out*/AllCheatCommands);

if (!UConsole::RegisterConsoleAutoCompleteEntries.IsBoundToObject(this))
{
Expand All @@ -42,26 +24,8 @@ void UMetaCheatManager::InitCheatManager()
// Is overridden to convert meta CheatName Your.Cheat.Name to the function name YourCheatFunction whenever user enters the command
bool UMetaCheatManager::ProcessConsoleExec(const TCHAR* Cmd, FOutputDevice& Ar, UObject* Executor)
{
constexpr bool bUseEscape = true;
const FString OriginalCmd = Cmd;
FString CommandName = TEXT("");
if (FParse::Token(/*InOut*/Cmd, /*Out*/CommandName, bUseEscape))
{
// CommandName: is the CheatName (Your.Cheat.Name)
// Cmd: is the value (if any) that was passed to the cheat
const FMetaCheatCommand& CheatCommand = GetCheatCommandByCheatName(*CommandName);
if (CheatCommand.IsValid())
{
// Get the function name (YourCheatFunction) from the CheatName (Your.Cheat.Name)
// and append it with the value that was passed to the cheat to process the call
// YourFunctionCheat Value
constexpr bool bForceCallWithNonExec = true;
const FString CmdString = CheatCommand.FunctionName.ToString() + Cmd;
return CallFunctionByNameWithArguments(*CmdString, Ar, Executor, bForceCallWithNonExec);
}
}

return Super::ProcessConsoleExec(*OriginalCmd, Ar, Executor);
const bool bProcessed = UMetaCheatManagerUtils::TryProcessConsoleExec(this, Cmd, Ar, Executor);
return bProcessed || Super::ProcessConsoleExec(Cmd, Ar, Executor);
}

// Garbage things before destroying the Cheat Manager
Expand All @@ -73,43 +37,7 @@ void UMetaCheatManager::BeginDestroy()
}

// Is bound to return all initialized meta cheat commands to see them in the console
void UMetaCheatManager::RegisterAutoCompleteEntries(TArray<FAutoCompleteCommand>& Commands) const
{
for (const FMetaCheatCommand& CheatCommandIt : AllCheatCommands)
{
Commands.Emplace(CheatCommandIt.ToAutoCompleteCommand());
}
}

// Finds and saves all cheat commands marked with 'CheatName' metadata
void UMetaCheatManager::InitAllCheatCommands()
void UMetaCheatManager::RegisterAutoCompleteEntries(TArray<FAutoCompleteCommand>& OutCommands) const
{
#if WITH_EDITOR
// It automatically adds DefaultMetaCheatManager.ini config on the editor startup to the Config folder on your project
// 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.
// 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.

if (!HasAllFlags(RF_ClassDefaultObject))
{
// Do not init cheat commands for instances since we save them as default values into config file
return;
}

if (!AllCheatCommands.IsEmpty())
{
AllCheatCommands.Empty();
}

// Find all cheat commands
for (TFieldIterator<UFunction> FunctionIt(GetClass(), EFieldIteratorFlags::ExcludeSuper); FunctionIt; ++FunctionIt)
{
FMetaCheatCommand CheatCommand = FMetaCheatCommand::Create(*FunctionIt);
if (CheatCommand.IsValid())
{
AllCheatCommands.Emplace(MoveTemp(CheatCommand));
}
}

TryUpdateDefaultConfigFile();
#endif // WITH_EDITOR
UMetaCheatManagerUtils::RegisterAutoCompleteEntries(/*out*/OutCommands, AllCheatCommands);
}
43 changes: 43 additions & 0 deletions Source/MetaCheatManager/Private/MetaCheatManagerExtension.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) Yevhenii Selivanov

#include "MetaCheatManagerExtension.h"
//---
#include "MetaCheatManagerUtils.h"
//---
#include "Engine/Console.h"
//---
#include UE_INLINE_GENERATED_CPP_BY_NAME(MetaCheatManagerExtension)

// Is overridden to initialize all cheat commands on startup
void UMetaCheatManagerExtension::PostInitProperties()
{
Super::PostInitProperties();

UMetaCheatManagerUtils::InitAllCheatCommands(this, /*Out*/AllCheatCommands);

if (!UConsole::RegisterConsoleAutoCompleteEntries.IsBoundToObject(this))
{
UConsole::RegisterConsoleAutoCompleteEntries.AddUObject(this, &ThisClass::RegisterAutoCompleteEntries);
}
}

// Is overridden to convert meta CheatName Your.Cheat.Name to the function name YourCheatFunction whenever user enters the command
bool UMetaCheatManagerExtension::ProcessConsoleExec(const TCHAR* Cmd, FOutputDevice& Ar, UObject* Executor)
{
const bool bProcessed = UMetaCheatManagerUtils::TryProcessConsoleExec(this, Cmd, Ar, Executor);
return bProcessed || Super::ProcessConsoleExec(Cmd, Ar, Executor);
}

// Garbage things before destroying the Cheat Manager
void UMetaCheatManagerExtension::BeginDestroy()
{
UConsole::RegisterConsoleAutoCompleteEntries.RemoveAll(this);

Super::BeginDestroy();
}

// Is bound to return all initialized meta cheat commands to see them in the console
void UMetaCheatManagerExtension::RegisterAutoCompleteEntries(TArray<FAutoCompleteCommand>& OutCommands) const
{
UMetaCheatManagerUtils::RegisterAutoCompleteEntries(/*out*/OutCommands, AllCheatCommands);
}
113 changes: 113 additions & 0 deletions Source/MetaCheatManager/Private/MetaCheatManagerUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright (c) Yevhenii Selivanov

#include "MetaCheatManagerUtils.h"
//---
#include "MetaCheatCommand.h"
#include "MetaCheatManagerInterface.h"
//---
#include "ConsoleSettings.h"
//---
#include UE_INLINE_GENERATED_CPP_BY_NAME(MetaCheatManagerUtils)

void UMetaCheatManagerUtils::InitAllCheatCommands(const TScriptInterface<IMetaCheatManagerInterface> CheatManager, TArray<FMetaCheatCommand>& OutAllCheatCommands)
{
#if WITH_EDITOR
if (!ensureMsgf(CheatManager, TEXT("ASSERT: [%i] %s:\n'CheatManager' is not valid!"), __LINE__, *FString(__FUNCTION__)))
{
return;
}

UObject* CheatManagerObj = CheatManager.GetObject();
checkf(CheatManagerObj, TEXT("ERROR: [%i] %s:\n'CheatManagerObj' is null!"), __LINE__, *FString(__FUNCTION__));

// It automatically adds DefaultMetaCheatManager.ini config on the editor startup to the Config folder on your project
// 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.
// 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.

if (!CheatManagerObj->HasAllFlags(RF_ClassDefaultObject))
{
// Do not init cheat commands for instances since we save them as default values into config file
return;
}

if (!OutAllCheatCommands.IsEmpty())
{
OutAllCheatCommands.Empty();
}

// Find all cheat commands
for (TFieldIterator<UFunction> FunctionIt(CheatManagerObj->GetClass(), EFieldIteratorFlags::ExcludeSuper); FunctionIt; ++FunctionIt)
{
FMetaCheatCommand CheatCommand = FMetaCheatCommand::Create(*FunctionIt);
if (CheatCommand.IsValid())
{
OutAllCheatCommands.Emplace(MoveTemp(CheatCommand));
}
}

CheatManagerObj->TryUpdateDefaultConfigFile();
#endif // WITH_EDITOR
}

// Returns the cheat command associated with specified CheatName meta value
const FMetaCheatCommand& UMetaCheatManagerUtils::GetCheatCommandByCheatName(FName CheatName, const TArray<FMetaCheatCommand>& InAllCheatCommands)
{
for (const FMetaCheatCommand& CheatCommandIt : InAllCheatCommands)
{
if (CheatCommandIt.CheatName.IsEqual(CheatName))
{
return CheatCommandIt;
}
}

return FMetaCheatCommand::EmptyCommand;
}

// Registers auto-complete entries for the cheat commands
void UMetaCheatManagerUtils::RegisterAutoCompleteEntries(TArray<FAutoCompleteCommand>& OutCommands, const TArray<FMetaCheatCommand>& InAllCheatCommands)
{
for (const FMetaCheatCommand& CheatCommandIt : InAllCheatCommands)
{
const FAutoCompleteCommand& NewCommand = CheatCommandIt.ToAutoCompleteCommand();
const bool bIsNew = !OutCommands.ContainsByPredicate([&NewCommand](const FAutoCompleteCommand& CommandIt) { return CommandIt.Command == NewCommand.Command; });
if (bIsNew)
{
OutCommands.Emplace(NewCommand);
}
}
}

// Processes the console execution of meta cheat commands
bool UMetaCheatManagerUtils::TryProcessConsoleExec(const TScriptInterface<IMetaCheatManagerInterface> CheatManager, const TCHAR* const Cmd, FOutputDevice& Ar, UObject* Executor)
{
if (!ensureMsgf(CheatManager, TEXT("ASSERT: [%i] %s:\n'CheatManager' is not valid!"), __LINE__, *FString(__FUNCTION__)))
{
return false;
}

UObject* CheatManagerObj = CheatManager.GetObject();
checkf(CheatManagerObj, TEXT("ERROR: [%i] %s:\n'CheatManagerObj' is null!"), __LINE__, *FString(__FUNCTION__));

constexpr bool bUseEscape = true;
const TCHAR* ParsedCmd = Cmd;
FString CommandName = TEXT("");
if (!FParse::Token(/*InOut*/ParsedCmd, /*Out*/CommandName, bUseEscape))
{
return false;
}

// CommandName: is the CheatName (Your.Cheat.Name)
// Cmd: is the value (if any) that was passed to the cheat
const FMetaCheatCommand& CheatCommand = GetCheatCommandByCheatName(*CommandName, CheatManager->GetAllCheatCommands());
if (!CheatCommand.IsValid())
{
return false;
}

// Get the function name (YourCheatFunction) from the CheatName (Your.Cheat.Name)
// and append it with the value that was passed to the cheat to process the call
// YourFunctionCheat Value
constexpr bool bForceCallWithNonExec = true;
const FString CmdString = CheatCommand.FunctionName.ToString() + ParsedCmd;
return CheatManagerObj->CallFunctionByNameWithArguments(*CmdString, Ar, Executor, bForceCallWithNonExec);
}
22 changes: 5 additions & 17 deletions Source/MetaCheatManager/Public/MetaCheatManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#pragma once

#include "GameFramework/CheatManager.h"
#include "MetaCheatManagerInterface.h"
//---
#include "MetaCheatCommand.h"
//---
Expand Down Expand Up @@ -46,17 +47,14 @@
*/
UCLASS(Config = "MetaCheatManager", DefaultConfig)
class METACHEATMANAGER_API UMetaCheatManager : public UCheatManager
, public IMetaCheatManagerInterface
{
GENERATED_BODY()

public:
/** Returns all cheat commands exposed by this cheat manager.
* @see UMetaCheatManager::AllCheatCommands */
UFUNCTION(BlueprintPure)
const FORCEINLINE TArray<FMetaCheatCommand>& GetAllCheatCommands() const { return AllCheatCommands; }

/** Returns the cheat command associated with specified CheatName meta value. */
UFUNCTION(BlueprintPure)
virtual const FMetaCheatCommand& GetCheatCommandByCheatName(const FName& CheatName) const;
virtual const FORCEINLINE TArray<FMetaCheatCommand>& GetAllCheatCommands() const override { return AllCheatCommands; }

protected:
/** Contains all cheat commands exposed by this cheat manager.
Expand All @@ -67,9 +65,6 @@ class METACHEATMANAGER_API UMetaCheatManager : public UCheatManager
/** Is overridden to initialize all cheat commands on editor startup. */
virtual void PostInitProperties() override;

/** Called when CheatManager is created to allow any needed initialization. */
virtual void InitCheatManager() override;

/** Is overridden to convert a meta CheatName 'Your.Cheat.Name'
* to the function name 'YourCheatFunction' to process the call whenever user enters the command. */
virtual bool ProcessConsoleExec(const TCHAR* Cmd, FOutputDevice& Ar, UObject* Executor) override;
Expand All @@ -78,12 +73,5 @@ class METACHEATMANAGER_API UMetaCheatManager : public UCheatManager
virtual void BeginDestroy() override;

/** Is bound to return all initialized meta cheat commands to see them in the console. */
virtual void RegisterAutoCompleteEntries(TArray<FAutoCompleteCommand>& Commands) const;

/** Finds and saves all cheat commands marked with 'CheatName' metadata.
* @warning its implementation is editor-only
* since we don't have access to any meta data in builds,
* but you can override it to use your own implementation.
* @see UMetaCheatManager::AllCheatCommandsInternal */
virtual void InitAllCheatCommands();
virtual void RegisterAutoCompleteEntries(TArray<FAutoCompleteCommand>& OutCommands) const override;
};
Loading

0 comments on commit 37ce84d

Please sign in to comment.