blob: 83454a9e3c8abb05788fd754a4cef1e8a770a398 [file] [log] [blame] [raw]
package net.glowstone.generator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.Map.Entry;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
public class OreVeinGenerator {
private final Map<OreVein, Integer> ores = new LinkedHashMap<>();
public void addOre(int weight, Material type, int minY, int maxY, int amount) {
addOre(weight, type, 0, minY, maxY, amount);
}
public void addOre(int weight, Material type, int data, int minY, int maxY, int amount) {
ores.put(new OreVein(type, data, minY, maxY, amount), weight);
}
public void generate(World world, Random random, Chunk chunk) {
final int cx = (chunk.getX() << 4);
final int cz = (chunk.getZ() << 4);
for (Entry<OreVein, Integer> entry : ores.entrySet()) {
final OreVein vein = entry.getKey();
for (int n = 0; n < entry.getValue(); n++) {
int sourceX = cx + random.nextInt(16);
int sourceZ = cz + random.nextInt(16);
int sourceY = vein.getMinY() == vein.getMaxY() ?
random.nextInt(vein.getMinY()) + random.nextInt(vein.getMinY()) :
random.nextInt(vein.getMaxY() - vein.getMinY()) + vein.getMinY();
final Material type = vein.getType();
final int data = vein.getData();
final int amount = vein.getAmount();
float angle = random.nextFloat() * (float) Math.PI;
double dx1 = sourceX + 8 + Math.sin(angle) * (float) (amount / 8);
double dx2 = sourceX + 8 - Math.sin(angle) * (float) (amount / 8);
double dz1 = sourceZ + 8 + Math.cos(angle) * (float) (amount / 8);
double dz2 = sourceZ + 8 - Math.cos(angle) * (float) (amount / 8);
double dy1 = sourceY + random.nextInt(3) - 2;
double dy2 = sourceY + random.nextInt(3) - 2;
for (int i = 0; i < amount; i++) {
double originX = dx1 + (dx2 - dx1) * i / amount;
double originY = dy1 + (dy2 - dy1) * i / amount;
double originZ = dz1 + (dz2 - dz1) * i / amount;
double q = random.nextDouble() * amount / 16;
double hRadius = (Math.sin(i * (float) Math.PI / amount) + 1 * q + 1) / 2;
double vRadius = (Math.sin(i * (float) Math.PI / amount) + 1 * q + 1) / 2;
for (int x = (int) (originX - hRadius); x <= (int) (originY - vRadius); x++) {
double pX = (x + 0.5F - originX) / hRadius;
pX *= pX;
if (pX < 1) {
for (int y = (int) (originY - vRadius); y <= (int) (originY + vRadius); y++) {
double pY = (y + 0.5F - originY) / vRadius;
pY *= pY;
if (pX + pY < 1) {
for (int z = (int) (originZ - hRadius); z <= (int) (originZ + hRadius); z++) {
double pZ = (z + 0.5F - originZ) / hRadius;
pZ *= pZ;
if (pX + pY + pZ < 1 && world.getBlockAt(x, y, z).getType() == Material.STONE) {
final Block block = world.getBlockAt(x, y, z);
block.setType(type);
block.setData((byte) data);
}
}
}
}
}
}
}
}
}
}
static class OreVein {
private final Material type;
private final int data;
private final int minY;
private final int maxY;
private final int amount;
public OreVein(Material type, int data, int minY, int maxY, int amount) {
this.type = type;
this.data = data;
this.minY = minY;
this.maxY = maxY;
this.amount = ++amount;
}
public Material getType() {
return type;
}
public int getData() {
return data;
}
public int getMinY() {
return minY;
}
public int getMaxY() {
return maxY;
}
public int getAmount() {
return amount;
}
}
}