Multiplayer, Player Hiding, and Cheating - security risk ?

Let’s say I wanted to make a MOBA game where some players can hide in bushes so others can’t find them.

From what I found w/e you do all the clients will still know all other players locations, it just won’t render them.

Isn’t that a security risk? Players can now cheat and extract that information, and now know when the players are even when they’re hiding.

Is there a way around it? am I missing something?

If the actor is hidden then the Actor is not relevant and the server will not bother sending updates for it unless if the actor collides with something relevant.

@GarnerP57 Actually that’s partially true, and still problematic:

(1) Hidden in game is not enough for actor not to be replicated, it also needs to have collision disabled.
Otherwise you can override


IsNetRelevantFor

in cpp and return false yourself when it’s not relevant.

(2) The result is not immediate. When IsNetRelevantFor return false after returning true, a channel for the actor will be closed.
But that closing is not immediate and there’s a timeout, so replication will still be sent for a short duration when changed.

@matan19 For ESP/wallhack etc you’re going to have to look at mitigation/server-side detection/arbitration instead of prevention. There’s no other cost effective approach to be had at this time. Especially for indie devs.

Look at games like PubG, WarZone, CoD, Battlefield…CSGO. They are inundated with cheats. These are games that spend millions on client-side cheat software, anti-cheat engineers, reverse engineering, patching etc. A week after they patch for specific cheats the cheats are updated and working again (ESP, Wallhack, Radar).

PubG (UE4 based game) recently started encrypting there updates (replication data) to stop middleware esp/wallhacks. Clients were routing through VPN’s that would sniff the packet and provide a radar map for another device to display. It worked for about a week. The longstanding approach is using DKOM to read game memory directly. The data can then be sent to another device on the local network (phone, laptop, pc, tablet etc) and display a radar map, a 1:1 view with esp overlay and so forth.


Hiding a player in an attempt to limit or outright stop replicating information would not work. Current cheats simply mark a players position frame to frame. In this regard they’d simply maintain a mark on the last known position.

Ever had a game lag out for a second or two? Did you notice that other players stopped moving? Last known position! Same applies to cheats.

@Rev0verDrive your not making much sense;

Why would one want to spend millions on client-side anti-cheat software, to prevent clients from sniffing data that they’re not suppose to have to begin with,
when you can simply not send the data? it doesn’t make any sense at all…

I feel as if you don’t understand the fundamentals as to how games work. I also feel your calling every AAA developer stupid as if they’ve never thought about this concept, nor tried it. If not sending data had zero repercussions then it would be in wide use.

If you’re proposing that as long as your hidden by geometry (LoS) you can move without sending updates then you have a very long road ahead of in the learning department. I’d highly recommend you dig into character/pawn development, client-side prediction, replication etc. You’re extremely out of your depth at this juncture.

@Rev0verDrive Don’t do that. Writing a post in a forum that’s suppose to help people and share information, and saying
“you don’t know what you’re talking about, go learn”, without giving any actual information or links, doesn’t help anyone and will drive the community down.
In those cases it’s better if you just don’t write anything.

Anyway, just to clarify, I am talking about server not sending updates to other non-relevant clients, not about the owner of it.

Also, here’s an actual article from Riot Game about implementing exactly what I wanted, in Unreal Engine, for anyone who’s interested.

What Valorant did is excellent. But they did it in a 10 player arena shooter. This isn’t something that can be done by the average/above average indie dev. Nor is it feasible for all games. For example 32 - 100+ player games on large maps. The compute times would decimate server tick.

Another factor you have to look at is avg player latencies, loss, variance. Some games … Battlefield, CoD, PubG, Warzone etc have player latencies as high as 500ms mixed with pings in the teens or less. With high pings your looking at players being up to 9 frames ahead of the server (outright malicious peekers advantage).

There’s also the issue of audio == update. Valorants system replicates if the player makes a sound that could be heard (within attenuation range). If your game uses a lot of player movement/item sounds (spawn at location), then valorants approach would send an update in these scenarios … regardless if occluded.

e.g. reloading, changing attachments, footsteps, equipment rustling, dropping/picking up loot, equipping an item, healing/meds, firing, throwing an item etc etc.

Everyone of these conditions would fire off a positional update. Which for the most part negates the intended purpose of the replication overhaul. The only time it would be completely effective is if the client didn’t move (but last known still works), or at long distances.

There’s a lot of factors that must be considered to determine if “some x feature functionality” is feasible or not. tech debt, implementation costs, running costs, performance etc.

/* cast: resurrect thread L1 */
@
matan19
hello, sorry for disturbance, don’t you accidentially find how to get rid of delay after returning false from isNetRelevantFor?

For anyone else: i understand that this decision will bring bunch of additional problems. I just need to find that lever which allow immediately stop replication. Or confirmation that for some reason that is totally impossible in UE

Keep talking to myself.
Found “RelevantTimeout=5.0” in inis. It looks like it the reason – it is used in NetDriver.
But… Either i try to set it in the wrong place(s) or this is just not our princess. Okay, think i can rebuild engine few times per today and maybe found something.

Have tried to replace RelevantTimeout with 0.5 right in code of engine’s netdriver. It cause Player Controller’s to contantly destroy and create (or something happend that look like this). Las few days trying to make minimal class inherited from NetDriver to conditionally decrease RelevantTimeout only for my own character class. It’s hard thou. I have 10 years long brain javascript :confused: Fighting with c++ and compiling…

Making of custom Net Driver seems unbearable for me. Too much errors. Last one was LNK2019: unresolved external symbol for FActorPriority. Even If i copy it to my net driver header file, rename, and use it. But…

Finally, i found solution that seems viable. As i can’t include own headers in engine’s files (can’t find how), so i can’t compare classes. So i compare name of classes and conditionally use constant timeout of 1.0s for my units.

In UnrealEngine\Engine\Source\Runtime\Engine\Private\NetDriver.cpp i replaced this:

const bool bIsRecentlyRelevant = bIsRelevant || ( Channel && ElapsedTime - Channel->RelevantTime < RelevantTimeout) || (ActorInfo->ForceRelevantFrame >= Connection->LastProcessedFrame);

with this:

FString actorName = *Actor->GetName();
double timeout = actorName.StartsWith(TEXT("GameUnit")) ? 1 : RelevantTimeout;
			
const bool bIsRecentlyRelevant = bIsRelevant || ( Channel && ElapsedTime - Channel->RelevantTime < timeout ) || (ActorInfo->ForceRelevantFrame >= Connection->LastProcessedFrame);

If use timeout less then 1 then something breaks and objects start flickering (creating/destroying). But one second is way much better than five. It leaves much less space for making decent wall hacks (sort of).

MAYBE something will break because of this change. Will see. I’ll report if found problems.