public static boolean playerBypassOp(Player player) {
   boolean ret = false;
   try {
     ret = OrebfuscatorConfig.getNoObfuscationForOps() && player.isOp();
   } catch (Exception e) {
     Orebfuscator.log(
         "Error while obtaining Operator status for player"
             + player.getName()
             + ": "
             + e.getMessage());
     e.printStackTrace();
   }
   return ret;
 }
 public static boolean playerBypassPerms(Player player) {
   boolean ret = false;
   try {
     ret =
         OrebfuscatorConfig.getNoObfuscationForPermission()
             && player.hasPermission("Orebfuscator.deobfuscate");
   } catch (Exception e) {
     Orebfuscator.log(
         "Error while obtaining permissions for player"
             + player.getName()
             + ": "
             + e.getMessage());
     e.printStackTrace();
   }
   return ret;
 }
  public static void load() {
    // Version check
    int version = getInt("ConfigVersion", CONFIG_VERSION);
    if (version < CONFIG_VERSION) {
      /*
      Orebfuscator.log("Configuration out of date. Recreating new configuration file.");
      File configFile = new File(Orebfuscator.instance.getDataFolder(), "config.yml");
      File destination = new File(Orebfuscator.instance.getDataFolder(), "config_old.yml");
      if (destination.exists())
      {
          try
          {
              destination.delete();
          }
          catch (Exception e)
          {
              Orebfuscator.log(e);
          }
      }
      configFile.renameTo(destination);
      reload();
      */
      ObfuscatedDataCache.ClearCache();
      setData("ConfigVersion", CONFIG_VERSION);
    }

    EngineMode = getInt("Integers.EngineMode", EngineMode);
    if (EngineMode != 1 && EngineMode != 2) {
      EngineMode = 2;
      System.out.println("[Orebfuscator] EngineMode must be 1 or 2.");
    }
    UpdateRadius = getInt("Integers.UpdateRadius", UpdateRadius);
    InitialRadius = getInt("Integers.InitialRadius", InitialRadius);
    if (InitialRadius > 5) {
      InitialRadius = 5;
      System.out.println("[Orebfuscator] InitialRadius must be less than 6.");
    }
    if (InitialRadius == 0) {
      System.out.println(
          "[Orebfuscator] Warning, InitialRadius is 0. This will cause all exposed blocks to be obfuscated.");
    }
    ProcessingThreads = getInt("Integers.ProcessingThreads", ProcessingThreads);
    MaxLoadedCacheFiles = getInt("Integers.MaxLoadedCacheFiles", MaxLoadedCacheFiles);
    ProximityHiderDistance = getInt("Integers.ProximityHiderDistance", ProximityHiderDistance);
    ProximityHiderID = getInt("Integers.ProximityHiderID", ProximityHiderID);
    ProximityHiderEnd = getInt("Integers.ProximityHiderEnd", ProximityHiderEnd);
    AirGeneratorMaxChance = getInt("Integers.AirGeneratorMaxChance", AirGeneratorMaxChance);
    OrebfuscatorPriority = getInt("Integers.OrebfuscatorPriority", OrebfuscatorPriority);
    UseProximityHider = getBoolean("Booleans.UseProximityHider", UseProximityHider);
    UseSpecialBlockForProximityHider =
        getBoolean("Booleans.UseSpecialBlockForProximityHider", UseSpecialBlockForProximityHider);
    UpdateOnDamage = getBoolean("Booleans.UpdateOnDamage", UpdateOnDamage);
    DarknessHideBlocks = getBoolean("Booleans.DarknessHideBlocks", DarknessHideBlocks);
    NoObfuscationForOps = getBoolean("Booleans.NoObfuscationForOps", NoObfuscationForOps);
    NoObfuscationForPermission =
        getBoolean("Booleans.NoObfuscationForPermission", NoObfuscationForPermission);
    UseCache = getBoolean("Booleans.UseCache", UseCache);
    LoginNotification = getBoolean("Booleans.LoginNotification", LoginNotification);
    AntiTexturePackAndFreecam =
        getBoolean("Booleans.AntiTexturePackAndFreecam", AntiTexturePackAndFreecam);
    Enabled = getBoolean("Booleans.Enabled", Enabled);
    setBlockValues(
        ObfuscateBlocks,
        getIntList(
            "Lists.ObfuscateBlocks",
            Arrays.asList(new Integer[] {14, 15, 16, 21, 54, 56, 73, 74, 129})));
    setBlockValues(
        ProximityHiderBlocks,
        getIntList(
            "Lists.ProximityHiderBlocks",
            Arrays.asList(new Integer[] {23, 54, 56, 58, 61, 62, 116, 129})));
    DisabledWorlds = getStringList("Lists.DisabledWorlds", DisabledWorlds);
    CacheLocation = getString("Strings.CacheLocation", CacheLocation);
    CacheFolder = new File(CacheLocation);

    RandomBlocks = getIntList2("Lists.RandomBlocks", Arrays.asList(RandomBlocks));

    // Validate RandomBlocks
    for (int i = 0; i < RandomBlocks.length; i++) {
      // Don't want people to put chests and other stuff that lags the hell out of players.
      if (OrebfuscatorConfig.isBlockTransparent((short) (int) RandomBlocks[i])) {
        RandomBlocks[i] = 0;
      }
    }
    RandomBlocks2 = RandomBlocks;

    save();
  }
  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;
  }