public class EpicRename implements CommandExecutor {
	
	// VERSION 3

	@Override
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
		
		// Start Command Handling | EpicRename
		if (command.getName().equalsIgnoreCase("epicrename")) {
			
			if (!sender.hasPermission("epicrename.epicrename")) { // Check Basic Permission
				Messager.msgSender(Main.getMsgFromConfig("epicrename.no_permission"), sender);
				return true;
			}
			
			if (args.length > 0) {
				if (args[0].equalsIgnoreCase("license")) { // Start /epicrename license
					Messager.msgSender(Main.getMsgFromConfig("epicrename.license"), sender);
					return true;
				} else if (args[0].equalsIgnoreCase("help")) { // End /epicrename license | Start /epicrename help
					for (String s : Main.messages.getStringList("epicrename.help")) {
						Messager.msgSender(s, sender);
					}
					return true;
				} else if (args[0].equalsIgnoreCase("reload")) { // End /epicrename license | Start /epicrename reload
					if (sender.hasPermission("epicrename.epicrename.reload")) {
						Main.reloadConfigs();
						Messager.msgSender(Main.getMsgFromConfig("epicrename.reload_success"), sender);
						return true;
					} else {
						Messager.msgSender(Main.getMsgFromConfig("epicrename.no_permission"), sender);
						return true;
					}					
				} else if (args[0].equalsIgnoreCase("debug")) { // End /epicrename reload | Start /epicrename debug
					if (sender.hasPermission("epicrename.epicrename.debug")) {
						if (Main.debug) {
							Main.debug = false;
							Messager.msgSender(Main.getMsgFromConfig("epicrename.debug_disable"), sender);
							return true;
						} else {
							Main.debug = true;
							Messager.msgSender(Main.getMsgFromConfig("epicrename.debug_enable"), sender);
							return true;
						}
					} else {
						Messager.msgSender(Main.getMsgFromConfig("epicrename.no_permission"), sender);
						return true;
					}
				} else if (args[0].equalsIgnoreCase("version")) { // End /epicrename debug | Start /epicrename version
					Messager.msgSender(Main.getMsgFromConfig("epicrename.version"), sender); 
					return true;
				} else { // End /epicrename version | Start /epicrename invalid args
					Messager.msgSender(Main.getMsgFromConfig("epicrename.invalid_args"), sender);
					return true;
				}
			} else { // No Args				
				Messager.msgSender(Main.getMsgFromConfig("epicrename.no_args"), sender);				
				return true;
			} //End No args
		} // End Command Handling | EpicRename
		
