mirror of
https://github.com/GTNewHorizons/Binnie.git
synced 2026-11-15 09:44:50 +00:00
218 lines
6.6 KiB
Java
218 lines
6.6 KiB
Java
package binnie.extratrees.worldgen;
|
|
|
|
import binnie.extratrees.genetics.ExtraTreeSpecies;
|
|
import forestry.api.world.ITreeGenData;
|
|
import net.minecraft.init.Blocks;
|
|
import net.minecraft.world.World;
|
|
import net.minecraft.world.gen.feature.WorldGenerator;
|
|
|
|
import java.util.Random;
|
|
|
|
public abstract class WorldGenTree extends WorldGenerator {
|
|
protected ITreeGenData treeGen;
|
|
protected World world;
|
|
protected Random rand;
|
|
protected int startX;
|
|
protected int startY;
|
|
protected int startZ;
|
|
protected int girth;
|
|
protected int height;
|
|
protected int minHeight;
|
|
protected int maxHeight;
|
|
protected boolean spawnPods;
|
|
protected int minPodHeight;
|
|
BlockType leaf;
|
|
BlockType wood;
|
|
BlockType vine;
|
|
BlockType air;
|
|
float bushiness;
|
|
|
|
public WorldGenTree(ITreeGenData tree) {
|
|
minHeight = 3;
|
|
maxHeight = 80;
|
|
spawnPods = false;
|
|
minPodHeight = 3;
|
|
vine = new BlockType(Blocks.vine, 0);
|
|
air = new BlockTypeVoid();
|
|
bushiness = 0.0f;
|
|
spawnPods = tree.allowsFruitBlocks();
|
|
treeGen = tree;
|
|
}
|
|
|
|
protected int randBetween(int a, int b) {
|
|
return a + rand.nextInt(b - a);
|
|
}
|
|
|
|
protected float randBetween(float a, float b) {
|
|
return a + rand.nextFloat() * (b - a);
|
|
}
|
|
|
|
public void generate() {
|
|
generateTreeTrunk(height, girth);
|
|
int leafSpawn = height + 1;
|
|
generateCylinder(new Vector(0.0f, leafSpawn--, 0.0f), 1.0f, 1, leaf, false);
|
|
generateCylinder(new Vector(0.0f, leafSpawn--, 0.0f), 1.5f, 1, leaf, false);
|
|
generateCylinder(new Vector(0.0f, leafSpawn--, 0.0f), 2.9f, 1, leaf, false);
|
|
generateCylinder(new Vector(0.0f, leafSpawn--, 0.0f), 2.9f, 1, leaf, false);
|
|
}
|
|
|
|
public boolean canGrow() {
|
|
return treeGen.canGrow(world, startX, startY, startZ, treeGen.getGirth(world, startX, startY, startZ), height);
|
|
}
|
|
|
|
public void preGenerate() {
|
|
height = determineHeight(5, 3);
|
|
girth = determineGirth(treeGen.getGirth(world, startX, startY, startZ));
|
|
}
|
|
|
|
protected int determineGirth(int base) {
|
|
return base;
|
|
}
|
|
|
|
protected int determineHeight(int required, int variation) {
|
|
int determined = Math.round((required + rand.nextInt(variation)) * treeGen.getHeightModifier());
|
|
return (determined < minHeight) ? minHeight : ((determined > maxHeight) ? maxHeight : determined);
|
|
}
|
|
|
|
public BlockType getLeaf() {
|
|
return new BlockTypeLeaf(true);
|
|
}
|
|
|
|
public BlockType getWood() {
|
|
return new BlockTypeLog(((ExtraTreeSpecies) treeGen.getGenome().getPrimary()).getLog());
|
|
}
|
|
|
|
@Override
|
|
public boolean generate(World world, Random random, int x, int y, int z) {
|
|
return generate(world, random, x, y, z, false);
|
|
}
|
|
|
|
public boolean generate(World world, Random random, int x, int y, int z, boolean force) {
|
|
this.world = world;
|
|
rand = random;
|
|
startX = x;
|
|
startY = y;
|
|
startZ = z;
|
|
leaf = getLeaf();
|
|
wood = getWood();
|
|
preGenerate();
|
|
if (!force && !canGrow()) {
|
|
return false;
|
|
}
|
|
|
|
for (int x2 = 0; x2 < girth; ++x2) {
|
|
for (int y2 = 0; y2 < girth; ++y2) {
|
|
addBlock(x2, 0, y2, new BlockTypeVoid(), true);
|
|
}
|
|
}
|
|
generate();
|
|
return true;
|
|
}
|
|
|
|
protected void generateTreeTrunk(int height, int width) {
|
|
generateTreeTrunk(height, width, 0.0f);
|
|
}
|
|
|
|
protected void generateTreeTrunk(int height, int width, float vines) {
|
|
int offset = (width - 1) / 2;
|
|
for (int x = 0; x < width; ++x) {
|
|
for (int y = 0; y < width; ++y) {
|
|
for (int i = 0; i < height; ++i) {
|
|
addWood(x - offset, i, y - offset, true);
|
|
if (rand.nextFloat() < vines) {
|
|
addVine(x - offset - 1, i, y - offset);
|
|
}
|
|
if (rand.nextFloat() < vines) {
|
|
addVine(x - offset + 1, i, y - offset);
|
|
}
|
|
if (rand.nextFloat() < vines) {
|
|
addVine(x - offset, i, y - offset - 1);
|
|
}
|
|
if (rand.nextFloat() < vines) {
|
|
addVine(x - offset, i, y - offset + 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!spawnPods) {
|
|
return;
|
|
}
|
|
for (int y2 = minPodHeight; y2 < height; ++y2) {
|
|
for (int x2 = 0; x2 < girth; ++x2) {
|
|
for (int z = 0; z < girth; ++z) {
|
|
if (x2 <= 0 || x2 >= girth || z <= 0 || z >= girth) {
|
|
treeGen.trySpawnFruitBlock(world, startX + x2 + 1, startY + y2, startZ + z);
|
|
treeGen.trySpawnFruitBlock(world, startX + x2 - 1, startY + y2, startZ + z);
|
|
treeGen.trySpawnFruitBlock(world, startX + x2, startY + y2, startZ + z + 1);
|
|
treeGen.trySpawnFruitBlock(world, startX + x2, startY + y2, startZ + z - 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void addBlock(int x, int y, int z, BlockType type, boolean doReplace) {
|
|
if (doReplace || world.isAirBlock(startX + x, startY + y, startZ + z)) {
|
|
type.setBlock(world, treeGen, startX + x, startY + y, startZ + z);
|
|
}
|
|
}
|
|
|
|
protected void addWood(int x, int y, int z, boolean doReplace) {
|
|
addBlock(x, y, z, wood, doReplace);
|
|
}
|
|
|
|
protected void addVine(int x, int y, int z) {
|
|
addBlock(x, y, z, vine, false);
|
|
}
|
|
|
|
protected void generateCylinder(Vector center2, float radius, int height, BlockType block, boolean doReplace) {
|
|
float centerOffset = (girth - 1) / 2.0f;
|
|
Vector center3 = new Vector(center2.x + centerOffset, center2.y, center2.z + centerOffset);
|
|
Vector start = new Vector(center3.x - radius, center3.y, center3.z - radius);
|
|
Vector area = new Vector(radius * 2.0f + 1.0f, height, radius * 2.0f + 1.0f);
|
|
for (int x = (int) start.x; x < (int) start.x + area.x; ++x) {
|
|
for (int y = (int) start.y; y < (int) start.y + area.y; ++y) {
|
|
for (int z = (int) start.z; z < (int) start.z + area.z; ++z) {
|
|
if (Vector.distance(new Vector(x, y, z), new Vector(center3.x, y, center3.z)) <= radius + 0.01) {
|
|
if (Vector.distance(new Vector(x, y, z), new Vector(center3.x, y, center3.z)) < radius - 0.5f || rand.nextFloat() >= bushiness) {
|
|
addBlock(x, y, z, block, doReplace);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void generateSphere(Vector center2, int radius, BlockType block, boolean doReplace) {
|
|
float centerOffset = (girth - 1) / 2.0f;
|
|
Vector center3 = new Vector(center2.x + centerOffset, center2.y, center2.z + centerOffset);
|
|
Vector start = new Vector(center3.x - radius, center3.y - radius, center3.z - radius);
|
|
Vector area = new Vector(radius * 2 + 1, radius * 2 + 1, radius * 2 + 1);
|
|
for (int x = (int) start.x; x < (int) start.x + area.x; ++x) {
|
|
for (int y = (int) start.y; y < (int) start.y + area.y; ++y) {
|
|
for (int z = (int) start.z; z < (int) start.z + area.z; ++z) {
|
|
if (Vector.distance(new Vector(x, y, z), new Vector(center3.x, center3.y, center3.z)) <= radius + 0.01) {
|
|
addBlock(x, y, z, block, doReplace);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static class Vector {
|
|
float x;
|
|
float y;
|
|
float z;
|
|
|
|
public Vector(float f, float h, float g) {
|
|
x = f;
|
|
y = h;
|
|
z = g;
|
|
}
|
|
|
|
public static double distance(Vector a, Vector b) {
|
|
return Math.sqrt(Math.pow(a.x - b.x, 2.0) + Math.pow(a.y - b.y, 2.0) + Math.pow(a.z - b.z, 2.0));
|
|
}
|
|
}
|
|
}
|