Unreal Cheat Manager In Multiplayer
[ue4
]
Running cheat commands on the server requires a bit of setup, as the cheat manager is not an actor and therefore not replicated.
I’ve solved this by creating a component, called UServerSideCheatsComponent, that I attach to the player controller. Whenever I add a command to the cheat manager I add a method with the same signature to this component, mark it up so that it runs on the server and simply call that from the cheat manager.
The code I’m showing here is accessible on GitHub: https://github.com/snorristurluson/UnrealChat
Setting up the cheat manager
Let’s set up a very simple cheat manager, with the Bingo cheat command that prints Bongo to the log:
UCLASS()
class UNREALCHAT_API UMyCheatManager : public UCheatManager
{
GENERATED_BODY()
public:
UFUNCTION(Exec)
void Bingo();
};
void UMyCheatManager::Bingo()
{
UE_LOG(LogTemp, Display, TEXT("Bongo"));
}
I have a Blueprint class for the player controller, so I set the cheat manager to use in the editor.
Let’s start the game up in multiplayer:
Using backtick (or whatever key you have configured) to open the console, we can type in Bingo - the console shows completion of the command as we start typing it, but this shows up in the log:
Cmd: Bingo
Command not recognized: Bingo
Obviously the cheat manager is not getting called, even though the console seems to have some knowledge of the command. Note that if you set the Net Mode to Play Standalone the command will work correctly.
Enabling cheats in multiplayer
After a fair bit of head scratching and reading through Unreal Engine source code, I came to the conclusion that not only is the cheat manager not replicated, but by default, it is not active at all in a multiplayer game. In order for it to work in a multiplayer game, you have to add a bit of C++ code to the player controller.
void AMyPlayerController::PostInitializeComponents()
{
Super::PostInitializeComponents();
EnableCheats();
}
void AMyPlayerController::EnableCheats()
{
AddCheats(true);
}
This class can then be set as the base class for the Blueprint class for the player controller. This will enable the cheats for both singleplayer and multiplayer setups.
Forwarding calls
This setup still only allows us to run cheats on the client - a bit more work is needed to forward the calls to the server. Note that it is not enough to add the Server function specifier to the function declaration as the cheat manager is not replicated - it is not an actor, and only actors are replicated.
To get around this, I’ve added a component I can attach to the player controller that can forward the calls.
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class UNREALCHAT_API UServerSideCheatsComponent : public UActorComponent
{
GENERATED_BODY()
public:
UServerSideCheatsComponent();
UFUNCTION(BlueprintCallable, Server, Reliable, Category="Cheat Manager")
virtual void Bingo();
};
And the .cpp file:
UServerSideCheatsComponent::UServerSideCheatsComponent()
{
SetIsReplicatedByDefault(true);
}
void UServerSideCheatsComponent::Bingo_Implementation()
{
if (GetOwner()->HasAuthority())
{
UE_LOG(LogTemp, Display, TEXT("Bongo on the server!"));
}
}
This implementation also prints to the log, but only if the owner (the player controller) has authority, just to show that the call indeed made it to the server.
Then we change the cheat manager to call this function:
UServerSideCheatsComponent* UMyCheatManager::GetServerSideCheats() const
{
return Cast<UServerSideCheatsComponent>(
GetPlayerController()->GetComponentByClass(UServerSideCheatsComponent::StaticClass()));
}
void UMyCheatManager::Bingo()
{
GetServerSideCheats()->Bingo();
}
I’ve extracted the code for getting the server side cheats component into a function - this will be called by all the cheat commands that end up getting added to the cheat manager and should be forwarded to the server.
See also
benui.ca is an excellent resource for Unreal Engine tutorials - there is a tutorial there on the cheat manager, but it does not go into multiplayer issues as I’ve covered here.