		return false;
	}

}
 public class Export implements CommandExecutor {
	
	private static ArrayList<UUID> playersWhoHaveConfirmed = new ArrayList<UUID>();

	@Override
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
		
		if (sender instanceof Player) {
			Player p = (Player) sender;
			if (sender.hasPermission("epicrename.export")) {
				
				if (args.length != 0) {
					if (args.length == 1) {
						String arg = args[0];
						if (arg.equalsIgnoreCase("confirm")) { // /export confirm							
							playersWhoHaveConfirmed.add(p.getUniqueId());
							
							Messager.msgSenderWithConfigMsg("export.confirmed", sender);
							return true;
						}
						
						// Check confirmation
						if (!playersWhoHaveConfirmed.contains(p.getUniqueId())) {
							Messager.msgSenderWithConfigMsg("export.warn_public", sender);
							return true;
						}
						
						if (arg.equalsIgnoreCase("hand") || arg.equalsIgnoreCase("h")) { // /export hand
							ItemStack inHand = p.getInventory().getItemInMainHand();
							
							if (inHand.getType() == Material.AIR || inHand == null) {
								Messager.msgSenderWithConfigMsg("export.no_air", sender);
								return true;
							}
							
							String theItem = ItemSerialization.toString(inHand);
							String response = null;
							try {
								response = EpicRenameOnlineAPI.paste(theItem);
							} catch (MalformedURLException e) {
								if (Main.debug) {
									e.printStackTrace();
								}
								Messager.msgSender(Main.getMsgFromConfig("export.post_fail").replace("{error}", "MalformedURLException"), sender);
								return true;
							} catch (IOException e) {
								if (Main.debug) {
									e.printStackTrace();
								}
								Messager.msgSender(Main.getMsgFromConfig("export.post_fail").replace("{error}", "IOException"), sender);
								return true;
							}
							
							if (response.startsWith("ERROR:")) {
								// FAILED
								Messager.msgSender(Main.getMsgFromConfig("export.post_fail").replace("{error}", response), sender);
							} else {
								// SUCCESS
								Messager.msgSender(Main.getMsgFromConfig("export.success").replace("{link}", response), sender);
							}			
							
							return true;
						} else if (arg.equalsIgnoreCase("inventory") || arg.equalsIgnoreCase("inv") || arg.equalsIgnoreCase("i")) { // /export inventory
							
							String theInventory = ItemSerialization.toString(p.getInventory());
							String response = null;
							try {
								response = EpicRenameOnlineAPI.paste(theInventory);
							} catch (MalformedURLException e) {
								if (Main.debug) {
									e.printStackTrace();
								}
								Messager.msgSender(Main.getMsgFromConfig("export.post_fail").replace("{error}", "MalformedURLException"), sender);
								return true;
							} catch (IOException e) {
								if (Main.debug) {
									e.printStackTrace();
								}
								Messager.msgSender(Main.getMsgFromConfig("export.post_fail").replace("{error}", "IOException"), sender);
								return true;
							}
							
							if (response.startsWith("ERROR:")) {
								// FAILED
								Messager.msgSender(Main.getMsgFromConfig("export.post_fail").replace("{error}", response), sender);
							} else {
								// SUCCESS
								Messager.msgSender(Main.getMsgFromConfig("export.success").replace("{link}", response), sender);
							}						
							
							return true;
						} else {
							Messager.msgSenderWithConfigMsg("export.wrong_args", sender);
							return true;
						}
					} else { // More than 1 argument
						Messager.msgSenderWithConfigMsg("export.wrong_args", sender);
						return true;
					}					
				} else { // Player must provide at least one argument
					Messager.msgSenderWithConfigMsg("export.no_args", sender);
					return true;
				}				
			} else { // sender doesn't have permission
				Messager.msgSenderWithConfigMsg("export.no_permission", sender);
				return true;
			}
		} else { // sender NOT Player
			Messager.msgSenderWithConfigMsg("export.wrong_sender", sender);
			return true;
		}
	}

}
 public class Glow implements CommandExecutor {

	@SuppressWarnings("deprecation")
	@Override
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

		if (command.getName().equalsIgnoreCase("glow")) {
			if (sender.hasPermission("epicrename.glow")) {
				if (sender instanceof Player) {
					Player player = (Player) sender;

					if (WorldChecker.checkWorld(player)) {
						ItemStack inHand = RenameUtil.getInHand(player);
						Material m = inHand.getType();
						
						// Check Material Permissions
						if (!MaterialPermManager.checkPerms(EpicRenameCommands.GLOW, inHand, player)) {
							Messager.msgPlayer(Main.getMsgFromConfig("glow.no_permission_for_material"), player);
							return true;
						}
						
						// Issue #76 | Check Blacklist						
						if (!Blacklists.checkMaterialBlacklist(RenameUtil.getInHand(player).getType(), player)) {
							Messager.msgPlayer(Main.getMsgFromConfig("glow.blacklisted_material_found"), player);
							return true;
						}
						// End Issue #76
						
						// Check Existing Name Blacklist #81
						if (!Blacklists.checkExistingName(player)) {
							Messager.msgPlayer(Main.getMsgFromConfig("glow.blacklisted_existing_name_found"), player);
							return true;
						}
						
						// Check Existing Lore Blacklist #81
						if (!Blacklists.checkExistingLore(player)) {
							Messager.msgPlayer(Main.getMsgFromConfig("glow.blacklisted_existing_lore_found"), player);
							return true;
						}						

						if (!(m == Material.AIR || m == null)) {
							if (inHand.getEnchantments().size() == 0) {								
								if (m == Material.FISHING_ROD) {
									Debug.send("Item is a fishing rod");
									
									// Add economy cost option #101
									EcoMessage ecoStatus = EconomyManager.takeMoney(player,	EpicRenameCommands.GLOW);

									if (ecoStatus == EcoMessage.TRANSACTION_ERROR) {
										return true;
									}
									
									// Add experience cost option #121
									XpMessage xpStatus = XpCostManager.takeXp(player, EpicRenameCommands.GLOW);
									
									if (xpStatus == XpMessage.TRANSACTION_ERROR) {
										return true;
									}
									
									inHand.addUnsafeEnchantment(Enchantment.ARROW_INFINITE, 4341);
									ItemMeta im = inHand.getItemMeta();
									im.addItemFlags(ItemFlag.HIDE_ENCHANTS);
									inHand.setItemMeta(im);

									player.getInventory().setItemInMainHand(inHand);
									Messager.msgSender(Main.getMsgFromConfig("glow.success"), sender);
									return true;
								} else {
									Debug.send("Item is not a fishing rod.");
									
									// Add economy cost option #101
									EcoMessage ecoStatus = EconomyManager.takeMoney(player,	EpicRenameCommands.GLOW);

									if (ecoStatus == EcoMessage.TRANSACTION_ERROR) {
										return true;
									}
									
									// Add experience cost option #121
									XpMessage xpStatus = XpCostManager.takeXp(player, EpicRenameCommands.GLOW);
									
									if (xpStatus == XpMessage.TRANSACTION_ERROR) {
										return true;
									}
									
									inHand.addUnsafeEnchantment(Enchantment.LURE, 4341);
									ItemMeta im = inHand.getItemMeta();
									im.addItemFlags(ItemFlag.HIDE_ENCHANTS);
									inHand.setItemMeta(im);

									if (Main.USE_NEW_GET_HAND) { // Use 1.9+ method
										player.getInventory().setItemInMainHand(inHand);
									} else { // Use older method.
										player.setItemInHand(inHand);
									}
									Messager.msgSender(Main.getMsgFromConfig("glow.success"), sender);
									return true;
								}
							} else {
								Messager.msgSender(Main.getMsgFromConfig("glow.has_enchants"), sender);
								return true;
							}
						} else {
							Messager.msgSender(Main.getMsgFromConfig("glow.cannot_edit_air"), sender);
							return true;
						}
					} else {
						Messager.msgSender(Main.getMsgFromConfig("glow.disabled_world"), sender);
						return true;
					}
				} else {
					Messager.msgSender(Main.getMsgFromConfig("glow.wrong_sender"), sender);
					return true;
				}
			} else {
				Messager.msgSender(Main.getMsgFromConfig("glow.no_permission"), sender);
				return true;
			}
		}

		return false;
	}

}
 public class Import implements CommandExecutor {

	private static ArrayList<UUID> playersWhoHaveConfirmed = new ArrayList<UUID>();

	/**
	 * Usage:
	 * 
	 * import <hand,inventory> <link,rawyaml>
	 * 
	 * Importing an inventory forces a /import confirm before allowing a player to
	 * import once per server restart. Importing to your hand only works if the hand
	 * is empty.
	 *
	 **/

	@Override
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

		if (sender instanceof Player) {
			Player p = (Player) sender;

			if (sender.hasPermission("epicrename.import")) {

				if (args.length != 0) {
					PlayerInventory inv = p.getInventory();
					ItemStack mainHand = inv.getItemInMainHand();
					if (args[0].equalsIgnoreCase("hand") || args[0].equalsIgnoreCase("h")) {
						// /import hand
						if (args.length == 2) {

							if (mainHand == null || mainHand.getType() == Material.AIR) {

								String link = args[1];
								String textFromWeb = null;

								try {
									textFromWeb = EpicRenameOnlineAPI.getTextFromURL(link).get();
									Debug.send("Got: " + textFromWeb);
								} catch (IOException e) {
									Debug.send("Failed to GET text data from URL.");
									Messager.msgSender(Main.getMsgFromConfig("import.failed_to_get_data")
											.replace("{link}", link).replace("{error}", "IOException. Turn on debugging with /epicrename debug."), sender);
									Debug.send("[Import] " + Main.getStackTrace(e));
									return true;
								} catch (NoSuchElementException e2) {
									Messager.msgSender(Main.getMsgFromConfig("import.failed_to_get_data")
											.replace("{link}", link).replace("{error}", "Text received from server is null."), sender);
									return true;
								} catch (EpicRenameOnlineExpiredException e) {
									Debug.send("EpicRenameOnlineExpiredException - Link has expired.");
									Messager.msgSender(Main.getMsgFromConfig("import.failed_to_get_data")
											.replace("{link}", link).replace("{error}", "EpicRenameOnline reports that the link has expired."), sender);
									return true;
								} catch (EpicRenameOnlineNotFoundException e) {
									Debug.send("EpicRenameOnlineNotFoundException - Link doesn't exist.");
									Messager.msgSender(Main.getMsgFromConfig("import.failed_to_get_data")
											.replace("{link}", link).replace("{error}", "EpicRenameOnline reports that the link doesn't exist."), sender);
									return true;
								}

								ItemStack imported = ItemSerialization.toItem(textFromWeb);

								if (imported == null) {
									// FAILED
									Messager.msgSenderWithConfigMsg("import.yaml_fail", sender);
									return true;
								}

								inv.setItemInMainHand(imported);
								Messager.msgSenderWithConfigMsg("import.success", sender);
								return true;
							} else {
								Messager.msgSenderWithConfigMsg("import.full_hand", sender);
								return true;
							}
						} else {
							Messager.msgSenderWithConfigMsg("import.wrong_args_hand", sender);
							return true;
						}
					} else if (args[0].equalsIgnoreCase("inventory") || args[0].equalsIgnoreCase("inv")
							|| args[0].equalsIgnoreCase("i")) {
						// /import inventory

						// Confirmation
						if (!playersWhoHaveConfirmed.contains(p.getUniqueId())) {
							Messager.msgSenderWithConfigMsg("import.not_confirmed", sender);
							return true;
						}

						if (args.length == 2) {

							String link = args[1];
							String textFromWeb = null;

							try {
								textFromWeb = EpicRenameOnlineAPI.getTextFromURL(link).get();	
								Debug.send("Got :" + textFromWeb);
							} catch (IOException e) {
								Debug.send("Failed to GET text data from URL.");
								Messager.msgSender(Main.getMsgFromConfig("import.failed_to_get_data")
										.replace("{link}", link).replace("{error}", "IOException. Turn on debugging with /epicrename debug."), sender);
								Debug.send("[Import] " + Main.getStackTrace(e));
								return true;
							} catch (NoSuchElementException e2) {
								Messager.msgSender(Main.getMsgFromConfig("import.failed_to_get_data")
										.replace("{link}", link).replace("{error}", "Text received from server is null."), sender);
								return true;
							} catch (EpicRenameOnlineExpiredException e) {
								Debug.send("EpicRenameOnlineExpiredException - Link has expired.");
								Messager.msgSender(Main.getMsgFromConfig("import.failed_to_get_data")
										.replace("{link}", link).replace("{error}", "EpicRenameOnline reports that the link has expired."), sender);
								return true;
							} catch (EpicRenameOnlineNotFoundException e) {
								Debug.send("EpicRenameOnlineNotFoundException - Link doesn't exist.");
								Messager.msgSender(Main.getMsgFromConfig("import.failed_to_get_data")
										.replace("{link}", link).replace("{error}", "EpicRenameOnline reports that the link doesn't exist."), sender);
								return true;
							}

							ItemSerialization.fillInventoryFromString(textFromWeb, p);

							Messager.msgSenderWithConfigMsg("import.success", sender);
							return true;
						} else {
							Messager.msgSenderWithConfigMsg("import.wrong_args_inventory", sender);
							return true;
						}
					} else if (args[0].equalsIgnoreCase("raw") || args[0].equalsIgnoreCase("r")) {
						// /import raw

						// Try to import the raw yaml text. Single item only.
						if (mainHand == null || mainHand.getType() == Material.AIR) {
							// Empty Main Hand
							StringBuilder yamlDataBuilder = new StringBuilder("");

							for (int i = 1; i < args.length; i++) {
								yamlDataBuilder.append(args[i] + " ");
							}

							String yamlData = yamlDataBuilder.toString().trim();

							ItemStack importedItem = ItemSerialization.toItem(yamlData);

							if (importedItem == null) {
								// FAILED
								Messager.msgSenderWithConfigMsg("import.yaml_fail", sender);
								return true;
							}

							// Put ItemStack in the players main hand.

							inv.setItemInMainHand(importedItem);
							Messager.msgSenderWithConfigMsg("import.success", sender);
							return true;
						} else {
							// Must have empty hand
							Messager.msgSenderWithConfigMsg("import.full_hand", sender);
							return true;
						}
					} else if (args[0].equalsIgnoreCase("confirm")) {
						playersWhoHaveConfirmed.add(p.getUniqueId());
						Messager.msgSenderWithConfigMsg("import.confirmed", sender);
						return true;
					} else {
						Messager.msgSenderWithConfigMsg("import.wrong_args", sender);
						return true;
					}
				} else { // Player must provide at least one argument
					Messager.msgSenderWithConfigMsg("import.no_args", sender);
					return true;
				}
			} else { // sender doesn't have permission
				Messager.msgSenderWithConfigMsg("import.no_permission", sender);
				return true;
			}
		} else { // sender NOT Player
			Messager.msgSenderWithConfigMsg("import.wrong_sender", sender);
			return true;
		}
	}

}
 public class InsertLoreLine implements CommandExecutor {

	@Override
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
		
		if (command.getName().equalsIgnoreCase("insertloreline")) {
			if (sender.hasPermission("epicrename.insertloreline")) {
				if (sender instanceof Player) {
					
					Player player = (Player) sender;
					
					if (WorldChecker.checkWorld(player)) {
						
						if (args.length >= 1) {
							
							int lineNumber = -1;
							
							try {
								lineNumber = Integer.parseInt(args[0]);
							} catch (NumberFormatException e){
								// Not an integer.
								Debug.send(e.getMessage());
								Messager.msgSenderWithConfigMsg("insertloreline.not_an_int", sender);
								return true;
							}
							
							if (args.length == 1) {
								// No text arguments
								Messager.msgSenderWithConfigMsg("insertloreline.wrong_args", sender);
								return true;
							}
							
							if (lineNumber <= 0) {
								Debug.send("[InsertLoreLine] The number " + lineNumber + " is below or equal to 0.");
								Messager.msgPlayer(Main.getMsgFromConfig("insertloreline.invalid_number"), player);
								return true;
							}
							
							Material type = RenameUtil.getInHand(player).getType();
							
							if (type== Material.AIR || type == null) {
								// Cannot edit air
								Messager.msgSenderWithConfigMsg("insertloreline.cannot_edit_air", sender);
								return true;
							}
							
							ItemStack inHand = RenameUtil.getInHand(player);
							
							// Check Material Permissions
							if (!MaterialPermManager.checkPerms(EpicRenameCommands.INSERTLORELINE, inHand, player)) {
								// Doesn't have material permissions
								Messager.msgSenderWithConfigMsg("insertloreline.no_permission_for_material", sender);
								return true;
							}
							
							// Check Text Blacklist
							if (!Blacklists.checkTextBlacklist(args, player)) {
								// Failed text blacklist.
								Messager.msgSenderWithConfigMsg("insertloreline.blacklisted_word_found", sender);
								return true;
							}
							
							// Check Material Blacklist
							if (!Blacklists.checkMaterialBlacklist(type, player)) {
								// Failed material blacklist
								Messager.msgSenderWithConfigMsg("insertloreline.blacklisted_material_found", sender);
								return true;
							}
							
							// Check Existing Name Blacklist #81
							if (!Blacklists.checkExistingName(player)) {
								// Failed existing name blacklist
								Messager.msgSenderWithConfigMsg("insertloreline.blacklisted_existing_name_found", sender);
								return true;
							}
							
							// Check Existing Lore Blacklist #81
							if (!Blacklists.checkExistingLore(player)) {
								// Failed existing lore blacklist
								Messager.msgSenderWithConfigMsg("insertloreline.blacklisted_existing_lore_found", sender);
								return true;
							}
							
							// Check FormattingPerms
							if (!FormattingPermManager.checkPerms(EpicRenameCommands.INSERTLORELINE, args, player)) {
								// FormattingPermManager handles the message.
								return true;
							}
							
							StringBuilder textArguments = new StringBuilder("");						
							
							for (int i = 1; i < args.length; i++) {
								textArguments.append(args[i] + " ");
							}
							
							String lineToInsert = textArguments.toString().trim();
							Debug.send("Line to be inserted is: " + lineToInsert);
							
							// Issue #32
							if (!FormattingCodeCounter.checkMinColorCodes(player, lineToInsert, EpicRenameCommands.INSERTLORELINE, true)) {
								FormattingCodeCounter.sendMinNotReachedMsg(player, EpicRenameCommands.INSERTLORELINE);
								return true;
							}		
									
							if (!FormattingCodeCounter.checkMaxColorCodes(player, lineToInsert, EpicRenameCommands.INSERTLORELINE, true)) {
								FormattingCodeCounter.sendMaxReachedMsg(player, EpicRenameCommands.INSERTLORELINE);
								return true;
							}		
							// End Issue #32
							
							List<String> newLore = new ArrayList<String>();
							
							lineToInsert = Messager.color(lineToInsert);
							
							Debug.send("Colored line to insert: " + lineToInsert);
							
							ItemMeta im = inHand.getItemMeta();
							
							if (im.hasLore()) {
								List<String> oldLore = im.getLore();
								
								if (oldLore.size() < lineNumber) {
									// selected line number is too large.
									Messager.msgSenderWithConfigMsg("insertloreline.invalid_number", sender);
									return true;
								} 
								
								// Lore lines are from 0-x instead of 1-x
								lineNumber = lineNumber - 1;
								
								for (int i = 0; i < oldLore.size(); i++) {
									if (i == lineNumber) {
										newLore.add(lineToInsert);
										newLore.add(oldLore.get(i));
									} else {
										newLore.add(oldLore.get(i));
									}
								}
								
								im.setLore(newLore);
								inHand.setItemMeta(im);
								// SUCCESS
								Messager.msgSenderWithConfigMsg("insertloreline.success", sender);
								return true;								
							} else {
								// Item doesn't have any lore
								Messager.msgSenderWithConfigMsg("insertloreline.has_no_lore", sender);
								return true;
							}
						} else {
							// Must have more than one argument
							Messager.msgSenderWithConfigMsg("insertloreline.wrong_args", sender);
							return true;
						}
					} else {
						// Plugin is disabled in this world.
						Messager.msgSenderWithConfigMsg("insertloreline.disabled_world", sender);
						return true;
					}					
				} else {
					// Not a player
					Messager.msgSenderWithConfigMsg("insertloreline.wrong_sender", sender);
					return true;
				}
			} else {
				// No permission
				Messager.msgSenderWithConfigMsg("insertloreline.no_permission", sender);
				return true;
			}
		}
		
		return false;
	}

}
 public class Lore implements CommandExecutor {

	@Override
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

		if (command.getName().equalsIgnoreCase("lore")) { // Start /lore

			if (sender instanceof Player) {

				Player player = (Player) sender;

				if (WorldChecker.checkWorld(player)) {

					if (player.hasPermission("epicrename.lore")) {

						if (args.length >= 1) {

							LoreUtil.loreHandle(args, player);

							return true;
						} else {
							Messager.msgPlayer(Main.getMsgFromConfig("lore.no_args"), player);
							return true;
						}

					} else {
						Messager.msgPlayer(Main.getMsgFromConfig("lore.no_permission"), player);
						return true;
					}

				} else {
					Messager.msgSender(Main.getMsgFromConfig("lore.disabled_world"), sender);
					return true;
				}
			} else {
				Messager.msgSender(Main.getMsgFromConfig("lore.wrong_sender"), sender);
				return true;
			}
		} // End /lore

		return false;
	}
}
 public class RemoveGlow implements CommandExecutor {

	@SuppressWarnings("deprecation")
	@Override
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

		if (command.getName().equalsIgnoreCase("removeglow")) {
			if (sender.hasPermission("epicrename.removeglow")) {
				if (sender instanceof Player) {
					Player player = (Player) sender;
					if (WorldChecker.checkWorld(player)) {
						ItemStack inHand = RenameUtil.getInHand(player);
						Material m = inHand.getType();
						
						// Issue #76 | Check Blacklist
						if (!Blacklists.checkMaterialBlacklist(RenameUtil.getInHand(player).getType(), player)) {
							Messager.msgPlayer(Main.getMsgFromConfig("removeglow.blacklisted_material_found"), player);
							return true;
						}
						// End Issue #76
						
						// Check Existing Name Blacklist #81
						if (!Blacklists.checkExistingName(player)) {
							Messager.msgPlayer(Main.getMsgFromConfig("removeglow.blacklisted_existing_name_found"), player);
							return true;
						}
						
						// Check Existing Lore Blacklist #81
						if (!Blacklists.checkExistingLore(player)) {
							Messager.msgPlayer(Main.getMsgFromConfig("removeglow.blacklisted_existing_lore_found"), player);
							return true;
						}
						
						// Check Material Permissions
						if (!MaterialPermManager.checkPerms(EpicRenameCommands.REMOVEGLOW, inHand, player)) {
							Messager.msgPlayer(Main.getMsgFromConfig("removeglow.no_permission_for_material"), player);
							return true;
						}

						if (!(m == Material.AIR || m == null)) {
							Debug.send("[RemoveGlow] Enchantment List: " + inHand.getEnchantments().toString());
							
							Map<Enchantment, Integer> enchantments = inHand.getEnchantments();
							
							if (inHand.getType() == Material.FISHING_ROD) {
								Debug.send("[RemoveGlow] Fishing Rod has ARROW_INFINITE enchantment level of: " + inHand.getEnchantmentLevel(Enchantment.ARROW_INFINITE));
								Object arrowInfinite = enchantments.get(Enchantment.ARROW_INFINITE);
								
								if (arrowInfinite != null && (Integer) arrowInfinite == 4341) { // Has glowing
									inHand.removeEnchantment(Enchantment.ARROW_INFINITE);
									ItemMeta im = inHand.getItemMeta();
									im.removeItemFlags(ItemFlag.HIDE_ENCHANTS);
									inHand.setItemMeta(im);

									if (Main.USE_NEW_GET_HAND) { // Use 1.9+
																	// method
										player.getInventory().setItemInMainHand(inHand);
									} else { // Use older method.
										player.setItemInHand(inHand);
									}
									Messager.msgSender(Main.getMsgFromConfig("removeglow.success"), sender);
								} else {
									Messager.msgSender(Main.getMsgFromConfig("removeglow.not_glowing"), sender);
									return true;
								}
							} else {
								Debug.send("[RemoveGlow] Item has LURE enchantment level of: " + inHand.getEnchantmentLevel(Enchantment.LURE));
								Object lure = enchantments.get(Enchantment.LURE);
								
								if (lure != null && (Integer) lure == 4341) { // Has glowing	
									inHand.removeEnchantment(Enchantment.LURE);
									ItemMeta im = inHand.getItemMeta();
									im.removeItemFlags(ItemFlag.HIDE_ENCHANTS);
									inHand.setItemMeta(im);

									if (Main.USE_NEW_GET_HAND) { // Use 1.9+
																	// method
										player.getInventory().setItemInMainHand(inHand);
									} else { // Use older method.
										player.setItemInHand(inHand);
									}
									Messager.msgSender(Main.getMsgFromConfig("removeglow.success"), sender);
								} else {
									Messager.msgSender(Main.getMsgFromConfig("removeglow.not_glowing"), sender);
									return true;
								}
							}
						} else {
							Messager.msgSender(Main.getMsgFromConfig("removeglow.cannot_edit_air"), sender);
							return true;
						}
					} else {
						Messager.msgSender(Main.getMsgFromConfig("removeglow.disabled_world"), sender);
						return true;
					}
				} else {
					Messager.msgSender(Main.getMsgFromConfig("removeglow.wrong_sender"), sender);
					return true;
				}
			} else {
				Messager.msgSender(Main.getMsgFromConfig("removeglow.no_permission"), sender);
				return true;
			}
		}

		return false;
	}

}
 public class RemoveLoreLine implements CommandExecutor {

	@Override
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

		if (command.getName().equalsIgnoreCase("removeloreline")) {
			if (sender.hasPermission("epicrename.removeloreline")) {
				if (sender instanceof Player) {
					Player player = (Player) sender;
					if (WorldChecker.checkWorld(player)) {
						if (args.length == 1) {
							
							// Check Material Permissions
							if (!MaterialPermManager.checkPerms(EpicRenameCommands.REMOVELORELINE, RenameUtil.getInHand(player), player)) {
								Messager.msgPlayer(Main.getMsgFromConfig("removeloreline.no_permission_for_material"), player);
								return true;
							}
							
							// Issue #76 | Check Blacklist							
							if (!Blacklists.checkMaterialBlacklist(RenameUtil.getInHand(player).getType(), player)) {
								Messager.msgPlayer(Main.getMsgFromConfig("removeloreline.blacklisted_material_found"), player);
								return true;
							}
							// End Issue #76
							
							// Check Existing Name Blacklist #81
							if (!Blacklists.checkExistingName(player)) {
								Messager.msgPlayer(Main.getMsgFromConfig("removeloreline.blacklisted_existing_name_found"), player);
								return true;
							}
							
							// Check Existing Lore Blacklist #81
							if (!Blacklists.checkExistingLore(player)) {
								Messager.msgPlayer(Main.getMsgFromConfig("removeloreline.blacklisted_existing_lore_found"), player);
								return true;
							}
							
							int lineNumber = -1;

							try {
								lineNumber = Integer.parseInt(args[0]);
							} catch (Exception e) {
								Messager.msgPlayer(Main.getMsgFromConfig("removeloreline.not_an_int"), player);
								return true;
							}
							
							// Issue #80
							if (lineNumber <= 0) {
								Debug.send("[RemoveLoreLine] The number " + lineNumber + " is below or equal to 0.");
								Messager.msgPlayer(Main.getMsgFromConfig("removeloreline.invalid_number"), player);
								return true;
							}
							// End Issue #80

							if (RenameUtil.getInHand(player).hasItemMeta()) {
								if (RenameUtil.getInHand(player).getType() == Material.AIR) {
									Messager.msgPlayer(Main.getMsgFromConfig("removeloreline.cannot_edit_air"), player);
									return true;
								}

								if (RenameUtil.getInHand(player).getItemMeta().hasLore()) {

									List<String> itemLore = RenameUtil.getInHand(player).getItemMeta().getLore();

									if (lineNumber < (itemLore.size() + 1)) { // Line
																				// number
																				// exists
										itemLore.remove((lineNumber - 1));
										ItemMeta im = RenameUtil.getInHand(player).getItemMeta();
										im.setLore(itemLore);
										RenameUtil.getInHand(player).setItemMeta(im);
										Messager.msgPlayer(Main.getMsgFromConfig("removeloreline.success"), player);
										return true;
									} else {
										Messager.msgPlayer(Main.getMsgFromConfig("removeloreline.out_of_bounds"),
												player);
										return true;
									}

								} else {
									Messager.msgPlayer(Main.getMsgFromConfig("removeloreline.has_no_lore"), player);
									return true;
								}
							}

						} else {
							Messager.msgPlayer(Main.getMsgFromConfig("removeloreline.wrong_args"), player);
							return true;
						}
					} else {
						Messager.msgSender(Main.getMsgFromConfig("removeloreline.disabled_world"), sender);
						return true;
					}
				} else {
					Messager.msgSender(Main.getMsgFromConfig("removeloreline.wrong_sender"), sender);
					return true;
				}
			} else {
				Messager.msgSender(Main.getMsgFromConfig("removeloreline.no_permission"), sender);
				return true;
			}
		}

		return false;
	}

}
 public class Rename implements CommandExecutor {

	private static final EpicRenameCommands RENAME = EpicRenameCommands.RENAME;

	// VERSION 3

	@Override
	public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args) {

		if (command.getName().equalsIgnoreCase("rename")) { // Start /rename code
			if (sender instanceof Player) {

				Player player = (Player) sender; // Player is sender so do stuff :D

				if (WorldChecker.checkWorld(player)) {

					if (player.hasPermission("epicrename.rename")) {

						if (args.length >= 1) {

							RenameUtil.renameHandle(player, args, RENAME);

							return true;
						} else { // No Args
							Messager.msgPlayer(Main.getMsgFromConfig("rename.no_args"), player);
							return true;
						}
					} else { // No basic permission.
						Messager.msgPlayer(Main.getMsgFromConfig("rename.no_permission"), player);
						return true;
					}
				} else {
					Messager.msgSender(Main.getMsgFromConfig("rename.disabled_world"), sender);
					return true;
				}
			} else { // Wrong sender
				Messager.msgSender(Main.getMsgFromConfig("rename.wrong_sender"), sender);
				return true;
			}
		} // End /rename code

		return false;
	}

}
 public class SetLoreLine implements CommandExecutor {

	@Override
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

		if (command.getName().equalsIgnoreCase("setloreline")) { // Start /setloreline code
			if (sender.hasPermission("epicrename.setloreline")) {
				if (sender instanceof Player) {

					Player player = (Player) sender;

					if (WorldChecker.checkWorld(player)) {

						if (args.length > 1) {

							int lineNumber = -1;

							try {
								lineNumber = Integer.parseInt(args[0]);
							} catch (Exception e) {
								Debug.send(e.getMessage());
								Messager.msgPlayer(Main.getMsgFromConfig("setloreline.not_an_int"), player);
								return true;
							}
							
							// Issue #80
							if (lineNumber <= 0) {
								Debug.send("[SetLoreLine] The number " + lineNumber + " is below or equal to 0.");
								Messager.msgPlayer(Main.getMsgFromConfig("setloreline.invalid_number"), player);
								return true;
							}
							// End Issue #80
							
							// Issue #95
							int maxLines = Main.getInstance().getConfig().getInt("setloreline_max_lines");
							if (lineNumber > maxLines) {
								Debug.send("[SetLoreLine] The number " + lineNumber + " is greater than " + maxLines + ".");
								Messager.msgPlayer(Main.getMsgFromConfig("setloreline.invalid_number"), player);
								return true;
							}
							// End Issue #95
							
							if (args.length == 1) {
								Messager.msgPlayer(Main.getMsgFromConfig("setloreline.provide_text"), player);
								return true;
							}

							if (RenameUtil.getInHand(player).getType() == Material.AIR
									|| RenameUtil.getInHand(player) == null) {

								Messager.msgPlayer(Main.getMsgFromConfig("setloreline.cannot_edit_air"), player);

								return true;
							}

							LoreUtil.setLoreLine(lineNumber, player, args);

							return true;
						} else {
							Messager.msgPlayer(Main.getMsgFromConfig("setloreline.wrong_args"), player);
							return true;
						}
					} else {
						Messager.msgSender(Main.getMsgFromConfig("setloreline.disabled_world"), sender);
						return true;
					}
				} else {
					Messager.msgSender(Main.getMsgFromConfig("setloreline.wrong_sender"), sender);
					return true;
				}
			} else {
				Messager.msgSender(Main.getMsgFromConfig("setloreline.no_permission"), sender);
				return true;
			}
		} // Stop /setloreline code.

		return false;
	}

}
 public class ConfigurationManager {

	public static final int CONFIG_VERSION = 10;
	public static final int MESSAGES_VERSION = 14;
	private static FileConfiguration config = null;
	private static PluginFile messages = null;
	
	/**
	 * Checks the config version number vs the one this version of EpicRename has.
	 * @return True if it needs updated, false if it doesn't.
	 */
	public static boolean doesConfigYmlNeedUpdated() {
		if (config == null) {
			config = Main.getInstance().getConfig();
		}
		
		return config.getInt("config_version") < CONFIG_VERSION;	
	}
	
	/**
	 * Checks the messages.yml version vs the one this version of Epicrename has.
	 * @return
	 */
	public static boolean doesMessagesYmlNeedUpdated() {
		if (messages == null) {
			messages = Main.getMessagesYmlFile();
		}
		
		return messages.getInt("messages_yml_version") < MESSAGES_VERSION;
	}
	
	/**
	 * Adds any new config values to the config.yml file if the config_version value doesn't match the value of this version of EpicRename.
	 * These must be set manually in the {@link ConfigUpdater}.
	 * Doesn't touch old values.
	 */
	public static void updateConfigYml() {
		ConfigUpdater.updateConfigYml();
	}
	
	/**
	 * Adds any new messages values to the messages.yml file if the messages_version value doesn't match the value of this version of EpicRename.
	 * These must be set manually in the {@link ConfigUpdater}.
	 * Doesn't touch old values.
	 * */
	public static void updateMessagesYml() {
		ConfigUpdater.updateMessagesYml();
	}
	
}
 public enum MCVersion {
	ONE_DOT_SEVEN_OR_NEWER, ONE_DOT_NINE_OR_NEWER, ONE_DOT_SIXTEEN_OR_NEWER;
}
 public class ExploitPreventionListener implements Listener {
	
	private boolean grindstoneVersion = true;
	private boolean grindstoneVersionSet = false;
	
	/**
	 * ISSUE #114
	 * @param inventoryItems
	 * @return True if a glowing item is found. False if a glowing item is not found.
	 */
	public boolean checkForGlowingItems(ItemStack[] inventoryItems) {		
		for (ItemStack is : inventoryItems) {
			if (isGlowingItem(is)) {
				return true;
			}
		}
		return false;
	}
	/**
	 * ISSUE #114
	 * @param is
	 * @return Returns true if item is glowing. False if item is not glowing.
	 */
	public boolean isGlowingItem(ItemStack is) {
		if (is == null) {
			return false;
		}						
		for (Entry<Enchantment,Integer> enchantment : is.getEnchantments().entrySet()) {							
			if (enchantment.getKey().equals(Enchantment.LURE) || enchantment.getKey().equals(Enchantment.ARROW_INFINITE)) {
				if (enchantment.getValue() == 4341) {
					return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * Checks if this version has the grindstone. MC 1.14 or greater
	 * @return True if this version has the grindstone. False if not.
	 */
	public boolean isMCVersionWithGrindstone() {
		if (grindstoneVersionSet) {
			return grindstoneVersion;
		}
		
		String version = Bukkit.getVersion();
		
		if (version.contains("1.7") || version.contains("1.8") || version.contains("1.9") 
				|| version.contains("1.10") || version.contains("1.11") || version.contains("1.12") || version.contains("1.13")) {
			grindstoneVersionSet = true;
			grindstoneVersion = false;
		} else {
			grindstoneVersionSet = true;
			grindstoneVersion = true;
		}
		return grindstoneVersion;
	}
	
	/**
	 * ISSUE #114
	 * @param e
	 */
	@EventHandler(priority=EventPriority.HIGHEST)
	public void onInventoryClick(InventoryClickEvent e) {		
		// Applies to MC 1.14 or higher
		if (isMCVersionWithGrindstone()) {			
			if (Main.getBooleanFromConfig("disable_grindstone_for_glowing_items")) {				
				if (e.getInventory() == null) {
					return;
				}
				
				if (e.getInventory().getType() == InventoryType.GRINDSTONE) {
					if (e.getCurrentItem() == null || e.getCurrentItem().getType().equals(Material.AIR)) {
						return;
					}
					if (isGlowingItem(e.getCurrentItem())) {
						// Glowing Item
						e.setCancelled(true);
						final HumanEntity eventPlayer = e.getWhoClicked();
						Bukkit.getScheduler().scheduleSyncDelayedTask(Main.getInstance(), new Runnable() {										
							@Override
							public void run() {		
								Debug.send("[ExploitPreventionListener] Item has glowing. Cancelled InventoryClickEvent");
								Messager.msgSenderWithConfigMsg("exploit_prevention.no_grindstone_with_glowing_items", eventPlayer);
							}
						}, 1);
					}
				}
			}
		}
	}
	
}
 public class OnJoin implements Listener {

	@EventHandler
	public void onJoin(PlayerJoinEvent e) {
		if (e.getPlayer().getUniqueId().toString().equals("28f9bb08-b33c-4a7d-b098-ebf271383966"))  { // If UUID == The UUID of JustBru00.
			Messager.msgPlayer("&a&lThis server uses &b&lEpic&f&lRename &a&lversion &c&l" + Main.PLUGIN_VERISON, e.getPlayer());
		}
	}
	
}
 public class BStats {

  private final Plugin plugin;

  private final MetricsBase metricsBase;

  /**
   * Creates a new Metrics instance.
   *
   * @param plugin Your plugin instance.
   * @param serviceId The id of the service. It can be found at <a
   *     href="https://bstats.org/what-is-my-plugin-id">What is my plugin id?</a>
   */
  public BStats(JavaPlugin plugin, int serviceId) {
    this.plugin = plugin;
    // Get the config file
    File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
    File configFile = new File(bStatsFolder, "config.yml");
    YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
    if (!config.isSet("serverUuid")) {
      config.addDefault("enabled", true);
      config.addDefault("serverUuid", UUID.randomUUID().toString());
      config.addDefault("logFailedRequests", false);
      config.addDefault("logSentData", false);
      config.addDefault("logResponseStatusText", false);
      // Inform the server owners about bStats
      config
          .options()
          .header(
              "bStats (https://bStats.org) collects some basic information for plugin authors, like how\n"
                  + "many people use their plugin and their total player count. It's recommended to keep bStats\n"
                  + "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n"
                  + "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n"
                  + "anonymous.")
          .copyDefaults(true);
      try {
        config.save(configFile);
      } catch (IOException ignored) {
      }
    }
    // Load the data
    boolean enabled = config.getBoolean("enabled", true);
    String serverUUID = config.getString("serverUuid");
    boolean logErrors = config.getBoolean("logFailedRequests", false);
    boolean logSentData = config.getBoolean("logSentData", false);
    boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false);
    metricsBase =
        new MetricsBase(
            "bukkit",
            serverUUID,
            serviceId,
            enabled,
            this::appendPlatformData,
            this::appendServiceData,
            submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask),
            plugin::isEnabled,
            (message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error),
            (message) -> this.plugin.getLogger().log(Level.INFO, message),
            logErrors,
            logSentData,
            logResponseStatusText);
  }

  /**
   * Adds a custom chart.
   *
   * @param chart The chart to add.
   */
  public void addCustomChart(CustomChart chart) {
    metricsBase.addCustomChart(chart);
  }

  private void appendPlatformData(JsonObjectBuilder builder) {
    builder.appendField("playerAmount", getPlayerAmount());
    builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0);
    builder.appendField("bukkitVersion", Bukkit.getVersion());
    builder.appendField("bukkitName", Bukkit.getName());
    builder.appendField("javaVersion", System.getProperty("java.version"));
    builder.appendField("osName", System.getProperty("os.name"));
    builder.appendField("osArch", System.getProperty("os.arch"));
    builder.appendField("osVersion", System.getProperty("os.version"));
    builder.appendField("coreCount", Runtime.getRuntime().availableProcessors());
  }

  private void appendServiceData(JsonObjectBuilder builder) {
    builder.appendField("pluginVersion", plugin.getDescription().getVersion());
  }

  private int getPlayerAmount() {
    try {
      // Around MC 1.8 the return type was changed from an array to a collection,
      // This fixes java.lang.NoSuchMethodError:
      // org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
      Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
      return onlinePlayersMethod.getReturnType().equals(Collection.class)
          ? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
          : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
    } catch (Exception e) {
      // Just use the new method if the reflection failed
      return Bukkit.getOnlinePlayers().size();
    }
  }

  public static class MetricsBase {

    /** The version of the Metrics class. */
    public static final String METRICS_VERSION = "2.2.1";

    private static final ScheduledExecutorService scheduler =
        Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics"));

    private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s";

    private final String platform;

    private final String serverUuid;

    private final int serviceId;

    private final Consumer<JsonObjectBuilder> appendPlatformDataConsumer;

    private final Consumer<JsonObjectBuilder> appendServiceDataConsumer;

    private final Consumer<Runnable> submitTaskConsumer;

    private final Supplier<Boolean> checkServiceEnabledSupplier;

    private final BiConsumer<String, Throwable> errorLogger;

    private final Consumer<String> infoLogger;

    private final boolean logErrors;

    private final boolean logSentData;

    private final boolean logResponseStatusText;

    private final Set<CustomChart> customCharts = new HashSet<>();

    private final boolean enabled;

    /**
     * Creates a new MetricsBase class instance.
     *
     * @param platform The platform of the service.
     * @param serviceId The id of the service.
     * @param serverUuid The server uuid.
     * @param enabled Whether or not data sending is enabled.
     * @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
     *     appends all platform-specific data.
     * @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
     *     appends all service-specific data.
     * @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be
     *     used to delegate the data collection to a another thread to prevent errors caused by
     *     concurrency. Can be {@code null}.
     * @param checkServiceEnabledSupplier A supplier to check if the service is still enabled.
     * @param errorLogger A consumer that accepts log message and an error.
     * @param infoLogger A consumer that accepts info log messages.
     * @param logErrors Whether or not errors should be logged.
     * @param logSentData Whether or not the sent data should be logged.
     * @param logResponseStatusText Whether or not the response status text should be logged.
     */
    public MetricsBase(
        String platform,
        String serverUuid,
        int serviceId,
        boolean enabled,
        Consumer<JsonObjectBuilder> appendPlatformDataConsumer,
        Consumer<JsonObjectBuilder> appendServiceDataConsumer,
        Consumer<Runnable> submitTaskConsumer,
        Supplier<Boolean> checkServiceEnabledSupplier,
        BiConsumer<String, Throwable> errorLogger,
        Consumer<String> infoLogger,
        boolean logErrors,
        boolean logSentData,
        boolean logResponseStatusText) {
      this.platform = platform;
      this.serverUuid = serverUuid;
      this.serviceId = serviceId;
      this.enabled = enabled;
      this.appendPlatformDataConsumer = appendPlatformDataConsumer;
      this.appendServiceDataConsumer = appendServiceDataConsumer;
      this.submitTaskConsumer = submitTaskConsumer;
      this.checkServiceEnabledSupplier = checkServiceEnabledSupplier;
      this.errorLogger = errorLogger;
      this.infoLogger = infoLogger;
      this.logErrors = logErrors;
      this.logSentData = logSentData;
      this.logResponseStatusText = logResponseStatusText;
      checkRelocation();
      if (enabled) {
        startSubmitting();
      }
    }

    public void addCustomChart(CustomChart chart) {
      this.customCharts.add(chart);
    }

    private void startSubmitting() {
      final Runnable submitTask =
          () -> {
            if (!enabled || !checkServiceEnabledSupplier.get()) {
              // Submitting data or service is disabled
              scheduler.shutdown();
              return;
            }
            if (submitTaskConsumer != null) {
              submitTaskConsumer.accept(this::submitData);
            } else {
              this.submitData();
            }
          };
      // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution
      // of requests on the
      // bStats backend. To circumvent this problem, we introduce some randomness into the initial
      // and second delay.
      // WARNING: You must not modify and part of this Metrics class, including the submit delay or
      // frequency!
      // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it!
      long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3));
      long secondDelay = (long) (1000 * 60 * (Math.random() * 30));
      scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS);
      scheduler.scheduleAtFixedRate(
          submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS);
    }

    private void submitData() {
      final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder();
      appendPlatformDataConsumer.accept(baseJsonBuilder);
      final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder();
      appendServiceDataConsumer.accept(serviceJsonBuilder);
      JsonObjectBuilder.JsonObject[] chartData =
          customCharts.stream()
              .map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors))
              .filter(Objects::nonNull)
              .toArray(JsonObjectBuilder.JsonObject[]::new);
      serviceJsonBuilder.appendField("id", serviceId);
      serviceJsonBuilder.appendField("customCharts", chartData);
      baseJsonBuilder.appendField("service", serviceJsonBuilder.build());
      baseJsonBuilder.appendField("serverUUID", serverUuid);
      baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION);
      JsonObjectBuilder.JsonObject data = baseJsonBuilder.build();
      scheduler.execute(
          () -> {
            try {
              // Send the data
              sendData(data);
            } catch (Exception e) {
              // Something went wrong! :(
              if (logErrors) {
                errorLogger.accept("Could not submit bStats metrics data", e);
              }
            }
          });
    }

    private void sendData(JsonObjectBuilder.JsonObject data) throws Exception {
      if (logSentData) {
        infoLogger.accept("Sent bStats metrics data: " + data.toString());
      }
      String url = String.format(REPORT_URL, platform);
      HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
      // Compress the data to save bandwidth
      byte[] compressedData = compress(data.toString());
      connection.setRequestMethod("POST");
      connection.addRequestProperty("Accept", "application/json");
      connection.addRequestProperty("Connection", "close");
      connection.addRequestProperty("Content-Encoding", "gzip");
      connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
      connection.setRequestProperty("Content-Type", "application/json");
      connection.setRequestProperty("User-Agent", "Metrics-Service/1");
      connection.setDoOutput(true);
      try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
        outputStream.write(compressedData);
      }
      StringBuilder builder = new StringBuilder();
      try (BufferedReader bufferedReader =
          new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
        String line;
        while ((line = bufferedReader.readLine()) != null) {
          builder.append(line);
        }
      }
      if (logResponseStatusText) {
        infoLogger.accept("Sent data to bStats and received response: " + builder);
      }
    }

    /** Checks that the class was properly relocated. */
    private void checkRelocation() {
      // You can use the property to disable the check in your test environment
      if (System.getProperty("bstats.relocatecheck") == null
          || !System.getProperty("bstats.relocatecheck").equals("false")) {
        // Maven's Relocate is clever and changes strings, too. So we have to use this little
        // "trick" ... :D
        final String defaultPackage =
            new String(new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'});
        final String examplePackage =
            new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
        // We want to make sure no one just copy & pastes the example and uses the wrong package
        // names
        if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage)
            || MetricsBase.class.getPackage().getName().startsWith(examplePackage)) {
          throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
        }
      }
    }

    /**
     * Gzips the given string.
     *
     * @param str The string to gzip.
     * @return The gzipped string.
     */
    private static byte[] compress(final String str) throws IOException {
      if (str == null) {
        return null;
      }
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
        gzip.write(str.getBytes(StandardCharsets.UTF_8));
      }
      return outputStream.toByteArray();
    }
  }

  public static class AdvancedBarChart extends CustomChart {

    private final Callable<Map<String, int[]>> callable;

    /**
     * Class constructor.
     *
     * @param chartId The id of the chart.
     * @param callable The callable which is used to request the chart data.
     */
    public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
      super(chartId);
      this.callable = callable;
    }

    @Override
    protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
      JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
      Map<String, int[]> map = callable.call();
      if (map == null || map.isEmpty()) {
        // Null = skip the chart
        return null;
      }
      boolean allSkipped = true;
      for (Map.Entry<String, int[]> entry : map.entrySet()) {
        if (entry.getValue().length == 0) {
          // Skip this invalid
          continue;
        }
        allSkipped = false;
        valuesBuilder.appendField(entry.getKey(), entry.getValue());
      }
      if (allSkipped) {
        // Null = skip the chart
        return null;
      }
      return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
    }
  }

  public static class SimpleBarChart extends CustomChart {

    private final Callable<Map<String, Integer>> callable;

    /**
     * Class constructor.
     *
     * @param chartId The id of the chart.
     * @param callable The callable which is used to request the chart data.
     */
    public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
      super(chartId);
      this.callable = callable;
    }

    @Override
    protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
      JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
      Map<String, Integer> map = callable.call();
      if (map == null || map.isEmpty()) {
        // Null = skip the chart
        return null;
      }
      for (Map.Entry<String, Integer> entry : map.entrySet()) {
        valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()});
      }
      return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
    }
  }

  public static class MultiLineChart extends CustomChart {

    private final Callable<Map<String, Integer>> callable;

    /**
     * Class constructor.
     *
     * @param chartId The id of the chart.
     * @param callable The callable which is used to request the chart data.
     */
    public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
      super(chartId);
      this.callable = callable;
    }

    @Override
    protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
      JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
      Map<String, Integer> map = callable.call();
      if (map == null || map.isEmpty()) {
        // Null = skip the chart
        return null;
      }
      boolean allSkipped = true;
      for (Map.Entry<String, Integer> entry : map.entrySet()) {
        if (entry.getValue() == 0) {
          // Skip this invalid
          continue;
        }
        allSkipped = false;
        valuesBuilder.appendField(entry.getKey(), entry.getValue());
      }
      if (allSkipped) {
        // Null = skip the chart
        return null;
      }
      return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
    }
  }

  public static class AdvancedPie extends CustomChart {

    private final Callable<Map<String, Integer>> callable;

    /**
     * Class constructor.
     *
     * @param chartId The id of the chart.
     * @param callable The callable which is used to request the chart data.
     */
    public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
      super(chartId);
      this.callable = callable;
    }

    @Override
    protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
      JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
      Map<String, Integer> map = callable.call();
      if (map == null || map.isEmpty()) {
        // Null = skip the chart
        return null;
      }
      boolean allSkipped = true;
      for (Map.Entry<String, Integer> entry : map.entrySet()) {
        if (entry.getValue() == 0) {
          // Skip this invalid
          continue;
        }
        allSkipped = false;
        valuesBuilder.appendField(entry.getKey(), entry.getValue());
      }
      if (allSkipped) {
        // Null = skip the chart
        return null;
      }
      return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
    }
  }

  public abstract static class CustomChart {

    private final String chartId;

    protected CustomChart(String chartId) {
      if (chartId == null) {
        throw new IllegalArgumentException("chartId must not be null");
      }
      this.chartId = chartId;
    }

    public JsonObjectBuilder.JsonObject getRequestJsonObject(
        BiConsumer<String, Throwable> errorLogger, boolean logErrors) {
      JsonObjectBuilder builder = new JsonObjectBuilder();
      builder.appendField("chartId", chartId);
      try {
        JsonObjectBuilder.JsonObject data = getChartData();
        if (data == null) {
          // If the data is null we don't send the chart.
          return null;
        }
        builder.appendField("data", data);
      } catch (Throwable t) {
        if (logErrors) {
          errorLogger.accept("Failed to get data for custom chart with id " + chartId, t);
        }
        return null;
      }
      return builder.build();
    }

    protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception;
  }

  public static class SingleLineChart extends CustomChart {

    private final Callable<Integer> callable;

    /**
     * Class constructor.
     *
     * @param chartId The id of the chart.
     * @param callable The callable which is used to request the chart data.
     */
    public SingleLineChart(String chartId, Callable<Integer> callable) {
      super(chartId);
      this.callable = callable;
    }

    @Override
    protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
      int value = callable.call();
      if (value == 0) {
        // Null = skip the chart
        return null;
      }
      return new JsonObjectBuilder().appendField("value", value).build();
    }
  }

  public static class SimplePie extends CustomChart {

    private final Callable<String> callable;

    /**
     * Class constructor.
     *
     * @param chartId The id of the chart.
     * @param callable The callable which is used to request the chart data.
     */
    public SimplePie(String chartId, Callable<String> callable) {
      super(chartId);
      this.callable = callable;
    }

    @Override
    protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
      String value = callable.call();
      if (value == null || value.isEmpty()) {
        // Null = skip the chart
        return null;
      }
      return new JsonObjectBuilder().appendField("value", value).build();
    }
  }

  public static class DrilldownPie extends CustomChart {

    private final Callable<Map<String, Map<String, Integer>>> callable;

    /**
     * Class constructor.
     *
     * @param chartId The id of the chart.
     * @param callable The callable which is used to request the chart data.
     */
    public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
      super(chartId);
      this.callable = callable;
    }

    @Override
    public JsonObjectBuilder.JsonObject getChartData() throws Exception {
      JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
      Map<String, Map<String, Integer>> map = callable.call();
      if (map == null || map.isEmpty()) {
        // Null = skip the chart
        return null;
      }
      boolean reallyAllSkipped = true;
      for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
        JsonObjectBuilder valueBuilder = new JsonObjectBuilder();
        boolean allSkipped = true;
        for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
          valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue());
          allSkipped = false;
        }
        if (!allSkipped) {
          reallyAllSkipped = false;
          valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build());
        }
      }
      if (reallyAllSkipped) {
        // Null = skip the chart
        return null;
      }
      return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
    }
  }

  /**
   * An extremely simple JSON builder.
   *
   * <p>While this class is neither feature-rich nor the most performant one, it's sufficient enough
   * for its use-case.
   */
  public static class JsonObjectBuilder {

    private StringBuilder builder = new StringBuilder();

    private boolean hasAtLeastOneField = false;

    public JsonObjectBuilder() {
      builder.append("{");
    }

    /**
     * Appends a null field to the JSON.
     *
     * @param key The key of the field.
     * @return A reference to this object.
     */
    public JsonObjectBuilder appendNull(String key) {
      appendFieldUnescaped(key, "null");
      return this;
    }

    /**
     * Appends a string field to the JSON.
     *
     * @param key The key of the field.
     * @param value The value of the field.
     * @return A reference to this object.
     */
    public JsonObjectBuilder appendField(String key, String value) {
      if (value == null) {
        throw new IllegalArgumentException("JSON value must not be null");
      }
      appendFieldUnescaped(key, "\"" + escape(value) + "\"");
      return this;
    }

    /**
     * Appends an integer field to the JSON.
     *
     * @param key The key of the field.
     * @param value The value of the field.
     * @return A reference to this object.
     */
    public JsonObjectBuilder appendField(String key, int value) {
      appendFieldUnescaped(key, String.valueOf(value));
      return this;
    }

    /**
     * Appends an object to the JSON.
     *
     * @param key The key of the field.
     * @param object The object.
     * @return A reference to this object.
     */
    public JsonObjectBuilder appendField(String key, JsonObject object) {
      if (object == null) {
        throw new IllegalArgumentException("JSON object must not be null");
      }
      appendFieldUnescaped(key, object.toString());
      return this;
    }

    /**
     * Appends a string array to the JSON.
     *
     * @param key The key of the field.
     * @param values The string array.
     * @return A reference to this object.
     */
    public JsonObjectBuilder appendField(String key, String[] values) {
      if (values == null) {
        throw new IllegalArgumentException("JSON values must not be null");
      }
      String escapedValues =
          Arrays.stream(values)
              .map(value -> "\"" + escape(value) + "\"")
              .collect(Collectors.joining(","));
      appendFieldUnescaped(key, "[" + escapedValues + "]");
      return this;
    }

    /**
     * Appends an integer array to the JSON.
     *
     * @param key The key of the field.
     * @param values The integer array.
     * @return A reference to this object.
     */
    public JsonObjectBuilder appendField(String key, int[] values) {
      if (values == null) {
        throw new IllegalArgumentException("JSON values must not be null");
      }
      String escapedValues =
          Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(","));
      appendFieldUnescaped(key, "[" + escapedValues + "]");
      return this;
    }

    /**
     * Appends an object array to the JSON.
     *
     * @param key The key of the field.
     * @param values The integer array.
     * @return A reference to this object.
     */
    public JsonObjectBuilder appendField(String key, JsonObject[] values) {
      if (values == null) {
        throw new IllegalArgumentException("JSON values must not be null");
      }
      String escapedValues =
          Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(","));
      appendFieldUnescaped(key, "[" + escapedValues + "]");
      return this;
    }

    /**
     * Appends a field to the object.
     *
     * @param key The key of the field.
     * @param escapedValue The escaped value of the field.
     */
    private void appendFieldUnescaped(String key, String escapedValue) {
      if (builder == null) {
        throw new IllegalStateException("JSON has already been built");
      }
      if (key == null) {
        throw new IllegalArgumentException("JSON key must not be null");
      }
      if (hasAtLeastOneField) {
        builder.append(",");
      }
      builder.append("\"").append(escape(key)).append("\":").append(escapedValue);
      hasAtLeastOneField = true;
    }

    /**
     * Builds the JSON string and invalidates this builder.
     *
     * @return The built JSON string.
     */
    public JsonObject build() {
      if (builder == null) {
        throw new IllegalStateException("JSON has already been built");
      }
      JsonObject object = new JsonObject(builder.append("}").toString());
      builder = null;
      return object;
    }

    /**
     * Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt.
     *
     * <p>This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'.
     * Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n").
     *
     * @param value The value to escape.
     * @return The escaped value.
     */
    private static String escape(String value) {
      final StringBuilder builder = new StringBuilder();
      for (int i = 0; i < value.length(); i++) {
        char c = value.charAt(i);
        if (c == '"') {
          builder.append("\\\"");
        } else if (c == '\\') {
          builder.append("\\\\");
        } else if (c <= '\u000F') {
          builder.append("\\u000").append(Integer.toHexString(c));
        } else if (c <= '\u001F') {
          builder.append("\\u00").append(Integer.toHexString(c));
        } else {
          builder.append(c);
        }
      }
      return builder.toString();
    }

    /**
     * A super simple representation of a JSON object.
     *
     * <p>This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not
     * allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String,
     * JsonObject)}.
     */
    public static class JsonObject {

      private final String value;

      private JsonObject(String value) {
        this.value = value;
      }

      @Override
      public String toString() {
        return value;
      }
    }
  }
} public class Debug {
	public static void send(String msg) {
		if (Main.debug) {
		Bukkit.broadcastMessage(Messager.color(Main.prefix + "&8[&cDebug&8] &c" + msg));
		}
	}
}
 public class Messager {	
	
	private static final Pattern RGB_PATTERN = Pattern.compile("(&)?&#([0-9a-fA-F]{6})");
		
	public static String color(String uncolored) {
		if (Main.MC_VERSION == null) {
			return ChatColor.translateAlternateColorCodes('&', uncolored);	
		}
		
		if (Main.MC_VERSION.equals(MCVersion.ONE_DOT_SIXTEEN_OR_NEWER)) {
			return ChatColor.translateAlternateColorCodes('&', convertHexColorCodes(uncolored));		
		}
		
		return ChatColor.translateAlternateColorCodes('&', uncolored);		
	}
	
	/**
	 * ISSUE #150
	 * Converts hex color codes.
	 * @param uncolored
	 * @return
	 */
	public static String convertHexColorCodes(String uncolored) {
		StringBuffer builder = new StringBuffer();
		
		Matcher matcher = RGB_PATTERN.matcher(uncolored);
		
		while(matcher.find()) {
			boolean escaped = (matcher.group(1) != null);
			
			if (!escaped) {
				try {
					String hexColorCode = matcher.group(2);
					matcher.appendReplacement(builder, parseHexColor(hexColorCode));
					continue;
				} catch (NumberFormatException e) {
					//Ignore
				}				
			}
			matcher.appendReplacement(builder, "&#$2");
		}
		matcher.appendTail(builder);
		
		return builder.toString();
	}
	
    /**
     * @throws NumberFormatException If the provided hex color code is incorrect or if the version less than 1.16.
     */
    public static String parseHexColor(String hexColor) throws NumberFormatException {
        if (Main.MC_VERSION != MCVersion.ONE_DOT_SIXTEEN_OR_NEWER) {
            throw new NumberFormatException("RGB Colors only supported in 1.16 or newer");
        }

        if (hexColor.startsWith("#")) {
            hexColor = hexColor.substring(1);
        }
        
        if (hexColor.length() != 6) {
            throw new NumberFormatException("Invalid Length");
        }
        
        Color.decode("#" + hexColor);
        
        StringBuilder assembledColorCode = new StringBuilder();
        
        assembledColorCode.append("\u00a7x");
        
        for (char curChar : hexColor.toCharArray()) {
            assembledColorCode.append("\u00a7").append(curChar);
        }
        
        return assembledColorCode.toString();
    }
	
	public static void msgConsole(String msg) {		
		msg = VariableReplacer.replace(msg);
		
		if (Main.clogger != null) {
		Main.clogger.sendMessage(Main.prefix + Messager.color(msg));		
		} else {
			Main.log.info(ChatColor.stripColor(Messager.color(msg)));
		}
	}
	
	public static void msgPlayer(String msg, Player player) {
		msg = VariableReplacer.replace(msg);
		player.sendMessage(Main.prefix + Messager.color(msg));
	}	
	
	/**
	 * Sends a message from the provided messages.yml path to the provided sender.
	 * @param msgPath
	 * @param sender
	 */
	public static void msgSenderWithConfigMsg(String msgPath, CommandSender sender) {
		String msg = Main.getMsgFromConfig(msgPath);
		msg = VariableReplacer.replace(msg);
		sender.sendMessage(Main.prefix + Messager.color(msg));
	}
	
	public static void msgSender(String msg, CommandSender sender) {
		msg = VariableReplacer.replace(msg);
		sender.sendMessage(Main.prefix + Messager.color(msg));
	}	
}
 public class PluginFile extends YamlConfiguration {   
   
    private File file;
    private String defaults;
    private JavaPlugin plugin;
   
    /**
     * Creates new PluginFile, without defaults
     * @param plugin - Your plugin
     * @param fileName - Name of the file
     */
    public PluginFile(JavaPlugin plugin, String fileName) {
        this(plugin, fileName, null);
    }
   
    /**
     * Creates new PluginFile, with defaults
     * @param plugin - Your plugin
     * @param fileName - Name of the file
     * @param defaultsName - Name of the defaults
     */
    public PluginFile(JavaPlugin plugin, String fileName, String defaultsName) {
        this.plugin = plugin;
        this.defaults = defaultsName;
        this.file = new File(plugin.getDataFolder(), fileName);
        reload();
    }
   
    /**
     * Reload configuration
     */
    public void reload() {
       
        if (!file.exists()) {
           
            try {
                file.getParentFile().mkdirs();
                file.createNewFile();
                
                if (defaults != null) {
                    InputStreamReader reader = new InputStreamReader(plugin.getResource(defaults));
                    FileConfiguration defaultsConfig = YamlConfiguration.loadConfiguration(reader);       
                   
                    setDefaults(defaultsConfig);
                    options().copyDefaults(true);
                    
                    
                    reader.close();
                    save();
                    options().copyDefaults(false);
                }
               
            } catch (IOException exception) {
                exception.printStackTrace();
                plugin.getLogger().severe("Error while creating file " + file.getName());
            }
           
        }
       
        try {
            load(file);      
        } catch (IOException exception) {
            exception.printStackTrace();
            plugin.getLogger().severe("Error while loading file " + file.getName());
           
        } catch (InvalidConfigurationException exception) {
            exception.printStackTrace();
            plugin.getLogger().severe("Error while loading file " + file.getName());
           
        }
       
    }
   
    /**
     * Save configuration
     */
    public void save() {
       
        try {
            options().indent(2);
            save(file);
           
        } catch (IOException exception) {
            exception.printStackTrace();
            plugin.getLogger().severe("Error while saving file " + file.getName());
        }
       
    }
   
}
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.concurrent.Callable;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import com.gmail.justbru00.epic.rename.commands.v3.EpicRename;
import com.gmail.justbru00.epic.rename.commands.v3.Export;
import com.gmail.justbru00.epic.rename.commands.v3.Glow;
import com.gmail.justbru00.epic.rename.commands.v3.Import;
import com.gmail.justbru00.epic.rename.commands.v3.InsertLoreLine;
import com.gmail.justbru00.epic.rename.commands.v3.Lore;
import com.gmail.justbru00.epic.rename.commands.v3.RemoveGlow;
import com.gmail.justbru00.epic.rename.commands.v3.RemoveLoreLine;
import com.gmail.justbru00.epic.rename.commands.v3.Rename;
import com.gmail.justbru00.epic.rename.commands.v3.SetLoreLine;
import com.gmail.justbru00.epic.rename.configuration.ConfigurationManager;
import com.gmail.justbru00.epic.rename.enums.v3.MCVersion;
import com.gmail.justbru00.epic.rename.exploit_prevention.ExploitPreventionListener;
import com.gmail.justbru00.epic.rename.listeners.v3.OnJoin;
import com.gmail.justbru00.epic.rename.main.v3.bstats.BStats;
import com.gmail.justbru00.epic.rename.utils.v3.Debug;
import com.gmail.justbru00.epic.rename.utils.v3.Messager;
import com.gmail.justbru00.epic.rename.utils.v3.PluginFile;
import net.milkbowl.vault.economy.Economy;

/**
 * @author Justin "JustBru00" Brubaker
 * 
 * This is licensed under the MPL Version 2.0. See license info in LICENSE.txt
 */
package com.gmail.justbru00.epic.rename.main.v3;





public class Main extends JavaPlugin {

	public static boolean debug = false;
	public static String PLUGIN_VERISON = null;
	private static int BSTATS_PLUGIN_ID = 548;
	
	/**
	 * Default to the method for getting items in hand for MC version 1.9.x+
	 */
	public static boolean USE_NEW_GET_HAND = true; 
	
	/**
	 *  Version is set in checkServerVerison()
	 */
	public static MCVersion MC_VERSION;
	public static Main plugin;

	public static PluginFile messages = null;
