World generation - place liquids and lights

Discussion in 'Plugin Development' started by MCMastery, Feb 14, 2020.

  1. Offline

    MCMastery

    Hello, I am working on a world generator and I want to be able to place water and lava. Unfortunately, if I just use chunkData.setBlock(... Material.WATER) the water will not be updated, so it will just be a single block of water; because of this, waterfalls are impossible. Anyone know how to "update" the block to force it to spread?

    Also, this is a different issue, but I would also like to be able to place glowstone if possible. If you simply try to place the glowstone, the client won't render the lighting and it will all be dark. Bonus points if you know how to do that.

    Thank you!
     
  2. Offline

    Kars

    Store the locations where you have placed water, then after generation is finished call <block>.setType(Material.WATER) on all of them to cause physics updates.

    Bad workaround but it will work.
     
  3. Offline

    MCMastery

    Thanks, good idea. This is what I have now:
    Code:
        private Set<Vector> waterLocations;
    
        public MiningWorld() {
            this.waterLocations = new HashSet<>();
        }
    
        private static World createWorld() {
            MiningWorld miningWorld = new MiningWorld();
            Messages.logInfo("Generating mining world...");
            long start = System.currentTimeMillis();
            WorldCreator wc = new WorldCreator(WORLD_NAME)
                    .generator(miningWorld);
            World world = Bukkit.createWorld(wc);
            Messages.logInfo("Performing physics update on mining world...");
            miningWorld.physicsUpdate(world);
            double seconds = (System.currentTimeMillis() - start) / 1000.0;
            Messages.logInfo("Finished generating mining world (" + String.format("%.2fs", seconds) + ")");
            return world;
        }
    
        public void physicsUpdate(World world) {
            // physics update previous water locations
            // true = force physics update
            for (Vector v : new HashSet<>(this.waterLocations))
                world.getBlockAt(v.getBlockX(), v.getBlockY(), v.getBlockZ()).setType(Material.WATER, true);
            this.waterLocations.clear();
        }
    
        @Override
        public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid grid) {
            SimplexNoiseGenerator sng = new SimplexNoiseGenerator(world);
    
            ChunkData data = createChunkData(world);
            for (int x = 0; x < 16; x++) {
                for (int z = 0; z < 16; z++) {
                    int worldX = chunkX * 16 + x;
                    int worldZ = chunkZ * 16 + z;
                    int height = getHeight(sng, worldX, worldZ);
                    if (height == 0)
                        continue;
    
                    // ...
    
                    // water on top?
                    if (random.nextDouble() < 0.05)
                        this.waterLocations.add(new Vector(worldX, height + 1, worldZ));
                }
            }
            return data;
        }
    }

    This only performs physics updates after world generation and does not perform updates as players generate new chunks. Any ideas how I can do that?

    EDIT: I'll try using a BlockPopulator
     
    Last edited: Feb 17, 2020

Share This Page