blob: 194bfe3f8170347f27733a9344463443a08f5bac [file] [log] [blame] [raw]
package net.glowstone.generator.objects;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.material.MaterialData;
import java.util.Random;
public class OreVein implements TerrainObject {
private final Material type;
private final MaterialData data;
private final int amount;
private final Material targetType;
/**
* Creates the instance for a given ore type.
*
* @param oreType the ore type
*/
public OreVein(OreType oreType) {
type = oreType.getType();
data = oreType.getData();
amount = oreType.getAmount();
targetType = oreType.getTargetType();
}
@Override
public boolean generate(World world, Random random, int sourceX, int sourceY, int sourceZ) {
float angle = random.nextFloat() * (float) Math.PI;
double dx1 = sourceX + Math.sin(angle) * amount / 8.0F;
double dx2 = sourceX - Math.sin(angle) * amount / 8.0F;
double dz1 = sourceZ + Math.cos(angle) * amount / 8.0F;
double dz2 = sourceZ - Math.cos(angle) * amount / 8.0F;
double dy1 = sourceY + random.nextInt(3) - 2;
double dy2 = sourceY + random.nextInt(3) - 2;
boolean succeeded = false;
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.0D;
double radiusH = (Math.sin(i * (float) Math.PI / amount) + 1 * q + 1) / 2.0D;
double radiusV = (Math.sin(i * (float) Math.PI / amount) + 1 * q + 1) / 2.0D;
for (int x = (int) (originX - radiusH); x <= (int) (originX + radiusH); x++) {
// scale the center of x to the range [-1, 1] within the circle
double squaredNormalizedX = normalizedSquaredCoordinate(originX, radiusH, x);
if (squaredNormalizedX >= 1) {
continue;
}
for (int y = (int) (originY - radiusV); y <= (int) (originY + radiusV); y++) {
double squaredNormalizedY = normalizedSquaredCoordinate(originY, radiusV, y);
if (squaredNormalizedX + squaredNormalizedY >= 1) {
continue;
}
for (int z = (int) (originZ - radiusH); z <= (int) (originZ + radiusH);
z++) {
double squaredNormalizedZ
= normalizedSquaredCoordinate(originZ, radiusH, z);
Block block = world.getBlockAt(x, y, z);
if (squaredNormalizedX + squaredNormalizedY + squaredNormalizedZ < 1
&& block.getType() == targetType) {
block.setTypeIdAndData(type.getId(), data.getData(), false);
succeeded = true;
}
}
}
}
}
return succeeded;
}
/**
* The square of the percentage of the radius that is the distance between the given block's
* center and the center of an orthogonal ellipsoid. A block's center is inside the ellipsoid
* if and only if its normalizedSquaredCoordinate values add up to less than 1.
*
* @param origin the center of the spheroid
* @param radius the spheroid's radius on this axis
* @param x the raw coordinate
* @return the square of the normalized coordinate
*/
protected static double normalizedSquaredCoordinate(double origin, double radius, int x) {
double squaredNormalizedX = (x + 0.5D - origin) / radius;
squaredNormalizedX *= squaredNormalizedX;
return squaredNormalizedX;
}
}