Behind the Scenes¶
In this section, you will learn how to keep your RPG or mini dungeon game clean, fancy, and modularized.
Area persistent data¶
You can assign data to an area during the generation process.
We can use this feature to randomize the spawner in our dungeon.
// server script
ServerEvents.recipes(event => {
LoquatPlacements.register("any_key_you_like", new LoquatTreeNodePlacer("pack:big_dungeon", ctx => {
// add monster rooms
let monsterRooms = []
// ctx.root is the start room according to the structure json file
let lastRoom = ctx.root
for (let i = 0; i < 5; i++) {
// lastRoom.addChild(target_name, template_pool_name)
monsterRooms.push(lastNode = lastRoom.addChild("door", "pack:monster"))
}
// add boss room
lastRoom.addChild("door", "pack:boss")
// add treasure room
monsterRooms[ctx.random.nextInt(monsterRooms.length)].addChild("door", "pack:treasure")
let spawners = ["zombies", "skeletons", "creepers"]
monsterRooms.forEach(room => {
// we don't want the entrance and exit to be too close, so we set a minimum distance
room.minEdgeDistance = 8
// we don't want two rooms are the same, so we make a unique group id for them
room.uniqueGroup = "monster"
room.data = {
spawner: "pack:" + spawners[ctx.random.nextInt(spawners.length)]
}
})
}))
})
LoquatEvents.playerEnteredArea(event => {
let data = event.area.persistentData
let tags = event.area.tags
if (data.contains("spawner") && !tags.contains("spawned")) {
event.player.runCommandSilent(`loquat spawn ${event.area.uuid} ${data.spawner}`)
tags.add("spawned")
event.areaManager.setChanged([event.area])
}
})
The aftercare¶
When the players finish the level, we want to be able to clean up all the stuff that we generated, for future generations. Here is the solution:
First we need to tag all the areas that will be generated along with our structure:
// server script
ServerEvents.recipes(event => {
LoquatPlacements.register("any_key_you_like", new LoquatTreeNodePlacer("pack:big_dungeon", ctx => {
ctx.globalTags.add("big_dungeon")
// ...
}))
})
Then write code to clean them up if necessary:
// server script
function clearDungeon() {
Utils.server.runCommandSilent(`execute in minecraft:overworld run loquat empty @a[tag=big_dungeon]`)
Utils.server.runCommandSilent(`execute in minecraft:overworld run loquat delete @a[tag=big_dungeon]`)
}
Dynamic processor assignment¶
A processor list is a list of processors used to affect blocks in structures, such as replacing blocks.
You can assign a processor list to a node (piece) during the generation process.
// server script
node.lowPriorityProcessors.add(ResourceLocation.tryParse('pack:replace_diamond'))
// or node.highPriorityProcessors, depending on whether you want to
// process blocks before or after the structure is rotated and mirrored
data/pack/worldgen/processor_list/replace_diamond.json:
{
"processors": [
{
"processor_type": "minecraft:rule",
"rules": [
{
"input_predicate": {
"block": "minecraft:diamond_block",
"predicate_type": "minecraft:block_match"
},
"location_predicate": {
"predicate_type": "minecraft:always_true"
},
"output_state": {
"Name": "minecraft:obsidian"
}
}
]
}
]
}