Jump to content

Recommended Posts

Posted (edited)

Hey, I'm really new to structure gen and have had nothing to go off of other than the source code of mods and the game itself and I think I'm close to getting it to work. However, when I create a new world, it gets stuck at loading world building terrain.

 

Here is my WorldGen class

Spoiler

package com.ninja3659.explorationexpansion.world.gen;

import java.util.Random;

import com.ninja3659.explorationexpansion.world.gen.structure.WorldGenHouse;

import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkGenerator;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.feature.WorldGenerator;
import net.minecraftforge.fml.common.IWorldGenerator;

public class NeemWorldGenerator implements IWorldGenerator {

	private WorldGenerator house = new WorldGenHouse();
	
	@Override
	public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider) {
		switch(world.provider.getDimension()) {
		case -1:
			break;
		case 0:
			generateOverworld(house, world, random, chunkX*16, chunkZ*16, 10);//you want x16 so that the structure isn't just generated near the origin
			break;
		case 1:
			break;
		}
	}//called any time a chunk is generated
	
	private void generateOverworld(WorldGenerator gen, World world, Random rand, int x, int z, int chance) {
		int randX = x + rand.nextInt(16);//takes the 0/16/32/48 and adds random number between 0 and 15 to have it spawn in any chunk
		int randZ = z + rand.nextInt(16);
		int y = world.getHeight(randX, randZ);
		
		for (int i = 0; i < chance; ++i) {
			gen.generate(world, rand, new BlockPos(randX, y, randZ));
		}
		
	}
	

}

 

 

And here's my WorldGenerator houseGen class

Spoiler

package com.ninja3659.explorationexpansion.world.gen.structure;

import java.util.Random;

import com.ninja3659.explorationexpansion.util.Utils;

import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.WorldGenerator;

public class WorldGenHouse extends WorldGenerator{
	public boolean isReplaceable(World world, BlockPos pos) {
		IBlockState state = world.getBlockState(pos);
		return state.getBlock().isAir(state, world, pos) || state.getBlock().isLeaves(state, world, pos) ||
				state.getBlock().isWood(world, pos) || state.getBlock() == Blocks.DIRT || 
				state.getBlock() == Blocks.GRASS || state.getBlock().getMaterial(state) == Material.PLANTS;
	}//determines if a block is replaceable
	
	public boolean generate(World world, Random rand, BlockPos pos) {
		int width = 9;
		int length = 9;
		int height = 6;
		
		boolean flag = true;
		
		if(pos.getY() >= 1 && pos.getY() <= 256) {
			for (int hc = pos.getY(); hc <= pos.getY() + height; ++hc) {
				
				int coordcheck = 1;
				
				if(hc == pos.getY())
					coordcheck = -1;//this is one inside
				
				
				BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
				
				for (int checkx = pos.getX() - coordcheck; checkx <=pos.getX() + coordcheck + width; ++checkx) {
					for(int checkz = pos.getZ() - coordcheck; checkz <=pos.getZ() + coordcheck + length; ++checkx){
						if (hc >= 0 && hc < world.getHeight()) {
							if (!this.isReplaceable(world, blockpos$mutableblockpos.setPos(checkx, hc, checkz))) {
								flag = false;
							}//if the place at the checking coords is not replaceable, then fuck it
						}//last check to see that it is in bounds
						else {
							flag = false;
						}//if the check point is out of bounds, then why are you even here
					}//does the same for y
				}//checks the block before the position and the one at the end of the x
			}//Check every layer of the structure
			
			if (!flag) {
				return false;
			}//if flag is false, then your sol
			else {
				//else you somehow managed to survive that, good job
				
				for(int ch = 0; ch <=height; ++ch) {
					for (int cx = 0; ch <=width; ++cx) {
						for (int cz = 0; cz <=length; ++cz) {
							this.setBlockAndNotifyAdequately(world, pos, Blocks.STONEBRICK.getDefaultState());
							Utils.getLogger().info("Built a house boss! at: " + pos.getX() + ", " + pos.getY() + ", " + pos.getZ());
						}//go through x
					}//go through z
				}//go through the y
				
				
				
				
				return true;
				
				
				
			}
		}//then it passes the in world test
		else {
			return false;
		}//if you didn't make it through the first step, bro u didn't have a chance
		
	}
	
	

}

 

 

