Issues with using TheNexusAvenger's buffer technique for projectile weapons

I’m trying to get the classic brick battle tools (eg rocket, superball, etc) to be as responsive as possible on the client. My first attempt was to use the conventional way of doing things, with the server waiting for the remote event the client fires. However, for a game like brick battle that was built around non-FE, this response time is really unacceptable (averaging at about 300 ms).

Last, I tried TheNexusAvenger’s buffer technique. This is essentially just exploiting a replication quirk. The server pre-creates the projectile with a BodyPosition out in the middle of nowhere, with the firing client as the network owner. The firing client can then retrieve it by locally destroying the BodyPosition and signaling the server to do the same, allowing other clients to see the firing client move it around. The server is responsible for handling damage through a Touched event on the projectile. While this works great for response times, I discovered it doesn’t work perfectly.

The issue with this approach is lag. Let’s say a player with a 300 ms ping fires a superball projectile. Once the remote event’s signal arrives the server has to reenact ~300 ms worth of the projectile’s trajectory. The Touched event only “wakes up” sometime after this reenactment, 9 times out of 10 missing the target player getting hit. Maybe the events only fire once the server is certain it’s done catching up?

A demonstration. Server on the left and client lagged at ~300 ms on the right. I start with a superball using TheNexusAvenger’s technique. Notice how the humanoids are only damaged after the “wake up” of about 300 ms. About half way in, I use a superball that only invokes the server.

I’d really like some help with knowing whether this is unavoidable or if I’m just missing something (after all, this technique was used in the official 2018 ROBLOX Deathbattle rewrite). I’m using Studio settings > Network > IncomingReplicationLag to simulate my lag. Could the lag simulation be causing my problem?

3 Likes

I have seen this before too. I am assuming you have made it that the super ball clones a damage script inside of it. Which the script has to load in while being thrown, but if there is lag the super ball will not do any damage. Perhaps the damage control should go in the same script creating the ball.

Actually, because of the buffer system, the damage script is always inside of the projectile, just waiting to be used. It uses WaitForChild to wait for the main server script loading in necessary components (configuration, a PlayerDamager script) once it fires it. I don’t see how the amount of time it takes to put these components inside could be responsible for this kind of lag.

1 Like

Why is physics ownership of the projectile being given to the client? Not only is this a security flaw, but it also causes a pause in movement on the server while the client receives the new projectile, removes the BodyPosition, and updates its position. The resulting effect is essentially the same as giving clients control of projectiles but moving the discrepancy caused by latency mid-flight instead of pre-flight. It also requires complicated manual collision detection for the simulated projectile path or it must ignore close targets and greatly complicates the entire process.

If physics ownership was left to the server, the security issue would be resolved and the pause in movement would be removed. This is close to the optimal solution in an enforced server-client model (clients can’t communicate with each other), however it still has the complexity of simulated collision detection, is still exploitable, and the visible discrepancy between clients is not minimized. Other players being shot at must have super-instantaneous reaction times because the server favors the attacker’s view of the world. The attacker’s actions are fast-forwarded but the reactions and movements of the victim are not. Even if they were, they may arrive at the server after the collision is detected when the movement would have caused the projectile to be cleared. Instead of imbalancing the players and opening up the ability for attackers to fake their latency and therefore cause their shots to jump forward more, simply to not fast-forward attacks and start them when the server receives the action. This way a balance is maintained between an attacker thinking they made a shot and actually miss and victim thinking they dodged a shot and are actually hit (it doesn’t eliminate one while increasing the other). This is also much simpler, less bug-prone, exploit-proof, and less computationally intensive.

TL;DR:
The conventional way of doing things is actually the time-tested, simplest, and optimal way of doing things. The client sends a message to the server, and the server fires and owns the projectile. Each alternative method will introduce side-effects and/or exploitable features. If you want to make the client more responsive, look into trying to make the client state match the server state, not the server match the client states.

1 Like

Good arguments! I enjoy discussing these things, so let me address some of your points, one by one:

Why is physics ownership of the projectile being given to the client? Not only is this a security flaw, but it also causes a pause in movement on the server while the client receives the new projectile, removes the BodyPosition, and updates its position.

That’s what the buffer is for. When the tool first loads into a player’s backpack, the server will create a projectile, accessible to the client who fires the weapon. It will automatically set the network owner to that client once he equips the weapon, to minimize the “pause” in movement you’re referring to. Setting the network owner would have to be done anyway with brick battle tools (see my point further down on why that is). At any point, he can pull this projectile from the buffer, minimizing the need for the server to create it on demand. After firing, it reloads a new projectile in the buffer, for him to use it at his disposal after the reload time is up.

It also requires complicated manual collision detection for the simulated projectile path or it must ignore close targets and greatly complicates the entire process.

This is correct. Having possible incorrect trajectory because targets were in a different state when the client fired it is a natural cost of this method and others like it, unfortunately. :l

Other players being shot at must have super-instantaneous reaction times because the server favors the attacker’s view of the world. The attacker’s actions are fast-forwarded but the reactions and movements of the victim are not.

If I understand your point correctly, you’re saying the client who fires it is at a natural advantage because of the ping overhead. If he fires the projectile, the others’ reaction times would have to be less than the ping for the projectile to replicate plus the amount of time for the projectile to reach them. But the damage is dealt with on the server, so their version of the projectile will be exactly as if there were no ping overhead. The only disadvantage I can think of is if when the projectile is catching up on the server it was sped up somehow to compensate, which I don’t think it does.

The conventional way of doing things is actually the time-tested, simplest, and optimal way of doing things.

I agree. In fact, I’ve decided against using this method since it is as you said, fairly useless for most applications. I’ve instead decided to create a fake superball on the client, with the “real” superball being created on the server for handling damage and other clients’ visualization. It opens the possibility of incorrect visualization (for example, if a player just clips a target on the client but ends up missing it on the server), but otherwise it just feels wrong.

Another reason brick battle should have clients own the projectiles is all of the interesting combos; superball + bomb equaling a bombshot, jumping on slingshot pellets to climb up a wall, etc, that people who play the game rely on. If it took place on the server, ROBLOX wouldn’t be intelligent enough to know a superball hitting a bomb should send it flying, I suppose because of lag.

Thanks for the points to think about, it was food for thought.

2 Likes