package erebus.world.feature.plant;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.util.math.BlockPos;
import erebus.ModBlocks;
import erebus.blocks.ErebusHugeMushroom;
import erebus.core.helper.MathUtil;
import erebus.world.feature.WorldGenErebus;
import erebus.world.feature.util.OldForgeDirection;
public class WorldGenGiantMushrooms extends WorldGenErebus {
private static final int stalkMeta = 10;
private static final int bulbFullMeta = 14;
//private static final Block tempBlock = Blocks.BEDROCK;
public static final int[] offsetX = new int[] {0, -1, 0, 1};
public static final int[] offsetZ = new int[] {1, 0, -1, 0};
public enum MushroomType {
DARK_CAPPED(ModBlocks.DARK_CAPPED_MUSHROOM, ModBlocks.DARK_CAPPED_MUSHROOM_BLOCK),
GRANDMAS_SHOES(ModBlocks.GRANDMAS_SHOES_MUSHROOM, ModBlocks.GRANDMAS_SHOES_MUSHROOM_BLOCK),
SARCASTIC_CZECH(ModBlocks.SARCASTIC_CZECH_MUSHROOM, ModBlocks.SARCASTIC_CZECH_MUSHROOM_BLOCK),
KAIZERS_FINGERS(ModBlocks.KAIZERS_FINGERS_MUSHROOM, ModBlocks.KAIZERS_FINGERS_MUSHROOM_BLOCK),
DUTCH_CAP(ModBlocks.DUTCH_CAP_MUSHROOM, ModBlocks.DUTCH_CAP_MUSHROOM_BLOCK);
public final Block mushroom, block;
MushroomType(Block mushroom, Block log) {
this.block = log;
this.mushroom = mushroom;
}
public static MushroomType getFromShroom(Block block) {
for (MushroomType type : values())
if (type.mushroom == block)
return type;
return null;
}
}
private MushroomType mushroomType = MushroomType.DARK_CAPPED;
private final List<BlockPos> bulbs = new ArrayList<BlockPos>();
public void setMushroomType(MushroomType type) {
mushroomType = type;
}
@Override
protected boolean generate(BlockPos pos) {
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
bulbs.clear();
Block mushroom = mushroomType.block;
boolean res = false;
switch (mushroomType) {
case DARK_CAPPED:
res = genBulbCapped(x, y, z, mushroom);
break;
case KAIZERS_FINGERS:
res = genKaizersFingers(x, y, z, mushroom);
break;
case DUTCH_CAP:
res = genDutchCap(x - 1, y, z, mushroom);
break;
case GRANDMAS_SHOES:
res = genGrandmasShoes(x - 1, y, z, mushroom);
break;
case SARCASTIC_CZECH:
res = genSarcasticCzech(x - 1, y, z, mushroom);
default:
break;
}
if (res) {
generateBulbs(x, z, mushroom);
return true;
} else
return false;
}
/*
* MUSHROOM TYPE - BULB CAPPED
*/
private boolean genBulbCapped(int x, int y, int z, Block mushroom) {
int stalkHeight = 3 + rand.nextInt(3 + rand.nextInt(2));
int sideHeight = 1 + rand.nextInt(stalkHeight > 3 ? 3 : 2);
if (!checkAirCube(x, y, z, x, y + stalkHeight - sideHeight, z) || !checkAirCube(x - 2, y + stalkHeight - sideHeight + 1, z - 2, x + 2, y + stalkHeight + 1, z + 2))
return false;
setBlockPillar(x, z, y, y + stalkHeight, mushroom, stalkMeta);
y += stalkHeight + 1;
for (int px = -1; px <= 1; px++)
for (int pz = -1; pz <= 1; pz++)
bulbs.add(new BlockPos(x + px, y, z + pz));
for (int py = 1; py <= sideHeight; py++)
for (int off = -1; off <= 1; off++) {
bulbs.add(new BlockPos(x + 2, y - py, z + off));
bulbs.add(new BlockPos(x - 2, y - py, z + off));
bulbs.add(new BlockPos(x + off, y - py, z + 2));
bulbs.add(new BlockPos(x + off, y - py, z - 2));
}
return true;
}
/*
* MUSHROOM TYPE - KAIZERS FINGERS
*/
private boolean genKaizersFingers(int x, int y, int z, Block mushroom) {
int mainShroomHeight = 4 + rand.nextInt(4);
if (!checkAirCube(x - 1, y + 3, z - 1, x + 1, y + mainShroomHeight + 1, z + 1) || !checkAirCube(x - 4, y, z - 4, x + 4, y + 2, z + 4) || !checkSolidCube(x - 4, y - 1, z - 4, x + 4, y - 1, z + 4))
return false;
for (int py = 0, sidesPlaced = 0; py <= mainShroomHeight; py++) {
setBlock(x, y + py, z, mushroom, stalkMeta);
if (py >= 2 && py < mainShroomHeight - 1 && rand.nextInt(4 + sidesPlaced * 2) == 0) {
int dir = rand.nextInt(4);
setBlock(x + offsetX[dir], y + py, z + offsetZ[dir], mushroom, bulbFullMeta);
++sidesPlaced;
}
}
bulbs.add(new BlockPos(x, y + mainShroomHeight + 1, z));
for (int a = 0; a < 4; a++)
bulbs.add(new BlockPos(x + offsetX[a], y + mainShroomHeight, z + offsetZ[a]));
List<BlockPos> connectList = new ArrayList<BlockPos>();
connectList.add(new BlockPos(x, y - 1, z));
for (int smallShroomAttempt = 0, xx, zz; smallShroomAttempt < 4 + rand.nextInt(7); smallShroomAttempt++) {
xx = x + rand.nextInt(4) - rand.nextInt(4);
zz = z + rand.nextInt(4) - rand.nextInt(4);
if (!isAir(xx, y, zz) || !isAir(xx - 1, y, zz) || !isAir(xx + 1, y, zz) || !isAir(xx, y, zz - 1) || !isAir(xx, y, zz + 1))
continue;
int smallShroomHeight = rand.nextBoolean() ? 1 : 1 + rand.nextInt(2);
setBlockPillar(xx, zz, y, y + smallShroomHeight - 1, mushroom, stalkMeta);
setBlock(xx, y + smallShroomHeight, zz, mushroom, bulbFullMeta);
connectList.add(new BlockPos(xx, y - 1, zz));
}
int coordAmt = connectList.size();
for (int connectionAttempt = 0, dir, xx, zz; connectionAttempt < 48; connectionAttempt++) {
BlockPos coords1 = connectList.get(rand.nextInt(coordAmt));
BlockPos coords2 = rand.nextInt(3) != 0 ? connectList.get(0) : connectList.get(rand.nextInt(coordAmt));
if (coords1 == coords2)
continue;
double dist = MathUtil.distance(coords1.getX() - coords2.getX(), coords1.getZ() - coords2.getZ());
if (dist < 1D)
continue;
dir = rand.nextInt(4);
xx = coords1.getX() + offsetX[dir];
zz = coords1.getZ() + offsetZ[dir];
if (MathUtil.distance(xx - coords2.getX(), zz - coords2.getZ()) < dist) {
setBlock(xx, y - 1, zz, mushroom, stalkMeta);
if (rand.nextInt(16) == 0)
setBlock(xx, y, zz, mushroom, stalkMeta);
coords1.add(offsetX[dir], 0, offsetZ[dir]);
}
}
return true;
}
/*
* MUSHROOM TYPE - DUTCH CAP
*/
private boolean genDutchCap(int x, int y, int z, Block mushroom) {
int height = 9 + rand.nextInt(8);
if (!checkAirCube(x - 2, y, z - 2, x + 3, y + 4, z + 3) || !checkAirCube(x - 3, y + 5, z - 3, x + 5, y + height + 1, z + 5) || !checkAirCube(x - 4, y + height + 2, z - 4, x + 7, y + height + 4, z + 7) || !checkSolidCube(x - 2, y - 1, z - 2, x + 3, y - 1, z + 3))
return false;
for (int a = 0; a < 2; a++)
for (int b = 0; b < 2; b++) {
setBlockPillar(x - 1 + 3 * a, z + b, y, y + 1, mushroom, stalkMeta);
setBlockPillar(x + b, z - 1 + 3 * a, y, y + 1, mushroom, stalkMeta);
setBlock(x - 1 + 3 * a, y, z - 1 + 3 * b, mushroom, stalkMeta);
setBlock(x - 2 + 5 * a, y, z + b, mushroom, stalkMeta);
setBlock(x + b, y, z - 2 + 5 * a, mushroom, stalkMeta);
}
setBlockCube(x, y, z, x + 1, y + height, z + 1, mushroom, stalkMeta);
for (int py = 4; py <= height; py++) {
boolean isTop = py >= height - 1;
if (rand.nextInt(3) == 0 || isTop)
for (int attempt = 0; attempt < (isTop ? 2 : 1); attempt++) {
int branchAddX = 0, branchAddZ = 0;
for (int branchAttempt = 0; branchAttempt < 12 && branchAddX == 0 && branchAddZ == 0; branchAttempt++) {
branchAddX = rand.nextInt(3) != 0 ? 0 : rand.nextInt(3) - 1;
branchAddZ = rand.nextInt(3) != 0 ? 0 : rand.nextInt(3) - 1;
}
if (branchAddX == 0 && branchAddZ == 0)
continue;
if (!checkAirCube(x + branchAddX * 2, y + py - 2, z + branchAddZ * 2, x + branchAddX * 2 + 1, y + py, z + branchAddZ * 2 + 1))
continue;
int branchSize = isTop ? 3 + rand.nextInt(2) : 2 + rand.nextInt(2 + rand.nextInt(2));
for (int branch = 1; branch <= branchSize; branch++) {
setBlockRect(x + branchAddX * branch, z + branchAddZ * branch, x + branchAddX * branch + 1, z + branchAddZ * branch + 1, y + py - 1 + branch, mushroom, stalkMeta);
if (isTop)
setBlockRect(x + branchAddX * branch, z + branchAddZ * branch, x + branchAddX * branch + 1, z + branchAddZ * branch + 1, y + py + branch, mushroom, stalkMeta);
}
int branchTopX = x + branchAddX * branchSize, branchTopY = y + py + branchSize, branchTopZ = z + branchAddZ * branchSize;
if (isTop) {
setBlockRect(branchTopX, branchTopZ, branchTopX + 1, branchTopZ + 1, branchTopY + 1, mushroom, stalkMeta);
branchTopY += 2;
for (int a = 0; a < 2; a++)
for (int b = 0; b < 2; b++) {
if (isAir(branchTopX + a, branchTopY, branchTopZ + b))
setBlock(branchTopX + a, branchTopY, branchTopZ + b, mushroom, bulbFullMeta);
if (isAir(branchTopX - 1 + 3 * a, branchTopY - 1, branchTopZ + b))
setBlock(branchTopX - 1 + 3 * a, branchTopY - 1, branchTopZ + b, mushroom, bulbFullMeta);
if (isAir(branchTopX + b, branchTopY - 1, branchTopZ - 1 + 3 * a))
setBlock(branchTopX + b, branchTopY - 1, branchTopZ - 1 + 3 * a, mushroom, bulbFullMeta);
if (isAir(branchTopX - 1 + 3 * a, branchTopY - 2, branchTopZ - 1 + 3 * b))
setBlock(branchTopX - 1 + 3 * a, branchTopY - 2, branchTopZ - 1 + 3 * b, mushroom, bulbFullMeta);
if (isAir(branchTopX - 2 + 5 * a, branchTopY - 2, branchTopZ + b))
setBlock(branchTopX - 2 + 5 * a, branchTopY - 2, branchTopZ + b, mushroom, bulbFullMeta);
if (isAir(branchTopX + b, branchTopY - 2, branchTopZ - 2 + 5 * a))
setBlock(branchTopX + b, branchTopY - 2, branchTopZ - 2 + 5 * a, mushroom, bulbFullMeta);
}
} else
for (int a = 0; a < 2; a++)
for (int b = 0; b < 2; b++) {
if (isAir(branchTopX + a, branchTopY, branchTopZ + b))
setBlock(branchTopX + a, branchTopY, branchTopZ + b, mushroom, bulbFullMeta);
if (isAir(branchTopX - 1 + 3 * a, branchTopY - 1, branchTopZ + b))
setBlock(branchTopX - 1 + 3 * a, branchTopY - 1, branchTopZ + b, mushroom, bulbFullMeta);
if (isAir(branchTopX + b, branchTopY - 1, branchTopZ - 1 + 3 * a))
setBlock(branchTopX + b, branchTopY - 1, branchTopZ - 1 + 3 * a, mushroom, bulbFullMeta);
}
}
}
return true;
}
/*
* MUSHROOM TYPE - GRANDMA'S SHOES
*/
private boolean genGrandmasShoes(int x, int y, int z, Block mushroom) {
int height = 5 + rand.nextInt(8), splits = rand.nextInt(height > 8 ? 3 : 2), splitSize = splits == 0 ? height : (int) Math.ceil(height / (1F + splits)), splitDir = splits != 0 ? rand.nextInt(4) : -1;
int splitOffX = splitDir == -1 ? 0 : offsetX[splitDir], splitOffZ = splitDir == -1 ? 0 : offsetZ[splitDir];
if (!checkAirCube(x - 1, y, z - 1, x + 2, y + height - 2, z + 2) || !checkAirCube(x - 3 + splitOffX, z - 3 + splitOffZ, y + height - 1, x + 3 + splitOffX, y + height + 1, z + 3 + splitOffZ) || !checkSolidCube(x - 1, y - 1, z - 1, x + 3, y - 1, z + 3))
return false;
for (int a = 0; a < 2; a++)
for (int b = 0; b < 2; b++) {
setBlockRect(x - 1 + 3 * b, z, x - 1 + 3 * b, z + 1, y, mushroom, stalkMeta);
setBlockRect(x, z - 1 + 3 * b, x + 1, z - 1 + 3 * b, y, mushroom, stalkMeta);
}
for (int py = 0, split = splitSize; py <= height; py++) {
setBlockRect(x, z, x + 1, z + 1, y + py, mushroom, stalkMeta);
if (--split < 0 && py < height) {
x += splitOffX;
z += splitOffZ;
split = splitSize - 1;
}
}
for (int a = 0; a < 2; a++) {
for (int b = 0; b < 2; b++) {
bulbs.add(new BlockPos(x + a, y + height + 1, z + b));
bulbs.add(new BlockPos(x - 1 + 3 * a, y + height + 1, z + b));
bulbs.add(new BlockPos(x + b, y + height + 1, z - 1 + 3 * a));
setBlock(x - 1 + 3 * a, y + height, z - 1 + 3 * b, mushroom, 5); // top
// only
bulbs.add(new BlockPos(x - 2 + 5 * a, y + height - 1, z - 2 + 5 * b));
}
for (int b = 0; b < 4; b++) {
bulbs.add(new BlockPos(x - 2 + 5 * a, y + height, z - 1 + b));
bulbs.add(new BlockPos(x - 1 + b, y + height, z - 2 + 5 * a));
bulbs.add(new BlockPos(x - 3 + 7 * a, y + height - 1, z - 1 + b));
bulbs.add(new BlockPos(x - 1 + b, y + height - 1, z - 3 + 7 * a));
}
}
return true;
}
/*
* MUSHROOM TYPE - SARCASTIC CZECH
*/
private boolean genSarcasticCzech(int x, int y, int z, Block mushroom) {
int height = 2 + rand.nextInt(3);
int armLength = 4 + rand.nextInt(3);
if (!checkAirCube(x, y, z, x, y + height, z) || !checkAirCube(x - armLength, y + height, z - armLength, x + armLength, y + height + 1, z + armLength))
return false;
setBlockPillar(x, z, y, y + height, mushroom, stalkMeta);
setBlockPillar(x + 1, z, y, y + height, mushroom, stalkMeta);
setBlockPillar(x, z + 1, y, y + height, mushroom, stalkMeta);
setBlockPillar(x + 1, z + 1, y, y + height, mushroom, stalkMeta);
y += height;
//temp fix until gany fixes (t)his shit :P
for (OldForgeDirection[] dirs : new OldForgeDirection[][] { new OldForgeDirection[] { OldForgeDirection.EAST, OldForgeDirection.SOUTH }, new OldForgeDirection[] { OldForgeDirection.EAST, OldForgeDirection.NORTH }, new OldForgeDirection[] { OldForgeDirection.WEST, OldForgeDirection.SOUTH }, new OldForgeDirection[] { OldForgeDirection.WEST, OldForgeDirection.NORTH } }) {
int xx = x + dirs[0].offsetX;
int yy = y;
int zz = z + dirs[0].offsetZ;
for (int i = 0; i < armLength; i++) {
if (i % 2 == 0)
yy++;
else {
OldForgeDirection dir = dirs[rand.nextInt(dirs.length)];
xx += dir.offsetX;
zz += dir.offsetZ;
}
setBlock(xx, yy, zz, mushroom, stalkMeta);
}
setBlock(xx, yy + 1, zz, mushroom, bulbFullMeta);
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
setBlock(xx + i, yy, zz + j, mushroom, bulbFullMeta);
}
setBlockRect(x, z, x + 1, z + 1, y + 1, mushroom, bulbFullMeta);
setBlockRect(x - 1, z - 1, x + 2, z + 2, y, mushroom, bulbFullMeta);
System.out.println("Did Gen");
return true;
}
/*
* BULB METADATA
*/
private void generateBulbs(int centerX, int centerZ, Block mushroom) {
for (BlockPos bulb : bulbs)
setBlock(bulb.getX(), bulb.getY(), bulb.getZ(), mushroom);
for (BlockPos bulb : bulbs)
setMetadata(bulb.getX(), bulb.getY(), bulb.getZ(), getBulbMetadata(centerX, centerZ, bulb));
//for (BlockPos bulb : bulbs) {
// int meta = getMetadata(bulb.getX(), bulb.getY(), bulb.getZ());
// System.out.println("Meta should ALSO not be 0 here: " + meta);
// setBlock(bulb.getX(), bulb.getY(), bulb.getZ(), mushroom, getMetadata(bulb.getX(), bulb.getY(), bulb.getZ()));
//}
bulbs.clear();
}
private int getBulbMetadata(int centerX, int centerZ, BlockPos bulb) {
boolean posX = getBlock(bulb.getX() + 1, bulb.getY(), bulb.getZ()) instanceof ErebusHugeMushroom, negX = getBlock(bulb.getX() - 1, bulb.getY(), bulb.getZ()) instanceof ErebusHugeMushroom, posZ = getBlock(bulb.getX(), bulb.getY(), bulb.getZ() + 1) instanceof ErebusHugeMushroom, negZ = getBlock(bulb.getX(), bulb.getY(), bulb.getZ() - 1) instanceof ErebusHugeMushroom;
if (posX && negX && posZ && negZ)
return 5; // if surrounded, use top only
if (posX && negX)
if (bulb.getZ() > centerZ)
return 8; // use top and south
else
return 2; // use top and north
if (posZ && negZ)
if (bulb.getX() > centerX)
return 6; // use top and east
else
return 4; // use top and west
if (posX && posZ)
return 1; // use top, north and west
if (negX && negZ)
return 9; // use top, south and east
if (negX && posZ)
return 3; // use top, north and east
if (posX && negZ)
return 7; // use top, south and west
int sides = (posX ? 1 : 0) + (negX ? 1 : 0) + (posZ ? 1 : 0) + (negZ ? 1 : 0);
if (sides > 1)
return 0; // go away, you're no longer needed here
boolean posXposZ = getBlock(bulb.getX() + 1, bulb.getY(), bulb.getZ() + 1) instanceof ErebusHugeMushroom, negXposZ = getBlock(bulb.getX() - 1, bulb.getY(), bulb.getZ() + 1) instanceof ErebusHugeMushroom, posXnegZ = getBlock(bulb.getX() + 1, bulb.getY(), bulb.getZ() - 1) instanceof ErebusHugeMushroom, negXnegZ = getBlock(bulb.getX() - 1, bulb.getY(), bulb.getZ() - 1) instanceof ErebusHugeMushroom;
int corners = (posXposZ ? 1 : 0) + (negXposZ ? 1 : 0) + (posXnegZ ? 1 : 0) + (negXnegZ ? 1 : 0);
if (sides == 0 && corners == 0)
return 14; // use full cap for lonely shrooms
if (posXposZ && negXposZ || negXnegZ && posXnegZ || posXposZ && posXnegZ || negXposZ && negXnegZ)
return 14; // use full cap for + pattern
if (sides == 0 && corners == 2)
for (int dir = 0, meta; dir < 4; dir++) {
meta = getMetadata(bulb.getX() + offsetX[dir], bulb.getY() - 1, bulb.getZ() + offsetZ[dir]);
if (meta != 0)
return meta; // use meta of cap above and to the side - either 2 side cap or full cap
}
if (sides == 1 && corners == 1 || sides == 0 && corners == 2)
if (bulb.getX() > centerX) {
if (bulb.getZ() > centerZ)
return 9; // use top, south and east
else
return 3; // use top, north and east
} else if (bulb.getZ() > centerZ)
return 7; // use top, south and west
else
return 1; // use top, north and west
return 0;
}
}