@Override
 public boolean isItemValidForSlot(int slot, ItemStack is) {
   if (slot > 3 && slot < 9) return false;
   if (slot == 0)
     return ReikaBlockHelper.isOre(is)
         || CustomExtractLoader.instance.getEntryFromOreBlock(is) != null;
   if (ItemRegistry.EXTRACTS.matchItem(is)) {
     return slot == 1 + is.getItemDamage() / 8;
   } else if (ItemRegistry.MODEXTRACTS.matchItem(is)) {
     return slot == 1 + is.getItemDamage() % 4;
   } else if (ItemRegistry.CUSTOMEXTRACT.matchItem(is)) {
     return slot == 1 + is.getItemDamage() % 4;
   }
   if (slot == 9)
     return !bedrock
         && ConfigRegistry.EXTRACTORMAINTAIN.getState()
         && ReikaItemHelper.matchStacks(is, ItemStacks.drill);
   return false;
 }
 private void removeFound(World world, int x, int y, int z, Block b, int meta) {
   if (Item.getItemFromBlock(b) == null) return;
   ItemStack is = new ItemStack(b, 1, meta);
   if (b instanceof SpecialOreBlock) {
     is = ((SpecialOreBlock) b).getDisplayItem(world, x, y, z);
   } else if (ReikaBlockHelper.isOre(b, meta)) {
     ReikaOreHelper ore = ReikaOreHelper.getEntryByOreDict(is);
     ModOreList mod = ModOreList.getModOreFromOre(is);
     if (ore != null) {
       is = ore.getOreBlock();
     } else if (mod != null && mod != ModOreList.CERTUSQUARTZ) {
       is = mod.getFirstOreBlock();
     }
   }
   Integer i = found.get(is);
   if (i == null) i = 0;
   if (i > 1) found.put(is, i - 1);
   else found.remove(is);
   // ReikaJavaLibrary.pConsole("Removed "+b+":"+meta+" from cache, now have "+found.get(is));
 }
 private void addFound(World world, int x, int y, int z, Block b, int meta) {
   if (b != null && Item.getItemFromBlock(b) == null) {
     ChromatiCraft.logger.logError("Block " + b + " has no item to drop when mined???");
     return;
   }
   ItemStack is = new ItemStack(b, 1, meta);
   if (b instanceof SpecialOreBlock) {
     is = ((SpecialOreBlock) b).getDisplayItem(world, x, y, z);
   } else if (ReikaBlockHelper.isOre(b, meta)) {
     ReikaOreHelper ore = ReikaOreHelper.getEntryByOreDict(is);
     ModOreList mod = ModOreList.getModOreFromOre(is);
     if (ore != null) {
       is = ore.getOreBlock();
     } else if (mod != null && mod != ModOreList.CERTUSQUARTZ) {
       is = mod.getFirstOreBlock();
     }
   }
   Integer i = found.get(is);
   if (i == null) i = 0;
   found.put(is, i + 1);
   // ReikaJavaLibrary.pConsole("Found "+b+":"+meta+" @ "+x+","+y+","+z+"; have "+(i+1));
 }
 @Override
 public void updateEntity(World world, int x, int y, int z, int meta) {
   if (!world.isRemote) {
     if (dropFlag) {
       if (this.getTicksExisted() % 20 == 0) {
         this.doDropWarning(world, x, y, z);
       }
     } else {
       int n = this.hasSpeed() ? 4 : 1;
       for (int k = 0; k < n; k++) {
         if (digging && !coords.isEmpty()) {
           // this.prepareChunkloading();
           if (this.hasEnergy(required)) {
             Coordinate c = coords.get(index);
             int dx = c.xCoord;
             int dy = c.yCoord;
             int dz = c.zCoord;
             Block id = this.parseBlock(world.getBlock(dx, dy, dz));
             int meta2 = world.getBlockMetadata(dx, dy, dz);
             // ReikaJavaLibrary.pConsole(readX+":"+dx+", "+dy+", "+readZ+":"+dz+" >
             // "+ores.getSize(), Side.SERVER);
             this.removeFound(world, dx, dy, dz, id, meta2);
             if (id instanceof SpecialOreBlock) {
               this.dropSpecialOreBlock(world, x, y, z, dx, dy, dz, (SpecialOreBlock) id, meta2);
             } else if (ReikaBlockHelper.isOre(id, meta2)) {
               // ores.addBlockCoordinate(dx, dy, dz);
               this.dropBlock(world, x, y, z, dx, dy, dz, id, meta2);
             } else if (this.shouldMine(id, meta2)) {
               this.dropBlock(world, x, y, z, dx, dy, dz, id, meta2);
             } else if (this.isTieredResource(world, dx, dy, dz, id, meta2)) {
               this.dropTieredResource(world, x, y, z, dx, dy, dz, id, meta2);
             } else if (id instanceof MinerBlock) {
               this.dropMineableBlock(world, x, y, z, dx, dy, dz, id, meta2);
             }
             this.useEnergy(required.copy().scale(this.hasEfficiency() ? 0.25F : 1));
             // ReikaJavaLibrary.pConsole("Mining "+id+":"+meta2+" @ "+dx+","+dy+","+dz+";
             // index="+index);
             index++;
             if (index >= coords.size()) {
               this.finishDigging();
               k = n;
             }
           }
         } else if (!digReady && !finishedDigging) {
           this.prepareChunkloading();
           for (int i = 0; i < TICKSTEP; i++) {
             int dx = x + readX;
             int dy = readY;
             int dz = z + readZ;
             ReikaWorldHelper.forceGenAndPopulate(world, dx, dz);
             Block id = this.parseBlock(world.getBlock(dx, dy, dz));
             int meta2 = world.getBlockMetadata(dx, dy, dz);
             // ReikaJavaLibrary.pConsole(readX+":"+dx+", "+dy+", "+readZ+":"+dz+" >
             // "+ores.getSize(), Side.SERVER);
             boolean add = false;
             if (ReikaBlockHelper.isOre(id, meta2)) {
               // ores.addBlockCoordinate(dx, dy, dz);
               add = coords.add(new Coordinate(dx, dy, dz));
             } else if (this.isTieredResource(world, dx, dy, dz, id, meta2)) {
               add = coords.add(new Coordinate(dx, dy, dz));
             } else if (id instanceof MinerBlock && ((MinerBlock) id).isMineable(meta2)) {
               add = coords.add(new Coordinate(dx, dy, dz));
             } else if (this.shouldMine(id, meta2)) {
               add = coords.add(new Coordinate(dx, dy, dz));
             }
             if (add) {
               this.addFound(world, dx, dy, dz, id, meta2);
             }
             this.updateReadPosition();
             if (readY >= worldObj.getActualHeight()) {
               this.prepareDigging();
             }
           }
         }
       }
       progress = readY;
     }
   }
   if (world.isRemote) this.spawnParticles(world, x, y, z);
 }
 @Override
 public boolean onItemUse(
     ItemStack is,
     EntityPlayer ep,
     World world,
     int x,
     int y,
     int z,
     int side,
     float par8,
     float par9,
     float par10) {
   if (!ReikaWorldHelper.softBlocks(world, x, y, z)
       && world.getBlockMaterial(x, y, z) != Material.water
       && world.getBlockMaterial(x, y, z) != Material.lava) {
     if (side == 0) --y;
     if (side == 1) ++y;
     if (side == 2) --z;
     if (side == 3) ++z;
     if (side == 4) --x;
     if (side == 5) ++x;
     this.clearBlocks(world, x, y, z);
     int id = world.getBlockId(x, y, z);
     if (ReikaBlockHelper.isPortalBlock(world, x, y, z)) {
       TileEntityShaft sha = new TileEntityShaft();
       sha.setBlockMetadata(RotaryAux.get6SidedMetadataFromPlayerLook(ep));
       sha.getIOSides(world, x, y, z, sha.getBlockMetadata());
       sha.xCoord = x;
       sha.yCoord = y;
       sha.zCoord = z;
       int dx = sha.getReadDirection().offsetX;
       int dy = sha.getReadDirection().offsetY;
       int dz = sha.getReadDirection().offsetZ;
       MachineRegistry m = MachineRegistry.getMachine(world, dx, dy, dz);
       if (m == MachineRegistry.SHAFT) {
         TileEntityShaft te = (TileEntityShaft) world.getBlockTileEntity(dx, dy, dz);
         if (te.isWritingToCoordinate(x, y, z)) {
           world.setBlock(
               dx,
               dy,
               dz,
               MachineRegistry.PORTALSHAFT.getBlockID(),
               MachineRegistry.PORTALSHAFT.getMachineMetadata(),
               3);
           TileEntityPortalShaft ps = new TileEntityPortalShaft();
           world.setBlockTileEntity(dx, dy, dz, ps);
           ps.setBlockMetadata(te.getBlockMetadata());
           ps.setPortalType(world, x, y, z);
           ps.material = te.getShaftType();
         }
       }
     }
     if (!ReikaWorldHelper.softBlocks(world, x, y, z)
         && world.getBlockMaterial(x, y, z) != Material.water
         && world.getBlockMaterial(x, y, z) != Material.lava) return false;
   }
   this.clearBlocks(world, x, y, z);
   AxisAlignedBB box = AxisAlignedBB.getBoundingBox(x, y, z, x + 1, y + 1, z + 1);
   List inblock = world.getEntitiesWithinAABB(EntityLivingBase.class, box);
   if (inblock.size() > 0) return false;
   if (!ep.canPlayerEdit(x, y, z, 0, is)) return false;
   else {
     if (!ep.capabilities.isCreativeMode) --is.stackSize;
     world.setBlock(x, y, z, MachineRegistry.SHAFT.getBlockID(), is.getItemDamage(), 3);
     if (is.getItemDamage() == RotaryNames.getNumberShaftTypes() - 1) {
       TileEntityShaft sha = (TileEntityShaft) world.getBlockTileEntity(x, y, z);
       if (sha != null) {
         // sha.type = MaterialRegistry.STEEL;
         sha.setBlockMetadata(6 + RotaryAux.get4SidedMetadataFromPlayerLook(ep));
       }
       return true;
     }
     TileEntityShaft sha = (TileEntityShaft) world.getBlockTileEntity(x, y, z);
     if (sha != null) {
       world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "step.stone", 1F, 1.5F);
       // sha.type = MaterialRegistry.setType(is.getItemDamage());
     }
   }
   TileEntityShaft sha = (TileEntityShaft) world.getBlockTileEntity(x, y, z);
   sha.setBlockMetadata(RotaryAux.get6SidedMetadataFromPlayerLook(ep));
   sha.placer = ep.getEntityName();
   if (RotaryAux.shouldSetFlipped(world, x, y, z)) {
     sha.isFlipped = true;
   }
   return true;
 }