I may be way off, but I haven't found an up to date tutorial that explains in as much detail as some of the tutorials I've found about making living entities.

Edited by GooberGunter
Posted

Ok....so you registered a world generator that possibly generates a house 10 times per every chunk that gets loaded. In the exact same place as it was the first time it generated in that chunk. Also i think your house is a 9 * 9 * 6 prism of stone brick. Try Not generating it 10 times every chunk and instead make it only appear in 1/50 chunks by removing the for loop in NeemWorldGenerator#generateOverWorld.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted (edited)

OH! What was I doing?! 

 

I changed it up a bit, making the chances for it to render lower, but still having the problem

 

private void generateOverworld(WorldGenerator gen, World world, Random rand, int x, int z, int chance) {
		int randX = x + rand.nextInt(16);//takes the 0/16/32/48 and adds random number between 0 and 15 to have it spawn in any chunk
		int randZ = z + rand.nextInt(16);
		int y = world.getHeight(randX, randZ);
		
		Random r = new Random();
		
		if(r.nextInt(chance) == 0);
			gen.generate(world, rand, new BlockPos(randX, y, randZ));
		
	}

 

Wait. Nevermind. The if statement wasn't enclosing generate. 

 

When do you use a chunkprovider?

 

Also if anyone knows of any good generation tutorials, could you link them? Thanks

Edited by GooberGunter
Posted

Ok so I updated the classes to: 

GenHouse

Spoiler

package com.ninja3659.explorationexpansion.world.gen.structure;

import java.util.Random;

import com.ninja3659.explorationexpansion.util.Utils;

import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.WorldGenerator;

public class WorldGenHouse extends WorldGenerator{
	public boolean isReplaceable(World world, BlockPos pos) {
		IBlockState state = world.getBlockState(pos);
		return state.getBlock().isAir(state, world, pos) || state.getBlock().isLeaves(state, world, pos) ||
				state.getBlock().isWood(world, pos) || state.getBlock() == Blocks.DIRT || 
				state.getBlock() == Blocks.GRASS || state.getBlock().getMaterial(state) == Material.PLANTS;
	}//determines if a block is replaceable
	
	public boolean generate(World world, Random rand, BlockPos pos) {
		int width = 9;
		int length = 9;
		int height = 6;
		
		boolean flag = true;
		
		if(pos.getY() >= 1 && pos.getY() <= 256) {
			for (int hc = pos.getY(); hc <= pos.getY() + height; ++hc) {
				
				int coordcheck = 1;
				
				if(hc == pos.getY())
					coordcheck = -1;//this is one inside
				
				
				BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
				
				for (int checkx = pos.getX() - coordcheck; checkx <=pos.getX() + coordcheck + width; ++checkx) {
					for(int checkz = pos.getZ() - coordcheck; checkz <=pos.getZ() + coordcheck + length; ++checkx){
						if (hc >= 0 && hc < world.getHeight()) {
							if (!this.isReplaceable(world, blockpos$mutableblockpos.setPos(checkx, hc, checkz))) {
								flag = false;
							}//if the place at the checking coords is not replaceable, then rip
						}//last check to see that it is in bounds
						else {
							flag = false;
						}//if the check point is out of bounds, then why are you even here
					}//does the same for y
				}//checks the block before the position and the one at the end of the x
			}//Check every layer of the structure
			
			if (!flag) {
				return false;
			}//if flag is false, then your sol
			else {
				//else you somehow managed to survive that, good job
				
				
				//floor
				for (int cx = pos.getX(); cx <= pos.getX()+width; ++cx) {
					for (int cz = pos.getZ(); cz <= pos.getZ() + length; ++cz) {
						BlockPos blockPos = new BlockPos(cx, pos.getY(), cz);
						setBlockAndNotifyAdequately(world, blockPos, Blocks.STONEBRICK.getDefaultState());
					}
				}
				
				
				
				return true;
				
				
				
			}
		}//then it passes the in world test
		else {
			return false;
		}//if you didn't make it through the first step, bro u didn't have a chance
		
	}
	
	

}

 

 

World Generator

Spoiler

package com.ninja3659.explorationexpansion.world.gen;

import java.util.Random;

import com.ninja3659.explorationexpansion.util.Utils;
import com.ninja3659.explorationexpansion.world.gen.structure.WorldGenHouse;

