package cofh.lib.world;
import static cofh.lib.world.WorldGenMinableCluster.*;
import cofh.lib.util.WeightedRandomBlock;
import java.util.List;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.WorldGenerator;
public class WorldGenSparseMinableCluster extends WorldGenerator {
private final List<WeightedRandomBlock> cluster;
private final int genClusterSize;
private final WeightedRandomBlock[] genBlock;
public WorldGenSparseMinableCluster(ItemStack ore, int clusterSize) {
this(new WeightedRandomBlock(ore), clusterSize);
}
public WorldGenSparseMinableCluster(WeightedRandomBlock resource, int clusterSize) {
this(fabricateList(resource), clusterSize);
}
public WorldGenSparseMinableCluster(List<WeightedRandomBlock> resource, int clusterSize) {
this(resource, clusterSize, Blocks.stone);
}
public WorldGenSparseMinableCluster(ItemStack ore, int clusterSize, Block block) {
this(new WeightedRandomBlock(ore, 1), clusterSize, block);
}
public WorldGenSparseMinableCluster(WeightedRandomBlock resource, int clusterSize, Block block) {
this(fabricateList(resource), clusterSize, block);
}
public WorldGenSparseMinableCluster(List<WeightedRandomBlock> resource, int clusterSize, Block block) {
this(resource, clusterSize, fabricateList(block));
}
public WorldGenSparseMinableCluster(List<WeightedRandomBlock> resource, int clusterSize, List<WeightedRandomBlock> block) {
cluster = resource;
genClusterSize = clusterSize > 32 ? 32 : clusterSize;
genBlock = block.toArray(new WeightedRandomBlock[block.size()]);
}
@Override
public boolean generate(World world, Random rand, int x, int y, int z) {
int blocks = genClusterSize;
float f = rand.nextFloat() * (float) Math.PI;
// despite naming, these are not exactly min/max. more like direction
float yMin = (y + rand.nextInt(3)) - 2;
float yMax = (y + rand.nextInt(3)) - 2;
// { HACK: at 1 and 2 no ores are ever generated. by doing it this way,
// 3 = 1/3rd clusters gen, 2 = 1/6, 1 = 1/12 allowing for much finer
// grained rarity than the non-sparse version
if (blocks == 1 && yMin > yMax) {
++blocks;
}
if (blocks == 2 && f > (float) Math.PI * 0.5f) {
++blocks;
}
// }
float xMin = x + 8 + (MathHelper.sin(f) * blocks) / 8F;
float xMax = x + 8 - (MathHelper.sin(f) * blocks) / 8F;
float zMin = z + 8 + (MathHelper.cos(f) * blocks) / 8F;
float zMax = z + 8 - (MathHelper.cos(f) * blocks) / 8F;
// optimization so this subtraction doesn't occur every time in the loop
xMax -= xMin;
yMax -= yMin;
zMax -= zMin;
boolean r = false;
for (int i = 0; i <= blocks; i++) {
float xCenter = xMin + (xMax * i) / blocks;
float yCenter = yMin + (yMax * i) / blocks;
float zCenter = zMin + (zMax * i) / blocks;
// preserved as nextDouble to ensure the rand gets ticked the same amount
float size = ((float) rand.nextDouble() * blocks) / 16f;
float hMod = ((MathHelper.sin((i * (float) Math.PI) / blocks) + 1f) * size + 1f) * .5f;
float vMod = ((MathHelper.sin((i * (float) Math.PI) / blocks) + 1f) * size + 1f) * .5f;
int xStart = MathHelper.floor_float(xCenter - hMod);
int yStart = MathHelper.floor_float(yCenter - vMod);
int zStart = MathHelper.floor_float(zCenter - hMod);
int xStop = MathHelper.floor_float(xCenter + hMod);
int yStop = MathHelper.floor_float(yCenter + vMod);
int zStop = MathHelper.floor_float(zCenter + hMod);
for (int blockX = xStart; blockX <= xStop; blockX++) {
float xDistSq = ((blockX + .5f) - xCenter) / hMod;
xDistSq *= xDistSq;
if (xDistSq >= 1f) {
continue;
}
for (int blockY = yStart; blockY <= yStop; blockY++) {
float yDistSq = ((blockY + .5f) - yCenter) / vMod;
yDistSq *= yDistSq;
float xyDistSq = yDistSq + xDistSq;
if (xyDistSq >= 1f) {
continue;
}
for (int blockZ = zStart; blockZ <= zStop; blockZ++) {
float zDistSq = ((blockZ + .5f) - zCenter) / hMod;
zDistSq *= zDistSq;
if (zDistSq + xyDistSq >= 1f) {
continue;
}
r |= generateBlock(world, blockX, blockY, blockZ, genBlock, cluster);
}
}
}
}
return r;
}
}