/**
  * Detects if a Player can use a protectable Block or not
  *
  * @param player the Player involved
  * @param b the Block to be used
  * @return true if the Player can use the Block, false otherwise
  */
 public boolean canUse(final Player player, final Block b) {
   if (Perms.hasProtectionSignBypass(player)) {
     return true;
   }
   final Material blockType = b.getType();
   final String userId = PlayerIdsUtil.getId(player.getName());
   final List<Sign> signLines;
   if (blockType == Material.CHEST || blockType == Material.TRAPPED_CHEST) {
     signLines = SignUtil.getSignsForChest(b);
   } else if (getProtectedMaterials().contains(blockType)) {
     signLines = SignUtil.getSignsForBlock(b);
   } else {
     return true;
   }
   boolean protectedBySign = false;
   boolean explicitlyAllowed = false;
   for (final Sign sign : signLines) {
     if (sign.getLine(0).equals(PROTECTION)) {
       protectedBySign = true;
       if (ColorUtil.stripColorCodes(sign.getLine(1)).equals(userId)
           || ColorUtil.stripColorCodes(sign.getLine(2)).equals(userId)
           || ColorUtil.stripColorCodes(sign.getLine(3)).equals(userId)) {
         explicitlyAllowed = true;
         break;
       }
     }
   }
   return !protectedBySign || explicitlyAllowed;
 }
 /**
  * Detect if a Block can be broken by a Player or by something else (Explosion...)
  *
  * @param b the Block to be broken
  * @param player the Player that want to break the Block, if there is one, null otherwise
  * @return true if the block can be broken [by the Player], false otherwise
  */
 public boolean canBreak(final Block b, final Player player) {
   final Material blockType = b.getType();
   final String userId = player != null ? PlayerIdsUtil.getId(player.getName()) : null;
   if (blockType == Material.SIGN_POST || blockType == Material.WALL_SIGN) {
     final Sign sign = (Sign) b.getState();
     return !sign.getLine(0).equals(PROTECTION)
         || player != null && ColorUtil.stripColorCodes(sign.getLine(3)).equals(userId)
         || player != null && Perms.hasProtectionSignBreak(player);
   } else {
     final List<Sign> signLines;
     if (blockType == Material.CHEST || blockType == Material.TRAPPED_CHEST) {
       signLines = SignUtil.getSignsForChest(b);
     } else if (getProtectedMaterials().contains(blockType)) {
       signLines = SignUtil.getSignsForBlock(b);
     } else {
       return true;
     }
     for (final Sign sign : signLines) {
       if (sign.getLine(0).equals(PROTECTION)) {
         return false;
       }
     }
     return true;
   }
 }
 @Override
 public boolean onCommand(
     final CommandSender sender, final Command cmd, final String label, final String[] args) {
   switch (cmd.getName()) {
     case "heal":
       if (Perms.hasHeal(sender)) {
         return this.cmdHeal(sender, args);
       } else {
         this.plugin.sendMessage(sender, MessageId.noPermissionForCommand);
         return true;
       }
     case "feed":
       if (Perms.hasFeed(sender)) {
         return this.cmdFeed(sender, args);
       } else {
         this.plugin.sendMessage(sender, MessageId.noPermissionForCommand);
         return true;
       }
     case "health":
       if (Perms.hasHealth(sender)) {
         return this.cmdHealth(sender, args);
       } else {
         this.plugin.sendMessage(sender, MessageId.noPermissionForCommand);
         return true;
       }
     case "food":
       if (Perms.hasFood(sender)) {
         return this.cmdFood(sender, args);
       } else {
         this.plugin.sendMessage(sender, MessageId.noPermissionForCommand);
         return true;
       }
     default:
       return false;
   }
 }
 @Override
 public boolean onCommand(
     final CommandSender sender, final Command cmd, final String label, final String[] args) {
   switch (cmd.getName()) {
     case COMMAND_TP:
       if (Perms.hasTp(sender)) {
         return this.execTpCommand(sender, args);
       } else {
         this.plugin.sendMessage(sender, MessageId.noPermissionForCommand);
         return true;
       }
     case COMMAND_TPPOS:
       if (Perms.hasTpPos(sender)) {
         return this.execTpPosCommand(sender, args);
       } else {
         this.plugin.sendMessage(sender, MessageId.noPermissionForCommand);
         return true;
       }
     case COMMAND_TPHERE:
       if (Perms.hasTpHere(sender)) {
         return this.execTpHereCommand(sender, args);
       } else {
         this.plugin.sendMessage(sender, MessageId.noPermissionForCommand);
         return true;
       }
     case COMMAND_TPTHERE:
       if (Perms.hasTpThere(sender)) {
         return this.execTpThereCommand(sender, args);
       } else {
         this.plugin.sendMessage(sender, MessageId.noPermissionForCommand);
         return true;
       }
     case COMMAND_TPWORLD:
       if (Perms.hasTpWorld(sender)) {
         return this.execTpWorldCommand(sender, args);
       } else {
         this.plugin.sendMessage(sender, MessageId.noPermissionForCommand);
         return true;
       }
     case COMMAND_TPBACK:
       if (Perms.hasTpBack(sender)) {
         return this.execTpBackCommand(sender, args);
       } else {
         this.plugin.sendMessage(sender, MessageId.noPermissionForCommand);
         return true;
       }
     default:
       return false;
   }
 }
 @Override
 public boolean onCommand(
     final CommandSender sender, final Command command, final String label, final String[] args) {
   if (command.getName().equals("itemnetwork")) {
     if (!Perms.hasItemNetwork(sender)) {
       feature.getPlugin().sendMessage(sender, MessageId.noPermissionForCommand);
       return true;
     } else {
       if (args.length < 2) {
         return false;
       } else {
         final String networkName = args[1];
         final ItemNetwork network = feature.getNetworks().get(networkName.toLowerCase());
         switch (args[0].toLowerCase()) {
           case "c":
           case "create":
             if (network != null) {
               feature
                   .getPlugin()
                   .sendMessage(sender, MessageId.general_itemnetwork_alreadyExists, networkName);
               return true;
             } else {
               feature
                   .getNetworks()
                   .put(
                       networkName.toLowerCase(),
                       new ItemNetwork(feature, networkName, sender.getName()));
               feature
                   .getPlugin()
                   .sendMessage(sender, MessageId.general_itemnetwork_created, networkName);
               return true;
             }
           case "d":
           case "delete":
             if (network == null) {
               feature
                   .getPlugin()
                   .sendMessage(sender, MessageId.general_itemnetwork_unknown, networkName);
               return true;
             } else if (network.getCreator().equals(sender.getName()) || Perms.isAdmin(sender)) {
               network.terminate();
               feature.getNetworks().remove(networkName.toLowerCase());
               feature
                   .getPlugin()
                   .sendMessage(sender, MessageId.general_itemnetwork_deleted, networkName);
               return true;
             } else {
               feature
                   .getPlugin()
                   .sendMessage(sender, MessageId.general_itemnetwork_youNeedToBeCreator);
               return true;
             }
           default:
             return false;
         }
       }
     }
   } else {
     return false;
   }
 }
 @Override
 public boolean onCommand(
     final CommandSender sender,
     final Command command,
     final String commandLabel,
     final String[] args) {
   if (command.getName().equals(COMMAND)) {
     if (!Perms.hasWeather(sender)) {
       this.plugin.sendMessage(sender, MessageId.noPermissionForCommand);
       return true;
     } else {
       World world;
       final String type;
       int duration = new Random().nextInt(1000) + 500;
       if (args.length == 1) {
         type = args[0];
         if (!(sender instanceof Player)) {
           this.plugin.sendMessage(sender, MessageId.missingWorldArg);
           return true;
         }
         world = ((Player) sender).getWorld();
       } else if (args.length == 2) {
         type = args[0];
         try {
           duration = Integer.parseInt(args[1]);
           if (!(sender instanceof Player)) {
             this.plugin.sendMessage(sender, MessageId.missingWorldArg);
             return true;
           }
           world = ((Player) sender).getWorld();
         } catch (final NumberFormatException e) {
           world = Bukkit.getWorld(args[1]);
           if (world == null) {
             this.plugin.sendMessage(sender, MessageId.unknownWorld, args[1]);
             return true;
           }
         }
       } else if (args.length == 3) {
         type = args[0];
         try {
           duration = Integer.parseInt(args[1]);
         } catch (final NumberFormatException e) {
           return false;
         }
         world = Bukkit.getWorld(args[2]);
         if (world == null) {
           this.plugin.sendMessage(sender, MessageId.unknownWorld, args[2]);
           return true;
         }
       } else {
         return false;
       }
       switch (type) {
         case "c":
         case "clear":
           world.setStorm(false);
           world.setThundering(false);
           world.setWeatherDuration(duration * 20);
           world.setThunderDuration(0);
           break;
         case "r":
         case "rain":
           world.setStorm(true);
           world.setThundering(false);
           world.setWeatherDuration(duration * 20);
           world.setThunderDuration(0);
           break;
         case "t":
         case "thunder":
           world.setStorm(true);
           world.setThundering(true);
           world.setWeatherDuration(duration * 20);
           world.setThunderDuration(duration * 20);
           break;
         default:
           return false;
       }
       this.plugin.broadcastMessage(
           MessageId.general_weatherSet,
           type,
           world.getName(),
           sender.getName(),
           Integer.toString(duration));
       return true;
     }
   } else {
     return false;
   }
 }