package net.glowstone.block.blocktype;
import net.glowstone.EventFactory;
import net.glowstone.GlowWorld;
import net.glowstone.block.GlowBlock;
import net.glowstone.block.GlowBlockState;
import net.glowstone.constants.GlowTree;
import net.glowstone.entity.GlowPlayer;
import net.glowstone.util.BlockStateDelegate;
import org.bukkit.DirtType;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.TreeType;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.event.block.BlockSpreadEvent;
import org.bukkit.event.world.StructureGrowEvent;
import org.bukkit.material.Dirt;
import org.bukkit.material.MaterialData;
import java.util.ArrayList;
import java.util.List;
public class BlockMushroom extends BlockNeedsAttached implements IBlockGrowable {
private final Material mushroomType;
public BlockMushroom(Material mushroomType) {
this.mushroomType = mushroomType;
}
@Override
public boolean canPlaceAt(GlowBlock block, BlockFace against) {
final GlowBlock belowBlock = block.getRelative(BlockFace.DOWN);
final Material type = belowBlock.getType();
final MaterialData data = belowBlock.getState().getData();
if (type == Material.GRASS || (data instanceof Dirt && ((Dirt) data).getType() != DirtType.PODZOL)) {
if (block.getLightLevel() < 13) { // checking light level for dirt, coarse dirt and grass
return true;
}
} else if (type == Material.MYCEL || (data instanceof Dirt && ((Dirt) data).getType() == DirtType.PODZOL)) {
// not checking light level if mycel or podzol
return true;
}
return false;
}
@Override
public boolean isFertilizable(GlowBlock block) {
return true;
}
@Override
public boolean canTickRandomly() {
return true;
}
@Override
public boolean canGrowWithChance(GlowBlock block) {
return (double) random.nextFloat() < 0.4D;
}
@Override
public void grow(GlowPlayer player, GlowBlock block) {
TreeType type;
if (mushroomType == Material.BROWN_MUSHROOM) {
type = TreeType.BROWN_MUSHROOM;
} else if (mushroomType == Material.RED_MUSHROOM) {
type = TreeType.RED_MUSHROOM;
} else {
return;
}
final Location loc = block.getLocation();
final BlockStateDelegate blockStateDelegate = new BlockStateDelegate();
if (GlowTree.newInstance(type, random, loc, blockStateDelegate).generate()) {
final List<BlockState> blockStates = new ArrayList<BlockState>(blockStateDelegate.getBlockStates());
StructureGrowEvent growEvent = new StructureGrowEvent(loc, type, true, player, blockStates);
EventFactory.callEvent(growEvent);
if (!growEvent.isCancelled()) {
for (BlockState state : blockStates) {
state.update(true);
}
}
}
}
@Override
public void updateBlock(GlowBlock block) {
if (random.nextInt(25) == 0) {
final GlowWorld world = block.getWorld();
int x, y, z;
int i = 0;
for (x = block.getX() - 4; x <= block.getX() + 4; x++) {
for (z = block.getZ() - 4; z <= block.getZ() + 4; z++) {
for (y = block.getY() - 1; y <= block.getY() + 1; y++) {
if (world.getBlockAt(x, y, z).getType() == mushroomType) {
if (++i > 4) {
return;
}
}
}
}
}
int nX, nY, nZ;
nX = block.getX() + random.nextInt(3) - 1;
nY = block.getY() + random.nextInt(2) - random.nextInt(2);
nZ = block.getZ() + random.nextInt(3) - 1;
x = block.getX(); y = block.getY(); z = block.getZ();
for (i = 0; i < 4; i++) {
if (world.getBlockAt(nX, nY, nZ).getType() == Material.AIR
&& canPlaceAt(world.getBlockAt(nX, nY, nZ), BlockFace.DOWN)) {
x = nX; y = nY; z = nZ;
}
nX = x + random.nextInt(3) - 1;
nY = y + random.nextInt(2) - random.nextInt(2);
nZ = z + random.nextInt(3) - 1;
}
if (world.getBlockAt(nX, nY, nZ).getType() == Material.AIR
&& canPlaceAt(world.getBlockAt(nX, nY, nZ), BlockFace.DOWN)) {
final GlowBlockState state = world.getBlockAt(nX, nY, nZ).getState();
state.setType(mushroomType);
BlockSpreadEvent spreadEvent = new BlockSpreadEvent(state.getBlock(), block, state);
EventFactory.callEvent(spreadEvent);
if (!spreadEvent.isCancelled()) {
state.update(true);
}
}
}
// mushroom does not uproot in vanilla due to a bug, but it should uproot as
// it is stated in the wiki
if (!canPlaceAt(block, BlockFace.DOWN)) {
block.breakNaturally();
}
}
}