Skip to content
damios edited this page Oct 12, 2018 · 4 revisions

The functionality of quakemonkey

A game state

The following game state should get sent to the server every tenth of a second.

public class GameStateMessage {
	public List<Integer> position;
	public List<Integer> orientation;
}

It is serialized via the following method (you can also use Kryos default serializers if you don't want to build your own):

output.writeShort(msg.position.size()); // A short indicating the number of integers following
for (int i = 0; i < n; ++i) {
	output.writeInt(msg.position.get(i)); // Write each position value
}

output.writeShort(msg.orientation.size()); // A short indicating the number of integers following
for (int i = 0; i < n; ++i) {
	output.writeInt(msg.orientation.get(i)); // Write each orientation value
}

Notable: In the table below you will see that the integer 2 converts to the following four bytes (in hex notation): 02 00 00 00. The wrong order (on first sight) is because of Kryo and nothing to worry about. Another thing you will see in the table is, that each serialized object is preceded by 13. This is an identifier for the serialized class (in this case GameStateMessage).

An example

Delta-Snapshot Compression

Instead of all 29 bytes of the new state a delta message is sent, consisting of a header (11001001 <- read right to left) indicating which byte-blocks (= 4 bytes = 1 integer) have changed and the changed byte-blocks itself (in hex: 13 03 00 02, 00 00 00 03, 00 07 00 00, 00 00 00 00). In this simple example this leads to a reduction in size of around 40 %. In real-life scenarios, if your game state includes more data the reduction-rate can easily go over 95 %.

Further reading

  • For more on the inspiration of this lib, the Quake 3 network code, see here
  • For more techniques involving snapshot compression take a look at this post
Clone this wiki locally