package zmaster587.advancedRocketry.world.gen;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.BlockSapling;
import net.minecraft.init.Blocks;
import net.minecraft.world.World;
import net.minecraft.world.gen.MapGenBase;
import net.minecraft.world.gen.feature.WorldGenAbstractTree;
import net.minecraftforge.common.util.ForgeDirection;
import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks;
import zmaster587.libVulpes.block.BlockMeta;
import zmaster587.libVulpes.util.BlockPosition;
public class WorldGenSwampTree extends MapGenBase {
Map<BlockPosition, BlockMeta> cachedCanopy;
Map<BlockPosition, BlockMeta> cachedRoots;
private final static double arcSize = 16.0;
int chancePerChunk;
public WorldGenSwampTree(int chancePerChunk) {
super();
chancePerChunk= 10;
cachedCanopy = new HashMap<BlockPosition, BlockMeta>();
cachedRoots = new HashMap<BlockPosition, BlockMeta>();
this.chancePerChunk = chancePerChunk;
buildCanopy();
buildRoots();
}
private void buildRoots() {
cachedRoots.clear();
for (double Yangle = 0; Yangle < 2*Math.PI; Yangle+=Math.PI/3.0){
// Yangle = 0.0;//Math.PI/4.0;
int yOffset = (int)(1.25*arcSize*Math.sin(Math.PI)) + 1;
int xOffset = (int)(1.1*arcSize*Math.cos(Math.PI)*Math.cos(Yangle));
int zOffset = (int)(1.1*arcSize*Math.cos(Math.PI)*Math.sin(Yangle));
for(double angle = Math.PI; angle > 0; angle -= Math.PI/40.0) {
int yy = (int)(1.25*arcSize*Math.sin(angle));
double xzRadius = (0.75*arcSize*Math.cos(angle));
int xx = (int) (xzRadius*Math.cos(Yangle));
int zz = (int) (xzRadius*Math.sin(Yangle));
if(!cachedRoots.containsKey(new BlockPosition(2 + xx - xOffset, yy - yOffset +2, zz- zOffset)))
cachedRoots.put( new BlockPosition(2 + xx - xOffset, yy - yOffset +2, zz- zOffset), new BlockMeta(Blocks.log, 3));
if(!cachedRoots.containsKey(new BlockPosition(3 + xx - xOffset, yy - yOffset +2, zz- zOffset)))
cachedRoots.put(new BlockPosition(3 + xx - xOffset, yy - yOffset +2, zz- zOffset), new BlockMeta(Blocks.log, 3));
if(!cachedRoots.containsKey(new BlockPosition(2 + xx - xOffset, yy - yOffset +2, 1 + zz- zOffset)))
cachedRoots.put( new BlockPosition(2 + xx - xOffset, yy - yOffset +2, 1 + zz- zOffset), new BlockMeta(Blocks.log, 3));
if(!cachedRoots.containsKey(new BlockPosition(2 + xx - xOffset, yy - yOffset +3, 1 + zz- zOffset)))
cachedRoots.put( new BlockPosition(2 + xx - xOffset, yy - yOffset +3, 1 + zz- zOffset), new BlockMeta(Blocks.log, 3));
if(!cachedRoots.containsKey(new BlockPosition(1 + xx - xOffset , yy - yOffset +2, zz- zOffset)))
cachedRoots.put(new BlockPosition(1 + xx - xOffset , yy - yOffset +2, zz- zOffset), new BlockMeta(Blocks.log, 3));
if(!cachedRoots.containsKey(new BlockPosition(2 + xx - xOffset, yy - yOffset +2, zz- zOffset - 1)))
cachedRoots.put( new BlockPosition(2 + xx - xOffset, yy - yOffset +2, zz- zOffset - 1), new BlockMeta(Blocks.log, 3));
}
}
}
private void buildCanopy() {
cachedCanopy.clear();
//Gen the canopy
for (double Yangle = 0; Yangle < 2*Math.PI; Yangle+=Math.PI/512.0){
// Yangle = 0.0;//Math.PI/4.0;
int yOffset = (int)(arcSize*Math.sin(1.5*Math.PI/2.0));
int xOffset = (int)(1.25*arcSize*Math.cos(1.5*Math.PI/2.0)*Math.cos(Yangle));
int zOffset = (int)(1.25*arcSize*Math.cos(1.5*Math.PI/2.0)*Math.sin(Yangle));
for(double angle = 1.5*Math.PI/2.0; angle > -Math.PI/6.0; angle -= Math.PI/128.0) {
int yy = (int)(arcSize*Math.sin(angle));
double xzRadius = (1.3*arcSize*Math.cos(angle));
int xx = (int) (xzRadius*Math.cos(Yangle));
int zz = (int) (xzRadius*Math.sin(Yangle));
for(int yyy = -2 ; yyy < 4; yyy++)
if(!cachedCanopy.containsKey(new BlockPosition(2 + xx - xOffset, yyy + yy - yOffset +2, zz- zOffset)))
cachedCanopy.put(new BlockPosition(2 + xx - xOffset, yyy + yy - yOffset +2, zz- zOffset), new BlockMeta(Blocks.leaves, 3));
//world.setBlock( x + 2 + xx - xOffset - radius/2, treeHeight -3 + yy - yOffset +2, z + zz- zOffset, Blocks.vine, 0,2);
}
}
}
protected void func_151538_a(World world2, int rangeX,
int rangeZ, int chunkX, int chunkZ,
Block[] blocks) {
if(rand.nextInt(chancePerChunk) == Math.abs(rangeX) % chancePerChunk && rand.nextInt(chancePerChunk) == Math.abs(rangeZ) % chancePerChunk) {
int x = (rangeX - chunkX)*16;
int z = (rangeZ- chunkZ)*16;
int y = 56;
int treeHeight = rand.nextInt(10) + 40;
int radius = 4;
int edgeRadius = 1;
int numDiag = edgeRadius + 1;
int meta = 3;
Block block = Blocks.log;
int currentEdgeRadius;
final float SHAPE = 0.1f;
currentEdgeRadius = (int)((SHAPE*(edgeRadius * treeHeight )) + ((1f-SHAPE)*edgeRadius));
y++;
for(int yOff = -20; yOff < treeHeight; yOff++) {
currentEdgeRadius = (int)((SHAPE*(edgeRadius * (treeHeight - yOff))) + ((1f-SHAPE)*edgeRadius));
//Generate the top trapezoid
for(int zOff = -numDiag - currentEdgeRadius/2; zOff <= -currentEdgeRadius/2; zOff++) {
for(int xOff = -numDiag -currentEdgeRadius/2; xOff <= numDiag + currentEdgeRadius/2; xOff++) {
setBlock(x + xOff, y + yOff, z + zOff, block, blocks);
}
currentEdgeRadius++;
}
//Generate square segment
for(int zOff = -currentEdgeRadius/2; zOff <= currentEdgeRadius/2; zOff++) {
for(int xOff = -numDiag -currentEdgeRadius/2; xOff <= numDiag + currentEdgeRadius/2; xOff++) {
setBlock(x + xOff, y + yOff, z + zOff, block, blocks);
}
}
//Generate the bottom trapezoid
for(int zOff = currentEdgeRadius/2; zOff <= numDiag + currentEdgeRadius/2; zOff++) {
currentEdgeRadius--;
for(int xOff = -numDiag -currentEdgeRadius/2; xOff <= numDiag + currentEdgeRadius/2; xOff++) {
setBlock(x + xOff, y + yOff, z + zOff, block, blocks);
}
}
}
//Canopy
for(Entry<BlockPosition, BlockMeta> entry : cachedCanopy.entrySet())
setBlock( entry.getKey().x + x - radius/2, y + treeHeight + entry.getKey().y, z + entry.getKey().z, entry.getValue().getBlock(), blocks);
//Generate Logs
for (double Yangle = 0; Yangle < 2*Math.PI; Yangle+=Math.PI/8.0){
// Yangle = 0.0;//Math.PI/4.0;
int yOffset = (int)(arcSize*Math.sin(1.5*Math.PI/2.0));
int xOffset = (int)(1.25*arcSize*Math.cos(1.5*Math.PI/2.0)*Math.cos(Yangle));
int zOffset = (int)(1.25*arcSize*Math.cos(1.5*Math.PI/2.0)*Math.sin(Yangle));
for(double angle = 1.5*Math.PI/2.0; angle > -Math.PI/6.0; angle -= Math.PI/40.0) {
int yy = (int)(arcSize*Math.sin(angle));
double xzRadius = (1.25*arcSize*Math.cos(angle));
int xx = (int) (xzRadius*Math.cos(Yangle));
int zz = (int) (xzRadius*Math.sin(Yangle));
setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +2, z + zz- zOffset, Blocks.log, blocks);
setBlock( x + 3 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +2, z + zz- zOffset, Blocks.log, blocks);
setBlock( x + 1 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +2, z + zz- zOffset, Blocks.log, blocks);
setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +3, z + zz- zOffset, Blocks.log, blocks);
setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +2, z + zz- zOffset + 1, Blocks.log, blocks);
setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +2, z + zz- zOffset - 1, Blocks.log, blocks);
}
//Generate the hangy things
if(rand.nextInt(4) == 0) {
int yy = (int)(arcSize*Math.sin(Math.PI/3.0));
double xzRadius = (1.25*arcSize*Math.cos(Math.PI/2.0));
int xx = (int) (xzRadius*Math.cos(Yangle));
int zz = (int) (xzRadius*Math.sin(Yangle));
int xxx = xx;
int zzz = zz;
//Leaf caps on bottom
for(zz = -1; zz < 2; zz++)
for(xx = -1; xx < 2; xx++)
setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight - 10 + yy - yOffset +2, z + zz- zOffset, Blocks.leaves, blocks);
xx=xxx;
zz=zzz;
//Descending
for(int yyy = 0; yyy < 10; yyy++) {
for(zz = -2; zz < 3; zz++)
for(xx = -2; xx < 3; xx++)
setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight - yyy + yy - yOffset +2, z + zz- zOffset, Blocks.leaves, blocks);
xx=xxx;
zz=zzz;
setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yyy - yOffset +2, z + zz- zOffset, Blocks.log, blocks);
setBlock( x + 3 + xx - xOffset - radius/2, y + treeHeight + yy - yyy - yOffset +2, z + zz- zOffset, Blocks.log, blocks);
setBlock( x + 1 + xx - xOffset - radius/2, y + treeHeight + yy - yyy - yOffset +2, z + zz- zOffset, Blocks.log, blocks);
setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yyy - yOffset +3, z + zz- zOffset, Blocks.log, blocks);
setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yyy - yOffset +2, z + zz- zOffset + 1, Blocks.log, blocks);
setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yyy - yOffset +2, z + zz- zOffset - 1, Blocks.log, blocks);
}
}
}
//roots
for(Entry<BlockPosition, BlockMeta> entry : cachedRoots.entrySet())
setBlock( entry.getKey().x + x - radius/2, y + entry.getKey().y, z + entry.getKey().z, entry.getValue().getBlock(), blocks);
}
}
private void setBlock(int x, int y, int z , Block block, Block[] blocks) {
if(x > 15 || x < 0 || z > 15 || z < 0 || y < 0 || y > 255)
return;
int index = (x * 16 + z) * 256 + y;
blocks[index] = block;
}
private Block getBlock(int x, int y, int z , Block block, Block[] blocks) {
if(x > 15 || x < 0 || z > 15 || z < 0 || y < 0 || y > 255)
return Blocks.air;
int index = (x * 16 + z) * 256 + y;
return blocks[index];
}
public boolean generate(World world, Random rand, int x, int y, int z)
{
int treeHeight = rand.nextInt(10) + 40;
int radius = 4;
boolean flag = true;
Block block2 = world.getBlock(x, y - 1, z);
int edgeRadius = 1;
int numDiag = edgeRadius + 1;
int meta = 3;
Block block = Blocks.log;
int currentEdgeRadius;
final float SHAPE = 0.1f;
currentEdgeRadius = (int)((SHAPE*(edgeRadius * treeHeight )) + ((1f-SHAPE)*edgeRadius));
//Make the base of the crystal
//Generate the top trapezoid
for(int zOff = -numDiag - currentEdgeRadius/2; zOff <= -currentEdgeRadius/2; zOff++) {
for(int xOff = -numDiag -currentEdgeRadius/2; xOff <= numDiag + currentEdgeRadius/2; xOff++) {
for(int yOff = world.getHeightValue(x + xOff, z + zOff); yOff < y; yOff++) //Fills the gaps under the crystal
world.setBlock(x + xOff, yOff, z + zOff, block);
world.setBlock(x + xOff, y, z + zOff, block);
}
currentEdgeRadius++;
}
//Generate square segment
for(int zOff = -currentEdgeRadius/2; zOff <= currentEdgeRadius/2; zOff++) {
for(int xOff = -numDiag -currentEdgeRadius/2; xOff <= numDiag + currentEdgeRadius/2; xOff++) {
for(int yOff = world.getHeightValue(x + xOff, z + zOff); yOff < y; yOff++) //Fills the gaps under the crystal
world.setBlock(x + xOff, yOff, z + zOff, block);
world.setBlock(x + xOff, y, z + zOff, block);
}
}
//Generate the bottom trapezoid
for(int zOff = currentEdgeRadius/2; zOff <= numDiag + currentEdgeRadius/2; zOff++) {
currentEdgeRadius--;
for(int xOff = -numDiag -currentEdgeRadius/2; xOff <= numDiag + currentEdgeRadius/2; xOff++) {
for(int yOff = world.getHeightValue(x + xOff, z + zOff); yOff < y; yOff++) //Fills the gaps under the crystal
world.setBlock(x + xOff, yOff, z + zOff, block);
world.setBlock(x + xOff, y, z + zOff, block);
}
}
y++;
for(int yOff = 0; yOff < treeHeight; yOff++) {
currentEdgeRadius = (int)((SHAPE*(edgeRadius * (treeHeight - yOff))) + ((1f-SHAPE)*edgeRadius));
//Generate the top trapezoid
for(int zOff = -numDiag - currentEdgeRadius/2; zOff <= -currentEdgeRadius/2; zOff++) {
for(int xOff = -numDiag -currentEdgeRadius/2; xOff <= numDiag + currentEdgeRadius/2; xOff++) {
world.setBlock(x + xOff, y + yOff, z + zOff, block, meta, 3);
}
currentEdgeRadius++;
}
//Generate square segment
for(int zOff = -currentEdgeRadius/2; zOff <= currentEdgeRadius/2; zOff++) {
for(int xOff = -numDiag -currentEdgeRadius/2; xOff <= numDiag + currentEdgeRadius/2; xOff++) {
world.setBlock(x + xOff, y + yOff, z + zOff, block, meta, 3);
}
}
//Generate the bottom trapezoid
for(int zOff = currentEdgeRadius/2; zOff <= numDiag + currentEdgeRadius/2; zOff++) {
currentEdgeRadius--;
for(int xOff = -numDiag -currentEdgeRadius/2; xOff <= numDiag + currentEdgeRadius/2; xOff++) {
world.setBlock(x + xOff, y + yOff, z + zOff, block, meta, 3);
}
}
}
//Canopy
for(Entry<BlockPosition, BlockMeta> entry : cachedCanopy.entrySet())
world.setBlock( entry.getKey().x + x - radius/2, y + treeHeight + entry.getKey().y, z + entry.getKey().z, entry.getValue().getBlock(), entry.getValue().getMeta(),2);
//Generate Logs
for (double Yangle = 0; Yangle < 2*Math.PI; Yangle+=Math.PI/8.0){
// Yangle = 0.0;//Math.PI/4.0;
int yOffset = (int)(arcSize*Math.sin(1.5*Math.PI/2.0));
int xOffset = (int)(1.25*arcSize*Math.cos(1.5*Math.PI/2.0)*Math.cos(Yangle));
int zOffset = (int)(1.25*arcSize*Math.cos(1.5*Math.PI/2.0)*Math.sin(Yangle));
for(double angle = 1.5*Math.PI/2.0; angle > -Math.PI/6.0; angle -= Math.PI/40.0) {
int yy = (int)(arcSize*Math.sin(angle));
double xzRadius = (1.25*arcSize*Math.cos(angle));
int xx = (int) (xzRadius*Math.cos(Yangle));
int zz = (int) (xzRadius*Math.sin(Yangle));
world.setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +2, z + zz- zOffset, Blocks.log, 3,5);
world.setBlock( x + 3 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +2, z + zz- zOffset, Blocks.log, 3,5);
world.setBlock( x + 1 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +2, z + zz- zOffset, Blocks.log, 3,5);
world.setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +3, z + zz- zOffset, Blocks.log, 3,5);
world.setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +2, z + zz- zOffset + 1, Blocks.log, 3,5);
world.setBlock( x + 2 + xx - xOffset - radius/2, y + treeHeight + yy - yOffset +2, z + zz- zOffset - 1, Blocks.log, 3,5);
}
//Generate the hangy things
if(rand.nextInt(4) == 0) {
int yy = (int)(arcSize*Math.sin(Math.PI/3.0));
double xzRadius = (1.25*arcSize*Math.cos(Math.PI/2.0));
int xx = (int) (xzRadius*Math.cos(Yangle));
int zz = (int) (xzRadius*Math.sin(Yangle));
int xxx = xx;
int zzz = zz;
//Leaf caps on bottom
for(zz = -1; zz < 2; zz++)
for(xx = -1; xx < 2; xx++)
world.setBlock( x + 2 + xx - xOffset - radius/2,y + treeHeight - 10 + yy - yOffset +2, z + zz- zOffset, Blocks.leaves, 3,5);
xx=xxx;
zz=zzz;
//Descending
for(int yyy = 0; yyy < 10; yyy++) {
for(zz = -2; zz < 3; zz++)
for(xx = -2; xx < 3; xx++)
world.setBlock( x + 2 + xx - xOffset - radius/2, y +treeHeight - yyy + yy - yOffset +2, z + zz- zOffset, Blocks.leaves, 3,5);
xx=xxx;
zz=zzz;
world.setBlock( x + 2 + xx - xOffset - radius/2, y +treeHeight + yy - yyy - yOffset +2, z + zz- zOffset, Blocks.log, 3,5);
world.setBlock( x + 3 + xx - xOffset - radius/2, y +treeHeight + yy - yyy - yOffset +2, z + zz- zOffset, Blocks.log, 3,5);
world.setBlock( x + 1 + xx - xOffset - radius/2, y +treeHeight + yy - yyy - yOffset +2, z + zz- zOffset, Blocks.log, 3,5);
world.setBlock( x + 2 + xx - xOffset - radius/2, y +treeHeight + yy - yyy - yOffset +3, z + zz- zOffset, Blocks.log, 3,5);
world.setBlock( x + 2 + xx - xOffset - radius/2, y +treeHeight + yy - yyy - yOffset +2, z + zz- zOffset + 1, Blocks.log, 3,5);
world.setBlock( x + 2 + xx - xOffset - radius/2, y +treeHeight + yy - yyy - yOffset +2, z + zz- zOffset - 1, Blocks.log, 3,5);
}
}
}
//roots
for(Entry<BlockPosition, BlockMeta> entry : cachedRoots.entrySet())
world.setBlock( entry.getKey().x + x - radius/2, y + entry.getKey().y, z + entry.getKey().z, entry.getValue().getBlock(), entry.getValue().getMeta(),2);
return true;
}
//Just a helper macro
private void onPlantGrow(World world, int x, int y, int z, int sourceX, int sourceY, int sourceZ)
{
world.getBlock(x, y, z).onPlantGrow(world, x, y, z, sourceX, sourceY, sourceZ);
}
}