Jump to content

[1.12] Cascading worldgen lag during structure generation


JoieNL

Recommended Posts

Hello fellow modders,

 

Currently I am working on a mod that, among other things, adds a Frozen Nether dimension. In this dimension, I want to generate Frozen Nether Fortresses. These structures look just like the normal variants, except, well, frozen. To create these structures, I have copied code from vanilla's MapGenNetherBridge and StructureNetherBridgePieces classes, and just changed some blocks. The structure is used in ChunkGeneratorFrozenHell (which also takes after the vanilla version) and registered in my ModStructures class.

 

Now for the issue. When I move around in the Frozen Nether, I experience extreme amounts of lag, and the structures only spawn one part in one chunk (always the Crossing). I've looked around already, and I know what causes this. The structure is trying to generate in unloaded chunks. This makes Minecraft load a large amount of chunks quickly, resulting in - as the console calls it - cascading worldgen lag. And because things cannot generate in unloaded chunks, only a single piece of the structure is actually generated.

 

I may know the cause of my problems, but what I cannot find is a descriptive solution. People are saying to generate the structure as the chunks are loaded, but I have no idea how I would go about this. Any help would be greatly appreciated. For reference, the classes involved can be found on my GitHub (some of them are too big to post here directly): https://github.com/JoieNL/Winter-Is-Here.

 

These classes are potentially important:

StructureFrozenNetherBridgePieces (in /world/gen/structure/).

MapGenFrozenNetherBridge (in /world/gen/structure).

ModStructures (in /world/gen/structure).

ChunkGeneratorFrozenHell (in /world/gen).

 

Thanks in advance!

Link to comment
Share on other sites

You may already know this but here is more information on what causes cascading worldgen: https://www.reddit.com/r/feedthebeast/comments/5x0twz/investigating_extreme_worldgen_lag/?st=jjge6795&sh=f1603e42

 

 

The key point is: 

Quote

Decoration is only fired when a chunk's +X, +Z, and +XZ neighbors have loaded already. Vanilla offsets all its worldgen so that it generates in the middle of these 4 loaded chunks, which greatly reduces the chance of accidentally overflowing into unloaded chunks.

and the solution is:

Quote

Correct world generation offsets everything by +8, +8 so that all generation happens in the middle of the loaded chunks, and has a low chance of spilling out.

 

If you look at the vanilla world gen you'll often see a +8 or similar in the locations.

 

To debug your problem, I would add console statements that, at each place where you generate a block in your worldgen, right before you place the block, print out the x, y location and also whether the chunk is already loaded or not. Actually, that might print out too much, so instead maybe have it print out only if the chunk is not already loaded. 

 

Basically you need to debug the cascading. One thing to think about as well is you can't have to much randomness in your x, y positions or it will greatly increase the chance of cascading. You should basically offset everything by +8, +8 and allow no more than 8 blocks of randomness.

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

Thanks for the quick reply.

I had indeed already had a look at this post and read about the offsetting by (8, 8). But I don't think this is the problem. I believe that vanilla methods like MapGenStructure#generateStructure handle that:

int i = (chunkCoord.x << 4) + 8;
int j = (chunkCoord.z << 4) + 8;

I think things are going wrong because pieces of the structure (and with pieces I mean StructureFrozenNetherBridgePieces.Pieces) are being generated in unloaded chunks when they should not.

I believe that pieces that are awaiting generation are stored in StructureFrozenNetherBridgePieces.Start#pendingChildren and generated in MapGenFrozenNetherBridge.Start like such:

List<StructureComponent> list = structurefrozennetherbridgepieces$start.pendingChildren;

while (!list.isEmpty()) {
    int i = random.nextInt(list.size());
    StructureComponent structurecomponent = list.remove(i);
    structurecomponent.buildComponent(structurefrozennetherbridgepieces$start, this.components, random);
}

My hypothesis that somehow all pieces of the structure end up in this list when the first crossing is initialised and everything tries to generate at once. Does anyone know how this could be?

 

 

Edit: I should've definitely checked this before I made this post... Printing the list after it is initialised reveals that it is always empty of all things:

[13:37:16] [Server thread/INFO]: [STDOUT]: []

Does this mean that all the structure pieces generate even before entering this list? It would explain why it remains empty. I will conduct further research regarding this finding.

 

 

Edit again: I did some more testing and it turns out that this list was empty because things were passing null all over the place. Bottom line is: IntelliJ was trying to be a smartass, replacing this...

return isAboveGround(structureboundingbox) && StructureComponent.findIntersecting(p_175882_0_, structureboundingbox) == null ? new StructureFrozenNetherBridgePieces.Straight(p_175882_6_, p_175882_1_, structureboundingbox, p_175882_5_) : null;

...with...

return null;

...for every piece.

 

Now that that's solved, the entire structure spawns, but the cascading worldgen lag remains. I'll continue my investigations.

 

 

I keep having to edit this post: I've 'turned off' all world generation features for my dimension except fortresses, and the cascading worldgen lag is gone. This means that there has been something besides the fortresses causing lag as well. I will now turn all features on again one by one to see if I can determine which of them causes the lag.

 

One last edit: All is well now! I figured out this line was the culprit:

this.lavaTrapGen.generate(this.world, this.rand, blockpos.add(this.rand.nextInt(16), this.rand.nextInt(108) + 4, this.rand.nextInt(16)));

So I added an (8, 8) offset and things are working fine now! Thanks again for the help jabelar.

Edited by JoieNL
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.