package net.glowstone.block.blocktype; import net.glowstone.block.GlowBlock; import net.glowstone.block.GlowBlockState; import net.glowstone.block.ItemTable; import net.glowstone.entity.GlowPlayer; import net.glowstone.net.message.play.game.BlockChangeMessage; import org.bukkit.Material; import org.bukkit.block.BlockFace; import org.bukkit.inventory.ItemStack; import org.bukkit.material.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * * @author Sam */ public class BlockRedstone extends BlockNeedsAttached { public BlockRedstone() { setDrops(new ItemStack(Material.REDSTONE)); } @Override public boolean canPlaceAt(GlowBlock block, BlockFace against) { if (block.getRelative(BlockFace.DOWN).getType().isSolid()) { return true; } GlowBlock target = block.getRelative(BlockFace.DOWN); switch (target.getType()) { case WOOD_STAIRS: case COBBLESTONE_STAIRS: case BRICK_STAIRS: case SMOOTH_STAIRS: case NETHER_BRICK_STAIRS: case SANDSTONE_STAIRS: case SPRUCE_WOOD_STAIRS: case BIRCH_WOOD_STAIRS: case JUNGLE_WOOD_STAIRS: case QUARTZ_STAIRS: case ACACIA_STAIRS: case DARK_OAK_STAIRS: return ((Stairs) target.getState().getData()).isInverted(); case STEP: case WOOD_STEP: return ((Step) target.getState().getData()).isInverted(); case GLOWSTONE: return true; } return false; } @Override public void afterPlace(GlowPlayer player, GlowBlock block, ItemStack holding, GlowBlockState oldState) { updatePhysics(block); } @Override public void onNearBlockChanged(GlowBlock block, BlockFace face, GlowBlock changedBlock, Material oldType, byte oldData, Material newType, byte newData) { updatePhysics(block); } @Override public void updatePhysics(GlowBlock me) { super.updatePhysics(me); for (BlockFace face : ADJACENT) { GlowBlock target = me.getRelative(face); switch (target.getType()) { case LEVER: Lever lever = (Lever) target.getState().getData(); if (lever.isPowered()) { if (me.getData() != 15) { me.setData((byte) 15); extraUpdate(me); } return; } break; case STONE_BUTTON: case WOOD_BUTTON: Button button = (Button) target.getState().getData(); if (button.isPowered()) { if (me.getData() != 15) { me.setData((byte) 15); extraUpdate(me); } return; } break; case DIODE_BLOCK_ON: Diode diode = (Diode) target.getState().getData(); if (face == diode.getFacing().getOppositeFace()) { if (me.getData() != 15) { me.setData((byte) 15); extraUpdate(me); } return; } break; case REDSTONE_BLOCK: case REDSTONE_TORCH_ON: if (me.getData() != 15) { me.setData((byte) 15); extraUpdate(me); } return; default: if (target.getType().isSolid() && target.getRelative(BlockFace.DOWN).getType() == Material.REDSTONE_TORCH_ON) { if (me.getData() != 15) { me.setData((byte) 15); extraUpdate(me); } return; } if (target.getType().isSolid()) { for (BlockFace face2 : ADJACENT) { GlowBlock target2 = target.getRelative(face2); if (target2.getType() == Material.DIODE_BLOCK_ON && ((Diode) target2.getState().getData()).getFacing() == target2.getFace(target)) { if (me.getData() != 15) { me.setData((byte) 15); extraUpdate(me); } return; } else if (target2.getType() == Material.STONE_BUTTON || target2.getType() == Material.WOOD_BUTTON) { Button button2 = (Button) target2.getState().getData(); if (button2.isPowered() && button2.getAttachedFace() == target2.getFace(target)) { if (me.getData() != 15) { me.setData((byte) 15); extraUpdate(me); } return; } } else if (target2.getType() == Material.LEVER) { Lever lever2 = (Lever) target2.getState().getData(); if (lever2.isPowered() && lever2.getAttachedFace() == target2.getFace(target)) { if (me.getData() != 15) { me.setData((byte) 15); extraUpdate(me); } return; } } } } } } byte power = 0; for (BlockFace face : calculateConnections(me)) { if (face == BlockFace.DOWN) { continue; } GlowBlock target = me.getRelative(face); if (target.getType() != Material.REDSTONE_WIRE) { if (!target.getType().isSolid()) { target = target.getRelative(BlockFace.DOWN); } else if (!me.getRelative(BlockFace.UP).getType().isSolid()) { target = target.getRelative(BlockFace.UP); } if (target.getType() != Material.REDSTONE_WIRE) { // There is no redstone wire here.. continue; } } if (target.getData() > power) { power = (byte) (target.getData() - 1); } } if (power != me.getData()) { me.setData(power); extraUpdate(me); me.getWorld().requestPulse(me, 1); } } private void extraUpdate(GlowBlock block) { ItemTable itemTable = ItemTable.instance(); for (BlockFace face : calculateConnections(block)) { GlowBlock target = block.getRelative(face); if (target.getType().isSolid()) { for (BlockFace face2 : ADJACENT) { GlowBlock target2 = target.getRelative(face2); BlockType notifyType = itemTable.getBlock(target2.getTypeId()); if (notifyType != null) { if (target2.getFace(block) == null) { notifyType.onNearBlockChanged(target2, BlockFace.SELF, block, block.getType(), block.getData(), block.getType(), block.getData()); } notifyType.onRedstoneUpdate(target2); } } } } } @Override public void receivePulse(GlowBlock me) { BlockChangeMessage bcmsg = new BlockChangeMessage(me.getX(), me.getY(), me.getZ(), me.getTypeId(), me.getData()); for (GlowPlayer p : me.getWorld().getRawPlayers()) { p.sendBlockChange(bcmsg); } } private static final BlockFace[] ADJACENT = new BlockFace[]{BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN}; private static final BlockFace[] SIDES = new BlockFace[]{BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST}; public static List<BlockFace> calculateConnections(GlowBlock block) { List<BlockFace> value = new ArrayList<>(); List<BlockFace> connections = new ArrayList<>(); value.add(BlockFace.DOWN); for (BlockFace face : SIDES) { GlowBlock target = block.getRelative(face); switch (target.getType()) { case DIODE_BLOCK_ON: case DIODE_BLOCK_OFF: Diode diode = (Diode) target.getState().getData(); if (face == diode.getFacing() || face == diode.getFacing().getOppositeFace()) { connections.add(face); } break; case REDSTONE_BLOCK: case REDSTONE_TORCH_ON: case REDSTONE_TORCH_OFF: case REDSTONE_WIRE: case WOOD_BUTTON: case STONE_BUTTON: case LEVER: connections.add(face); break; default: if (target.getType().isSolid() && !block.getRelative(BlockFace.UP).getType().isSolid() && target.getRelative(BlockFace.UP).getType() == Material.REDSTONE_WIRE) { connections.add(face); } else if (!target.getType().isSolid() && target.getRelative(BlockFace.DOWN).getType() == Material.REDSTONE_WIRE) { connections.add(face); } break; } } if (connections.isEmpty()) { value.addAll(Arrays.asList(SIDES)); } else { value.addAll(connections); if (connections.size() == 1) { value.add(connections.get(0).getOppositeFace()); } } return value; } }