package net.glowstone.block.blocktype; import net.glowstone.block.GlowBlock; import net.glowstone.block.GlowBlockState; import net.glowstone.block.entity.BlockEntity; import net.glowstone.block.entity.ContainerEntity; import net.glowstone.block.entity.HopperEntity; import net.glowstone.block.state.GlowHopper; import net.glowstone.chunk.GlowChunk; import net.glowstone.entity.GlowPlayer; import net.glowstone.entity.objects.GlowItem; import net.glowstone.inventory.MaterialMatcher; import net.glowstone.inventory.ToolType; import org.bukkit.Location; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.Sign; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.material.*; import org.bukkit.util.Vector; import java.util.HashMap; public class BlockHopper extends BlockContainer { public void setFacingDirection(BlockState bs, BlockFace face) { byte data; switch (face) { case DOWN: data = 0; break; case UP: data = 1; break; case NORTH: data = 2; break; case SOUTH: data = 3; break; case WEST: data = 4; break; case EAST: default: data = 5; break; } bs.setRawData(data); } @Override public BlockEntity createBlockEntity(GlowChunk chunk, int cx, int cy, int cz) { return new HopperEntity(chunk.getBlock(cx, cy, cz)); } @Override public void placeBlock(GlowPlayer player, GlowBlockState state, BlockFace face, ItemStack holding, Vector clickedLoc) { super.placeBlock(player, state, face, holding, clickedLoc); setFacingDirection(state, face.getOppositeFace()); state.getBlock().getWorld().requestPulse(state.getBlock()); } @Override protected MaterialMatcher getNeededMiningTool(GlowBlock block) { return ToolType.PICKAXE; } @Override public void receivePulse(GlowBlock block) { if (block.getBlockEntity() == null) { return; } HopperEntity hopper = (HopperEntity) block.getBlockEntity(); if (!((Hopper) block.getState().getData()).isPowered()) { pushItems(block, hopper); } pullItems(block, hopper); } @Override public void onRedstoneUpdate(GlowBlock block) { ((Hopper) block.getState().getData()).setActive(!block.isBlockPowered()); } private void pullItems(GlowBlock block, HopperEntity hopper) { GlowBlock source = block.getRelative(BlockFace.UP); MaterialData data = source.getState().getData(); if (!source.getType().isSolid() || (data instanceof Step && !((Step) data).isInverted()) || (data instanceof WoodenStep && !((WoodenStep) data).isInverted()) || (data instanceof Sign) || (data instanceof Rails)) { GlowItem item = getFirstDroppedItem(source.getLocation()); if (item == null) { return; } ItemStack stack = item.getItemStack(); HashMap<Integer, ItemStack> add = hopper.getInventory().addItem(stack); if (add.size() > 0) { item.setItemStack(add.get(0)); } else { item.remove(); } } else if (source.getBlockEntity() != null && source.getBlockEntity() instanceof ContainerEntity) { ContainerEntity sourceContainer = (ContainerEntity) source.getBlockEntity(); if (sourceContainer.getInventory() == null || sourceContainer.getInventory().getContents().length == 0) { return; } ItemStack item = getFirstItem(sourceContainer); if (item == null) { return; } ItemStack clone = item.clone(); clone.setAmount(1); if (hopper.getInventory().addItem(clone).size() > 0) { return; } if (item.getAmount() - 1 == 0) { sourceContainer.getInventory().remove(item); } else { item.setAmount(item.getAmount() - 1); } } } private boolean pushItems(GlowBlock block, HopperEntity hopper) { if (hopper.getInventory() == null || hopper.getInventory().getContents().length == 0) { return false; } GlowBlock target = block.getRelative(((Hopper) block.getState().getData()).getFacing()); if (target.getType() != null && target.getBlockEntity() instanceof ContainerEntity) { if (target.getState() instanceof GlowHopper) { if (((Hopper) block.getState().getData()).getFacing() == BlockFace.DOWN) { // If the hopper is facing downwards, the target hopper can do the pulling task itself return false; } } ItemStack item = getFirstItem(hopper); if (item == null) { return false; } ItemStack clone = item.clone(); clone.setAmount(1); if (((ContainerEntity) target.getBlockEntity()).getInventory().addItem(clone).size() > 0) { return false; } if (item.getAmount() - 1 == 0) { hopper.getInventory().remove(item); } else { item.setAmount(item.getAmount() - 1); } return true; } return false; } private GlowItem getFirstDroppedItem(Location location) { for (Entity entity : location.getChunk().getEntities()) { if (location.getBlockX() != entity.getLocation().getBlockX() || location.getBlockY() != entity.getLocation().getBlockY() || location.getBlockZ() != entity.getLocation().getBlockZ()) { continue; } if (entity.getType() != EntityType.DROPPED_ITEM) { continue; } return ((GlowItem) entity); } return null; } private ItemStack getFirstItem(ContainerEntity container) { Inventory inventory = container.getInventory(); for (int i = 0; i < inventory.getSize(); i++) { if (inventory.getItem(i) == null || inventory.getItem(i).getType() == null) { continue; } return inventory.getItem(i); } return null; } @Override public boolean isPulseOnce(GlowBlock block) { return false; } @Override public int getPulseTickSpeed(GlowBlock block) { return 8; } }