TeamVento/src/main/java/eu/univento/teamvento/generator/CustomGenerator.java

100 lines
3.8 KiB
Java

/*
* Copyright (c) 2018 univento.eu - All rights reserved
* You are not allowed to use, distribute or modify this code
*/
package eu.univento.teamvento.generator;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.util.noise.PerlinOctaveGenerator;
import org.bukkit.util.noise.SimplexOctaveGenerator;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* @author joethei
* @version 1.0
*/
public class CustomGenerator extends ChunkGenerator {
private double scale = 32.0; //how far apart the tops of the hills are
private double threshold = 0.0; // the cutoff point for terrain
private int middle = 70; // the "middle" of the road
public List<BlockPopulator> getDefaultPopulators(World world) {
ArrayList<BlockPopulator> populators = new ArrayList<>();
populators.add(new CustomPopulator());
return populators;
}
/*
* Sets a block in the chunk. If the Block section doesn't exist, it allocates it.
* [y>>4] the section id (y/16)
* the math for the second offset confuses me
*/
void setBlock(int x, int y, int z, byte[][] chunk, Material material) {
if (chunk[y >> 4] == null)
chunk[y >> 4] = new byte[16 * 16 * 16];
if (!(y <= 256 && y >= 0 && x <= 16 && x >= 0 && z <= 16 && z >= 0))
return; //Out of bounds
try {
chunk[y >> 4][((y & 0xF) << 8) | (z << 4) | x] = (byte) material.getId();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
//Generates block sections. Each block section is 16*16*16 blocks, stacked above each other. //There are world height / 16 sections. section number is world height / 16 (>>4)
//returns a byte[world height / 16][], formatted [section id][Blocks]. If there are no blocks in a section, it need not be allocated.
public byte[][] generateBlockSections(World world, Random rand, int ChunkX, int ChunkZ, BiomeGrid biomes) {
Random random = new Random(world.getSeed());
SimplexOctaveGenerator gen = new SimplexOctaveGenerator(random, 8);
PerlinOctaveGenerator gen2 = new PerlinOctaveGenerator(world.getSeed(), 8);
byte[][] chunk = new byte[world.getMaxHeight() / 16][];
gen2.setScale(1 / scale);
gen.setScale(1 / scale); //The distance between peaks of the terrain. Scroll down more to see what happens when you play with this
double threshold = this.threshold; //scroll down to see what happens when you play with this.
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
int real_x = x + ChunkX * 16;
int real_z = z + ChunkZ * 16;
double height = middle + gen2.noise(real_x, real_z, 0.5, 0.5) * middle / 3; // generate some smoother terrain
for (int y = 1; y < height && y < 256; y++) {
if (y > middle - middle / 3) {
double noise = gen.noise(real_x, y, real_z, 0.5, 0.5);
if (noise > threshold) //explained above
setBlock(x, y, z, chunk, Material.STONE); //set the block solid
} else {
setBlock(x, y, z, chunk, Material.STONE);
}
}
}
}
return chunk;
}
}
class CustomPopulator extends BlockPopulator {
@Override
public void populate(World world, Random random, Chunk chunk) {
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
world.getBlockAt(x + chunk.getX() * 16, 64, z + chunk.getZ() * 16).setType(Material.GRASS);
}
}
}
}