Dungeon Generation (Like Mineshaft)

Started by Starobino on

Topic category: Help with modding (Java Edition)

Last seen on 16:52, 11. Mar 2024
Joined Dec 2023
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Dungeon Generation (Like Mineshaft)

Hey everyone,

I work at a VR Arcade in the UK, and we have started using MCreator to teach kids about coding. Basic stuff so far, like making their own mobs and weapons ect.
Myself and my colleague have been trying to work on structured classes for next year, and to do that, we decided to make structures into a randomly generated dungeon.
I have been working on this for the past few months and have had ample opportunities to learn from the vast wealth of knowledge in this program, and the insanely talented people who work with it! I would love to personally tap that font, for I am a bit stuck.

The idea is to make a large series of structures that the kids will populate with their own custom mobs, traps, and loot. I have personally been working on two different kinds of structure, and I am having some trouble with its generation. To make this easier to follow, we have Old and New Dungeons. 

Old Dungeon is made up of 8 individual 19 x 19 x 19 cubes (I shall see if I can get a picture in here somewhere). It comprises of a Crossroads, a corner for each direction, 2 straights and a 'loot' hall. It was made to toy with the idea of how they would generate. Initially I made a separate block that would just spawn the thing when destroyed. I used this video to do so, and my code is the same (https://youtu.be/2sfqLgUR2Tw?si=FkgooUZqe4IP1aqf) This kinda worked, but got complicated with the number of rooms I had, so I simplified my design to New Dungeon.

New Dungeon is big. Its 38 x 38 x 38. I basically made it to be 4 rooms in a square in two floors. This would make 8 rooms, a condensed version of Old Dungeon. I also made an entrance for it, which was basically a surface house, with stairs down into it. Nothing fancy, just for testing. Under the same code as above, it worked well. But the issues occurred when it would overlap dungeons that were already there. 
Its about here I found this post (https://mcreator.net/forum/62582/guide-random-generated-structures), which was insanely helpful, and prompted another angle. I tried all the variants of the code examples, and started using Ticks to help generate the structures. This unfortunately led to a similar overlapping issue. 

The next thing I tried was Jigsaw blocks. Using this video (https://youtu.be/5a4DAkWW3JQ?si=E8KzFEw0S733QCnh) I used the Old Dungeon to map up for use with Jigsaws. Following all the examples I saw on the video and with the various other Jigsaw posts on here, I was unable to generate anything! And with the sheer complexity of making them work (or at least attempt to work for me) would go clear over the heads of the kids I am supposed to teach this to. So I gave up, and tried more with Tick generation.

My most recent attempt is using the Old Dungeon and Ticks to generate something that just doesn't overlap, and as such, I have had no success. I need something in my code to see that there is a dungeon already there, and so, not place one down. I have multiple sheets of A4 full of notes documenting it all, and I know this is a mega long post already (apologies!). 
I would just love to get some more direction on this. The main goal here is to generate something akin to an Abandoned Mineshaft, full of stuff the kids make, that fits together into this randomly generated madness! For clarity, they are quite large simply because these kids are great builders, so I wanted plenty of room to give them the chance to show off a bit! They can be smaller if that is what is needed. If there was a way for me to share my Workspace files, I would be more than happy to do so as well.

Thank you for all the help you have given me to get this far! Hopefully with more of that help, we can get this working too!

Last seen on 20:37, 26. Jul 2024
Joined May 2022
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Yeah, jigsaw blocks are kind…
Fri, 12/29/2023 - 13:33

Yeah, jigsaw blocks are kind of overrated. They're useful, but very limited in how they can function. I also came across the idea of using world features instead of structures, and using modded blocks to place them post instead of pre generation- I also recently finished overhauling mineshafts! Hopefully I can help out a bit, MCreator sounds like a great teaching resource. Here's an example of an early generation test, using modded blocks to randomly select halls/rooms, and then randomly place furniture, cobwebs, rubble, etc.

Looks kind of messy, but the basic idea is similar to what you came up with- there's a large central room, and then it generates hallways and rooms in a grid pattern, with the rooms randomly being a dead end, corner, t-junction, or shaft; and the halls randomly being a straight hallway, stairway, or split stairway. In order to avoid worrying about y-axis intersections, the central room is always at the bottom, and the shafts and stairways always lead upwards.

There's still the problem of making sure a hallway or room doesn't accidentally generate where there's already a room or hallway. As long as you're doing this post generation, (so a world feature that places your modded block, instead of an actual structure), you can use a recursive procedure to check a box for a block. (There's even a 'check for block in 6*6*6 box procedure template that explains the idea pretty well.) Each of the hallway-selector blocks checks for wooden planks directly adjacent to it to determine the rotation and offset of the hallway, and also checks in a rectangular box in that direction for wooden planks, or other obstructions. (Such as lava, or sky access, indicating the mineshaft is too close to the surface.) If it finds an obstruction, it generates a dead end hallway instead that cuts off immediately. 

Some other issues I ran into:

  • It's tricky (but not impossible) to determine whether a room/hall is underground or in a cave. To avoid making even more random structure variants, These ones work either way, and have additional generator-blocks that use recursion to randomly place support beams above or below them if they're in air. 
  • Aquifers are also a nuisance. I used a custom generator block that vanishes and then simply replaces adjacent fluid blocks with cobblestone, and then used those on all the ceilings and walls.
  • ...And of course this will generate totally out of control if you don't have an end condition. I made an invisible marker entity that spawns in the central room, and despawns after 20 ticks or so, depending on the amount of tick delay you have on your generators. The likelihood of choosing a hallway or junction instead of a dead end is determined by how far away the generator block is from the nearest marker entity, and immediately hits zero when no entity is found. (So the mineshaft is densest nearer to the center.) 

Anyways, good luck with the teaching! I've been working on this procedural structure idea for way too long now, and it's as fun as it is frustrating. Minecraft is a great tool just by virtue of how accessible it is, but it can quickly become troublesome just by how complicated modding can become, both as a result of how old the game is, and how many volunteer-run third party tools you need to mod it... but best wishes! Maybe consider looking into Gamemaker Studio too, it's another great free game-design tool with decent teaching value and accessibility.

Last seen on 16:52, 11. Mar 2024
Joined Dec 2023
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Thank you for the reply! My…
Wed, 01/03/2024 - 16:56

Thank you for the reply!

My collegues tell me they get what you are talking about, which is a relief!

I however, am still struggling with it. I think this time I have managed to add some images. One should show the code that I have managed to figure out by myself, and another is the result of its generation.
Can you tell me what I am doing wrong? 

Last seen on 16:52, 11. Mar 2024
Joined Dec 2023
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
(No subject)
Wed, 01/03/2024 - 17:01

Last seen on 20:37, 26. Jul 2024
Joined May 2022
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
You've got the right idea! I…
Wed, 01/03/2024 - 18:36

You've got the right idea! I'd just give a couple of pointers:

  • Don't use a global variable for the center timer, otherwise you're going to run into problems if multiple dungeons try to generate at the same time. You can spawn an invisible entity in the dungeon's center, and then have your procedures check if such an entity exists in a certain radius. This has the added bonus of letting you always be able to use the center of the dungeon and the distance from the center to determine the dungeon's generation.
  • In terms of your problem, I think you need to change the way you're generating each section of the structure. Here's the basic idea:

Structures! Yay!

(Oops, the bottom left corner is supposed to be N/E, forgot to change it!)

  • You can build your generator blocks into your structures, like so, and then use which corner they're in to determine where to generate the next structure, and with what offset/rotation. If you always place a block on the left hand side of where you want the path to continue, then there will only ever be four possible configurations it can be in. (You can use the adjacent cobblestone blocks to determine which corner the generator is in.) 
  • In order for this to be a bit easier, I recommend making a gamerule that determines whether or not your generator blocks do anything on update tick. This way you can turn it on and off while in the game, depending on whether you're building with them, or testing the generation, and you can have one world where the generator blocks don't do anything, (so that you can build with them), and another where they do, (so you can test that they're working.) It took me an embarrassingly long time to do this, before which I was just manually disabling the code every time I wanted to test anything.
  • Your other issue is that your structures are overriding each other. Each time a segment of your dungeon generates, it replaces each of the adjacent four spaces with a new room- including the room that it generated from. This will be partly fixed by having the blocks built into the structure, but there's still the chance that a hallway winds all the way back around and cuts through existing rooms. For this, I recommend using a modified version of the 'check for block in 6*6*6 box' procedure template to check for cobblestone where the structure is trying to generate, then only generate the structure if cobblestone isn't found in that box. This should prevent your pathways from intersecting.
  • And lastly, use more procedures! Usually my advice is to try to condense things as much as possible, but in the case of something like this, with a lot of moving parts, it's easier to fix and edit things if you have a separate procedure for each step of the process. (Also, at least in older versions, MCreator slows down when you reference a lot of structure files in one procedure. I don't know why, but it's annoying.) In your case, you could have a separate procedure whose sole purpose is to randomly choose from a list of structures and place them in the world; or multiple, different procedures for different room types, rotations, etc. (This way you don't have big bulky sections of code in your generation procedure devoted to picking structures, and you can also edit the chances of each structure being chosen without having to worry about messing with the larger scale generation.)

Good luck, it looks like you've made a lot of progress already! I could also send examples of my generation code, if that would be helpful?

Last seen on 16:52, 11. Mar 2024
Joined Dec 2023
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Thank you very much! This…
Wed, 01/03/2024 - 18:43

Thank you very much! This has been a mixture of YouTube videos and help from on here, so I am just happy it makes sense!
I would LOVE to see how you have done it, if that's possible. Still learning a lot of this myself, so as soon as I can see how it's done, and I can understand how its all connected, the hope is, I can teach the kids the same stuff!
So yeah, any code pictures and examples would be VERY much appreciated!
 

Last seen on 20:37, 26. Jul 2024
Joined May 2022
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Sure thing. Here's some…
Wed, 01/03/2024 - 19:40

Sure thing. Here's some examples of the actual structures:

The first one has structure voids turned on, just to demonstrate that these will work underground or above ground. The orange floating blocks are structure voids, (they assume the form of whatever was already there), blue floating blocks are air, and the red ones are a block of my own design, which becomes solid if there's water or lava adjacent. (To prevent leaks.) The generator blocks are kind of hard to tell apart, but the ones on the pillars continue the pillars up or down if there's air above them, the one under the rail in the first image generates a room in the direction it's facing, and the ones with the pink blocks behind them in the second image generate a hall. (The pink block is just to simplify determining which direction the block is facing, it's replaced with oak planks once the hallway generates.) The rooms and hallways are also a very specific size so that everything lines up properly in a grid. (You don't have to worry about this if your dungeon is all box-shaped rooms, but keep in mind, as long as the paths line up, you could make more complex arrangements with halls, larger rooms, etc.) 

This is the first, (well, technically the second) procedure run by the first generator block. The entire structure is saved as a single block, which is generated underground. (There's another procedure that gives the block an update tick when the world feature generates, since naturally generated blocks don't tick by default, but this is the first important procedure.) If the gamerule is true, (it can be disabled so I can build using the generator blocks), it first replaces the original generator block, then checks for another gamerule. (I use this one so that players can configure the likelihood of different structures.)

If both pass, it waits a random amount of time before calling the build procedure.  Since I don't want two mineshafts generating nearby, I need to check the surrounding area for other mineshafts- I randomize the delay before checking so that if two mineshafts generate next to each other, one is likely to generate first and prevent the other one from generating. Not an ideal method, but works most of the time. (Also not something you need to worry about if you don't want your dungeons to generate naturally.)

This is the second procedure, which the first procedure calls. It again makes sure the gamerule is enabled, then calls 'mini-village-scanner,' which runs a larger check in the nearby area and on the surface for other structures. (Again, to prevent structures from generating nearby.) If we've determined there aren't any structures nearby, I then do a sort of 'tolerance check' to determine whether the nearby area is suitable for a mineshaft. (And not, say, the middle of a lava lake.) This uses the 'check for block in 6*6*6 box' procedure template I mentioned, but modified for a 30*16*30 area, roughly the size of the mineshaft center. It increases a local variable every time a location in that box is lava, tagged as 'structure blockable,' or exposed to the sky, and then only allows the mineshaft to generate if the variable is below a certain number.

...That's all mostly related to determining whether or not it should generate, which probably isn't your main concern, but useful if you're planning on it at some point.

Once we know the mineshaft is going to generate, we choose the type of mineshaft based on the biome, (there's three different types for warm, cold, and temperate biomes), set a local number variable to a random number to determine which variant of the mineshaft center to generate. (this is the same thing as the random chance you use, it's just easier to keep track of probability.)

...And that's about it. Everything else is the individual generator blocks in each section of the mineshaft deciding whether or not to add another room, what type of room to add, and how to rotate it. They use a check that looks something like this:

Which is basically just the 'check for block in 6*6*6 box' procedure template again. This is what determines whether or not a new room/hall is added, or a dead end is added. You do, however, either need multiple versions of this depending on which direction you need to check; or need to call this with an offset each time you check. In this case the box size is 16*12*16, the size of the room/hall structures.

From then on, if this returns true, there's a bunch of additional procedures that just randomly choose which structure to place. I've locked each of them and made duplicates set to slightly different directions and offsets, and then just call the correct room-selector procedure depending on the type of room and direction to generate it.

Hope some of this is helpful!

Last seen on 20:37, 26. Jul 2024
Joined May 2022
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
BTW, I've been doing some…
Thu, 01/18/2024 - 15:19

BTW, I've been doing some experimenting with 2023.4, and updating will very much break structures generated in this manner. It is still possible to lock the mod elements and manually return them to their previous versions, (I've also been looking into using entities in true structures instead, as these will tick even when naturally generated), but just a heads up if you plan on updating, might be a bit of an extra headache.

Last seen on 16:52, 11. Mar 2024
Joined Dec 2023
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Hey again!Thank you for the…
Mon, 02/19/2024 - 17:39

Hey again!

Thank you for the heads up! And apologies for the radio silence! 
We are swiftly coming up to the point where we will be trying this out, and as such, I am working on the worksheet for the specific code needed to generate the 8 rooms together into a little dungeon! 
Currently we are on the newest version, and have yet to get it working still. Though I am told by my colleagues that it still is doable!

Last seen on 20:33, 8. May 2024
Joined Feb 2024
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
This Was Insanely Helpful…
Mon, 02/19/2024 - 18:08

This Was Insanely Helpful even to me Thank you for Making this forum post , you all are life savers!!!!

Last seen on 20:37, 26. Jul 2024
Joined May 2022
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Code copied from stuff…
Tue, 02/20/2024 - 21:55

Code copied from stuff compiled in the previous version will still work in the latest version of MCreator, but you then need to edit the Java code directly- you can also sort of do the same thing with world features in the latest version. I've been told a more effective method in the latest version of MCreator is to use an entity to begin the structure generation process, since these tick by default, but haven't tried it myself. I've just been copying a template 'custom structure block that schedules an update tick of itself' from the older version of the mod, and then just doing the actual code editing on the block itself.