Generate caves using custom generator

Discussion in 'Spigot Plugin Development' started by NubeBuster, May 25, 2016.

  1. I am trying to create a world generator which fits my needs. My needs are that I can control the terrain and that it is performance friendly. TerrainControl is waaay too slow so I don't want to use that.

    With my current generator I am 99% satisfied.
    These are screen shots:
    https://gyazo.com/fc058bc575b0cf463e97b8420441e72f
    https://gyazo.com/07b4a81e652788f3b07cff021c0d8b42
    https://gyazo.com/42bc5b1038e9f20fb8607677f3eea587

    There is just one thing missing: caves!

    I have tried creating caves with the following ways:

    Using WorldGenCaves wgc = new WorldGenCaves(); and somehow putting various parameters together

    Using PerlinNoiseGenerator which ended up doing the same as SimplexOctaveGenerator and I could only make it give me the highest block at an x and z

    I have spent days and hours researching classes from Bukkit, Minecraft and other people. I have stumbled across this post: https://bukkit.org/threads/vanilla-caves.360460/ where the guy got almost as far as I did but probably gave up.

    Do you guys know how to make caves? Or how I need to make the ways above working?

    (I have a byte[][] with block ids which I have filled, and I need to remove certain bytes from it to get caves)

    [Edit] I would be satisfied with ravines too, but no idea how to generate those either
     
    #1 NubeBuster, May 25, 2016
    Last edited: May 25, 2016
  2. Cough cough hardcore games c: ?
     
  3. ;) the best one
     
  4. Neat. I'm working on CTF if ya catch my drift. In the network I am working with, another dev who made HG was kinda stuck at the same place :p. So he kinda just gave in to Terrain Control XD.
     
  5. As you can tell from my public HG plugin post I have already set up terrain control to it's finest. But performance is unfortunately a priority
     
    • Funny Funny x 1
  6. Just take apart the minecraft world generators and learn how 3d noise maps work, then design your own. Or just use the normal world generator, Those sort of rolling flat worlds are very easy to make with presets, and probably much faster..
     
  7. I attempted to study the art of noise generators but the internet is so full of bad information.. Do you happen to know a good tutorial on how to use 3d noise maps?
     
  8. "Just take apart the minecraft world generators" - then experiment a bit on your own. See what you get, learn how it works.
     
  9. I am sure that I won't be able to program PerlinNoiseWorms by experimenting with it. I know it generates a 1 or a -1 but thats all I can fo
     
  10. A 1 or -1?.. It generates a pseudorandom float based on the input numbers.
    Use simplex, not perlin. It is much faster. And you will learn how it works by experimenting it. Making good terrain requires you to understand how to combine maps.

    Also be aware you cannot sample noise for every block, the lag would be horrible. Minecraft samples every 64th block (4x4x4 area) and extrapolates over the others. It is also very easy to simply modify the built-in terrain generators - replace the actual math that generates the terrain weight array, but retain the code that extrapolates terrain, places blocks and handles decorators and biome nonsense.

    It is almost impossible to make non-laggy generators using bukkit ChunkGenerators, without using some advanced math trickery and useless overhead.
     
    • Informative Informative x 1
  11. Have you taken a look at something like this? The Dropbox is blocked up due to traffic, but I'd still check it periodically.

    I agree with the other guy, though, you can figure out some of this by tearing apart other people's code. Good luck man!
     
  12. I really need that, I wish dropbox weren't stupid. However, that's from 2012, thats not what I want
     
    • Agree Agree x 1
  13. I used a little math magic and a hijacked net.minecraft.server.ChunkProriderServer to make this world generator, a fractal-inspired skyland:

    [​IMG]

    Injecting the new generator class is as simple as craftworld.getHandle().generator = your generator, in the WorldInit event. It can easily take advantage of the well-optimized (compared to bukkit) existing code. I used to the same thing to make biome-specific stone types and stratification layers in otherwise normal worlds.
     
    • Creative Creative x 2
  14. So how would I turn this magic and math into caves?
     
  15. By doing what everyone has suggested: learning how it works by experience, instead of hoping for spoonfeeding.

    Caves are complicated, and will require knowledge, not copypasting.
     
  16. As I stated before, I want to learn this with a tutorial. You are telling me to learn this without any source of information
     
  17. You wont find a tutorial and specific as minecraft caves, most likely - any that you do find will either be a copypaste, or expect you to already have a total understanding of how noise maps work. Most of the online voxel terrain tutorials are either very simple (2d maps, not 3d or 4d like minecraft uses) or use the marching cubes algorithm, which is completely incompatible with minecraft.

    If you are at all competent with java, you should be able to make your own generator in a day or two after looking over the internal chunk generators.

    It is really very simple, but fairly abstract. You need to be able to visualize what will happen when you combine different maps or other values, which is where "messing with it" provides invaluable experience.

    SimplexNoiseGenerator.getNoise() is a very simple function to use, think of it as getting a pixel from an infinite "plasma" image. The x,y or x,y,z
    values you give it just determine where it samples from. Bigger coordinates make the resultling values change faster, resulting in bumpier terrain, smaller values cause the same elevations, ect, but stretched over a bigger area. This is basically what the "noiseScale" settings in the "customized" world type do.

    Minecraft also uses another noise for the Y-axis, that determines overhangs and other things, by combining it with the XZ map values.

    As an example of how simple it is, comparatively:
    Code (Java):
    // This is the generator i used for the picture i posted above, it uses three maps: a 2D "height" map (altStoneNoise) that modifies the terrain altitude,
        //another 2D map (m) that determines where solid land is on X,Z,
        //and a final 3D map that is a combination of the two, and shapes the swirled, fractal-like landscape.
    protected double[] x825GetNoise(float x, float z) // y is y/16
       {
         this.altStoneNoise = new float[256]; // this is is a 16x16 grid of noise values that determines the "lift" of the terrain
         int nx=16,nz;
         while(--nx>-1)
           for(nz=15; nz>-1; --nz)
             this.altStoneNoise[(nx<<4)+nz]=(float) SimplexNoiseGenerator.getNoise( ((float)(x+nx))/altStoneNoiseLevel, altStoneNoiseLevel, (float)(z+nz)/altStoneNoiseLevel);
       
         double[] n = new double[825];// this is a 5x5x33 3d space that represents a chunk (each value represents 4x4x4 blocks, with one more over the edge of the chunk for smoothing with the next chunk, to prevent seams. this is how minecraft does it internally, and is actually quite efficient)
         int c = 0;
         for(int lx = 0; lx < 5; ++lx)
           for(int lz = 0; lz < 5; ++lz)
           {
             double m = 32+(1f+SimplexNoiseGenerator.getNoise( (x+(lx*4))/256, (z+(lz*4))/256) )*32; // this is some additional noise on a different scale.
             for(int ly = 0; ly < 33; ++ly)
             {
                // X,Z coords just based on the location, Y coord is modified by m
               double g = SimplexNoiseGenerator.getNoise( (float)(x+(lx*4))/512f, ((float)ly*8)/m, (float)(z+(lz*4))/512f  ) * (1.5f-(Math.abs(16f-ly)/16f)) ;
             
               //if(g<=1.5f) g=0; // positive values are normally stone, negative are air.
               n[c]=g;
               ++c;
             }
           }
         return n; // return the 5x5x33 array of values, they then go directly to ChunkProviderGenerate.a(int x, int z, ChunkSnapshot), which fills in the chunksnapshot with stone or air, based on the values (and also calculates curves in the terrain from the 4x4x4 section represented by each value)
       }
     
     
    • Informative Informative x 1