With the RPC_Validate, is that check and disconnect performed on the client that is trying to send bad data, or on the server which is receiving it, or both?
If it is client-side there’s a chance that code could be adjusted by a cheater, if it is server-side then we don’t save any packets (the rpc data is still transmitted) so it’s just a small convenience (we could validate the arg in the _Implementation).
However, if it’s done on both, that would be very useful and a lot less code.
Validation is performed on the server. The server is the source of truth and is the only true place where it can be validated. It is handled via the RPC when validation is on.
So is there any difference between writing a validation function and just adding the validation into the serverrpc function? Feels like they’re both equivalent.
There is. The engine handles the validation if you do the validation function and prevents execution of the replication. This guarantees your replicated data is correct and shuts out cheaters, or at least is the first stage to this.
That’s a good thought. If I made a web app I would do Validation on the front end, the API, and the db.
This was strait forward to test. I added a debug message
bool ATCoOpAdventureCharacter::ServerRPCFunction_Validate(int MyArg)
{
int32 PlayInEditorID = GPlayInEditorID;
GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Yellow,
FString::Printf(TEXT("Client %d is validating..."), PlayInEditorID));
if (MyArg >= 0 && MyArg <= 100)
{
return true;
}
return false;
}
It’s only run on the server like Beegeedee said.
However, if I change the Reflection specifier from Server to Client
UFUNCTION(Client, Reliable, WithValidation, BlueprintCallable)
Then it’s run on the client.
I’m assuming Multicast does both, but IDK I haven’t gotten there yet. Disclaimer, I haven’t seen the Client or Multicast RPC videos yet, and I have no prior knowlege. It’s really strange to me that it only ran on the client, but I’m sure it will make sense when I get there.
The big thing I noticed is a _Validate function boots a player from the game (there maybe a way to handle this differently). I would imaging there’s validation that doesn’t warrant a boot that goes into the _Implementation or before the RPC is called.
Imagine player presses the throw grenade key, but doesn’t have any more grenades. Do you boot the player, or just don’t let him throw a grenade? What if he picked up a grenade and immediately threw it and what if the ‘picked up grenade packet’ got lost on a router queue somewhere or got to the server late? If you boot every player that does something like that, you’ll have a inexpensive EC2 instance.
Also the Docs say the _Validate is now mandatory, but I commented mine out and it compiled, something to keep an eye out for.
I would say in the implementation. Something like clamping values could be in there to prevent outrageous values like super jumps and the likes.
I found the docs on the various options and nothing here says _Validate kicks the player when they cheat. The original premise of the validation was to ensure a move was valid and if it was, proceed to the implementation. Of course, that doesn’t mean it doesn’t behave like this.
RPCs | Unreal Engine Documentation
I do see in the compendium from Cedric that it disconnects the caller but I don’t recall this happening in UE4 so if it does, it’s a UE5 feature. His docs, aside from a few additional hints, are basically the same as the unreal docs.
This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.