Written on January 3, 2018 by Trentv4
This article covers the development of Libraria as it was written, both as a way to keep show my thought process and to organize it as I'm working. This will be heavy on concepts, and light on code, but you will see the results as I work.
So let's get some background information about this project out now. I had a dream, a few years ago now as of this article, about an endless library. This endless place where you could find long forgotten powers, books on any subject, artifacts just left among the shelves, and haunted by the lost souls of those who had died in that realm. I'm pretty sure the idea originally came from the realm of Hermaeus Mora from the Elder Scrolls games, Aprocrypha. I know this idea originated before Skyrim came out, because there's a lot more detail in that article than I had before today. I dropped the idea in a text file (looooong gone) and forgot about it. Later the Library of Babel came up which fit pretty well, and I dropped that in the file too and forgot about it. At some point I mentioned it to my friend JamiesWhiteShirt, who I bounced some ideas off and wrote down some of his. I wish I had that text file so I could properly attribute who did who.
Both of us do Minecraft modding, although he is far more prolific than I am. Eventually JamiesWhiteShirt actually sat down and fleshed the idea out. After a while and a few teaser pictures, he abandoned it and I picked up the idea. I stole the textures shamelessly. You can see the images he posted in the previews right below. Go ahead, click for more details on each image.
Looks pretty neat to me.
Working from this image, we have a pretty solid foundation of this dimension called Libraria. You can see four distinct zones: charred, wet, some sort of white polished stone (marmor), and classic wooden. Those will become biomes, of sorts. It looks from those images that these zones are constructed out of prefabs, in 8, 16, and 32 block cubed prefabs.
I want Libraria to be part of a greater whole in this mod. The dream is to have several unique dimensions sprouting off Libraria, but those particular ones are outside the scope of this endeavor. For now, I'll mention that they are the Smudged City (located in the burning section, hush hush), an ocean dimension (aptly found in the soaked section), the wood section for the Overworld, and Libraria's own rewards in the marmor section.
There's also a really cool book you can see in one of those images, which is used to transport to and from the dimension. This entire idea is JamiesWhiteShirt, as is this implementation. I retained it in my version. I woulld like there to be unique books for each dimension you use to transport between it and Libraria.
Looks pretty neat to me. There's more I want to put in the dimension, but this works for now. The rest would just be iterating.
So, worldgen. I've never touched it in Minecraft before, so let's open up a new repository and see what our restrictions are. By the way, it's open source if you want to follow along, roughly. Minecraft generates worlds on a chunk by chunk basis, which are [16, 256, 16] in size. There's a couple stages in chunk generation, but right now I'm only really concerned with placing terrain. This means I'll primarily working with something called a ChunkPrimer, which only grants me access to a 16 * 256 * 16 of block states. No entities, no tile entities, so on and so forth. Super high performance compared to a World though, which is what I'll probably need here. Most clock time will be in actually generating the zones.
If I'm going to make this dimension out of prefabs, there should be a way to copy what is built ingame and then place it during world generation. IF ONLY THERE WAS A WAY TO DO THAT IN VANILLA. I had the option of either using Structure Blocks and the underlying Template system, which is what vanilla uses, or I can write my own parser, serializer, storage format, deserializer, et cetera...
I chose the Template system. Obviously. I'm a lazy sort of guy.
So what's the issue with Template systems? There's two main limitations. Templates can only support an area of 32 cubic blocks, which severely limits the area we can use prefabs for. Vanilla gets around that by using several templates for the same structure and being really careful in placing them (see: Woodland Mansions). In that case, well, not quite as careful - sometimes rooms in woodland mansions don't quite line up, have coherent entrances, and so on. If there was some sort of meta information, this wouldn't be an issue. Almost as if I should have rolled my own...
The other issue with Templates is that all the information in it is strictly private. All blocks, all entities. Normally this isn't an issue. The proper way to use Templates is to pass a World into Template#addBlocksToWorld and Template#addEntitiesToWorld. However, when I'm working on generating chunks, it's before I have a World to pass into it. The data is stored in Templates as a private List
Bah. I hate it when people try and stop me from letting me do what I want. Normally my options would be limited to reflection, which cuts into the performance I'm trying to optimize for here. Luckily, MinecraftForge has an amazing feature called Access Transformers, which lets me set the access at the decompilation level. You can read more at the wonderful Darkhax tutorial.
I'm going to credit the whole next technique to JamiesWhiteShirt, because he came up with it and I don't think he implemented it. The first attempt at generating Libraria is using an octree structure. Just to refresh you, an octree is a tree where each layer has 8 entries. The entry is either a room, or another list of 8 entries down to a minimum size.
The technique here is to start at the largest square area we want to generate as a "Zone", traverse the tree, and at every instance decide to randomly place either a room or another layer half the size and recurse. This will result in a structure where you ideally have a balance of every room size.
However, this isn't ideal. Done correctly, this results in a very very very tightly packed world generation of a [64, 64, 64] block (or a [4, 4, 4] chunk) area. This makes it difficult to observe and tweak, particularly when you get down to playing with random values to balance the number of rooms. It also means you're generating a lot of rooms, with a lot of repeat prefabs. The solution to that is to sometimes generate empty space, or create a lot of prefabs which will increase workload dramatically.
It is also wise to consider the mistakes of vanilla. There's only one really good example of lots of structure blocks together in vanilla, which is the Woodland Mansion. Consider this excerpt from the wiki page:
It would be a massive headache to make sure every room lines up with every other room. It's possible to do this within the same zone by doing two passes on every available room, but once you start working with nearby zones, you start running the risk of runaway world generation plus the massive headache and edge cases for a technique I'm really not a fan of anyway. Next!
ayy lmao gotta work on actually implementing this first
Alright. Let's see what we're working with.
Good selection of materials. So we know from the generation section that we can only use 8^3, 16^3, and 32^2 due to limitations in vanilla structures. That's okay, it works for me... for now.