package net.minecraft.world.gen.feature;
import com.google.common.collect.Lists;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLog;
import net.minecraft.block.material.Material;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
public class WorldGenBigTree extends WorldGenAbstractTree
{
private Random field_175949_k;
private World field_175946_l;
private BlockPos field_175947_m;
int heightLimit;
int height;
double heightAttenuation;
double field_175944_d;
double field_175945_e;
double leafDensity;
int field_175943_g;
int field_175950_h;
/**
* Sets the distance limit for how far away the generator will populate leaves from the base leaf node.
*/
int leafDistanceLimit;
List field_175948_j;
private static final String __OBFID = "CL_00000400";
public WorldGenBigTree(boolean p_i2008_1_)
{
super(p_i2008_1_);
this.field_175947_m = BlockPos.ORIGIN;
this.heightAttenuation = 0.618D;
this.field_175944_d = 0.381D;
this.field_175945_e = 1.0D;
this.leafDensity = 1.0D;
this.field_175943_g = 1;
this.field_175950_h = 12;
this.leafDistanceLimit = 4;
}
/**
* Generates a list of leaf nodes for the tree, to be populated by generateLeaves.
*/
void generateLeafNodeList()
{
this.height = (int)((double)this.heightLimit * this.heightAttenuation);
if (this.height >= this.heightLimit)
{
this.height = this.heightLimit - 1;
}
int var1 = (int)(1.382D + Math.pow(this.leafDensity * (double)this.heightLimit / 13.0D, 2.0D));
if (var1 < 1)
{
var1 = 1;
}
int var2 = this.field_175947_m.getY() + this.height;
int var3 = this.heightLimit - this.leafDistanceLimit;
this.field_175948_j = Lists.newArrayList();
this.field_175948_j.add(new WorldGenBigTree.FoliageCoordinates(this.field_175947_m.offsetUp(var3), var2));
for (; var3 >= 0; --var3)
{
float var4 = this.layerSize(var3);
if (var4 >= 0.0F)
{
for (int var5 = 0; var5 < var1; ++var5)
{
double var6 = this.field_175945_e * (double)var4 * ((double)this.field_175949_k.nextFloat() + 0.328D);
double var8 = (double)(this.field_175949_k.nextFloat() * 2.0F) * Math.PI;
double var10 = var6 * Math.sin(var8) + 0.5D;
double var12 = var6 * Math.cos(var8) + 0.5D;
BlockPos var14 = this.field_175947_m.add(var10, (double)(var3 - 1), var12);
BlockPos var15 = var14.offsetUp(this.leafDistanceLimit);
if (this.func_175936_a(var14, var15) == -1)
{
int var16 = this.field_175947_m.getX() - var14.getX();
int var17 = this.field_175947_m.getZ() - var14.getZ();
double var18 = (double)var14.getY() - Math.sqrt((double)(var16 * var16 + var17 * var17)) * this.field_175944_d;
int var20 = var18 > (double)var2 ? var2 : (int)var18;
BlockPos var21 = new BlockPos(this.field_175947_m.getX(), var20, this.field_175947_m.getZ());
if (this.func_175936_a(var21, var14) == -1)
{
this.field_175948_j.add(new WorldGenBigTree.FoliageCoordinates(var14, var21.getY()));
}
}
}
}
}
}
void func_180712_a(BlockPos p_180712_1_, float p_180712_2_, Block p_180712_3_)
{
int var4 = (int)((double)p_180712_2_ + 0.618D);
for (int var5 = -var4; var5 <= var4; ++var5)
{
for (int var6 = -var4; var6 <= var4; ++var6)
{
if (Math.pow((double)Math.abs(var5) + 0.5D, 2.0D) + Math.pow((double)Math.abs(var6) + 0.5D, 2.0D) <= (double)(p_180712_2_ * p_180712_2_))
{
BlockPos var7 = p_180712_1_.add(var5, 0, var6);
Material var8 = this.field_175946_l.getBlockState(var7).getBlock().getMaterial();
if (var8 == Material.air || var8 == Material.leaves)
{
this.func_175905_a(this.field_175946_l, var7, p_180712_3_, 0);
}
}
}
}
}
/**
* Gets the rough size of a layer of the tree.
*/
float layerSize(int p_76490_1_)
{
if ((float)p_76490_1_ < (float)this.heightLimit * 0.3F)
{
return -1.0F;
}
else
{
float var2 = (float)this.heightLimit / 2.0F;
float var3 = var2 - (float)p_76490_1_;
float var4 = MathHelper.sqrt_float(var2 * var2 - var3 * var3);
if (var3 == 0.0F)
{
var4 = var2;
}
else if (Math.abs(var3) >= var2)
{
return 0.0F;
}
return var4 * 0.5F;
}
}
float leafSize(int p_76495_1_)
{
return p_76495_1_ >= 0 && p_76495_1_ < this.leafDistanceLimit ? (p_76495_1_ != 0 && p_76495_1_ != this.leafDistanceLimit - 1 ? 3.0F : 2.0F) : -1.0F;
}
void func_175940_a(BlockPos p_175940_1_)
{
for (int var2 = 0; var2 < this.leafDistanceLimit; ++var2)
{
this.func_180712_a(p_175940_1_.offsetUp(var2), this.leafSize(var2), Blocks.leaves);
}
}
void func_175937_a(BlockPos p_175937_1_, BlockPos p_175937_2_, Block p_175937_3_)
{
BlockPos var4 = p_175937_2_.add(-p_175937_1_.getX(), -p_175937_1_.getY(), -p_175937_1_.getZ());
int var5 = this.func_175935_b(var4);
float var6 = (float)var4.getX() / (float)var5;
float var7 = (float)var4.getY() / (float)var5;
float var8 = (float)var4.getZ() / (float)var5;
for (int var9 = 0; var9 <= var5; ++var9)
{
BlockPos var10 = p_175937_1_.add((double)(0.5F + (float)var9 * var6), (double)(0.5F + (float)var9 * var7), (double)(0.5F + (float)var9 * var8));
BlockLog.EnumAxis var11 = this.func_175938_b(p_175937_1_, var10);
this.func_175903_a(this.field_175946_l, var10, p_175937_3_.getDefaultState().withProperty(BlockLog.AXIS_PROP, var11));
}
}
private int func_175935_b(BlockPos p_175935_1_)
{
int var2 = MathHelper.abs_int(p_175935_1_.getX());
int var3 = MathHelper.abs_int(p_175935_1_.getY());
int var4 = MathHelper.abs_int(p_175935_1_.getZ());
return var4 > var2 && var4 > var3 ? var4 : (var3 > var2 ? var3 : var2);
}
private BlockLog.EnumAxis func_175938_b(BlockPos p_175938_1_, BlockPos p_175938_2_)
{
BlockLog.EnumAxis var3 = BlockLog.EnumAxis.Y;
int var4 = Math.abs(p_175938_2_.getX() - p_175938_1_.getX());
int var5 = Math.abs(p_175938_2_.getZ() - p_175938_1_.getZ());
int var6 = Math.max(var4, var5);
if (var6 > 0)
{
if (var4 == var6)
{
var3 = BlockLog.EnumAxis.X;
}
else if (var5 == var6)
{
var3 = BlockLog.EnumAxis.Z;
}
}
return var3;
}
void func_175941_b()
{
Iterator var1 = this.field_175948_j.iterator();
while (var1.hasNext())
{
WorldGenBigTree.FoliageCoordinates var2 = (WorldGenBigTree.FoliageCoordinates)var1.next();
this.func_175940_a(var2);
}
}
/**
* Indicates whether or not a leaf node requires additional wood to be added to preserve integrity.
*/
boolean leafNodeNeedsBase(int p_76493_1_)
{
return (double)p_76493_1_ >= (double)this.heightLimit * 0.2D;
}
void func_175942_c()
{
BlockPos var1 = this.field_175947_m;
BlockPos var2 = this.field_175947_m.offsetUp(this.height);
Block var3 = Blocks.log;
this.func_175937_a(var1, var2, var3);
if (this.field_175943_g == 2)
{
this.func_175937_a(var1.offsetEast(), var2.offsetEast(), var3);
this.func_175937_a(var1.offsetEast().offsetSouth(), var2.offsetEast().offsetSouth(), var3);
this.func_175937_a(var1.offsetSouth(), var2.offsetSouth(), var3);
}
}
void func_175939_d()
{
Iterator var1 = this.field_175948_j.iterator();
while (var1.hasNext())
{
WorldGenBigTree.FoliageCoordinates var2 = (WorldGenBigTree.FoliageCoordinates)var1.next();
int var3 = var2.func_177999_q();
BlockPos var4 = new BlockPos(this.field_175947_m.getX(), var3, this.field_175947_m.getZ());
if (this.leafNodeNeedsBase(var3 - this.field_175947_m.getY()))
{
this.func_175937_a(var4, var2, Blocks.log);
}
}
}
int func_175936_a(BlockPos p_175936_1_, BlockPos p_175936_2_)
{
BlockPos var3 = p_175936_2_.add(-p_175936_1_.getX(), -p_175936_1_.getY(), -p_175936_1_.getZ());
int var4 = this.func_175935_b(var3);
float var5 = (float)var3.getX() / (float)var4;
float var6 = (float)var3.getY() / (float)var4;
float var7 = (float)var3.getZ() / (float)var4;
if (var4 == 0)
{
return -1;
}
else
{
for (int var8 = 0; var8 <= var4; ++var8)
{
BlockPos var9 = p_175936_1_.add((double)(0.5F + (float)var8 * var5), (double)(0.5F + (float)var8 * var6), (double)(0.5F + (float)var8 * var7));
if (!this.func_150523_a(this.field_175946_l.getBlockState(var9).getBlock()))
{
return var8;
}
}
return -1;
}
}
public void func_175904_e()
{
this.leafDistanceLimit = 5;
}
public boolean generate(World worldIn, Random p_180709_2_, BlockPos p_180709_3_)
{
this.field_175946_l = worldIn;
this.field_175947_m = p_180709_3_;
this.field_175949_k = new Random(p_180709_2_.nextLong());
if (this.heightLimit == 0)
{
this.heightLimit = 5 + this.field_175949_k.nextInt(this.field_175950_h);
}
if (!this.validTreeLocation())
{
return false;
}
else
{
this.generateLeafNodeList();
this.func_175941_b();
this.func_175942_c();
this.func_175939_d();
return true;
}
}
/**
* Returns a boolean indicating whether or not the current location for the tree, spanning basePos to to the height
* limit, is valid.
*/
private boolean validTreeLocation()
{
Block var1 = this.field_175946_l.getBlockState(this.field_175947_m.offsetDown()).getBlock();
if (var1 != Blocks.dirt && var1 != Blocks.grass && var1 != Blocks.farmland)
{
return false;
}
else
{
int var2 = this.func_175936_a(this.field_175947_m, this.field_175947_m.offsetUp(this.heightLimit - 1));
if (var2 == -1)
{
return true;
}
else if (var2 < 6)
{
return false;
}
else
{
this.heightLimit = var2;
return true;
}
}
}
static class FoliageCoordinates extends BlockPos
{
private final int field_178000_b;
private static final String __OBFID = "CL_00002001";
public FoliageCoordinates(BlockPos p_i45635_1_, int p_i45635_2_)
{
super(p_i45635_1_.getX(), p_i45635_1_.getY(), p_i45635_1_.getZ());
this.field_178000_b = p_i45635_2_;
}
public int func_177999_q()
{
return this.field_178000_b;
}
}
}