package net.minecraft.server; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.koloboke.collect.set.hash.HashObjSets; import java.util.ArrayList; import java.util.EnumSet; import java.util.Iterator; import java.util.Random; import java.util.Set; import javax.annotation.Nullable; import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit public class BlockRedstoneWire extends Block { public static final BlockStateEnum<BlockRedstoneWire.EnumRedstoneWireConnection> NORTH = BlockStateEnum.of("north", BlockRedstoneWire.EnumRedstoneWireConnection.class); public static final BlockStateEnum<BlockRedstoneWire.EnumRedstoneWireConnection> EAST = BlockStateEnum.of("east", BlockRedstoneWire.EnumRedstoneWireConnection.class); public static final BlockStateEnum<BlockRedstoneWire.EnumRedstoneWireConnection> SOUTH = BlockStateEnum.of("south", BlockRedstoneWire.EnumRedstoneWireConnection.class); public static final BlockStateEnum<BlockRedstoneWire.EnumRedstoneWireConnection> WEST = BlockStateEnum.of("west", BlockRedstoneWire.EnumRedstoneWireConnection.class); public static final BlockStateInteger POWER = BlockStateInteger.of("power", 0, 15); protected static final AxisAlignedBB[] f = new AxisAlignedBB[] { new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 1.0D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 1.0D, 0.0625D, 1.0D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 1.0D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.0625D, 1.0D)}; private boolean g = true; private final Set<BlockPosition> B = HashObjSets.newMutableSet(); private final Set<BlockPosition> blocksToUpdate = B; // Paper - OBFHELPER public BlockRedstoneWire() { super(Material.ORIENTABLE); this.y(this.blockStateList.getBlockData().set(BlockRedstoneWire.NORTH, BlockRedstoneWire.EnumRedstoneWireConnection.NONE).set(BlockRedstoneWire.EAST, BlockRedstoneWire.EnumRedstoneWireConnection.NONE).set(BlockRedstoneWire.SOUTH, BlockRedstoneWire.EnumRedstoneWireConnection.NONE).set(BlockRedstoneWire.WEST, BlockRedstoneWire.EnumRedstoneWireConnection.NONE).set(BlockRedstoneWire.POWER, Integer.valueOf(0))); } @Override public AxisAlignedBB b(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition) { return BlockRedstoneWire.f[z(iblockdata.b(iblockaccess, blockposition))]; } private static int z(IBlockData iblockdata) { int i = 0; boolean flag = iblockdata.get(BlockRedstoneWire.NORTH) != BlockRedstoneWire.EnumRedstoneWireConnection.NONE; boolean flag1 = iblockdata.get(BlockRedstoneWire.EAST) != BlockRedstoneWire.EnumRedstoneWireConnection.NONE; boolean flag2 = iblockdata.get(BlockRedstoneWire.SOUTH) != BlockRedstoneWire.EnumRedstoneWireConnection.NONE; boolean flag3 = iblockdata.get(BlockRedstoneWire.WEST) != BlockRedstoneWire.EnumRedstoneWireConnection.NONE; if (flag || flag2 && !flag && !flag1 && !flag3) { i |= 1 << EnumDirection.NORTH.get2DRotationValue(); } if (flag1 || flag3 && !flag && !flag1 && !flag2) { i |= 1 << EnumDirection.EAST.get2DRotationValue(); } if (flag2 || flag && !flag1 && !flag2 && !flag3) { i |= 1 << EnumDirection.SOUTH.get2DRotationValue(); } if (flag3 || flag1 && !flag && !flag2 && !flag3) { i |= 1 << EnumDirection.WEST.get2DRotationValue(); } return i; } @Override public IBlockData updateState(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition) { iblockdata = iblockdata.set(BlockRedstoneWire.WEST, this.b(iblockaccess, blockposition, EnumDirection.WEST)); iblockdata = iblockdata.set(BlockRedstoneWire.EAST, this.b(iblockaccess, blockposition, EnumDirection.EAST)); iblockdata = iblockdata.set(BlockRedstoneWire.NORTH, this.b(iblockaccess, blockposition, EnumDirection.NORTH)); iblockdata = iblockdata.set(BlockRedstoneWire.SOUTH, this.b(iblockaccess, blockposition, EnumDirection.SOUTH)); return iblockdata; } private BlockRedstoneWire.EnumRedstoneWireConnection b(IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { BlockPosition blockposition1 = blockposition.shift(enumdirection); IBlockData iblockdata = iblockaccess.getType(blockposition.shift(enumdirection)); if (!a(iblockaccess.getType(blockposition1), enumdirection) && (iblockdata.m() || !i(iblockaccess.getType(blockposition1.down())))) { IBlockData iblockdata1 = iblockaccess.getType(blockposition.up()); if (!iblockdata1.m()) { boolean flag = iblockaccess.getType(blockposition1).r() || iblockaccess.getType(blockposition1).getBlock() == Blocks.GLOWSTONE; if (flag && i(iblockaccess.getType(blockposition1.up()))) { if (iblockdata.l()) { return BlockRedstoneWire.EnumRedstoneWireConnection.UP; } return BlockRedstoneWire.EnumRedstoneWireConnection.SIDE; } } return BlockRedstoneWire.EnumRedstoneWireConnection.NONE; } else { return BlockRedstoneWire.EnumRedstoneWireConnection.SIDE; } } @Override @Nullable public AxisAlignedBB a(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition) { return BlockRedstoneWire.k; } @Override public boolean b(IBlockData iblockdata) { return false; } @Override public boolean c(IBlockData iblockdata) { return false; } @Override public boolean canPlace(World world, BlockPosition blockposition) { return world.getType(blockposition.down()).r() || world.getType(blockposition.down()).getBlock() == Blocks.GLOWSTONE; } private IBlockData e(World world, BlockPosition blockposition, IBlockData iblockdata) { iblockdata = this.a(world, blockposition, blockposition, iblockdata); ArrayList arraylist = Lists.newArrayList(this.B); this.B.clear(); Iterator iterator = arraylist.iterator(); while (iterator.hasNext()) { BlockPosition blockposition1 = (BlockPosition) iterator.next(); world.applyPhysics(blockposition1, this, false); } return iblockdata; } private IBlockData a(World world, BlockPosition blockposition, BlockPosition blockposition1, IBlockData iblockdata) { IBlockData iblockdata1 = iblockdata; int i = iblockdata.get(BlockRedstoneWire.POWER).intValue(); byte b0 = 0; int j = this.getPower(world, blockposition1, b0); this.g = false; int k = world.z(blockposition); this.g = true; if (k > 0 && k > j - 1) { j = k; } int l = 0; Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); while (iterator.hasNext()) { EnumDirection enumdirection = (EnumDirection) iterator.next(); BlockPosition blockposition2 = blockposition.shift(enumdirection); boolean flag = blockposition2.getX() != blockposition1.getX() || blockposition2.getZ() != blockposition1.getZ(); if (flag) { l = this.getPower(world, blockposition2, l); } if (world.getType(blockposition2).m() && !world.getType(blockposition.up()).m()) { if (flag && blockposition.getY() >= blockposition1.getY()) { l = this.getPower(world, blockposition2.up(), l); } } else if (!world.getType(blockposition2).m() && flag && blockposition.getY() <= blockposition1.getY()) { l = this.getPower(world, blockposition2.down(), l); } } if (l > j) { j = l - 1; } else if (j > 0) { --j; } else { j = 0; } if (k > j - 1) { j = k; } // CraftBukkit start if (i != j) { BlockRedstoneEvent event = new BlockRedstoneEvent(world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), i, j); world.getServer().getPluginManager().callEvent(event); j = event.getNewCurrent(); } // CraftBukkit end if (i != j) { iblockdata = iblockdata.set(BlockRedstoneWire.POWER, Integer.valueOf(j)); if (world.getType(blockposition) == iblockdata1) { world.setTypeAndData(blockposition, iblockdata, 2); } this.B.add(blockposition); // Paper start - Old TNT cannon behaviors if (world.paperConfig.oldCannonBehaviors) { this.blocksToUpdate.add(blockposition.shift(EnumDirection.WEST)); this.blocksToUpdate.add(blockposition.shift(EnumDirection.EAST)); this.blocksToUpdate.add(blockposition.shift(EnumDirection.DOWN)); this.blocksToUpdate.add(blockposition.shift(EnumDirection.UP)); this.blocksToUpdate.add(blockposition.shift(EnumDirection.NORTH)); this.blocksToUpdate.add(blockposition.shift(EnumDirection.SOUTH)); return iblockdata; } // Paper end EnumDirection[] aenumdirection = EnumDirection.values(); int i1 = aenumdirection.length; for (int j1 = 0; j1 < i1; ++j1) { EnumDirection enumdirection1 = aenumdirection[j1]; this.B.add(blockposition.shift(enumdirection1)); } } return iblockdata; } private void b(World world, BlockPosition blockposition) { if (world.getType(blockposition).getBlock() == this) { world.applyPhysics(blockposition, this, false); if (world.paperConfig.oldCannonBehaviors) { world.applyPhysics(blockposition.shift(EnumDirection.WEST), this, false); world.applyPhysics(blockposition.shift(EnumDirection.EAST), this, false); world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this, false); world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this, false); world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this, false); world.applyPhysics(blockposition.shift(EnumDirection.UP), this, false); return; } // Paper end EnumDirection[] aenumdirection = EnumDirection.values(); int i = aenumdirection.length; for (int j = 0; j < i; ++j) { EnumDirection enumdirection = aenumdirection[j]; world.applyPhysics(blockposition.shift(enumdirection), this, false); } } } @Override public void onPlace(World world, BlockPosition blockposition, IBlockData iblockdata) { if (!world.isClientSide) { this.e(world, blockposition, iblockdata); Iterator iterator = EnumDirection.EnumDirectionLimit.VERTICAL.iterator(); EnumDirection enumdirection; while (iterator.hasNext()) { enumdirection = (EnumDirection) iterator.next(); world.applyPhysics(blockposition.shift(enumdirection), this, false); } iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); while (iterator.hasNext()) { enumdirection = (EnumDirection) iterator.next(); this.b(world, blockposition.shift(enumdirection)); } iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); while (iterator.hasNext()) { enumdirection = (EnumDirection) iterator.next(); BlockPosition blockposition1 = blockposition.shift(enumdirection); if (world.getType(blockposition1).m()) { this.b(world, blockposition1.up()); } else { this.b(world, blockposition1.down()); } } } } @Override public void remove(World world, BlockPosition blockposition, IBlockData iblockdata) { super.remove(world, blockposition, iblockdata); if (!world.isClientSide) { EnumDirection[] aenumdirection = EnumDirection.values(); int i = aenumdirection.length; for (int j = 0; j < i; ++j) { EnumDirection enumdirection = aenumdirection[j]; world.applyPhysics(blockposition.shift(enumdirection), this, false); } this.e(world, blockposition, iblockdata); Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); EnumDirection enumdirection1; while (iterator.hasNext()) { enumdirection1 = (EnumDirection) iterator.next(); this.b(world, blockposition.shift(enumdirection1)); } iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); while (iterator.hasNext()) { enumdirection1 = (EnumDirection) iterator.next(); BlockPosition blockposition1 = blockposition.shift(enumdirection1); if (world.getType(blockposition1).m()) { this.b(world, blockposition1.up()); } else { this.b(world, blockposition1.down()); } } } } public int getPower(World world, BlockPosition blockposition, int i) { if (world.getType(blockposition).getBlock() != this) { return i; } else { int j = world.getType(blockposition).get(BlockRedstoneWire.POWER).intValue(); return j > i ? j : i; } } @Override public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1) { if (!world.isClientSide) { if (this.canPlace(world, blockposition)) { this.e(world, blockposition, iblockdata); } else { this.b(world, blockposition, iblockdata, 0); world.setAir(blockposition); } } } @Override public Item getDropType(IBlockData iblockdata, Random random, int i) { return Items.REDSTONE; } @Override public int c(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { return !this.g ? 0 : iblockdata.a(iblockaccess, blockposition, enumdirection); } @Override public int b(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { if (!this.g) { return 0; } else { int i = iblockdata.get(BlockRedstoneWire.POWER).intValue(); if (i == 0) { return 0; } else if (enumdirection == EnumDirection.UP) { return i; } else { EnumSet enumset = EnumSet.noneOf(EnumDirection.class); Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); while (iterator.hasNext()) { EnumDirection enumdirection1 = (EnumDirection) iterator.next(); if (this.c(iblockaccess, blockposition, enumdirection1)) { enumset.add(enumdirection1); } } if (enumdirection.k().c() && enumset.isEmpty()) { return i; } else if (enumset.contains(enumdirection) && !enumset.contains(enumdirection.f()) && !enumset.contains(enumdirection.e())) { return i; } else { return 0; } } } } private boolean c(IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { BlockPosition blockposition1 = blockposition.shift(enumdirection); IBlockData iblockdata = iblockaccess.getType(blockposition1); boolean flag = iblockdata.m(); boolean flag1 = iblockaccess.getType(blockposition.up()).m(); return !flag1 && flag && c(iblockaccess, blockposition1.up()) ? true : (a(iblockdata, enumdirection) ? true : (iblockdata.getBlock() == Blocks.POWERED_REPEATER && iblockdata.get(BlockDiodeAbstract.FACING) == enumdirection ? true : !flag && c(iblockaccess, blockposition1.down()))); } protected static boolean c(IBlockAccess iblockaccess, BlockPosition blockposition) { return i(iblockaccess.getType(blockposition)); } protected static boolean i(IBlockData iblockdata) { return a(iblockdata, (EnumDirection) null); } protected static boolean a(IBlockData iblockdata, @Nullable EnumDirection enumdirection) { Block block = iblockdata.getBlock(); if (block == Blocks.REDSTONE_WIRE) { return true; } else if (Blocks.UNPOWERED_REPEATER.E(iblockdata)) { EnumDirection enumdirection1 = iblockdata.get(BlockRepeater.FACING); return enumdirection1 == enumdirection || enumdirection1.opposite() == enumdirection; } else { return Blocks.dk == iblockdata.getBlock() ? enumdirection == iblockdata.get(BlockObserver.FACING) : iblockdata.n() && enumdirection != null; } } @Override public boolean isPowerSource(IBlockData iblockdata) { return this.g; } @Override public ItemStack a(World world, BlockPosition blockposition, IBlockData iblockdata) { return new ItemStack(Items.REDSTONE); } @Override public IBlockData fromLegacyData(int i) { return this.getBlockData().set(BlockRedstoneWire.POWER, Integer.valueOf(i)); } @Override public int toLegacyData(IBlockData iblockdata) { return iblockdata.get(BlockRedstoneWire.POWER).intValue(); } @Override public IBlockData a(IBlockData iblockdata, EnumBlockRotation enumblockrotation) { switch (enumblockrotation) { case CLOCKWISE_180: return iblockdata.set(BlockRedstoneWire.NORTH, iblockdata.get(BlockRedstoneWire.SOUTH)).set(BlockRedstoneWire.EAST, iblockdata.get(BlockRedstoneWire.WEST)).set(BlockRedstoneWire.SOUTH, iblockdata.get(BlockRedstoneWire.NORTH)).set(BlockRedstoneWire.WEST, iblockdata.get(BlockRedstoneWire.EAST)); case COUNTERCLOCKWISE_90: return iblockdata.set(BlockRedstoneWire.NORTH, iblockdata.get(BlockRedstoneWire.EAST)).set(BlockRedstoneWire.EAST, iblockdata.get(BlockRedstoneWire.SOUTH)).set(BlockRedstoneWire.SOUTH, iblockdata.get(BlockRedstoneWire.WEST)).set(BlockRedstoneWire.WEST, iblockdata.get(BlockRedstoneWire.NORTH)); case CLOCKWISE_90: return iblockdata.set(BlockRedstoneWire.NORTH, iblockdata.get(BlockRedstoneWire.WEST)).set(BlockRedstoneWire.EAST, iblockdata.get(BlockRedstoneWire.NORTH)).set(BlockRedstoneWire.SOUTH, iblockdata.get(BlockRedstoneWire.EAST)).set(BlockRedstoneWire.WEST, iblockdata.get(BlockRedstoneWire.SOUTH)); default: return iblockdata; } } @Override public IBlockData a(IBlockData iblockdata, EnumBlockMirror enumblockmirror) { switch (enumblockmirror) { case LEFT_RIGHT: return iblockdata.set(BlockRedstoneWire.NORTH, iblockdata.get(BlockRedstoneWire.SOUTH)).set(BlockRedstoneWire.SOUTH, iblockdata.get(BlockRedstoneWire.NORTH)); case FRONT_BACK: return iblockdata.set(BlockRedstoneWire.EAST, iblockdata.get(BlockRedstoneWire.WEST)).set(BlockRedstoneWire.WEST, iblockdata.get(BlockRedstoneWire.EAST)); default: return super.a(iblockdata, enumblockmirror); } } @Override protected BlockStateList getStateList() { return new BlockStateList(this, new IBlockState[] { BlockRedstoneWire.NORTH, BlockRedstoneWire.EAST, BlockRedstoneWire.SOUTH, BlockRedstoneWire.WEST, BlockRedstoneWire.POWER}); } static enum EnumRedstoneWireConnection implements INamable { UP("up"), SIDE("side"), NONE("none"); private final String d; private EnumRedstoneWireConnection(String s) { this.d = s; } @Override public String toString() { return this.getName(); } @Override public String getName() { return this.d; } } }