package eu.thog.uhcrun.generator;
import net.minecraft.server.v1_8_R3.ChunkSnapshot;
import net.minecraft.server.v1_8_R3.WorldGenCanyon;
import net.minecraft.server.v1_8_R3.WorldGenCaves;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
import org.bukkit.generator.BlockPopulator;
import java.util.List;
import java.util.Random;
/**
* This file is a part of the UHCRun Project CodeBase
* Created by Thog
* (C) Copyright Thomas Guillemard 2016
* All rights reserved.
*/
public class OrePopulator extends BlockPopulator
{
private List<Rule> rules = new java.util.ArrayList<>();
private int randInt(Random rand, int min, int max)
{
return rand.nextInt((max - min) + 1) + min;
}
public void addRule(Rule rule)
{
if (!rules.contains(rule))
{
rules.add(rule);
}
}
@Override
public void populate(World world, Random random, Chunk chunk)
{
if (chunk == null)
{
return;
}
// Gen more caves
CraftWorld handle = (CraftWorld) world;
int xr = randInt(random, -100, 100);
if (xr >= 50)
{
new WorldGenCaves().a(handle.getHandle().chunkProviderServer, handle.getHandle(), chunk.getX(), chunk.getZ(), new ChunkSnapshot());
} else if (xr <= -50)
{
new WorldGenCanyon().a(handle.getHandle().chunkProviderServer, handle.getHandle(), chunk.getX(), chunk.getZ(), new ChunkSnapshot());
}
// Apply rules
for (Rule bloc : rules)
{
for (int i = 0; i < bloc.round; i++)
{
int x = chunk.getX() * 16 + random.nextInt(16);
int y = bloc.minY + random.nextInt(bloc.maxY - bloc.minY);
int z = chunk.getZ() * 16 + random.nextInt(16);
generate(world, random, x, y, z, bloc.size, bloc);
}
}
}
private void generate(World world, Random rand, int x, int y, int z, int size, Rule material)
{
double rpi = rand.nextDouble() * Math.PI;
double x1 = x + 8 + Math.sin(rpi) * size / 8.0F;
double x2 = x + 8 - Math.sin(rpi) * size / 8.0F;
double z1 = z + 8 + Math.cos(rpi) * size / 8.0F;
double z2 = z + 8 - Math.cos(rpi) * size / 8.0F;
double y1 = y + rand.nextInt(3) + 2;
double y2 = y + rand.nextInt(3) + 2;
for (int i = 0; i <= size; i++)
{
double xPos = x1 + (x2 - x1) * i / size;
double yPos = y1 + (y2 - y1) * i / size;
double zPos = z1 + (z2 - z1) * i / size;
double fuzz = rand.nextDouble() * size / 16.0D;
double fuzzXZ = (Math.sin((float) (i * Math.PI / size)) + 1.0F) * fuzz + 1.0D;
double fuzzY = (Math.sin((float) (i * Math.PI / size)) + 1.0F) * fuzz + 1.0D;
int xStart = (int) Math.floor(xPos - fuzzXZ / 2.0D);
int yStart = (int) Math.floor(yPos - fuzzY / 2.0D);
int zStart = (int) Math.floor(zPos - fuzzXZ / 2.0D);
int xEnd = (int) Math.floor(xPos + fuzzXZ / 2.0D);
int yEnd = (int) Math.floor(yPos + fuzzY / 2.0D);
int zEnd = (int) Math.floor(zPos + fuzzXZ / 2.0D);
for (int ix = xStart; ix <= xEnd; ix++)
{
double xThresh = (ix + 0.5D - xPos) / (fuzzXZ / 2.0D);
if (xThresh * xThresh < 1.0D)
{
for (int iy = yStart; iy <= yEnd; iy++)
{
double yThresh = (iy + 0.5D - yPos) / (fuzzY / 2.0D);
if (xThresh * xThresh + yThresh * yThresh < 1.0D)
{
for (int iz = zStart; iz <= zEnd; iz++)
{
double zThresh = (iz + 0.5D - zPos) / (fuzzXZ / 2.0D);
if (xThresh * xThresh + yThresh * yThresh + zThresh * zThresh < 1.0D)
{
Block block = getBlock(world, ix, iy, iz);
if (block != null && block.getType() == Material.STONE)
{
block.setType(Material.getMaterial(material.id));
}
}
}
}
}
}
}
}
}
private Block getBlock(World world, int x, int y, int z)
{
int cx = x >> 4;
int cz = z >> 4;
if ((!world.isChunkLoaded(cx, cz)) &&
(!world.loadChunk(cx, cz, false)))
{
return null;
}
Chunk chunk = world.getChunkAt(cx, cz);
if (chunk == null)
{
return null;
}
return chunk.getBlock(x & 0xF, y, z & 0xF);
}
public static class Rule
{
public String id;
public int round;
public int minY;
public int maxY;
public int size;
public Rule(String type, int round, int minY, int maxY, int size)
{
this.id = type;
this.round = round;
this.minY = minY;
this.maxY = maxY;
this.size = size;
}
}
}