package net.tropicraft.world.worldgen;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntityChest;
import net.minecraft.tileentity.TileEntityMobSpawner;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import net.tropicraft.info.TCInfo;
import net.tropicraft.registry.TCBlockRegistry;
import net.tropicraft.registry.TCItemRegistry;
import net.tropicraft.world.biomes.BiomeGenRainforest;
public class WorldGenHomeTree extends TCGenBase {
private class BranchNode
{
public int x1, y1, z1;
public int x2, y2, z2;
public BranchNode(int i, int j, int k, int x, int y, int z)
{
x1 = i;
y1 = j;
z1 = k;
x2 = x;
y2 = y;
z2 = z;
}
}
private final Block woodID = TCBlockRegistry.logs;
private final int woodMeta = 1;
private final Block leafID = TCBlockRegistry.rainforestLeaves;
private final int leafMeta = 0;
private ArrayList<BranchNode> branchList = new ArrayList();
private int trunkRadius;
public WorldGenHomeTree(World world, Random random) {
super(world, random);
}
@Override
public boolean generate(int i, int j, int k) {
j = 127;
trunkRadius = rand.nextInt(3) + 7;
for(int x = i - trunkRadius; x < i + trunkRadius; x++)
{
for(int z = k - trunkRadius; z < k + trunkRadius; z++)
{
int tHeight = getTerrainHeightAt(x, z);
if(tHeight < j)
{
j = tHeight;
}
}
}
/* BiomeGenBase currentBiome = worldObj.getWorldChunkManager().getBiomeGenAt(i, k);
if(!(currentBiome instanceof BiomeGenRainforest)) {
return false;
}*/
int height = rand.nextInt(20) + 30;
if(height + j + 12 > 255) {
return false;
}
System.err.println("HOME TREE INCOMING!" + " " + i + " " + j + " " + k);
int[] top = generateTrunk(i, j, k, height);
generateBranches(top[0], top[1], height + j);
return true;
}
public int[] generateTrunk(int i, int j, int k, int height)
{
int bn = 0;
int chanceToDisplace = 0;
int xDisplace = rand.nextBoolean() ? 1 : -1;
int zDisplace = rand.nextBoolean() ? 1 : -1;
int trunkX = i;
int trunkZ = k;
for(int y = j; y < height + j; y++)
{
chanceToDisplace++;
genCircle(trunkX, y, trunkZ, trunkRadius, trunkRadius - 3, woodID, woodMeta, false);
if(y == height + j - 1 || ((y - j) % 6 == 0))
{
genCircle(trunkX, y, trunkZ, trunkRadius, 2, woodID, woodMeta, false);
placeBlock(trunkX + 1, y, trunkZ + 1, woodID, woodMeta, false);
placeBlock(trunkX + 1, y, trunkZ - 1, woodID, woodMeta, false);
placeBlock(trunkX - 1, y, trunkZ + 1, woodID, woodMeta, false);
placeBlock(trunkX - 1, y, trunkZ - 1, woodID, woodMeta, false);
double angle = rand.nextDouble() * 3.141592D * 2D;
if(rand.nextInt(3) == 0)
{
double length = rand.nextDouble() * trunkRadius - 4;
int spawnerX = trunkX - 4 + rand.nextInt(9);
int spawnerZ = trunkZ - 4 + rand.nextInt(9);
worldObj.setBlock(spawnerX, y + 1, spawnerZ, Blocks.mob_spawner);
StringBuilder sb = new StringBuilder(String.format("%s.", TCInfo.MODID));
sb.append(rand.nextBoolean() ? "AshenHunter" : "Iguana");
TileEntityMobSpawner spawner = ((TileEntityMobSpawner)worldObj.getTileEntity(spawnerX, y + 1, spawnerZ));
if(spawner != null)
{
spawner.func_145881_a().setEntityName(sb.toString());
}
}
}
placeBlock(trunkX, y, trunkZ, woodID, woodMeta, false);
placeBlock(trunkX + 1, y, trunkZ, Blocks.vine, 2, false);
placeBlock(trunkX - 1, y, trunkZ, Blocks.vine, 2, false);
placeBlock(trunkX, y, trunkZ + 1, Blocks.vine, 2, false);
placeBlock(trunkX, y, trunkZ - 1, Blocks.vine, 2, false);
if(rand.nextInt(6) == 0);
{
if(y >= j + height - 6)
{
int branches = rand.nextInt(4) + 2;
for(int x = 0; x < branches; x++)
{
int branchLength = rand.nextInt(10) + 15;
int branchX1 = trunkX;
int branchZ1 = trunkZ;
double angle = rand.nextDouble() * 3.141592D * 2D;
branchX1 = (int)((trunkRadius * Math.sin(angle)) + branchX1);
branchZ1 = (int)((trunkRadius * Math.cos(angle)) + branchZ1);
int branchX2 = (int)((branchLength * Math.sin(angle)) + branchX1);
int branchZ2 = (int)((branchLength * Math.cos(angle)) + branchZ1);
int branchY2 = rand.nextInt(4) + 4;
branchList.add(new BranchNode(branchX1, y, branchZ1, branchX2, y + branchY2, branchZ2));
bn++;
}
}
}
if(rand.nextInt(6) + 4 <= chanceToDisplace && chanceToDisplace * 9 > y)
{
if(rand.nextBoolean())
{
trunkX += xDisplace;
if(rand.nextBoolean())
{
trunkZ += zDisplace;
}
}
else if(rand.nextBoolean())
{
trunkZ += zDisplace;
if(rand.nextBoolean())
{
trunkZ += xDisplace;
}
}
chanceToDisplace = 0;
}
placeBlock(trunkX, y, trunkZ, Blocks.log, 0, false);
}
worldObj.setBlock(trunkX - 1, height + j, trunkZ - 1, TCBlockRegistry.bambooChest);
TileEntityChest chest = (TileEntityChest)worldObj.getTileEntity(trunkX - 1, height + j, trunkZ - 1);
if(chest != null)
{
int treasure = rand.nextInt(6) + 4;
for(int x = 0; x < treasure; x++)
{
chest.setInventorySlotContents(rand.nextInt(chest.getSizeInventory()), randLoot());
}
}
return new int[] {trunkX, trunkZ};
}
public void generateBranches(int topX, int topZ, int height)
{
for(int x = 0; x < branchList.size(); x++)
{
BranchNode bnode = branchList.get(x);
int lSize = 3;
if(!checkBlockLine(new int[] { bnode.x1, bnode.y1, bnode.z1 }, new int[] {bnode.x2, bnode.y2, bnode.z2 }, this.standardAllowedBlocks) && !checkBlockLine(new int[] { bnode.x1 + 1, bnode.y1, bnode.z1 }, new int[] {bnode.x2 + 1, bnode.y2, bnode.z2 }, this.standardAllowedBlocks) && !checkBlockLine(new int[] { bnode.x1 - 1, bnode.y1, bnode.z1 }, new int[] {bnode.x2 - 1, bnode.y2, bnode.z2 }, this.standardAllowedBlocks) && !checkBlockLine(new int[] { bnode.x1, bnode.y1, bnode.z1 + 1 }, new int[] {bnode.x2, bnode.y2, bnode.z2 + 1 }, this.standardAllowedBlocks) && !checkBlockLine(new int[] { bnode.x1, bnode.y1, bnode.z1 - 1 }, new int[] {bnode.x2, bnode.y2, bnode.z2 - 1 }, this.standardAllowedBlocks) && !checkBlockLine(new int[] { bnode.x1, bnode.y1 - 1, bnode.z1 }, new int[] {bnode.x2, bnode.y2 - 1, bnode.z2 }, this.standardAllowedBlocks))
{
continue;
}
placeBlockLine(new int[] { bnode.x1, bnode.y1, bnode.z1 }, new int[] {bnode.x2, bnode.y2, bnode.z2 }, woodID, woodMeta);
placeBlockLine(new int[] { bnode.x1 + 1, bnode.y1, bnode.z1 }, new int[] {bnode.x2 + 1, bnode.y2, bnode.z2 }, woodID, woodMeta);
placeBlockLine(new int[] { bnode.x1 - 1, bnode.y1, bnode.z1 }, new int[] {bnode.x2 - 1, bnode.y2, bnode.z2 }, woodID, woodMeta);
placeBlockLine(new int[] { bnode.x1, bnode.y1, bnode.z1 + 1 }, new int[] {bnode.x2, bnode.y2, bnode.z2 + 1 }, woodID, woodMeta);
placeBlockLine(new int[] { bnode.x1, bnode.y1, bnode.z1 - 1 }, new int[] {bnode.x2, bnode.y2, bnode.z2 - 1 }, woodID, woodMeta);
placeBlockLine(new int[] { bnode.x1, bnode.y1 - 1, bnode.z1 }, new int[] {bnode.x2, bnode.y2 - 1, bnode.z2 }, woodID, woodMeta);
if(bnode.y2 + 1 <= height)
{
placeBlockLine(new int[] { bnode.x1, bnode.y1 + 1, bnode.z1 }, new int[] {bnode.x2, bnode.y2 + 1, bnode.z2 }, woodID, woodMeta);
}
genLeafCircle(bnode.x2, bnode.y2 - 1, bnode.z2, lSize + 5, lSize + 3, leafID, leafMeta, true);
genLeafCircle(bnode.x2, bnode.y2, bnode.z2, lSize + 6, 0, leafID, leafMeta, true);
genLeafCircle(bnode.x2, bnode.y2 + 1, bnode.z2, lSize + 10, 0, leafID, leafMeta, true);
genLeafCircle(bnode.x2, bnode.y2 + 2, bnode.z2, lSize + 9, 0, leafID, leafMeta, true);
}
int topBranches = rand.nextInt(6) + 6;
/*for(int x = 0; x < topBranches; x++)
{
int branchLength = rand.nextInt(10) + 15;
int baseDistance = rand.nextInt(trunkRadius - 3);
int branchX1 = topX;
int branchZ1 = topZ;
double angle = rand.nextDouble() * 3.141592D * 2D;
branchX1 = (int)((baseDistance * Math.sin(angle)) + branchX1);
branchZ1 = (int)((baseDistance * Math.cos(angle)) + branchZ1);
int branchX2 = (int)((branchLength * Math.sin(angle)) + branchX1);
int branchZ2 = (int)((branchLength * Math.cos(angle)) + branchZ1);
int branchHeight = height + rand.nextInt(4);
int leafRadius = rand.nextInt(5) - 3;
genTopBranch(branchX1, height, branchZ1, branchX1, height + rand.nextInt(4) + 4, branchZ1, topX, topZ);
genLeafCircle(branchX1, branchHeight - 1, branchZ1, leafRadius + 5, leafRadius + 3, leafID, leafMeta, true);
genLeafCircle(branchX1, branchHeight, branchZ1, leafRadius + 6, 0, leafID, leafMeta, true);
genLeafCircle(branchX1, branchHeight + 1, branchZ1, leafRadius + 10, 0, leafID, leafMeta, true);
genLeafCircle(branchX1, branchHeight + 2, branchZ1, leafRadius + 9, 0, leafID, leafMeta, true);
}*/
}
public boolean genTopBranch(int i, int j, int k, int sX, int sY, int sZ, int topX, int topZ)
{
ArrayList<Block> allowedBlocks = new ArrayList(this.standardAllowedBlocks);
allowedBlocks.add(woodID);
allowedBlocks.add(leafID);
allowedBlocks.add(Blocks.vine);
int branchSize = rand.nextInt(2) + 4;
ArrayList<int[]> lines = new ArrayList<int[]>();
for(int x = i - branchSize; x < i + branchSize; x++)
{
for(int z = k - branchSize; z < k + branchSize; z++)
{
if((x - i) * (x - i) + (z - k) * (z - k) < branchSize * branchSize && (x - topX) * (x - topX) + (z - topZ) * (z - topZ) < trunkRadius * trunkRadius)
{
if(!checkBlockLine(new int[] { x, j, z }, new int[] { sX + (i - x), sY, sZ + (k - z) }, allowedBlocks))
{
return false;
}
}
}
}
for(int x = i - branchSize; x < i + branchSize; x++)
{
for(int z = k - branchSize; z < k + branchSize; z++)
{
if((x - i) * (x - i) + (z - k) * (z - k) < branchSize * branchSize && (x - topX) * (x - topX) + (z - topZ) * (z - topZ) < trunkRadius * trunkRadius)
{
placeBlockLine(new int[] { x, j, z }, new int[] { sX + (i - x), sY, sZ + (k - z) }, woodID, woodMeta);
}
}
}
return true;
}
public void genLeafCircle(int x, int y, int z, int outerRadius, int innerRadius, Block leafID2, int meta, boolean vines)
{
int outerRadiusSquared = outerRadius * outerRadius;
int innerRadiusSquared = innerRadius * innerRadius;
for(int i = -outerRadius + x; i < outerRadius + x; i++)
{
for(int k = -outerRadius + z; k < outerRadius + z; k++)
{
double d = (x - i) * (x - i) + (z - k) * (z - k);
if(d <= outerRadiusSquared && d >= innerRadiusSquared)
{
if(worldObj.isAirBlock(i, y, k) || worldObj.getBlock(i, y, k) == leafID2)
{
placeBlock(i, y, k, leafID2, meta, false);
}
if(rand.nextInt(20) == 0 && vines)
{
genVines(i, y - 1, k);
}
}
}
}
}
public void genVines(int i, int j, int k)
{
int length = rand.nextInt(15) + 8;
int dir = rand.nextInt(4);
for(int y = j; y > j - length; y--)
{
if(worldObj.isAirBlock(i, y, k))
{
placeBlock(i, y, k, Blocks.vine, dir, false);
}
else break;
}
}
public boolean placeBlock(int i, int j, int k, Block woodID2, int meta, boolean force)
{
Block bID = worldObj.getBlock(i, j, k);
if(force || bID == Blocks.water || bID == Blocks.flowing_water || bID == TCBlockRegistry.tropicsWater
|| /* flowing tropics water */ bID == Blocks.air)
{
if(meta == 0)
{
return worldObj.setBlock(i, j, k, woodID2, 0, 0);
}
return worldObj.setBlock(i, j, k, woodID2, meta, 0);
}
return false;
}
@Override
public boolean genCircle(int i, int j, int k, double outerRadius, double innerRadius, Block id, int meta, boolean solid)
{
boolean hasGenned = false;
double outerRadiusSquared = outerRadius * outerRadius;
double innerRadiusSquared = innerRadius * innerRadius;
for(int x = (int)-outerRadius + i; x < (int)outerRadius + i; x++)
{
for(int z = (int)-outerRadius + k; z < (int)outerRadius + k; z++)
{
double d = (x - i) * (x - i) + (z - k) * (z - k);
if(d <= outerRadiusSquared && d >= innerRadiusSquared)
{
Block bID = worldObj.getBlock(x, j, z);
if((bID == Blocks.air || bID == Blocks.water || bID == Blocks.flowing_water)
|| bID == TCBlockRegistry.tropicsWater
|| /*bID == TCBlockRegistry.tropicsWaterFlowing ||*/ solid)
{
if(placeBlock(x, j, z, id, meta, solid))
{
hasGenned = true;
}
}
}
}
}
return hasGenned;
}
@Override
public ArrayList<int[]> placeBlockLine(int ai[], int ai1[], Block i, int meta)
{
ArrayList<int[]> places = new ArrayList<int[]>();
int ai2[] = {
0, 0, 0
};
byte byte0 = 0;
int j = 0;
for(; byte0 < 3; byte0++)
{
ai2[byte0] = ai1[byte0] - ai[byte0];
if(Math.abs(ai2[byte0]) > Math.abs(ai2[j]))
{
j = byte0;
}
}
if(ai2[j] == 0)
{
return null;
}
byte byte1 = otherCoordPairs[j];
byte byte2 = otherCoordPairs[j + 3];
byte byte3;
if(ai2[j] > 0)
{
byte3 = 1;
} else
{
byte3 = -1;
}
double d = (double)ai2[byte1] / (double)ai2[j];
double d1 = (double)ai2[byte2] / (double)ai2[j];
int ai3[] = {
0, 0, 0
};
int k = 0;
for(int l = ai2[j] + byte3; k != l; k += byte3)
{
ai3[j] = MathHelper.floor_double(ai[j] + k + 0.5D);
ai3[byte1] = MathHelper.floor_double(ai[byte1] + k * d + 0.5D);
ai3[byte2] = MathHelper.floor_double(ai[byte2] + k * d1 + 0.5D);
placeBlock(ai3[0], ai3[1], ai3[2], i, meta, true);
places.add(new int[] { ai3[0], ai3[1], ai3[2] });
}
return places;
}
@Override
public ArrayList<int[]> checkAndPlaceBlockLine(int ai[], int ai1[], Block i, int meta, List a)
{
ArrayList<int[]> places = new ArrayList<int[]>();
int ai2[] = {
0, 0, 0
};
byte byte0 = 0;
int j = 0;
for(; byte0 < 3; byte0++)
{
ai2[byte0] = ai1[byte0] - ai[byte0];
if(Math.abs(ai2[byte0]) > Math.abs(ai2[j]))
{
j = byte0;
}
}
if(ai2[j] == 0)
{
return null;
}
byte byte1 = otherCoordPairs[j];
byte byte2 = otherCoordPairs[j + 3];
byte byte3;
if(ai2[j] > 0)
{
byte3 = 1;
} else
{
byte3 = -1;
}
double d = (double)ai2[byte1] / (double)ai2[j];
double d1 = (double)ai2[byte2] / (double)ai2[j];
int ai3[] = {
0, 0, 0
};
int k = 0;
for(int l = ai2[j] + byte3; k != l; k += byte3)
{
ai3[j] = MathHelper.floor_double(ai[j] + k + 0.5D);
ai3[byte1] = MathHelper.floor_double(ai[byte1] + k * d + 0.5D);
ai3[byte2] = MathHelper.floor_double(ai[byte2] + k * d1 + 0.5D);
Block bId = worldObj.getBlock(ai3[0], ai3[1], ai3[2]);
if(!a.contains(bId))
{
return null;
}
}
for(int l = ai2[j] + byte3; k != l; k += byte3)
{
ai3[j] = MathHelper.floor_double(ai[j] + k + 0.5D);
ai3[byte1] = MathHelper.floor_double(ai[byte1] + k * d + 0.5D);
ai3[byte2] = MathHelper.floor_double(ai[byte2] + k * d1 + 0.5D);
placeBlock(ai3[0], ai3[1], ai3[2], i, meta, true);
places.add(new int[] { ai3[0], ai3[1], ai3[2] });
}
return places;
}
public ItemStack randLoot()
{
int picker = rand.nextInt(18);
if(picker < 6)
{
return new ItemStack(TCItemRegistry.bambooShoot, rand.nextInt(20) + 1);
}
else if(picker < 8)
{
return new ItemStack(TCItemRegistry.coconutBomb, rand.nextInt(3) + 1);
}
else if(picker < 10)
{
return new ItemStack(TCItemRegistry.scale, rand.nextInt(3) + 1);
}
// else if(picker < 12)
// {
// return new ItemStack(TCBlockRegistry.tropicsBuildingBlock, rand.nextInt(20) + 1);
// }
else if(picker < 14)
{
return new ItemStack(TCItemRegistry.cookedFrogLeg, rand.nextInt(4) + 1);
}
/* else if(picker == 14)
{
return new ItemStack(TCItemRegistry.ashenMasks, 1, rand.nextInt(7));
}*/
else if(picker <= 15)
{
return new ItemStack(TCItemRegistry.recordTradeWinds, 1);
}
else if(picker == 16)
{
return new ItemStack(TCItemRegistry.recordEasternIsles, 1);
}
else
{
return new ItemStack(TCItemRegistry.ore, 1, 3);
}
}
}