Aug 10, 2025, 05:43 AM | |
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:
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. |
![]() |
«
Previous Thread
|
Next Thread
»
Thread Tools | |
|
|
All times are GMT -8. The time now is 08:32 AM.
Jazz2Online © 1999-INFINITY (Site Credits). Jazz Jackrabbit, Jazz Jackrabbit 2, Jazz Jackrabbit Advance and all related trademarks and media are ™ and © Epic Games. Lori Jackrabbit is © Dean Dodrill. J2O development powered by Loops of Fury and Chemical Beats. Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Original site design by Ovi Demetrian. DrJones is the puppet master. Eat your lima beans, Johnny.