In today's experiment, we have Green Field City from Minecraft versus me on three different accounts connected to the same server watching my fourth account who is going to detonate several megat tons worth of TNT in this nuke. But there's one thing off about this. This isn't Minecraft.
It's my own programming experiment where I attempt to combine Distant Horizons and Cubic Chunks from Minecraft while making it work in multiplayer. Distant Horizons is a Minecraft mod that increases Minecraft's max render distance up to infinity, while Cubic Chunks removes Minecraft's vertical limits. However, these two mods do not work together in Minecraft, which is exactly why I made my own game to create a massive world without build limits or render distance limits, which could also work in multiplayer.
But how exactly does my game work? Let's start with the basics. Pieces of the world are loaded whenever a player goes somewhere and unloaded whenever they get too far away.
These pieces are called chunks, which are regions of 32x 32x 32 blocks. So, there is a sphere of chunks surrounding the player at all times. Beyond this is a bigger sphere of chunks around the player.
There are the same number of chunks in each sphere, and the chunks in each sphere are all 32 blocks wide. However, the blocks themselves are twice as large in the farther sphere, meaning they have a lower level of detail, which is why we will be calling these chunks LODs. The terrain generation simply uses a lower resolution when it generates chunks that are farther away from the player, meaning it only generates one block per 8 cubic m, then one block per 64 cub m, and so on as you get farther.
So, no matter how big the chunk may look, it's still the same number of blocks being generated. This means that the massive regions of land that you see here actually take the same amount of time to generate as the chunks right next to me, allowing me to generate LODs much faster than Minecraft's LOD mods. Unfortunately, terrain is only one part of world generation.
Structures are a completely different problem. Structures can cross chunk boundaries or even level of detail boundaries, which is why I separated structure generation from world generation. Structures are generated before the terrain is generated.
After a chunk is created, we simply see which structures intersect that chunk and copy them onto the chunk. For lower resolution chunks, we simply do the same process, but after downscaling the structure to match the chunk's resolution. The problem is that with thousands of structures, each chunk has to check every structure to see if it is intersected.
This can lead to millions of checks happening at once, resulting in catastrophic lag. To optimize this process, the structures are stored in a bounding volume hierarchy which puts each structure into regions that are divided into regions that are divided into regions and so on. Now when we generate a chunk, we simply find the smallest region corresponding to that chunk and check only the structures in that region to see if it intersects with that chunk.
After that was done, I can finally fly around my densely forested world with massive kilometer high mountain ranges. Now that the Distant Horizons and Cubid Chunks part is completed, it is time to code the multiplayer part. Since I'm using C++ as the programming language, there are none of the networking conveniences seen in C or Java.
And since this is my first C++ project, I had to read a novel on C++ sockets to understand how to send a single message. So, I simply applied this knowledge to create a basic client and server system. This could handle chat messages, block changes, and so on.
There are two main ways this data is sent. TCP or UDP. TCP guarantees that data reaches its destination, which is why I use it for chat messages, login attempts, block changes, and anything else that I don't want the player to miss.
UDP does not guarantee that the data reaches its destination, making it faster but less reliable. So, I use UDP for realtime data like player positions. But when I began sending chunka data over the network, I realized that I would need to keep track of LDS on the server as well.
Let's say we have two players that are a considerable distance away from each other. If player A places a block here, then player B won't be able to see the changes unless we generate LODs around both players and update the LODs whenever the normal chunks get updated, allowing the changes to be visible to everyone. Things were getting extremely messy because LODs can now overlap with normal chunks.
So, after rewriting basically half of the entire game to work with this new change, I now have realtime LOD updates, meaning anyone can immediately see world changes made by players no matter how far away they are. Now, it is time to test this with an actual gaming situation. If you have seen my more obscure videos, you know that I love Greenfield a city, which is why I created a program specifically to convert the green field Minecraft world into something usable by my game.
This is made possible by the fact that the data of Minecraft worlds is stored in MCA files. The format of these MCA files is publicly documented, which I use to translate Minecraft data into my game data. After doing this, I can now explore Green Field the city while being able to see Miles in the distance until I realized that the real way to stress test this game is to see if the world can handle a several megaton explosion.
I created a nuclear bomb that explodes whenever it is right clicked with a blast radius of a few hundred blocks. After loading the world on my server, joining the game, planting the nuclear bomb, and igniting it, I discovered insane lag. After doing some investigation into the cause of this lag, I found the issue.
If we do the calculations, a sphere with this radius has a volume of several tens of millions of units. This bomb is removing 65 million blocks, meaning the server has to tell the player that a certain block has been removed 65 million times. Unsurprisingly, this causes the network to explode.
So, I combined these blockchange notifications into chunk change notifications. The server now tells the player that a few thousand chunks are completely empty. Now, this uses about 32,000 times less data to communicate basically the same thing.
After this improvement, multiplayer is now somewhat playable with nukes. But the journey to get here was actually much longer than what I'm interested in covering in this video. I completely skipped over how I added multi-threading to this game because it is more complicated than I previously thought.
You have probably seen bajillions of gamers complain that Minecraft is single threaded. And the reason why comes down to this. Try writing a program where multiple threads are reading and writing to the same data halfhazardly.
and watch how quickly it crashes and burns. C++ has multiple features to help programmers avoid common multi-threading issues. But because this is my first C++ project, this went horribly wrong.
Now, some of you might be asking, why not use Rust? It's memory safe and blazingly fast. The answer is that I already tried Rust.
I spent a grand total of 5 hours rewriting the game in Rust until I realized that those who sacrifice essential liberty for memory safety deserve neither liberty nor memory safety. Now back to the video. I was actually able to parallelize world generation, which is part of why world generation looks like this and not like this.
I also use SIMD, which stands for single instruction, multiple data to speed up terrain generation by an amount that I don't actually know, but I assume that it was a lot. But I wasn't the only one adding random improvements to this project. A large part of the user interface was designed by Airblow, and grass was coded by an individual known as Chudsell.
Vier was also in this episode. So, I guess after all of this progress, my Distant Horizons Cubid Chunks multiplayer experiment has reached its original goal after an entire year. I have no idea what to do now.
Suggest stuff to add in the comments and I will genuinely consider these suggestions goodbye.