0
\$\begingroup\$

I am creating a 'Minecraft clone' and the game is going to be only multiplayer. I currently have a limited world (it's not going to be infinite) that is 512 chunks.

Each chunk is 16(X) * 16(Z) * 128(Y) of blocks.

Each block is represented by a byte. This means I have a 3D array of bytes that represents which block is in which position in the chunk (0 means Air). I got to the part where I want to send the world though the TCP connection.

I am using KryoNet for my multiplayer needs. Currently what I do is I flatten the 3D array to the highest Y coordinate that is not air, making my (16 * 16 * 128) array into a (16 * 16 * less than 128) array. After doing this I take the 3D array and flatten it into a 1D array. After doing that I have a 1D array of size ~32,000. Obviously sending the entire 32KB of data through the connection at once is stupid and it also crashes KryoNet.

My question is how would I efficiently go about sending 512 chunks (512*32 KB of data) through the connection?

I thought about separating the 1D array (32,000 bytes) into 32 packets each of 1KB of data but it seems odd to send 512 * 32 packets to send the world (~16,000 packets). Is there any way to compress this data or send it in a more efficient way through my TCP connection? Obviously this is done once per session but still 16,000 seems a lot.

Progress update:

I have separated the chunks into 33 packets each, and I send them one after the other. It seems to be working well, but I have a slight ordering issue that is unrelated. At the times that it works it loads quite quickly and with no problem! If there is a more efficient way of going about this please do post it here!

\$\endgroup\$
  • \$\begingroup\$ Why do you think it would crash KryoNet? When you download a file with a web browser, you can transfer gigabytes of data via TCP/IP. \$\endgroup\$ – Philipp Feb 7 '15 at 13:35
  • \$\begingroup\$ Yeah but not at once. It does crash Kryo. It cannot serialise so much data at once. \$\endgroup\$ – George Cloone-y Feb 7 '15 at 14:45
1
\$\begingroup\$

Besides splitting up the data in multiple packets as you've already proposed, you could try 2 more things:

The first (and simplest) is to do run length encoding on the data.

Run length encoding is when, instead of saying "Stone,Stone,Stone,Air,Air,Air" you say "3,Stone,3,Air". In typical minecraft style maps that saves a lot of data and it is used in most games like it.

Besides run length encoding, if you're dealing with this much data, and data for which latency isn't that big a deal, try using a generic compression algorithm!

Java already has an implementation for GZIP, try sending the data to a memory buffer via a GZIPOutputStream and sending that data, it should be a lot smaller. (Speed wise, this is something that can rather easily be done in another thread so it shouldn't affect the game much)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.