@Override
 public void run() {
   while (!Thread.interrupted() && !kill.get()) {
     try {
       ChunkProcessingOrder order = queue.dequeue();
       Calculations.Obfuscate(order.packet, order.player);
       order.packet.compress(localDeflater.get());
       order.output.FinishedProcessing(order.packet);
       Thread.sleep(1);
     } catch (InterruptedException e) {
       // If interrupted then exit
     } catch (Exception e) {
       Orebfuscator.log(e);
     }
   }
 }
  public void run() {
    while (!this.isInterrupted() && !kill.get()) {
      try {
        // Wait until necessary
        long timeWait =
            lastExecute + OrebfuscatorConfig.ProximityHiderRate - System.currentTimeMillis();
        lastExecute = System.currentTimeMillis();
        if (timeWait > 0) {
          Thread.sleep(timeWait);
        }

        if (!OrebfuscatorConfig.UseProximityHider) {
          running = false;
          return;
        }

        HashMap<Player, Location> checkPlayers = new HashMap<Player, Location>();

        synchronized (playersToCheck) {
          checkPlayers.putAll(playersToCheck);
          playersToCheck.clear();
        }

        int distance = OrebfuscatorConfig.ProximityHiderDistance;
        int distanceSquared = distance * distance;

        for (Player p : checkPlayers.keySet()) {

          if (p == null) {
            continue;
          }

          synchronized (proximityHiderTracker) {
            if (!proximityHiderTracker.containsKey(p)) {
              continue;
            }
          }

          Location loc1 = p.getLocation();
          Location loc2 = checkPlayers.get(p);

          // If player changed world
          if (!loc1.getWorld().equals(loc2.getWorld())) {
            synchronized (proximityHiderTracker) {
              proximityHiderTracker.remove(p);
              proximityHiderTrackerLocal.remove(p);
            }
            continue;
          }

          // Player didn't actually move
          if (loc1.getBlockX() == loc2.getBlockX()
              && loc1.getBlockY() == loc2.getBlockY()
              && loc1.getBlockZ() == loc2.getBlockZ()) {
            continue;
          }

          Set<Block> blocks = proximityHiderTrackerLocal.get(p);
          Set<Block> removedBlocks = new HashSet<Block>();
          if (blocks == null) {
            blocks = new HashSet<Block>();
            proximityHiderTrackerLocal.put(p, blocks);
          }

          int y = (int) Math.floor(p.getLocation().getY());

          boolean skip = OrebfuscatorConfig.skipProximityHiderCheck(y);

          synchronized (proximityHiderTracker) {
            Set<Block> synchronizedBlocks = proximityHiderTracker.get(p);
            if (synchronizedBlocks != null) {
              blocks.addAll(synchronizedBlocks);
              synchronizedBlocks.clear();
            }
          }

          if (!skip) {
            for (Block b : blocks) {
              if (b == null || b.getWorld() == null || p.getWorld() == null) {
                removedBlocks.add(b);
                continue;
              }

              if (!p.getWorld().equals(b.getWorld())) {
                removedBlocks.add(b);
                continue;
              }

              if (OrebfuscatorConfig.proximityHiderDeobfuscate(y, b)
                  || p.getLocation().distanceSquared(b.getLocation()) < distanceSquared) {
                removedBlocks.add(b);

                if (CalculationsUtil.isChunkLoaded(
                    b.getWorld(), b.getChunk().getX(), b.getChunk().getZ())) {
                  p.sendBlockChange(b.getLocation(), b.getTypeId(), b.getData());
                  final Block block = b;
                  final Player player = p;
                  Orebfuscator.instance.runTask(
                      new Runnable() {
                        @Override
                        public void run() {
                          OrebfuscatorConfig.blockAccess.updateBlockTileEntity(block, player);
                        }
                      });
                }
              }
            }

            for (Block b : removedBlocks) {
              blocks.remove(b);
            }
          }
        }
      } catch (Exception e) {
        Orebfuscator.log(e);
      }
    }

    running = false;
  }