Solved Generate a Flat Square via BlockPopulator in a map

Discussion in 'Plugin Development' started by Xenon117, Nov 1, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    Xenon117

    Hey Guys,

    I just want to know how I actualy implement a WorldGenerator and ord a BlockPopulator which generates a flat square of Blocks surrounded by an normal terrain.
     
  2. Offline

    FTWinston

    Well if you want to use the existing ChunkGenerator (i.e. the default world), then you'll want to listen for the WorldInitEvent, and add a BlockPopulator of your own to the list returned by the world's getPopulators method.

    How big do you want your square to be, and do you want to fill in all of the terrain under it (e.g. with stone)?

    If you want the square to be the size of one chunk, at 0,0, and you do want to fill it all in, then (assuming the height of the top is at y=80) I'd have your BlockPopulator's populate method look something like this:


    Code:
    public void populate(World world, Random random, Chunk chunk)
    {
        if ( chunk.getX() != 0 || chunk.getZ() != 0
            return;
       
        for ( int x=0; x<16; x++ )
            for int z=0; z<16; z++ )
            {
                for ( int y=80; y>0; y-- )
                    chunk.getBlock(x,y,z).setType(Material.STONE);
                for ( int y=81; y<chunk.getWorld().getMaxHeight(); y++ )
                    chunk.getBlock(x,y,z).setType(Material.AIR);
            }
    }
     
  3. Offline

    Xenon117

    But I want to smooth out the edges. That code only generates a flat square with hard edges and if you are in a big mountain biome the edges look really weird.
     
  4. Offline

    Hoolean

    :confused:

    Don't squares generally have hard edges? Or do you want a circle?
     
  5. Offline

    Xenon117

    i need at least a flat square, but there should be smoothed out edges.

    think about a mountain biome and you generate a flat square at y = 64. Then you get a loot of edges that do not look natural. i wannt to smooth out these "walls"
     
  6. Offline

    Hoolean

    Code:
    public void populate(World world, Random random, Chunk chunk)
    {
        int smoothness = 16;
        if ( chunk.getX() != 0 || chunk.getZ() != 0
            return;
     
        for ( int x=0; x<16; x++ )
            for int z=0; z<16; z++ )
            {
                for ( int y=80; y>0; y-- )
                    if(chunk.getBlock(x,y,z).getLocation().getDistance(world.getBlockAt(new Location(world, 0 , y,  0))<smoothness) {
                          chunk.getBlock(x,y,z).setType(Material.STONE);
                    }
                for ( int y=81; y<chunk.getWorld().getMaxHeight(); y++ )
                    chunk.getBlock(x,y,z).setType(Material.AIR);
            }
    }
    The lower the value of smoothness, the smoother it will be!
     
  7. Offline

    Xenon117

    No i dont want a square or this type of edge smoothing you showed me.
    [​IMG]
    The Diamonds are my generated flat square and i want these walls to be smoothed out, so it looks natural
     
  8. Offline

    FTWinston

    Oh so you want your square to be sunk into the rest of the world, as opposed to raised above it?

    You'll need to extra code to handle the surrounding chunks, and change blocks to air if they're low down & close by.

    The following ought to work for 1 chunk in each direction - if you need it extended further, it should be straightforward to extend this. Note that it's not tested: some of the slopes might go in the wrong direction.

    Code:
    public void populate(World world, Random random, Chunk chunk)
    {
        int surfaceHeight = 64;
        if ( chunk.getX() == 0 )
        {
            if ( chunk.getZ() == 0 )
            {// lowered platform
                for ( int x=0; x<16; x++ )
                    for int z=0; z<16; z++ )
                    {
                        for ( int y=surfaceHeight; y>0; y-- )
                            chunk.getBlock(x,y,z).setType(Material.DIAMOND_BLOCK);
                        for ( int y=surfaceHeight+1; y<chunk.getWorld().getMaxHeight(); y++ )
                            chunk.getBlock(x,y,z).setType(Material.AIR);
                    }
            }
            else if ( chunk.getZ() == 1 )
            {// sloping edge
                for ( int x=0; x<16; x++ )
                    for int z=0; z<16; z++ )
                        for ( int y=surfaceHeight+1+z; y<chunk.getWorld().getMaxHeight(); y++ )
                            chunk.getBlock(x,y,z).setType(Material.AIR);
            }
            else if ( chunk.getZ() == -1 )
            {// sloping edge
                for ( int x=0; x<16; x++ )
                    for int z=0; z<16; z++ )
                        for ( int y=surfaceHeight+17-z; y<chunk.getWorld().getMaxHeight(); y++ )
                            chunk.getBlock(x,y,z).setType(Material.AIR);
            }
        }
        else if ( chunk.getX() == 1 )
        {
            if ( chunk.getZ() == 0 )
            {// sloping edge
                for ( int x=0; x<16; x++ )
                    for int z=0; z<16; z++ )
                        for ( int y=surfaceHeight+1+x; y<chunk.getWorld().getMaxHeight(); y++ )
                            chunk.getBlock(x,y,z).setType(Material.AIR);
            }
            else if ( chunk.getZ() == -1 )
            {// diagonal sloping edge
                for ( int x=0; x<16; x++ )
                    for int z=0; z<16; z++ )
                        for ( int y=surfaceHeight+Math.min(1+x, 17-z); y<chunk.getWorld().getMaxHeight(); y++ )
                            chunk.getBlock(x,y,z).setType(Material.AIR);
            }
            else if ( chunk.getZ() == 1 )
            {// diagonal sloping edge
                for ( int x=0; x<16; x++ )
                    for int z=0; z<16; z++ )
                        for ( int y=surfaceHeight+Math.min(1+x, 1+z); y<chunk.getWorld().getMaxHeight(); y++ )
                            chunk.getBlock(x,y,z).setType(Material.AIR);
            }
        }
        else if ( chunk.getX() == -1 )
        {
            if ( chunk.getZ() == 0 )
            {// sloping edge
                for ( int x=0; x<16; x++ )
                    for int z=0; z<16; z++ )
                        for ( int y=surfaceHeight+17-x; y<chunk.getWorld().getMaxHeight(); y++ )
                            chunk.getBlock(x,y,z).setType(Material.AIR);
            }
            else if ( chunk.getZ() == -1 )
            {// diagonal sloping edge
                for ( int x=0; x<16; x++ )
                    for int z=0; z<16; z++ )
                        for ( int y=surfaceHeight+Math.min(17-x, 17-z); y<chunk.getWorld().getMaxHeight(); y++ )
                            chunk.getBlock(x,y,z).setType(Material.AIR);
            }
            else if ( chunk.getZ() == 1 )
            {// diagonal sloping edge
                for ( int x=0; x<16; x++ )
                    for int z=0; z<16; z++ )
                        for ( int y=surfaceHeight+Math.min(17-x, 1+z); y<chunk.getWorld().getMaxHeight(); y++ )
                            chunk.getBlock(x,y,z).setType(Material.AIR);
            }
        }
    }
     
  9. Offline

    Xenon117

    looks far better, but not natural as well. I think i should use a SimplexOctave Noise Generator for this purpose. (btw it is possible to change block values in other chunks via world.getBlockAt() )
     
  10. Offline

    Hoolean

    Maybe it would be better of you tell us what you are trying to make? It might help with our suggestions.
     
  11. Offline

    Xenon117

    I want to spawn a City in the middle of a World. its about 144x165 blocks big. And It should look like its natural, with smooth blended edges and so on.
     
  12. Offline

    Hoolean

    Ah! Do you want it to be on the top of the land? I think I have a way of doing that! It would be almost flawless! I'm busy at the moment but I will post it soon!
     
  13. Offline

    Xenon117

    its not as easy as its sounds like.... i got the highest surrounding block ans spawned the city/flat square with the same height.... but it doesnt look right.
     
  14. Offline

    Hoolean

    I will post it soon! I will do it how I think the Minecraft villages do it.
     
  15. Offline

    Xenon117

    Just to clarify.
    [​IMG]

    the red square is the generated flat square and the surrounding environment should be adapted to the flat surface.

    (Just ignore the cathedral )
     
  16. Offline

    Hoolean

    What should the flat surface be made of? The blocks that should be there?
     
  17. Offline

    Xenon117

    Grass
     
  18. Offline

    Hoolean

  19. Offline

    chaseoes

    You could try looking at WorldEdit's source to see how they handle the //smooth command.
     
  20. Offline

    Hoolean

    Oh wait! I see what you mean now... Smoothing it might be harder unfortunately, although getting the platform a better height might be easier.
     
  21. Offline

    Xenon117

    i could add the height of all surrounding blocks and add them together and divide it by the number of surrounding blocks and smooth it out with the smooth code from worldedit. i could do it in 10 or 20 iterations.
    Or do i have a big mistake in my theory?
     
  22. Offline

    Hoolean

    That would work yeah! I am also considering a way where you get the values of each block at the side and somehow smooth it out from there.
     
  23. Offline

    Xenon117

    Anybody knows something about Gaussian Blur? i could use it for this purpose?

    Ok Guys, I've got a solution.
    Code:
    private void blurOne( World world, int x, int z ){
            float weight = 0;
           
            weight += world.getHighestBlockYAt(x  , z-3) * 0.1;
            weight += world.getHighestBlockYAt(x  , z-2) * 0.1;
            weight += world.getHighestBlockYAt(x  , z-1) * 0.1;
            weight += world.getHighestBlockYAt(x  , z  ) * 0.1;
            weight += world.getHighestBlockYAt(x  , z+1) * 0.1;
            weight += world.getHighestBlockYAt(x  , z+2) * 0.1;
            weight += world.getHighestBlockYAt(x  , z+3) * 0.1;
           
           
            weight += world.getHighestBlockYAt(x-3, z  ) * 0.1;
            weight += world.getHighestBlockYAt(x-2, z  ) * 0.1;
            weight += world.getHighestBlockYAt(x-1, z  ) * 0.1;
            weight += world.getHighestBlockYAt(x  , z  ) * 0.1;
            weight += world.getHighestBlockYAt(x+1, z  ) * 0.1;
            weight += world.getHighestBlockYAt(x+2, z  ) * 0.1;
            weight += world.getHighestBlockYAt(x+3, z  ) * 0.1;
           
            weight = Math.round(weight/1.4f);
           
            for( int y = 256; y > 0; y-- ){
                if( y >= weight ){
                    world.getBlockAt( x, y, z).setType(Material.AIR);
                }else{
                    world.getBlockAt( x, y, z).setType(Material.DIRT);
                }
            }
        }
    is the code for bluring/smoothing out a single block. I know its not gaussian, but it worked.
    [​IMG]

    heres the result

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 29, 2016
  24. Offline

    FTWinston

    Looks pretty good, thanks for posting the solution.
     
Thread Status:
Not open for further replies.

Share This Page