Register FAQ Search Today's Posts Mark Forums Read
Go Back   JazzJackrabbit Community Forums » Open Forums » General Jazz Jackrabbit Talk

3hks, why they happen, and what could be done about them

Stijn

Administrator

Joined: Mar 2001

Posts: 6,971

Stijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to behold

Aug 10, 2025, 05:43 AM
Stijn is offline
Reply With Quote
3hks, why they happen, and what could be done about them

One of JJ2's most enduring multiplayer bugs is one where the player is killed by a bullet that does less damage than the health they seem to have. This is commonly called a '3hk' or '2hk', i.e. a three-heart kill or a two-heart kill, because the player thinks they have (for example) three hearts of health, but are then killed by e.g. a powered-up bullet that should do two hearts of damage at most.

Communication between servers and players: UDP and TCP
To understand why this occurs, it helps to have a bit of background knowledge about how data can be sent over a network. This is what JJ2 does, in the end; the server sends data about bullets, health, player position, et cetera, to the client (the player's computer). The client, for example, gets some data from the server indicating that they have been hit by a bullet; or that a certain player (possibly the client's own player!) has died.

Communication between client and server, in JJ2's case, comes in two main flavours: UDP and TCP. Both are protocols for sending packets of data back and forth between computers.

For our purposes here, the most important difference between the two is that with TCP, the recipient of a packet needs to acknowledge receiving it; if there is no such acknowledgement, the packet is re-sent. Meanwhile, UDP packets are simply sent without care for whether they are received properly or not. TCP also contains some features to ensure packets arrive in the correct order; UDP does not.

With that in mind, TCP seems like the superior protocol, but the extra security comes at a cost; it takes some time to handle the acknowledgement of receipt, et cetera, so when it is important to decrease latency as much as possible, UDP can be an attractive option too. In multiplayer games, latency is never desireable, which is probably why back in 1998 Arjan Brussee chose UDP as the protocol for sending around multiplayer data in JJ2.

One of the types of packets sent via UDP in JJ2 is the 'bullet hit packet', a packet informing the client that a player has been hit by a bullet, and how much damage that bullet did. Upon receiving this packet, the client will e.g. update the player's health, and play the relevant animation and sound.

Why the bug occurs
You can see how this could go wrong; if the packet is not received properly, the health is not updated, and from the perspective of the client, the player still has the same health as before (e.g. three hearts). Meanwhile, from the server's perspective, the player's health has decreased (e.g. to one heart). If the player is then hit again, the server recognises that they have been killed, and sends another type of packet to tell the client that they have been killed and should, again, play the relevant animations and sounds, and do all the other things that happen when you die. But from the player's perspective, they went straight from three hearts to dying; which is of course confusing and feels unfair.

Possible solutions
How could this be solved? Two obvious solutions come to mind:
  1. Use TCP instead of UDP to synchronise player data, to ensure everyone always has the correct information.
  2. Send extra packets - with either TCP or UDP - just to synchronise player health. Even if one doesn't arrive occasionally, the health would still be updated with a small(er) delay.

Solution 1- use TCP instead of UDP - could increase latency, and in any case is a substantial change to JJ2's net code, which could have all kinds of unforeseen side effects and is a lot of work.

Solution 2 is less likely to introduce additional latency, but tricky to get right - you would need to ensure health updates are handled in the correct order, that the packet is handled correctly and doesn't just update health but also has all the side-effects of an ordinary health update, et cetera.

Since this is difficult to do right and any change in this area is likely to be somewhat controversial, JJ2+ still mostly works with the original net code written by Arjan Brussee in this area. What JJ2+ does change at the moment is that in vanilla JJ2, sometimes 'player hit' packets would not be sent at all, e.g. when hitting a 'hurt' event, and that would easily lead to desynchronisations. It is more straightforward to fix this, by sending a packet when necessary. But a more fundamental solution has not been worked on so far.

Prospects
Mutators have been developed that use AngelScript to send information about health from the server to clients, on top of what JJ2(+) communicates by itself. AngelScript always uses TCP for data transmission, so this is more reliable; but for reasons described above, implementing this on a more fundamental level is less straightforward. Depending on the implementation, it can also leave room for the development of cheats, because the mutator can send the health data outside of the mechanisms JJ2+ implements for ensuring health information is restricted (as part of the 'anti-radar' feature).

Bottom line: there is a general understanding of why this bug occurs, but fixing it comprehensively is difficult and comes with trade-offs that may be controversial.

Last edited by Stijn; Aug 10, 2025 at 05:55 AM.
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On

Forum Jump

All times are GMT -8. The time now is 08:26 AM.