import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkGenerator;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.feature.WorldGenerator;
import net.minecraftforge.fml.common.IWorldGenerator;

public class NeemWorldGenerator implements IWorldGenerator {

	private WorldGenerator house = new WorldGenHouse();
	
	@Override
	public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider) {
		switch(world.provider.getDimension()) {
		case -1:
			break;
		case 0:
			generateOverworld(house, world, random, chunkX*16, chunkZ*16, 2000);//you want x16 so that the structure isn't just generated near the origin
			break;
		case 1:
			break;
		}
	}//called any time a chunk is generated
	
	private void generateOverworld(WorldGenerator gen, World world, Random rand, int x, int z, int chance) {
		int randX = x + rand.nextInt(16);//takes the 0/16/32/48 and adds random number between 0 and 15 to have it spawn in any chunk
		int randZ = z + rand.nextInt(16);
		int y = world.getHeight(randX, randZ);
		
		
		if(rand.nextInt(1000) < 1) {
			gen.generate(world, rand, new BlockPos(randX, y, randZ));
			Utils.getLogger().info("here it is at: " + randX + ", " + y + ", " + randZ);

			
		}
	}
	

}

 

I finally got the game to load, but I had to make the spawn chance .1% and I can't find it. The logger isn't logging in these methods either

Posted
51 minutes ago, GooberGunter said:

When do you use a chunkprovider?

If I am not mistaken you do not need a ChunkProvider for Structure Generation.

26 minutes ago, GooberGunter said:

Ok so I updated the classes to: 

I think the biggest problem you have is that you check if the block is replaceable, why? Instead you should get the first ground block at the x, z position you get, and then tell the game to generate your structure. If there are air blocks or plants underneath then simply replace them with a foundation type of block. Kinda like what Minecraft does with it's village buildings, and then clear above your structure by replacing with air. Not all the way up to build height mind you, maybe a couple blocks if the structure is huge and if not clear until there is nothing connected above it.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

Step through your code (and into calls) in the debugger. See if you notice recursion (if your structure spills into another chunk, then that chunk may generate another structure and so-on).

  • Like 1

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

Thanks, I cleared that method up and its spawning in the world, but

 

Animefan8888, how would I go about clearing the blocks above it? is there a specific method? Or do I have to literally make a method that places a bunch of air blocks right before the rest is generated?

Posted
2 minutes ago, GooberGunter said:

Thanks, I cleared that method up and its spawning in the world, but

 

Animefan8888, how would I go about clearing the blocks above it? is there a specific method? Or do I have to literally make a method that places a bunch of air blocks right before the rest is generated?

You will have to make a method to do it, I would not necessarily do it before because then you will have to call World#setBlockState more times than necessary. Instead place your building in the world and then clear the area above it. Also do take into account what jeffryfisher said because what he said can and will happen which causes world gen lag because it can spiral out of control. It is called Runaway Chunk Generation.

  • Like 1

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

So now that I have a better understanding of this. My goal is to have a structure that is about 30x30, could cause runaway chunk generation since it's more than a chunk. So, would this be the case where I use a chunkprovider? If so, how? are there any tutorials on it?

Posted
4 hours ago, GooberGunter said:

So now that I have a better understanding of this. My goal is to have a structure that is about 30x30, could cause runaway chunk generation since it's more than a chunk. So, would this be the case where I use a chunkprovider? If so, how? are there any tutorials on it?

What you will want to do is make a List of ChunkPos that it has generated in. And if the position is to close to one in the list don't generate.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
7 minutes ago, GooberGunter said:

So, I make a list of the chunkPos that the structure spawns in, and set up a boolean that returns false when it's too close to another structure?

Pretty much. At most your structure of 30x30 could belong in 4 chunks. Which means 3 extra chunks are possible when the world is generating, but the problem with that is when it loads those chunks it is possible that, that chunk will also want to generate it there to. There is almost nothing you can do about it taking up four chunks and those chunks generating.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
22 hours ago, GooberGunter said:

how would I go about clearing the blocks above it?

Why would a separate method be needed? Can't a structure include air blocks around and above its  solid blocks?

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

Well yeah, but what I did is I had a new method that had a for loop to replace all blocks in the length width and height of the structure so I could just call a "setBlockState to air" method once. I call this method before I build anything. I just personally find it easier, but maybe this way has its problems

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.