package net.minecraft.server; import java.util.Iterator; import java.util.Map; import java.util.Random; import java.util.Map.Entry; import javax.annotation.Nullable; import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit public class BlockVine extends Block { public static final BlockStateBoolean UP = BlockSprawling.e; public static final BlockStateBoolean NORTH = BlockSprawling.a; public static final BlockStateBoolean EAST = BlockSprawling.b; public static final BlockStateBoolean SOUTH = BlockSprawling.c; public static final BlockStateBoolean WEST = BlockSprawling.d; public static final Map<EnumDirection, BlockStateBoolean> f = (Map) BlockSprawling.g.entrySet().stream().filter((entry) -> { return entry.getKey() != EnumDirection.DOWN; }).collect(SystemUtils.a()); protected static final VoxelShape g = Block.a(0.0D, 15.0D, 0.0D, 16.0D, 16.0D, 16.0D); protected static final VoxelShape h = Block.a(0.0D, 0.0D, 0.0D, 1.0D, 16.0D, 16.0D); protected static final VoxelShape i = Block.a(15.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D); protected static final VoxelShape j = Block.a(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 1.0D); protected static final VoxelShape k = Block.a(0.0D, 0.0D, 15.0D, 16.0D, 16.0D, 16.0D); public BlockVine(Block.Info block_info) { super(block_info); this.p((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.blockStateList.getBlockData()).set(BlockVine.UP, false)).set(BlockVine.NORTH, false)).set(BlockVine.EAST, false)).set(BlockVine.SOUTH, false)).set(BlockVine.WEST, false)); } @Override public VoxelShape a(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition, VoxelShapeCollision voxelshapecollision) { VoxelShape voxelshape = VoxelShapes.a(); if ((Boolean) iblockdata.get(BlockVine.UP)) { voxelshape = VoxelShapes.a(voxelshape, BlockVine.g); } if ((Boolean) iblockdata.get(BlockVine.NORTH)) { voxelshape = VoxelShapes.a(voxelshape, BlockVine.j); } if ((Boolean) iblockdata.get(BlockVine.EAST)) { voxelshape = VoxelShapes.a(voxelshape, BlockVine.i); } if ((Boolean) iblockdata.get(BlockVine.SOUTH)) { voxelshape = VoxelShapes.a(voxelshape, BlockVine.k); } if ((Boolean) iblockdata.get(BlockVine.WEST)) { voxelshape = VoxelShapes.a(voxelshape, BlockVine.h); } return voxelshape; } @Override public boolean canPlace(IBlockData iblockdata, IWorldReader iworldreader, BlockPosition blockposition) { return this.h(this.n(iblockdata, iworldreader, blockposition)); } private boolean h(IBlockData iblockdata) { return this.i(iblockdata) > 0; } private int i(IBlockData iblockdata) { int i = 0; Iterator iterator = BlockVine.f.values().iterator(); while (iterator.hasNext()) { BlockStateBoolean blockstateboolean = (BlockStateBoolean) iterator.next(); if ((Boolean) iblockdata.get(blockstateboolean)) { ++i; } } return i; } private boolean b(IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { if (enumdirection == EnumDirection.DOWN) { return false; } else { BlockPosition blockposition1 = blockposition.shift(enumdirection); if (a(iblockaccess, blockposition1, enumdirection)) { return true; } else if (enumdirection.m() == EnumDirection.EnumAxis.Y) { return false; } else { BlockStateBoolean blockstateboolean = (BlockStateBoolean) BlockVine.f.get(enumdirection); IBlockData iblockdata = iblockaccess.getType(blockposition.up()); return iblockdata.getBlock() == this && (Boolean) iblockdata.get(blockstateboolean); } } } public static boolean a(IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { IBlockData iblockdata = iblockaccess.getType(blockposition); return Block.a(iblockdata.getCollisionShape(iblockaccess, blockposition), enumdirection.opposite()); } private IBlockData n(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition) { BlockPosition blockposition1 = blockposition.up(); if ((Boolean) iblockdata.get(BlockVine.UP)) { iblockdata = (IBlockData) iblockdata.set(BlockVine.UP, a(iblockaccess, blockposition1, EnumDirection.DOWN)); } IBlockData iblockdata1 = null; Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); while (iterator.hasNext()) { EnumDirection enumdirection = (EnumDirection) iterator.next(); BlockStateBoolean blockstateboolean = getDirection(enumdirection); if ((Boolean) iblockdata.get(blockstateboolean)) { boolean flag = this.b(iblockaccess, blockposition, enumdirection); if (!flag) { if (iblockdata1 == null) { iblockdata1 = iblockaccess.getType(blockposition1); } flag = iblockdata1.getBlock() == this && (Boolean) iblockdata1.get(blockstateboolean); } iblockdata = (IBlockData) iblockdata.set(blockstateboolean, flag); } } return iblockdata; } @Override public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { if (enumdirection == EnumDirection.DOWN) { return super.updateState(iblockdata, enumdirection, iblockdata1, generatoraccess, blockposition, blockposition1); } else { IBlockData iblockdata2 = this.n(iblockdata, generatoraccess, blockposition); return !this.h(iblockdata2) ? Blocks.AIR.getBlockData() : iblockdata2; } } @Override public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { IBlockData iblockdata1 = this.n(iblockdata, worldserver, blockposition); if (iblockdata1 != iblockdata) { if (this.h(iblockdata1)) { worldserver.setTypeAndData(blockposition, iblockdata1, 2); } else { c(iblockdata, (World) worldserver, blockposition); worldserver.a(blockposition, false); } } else if (worldserver.random.nextInt(4) == 0) { EnumDirection enumdirection = EnumDirection.a(random); BlockPosition blockposition1 = blockposition.up(); BlockPosition blockposition2; IBlockData iblockdata2; EnumDirection enumdirection1; if (enumdirection.m().c() && !(Boolean) iblockdata.get(getDirection(enumdirection))) { if (this.a((IBlockAccess) worldserver, blockposition)) { blockposition2 = blockposition.shift(enumdirection); iblockdata2 = worldserver.getType(blockposition2); if (iblockdata2.isAir()) { enumdirection1 = enumdirection.f(); EnumDirection enumdirection2 = enumdirection.g(); boolean flag = (Boolean) iblockdata.get(getDirection(enumdirection1)); boolean flag1 = (Boolean) iblockdata.get(getDirection(enumdirection2)); BlockPosition blockposition3 = blockposition2.shift(enumdirection1); BlockPosition blockposition4 = blockposition2.shift(enumdirection2); // CraftBukkit start - Call BlockSpreadEvent BlockPosition source = blockposition; if (flag && a((IBlockAccess) worldserver, blockposition3, enumdirection1)) { CraftEventFactory.handleBlockSpreadEvent(worldserver, source, blockposition2, (IBlockData) this.getBlockData().set(getDirection(enumdirection1), true), 2); } else if (flag1 && a((IBlockAccess) worldserver, blockposition4, enumdirection2)) { CraftEventFactory.handleBlockSpreadEvent(worldserver, source, blockposition2, (IBlockData) this.getBlockData().set(getDirection(enumdirection2), true), 2); } else { EnumDirection enumdirection3 = enumdirection.opposite(); if (flag && worldserver.isEmpty(blockposition3) && a((IBlockAccess) worldserver, blockposition.shift(enumdirection1), enumdirection3)) { CraftEventFactory.handleBlockSpreadEvent(worldserver, source, blockposition3, (IBlockData) this.getBlockData().set(getDirection(enumdirection3), true), 2); } else if (flag1 && worldserver.isEmpty(blockposition4) && a((IBlockAccess) worldserver, blockposition.shift(enumdirection2), enumdirection3)) { CraftEventFactory.handleBlockSpreadEvent(worldserver, source, blockposition4, (IBlockData) this.getBlockData().set(getDirection(enumdirection3), true), 2); } else if ((double) worldserver.random.nextFloat() < 0.05D && a((IBlockAccess) worldserver, blockposition2.up(), EnumDirection.UP)) { CraftEventFactory.handleBlockSpreadEvent(worldserver, source, blockposition2, (IBlockData) this.getBlockData().set(BlockVine.UP, true), 2); } // CraftBukkit end } } else if (a((IBlockAccess) worldserver, blockposition2, enumdirection)) { worldserver.setTypeAndData(blockposition, (IBlockData) iblockdata.set(getDirection(enumdirection), true), 2); } } } else { if (enumdirection == EnumDirection.UP && blockposition.getY() < 255) { if (this.b((IBlockAccess) worldserver, blockposition, enumdirection)) { worldserver.setTypeAndData(blockposition, (IBlockData) iblockdata.set(BlockVine.UP, true), 2); return; } if (worldserver.isEmpty(blockposition1)) { if (!this.a((IBlockAccess) worldserver, blockposition)) { return; } IBlockData iblockdata3 = iblockdata; Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); while (iterator.hasNext()) { enumdirection1 = (EnumDirection) iterator.next(); if (random.nextBoolean() || !a((IBlockAccess) worldserver, blockposition1.shift(enumdirection1), EnumDirection.UP)) { iblockdata3 = (IBlockData) iblockdata3.set(getDirection(enumdirection1), false); } } if (this.canSpread(iblockdata3)) { CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition1, iblockdata3, 2); // CraftBukkit } return; } } if (blockposition.getY() > 0) { blockposition2 = blockposition.down(); iblockdata2 = worldserver.getType(blockposition2); if (iblockdata2.isAir() || iblockdata2.getBlock() == this) { IBlockData iblockdata4 = iblockdata2.isAir() ? this.getBlockData() : iblockdata2; IBlockData iblockdata5 = this.a(iblockdata, iblockdata4, random); if (iblockdata4 != iblockdata5 && this.canSpread(iblockdata5)) { CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition2, iblockdata5, 2); // CraftBukkit } } } } } } private IBlockData a(IBlockData iblockdata, IBlockData iblockdata1, Random random) { Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); while (iterator.hasNext()) { EnumDirection enumdirection = (EnumDirection) iterator.next(); if (random.nextBoolean()) { BlockStateBoolean blockstateboolean = getDirection(enumdirection); if ((Boolean) iblockdata.get(blockstateboolean)) { iblockdata1 = (IBlockData) iblockdata1.set(blockstateboolean, true); } } } return iblockdata1; } private boolean canSpread(IBlockData iblockdata) { return (Boolean) iblockdata.get(BlockVine.NORTH) || (Boolean) iblockdata.get(BlockVine.EAST) || (Boolean) iblockdata.get(BlockVine.SOUTH) || (Boolean) iblockdata.get(BlockVine.WEST); } private boolean a(IBlockAccess iblockaccess, BlockPosition blockposition) { boolean flag = true; Iterable<BlockPosition> iterable = BlockPosition.b(blockposition.getX() - 4, blockposition.getY() - 1, blockposition.getZ() - 4, blockposition.getX() + 4, blockposition.getY() + 1, blockposition.getZ() + 4); int i = 5; Iterator iterator = iterable.iterator(); while (iterator.hasNext()) { BlockPosition blockposition1 = (BlockPosition) iterator.next(); if (iblockaccess.getType(blockposition1).getBlock() == this) { --i; if (i <= 0) { return false; } } } return true; } @Override public boolean a(IBlockData iblockdata, BlockActionContext blockactioncontext) { IBlockData iblockdata1 = blockactioncontext.getWorld().getType(blockactioncontext.getClickPosition()); return iblockdata1.getBlock() == this ? this.i(iblockdata1) < BlockVine.f.size() : super.a(iblockdata, blockactioncontext); } @Nullable @Override public IBlockData getPlacedState(BlockActionContext blockactioncontext) { IBlockData iblockdata = blockactioncontext.getWorld().getType(blockactioncontext.getClickPosition()); boolean flag = iblockdata.getBlock() == this; IBlockData iblockdata1 = flag ? iblockdata : this.getBlockData(); EnumDirection[] aenumdirection = blockactioncontext.e(); int i = aenumdirection.length; for (int j = 0; j < i; ++j) { EnumDirection enumdirection = aenumdirection[j]; if (enumdirection != EnumDirection.DOWN) { BlockStateBoolean blockstateboolean = getDirection(enumdirection); boolean flag1 = flag && (Boolean) iblockdata.get(blockstateboolean); if (!flag1 && this.b((IBlockAccess) blockactioncontext.getWorld(), blockactioncontext.getClickPosition(), enumdirection)) { return (IBlockData) iblockdata1.set(blockstateboolean, true); } } } return flag ? iblockdata1 : null; } @Override protected void a(BlockStateList.a<Block, IBlockData> blockstatelist_a) { blockstatelist_a.a(BlockVine.UP, BlockVine.NORTH, BlockVine.EAST, BlockVine.SOUTH, BlockVine.WEST); } @Override public IBlockData a(IBlockData iblockdata, EnumBlockRotation enumblockrotation) { switch (enumblockrotation) { case CLOCKWISE_180: return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) iblockdata.set(BlockVine.NORTH, iblockdata.get(BlockVine.SOUTH))).set(BlockVine.EAST, iblockdata.get(BlockVine.WEST))).set(BlockVine.SOUTH, iblockdata.get(BlockVine.NORTH))).set(BlockVine.WEST, iblockdata.get(BlockVine.EAST)); case COUNTERCLOCKWISE_90: return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) iblockdata.set(BlockVine.NORTH, iblockdata.get(BlockVine.EAST))).set(BlockVine.EAST, iblockdata.get(BlockVine.SOUTH))).set(BlockVine.SOUTH, iblockdata.get(BlockVine.WEST))).set(BlockVine.WEST, iblockdata.get(BlockVine.NORTH)); case CLOCKWISE_90: return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) iblockdata.set(BlockVine.NORTH, iblockdata.get(BlockVine.WEST))).set(BlockVine.EAST, iblockdata.get(BlockVine.NORTH))).set(BlockVine.SOUTH, iblockdata.get(BlockVine.EAST))).set(BlockVine.WEST, iblockdata.get(BlockVine.SOUTH)); default: return iblockdata; } } @Override public IBlockData a(IBlockData iblockdata, EnumBlockMirror enumblockmirror) { switch (enumblockmirror) { case LEFT_RIGHT: return (IBlockData) ((IBlockData) iblockdata.set(BlockVine.NORTH, iblockdata.get(BlockVine.SOUTH))).set(BlockVine.SOUTH, iblockdata.get(BlockVine.NORTH)); case FRONT_BACK: return (IBlockData) ((IBlockData) iblockdata.set(BlockVine.EAST, iblockdata.get(BlockVine.WEST))).set(BlockVine.WEST, iblockdata.get(BlockVine.EAST)); default: return super.a(iblockdata, enumblockmirror); } } public static BlockStateBoolean getDirection(EnumDirection enumdirection) { return (BlockStateBoolean) BlockVine.f.get(enumdirection); } }