public final class CommandLoader {

    /* (non-Javadoc)
     *
     * No need to instantiate!
     */
    private CommandLoader() {}

    private static Set<? extends CommandExecutorBase> getCommands() {
        return Sets.newHashSet(
            new AddRuleExecutor(),
            new AFKExecutor(),
            new AsConsoleExecutor(),
            new BackExecutor(),
            new BanExecutor(),
            new BlacklistBase(),
            new BlockInfoExecutor(),
            new BroadcastExecutor(),
            new ButcherExecutor(),
            new CreateWorldExecutor(),
            new DeleteHomeExecutor(),
            new DeleteWarpExecutor(),
            new DeleteWorldExecutor(),
            new DirectionExecutor(),
            new EnchantExecutor(),
            new EntityInfoExecutor(),
            new EssentialCmdsExecutor(),
            new ExpExecutor(),
            new FeedExecutor(),
            new FireballExecutor(),
            new FlyExecutor(),
            new GamemodeExecutor(),
            new GCExecutor(),
            new GetPosExecutor(),
            new HatExecutor(),
            new HomeExecutor(),
            new HealExecutor(),
            new IgniteExecutor(),
            new InvSeeExecutor(),
            new ItemInfoExecutor(),
            new JumpExecutor(),
            new KickExecutor(),
            new KillExecutor(),
            new LightningExecutor(),
            new ListHomeExecutor(),
            new ListWarpExecutor(),
            new ListWorldExecutor(),
            new LoadWorldExecutor(),
            new LockWeatherExecutor(),
            new MailExecutor(),
            new MailListExecutor(),
            new MailReadExecutor(),
            new MessageExecutor(),
            new MobSpawnerExecutor(),
            new MobSpawnExecutor(),
            new MoreExecutor(),
            new MotdExecutor(),
            new MuteExecutor(),
            new NickExecutor(),
            new PardonExecutor(),
            new PlayerFreezeExecutor(),
            new PowertoolExecutor(),
            new RemoveRuleExecutor(),
            new RepairExecutor(),
            new RespondExecutor(),
            new RocketExecutor(),
            new RTPExecutor(),
            new RuleExecutor(),
            new SetHomeExecutor(),
            new SetSpawnExecutor(),
            new SetWarpExecutor(),
            new SetWorldSpawnExecutor(),
            new SkullExecutor(),
            new SlapExecutor(),
            new SocialSpyExecutor(),
            new SpawnExecutor(),
            new SpeedExecutor(),
            new SudoExecutor(),
            new TakeExecutor(),
            new TeleportExecutor(),
            new TeleportPosExecutor(),
            new TeleportWorldExecutor(),
            new ThruExecutor(),
            new TimeExecutor(),
            new TPAAcceptExecutor(),
            new TPADenyExecutor(),
            new TPAExecutor(),
            new TPAHereExecutor(),
            new TPHereExecutor(),
            new UnmuteExecutor(),
            new WarpExecutor(),
            new WeatherExecutor(),
            new WhoisExecutor(),
            new WorldsBase(),
            new JailExecutor(),
            new UnJailExecutor(),
            new VanishExecutor(),
            new KickAllExecutor(),
            new WorldInfoExecutor(),
            new SlapExecutor(),
            new RocketExecutor(),
            new ClearInventoryExecutor(),
            new TempBanExecutor(),
            new SetNameExecutor(),
            new LoreBase(),
            new HelpOpExecutor(),
            new ListExecutor(),
            new StopExecutor(),
            new GodExecutor(),
            new TPChunkExecutor(),
            new TPAllExecutor(),
            new TPAAllExecutor(),
            new SetFirstSpawnExecutor(),
            new SayExecutor(),
            new MeExecutor(),
            new KittyCannonExecutor()
        );
    }

    /**
     * Registers the EssentialCmds commands.
     */
    public static void registerCommands() {
        // TODO: Put module checks here in a stream.
        // getCommands().stream().filter(c -> c.getAssociatedModules().length == 0 && checkModules).forEach(CommandLoader::registerCommand);
        getCommands().forEach(cmd -> Sponge.getCommandManager().register(EssentialCmds.getEssentialCmds(), cmd.getSpec(), cmd.getAliases()));
    }
} public class BlacklistListener
{
	@Listener
	public void onChangeHeldItem(ChangeInventoryEvent.Held event, @Root Player player)
	{
		if (!player.hasPermission("essentialcmds.blacklist.bypass"))
		{
			for (SlotTransaction transaction : event.getTransactions())
			{
				if (Utils.getBlacklistItems().contains(transaction.getFinal().createStack().getItem().getId()))
				{
					if (Utils.areBlacklistMsgsEnabled())
						player.sendMessage(Text.of(TextColors.RED, "The item ", TextColors.GRAY, transaction.getFinal().createStack().getItem().getId(), TextColors.RED, " has been confiscated as it is blacklisted."));

					transaction.setCustom(Sponge.getRegistry().createBuilder(ItemStack.Builder.class).itemType(ItemTypes.DIRT).quantity(1).build());
				}
			}
		}
	}

	@Listener
	public void onChangeEquipment(ChangeInventoryEvent.Equipment event, @Root Player player)
	{
		if (!player.hasPermission("essentialcmds.blacklist.bypass"))
		{
			for (SlotTransaction transaction : event.getTransactions())
			{
				if (Utils.getBlacklistItems().contains(transaction.getFinal().createStack().getItem().getId()))
				{
					if (Utils.areBlacklistMsgsEnabled())
						player.sendMessage(Text.of(TextColors.RED, "The item ", TextColors.GRAY, transaction.getFinal().createStack().getItem().getId(), TextColors.RED, " has been confiscated as it is blacklisted."));

					transaction.setCustom(Sponge.getRegistry().createBuilder(ItemStack.Builder.class).itemType(ItemTypes.DIRT).quantity(1).build());
				}
			}
		}
	}

	@Listener
	public void onPlaceBlock(ChangeBlockEvent.Place event, @Root Player player)
	{
		if (!player.hasPermission("essentialcmds.blacklist.bypass"))
		{
			for (Transaction<BlockSnapshot> transaction : event.getTransactions())
			{
				if (Utils.getBlacklistItems().contains(transaction.getFinal().getState().getType().getId()))
				{
					if (Utils.areBlacklistMsgsEnabled())
						player.sendMessage(Text.of(TextColors.RED, "The item ", TextColors.GRAY, transaction.getFinal().getState().getType().getId(), TextColors.RED, " has been confiscated as it is blacklisted."));

					event.setCancelled(true);
				}
			}
		}
	}

	@Listener
	public void onBreakBlock(ChangeBlockEvent.Break event, @Root Player player)
	{
		if (!player.hasPermission("essentialcmds.blacklist.bypass"))
		{
			for (Transaction<BlockSnapshot> transaction : event.getTransactions())
			{
				if (Utils.getBlacklistItems().contains(transaction.getOriginal().getState().getType().getId()))
				{
					if (Utils.areBlacklistMsgsEnabled())
						player.sendMessage(Text.of(TextColors.RED, "The item ", TextColors.GRAY, transaction.getFinal().getState().getType().getId(), TextColors.RED, " has been confiscated as it is blacklisted."));

					event.setCancelled(true);
				}
			}
		}
	}

	@Listener
	public void onDropItem(DropItemEvent.Dispense event, @Root Player player)
	{
		if (!player.hasPermission("essentialcmds.blacklist.bypass"))
		{
			event.filterEntities(e -> {
				if (e.get(RepresentedItemData.class).isPresent())
				{
					RepresentedItemData itemData = e.get(RepresentedItemData.class).get();
					boolean blacklisted = Utils.getBlacklistItems().contains(itemData.item().get().getType().getId());

					if (blacklisted)
					{
						if (Utils.areBlacklistMsgsEnabled())
							player.sendMessage(Text.of(TextColors.RED, "The item ", TextColors.GRAY, itemData.item().get().getType().getId(), TextColors.RED, " has been confiscated as it is blacklisted."));
					}

					return !blacklisted;
				}
				return false;
			});
		}
	}

	@Listener
	public void onPickupItem(ChangeInventoryEvent.Pickup event, @Root Player player)
	{
		if (!player.hasPermission("essentialcmds.blacklist.bypass"))
		{
			for (SlotTransaction transaction : event.getTransactions())
			{
				if (Utils.getBlacklistItems().contains(transaction.getFinal().createStack().getItem().getId()))
				{
					if (Utils.areBlacklistMsgsEnabled())
						player.sendMessage(Text.of(TextColors.RED, "The item ", TextColors.GRAY, transaction.getFinal().createStack().getItem().getId(), TextColors.RED, " has been confiscated as it is blacklisted."));

					transaction.setCustom(Sponge.getRegistry().createBuilder(ItemStack.Builder.class).itemType(ItemTypes.DIRT).quantity(1).build());
				}
			}
		}
	}
} public class ChangeBlockListener
{
	@Listener
	public void onPlayerChangeBlock(ChangeBlockEvent event, @Root Player player)
	{
		if(EssentialCmds.jailedPlayers.contains(player.getUniqueId()))
		{
			player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You may not modify blocks while in jail!"));
			event.setCancelled(true);
		}
	}
} public class CommandListener
{
	@Listener
	public void onPlayerSendCommand(SendCommandEvent event, @Root Player player)
	{
		if(EssentialCmds.jailedPlayers.contains(player.getUniqueId()))
		{
			player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You may not execute commands while in jail!"));
			event.setCancelled(true);
		}
	}
} public class CommandSentListener
{
	@Listener
	public void onCommandSent(SendCommandEvent event, @Root CommandSource src)
	{
		if (src instanceof Player && Utils.isPlayerCommandLoggingEnabled())
		{
			EssentialCmds.getEssentialCmds().getLogger().info("[" + src.getName() + "]" + " executed command " + event.getCommand() + " " + event.getArguments());
		}
		else if (src instanceof ConsoleSource && Utils.isConsoleCommandLoggingEnabled())
		{
			EssentialCmds.getEssentialCmds().getLogger().info("[" + src.getName() + "]" + " executed command " + event.getCommand() + " " + event.getArguments());
		}
		else if (src instanceof CommandBlockSource && Utils.isCommandBlockCommandLoggingEnabled())
		{
			EssentialCmds.getEssentialCmds().getLogger().info("[" + src.getName() + "]" + " executed command " + event.getCommand() + " " + event.getArguments());
		}
		else if (Utils.isOtherCommandLoggingEnabled())
		{
			EssentialCmds.getEssentialCmds().getLogger().info("[" + src.getName() + "]" + " executed command " + event.getCommand() + " " + event.getArguments());
		}
	}
} public class MailListener
{
	private Game game = getEssentialCmds().getGame();

	@Listener
	public void onMailSend(MailSendEvent event)
	{
		String recipientName = event.getRecipientName();

		if (game.getServer().getPlayer(recipientName).isPresent())
		{
			Utils.addMail(event.getSender().getName(), recipientName, event.getMessage());
			game.getServer()
				.getPlayer(recipientName)
				.get()
				.sendMessage(
					Text.of(TextColors.GOLD, "[Mail]: ", TextColors.GRAY, "You have received new mail from " + event.getSender().getName()
						+ " do ", TextColors.RED, "/listmail!"));
		}
		else
		{
			Utils.addMail(event.getSender().getName(), recipientName, event.getMessage());
		}
	}
} public class MessageSinkListener
{
	@Listener(order = Order.PRE)
	public void onMessage(MessageChannelEvent.Chat event)
	{
		Optional<ClickAction.OpenUrl> clickAction = Optional.empty();

		if (event.getCause().first(Player.class).isPresent())
		{
			Player player = event.getCause().first(Player.class).get();
			String message = event.getMessage().toPlain();

			if (message.contains("http://") || message.contains("https://"))
			{
				if (player.hasPermission("essentialcmds.link.chat"))
				{
					String foundLink;

					if (message.substring(message.indexOf("http")).contains(" "))
					{
						foundLink = message.substring(message.indexOf("http"), message.indexOf(" ", message.indexOf("http")));
					}
					else
					{
						foundLink = message.substring(message.indexOf("http"));
					}

					try
					{
						clickAction = Optional.of(TextActions.openUrl(new URL(foundLink)));
					}
					catch (MalformedURLException e)
					{
						e.printStackTrace();
					}
				}
				else
				{
					player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You don't have permission to send links."));
					event.setCancelled(true);
					return;
				}
			}
		}
		else
		{
			String message = event.getMessage().toPlain();

			if (message.contains("http://") || message.contains("https://"))
			{
				String foundLink;

				if (message.substring(message.indexOf("http")).contains(" "))
				{
					foundLink = message.substring(message.indexOf("http"), message.indexOf(" ", message.indexOf("http")));
				}
				else
				{
					foundLink = message.substring(message.indexOf("http"));
				}

				try
				{
					Text newMessage = Text.builder().append(event.getMessage()).onClick(TextActions.openUrl(new URL(foundLink))).build();
					event.setMessage(newMessage);
				}
				catch (MalformedURLException e)
				{
					e.printStackTrace();
				}
			}
		}

		if (event.getCause().first(Player.class).isPresent())
		{
			Player player = event.getCause().first(Player.class).get();

			if (EssentialCmds.recentlyJoined.contains(player))
			{
				EssentialCmds.recentlyJoined.remove(player);

				if (EssentialCmds.afkList.containsKey(player.getUniqueId()))
				{
					EssentialCmds.afkList.remove(player.getUniqueId());
				}
			}
			else
			{
				AFK afk = new AFK(System.currentTimeMillis());

				if (EssentialCmds.afkList.containsKey(player.getUniqueId()))
				{
					AFK removeAFK = EssentialCmds.afkList.get(player.getUniqueId());

					if (removeAFK.getAFK())
					{
						if (removeAFK.getAFK())
						{
							if (Utils.shouldAnnounceAFK())
							{
								MessageChannel.TO_ALL.send(Text.of(TextColors.BLUE, player.getName(), TextColors.GOLD, " is no longer AFK."));
							}
						}
					}

					EssentialCmds.afkList.remove(removeAFK);
				}

				EssentialCmds.afkList.put(player.getUniqueId(), afk);
			}

			if (EssentialCmds.muteList.contains(player.getUniqueId()))
			{
				player.sendMessage(Text.of(TextColors.RED, "You have been muted."));
				event.setCancelled(true);
				return;
			}

			StringBuilder original = new StringBuilder(event.getMessage().toPlain());
			Subject subject = player.getContainingCollection().get(player.getIdentifier());

			String prefix = subject.getOption("prefix").orElse("");
			String prefix2 = subject.getOption("prefix2").orElse("");
			String prefix3 = subject.getOption("prefix3").orElse("");
			String prefix4 = subject.getOption("prefix4").orElse("");
			String prefix5 = subject.getOption("prefix5").orElse("");
			String suffix = subject.getOption("suffix").orElse("");
			TextColor nameColor = Sponge.getRegistry().getType(TextColor.class, subject.getOption("namecolor").orElse("")).orElse(TextColors.WHITE);

			String restOfOriginal = original.substring(original.indexOf(">") + 1, original.length());

			original = original.replace(0, 1, ("<" + prefix));
			String prefixInOriginal = original.substring(0, prefix.length() + 1);

			original = original.replace(original.indexOf(player.getName()) + player.getName().length(), original.indexOf(player.getName()) + player.getName().length() + 1, suffix + ">");
			String suffixInOriginal = original.substring(original.indexOf(player.getName()) + player.getName().length(), original.indexOf(restOfOriginal));

			String nick = Utils.getNick(player);
			original = original.replace(original.indexOf(player.getName()) - 1, original.indexOf(player.getName()) + player.getName().length(), nick);
			String playerName = original.substring(prefixInOriginal.length() - 1, original.indexOf(nick) + nick.length());

			prefixInOriginal = prefixInOriginal.replaceFirst("<", Utils.getFirstChatCharReplacement());

			if (suffixInOriginal.length() != 0)
				suffixInOriginal = suffixInOriginal.substring(0, suffixInOriginal.length() - 1) + Utils.getLastChatCharReplacement();

			if (!player.hasPermission("essentialcmds.color.chat.use"))
			{
				event.setMessage(Text.builder().append(TextSerializers.formattingCode('&').deserialize(prefixInOriginal)).append(TextSerializers.formattingCode('&').deserialize(prefix2)).append(TextSerializers.formattingCode('&').deserialize(prefix3)).append(TextSerializers.formattingCode('&').deserialize(prefix4)).append(TextSerializers.formattingCode('&').deserialize(prefix5)).append(Text.builder().append(TextSerializers.formattingCode('&').deserialize(playerName)).color(nameColor).build()).append(TextSerializers.formattingCode('&').deserialize(suffixInOriginal)).append(Text.of(TextColors.RESET)).append(Text.of(restOfOriginal)).onClick(clickAction.isPresent() ? clickAction.get() : event.getMessage().getClickAction().orElse(null)).style(event.getMessage().getStyle()).onHover(event.getMessage().getHoverAction().orElse(null)).build());
			}
			else
			{
				event.setMessage(Text.builder().append(TextSerializers.formattingCode('&').deserialize(prefixInOriginal)).append(TextSerializers.formattingCode('&').deserialize(prefix2)).append(TextSerializers.formattingCode('&').deserialize(prefix3)).append(TextSerializers.formattingCode('&').deserialize(prefix4)).append(TextSerializers.formattingCode('&').deserialize(prefix5)).append(Text.builder().append(TextSerializers.formattingCode('&').deserialize(playerName)).color(nameColor).build()).append(TextSerializers.formattingCode('&').deserialize(suffixInOriginal)).append(Text.of(TextColors.RESET)).append(TextSerializers.formattingCode('&').deserialize(restOfOriginal)).onClick(clickAction.isPresent() ? clickAction.get() : event.getMessage().getClickAction().orElse(null)).style(event.getMessage().getStyle()).onHover(event.getMessage().getHoverAction().orElse(null)).build());
			}
		}
	}
} public class PlayerClickListener
{
	@Listener
	public void onPlayerClick(InteractEvent event, @Root Player player)
	{
		if (EssentialCmds.frozenPlayers.contains(player.getUniqueId()))
		{
			player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot click while frozen."));
			event.setCancelled(true);
			return;
		}

		if (EssentialCmds.jailedPlayers.contains(player.getUniqueId()))
		{
			player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot click while jailed."));
			event.setCancelled(true);
			return;
		}

		Powertool foundTool = null;

		for (Powertool powertool : EssentialCmds.powertools)
		{
			if (powertool.getPlayer().equals(player))
			{
				if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent() && powertool.getItemID().equals(player.getItemInHand(HandTypes.MAIN_HAND).get().getItem().getName()))
				{
					foundTool = powertool;
					break;
				}
			}
		}

		if (foundTool != null)
		{
			Sponge.getGame().getCommandManager().process(player, foundTool.getCommand());
		}
	}

	@Listener
	public void onPlayerClickEntity(InteractEntityEvent event, @First Player player)
	{
		if (EssentialCmds.frozenPlayers.contains(player.getUniqueId()))
		{
			player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot interact with entities while frozen."));
			event.setCancelled(true);
			return;
		}
	}
} public class PlayerDisconnectListener
{
	@Listener
	public void onPlayerDisconnect(ClientConnectionEvent.Disconnect event)
	{
		Player player = event.getTargetEntity();
		String disconnectMessage = Utils.getDisconnectMessage();

		if (disconnectMessage != null && !disconnectMessage.equals(""))
		{
			if (disconnectMessage.equals("none"))
			{
				event.setMessageCancelled(true);
			}
			else
			{
				disconnectMessage = disconnectMessage.replaceAll("@p", player.getName());
				Text newMessage = TextSerializers.formattingCode('&').deserialize(disconnectMessage);
				event.setMessage(newMessage);
			}
		}

		if (EssentialCmds.afkList.containsKey(player.getUniqueId()))
		{
			EssentialCmds.afkList.remove(player.getUniqueId());
		}

		Utils.savePlayerInventory(player, player.getWorld().getUniqueId());
	}
} public class PlayerInteractListener
{
	@Listener
	public void onPlayerInteractBlock(InteractBlockEvent event, @Root Player player)
	{
		if (EssentialCmds.frozenPlayers.contains(player.getUniqueId()))
		{
			player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot interact while frozen."));
			event.setCancelled(true);
			return;
		}

		if (EssentialCmds.jailedPlayers.contains(player.getUniqueId()))
		{
			player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot interact while jailed."));
			event.setCancelled(true);
			return;
		}

		Optional<Location<World>> optLocation = event.getTargetBlock().getLocation();

		if (optLocation.isPresent() && optLocation.get().getTileEntity().isPresent())
		{
			Location<World> location = optLocation.get();
			TileEntity clickedEntity = location.getTileEntity().get();

			if (event.getTargetBlock().getState().getType().equals(BlockTypes.STANDING_SIGN) || event.getTargetBlock().getState().getType().equals(BlockTypes.WALL_SIGN))
			{
				Optional<SignData> signData = clickedEntity.getOrCreate(SignData.class);

				if (signData.isPresent())
				{
					SignData data = signData.get();
					CommandManager cmdService = Sponge.getGame().getCommandManager();
					String line0 = data.getValue(Keys.SIGN_LINES).get().get(0).toPlain();
					String line1 = data.getValue(Keys.SIGN_LINES).get().get(1).toPlain();
					String command = "warp " + line1;

					if (line0.equals("[Warp]"))
					{
						if (player.hasPermission("essentialcmds.warps.use.sign"))
						{
							cmdService.process(player, command);
						}
						else
						{
							player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You do not have permission to use Warp Signs!"));
						}
					}
				}
			}
		}
	}
} public class PlayerJoinListener
{
	@Listener
	public void onPlayerJoin(ClientConnectionEvent.Join event)
	{
		Player player = event.getTargetEntity();

		try
		{
			EssentialCmds.timings.firstJoin().startTimingIfSync();

			if (this.compareInstants(player.getJoinData().firstPlayed().get(), player.getJoinData().lastPlayed().get()))
			{
				Transform<World> spawn = Utils.getFirstSpawn();

				if (spawn != null)
				{
					if (!Objects.equals(player.getWorld().getUniqueId(), spawn.getExtent().getUniqueId()))
					{
						player.transferToWorld(spawn.getExtent().getUniqueId(), spawn.getPosition());
						player.setTransform(spawn);
					}
					else
					{
						player.setTransform(spawn);
					}
				}
				else
				{
					spawn = Utils.getSpawn();

					if (spawn != null)
					{
						if (!Objects.equals(player.getWorld().getUniqueId(), spawn.getExtent().getUniqueId()))
						{
							player.transferToWorld(spawn.getExtent().getUniqueId(), spawn.getPosition());
							player.setTransform(spawn);
						}
						else
						{
							player.setTransform(spawn);
						}
					}
				}

				Text firstJoinMsg = Utils.getFirstJoinMsg(player.getName());
				MessageChannel.TO_ALL.send(firstJoinMsg);
			}
		}
		finally
		{
			EssentialCmds.timings.firstJoin().stopTimingIfSync();
		}

		try
		{
			EssentialCmds.timings.safeLogin().startTimingIfSync();

			if (EssentialCmds.flyingPlayers.contains(player.getUniqueId()))
			{
				player.offer(Keys.CAN_FLY, true);

				if (player.getLocation().sub(0, 1, 0).getBlockType() == BlockTypes.AIR)
				{
					player.offer(Keys.IS_FLYING, true);
				}
			}
		}
		finally
		{
			EssentialCmds.timings.safeLogin().stopTimingIfSync();
		}

		player.sendMessage(Utils.getJoinMsg(player.getName()));

		try
		{
			EssentialCmds.timings.getMail().startTimingIfSync();

			List<Mail> mail = Utils.getMail(player);

			if (mail.size() > 0)
			{
				player.sendMessage(Text.of(TextColors.GOLD, "[Mail]: ", TextColors.GRAY, "While you were away, you received new mail to view it do ", TextColors.RED, "/listmail"));
			}
		}
		finally
		{
			EssentialCmds.timings.getMail().stopTimingIfSync();
		}

		try
		{
			EssentialCmds.timings.afk().startTimingIfSync();

			EssentialCmds.recentlyJoined.add(event.getTargetEntity());

			// Remove previous AFK, so player does not join as AFK.
			if (EssentialCmds.afkList.containsKey(player.getUniqueId()))
			{
				EssentialCmds.afkList.remove(player.getUniqueId());
			}
		}
		finally
		{
			EssentialCmds.timings.afk().stopTimingIfSync();
		}

		try
		{
			EssentialCmds.timings.loginMessage().startTimingIfSync();

			Text loginMessage = Utils.getLoginMessage(player.getName());

			if (loginMessage != null && !loginMessage.equals(""))
			{
				if (loginMessage.isEmpty())
				{
					event.setMessageCancelled(true);
				}
				else
				{
					event.setMessage(loginMessage);
				}
			}
		}
		finally
		{
			EssentialCmds.timings.loginMessage().stopTimingIfSync();
		}

		try
		{
			EssentialCmds.timings.saveInventory().startTimingIfSync();

			Utils.savePlayerInventory(player, player.getWorld().getUniqueId());
		}
		finally
		{
			EssentialCmds.timings.saveInventory().stopTimingIfSync();
		}
	}

	public boolean compareInstants(Instant o1, Instant o2)
	{
		int cmp = Long.compare(o1.getEpochSecond(), o2.getEpochSecond());

		if (cmp == 0)
		{
			return true;
		}

		return false;
	}
} public class PlayerMoveListener
{
	@Listener
	public void onPlayerMove(MoveEntityEvent event)
	{
		if (event.getTargetEntity() instanceof Player)
		{
			Player player = (Player) event.getTargetEntity();

			if (Utils.isTeleportCooldownEnabled() && EssentialCmds.teleportingPlayers.contains(player.getUniqueId()))
			{
				EssentialCmds.teleportingPlayers.remove(player.getUniqueId());
				player.sendMessage(Text.of(TextColors.RED, "Teleportation canceled due to movement."));
			}

			if (EssentialCmds.frozenPlayers.contains(player.getUniqueId()))
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot move while frozen."));
				event.setCancelled(true);
				return;
			}

			if (EssentialCmds.recentlyJoined.contains(player))
			{
				EssentialCmds.recentlyJoined.remove(player);

				if (EssentialCmds.afkList.containsKey(player.getUniqueId()))
				{
					EssentialCmds.afkList.remove(player.getUniqueId());
				}
			}
			else
			{
				if (EssentialCmds.afkList.containsKey(player.getUniqueId()))
				{
					AFK removeAFK = EssentialCmds.afkList.get(player.getUniqueId());

					if (removeAFK.getAFK())
					{
						if (Utils.shouldAnnounceAFK())
						{
							MessageChannel.TO_ALL.send(Text.of(TextColors.BLUE, player.getName(), TextColors.GOLD, " is no longer AFK."));
						}
					}

					EssentialCmds.afkList.remove(removeAFK);
				}

				AFK afk = new AFK(System.currentTimeMillis());
				EssentialCmds.afkList.put(player.getUniqueId(), afk);
			}

			if (!event.getFromTransform().getExtent().getUniqueId().equals(event.getToTransform().getExtent().getUniqueId()))
			{
				World oldWorld = event.getFromTransform().getExtent();
				World newWorld = event.getToTransform().getExtent();

				Utils.savePlayerInventory(player, oldWorld.getUniqueId());

				if (!Utils.doShareInventories(oldWorld.getName(), newWorld.getName()))
				{
					Utils.updatePlayerInventory(player, newWorld.getUniqueId());
				}

				player.offer(Keys.GAME_MODE, newWorld.getProperties().getGameMode());
			}
		}
	}
} public class TPAListener
{
	private EssentialCmds plugin;

	public TPAListener(EssentialCmds plugin)
	{
		this.plugin = plugin;
	}

	@Listener
	public void tpaEventHandler(TPAEvent event)
	{
		String senderName = event.getSender().getName();
		event.getRecipient().sendMessage(Text.of(TextColors.BLUE, "TPA Request From: ", TextColors.GOLD, senderName + ".", TextColors.RED, " You have 10 seconds to do /tpaccept to accept the request"));

		// Adds Invite to List
		final PendingInvitation invite = new PendingInvitation(event.getSender(), event.getRecipient());
		EssentialCmds.pendingInvites.add(invite);

		// Removes Invite after 10 Seconds
		Sponge.getScheduler().createTaskBuilder().execute(() -> {
			if (EssentialCmds.pendingInvites.contains(invite))
			{
				EssentialCmds.pendingInvites.remove(invite);
			}
		}).delay(10, TimeUnit.SECONDS).name("EssentialCmds - Remove Pending Invite").submit(plugin);
	}

	@Listener
	public void tpaAcceptEventHandler(TPAAcceptEvent event)
	{
		String senderName = event.getSender().getName();

		if (Utils.isTeleportCooldownEnabled() && !event.getRecipient().hasPermission("essentialcmds.teleport.cooldown.override"))
		{
			EssentialCmds.teleportingPlayers.add(event.getRecipient().getUniqueId());
			event.getRecipient().sendMessage(Text.of(TextColors.GREEN, senderName, TextColors.WHITE, " accepted your TPA Request. Please wait " + Utils.getTeleportCooldown() + " seconds."));

			Sponge.getScheduler().createTaskBuilder().execute(() -> {
				try
				{
					EssentialCmds.timings.teleportCooldown().startTiming();

					if (EssentialCmds.teleportingPlayers.contains(event.getRecipient().getUniqueId()))
					{
						Utils.setLastTeleportOrDeathLocation(event.getRecipient().getUniqueId(), event.getRecipient().getLocation());
						event.getRecipient().setLocation(event.getSender().getLocation());
						EssentialCmds.teleportingPlayers.remove(event.getRecipient().getUniqueId());
					}
				}
				finally
				{
					EssentialCmds.timings.teleportCooldown().stopTiming();
				}
			}).delay(Utils.getTeleportCooldown(), TimeUnit.SECONDS).name("EssentialCmds - TPA Timer").submit(plugin);
		}
		else
		{
			try
			{
				EssentialCmds.timings.teleportPlayer().startTiming();

				event.getRecipient().sendMessage(Text.of(TextColors.GREEN, senderName, TextColors.WHITE, " accepted your TPA Request."));
				Utils.setLastTeleportOrDeathLocation(event.getRecipient().getUniqueId(), event.getRecipient().getLocation());
				event.getRecipient().setLocation(event.getSender().getLocation());
			}
			finally
			{
				EssentialCmds.timings.teleportPlayer().stopTiming();
			}
		}
	}

	@Listener
	public void tpaHereAcceptEventHandler(TPAHereAcceptEvent event)
	{
		String recipientName = event.getRecipient().getName();

		if (Utils.isTeleportCooldownEnabled() && !event.getSender().hasPermission("essentialcmds.teleport.cooldown.override"))
		{
			EssentialCmds.teleportingPlayers.add(event.getSender().getUniqueId());
			event.getSender().sendMessage(Text.of(TextColors.GREEN, recipientName, TextColors.WHITE, " accepted your TPA Here Request. Please wait " + Utils.getTeleportCooldown() + " seconds."));

			Sponge.getScheduler().createTaskBuilder().execute(() -> {
				try
				{
					EssentialCmds.timings.teleportCooldown().startTiming();

					if (EssentialCmds.teleportingPlayers.contains(event.getSender().getUniqueId()))
					{
						Utils.setLastTeleportOrDeathLocation(event.getSender().getUniqueId(), event.getSender().getLocation());
						event.getSender().setLocation(event.getRecipient().getLocation());
						EssentialCmds.teleportingPlayers.remove(event.getSender().getUniqueId());
					}
				}
				finally
				{
					EssentialCmds.timings.teleportCooldown().stopTiming();
				}
			}).delay(Utils.getTeleportCooldown(), TimeUnit.SECONDS).name("EssentialCmds - TPA Timer").submit(plugin);
		}
		else
		{
			try
			{
				EssentialCmds.timings.teleportPlayer().startTiming();

				event.getSender().sendMessage(Text.of(TextColors.GREEN, recipientName, TextColors.WHITE, " accepted your TPA Here Request."));
				Utils.setLastTeleportOrDeathLocation(event.getSender().getUniqueId(), event.getSender().getLocation());
				event.getSender().setLocation(event.getRecipient().getLocation());
			}
			finally
			{
				EssentialCmds.timings.teleportPlayer().stopTiming();
			}
		}
	}

	@Listener
	public void tpaHereEventHandler(TPAHereEvent event)
	{
		String senderName = event.getSender().getName();
		event.getRecipient().sendMessage(Text.of(TextColors.BLUE, senderName, TextColors.GOLD, " has requested for you to teleport to them.", TextColors.RED, " You have 10 seconds to do /tpaccept to accept the request"));

		// Adds Invite to List
		final PendingInvitation invite = new PendingInvitation(event.getSender(), event.getRecipient());
		invite.isTPAHere = true;
		EssentialCmds.pendingInvites.add(invite);

		// Removes Invite after 10 Seconds
		Sponge.getScheduler().createTaskBuilder().execute(() -> {
			if (EssentialCmds.pendingInvites.contains(invite))
			{
				EssentialCmds.pendingInvites.remove(invite);
			}
		}).delay(10, TimeUnit.SECONDS).name("EssentialCmds - Remove Pending Invite").submit(plugin);
	}
} public class WeatherChangeListener
{
	@Listener
	public void onWeatherChanged(ChangeWorldWeatherEvent event)
	{
		if (Utils.getLockedWeatherWorlds().contains(event.getTargetWorld().getUniqueId().toString()))
		{
			event.setCancelled(true);
		}
	}
} public class HomeConfig implements Configurable
{
	private static HomeConfig config = new HomeConfig();

	private HomeConfig()
	{
		;
	}

	public static HomeConfig getConfig()
	{
		return config;
	}

	private Path configFile = Paths.get(EssentialCmds.getEssentialCmds().getConfigDir().resolve("data") + "/homes.conf");
	private ConfigurationLoader<CommentedConfigurationNode> configLoader = HoconConfigurationLoader.builder().setPath(configFile).build();
	private CommentedConfigurationNode configNode;

	@Override
	public void setup()
	{
		if (!Files.exists(configFile))
		{
			try
			{
				Files.createFile(configFile);
				load();
				populate();
				save();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		else
		{
			load();
		}
	}

	@Override
	public void load()
	{
		try
		{
			configNode = configLoader.load();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void save()
	{
		try
		{
			configLoader.save(configNode);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void populate()
	{
		get().getNode("home").setComment("Contains all homes.");
	}

	@Override
	public CommentedConfigurationNode get()
	{
		return configNode;
	}
} public class InventoryConfig implements Configurable
{
	private static InventoryConfig config = new InventoryConfig();

	private InventoryConfig()
	{
		;
	}

	public static InventoryConfig getConfig()
	{
		return config;
	}

	private Path configFile = Paths.get(EssentialCmds.getEssentialCmds().getConfigDir().resolve("data") + "/inventory.conf");
	private ConfigurationLoader<CommentedConfigurationNode> configLoader = HoconConfigurationLoader.builder().setPath(configFile).build();
	private CommentedConfigurationNode configNode;

	@Override
	public void setup()
	{
		if (!Files.exists(configFile))
		{
			try
			{
				Files.createFile(configFile);
				load();
				populate();
				save();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		else
		{
			load();
		}
	}

	@Override
	public void load()
	{
		try
		{
			configNode = configLoader.load();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void save()
	{
		try
		{
			configLoader.save(configNode);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void populate()
	{
		get().getNode("inventory").setComment("Contains all inventories.");
	}

	@Override
	public CommentedConfigurationNode get()
	{
		return configNode;
	}
} public class JailConfig implements Configurable
{
	private static JailConfig config = new JailConfig();

	private JailConfig()
	{
		;
	}

	public static JailConfig getConfig()
	{
		return config;
	}

	private Path configFile = Paths.get(EssentialCmds.getEssentialCmds().getConfigDir().resolve("data") + "/jails.conf");
	private ConfigurationLoader<CommentedConfigurationNode> configLoader = HoconConfigurationLoader.builder().setPath(configFile).build();
	private CommentedConfigurationNode configNode;

	@Override
	public void setup()
	{
		if (!Files.exists(configFile))
		{
			try
			{
				Files.createFile(configFile);
				load();
				populate();
				save();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		else
		{
			load();
		}
	}

	@Override
	public void load()
	{
		try
		{
			configNode = configLoader.load();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void save()
	{
		try
		{
			configLoader.save(configNode);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void populate()
	{
		get().getNode("jails").setComment("Contains all jails.");
	}

	@Override
	public CommentedConfigurationNode get()
	{
		return configNode;
	}
} public class RulesConfig implements Configurable
{
	private static RulesConfig config = new RulesConfig();

	private RulesConfig()
	{
		;
	}

	public static RulesConfig getConfig()
	{
		return config;
	}

	private Path configFile = Paths.get(EssentialCmds.getEssentialCmds().getConfigDir().resolve("data") + "/rules.conf");
	private ConfigurationLoader<CommentedConfigurationNode> configLoader = HoconConfigurationLoader.builder().setPath(configFile).build();
	private CommentedConfigurationNode configNode;

	@Override
	public void setup()
	{
		if (!Files.exists(configFile))
		{
			try
			{
				Files.createFile(configFile);
				load();
				populate();
				save();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		else
		{
			load();
		}
	}

	@Override
	public void load()
	{
		try
		{
			configNode = configLoader.load();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void save()
	{
		try
		{
			configLoader.save(configNode);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void populate()
	{
		get().getNode("rules").setComment("Contains all rules.");
	}

	@Override
	public CommentedConfigurationNode get()
	{
		return configNode;
	}
} public class SpawnConfig implements Configurable
{
	private static SpawnConfig config = new SpawnConfig();

	private SpawnConfig()
	{
		;
	}

	public static SpawnConfig getConfig()
	{
		return config;
	}

	private Path configFile = Paths.get(EssentialCmds.getEssentialCmds().getConfigDir().resolve("data") + "/spawn.conf");
	private ConfigurationLoader<CommentedConfigurationNode> configLoader = HoconConfigurationLoader.builder().setPath(configFile).build();
	private CommentedConfigurationNode configNode;

	@Override
	public void setup()
	{
		if (!Files.exists(configFile))
		{
			try
			{
				Files.createFile(configFile);
				load();
				populate();
				save();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		else
		{
			load();
		}
	}

	@Override
	public void load()
	{
		try
		{
			configNode = configLoader.load();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void save()
	{
		try
		{
			configLoader.save(configNode);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void populate()
	{
		get().getNode("spawn").setComment("Contains spawn data.");
	}

	@Override
	public CommentedConfigurationNode get()
	{
		return configNode;
	}
} public class WorldConfig implements Configurable
{
	private static WorldConfig config = new WorldConfig();

	private WorldConfig()
	{
		;
	}

	public static WorldConfig getConfig()
	{
		return config;
	}

	private Path configFile = Paths.get(EssentialCmds.getEssentialCmds().getConfigDir().resolve("data") + "/world.conf");
	private ConfigurationLoader<CommentedConfigurationNode> configLoader = HoconConfigurationLoader.builder().setPath(configFile).build();
	private CommentedConfigurationNode configNode;

	@Override
	public void setup()
	{
		if (!Files.exists(configFile))
		{
			try
			{
				Files.createFile(configFile);
				load();
				populate();
				save();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		else
		{
			load();
		}
	}

	@Override
	public void load()
	{
		try
		{
			configNode = configLoader.load();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void save()
	{
		try
		{
			configLoader.save(configNode);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void populate()
	{
		get().getNode("world", "inventory", "separate").setValue(false).setComment("Toggles separate inventories between worlds.");
		get().getNode("world", "inventory", "groups").setComment("Contains all world inventory groups.");
		get().getNode("world", "inventory", "groups", "example").setValue("world, DIM1, DIM-1").setComment("Example world inventory group.");
		get().getNode("world", "weather", "locked").setComment("Worlds listed here, will not change weather.");
	}

	@Override
	public CommentedConfigurationNode get()
	{
		return configNode;
	}
} public class AFK
{
	public long lastMovementTime;
	public boolean AFK = false;
	public boolean messaged = false;
	public int foodLevel;

	public AFK(long lastMovementTime)
	{
		this.lastMovementTime = lastMovementTime;
	}

	public int getFood()
	{
		return this.foodLevel;
	}

	public void setFood(int foodLevel)
	{
		this.foodLevel = foodLevel;
	}

	public boolean getAFK()
	{
		return AFK;
	}

	public void setAFK(boolean AFK)
	{
		this.AFK = AFK;
	}

	public boolean getMessaged()
	{
		return messaged;
	}

	public void setMessaged(boolean messaged)
	{
		this.messaged = messaged;
	}

	public long getLastMovementTime()
	{
		return lastMovementTime;
	}
} public class Message
{
	private Player sender;
	private Player recipient;
	private String message;

	public Message(Player sender, Player recipient, String message)
	{
		this.sender = sender;
		this.recipient = recipient;
		this.message = message;
	}

	public Player getSender()
	{
		return sender;
	}

	public Player getRecipient()
	{
		return recipient;
	}

	public String getMessage()
	{
		return message;
	}
} public class PendingInvitation
{
	public boolean isTPAHere = false;
	public Player sender;
	public Player recipient;

	public PendingInvitation(Player sender, Player recipient)
	{
		this.sender = sender;
		this.recipient = recipient;
	}

	public Player getSender()
	{
		return sender;
	}

	public Player getRecipient()
	{
		return recipient;
	}
} public class Timings
{
	private final EssentialCmds plugin;
	private final Timing firstJoin, safeLogin, mail, saveInventory, loginMessage, afk, teleportPlayer, teleportCooldown;

	public Timings(EssentialCmds plugin)
	{
		this.plugin = plugin;
		this.firstJoin = timing("firstJoin");
		this.safeLogin = timing("safeLogin");
		this.mail = timing("getMail");
		this.saveInventory = timing("saveInventory");
		this.loginMessage = timing("loginMessage");
		this.teleportPlayer = timing("teleportPlayer");
		this.teleportCooldown = timing("teleportCooldown");
		this.afk = timing("afk");
	}

	private Timing timing(String key)
	{
		return co.aikar.timings.Timings.of(this.plugin, key);
	}

	public Timing firstJoin()
	{
		return firstJoin;
	}

	public Timing safeLogin()
	{
		return safeLogin;
	}

	public Timing getMail()
	{
		return mail;
	}

	public Timing saveInventory()
	{
		return saveInventory;
	}

	public Timing loginMessage()
	{
		return loginMessage;
	}

	public Timing afk()
	{
		return afk;
	}

	public Timing teleportPlayer()
	{
		return teleportPlayer;
	}

	public Timing teleportCooldown()
	{
		return teleportCooldown;
	}
} public class Utils
{
	private static Gson gson = new GsonBuilder().create();

	private static Game game = Sponge.getGame();
	private static Configurable mainConfig = Config.getConfig();
	private static Configurable warpsConfig = WarpConfig.getConfig();
	private static Configurable homesConfig = HomeConfig.getConfig();
	private static Configurable rulesConfig = RulesConfig.getConfig();
	private static Configurable jailsConfig = JailConfig.getConfig();
	private static Configurable spawnConfig = SpawnConfig.getConfig();
	private static Configurable inventoryConfig = InventoryConfig.getConfig();
	private static Configurable worldConfig = WorldConfig.getConfig();
	private static ConfigManager configManager = new ConfigManager();

	private static List<Mail> mail = Lists.newArrayList();

	public static void setSQLPort(String value)
	{
		Configs.setValue(mainConfig, new Object[] { "mysql", "port" }, value);
	}

	public static void addMute(UUID playerUUID)
	{
		Connection c;
		Statement stmt;

		try
		{
			if (Utils.useMySQL())
			{
				SqlService sql = game.getServiceManager().provide(SqlService.class).get();
				String host = getMySQLHost();
				String port = getMySQLPort();
				String username = getMySQLUsername();
				String password = getMySQLPassword();
				String database = getMySQLDatabase();

				DataSource datasource = sql.getDataSource("jdbc:mysql://" + host + ":" + port + "/" + database + "?user=" + username + "&password=" + password);

				String executeString = "CREATE TABLE IF NOT EXISTS MUTES " + "(UUID VARCHAR(256) PRIMARY KEY NOT NULL)";
				execute(executeString, datasource);

				executeString = "INSERT INTO MUTES (UUID) " + "VALUES ('" + playerUUID.toString() + "');";
				execute(executeString, datasource);
			}
			else
			{
				try
				{
					Class.forName("org.sqlite.JDBC");
				}
				catch (ClassNotFoundException exception)
				{
					EssentialCmds.getEssentialCmds().getLogger().error("[EssentialCmds]: You do not have ANY database software installed! Mutes will not work or be saved until this is fixed.");
				}

				c = DriverManager.getConnection("jdbc:sqlite:Mutes.db");
				stmt = c.createStatement();

				String sql = "CREATE TABLE IF NOT EXISTS MUTES " + "(UUID VARCHAR(256) PRIMARY KEY NOT NULL)";
				stmt.executeUpdate(sql);

				sql = "INSERT INTO MUTES (UUID) " + "VALUES ('" + playerUUID.toString() + "');";
				stmt.executeUpdate(sql);

				stmt.close();
				c.close();
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	public static void removeMute(UUID playerUUID)
	{
		Connection c;
		Statement stmt;

		try
		{
			if (Utils.useMySQL())
			{
				SqlService sql = game.getServiceManager().provide(SqlService.class).get();
				String host = getMySQLHost();
				String port = getMySQLPort();
				String username = getMySQLUsername();
				String password = getMySQLPassword();
				String database = getMySQLDatabase();

				DataSource datasource = sql.getDataSource("jdbc:mysql://" + host + ":" + port + "/" + database + "?user=" + username + "&password=" + password);

				String executeString = "CREATE TABLE IF NOT EXISTS MUTES " + "(UUID CHAR(36) PRIMARY KEY NOT NULL)";
				execute(executeString, datasource);

				executeString = "DELETE FROM MUTES WHERE UUID='" + playerUUID.toString() + "';";
				execute(executeString, datasource);
			}
			else
			{
				try
				{
					Class.forName("org.sqlite.JDBC");
				}
				catch (ClassNotFoundException exception)
				{
					EssentialCmds.getEssentialCmds().getLogger().error("You do not have ANY database software installed! Mutes will not work or be saved until this is fixed.");
				}

				c = DriverManager.getConnection("jdbc:sqlite:Mutes.db");
				stmt = c.createStatement();

				String sql = "CREATE TABLE IF NOT EXISTS MUTES " + "(UUID VARCHAR(256) PRIMARY KEY NOT NULL)";
				stmt.executeUpdate(sql);

				sql = "DELETE FROM MUTES WHERE UUID='" + playerUUID.toString() + "';";
				stmt.executeUpdate(sql);

				stmt.close();
				c.close();
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	public static void startAFKService()
	{
		Task.Builder taskBuilder = Sponge.getScheduler().createTaskBuilder();

		taskBuilder.execute(() -> {
			for (Player player : Sponge.getServer().getOnlinePlayers())
			{
				if (EssentialCmds.afkList.containsKey(player.getUniqueId()))
				{
					AFK afk = EssentialCmds.afkList.get(player.getUniqueId());

					if (((System.currentTimeMillis() - afk.lastMovementTime) > Utils.getAFK()) && !afk.getMessaged())
					{
						if (Utils.shouldAnnounceAFK())
						{
							MessageChannel.TO_ALL.send(Text.of(TextColors.BLUE, player.getName(), TextColors.GOLD, " is now AFK."));
						}

						if (player.get(Keys.FOOD_LEVEL).isPresent())
						{
							afk.setFood(player.get(Keys.FOOD_LEVEL).get());
						}

						afk.setMessaged(true);
						afk.setAFK(true);
					}

					if (afk.getAFK())
					{
						Optional<FoodData> data = player.get(FoodData.class);

						if (data.isPresent())
						{
							FoodData food = data.get();

							if (food.foodLevel().get() < afk.getFood())
							{
								Value<Integer> foodLevel = food.foodLevel().set(afk.getFood());
								food.set(foodLevel);
								player.offer(food);
							}
						}

						if (!(player.hasPermission("essentialcmds.afk.kick.false")) && Utils.getAFKKick() && afk.getLastMovementTime() >= Utils.getAFKKickTimer())
						{
							player.kick(Text.of(TextColors.GOLD, "Kicked for being AFK too long."));
							EssentialCmds.afkList.remove(player.getUniqueId());
						}
					}
				}
			}
		}).interval(1, TimeUnit.SECONDS).name("EssentialCmds - AFK").submit(game.getPluginManager().getPlugin(PluginInfo.ID).get().getInstance().get());
	}

	public static String getMySQLPort()
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("mysql", "port");
		if (configManager.getString(node).isPresent())
			return node.getString();
		setSQLPort("8080");
		return "8080";
	}

	public static String getMySQLDatabase()
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("mysql", "database");
		if (configManager.getString(node).isPresent())
			return node.getString();
		setSQLDatabase("Mutes");
		return "Mutes";
	}

	public static boolean areBlacklistMsgsEnabled()
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("blacklist", "messages");

		if (node.getValue() != null)
			return node.getBoolean();
		else
			Configs.setValue(mainConfig, node.getPath(), true);

		return true;
	}

	public static boolean isTeleportCooldownEnabled()
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("teleport", "cooldown", "enabled");

		if (node.getValue() != null)
			return node.getBoolean();
		else
			Utils.setTeleportCooldownEnabled(false);

		return false;
	}

	public static void setTeleportCooldownEnabled(boolean value)
	{
		Configs.setValue(mainConfig, new Object[] { "teleport", "cooldown", "enabled" }, value);
	}

	public static long getTeleportCooldown()
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("teleport", "cooldown", "timer");
		if (configManager.getLong(node).isPresent())
			return node.getLong();
		setTeleportCooldown(10);
		return 10l;
	}

	public static void setTeleportCooldown(long value)
	{
		Configs.setValue(mainConfig, new Object[] { "teleport", "cooldown", "timer" }, value);
	}

	public static String getMySQLPassword()
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("mysql", "password");
		if (configManager.getString(node).isPresent())
			return node.getString();
		setSQLPass("cat");
		return "cat";
	}

	public static String getMySQLUsername()
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("mysql", "username");
		if (configManager.getString(node).isPresent())
			return node.getString();
		setSQLUsername("HassanS6000");
		return "HassanS6000";
	}

	public static String getMySQLHost()
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("mysql", "host");
		if (configManager.getString(node).isPresent())
			return node.getString();
		setSQLHost("");
		return "";
	}

	public static boolean useMySQL()
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("mysql", "use");
		if (configManager.getBoolean(node).isPresent())
			return node.getBoolean();
		setUseMySQL(false);
		return false;
	}

	public static void setUseMySQL(boolean value)
	{
		Configs.setValue(mainConfig, new Object[] { "mysql", "use" }, value);
	}

	public static Text getLoginMessage(String playerName)
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("message", "login");
		String message;

		if (configManager.getString(node).isPresent())
		{
			message = node.getString();
		}
		else
		{
			setLoginMessage("");
			message = "";
		}

		if (message.isEmpty())
		{
			return Text.EMPTY;
		}

		message = message.replaceAll("@p", playerName);

		if ((message.contains("https://")) || (message.contains("http://")))
		{
			return Utils.getURL(message);
		}

		return TextSerializers.FORMATTING_CODE.deserialize(message);
	}

	public static void setLoginMessage(String value)
	{
		Configs.setValue(mainConfig, new Object[] { "message", "login" }, value);
	}

	public static String getDisconnectMessage()
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("message", "disconnect");
		if (configManager.getString(node).isPresent())
			return node.getString();
		setDisconnectMessage("");
		return "";
	}

	public static void setDisconnectMessage(String value)
	{
		Configs.setValue(mainConfig, new Object[] { "message", "disconnect" }, value);
	}

	public static Text getFirstJoinMsg(String playerName)
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("message", "firstjoin");
		String message;

		if (configManager.getString(node).isPresent())
		{
			message = node.getString();
		}
		else
		{
			setFirstJoinMsg("&4Welcome &a@p &4to the server!");
			message = "&4Welcome &a@p &4to the server!";
		}

		message = message.replaceAll("@p", playerName);

		if ((message.contains("https://")) || (message.contains("http://")))
		{
			return Utils.getURL(message);
		}

		return TextSerializers.FORMATTING_CODE.deserialize(message);
	}

	public static Text getURL(String message)
	{
		List<String> extractedUrls = extractUrls(message);
		for (String url : extractedUrls)
		{
			List<String> extractmb = extractmbefore(message);
			for (String preurl : extractmb)
			{
				List<String> extractma = extractmafter(message);
				for (String posturl : extractma)
				{
					try
					{
						String preurlline = preurl.replaceAll("(((https?|ftp|gopher|telnet|file):((//)|(\\\\))+[\\w\\d:#@%/;$()~_?\\+-=\\\\\\.&]*).*?)(?=\\w).*", "");
						String posturlline = posturl.replaceAll("((https?|ftp|gopher|telnet|file|Unsure|http):((//)|(\\\\))+[\\w\\d:#@%/;$()~_?\\+-=\\\\\\.&]*)", "");
						Text preMessage = TextSerializers.FORMATTING_CODE.deserialize(preurlline);
						Text postMessage = TextSerializers.FORMATTING_CODE.deserialize(posturlline);
						Text linkmessage = Text.builder(url).onClick(TextActions.openUrl(new URL(url))).build();
						Text newmessage = Text.builder().append(preMessage).append(linkmessage).append(postMessage).build();
						return newmessage;
					}
					catch (MalformedURLException e)
					{
						e.printStackTrace();
					}
				}
			}
		}

		return TextSerializers.FORMATTING_CODE.deserialize(message);
	}

	public static List<String> extractUrls(String text)
	{
		List<String> containedUrls = new ArrayList<String>();
		String urlRegex = "((https?|ftp|gopher|telnet|file):((//)|(\\\\))+[\\w\\d:#@%/;$()~_?\\+-=\\\\\\.&]*)";
		Pattern pattern = Pattern.compile(urlRegex, Pattern.CASE_INSENSITIVE);
		Matcher urlMatcher = pattern.matcher(text);
		while (urlMatcher.find())
		{
			containedUrls.add(text.substring(urlMatcher.start(0), urlMatcher.end(0)));
		}
		return containedUrls;
	}

	public static List<String> extractmbefore(String pretext)
	{
		List<String> preurlmess = new ArrayList<String>();
		String preurlRegex = ".*((https?|ftp|gopher|telnet|file):((//)|(\\\\))+[\\w\\d:#@%/;$()~_?\\+-=\\\\\\.&]*)(.*)";
		Pattern prepattern = Pattern.compile(preurlRegex, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
		Matcher preMessage = prepattern.matcher(pretext);
		while (preMessage.find())
		{
			preurlmess.add(pretext.substring(preMessage.start(0), preMessage.end(0)));
		}
		return preurlmess;
	}

	public static List<String> extractmafter(String posttext)
	{
		List<String> posturlmess = new ArrayList<String>();
		String posturlRegex = "(((https?|ftp|gopher|telnet|file):((//)|(\\\\))+[\\w\\d:#@%/;$()~_?\\+-=\\\\\\.&]).*)";
		Pattern postpattern = Pattern.compile(posturlRegex, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
		Matcher postMessage = postpattern.matcher(posttext);
		while (postMessage.find())
		{
			posturlmess.add(posttext.substring(postMessage.start(0), postMessage.end(0)));
		}
		return posturlmess;
	}

	public static void setFirstJoinMsg(String value)
	{
		Configs.setValue(mainConfig, new Object[] { "message", "firstjoin" }, value);
	}

	public static String getNick(Player player)
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("nick", player.getUniqueId().toString());
		if (configManager.getString(node).isPresent())
			return node.getString();
		else
			return player.getName();
	}

	public static void setNick(String value, UUID playerUuid)
	{
		Configs.setValue(mainConfig, new Object[] { "nick", playerUuid.toString() }, value);
	}

	public static boolean unsafeEnchanmentsEnabled()
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("unsafeenchantments", "enabled");
		if (configManager.getBoolean(node).isPresent())
			return node.getBoolean();
		setUnsafeEnchanmentsEnabled(false);
		return false;
	}

	public static void setUnsafeEnchanmentsEnabled(boolean value)
	{
		Configs.setValue(mainConfig, new Object[] { "unsafeenchantments", "enabled" }, value);
	}

	public static void setSQLDatabase(String value)
	{
		Configs.setValue(mainConfig, new Object[] { "mysql", "database" }, value);
	}

	public static void setSQLHost(String value)
	{
		Configs.setValue(mainConfig, new Object[] { "mysql", "host" }, value);
	}

	public static void setSQLPass(String value)
	{
		Configs.setValue(mainConfig, new Object[] { "mysql", "password" }, value);
	}

	public static void setSQLUsername(String value)
	{
		Configs.setValue(mainConfig, new Object[] { "mysql", "username" }, value);
	}

	public static void execute(String execute, DataSource datasource)
	{
		try
		{
			Connection connection = datasource.getConnection();
			Statement statement = connection.createStatement();
			statement.execute(execute);
			statement.close();
			connection.close();

		}
		catch (SQLException e)
		{
			e.printStackTrace();
		}
	}

	public static void readMutes()
	{
		try
		{
			if (Utils.useMySQL())
			{
				SqlService sql = game.getServiceManager().provide(SqlService.class).get();
				String host = getMySQLHost();
				String port = getMySQLPort();
				String username = getMySQLUsername();
				String password = getMySQLPassword();
				String database = getMySQLDatabase();

				DataSource datasource = sql.getDataSource("jdbc:mysql://" + host + ":" + port + "/" + database + "?user=" + username + "&password=" + password);

				String executeString = "CREATE TABLE IF NOT EXISTS MUTES " + "(UUID VARCHAR(256) PRIMARY KEY NOT NULL)";
				execute(executeString, datasource);

				DatabaseMetaData metadata = datasource.getConnection().getMetaData();
				ResultSet rs = metadata.getTables(null, null, "Mutes", null);
				Set<UUID> muteList = Sets.newHashSet();

				while (rs.next())
				{
					String uuid = rs.getString("uuid");
					muteList.add(UUID.fromString(uuid));
				}

				EssentialCmds.muteList = muteList;
				rs.close();
			}
			else
			{
				Connection c;
				Statement stmt;

				try
				{
					Class.forName("org.sqlite.JDBC");
				}
				catch (ClassNotFoundException exception)
				{
					EssentialCmds.getEssentialCmds().getLogger().error("You do not have ANY database software installed! Mutes will not work or be saved until this is fixed.");
				}

				c = DriverManager.getConnection("jdbc:sqlite:Mutes.db");
				c.setAutoCommit(false);
				stmt = c.createStatement();

				String sql = "CREATE TABLE IF NOT EXISTS MUTES " + "(UUID VARCHAR(256) PRIMARY KEY NOT NULL)";
				stmt.executeUpdate(sql);

				ResultSet rs = stmt.executeQuery("SELECT * FROM MUTES;");
				Set<UUID> muteList = Sets.newHashSet();

				while (rs.next())
				{
					String uuid = rs.getString("uuid");
					muteList.add(UUID.fromString(uuid));
				}

				EssentialCmds.muteList = muteList;

				rs.close();
				stmt.close();
				c.close();
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	public static void addRule(String rule)
	{
		CommentedConfigurationNode node = Configs.getConfig(rulesConfig).getNode("rules", "rules");
		String formattedItem = (rule + ",");

		if (configManager.getString(node).isPresent())
		{
			String items = node.getString();

			if (!items.contains(formattedItem))
				Configs.setValue(rulesConfig, node.getPath(), items + formattedItem);
			return;
		}

		Configs.setValue(rulesConfig, node.getPath(), formattedItem);
	}

	public static void removeRule(int ruleIndex)
	{
		CommentedConfigurationNode node = Configs.getConfig(rulesConfig).getNode("rules", "rules");
		String ruleToRemove = getRules().get(ruleIndex);

		if (configManager.getString(node).isPresent() && ruleToRemove != null)
		{
			String items = node.getString();
			Configs.setValue(rulesConfig, node.getPath(), items.replace(ruleToRemove + ",", ""));
		}
	}

	public static boolean removeJail(int number)
	{
		if (Configs.getConfig(jailsConfig).getNode(new Object[] { "jails", String.valueOf(number), "X" }).getValue() != null)
		{
			Configs.removeChild(jailsConfig, new Object[] { "jails" }, String.valueOf(number));
			return true;
		}

		return false;
	}

	public static void teleportPlayerToJail(Player player, int number)
	{
		UUID worldUuid = UUID.fromString(Configs.getConfig(jailsConfig).getNode("jails", String.valueOf(number), "world").getString());
		double x = Configs.getConfig(jailsConfig).getNode("jails", String.valueOf(number), "X").getDouble();
		double y = Configs.getConfig(jailsConfig).getNode("jails", String.valueOf(number), "Y").getDouble();
		double z = Configs.getConfig(jailsConfig).getNode("jails", String.valueOf(number), "Z").getDouble();
		World world = Sponge.getServer().getWorld(worldUuid).orElse(null);

		if (world != null)
		{
			Location<World> location = new Location<World>(world, x, y, z);

			if (player.getWorld().getUniqueId().equals(worldUuid))
			{
				player.setLocation(location);
			}
			else
			{
				player.transferToWorld(world.getUniqueId(), location.getPosition());
			}
		}
	}

	public static int getNumberOfJails()
	{
		return Configs.getConfig(jailsConfig).getNode("jails").getChildrenMap().values().size();
	}

	public static void addJail(Location<World> location)
	{
		int number = Utils.getNumberOfJails() + 1;
		Configs.getConfig(jailsConfig).getNode("jails", String.valueOf(number), "world").setValue(location.getExtent().getUniqueId().toString());
		Configs.getConfig(jailsConfig).getNode("jails", String.valueOf(number), "X").setValue(location.getX());
		Configs.getConfig(jailsConfig).getNode("jails", String.valueOf(number), "Y").setValue(location.getY());
		Configs.getConfig(jailsConfig).getNode("jails", String.valueOf(number), "Z").setValue(location.getZ());
		Configs.saveConfig(jailsConfig);
	}

	public static void setHome(UUID uuid, Transform<World> transform, String worldName, String homeName)
	{
		Configs.getConfig(homesConfig).getNode("home", "users", uuid.toString(), homeName, "world").setValue(worldName);
		Configs.getConfig(homesConfig).getNode("home", "users", uuid.toString(), homeName, "X").setValue(transform.getLocation().getX());
		Configs.getConfig(homesConfig).getNode("home", "users", uuid.toString(), homeName, "Y").setValue(transform.getLocation().getY());
		Configs.getConfig(homesConfig).getNode("home", "users", uuid.toString(), homeName, "Z").setValue(transform.getLocation().getZ());
		Configs.getConfig(homesConfig).getNode("home", "users", uuid.toString(), homeName, "transform", "pitch").setValue(transform.getRotation().getX());
		Configs.getConfig(homesConfig).getNode("home", "users", uuid.toString(), homeName, "transform", "yaw").setValue(transform.getRotation().getY());
		Configs.getConfig(homesConfig).getNode("home", "users", uuid.toString(), homeName, "transform", "roll").setValue(transform.getRotation().getZ());

		Configs.saveConfig(homesConfig);
	}

	public static void addBlacklistItem(String itemId)
	{
		CommentedConfigurationNode node = Configs.getConfig(mainConfig).getNode("essentialcmds", "items", "blacklist");
		String formattedItem = (itemId + ",");

		if (configManager.getString(node).isPresent())
		{
			String items = node.getString();
			Configs.setValue(mainConfig, node.getPath(), items + formattedItem);
			return;
		}

		Configs.setValue(mainConfig, node.getPath(), formattedItem);
	}

	public static void removeBlacklistItem(String itemId)
	{
		ConfigurationNode blacklistNode = Configs.getConfig(mainConfig).getNode("essentialcmds", "items", "blacklist");

		String blacklist = blacklistNode.getString();
		String newValue = blacklist.replace(itemId + ",", "");

		Configs.setValue(mainConfig, blacklistNode.getPath(), newValue);
	}

	public static void readMail()
	{
		String json = null;

		if (new File("Mail.json").exists())
		{
			try
			{
				json = readFile("Mail.json", StandardCharsets.UTF_8);
			}
			catch (Exception e)
			{
				EssentialCmds.getEssentialCmds().getLogger().error("Error while reading Mail:");
				e.printStackTrace();
			}

			if (json != null && json.length() > 0)
			{
				Utils.mail = new ArrayList<>(Arrays.asList(gson.fromJson(json, Mail[].class)));
			}
		}
	}

	static String readFile(String path, Charset encoding) throws IOException
	{
		byte[] encoded = Files.readAllBytes(Paths.get(path));
		return new String(encoded, encoding);
	}

	public static void addMail(String senderName, String recipientName, String message)
	{
		Utils.mail.add(new Mail(recipientName, senderName, message));
	}

	public static void removeMail(Mail mail)
	{
		Utils.mail.removeIf(m -> {
			if (m.getRecipientName().equals(mail.getRecipientName()) && m.getSenderName().equals(mail.getSenderName()) && m.getMessage().equals(mail.getMessage()))
			{
				return true;
			}

			return false;
		});
	}

	public static void setWarp(Transform<World> transform, String warpName)
	{
		Configs.getConfig(warpsConfig).getNode("warps", warpName, "world").setValue(transform.getExtent().getUniqueId().toString());
		Configs.getConfig(warpsConfig).getNode("warps", warpName, "X").setValue(transform.getLocation().getX());
		Configs.getConfig(warpsConfig).getNode("warps", warpName, "Y").setValue(transform.getLocation().getY());
		Configs.getConfig(warpsConfig).getNode("warps", warpName, "Z").setValue(transform.getLocation().getZ());
		Configs.getConfig(warpsConfig).getNode("warps", warpName, "transform", "pitch").setValue(transform.getRotation().getX());
		Configs.getConfig(warpsConfig).getNode("warps", warpName, "transform", "yaw").setValue(transform.getRotation().getY());
		Configs.getConfig(warpsConfig).getNode("warps", warpName, "transform", "roll").setValue(transform.getRotation().getZ());

		Configs.saveConfig(warpsConfig);
	}

	public static Text getJoinMsg(String name)
	{
		ConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode((Object[]) ("message.join").split("\\."));
		String message;

		if (valueNode.getValue() != null)
		{
			message = valueNode.getString();
		}
		else
		{
			Utils.setJoinMsg("&4Welcome");
			message = "&4Welcome";
		}

		if ((message.contains("https://")) || (message.contains("http://")))
		{
			return Utils.getURL(message);
		}

		return TextSerializers.FORMATTING_CODE.deserialize(message.replaceAll("@p", name));
	}

	public static String getFirstChatCharReplacement()
	{
		ConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode((Object[]) ("chat.firstcharacter").split("\\."));
		if (valueNode.getValue() != null)
		{
			return valueNode.getString();
		}
		else
		{
			Utils.setFirstChatCharReplacement("<");
			return "<";
		}
	}

	public static String getLastChatCharReplacement()
	{
		ConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode((Object[]) ("chat.lastcharacter").split("\\."));
		if (valueNode.getValue() != null)
		{
			return valueNode.getString();
		}
		else
		{
			Utils.setLastChatCharReplacement(">");
			return ">";
		}
	}

	public static double getAFK()
	{
		ConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode((Object[]) ("afk.timer").split("\\."));

		if (valueNode.getValue() != null)
		{
			return valueNode.getDouble();
		}
		else
		{
			Utils.setAFK(300000);
			return 300000;
		}
	}

	public static boolean getAFKKick()
	{
		ConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode((Object[]) ("afk.kick.use").split("\\."));

		if (valueNode.getValue() != null)
		{
			return valueNode.getBoolean();
		}
		else
		{
			Utils.setAFKKick(false);
			return false;
		}
	}

	public static boolean shouldAnnounceAFK()
	{
		ConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode((Object[]) ("afk.announce").split("\\."));

		if (valueNode.getValue() != null)
		{
			return valueNode.getBoolean();
		}
		else
		{
			Configs.setValue(mainConfig, valueNode.getPath(), true);
			return true;
		}
	}

	public static double getAFKKickTimer()
	{
		ConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode((Object[]) ("afk.kick.timer").split("\\."));

		if (valueNode.getValue() != null)
		{
			return valueNode.getDouble();
		}
		else
		{
			Utils.setAFKKickTimer(30000);
			ConfigurationNode valNode = Configs.getConfig(mainConfig).getNode((Object[]) ("afk.timer").split("\\."));
			return valNode.getDouble();
		}
	}

	public static void setSpawn(Transform<World> transform, String worldName)
	{
		Configs.getConfig(spawnConfig).getNode("spawn", "X").setValue(transform.getLocation().getX());
		Configs.getConfig(spawnConfig).getNode("spawn", "Y").setValue(transform.getLocation().getY());
		Configs.getConfig(spawnConfig).getNode("spawn", "Z").setValue(transform.getLocation().getZ());
		Configs.getConfig(spawnConfig).getNode("spawn", "world").setValue(worldName);
		Configs.getConfig(spawnConfig).getNode("spawn", "transform", "pitch").setValue(transform.getRotation().getX());
		Configs.getConfig(spawnConfig).getNode("spawn", "transform", "yaw").setValue(transform.getRotation().getY());
		Configs.getConfig(spawnConfig).getNode("spawn", "transform", "roll").setValue(transform.getRotation().getZ());

		Configs.saveConfig(spawnConfig);
	}

	public static void setFirstSpawn(Transform<World> transform, String worldName)
	{
		Configs.getConfig(spawnConfig).getNode("first-spawn", "X").setValue(transform.getLocation().getX());
		Configs.getConfig(spawnConfig).getNode("first-spawn", "Y").setValue(transform.getLocation().getY());
		Configs.getConfig(spawnConfig).getNode("first-spawn", "Z").setValue(transform.getLocation().getZ());
		Configs.getConfig(spawnConfig).getNode("first-spawn", "world").setValue(worldName);
		Configs.getConfig(spawnConfig).getNode("first-spawn", "transform", "pitch").setValue(transform.getRotation().getX());
		Configs.getConfig(spawnConfig).getNode("first-spawn", "transform", "yaw").setValue(transform.getRotation().getY());
		Configs.getConfig(spawnConfig).getNode("first-spawn", "transform", "roll").setValue(transform.getRotation().getZ());

		Configs.saveConfig(spawnConfig);
	}

	public static void setJoinMsg(String msg)
	{
		Configs.getConfig(mainConfig).getNode("message", "join").setValue(msg);
		Configs.saveConfig(mainConfig);
	}

	public static void setFirstChatCharReplacement(String replacement)
	{
		Configs.getConfig(mainConfig).getNode("chat", "firstcharacter").setValue(replacement);
		Configs.saveConfig(mainConfig);
	}

	public static void setLastChatCharReplacement(String replacement)
	{
		Configs.getConfig(mainConfig).getNode("chat", "lastcharacter").setValue(replacement);
		Configs.saveConfig(mainConfig);
	}

	public static void setAFK(double length)
	{
		Configs.getConfig(mainConfig).getNode("afk", "timer").setValue(length);
		Configs.saveConfig(mainConfig);
	}

	public static void setAFKKick(boolean val)
	{
		Configs.getConfig(mainConfig).getNode("afk", "kick", "use").setValue(val);
		Configs.saveConfig(mainConfig);
	}

	public static void setAFKKickTimer(double length)
	{
		Configs.getConfig(mainConfig).getNode("afk", "kick", "timer").setValue(length);
		Configs.saveConfig(mainConfig);
	}

	public static void setLastTeleportOrDeathLocation(UUID uuid, Location<World> playerLocation)
	{
		if (EssentialCmds.backLocations.containsKey(uuid))
		{
			EssentialCmds.backLocations.remove(uuid);
		}

		EssentialCmds.backLocations.put(uuid, playerLocation);
	}

	public static Location<World> getLastTeleportOrDeathLocation(Player player)
	{
		if (EssentialCmds.backLocations.containsKey(player.getUniqueId()))
		{
			return EssentialCmds.backLocations.get(player.getUniqueId());
		}

		return null;
	}

	public static ArrayList<String> getRules()
	{
		ConfigurationNode valueNode = Configs.getConfig(rulesConfig).getNode((Object[]) ("rules.rules").split("\\."));

		if (valueNode.getValue() == null)
			return Lists.newArrayList();

		String list = valueNode.getString();
		ArrayList<String> rulesList = Lists.newArrayList();
		boolean finished = false;
		int endIndex = list.indexOf(",");

		if (endIndex != -1)
		{
			String substring = list.substring(0, endIndex);
			rulesList.add(substring);

			while (!finished)
			{
				int startIndex = endIndex;
				endIndex = list.indexOf(",", startIndex + 1);

				if (endIndex != -1)
				{
					String substrings = list.substring(startIndex + 1, endIndex);
					rulesList.add(substrings);
				}
				else
				{
					finished = true;
				}
			}
		}

		return rulesList;
	}

	public static List<String> getBlacklistItems()
	{
		ConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode("essentialcmds", "items", "blacklist");

		if (valueNode.getValue() == null || valueNode.getString().length() == 0)
		{
			return Lists.newArrayList();
		}

		String list = valueNode.getString();

		List<String> itemList = Lists.newArrayList();
		boolean finished = false;
		int endIndex = list.indexOf(",");

		if (endIndex != -1)
		{
			String substring = list.substring(0, endIndex);
			itemList.add(substring);

			while (!finished)
			{
				int startIndex = endIndex;
				endIndex = list.indexOf(",", startIndex + 1);

				if (endIndex != -1)
				{
					String substrings = list.substring(startIndex + 1, endIndex);
					itemList.add(substrings);
				}
				else
				{
					finished = true;
				}
			}
		}

		return itemList;
	}

	public static Set<Object> getHomes(UUID uuid)
	{
		return Configs.getConfig(homesConfig).getNode("home", "users", uuid.toString()).getChildrenMap().keySet();
	}

	public static Set<Object> getWarps()
	{
		return Configs.getConfig(warpsConfig).getNode("warps").getChildrenMap().keySet();
	}

	public static Transform<World> getHome(UUID uuid, String homeName)
	{
		CommentedConfigurationNode homeNode = Configs.getConfig(homesConfig).getNode("home", "users", uuid.toString(), getConfigHomeName(uuid, homeName));
		String worldName = homeNode.getNode("world").getString();
		World world = Sponge.getServer().getWorld(worldName).orElse(null);
		double x = homeNode.getNode("X").getDouble();
		double y = homeNode.getNode("Y").getDouble();
		double z = homeNode.getNode("Z").getDouble();

		if (homeNode.getNode("transform", "pitch").getValue() == null)
		{
			if (world != null)
				return new Transform<>(new Location<>(world, x, y, z));
			else
				return null;
		}
		else
		{
			double pitch = homeNode.getNode("transform", "pitch").getDouble();
			double yaw = homeNode.getNode("transform", "yaw").getDouble();
			double roll = homeNode.getNode("transform", "roll").getDouble();

			if (world != null)
				return new Transform<>(world, new Vector3d(x, y, z), new Vector3d(pitch, yaw, roll));
			else
				return null;
		}
	}

	public static Transform<World> getWarp(String warpName)
	{
		CommentedConfigurationNode warpNode = Configs.getConfig(warpsConfig).getNode("warps", getConfigWarpName(warpName));
		UUID worldUuid = UUID.fromString(warpNode.getNode("world").getString());
		World world = Sponge.getServer().getWorld(worldUuid).orElse(null);

		double x = warpNode.getNode("X").getDouble();
		double y = warpNode.getNode("Y").getDouble();
		double z = warpNode.getNode("Z").getDouble();

		if (warpNode.getNode("transform", "pitch").getValue() == null)
		{
			if (world != null)
				return new Transform<>(new Location<>(world, x, y, z));
			else
				return null;
		}
		else
		{
			double pitch = warpNode.getNode("transform", "pitch").getDouble();
			double yaw = warpNode.getNode("transform", "yaw").getDouble();
			double roll = warpNode.getNode("transform", "roll").getDouble();

			if (world != null)
				return new Transform<>(world, new Vector3d(x, y, z), new Vector3d(pitch, yaw, roll));
			else
				return null;
		}
	}

	public static String getConfigHomeName(UUID uuid, String homeName)
	{
		Set<Object> homes = getHomes(uuid);
		for (Object home : homes)
		{
			if (home.toString().equalsIgnoreCase(homeName))
				return home.toString();
		}
		return null;
	}

	public static String getConfigWarpName(String warpName)
	{
		Set<Object> warps = getWarps();
		for (Object warp : warps)
		{
			if (warp.toString().equalsIgnoreCase(warpName))
				return warp.toString();
		}
		return null;
	}

	public static boolean isHomeInConfig(UUID playerUuid, String homeName)
	{
		return getConfigHomeName(playerUuid, homeName) != null;
	}

	public static boolean isWarpInConfig(String warpName)
	{
		return getConfigWarpName(warpName) != null;
	}

	public static boolean isSpawnInConfig()
	{
		return Configs.getConfig(spawnConfig).getNode("spawn", "X").getValue() != null;
	}

	public static Transform<World> getSpawn()
	{
		String worldName = Configs.getConfig(spawnConfig).getNode("spawn", "world").getString();
		World world = Sponge.getServer().getWorld(worldName).orElse(null);
		double x = Configs.getConfig(spawnConfig).getNode("spawn", "X").getDouble();
		double y = Configs.getConfig(spawnConfig).getNode("spawn", "Y").getDouble();
		double z = Configs.getConfig(spawnConfig).getNode("spawn", "Z").getDouble();

		if (Configs.getConfig(spawnConfig).getNode("spawn", "transform", "pitch").getValue() == null)
		{
			if (world != null)
				return new Transform<>(new Location<>(world, x, y, z));
			else
				return null;
		}
		else
		{
			double pitch = Configs.getConfig(spawnConfig).getNode("spawn", "transform", "pitch").getDouble();
			double yaw = Configs.getConfig(spawnConfig).getNode("spawn", "transform", "yaw").getDouble();
			double roll = Configs.getConfig(spawnConfig).getNode("spawn", "transform", "roll").getDouble();

			if (world != null)
				return new Transform<>(world, new Vector3d(x, y, z), new Vector3d(pitch, yaw, roll));
			else
				return null;
		}
	}

	public static Transform<World> getFirstSpawn()
	{
		String worldName = Configs.getConfig(spawnConfig).getNode("first-spawn", "world").getString();
		World world = Sponge.getServer().getWorld(worldName).orElse(null);
		double x = Configs.getConfig(spawnConfig).getNode("first-spawn", "X").getDouble();
		double y = Configs.getConfig(spawnConfig).getNode("first-spawn", "Y").getDouble();
		double z = Configs.getConfig(spawnConfig).getNode("first-spawn", "Z").getDouble();

		if (Configs.getConfig(spawnConfig).getNode("spawn", "transform", "pitch").getValue() == null)
		{
			if (world != null)
				return new Transform<>(new Location<>(world, x, y, z));
			else
				return null;
		}
		else
		{
			double pitch = Configs.getConfig(spawnConfig).getNode("spawn", "transform", "pitch").getDouble();
			double yaw = Configs.getConfig(spawnConfig).getNode("spawn", "transform", "yaw").getDouble();
			double roll = Configs.getConfig(spawnConfig).getNode("spawn", "transform", "roll").getDouble();

			if (world != null)
				return new Transform<>(world, new Vector3d(x, y, z), new Vector3d(pitch, yaw, roll));
			else
				return null;
		}
	}

	public static boolean isLastDeathInConfig(Player player)
	{
		return Utils.getLastTeleportOrDeathLocation(player) != null;
	}

	public static void deleteHome(Player player, String homeName)
	{
		Configs.removeChild(homesConfig, new Object[] { "home", "users", player.getUniqueId().toString() }, getConfigHomeName(player.getUniqueId(), homeName));
	}

	public static void deleteWarp(String warpName)
	{
		Configs.removeChild(warpsConfig, new Object[] { "warps" }, getConfigWarpName(warpName));
	}

	public static void savePlayerInventory(Player player, UUID worldUuid)
	{
		if (!Utils.areSeparateWorldInventoriesEnabled())
			return;

		String worldName = Sponge.getServer().getWorld(worldUuid).get().getName();
		Set<UUID> worlds = Sets.newHashSet();

		for (World world : Sponge.getServer().getWorlds())
		{
			if (Utils.doShareInventories(worldName, world.getName()))
			{
				if (!worlds.contains(world.getUniqueId()))
					worlds.add(world.getUniqueId());
			}
		}

		if (!worlds.contains(worldUuid))
			worlds.add(worldUuid);

		for (UUID uuid : worlds)
		{
			List<Inventory> slots = Lists.newArrayList(player.getInventory().slots());

			for (int i = 0; i < slots.size(); i++)
			{
				Optional<ItemStack> stack;

				if (i < 36)
					stack = slots.get(i).peek();
				else if (i == 36)
					stack = player.getHelmet();
				else if (i == 37)
					stack = player.getChestplate();
				else if (i == 38)
					stack = player.getLeggings();
				else if (i == 39)
					stack = player.getBoots();
				else
					stack = Optional.empty();

				if (stack.isPresent())
				{
					Object object = ItemStackSerializer.serializeItemStack(stack.get());
					Configs.setValue(inventoryConfig, new Object[] { "inventory", player.getUniqueId().toString(), uuid.toString(), "slots", String.valueOf(i) }, object);
				}
				else if (Configs.getConfig(inventoryConfig).getNode("inventory", player.getUniqueId().toString(), uuid.toString(), "slots").getChildrenMap().containsKey(String.valueOf(i)))
				{
					Configs.removeChild(inventoryConfig, new Object[] { "inventory", player.getUniqueId().toString(), uuid.toString(), "slots" }, String.valueOf(i));
				}
			}
		}
	}

	public static PlayerInventory getPlayerInventory(UUID playerUuid, UUID worldUuid)
	{
		ConfigurationNode parentNode = Configs.getConfig(inventoryConfig).getNode("inventory", playerUuid.toString(), worldUuid.toString(), "slots");
		List<ItemStack> slots = Lists.newArrayList();

		for (int slot = 0; slot < parentNode.getChildrenMap().keySet().size(); slot++)
		{
			if (parentNode.getChildrenMap().keySet().contains(String.valueOf(slot)))
			{
				ConfigurationNode inventoryNode = Configs.getConfig(inventoryConfig).getNode("inventory", playerUuid.toString(), worldUuid.toString(), "slots", String.valueOf(slot));
				Optional<ItemStack> optionalStack = ItemStackSerializer.readItemStack(inventoryNode, slot);
				slots.add(optionalStack.orElse(ItemStack.builder().itemType(ItemTypes.NONE).build()));
			}
			else
			{
				slots.add(ItemStack.builder().itemType(ItemTypes.NONE).build());
			}
		}

		return new PlayerInventory(playerUuid, worldUuid, slots);
	}

	public static void updatePlayerInventory(Player player, UUID worldUuid)
	{
		if (!Utils.areSeparateWorldInventoriesEnabled())
			return;

		PlayerInventory playerInventory = Utils.getPlayerInventory(player.getUniqueId(), worldUuid);
		player.getInventory().clear();

		if (playerInventory != null)
		{
			final Iterator<ItemStack> slots = playerInventory.getSlots().iterator();
			player.getInventory().slots().forEach(c -> {
				if (slots.hasNext())
					c.set(slots.next());
			});
		}
	}

	public static boolean areSeparateWorldInventoriesEnabled()
	{
		return Configs.getConfig(worldConfig).getNode("world", "inventory", "separate").getBoolean();
	}

	public static boolean doShareInventories(String world1, String world2)
	{
		CommentedConfigurationNode valueNode = Configs.getConfig(worldConfig).getNode("world", "inventory", "groups");

		for (Object group : valueNode.getChildrenMap().keySet())
		{
			String worldString = Configs.getConfig(worldConfig).getNode("world", "inventory", "groups", String.valueOf(group)).getString();
			List<String> worlds = Arrays.asList(worldString.split("\\s*,\\s*"));

			if (worlds.contains(world1) && worlds.contains(world2))
				return true;
		}

		return false;
	}

	public static List<String> getLockedWeatherWorlds()
	{
		CommentedConfigurationNode valueNode = Configs.getConfig(worldConfig).getNode("world", "weather", "locked");

		if (valueNode.getValue() != null)
		{
			List<String> worlds = Arrays.asList(valueNode.getString().split("\\s*,\\s*"));
			return worlds;
		}
		else
		{
			return Lists.newArrayList();
		}
	}

	public static void addLockedWeatherWorld(UUID worldUuid)
	{
		CommentedConfigurationNode valueNode = Configs.getConfig(worldConfig).getNode("world", "weather", "locked");

		if (valueNode.getValue() != null)
		{
			Configs.setValue(worldConfig, valueNode.getPath(), valueNode.getString() + ", " + worldUuid.toString());
		}
		else
		{
			Configs.setValue(worldConfig, valueNode.getPath(), worldUuid.toString());
		}
	}

	public static void removeLockedWeatherWorld(UUID worldUuid)
	{
		CommentedConfigurationNode valueNode = Configs.getConfig(worldConfig).getNode("world", "weather", "locked");

		if (valueNode.getValue() != null)
		{
			if (valueNode.getString().contains(worldUuid.toString() + ", "))
			{
				Configs.setValue(worldConfig, valueNode.getPath(), valueNode.getString().replace(worldUuid.toString() + ", ", ""));
			}
			else
			{
				Configs.setValue(worldConfig, valueNode.getPath(), valueNode.getString().replace(worldUuid.toString(), ""));
			}
		}
	}

	public static boolean isPlayerCommandLoggingEnabled()
	{
		CommentedConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode("log", "command", "player");

		if (valueNode.getValue() != null)
		{
			return valueNode.getBoolean();
		}
		else
		{
			Configs.setValue(mainConfig, valueNode.getPath(), true);
			return true;
		}
	}

	public static boolean isConsoleCommandLoggingEnabled()
	{
		CommentedConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode("log", "command", "console");

		if (valueNode.getValue() != null)
		{
			return valueNode.getBoolean();
		}
		else
		{
			Configs.setValue(mainConfig, valueNode.getPath(), true);
			return true;
		}
	}

	public static boolean isCommandBlockCommandLoggingEnabled()
	{
		CommentedConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode("log", "command", "command-block");

		if (valueNode.getValue() != null)
		{
			return valueNode.getBoolean();
		}
		else
		{
			Configs.setValue(mainConfig, valueNode.getPath(), true);
			return true;
		}
	}

	public static boolean isOtherCommandLoggingEnabled()
	{
		CommentedConfigurationNode valueNode = Configs.getConfig(mainConfig).getNode("log", "command", "other");

		if (valueNode.getValue() != null)
		{
			return valueNode.getBoolean();
		}
		else
		{
			Configs.setValue(mainConfig, valueNode.getPath(), true);
			return true;
		}
	}

	public static List<Mail> getMail(Player player)
	{
		return Utils.mail.stream().filter(m -> m.getRecipientName().equals(player.getName())).collect(Collectors.toList());
	}

	public static void saveMail()
	{
		try
		{
			String json = gson.toJson(Utils.mail);

			// Assume default encoding.
			FileWriter fileWriter = new FileWriter("Mail.json");

			// Always wrap FileWriter in BufferedWriter.
			BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);

			bufferedWriter.write(json);
			bufferedWriter.flush();

			// Always close files.
			bufferedWriter.close();
		}
		catch (Exception ex)
		{
			EssentialCmds.getEssentialCmds().getLogger().error("Could not save JSON file!");
		}
	}
}
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import io.github.hsyyid.essentialcmds.internal.CommandLoader;
import io.github.hsyyid.essentialcmds.listeners.BlacklistListener;
import io.github.hsyyid.essentialcmds.listeners.ChangeBlockListener;
import io.github.hsyyid.essentialcmds.listeners.CommandListener;
import io.github.hsyyid.essentialcmds.listeners.CommandSentListener;
import io.github.hsyyid.essentialcmds.listeners.MailListener;
import io.github.hsyyid.essentialcmds.listeners.MessageSinkListener;
import io.github.hsyyid.essentialcmds.listeners.PlayerClickListener;
import io.github.hsyyid.essentialcmds.listeners.PlayerDamageListener;
import io.github.hsyyid.essentialcmds.listeners.PlayerDeathListener;
import io.github.hsyyid.essentialcmds.listeners.PlayerDisconnectListener;
import io.github.hsyyid.essentialcmds.listeners.PlayerInteractListener;
import io.github.hsyyid.essentialcmds.listeners.PlayerJoinListener;
import io.github.hsyyid.essentialcmds.listeners.PlayerMoveListener;
import io.github.hsyyid.essentialcmds.listeners.SignChangeListener;
import io.github.hsyyid.essentialcmds.listeners.TPAListener;
import io.github.hsyyid.essentialcmds.listeners.WeatherChangeListener;
import io.github.hsyyid.essentialcmds.managers.config.Config;
import io.github.hsyyid.essentialcmds.managers.config.HomeConfig;
import io.github.hsyyid.essentialcmds.managers.config.InventoryConfig;
import io.github.hsyyid.essentialcmds.managers.config.JailConfig;
import io.github.hsyyid.essentialcmds.managers.config.RulesConfig;
import io.github.hsyyid.essentialcmds.managers.config.SpawnConfig;
import io.github.hsyyid.essentialcmds.managers.config.WarpConfig;
import io.github.hsyyid.essentialcmds.managers.config.WorldConfig;
import io.github.hsyyid.essentialcmds.utils.AFK;
import io.github.hsyyid.essentialcmds.utils.Message;
import io.github.hsyyid.essentialcmds.utils.PendingInvitation;
import io.github.hsyyid.essentialcmds.utils.Powertool;
import io.github.hsyyid.essentialcmds.utils.Timings;
import io.github.hsyyid.essentialcmds.utils.Utils;
import me.flibio.updatifier.Updatifier;
import org.slf4j.Logger;
import org.spongepowered.api.Game;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.game.state.GameInitializationEvent;
import org.spongepowered.api.event.game.state.GamePreInitializationEvent;
import org.spongepowered.api.event.game.state.GameStoppingEvent;
import org.spongepowered.api.plugin.Dependency;
import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/*
 * This file is part of EssentialCmds, licensed under the MIT License (MIT).
 *
 * Copyright (c) 2015 - 2015 HassanS6000
 * Copyright (c) contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package io.github.hsyyid.essentialcmds;



@Updatifier(repoName = "EssentialCmds", repoOwner = "hsyyid", version = "v" + PluginInfo.VERSION)
@Plugin(id = PluginInfo.ID, name = PluginInfo.NAME, version = PluginInfo.INFORMATIVE_VERSION, description = PluginInfo.DESCRIPTION, dependencies = @Dependency(id = "Updatifier", version = "1.0", optional = true) )
public class EssentialCmds
{
	protected EssentialCmds()
	{
		;
	}

	private static EssentialCmds essentialCmds;

	public static Timings timings;

	public static HashMap<UUID, AFK> afkList = new HashMap<>();
	public static List<PendingInvitation> pendingInvites = Lists.newArrayList();
	public static List<Player> recentlyJoined = Lists.newArrayList();
	public static List<Powertool> powertools = Lists.newArrayList();
	public static Set<UUID> socialSpies = Sets.newHashSet();
	public static List<Message> recentlyMessaged = Lists.newArrayList();
	public static Set<UUID> muteList = Sets.newHashSet();
	public static Set<UUID> frozenPlayers = Sets.newHashSet();
	public static Set<UUID> jailedPlayers = Sets.newHashSet();
	public static Set<UUID> teleportingPlayers = Sets.newHashSet();
	public static Set<UUID> godPlayers = Sets.newHashSet();
	public static Set<UUID> flyingPlayers = Sets.newHashSet();
	public static Map<UUID, Location<World>> backLocations = Maps.newHashMap();

	@Inject
	private Logger logger;

	public Logger getLogger()
	{
		return logger;
	}

	@Inject
	@ConfigDir(sharedRoot = false)
	private Path configDir;

	public static EssentialCmds getEssentialCmds()
	{
		return essentialCmds;
	}

	@Listener
	public void onPreInitialization(GamePreInitializationEvent event)
	{
		essentialCmds = this;
		timings = new Timings(this);

		// Create Config Directory for EssentialCmds
		if (!Files.exists(configDir))
		{
			if (Files.exists(configDir.resolveSibling("essentialcmds")))
			{
				try
				{
					Files.move(configDir.resolveSibling("essentialcmds"), configDir);
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			}
			else
			{
				try
				{
					Files.createDirectories(configDir);
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}

		// Create data Directory for EssentialCmds
		if (!Files.exists(configDir.resolve("data")))
		{
			try
			{
				Files.createDirectories(configDir.resolve("data"));
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}

		// Create config.conf
		Config.getConfig().setup();
		// Create warps.conf
		WarpConfig.getConfig().setup();
		// Create homes.conf
		HomeConfig.getConfig().setup();
		// Create rules.conf
		RulesConfig.getConfig().setup();
		// Create jails.conf
		JailConfig.getConfig().setup();
		// Create spawn.conf
		SpawnConfig.getConfig().setup();