@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();
		// Create worlds.conf
		WorldConfig.getConfig().setup();
		// Create inventory.conf
		InventoryConfig.getConfig().setup();
	}

	@Listener
	public void onServerInit(GameInitializationEvent event)
	{
		getLogger().info(PluginInfo.NAME + " loading...");

		Utils.readMutes();
		Utils.readMail();
		Utils.startAFKService();

		// Register all commands.
		CommandLoader.registerCommands();

		getGame().getEventManager().registerListeners(this, new SignChangeListener());
		getGame().getEventManager().registerListeners(this, new PlayerJoinListener());
		getGame().getEventManager().registerListeners(this, new MessageSinkListener());
		getGame().getEventManager().registerListeners(this, new PlayerClickListener());
		getGame().getEventManager().registerListeners(this, new PlayerInteractListener());
		getGame().getEventManager().registerListeners(this, new PlayerMoveListener());
		getGame().getEventManager().registerListeners(this, new PlayerDeathListener());
		getGame().getEventManager().registerListeners(this, new TPAListener(this));
		getGame().getEventManager().registerListeners(this, new MailListener());
		getGame().getEventManager().registerListeners(this, new PlayerDisconnectListener());
		getGame().getEventManager().registerListeners(this, new WeatherChangeListener());
		getGame().getEventManager().registerListeners(this, new BlacklistListener());
		getGame().getEventManager().registerListeners(this, new CommandListener());
		getGame().getEventManager().registerListeners(this, new ChangeBlockListener());
		getGame().getEventManager().registerListeners(this, new PlayerDamageListener());
		getGame().getEventManager().registerListeners(this, new CommandSentListener());

		getLogger().info("-----------------------------");
		getLogger().info("EssentialCmds was made by HassanS6000!");
		getLogger().info("Please post all errors on the Sponge Thread or on GitHub!");
		getLogger().info("Have fun, and enjoy! :D");
		getLogger().info("-----------------------------");
		getLogger().info("EssentialCmds loaded!");
	}

	@Listener
	public void onServerStopping(GameStoppingEvent event)
	{
		Utils.saveMail();
	}

	public Path getConfigDir()
	{
		return configDir;
	}

	public Game getGame()
	{
		return Sponge.getGame();
	}
} public class AddRuleExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		String rule = ctx.<String> getOne("rule").get();
		Utils.addRule(rule);
		src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Added rule."));
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "addrule" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("Add Rule Command")).permission("essentialcmds.rules.add")
				.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("rule")))).executor(this).build();
	}
} public class AsConsoleExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Game game = EssentialCmds.getEssentialCmds().getGame();
		String command = ctx.<String> getOne("command").get();
		game.getCommandManager().process(game.getServer().getConsole().getCommandSource().get(), command);
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "asconsole", "asConsole" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("AsConsole Command")).permission("essentialcmds.asconsole.use")
				.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("command"))))
				.executor(this).build();
	}
} public class BlacklistBase extends CommandExecutorBase
{
	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "blacklist", "bl" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Blacklist Command"))
			.permission("essentialcmds.blacklist.use")
			.children(getChildrenList(new BlacklistAddExecutor(), new BlacklistListExecutor(), new BlacklistRemoveExecutor()))
			.build();
	}

	@Override
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		return CommandResult.empty();
	}

	private static class BlacklistAddExecutor extends CommandExecutorBase
	{

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "add" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("Add Blacklist Command"))
				.permission("essentialcmds.blacklist.add")
				.arguments(GenericArguments.onlyOne(GenericArguments.string(Text.of("item id"))))
				.executor(this)
				.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			String itemId = ctx.<String> getOne("item id").get();

			if (!Utils.getBlacklistItems().contains(itemId))
			{
				Utils.addBlacklistItem(itemId);
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, itemId + " has been blacklisted."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, itemId + " has already been blacklisted."));
			}

			return CommandResult.success();
		}
	}

	private static class BlacklistRemoveExecutor extends CommandExecutorBase
	{

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "remove" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("Remove Blacklist Command"))
				.permission("essentialcmds.blacklist.remove")
				.arguments(GenericArguments.onlyOne(GenericArguments.string(Text.of("item id"))))
				.executor(this)
				.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			String itemId = ctx.<String> getOne("item id").get();

			if (Utils.getBlacklistItems().contains(itemId))
			{
				Utils.removeBlacklistItem(itemId);
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, itemId + " has been un-blacklisted."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "This item is not blacklisted."));
			}

			return CommandResult.success();
		}
	}

	private static class BlacklistListExecutor extends CommandExecutorBase
	{

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "list" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("List Blacklist Command"))
				.permission("essentialcmds.blacklist.list")
				.executor(this)
				.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			List<String> blacklistItems = Utils.getBlacklistItems();

			if (blacklistItems.size() == 0)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "There are no blacklisted items!"));
				return CommandResult.success();
			}

			PaginationService paginationService = Sponge.getServiceManager().provide(PaginationService.class).get();
			List<Text> blacklistText = Lists.newArrayList();

			for (String name : blacklistItems)
			{
				Text item = Text.builder(name)
					.color(TextColors.DARK_AQUA)
					.style(TextStyles.UNDERLINE)
					.build();

				blacklistText.add(item);
			}

			PaginationList.Builder paginationBuilder = paginationService.builder().contents(blacklistText).title(Text.of(TextColors.GREEN, "Showing Blacklist")).padding(Text.of("-"));
			paginationBuilder.sendTo(src);

			return CommandResult.success();
		}
	}
} public class ButcherExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Game game = EssentialCmds.getEssentialCmds().getGame();

		if (src instanceof Player)
		{
			Player player = (Player) src;
			int butcheredEntities = 0;
			
			for (Entity entity : player.getWorld().getEntities())
			{
				if (entity instanceof Monster)
				{
					entity.remove();
					butcheredEntities++;
				}
			}
			
			player.sendMessage(Text.of(TextColors.LIGHT_PURPLE, "Butchered " + butcheredEntities + " entities."));
		}
		else
		{
			int butcheredEntities = 0;
			
			for (World world : game.getServer().getWorlds())
			{
				for (Entity entity : world.getEntities())
				{
					if (entity instanceof Monster)
					{
						entity.remove();
						butcheredEntities++;
					}
				}
			}
			
			src.sendMessage(Text.of(TextColors.LIGHT_PURPLE, "Butchered " + butcheredEntities + " entities."));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "butcher" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("Butcher Command")).permission("essentialcmds.butcher.use")
				.executor(this).build();
	}
} public class DeleteHomeExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		String homeName = ctx.<String> getOne("home name").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;

			if (Utils.isHomeInConfig(player.getUniqueId(), homeName))
			{
				String configHomeName = Utils.getConfigHomeName(player.getUniqueId(), homeName);
				Utils.deleteHome(player, homeName);
				src.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "Deleted home " + configHomeName));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "This home doesn't exist!"));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /delhome!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "deletehome", "delhome" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Delete Home Command")).permission("essentialcmds.home.delete").arguments(GenericArguments.onlyOne(GenericArguments.string(Text.of("home name")))).executor(this).build();
	}
} public class DeleteWarpExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx) {
		String warpName = ctx.<String> getOne("warp name").get();

		if (Utils.isWarpInConfig(warpName))
		{
			String configWarpName = Utils.getConfigWarpName(warpName);
			Utils.deleteWarp(warpName);
			src.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "Deleted warp " + configWarpName));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "This warp doesn't exist!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "deletewarp", "delwarp" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder()
			.description(Text.of("Delete Warp Command"))
			.permission("essentialcmds.warp.delete")
			.arguments(GenericArguments.onlyOne(GenericArguments.string(Text.of("warp name"))))
			.executor(this)
			.build();
	}
} public class DirectionExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;
			// Credit to kenzierocks for the following line. =D
			player.sendMessage(Text.of(TextColors.GOLD, "You are facing: ", TextColors.GRAY, Direction.getClosest(player.getTransform().getRotationAsQuaternion().getDirection()).toString()));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player to use /direction!"));
		}
		
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "direction", "compass" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("Direction Command")).permission("essentialcmds.direction.use")
				.executor(this).build();
	}
} public class EnchantExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> target = ctx.<Player> getOne("target");
		String enchantmentName = ctx.<String> getOne("enchantment").get();
		int level = ctx.<Integer> getOne("level").get();

		Enchantment enchantment = Sponge.getRegistry().getType(Enchantment.class, enchantmentName).orElse(null);

		if (enchantment == null)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Enchantment specified not found!"));
			return CommandResult.success();
		}

		if (!Utils.unsafeEnchanmentsEnabled())
		{
			if (enchantment.getMaximumLevel() < level)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Enchantment level too high!"));
				return CommandResult.success();
			}

		}

		if (!target.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;

				if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent())
				{
					ItemStack itemInHand = player.getItemInHand(HandTypes.MAIN_HAND).get();

					if (!enchantment.canBeAppliedToStack(itemInHand))
					{
						src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Enchantment cannot be applied to this item!"));
						return CommandResult.success();
					}

					EnchantmentData enchantmentData = itemInHand.getOrCreate(EnchantmentData.class).get();
					ItemEnchantment itemEnchantment = new ItemEnchantment(enchantment, level);
					ItemEnchantment sameEnchantment = null;

					for (ItemEnchantment ench : enchantmentData.enchantments())
					{
						if (ench.getEnchantment().getId().equals(enchantment.getId()))
						{
							sameEnchantment = ench;
							break;
						}
					}

					if (sameEnchantment == null)
					{
						enchantmentData.set(enchantmentData.enchantments().add(itemEnchantment));
					}
					else
					{
						enchantmentData.set(enchantmentData.enchantments().remove(sameEnchantment));
						enchantmentData.set(enchantmentData.enchantments().add(itemEnchantment));
					}

					itemInHand.offer(enchantmentData);
					player.setItemInHand(HandTypes.MAIN_HAND, itemInHand);
					player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Enchanted item(s) in your hand."));
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be holding something to enchant!"));
				}
			}
			else if (src instanceof ConsoleSource)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /enchant!"));
			}
			else if (src instanceof CommandBlockSource)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /enchant!"));
			}
		}
		else if (target.isPresent() && src.hasPermission("essentialcmds.enchant.others"))
		{
			Player player = target.get();

			if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent())
			{
				ItemStack itemInHand = player.getItemInHand(HandTypes.MAIN_HAND).get();

				if (!enchantment.canBeAppliedToStack(itemInHand))
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Enchantment cannot be applied to this item!"));
					return CommandResult.success();
				}

				EnchantmentData enchantmentData = itemInHand.getOrCreate(EnchantmentData.class).get();
				ItemEnchantment itemEnchantment = new ItemEnchantment(enchantment, level);
				ItemEnchantment sameEnchantment = null;

				for (ItemEnchantment ench : enchantmentData.enchantments())
				{
					if (ench.getEnchantment().getId().equals(enchantment.getId()))
					{
						sameEnchantment = ench;
						break;
					}
				}

				if (sameEnchantment == null)
				{
					enchantmentData.set(enchantmentData.enchantments().add(itemEnchantment));
				}
				else
				{
					enchantmentData.set(enchantmentData.enchantments().remove(sameEnchantment));
					enchantmentData.set(enchantmentData.enchantments().add(itemEnchantment));
				}

				itemInHand.offer(enchantmentData);
				player.setItemInHand(HandTypes.MAIN_HAND, itemInHand);
				player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Enchanted item(s) in your hand."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be holding something to enchant!"));
			}
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "enchant", "ench" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec
			.builder()
			.description(Text.of("Enchant Command"))
			.permission("essentialcmds.enchant.use")
			.arguments(GenericArguments.seq(GenericArguments.optional(GenericArguments.player(Text.of("target"))), GenericArguments.onlyOne(GenericArguments.integer(Text.of("level")))), GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("enchantment"))))
			.executor(this).build();
	}
} public class EssentialCmdsExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext args) {
		src.sendMessage(Text.of(TextColors.GOLD, "[EssentialCmds]: ", TextColors.GRAY, "Version: ", TextColors.GREEN, Sponge.getPluginManager().getPlugin(PluginInfo.ID).get().getVersion()));
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "essentialcmds", "essentialcmd" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder()
				.description(Text.of("EssentialCmds Command"))
				.children(getChildrenList(new ReloadExecutor()))
				.executor(this)
				.build();
	}

	private static class ReloadExecutor extends AsyncCommandExecutorBase {

		@Override
		public void executeAsync(CommandSource src, CommandContext args) {
			Config.getConfig().load();
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Config reloaded."));
		}

		@Nonnull
		@Override
		public String[] getAliases() {
			return new String[] { "reload" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec() {
			return CommandSpec.builder()
					.description(Text.of("Reload Command"))
					.permission("essentialcmds.reload.use")
					.executor(this)
					.build();
		}
	}
} public class ExpExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		if(src instanceof Player)
		{
			Player player = (Player) src;
			ExperienceHolderData expHolderData = player.getOrCreate(ExperienceHolderData.class).get();
			player.sendMessage(Text.of(TextColors.GOLD, "Your current experience: ", TextColors.GRAY, expHolderData.totalExperience().get()));
			player.sendMessage(Text.of(TextColors.GOLD, "Experience to next level: ", TextColors.GRAY, expHolderData.getExperienceBetweenLevels().get() - expHolderData.experienceSinceLevel().get()));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player to use this command!"));
		}
		
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "exp", "experience" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder()
				.description(Text.of("Experience Command"))
				.children(getChildrenList(new GiveExecutor(), new SetExecutor(), new TakeExecutor()))
				.permission("essentialcmds.exp.use")
				.executor(this)
				.build();
	}

	private static class GiveExecutor extends CommandExecutorBase {

		@Nonnull
		@Override
		public String[] getAliases() {
			return new String[] { "give" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec() {
			return CommandSpec.builder()
					.description(Text.of("Experience Give Command"))
					.permission("essentialcmds.exp.give.use")
					.arguments(GenericArguments.seq(
							GenericArguments.player(Text.of("target")),
							GenericArguments.integer(Text.of("exp"))))
					.executor(this)
					.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException {
			int expLevel = ctx.<Integer> getOne("exp").get();
			Player player = ctx.<Player> getOne("target").get();
			player.offer(Keys.TOTAL_EXPERIENCE, player.get(Keys.TOTAL_EXPERIENCE).get() + expLevel);
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Gave " + player.getName() + " " + expLevel + " experience."));
			return CommandResult.success();
		}
	}

	private static class SetExecutor extends CommandExecutorBase {

		@Nonnull
		@Override
		public String[] getAliases() {
			return new String[] { "set" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec() {
			return CommandSpec.builder()
					.description(Text.of("Experience Set Command"))
					.permission("essentialcmds.exp.set.use")
					.arguments(GenericArguments.seq(
							GenericArguments.player(Text.of("target")),
							GenericArguments.integer(Text.of("exp"))))
					.executor(this)
					.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException {
			int expLevel = ctx.<Integer> getOne("exp").get();
			Player player = ctx.<Player> getOne("target").get();
			player.offer(Keys.TOTAL_EXPERIENCE, expLevel);
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Set " + player.getName() + "'s experience level to " + expLevel + "."));
			return CommandResult.success();
		}
	}

	private static class TakeExecutor extends CommandExecutorBase {

		@Nonnull
		@Override
		public String[] getAliases() {
			return new String[] { "take" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec() {
			return CommandSpec.builder()
				.description(Text.of("Experience Take Command"))
				.permission("essentialcmds.exp.take.use")
				.arguments(GenericArguments.seq(
						GenericArguments.player(Text.of("target")),
						GenericArguments.integer(Text.of("exp"))))
				.executor(this)
				.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException {
			int expLevel = ctx.<Integer> getOne("exp").get();
			Player player = ctx.<Player> getOne("target").get();
			player.offer(Keys.TOTAL_EXPERIENCE, player.get(Keys.TOTAL_EXPERIENCE).get() - expLevel);
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Took " + expLevel + " experience from " + player.getName() + "."));
			return CommandResult.success();
		}
	}
} public class FireballExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> optionalTarget = ctx.<Player> getOne("player");

		if (!optionalTarget.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				BlockRay<World> playerBlockRay = BlockRay.from(player).blockLimit(350).build();

				Location<World> spawnLocation = null;
				int i = 0;

				while (playerBlockRay.hasNext())
				{
					// TODO: Come up with a better way of making sure it doesn't hit the player.
					i++;

					BlockRayHit<World> currentHitRay = playerBlockRay.next();

					if (i > 5)
					{
						// We can set the spawn location, so break here.
						spawnLocation = currentHitRay.getLocation();
						break;
					}
				}

				Vector3d velocity = player.getTransform().getRotationAsQuaternion().getDirection();
				spawnEntity(spawnLocation, velocity, player);
				player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Created Fireball!"));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /fireball!"));
			}
		}
		else
		{
			Player player = optionalTarget.get();
			Location<World> playerLocation = player.getLocation();
			Vector3d velocity = player.getTransform().getRotationAsQuaternion().getDirection();
			spawnEntity(playerLocation, velocity, src);
			player.sendMessage(Text.of(TextColors.GRAY, src.getName(), TextColors.GOLD, " has struck you with a fireball."));
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Struck " + player.getName() + " with fireball."));
		}

		return CommandResult.success();
	}

	public void spawnEntity(Location<World> location, Vector3d velocity, CommandSource src)
	{
		Extent extent = location.getExtent();
		Entity fireball = extent.createEntity(EntityTypes.FIREBALL, location.getPosition());
		fireball.offer(Keys.VELOCITY, velocity);
		extent.spawnEntity(fireball, Cause.of(NamedCause.source(SpawnCause.builder().type(SpawnTypes.CUSTOM).build())));
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "fireball", "ghast" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Fireball Command")).permission("essentialcmds.fireball.use")
			.arguments(GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))))
			.executor(new FireballExecutor()).build();
	}
} public class FlyExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> targetPlayer = ctx.<Player> getOne("player");

		if (!targetPlayer.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;

				if (player.get(Keys.CAN_FLY).isPresent())
				{
					boolean canFly = player.get(Keys.CAN_FLY).get();
					player.offer(Keys.CAN_FLY, !canFly);

					if (canFly)
					{
						player.offer(Keys.IS_FLYING, !canFly);
						player.sendMessage(Text.of(TextColors.GOLD, "Toggled flying: ", TextColors.GRAY, "off."));

						if (EssentialCmds.flyingPlayers.contains(player.getUniqueId()))
						{
							EssentialCmds.flyingPlayers.remove(player.getUniqueId());
						}
					}
					else
					{
						player.sendMessage(Text.of(TextColors.GOLD, "Toggled flying: ", TextColors.GRAY, "on."));

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

					if (!EssentialCmds.flyingPlayers.contains(player.getUniqueId()))
					{
						EssentialCmds.flyingPlayers.add(player.getUniqueId());
					}
				}
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /fly!"));
			}
		}
		else if (src.hasPermission("essentialcmds.fly.others"))
		{
			Player player = targetPlayer.get();

			if (player.get(Keys.CAN_FLY).isPresent())
			{
				boolean canFly = player.get(Keys.CAN_FLY).get();
				player.offer(Keys.CAN_FLY, !canFly);

				if (canFly)
				{
					src.sendMessage(Text.of(TextColors.GOLD, "Toggled flying: ", TextColors.GRAY, "off."));
					player.sendMessage(Text.of(TextColors.GOLD, "Toggled flying: ", TextColors.GRAY, "off."));

					if (EssentialCmds.flyingPlayers.contains(player.getUniqueId()))
					{
						EssentialCmds.flyingPlayers.remove(player.getUniqueId());
					}
				}
				else
				{
					src.sendMessage(Text.of(TextColors.GOLD, "Toggled flying: ", TextColors.GRAY, "on."));
					player.sendMessage(Text.of(TextColors.GOLD, "Toggled flying: ", TextColors.GRAY, "on."));

					if (!EssentialCmds.flyingPlayers.contains(player.getUniqueId()))
					{
						EssentialCmds.flyingPlayers.add(player.getUniqueId());
					}
				}
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You do not have permission to change others ability to fly."));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "fly" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Fly Command"))
			.permission("essentialcmds.fly.use")
			.arguments(GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))))
			.executor(this)
			.build();
	}
} public class GCExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		double tps = Sponge.getServer().getTicksPerSecond();
		src.sendMessage(Text.of(TextColors.GOLD, "Current TPS: ", TextColors.GRAY, tps));
		src.sendMessage(Text.of(TextColors.GOLD, "World Info:"));

		for (World world : Sponge.getServer().getWorlds())
		{
			int numOfEntities = world.getEntities().size();
			int loadedChunks = Iterables.size(world.getLoadedChunks());
			src.sendMessage(Text.of());
			src.sendMessage(Text.of(TextColors.GREEN, "World: ", world.getName()));
			src.sendMessage(Text.of(TextColors.GOLD, "Entities: ", TextColors.GRAY, numOfEntities));
			src.sendMessage(Text.of(TextColors.GOLD, "Loaded Chunks: ", TextColors.GRAY, loadedChunks));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "gc", "tickstat" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder()
				.description(Text.of("TickStat Command"))
				.permission("essentialcmds.tickstat.use")
				.executor(this)
				.build();
	}
} public class GetPosExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> optionalPlayer = ctx.<Player> getOne("player");

		if (!optionalPlayer.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				player.sendMessage(Text.of(TextColors.GOLD, "Your current position is: ", TextColors.GRAY, player.getLocation().getX() + ", " + player.getLocation().getY() + ", " + player.getLocation().getZ()));
			}
			else if (src instanceof ConsoleSource)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /getpos!"));
			}
			else if (src instanceof CommandBlockSource)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /getpos!"));
			}
		}
		else if (src.hasPermission("essentialscmds.getpos.others"))
		{
			Player player = optionalPlayer.get();
			src.sendMessage(Text.of(TextColors.GOLD, player.getName() + "'s current position is: ", TextColors.GRAY, player.getLocation().getX() + ", " + player.getLocation().getY() + ", " + player.getLocation().getZ()));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You don't have permission to get the positon of others!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "getpos" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("GetPos Command"))
			.permission("essentialcmds.getpos.use")
			.arguments(GenericArguments.optional(
				GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))))
			.executor(this).build();
	}
} public class GodExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;

			if (EssentialCmds.godPlayers.contains(player.getUniqueId()))
			{
				EssentialCmds.godPlayers.remove(player.getUniqueId());
				player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.RED, "Toggled god mode off!"));
			}
			else
			{
				EssentialCmds.godPlayers.add(player.getUniqueId());
				player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.GOLD, "Toggled god mode on!"));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /god!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "god", "godmode" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Allows Toggling of God Mode")).permission("essentialcmds.god.use")
			.executor(this).build();
	}
} public class HatExecutor extends CommandExecutorBase
{
	@Override
	public CommandResult execute(CommandSource src, CommandContext args) throws CommandException
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;
			Optional<ItemStack> itemInHand = player.getItemInHand(HandTypes.MAIN_HAND);

			if (itemInHand.isPresent())
			{
				if (itemInHand.get().getQuantity() > 1)
				{
					ItemStack stack = itemInHand.get();
					stack.setQuantity(itemInHand.get().getQuantity() - 1);
					player.setItemInHand(HandTypes.MAIN_HAND, stack);
					stack.setQuantity(1);
					player.setHelmet(stack);
				}
				else
				{
					player.setHelmet(itemInHand.get());
					player.setItemInHand(HandTypes.MAIN_HAND, null);
				}
			}
			else
			{
				player.sendMessage(Text.of("No item selected in hotbar."));
			}
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "hat" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Hat Command")).permission("essentialcmds.hat.use").executor(this).build();
	}
} public class HealExecutor extends CommandExecutorBase
{

	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> p = ctx.<Player> getOne("player");

		if (src instanceof Player)
		{
			Player player = (Player) src;

			if (player.hasPermission("essentialcmds.heal.others") && p.isPresent())
			{
				Player recipient = p.get();
				recipient.offer(Keys.HEALTH, player.get(Keys.MAX_HEALTH).get());
				recipient.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "You've been healed by " + player.getName()));
				src.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "You've healed " + recipient.getName()));
			}
			else if (p.isPresent())
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You do not have permission to heal other players!"));
			}
			else
			{
				player.offer(Keys.HEALTH, player.get(Keys.MAX_HEALTH).get());
				src.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "You've been healed."));
			}
		}
		else if (src instanceof ConsoleSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /heal!"));
		}
		else if (src instanceof CommandBlockSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /heal!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "heal" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("Heal Command")).permission("essentialcmds.heal.use")
				.arguments(GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))))
				.executor(this).build();
	}
} public class HelpOpExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		String question = ctx.<String> getOne("question").get();
		
		if (src instanceof Player)
		{
			Player player = (Player) src;
			
			for(Player p : Sponge.getServer().getOnlinePlayers())
			{
				if(p.hasPermission("essentialcmds.helpop.receive"))
					p.sendMessage(Text.of(TextColors.RED, "[Help-Op]: ", TextColors.GOLD, player.getName(), TextColors.GRAY, " needs help! ", TextColors.WHITE, question));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /helpop!"));
		}
		
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "helpop" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder()
			.description(Text.of("Help-Op Command"))
			.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("question"))))
			.permission("essentialcmds.helpop.use")
			.executor(this)
			.build();
	}
} public class HomeExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		String homeName = ctx.<String> getOne("home name").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;

			if (Utils.isHomeInConfig(player.getUniqueId(), homeName))
			{
				try
				{
					if (Utils.isTeleportCooldownEnabled() && !player.hasPermission("essentialcmds.teleport.cooldown.override"))
					{
						EssentialCmds.teleportingPlayers.add(player.getUniqueId());
						src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleporting to home " + Utils.getConfigHomeName(player.getUniqueId(), homeName) + ". Please wait " + Utils.getTeleportCooldown() + " seconds."));

						Sponge.getScheduler().createTaskBuilder().execute(() -> {
							if (EssentialCmds.teleportingPlayers.contains(player.getUniqueId()))
							{
								Utils.setLastTeleportOrDeathLocation(player.getUniqueId(), player.getLocation());

								if (Objects.equals(player.getWorld().getUniqueId(), Utils.getHome(player.getUniqueId(), homeName).getExtent().getUniqueId()))
								{
									player.setTransform(Utils.getHome(player.getUniqueId(), homeName));
								}
								else
								{
									player.transferToWorld(Utils.getHome(player.getUniqueId(), homeName).getExtent().getUniqueId(), Utils.getHome(player.getUniqueId(), homeName).getPosition());
									player.setTransform(Utils.getHome(player.getUniqueId(), homeName));
								}

								src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to home " + Utils.getConfigHomeName(player.getUniqueId(), homeName)));
								EssentialCmds.teleportingPlayers.remove(player.getUniqueId());
							}
						}).delay(Utils.getTeleportCooldown(), TimeUnit.SECONDS).name("EssentialCmds - Back Timer").submit(Sponge.getGame().getPluginManager().getPlugin(PluginInfo.ID).get().getInstance().get());
					}
					else
					{
						Utils.setLastTeleportOrDeathLocation(player.getUniqueId(), player.getLocation());

						if (Objects.equals(player.getWorld().getUniqueId(), Utils.getHome(player.getUniqueId(), homeName).getExtent().getUniqueId()))
						{
							player.setTransform(Utils.getHome(player.getUniqueId(), homeName));
						}
						else
						{
							player.transferToWorld(Utils.getHome(player.getUniqueId(), homeName).getExtent().getUniqueId(), Utils.getHome(player.getUniqueId(), homeName).getPosition());
							player.setTransform(Utils.getHome(player.getUniqueId(), homeName));
						}

						src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to home " + Utils.getConfigHomeName(player.getUniqueId(), homeName)));
					}
				}
				catch (PositionOutOfBoundsException e)
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Home is in invalid coordinates!"));
				}
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must first set your home!"));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /home!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "home" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Home Command"))
			.permission("essentialcmds.home.use")
			.arguments(GenericArguments.onlyOne(GenericArguments.string(Text.of("home name"))))
			.executor(this)
			.build();
	}
} public class IgniteExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Integer ticks = ctx.<Integer> getOne("ticks").get();
		Optional<Player> target = ctx.<Player> getOne("player");

		if (!target.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				player.offer(Keys.FIRE_TICKS, ticks);
				player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "You are now on fire."));
			}
			else if (src instanceof ConsoleSource)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /ignite!"));
			}
			else if (src instanceof CommandBlockSource)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /ignite!"));
			}
		}
		else if (target.isPresent() && src.hasPermission("ignite.others"))
		{
			Player player = target.get();
			player.offer(Keys.FIRE_TICKS, ticks);
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Set player on fire."));
			player.sendMessage(Text.of(TextColors.GOLD, src.getName(), TextColors.RED, " has set you on fire."));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "ignite", "burn", "fire" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("Ignite Command")).permission("essentialcmds.ignite.use")
				.arguments(GenericArguments.seq(
						GenericArguments.onlyOne(GenericArguments.integer(Text.of("ticks"))),
						GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player"))))))
				.executor(this).build();
	}
} public class InvSeeExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Player target = ctx.<Player> getOne("target").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;
			EntityPlayerMP playerMP = ((EntityPlayerMP) (Object) player);
			EntityPlayerMP targetMP = ((EntityPlayerMP) (Object) target);

			InventoryPlayer inventory = targetMP.inventory;
			ContainerChest container = new ContainerChest(playerMP.inventory, inventory, playerMP);

			if (playerMP.openContainer != playerMP.inventoryContainer)
			{
				playerMP.closeScreen();
			}

			playerMP.getNextWindowId();

			playerMP.connection.sendPacket(new SPacketOpenWindow(playerMP.currentWindowId, "minecraft:container", inventory.getDisplayName(), inventory.getSizeInventory()));
			playerMP.openContainer = container;

			playerMP.openContainer.windowId = playerMP.currentWindowId;
			playerMP.openContainer.addListener(playerMP);
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be a player to see other inventories."));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "invsee", "inventorysee", "invview" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("InvSee Command")).permission("essentialcmds.invsee.use").arguments(GenericArguments.onlyOne(GenericArguments.player(Text.of("target")))).executor(this).build();
	}
} public class ItemInfoExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;

			if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent())
			{
				ItemStack itemInHand = player.getItemInHand(HandTypes.MAIN_HAND).get();
				player.sendMessage(Text.of(TextColors.GOLD, "The name of the item in your hand is: ", TextColors.GRAY, itemInHand.getTranslation().get()));
				player.sendMessage(Text.of(TextColors.GOLD, "The ID of the item in your hand is: ", TextColors.GRAY, itemInHand.getItem().getId()));
				player.sendMessage(Text.of(TextColors.GOLD, "The meta of the item in your hand is: ", TextColors.GRAY, itemInHand.toContainer().get(DataQuery.of("UnsafeDamage")).get().toString()));
			}
			else
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must hold an item."));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player to use this command."));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "iteminfo", "itemdb" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("ItemInfo Command")).permission("essentialcmds.iteminfo.use")
			.executor(this).build();
	}
} public class JailExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Player target = ctx.<Player> getOne("target").get();
		int jailNumber = ctx.<Integer> getOne("number").get();

		if (!EssentialCmds.jailedPlayers.contains(target.getUniqueId()))
		{
			if (Utils.getNumberOfJails() >= jailNumber)
			{
				EssentialCmds.jailedPlayers.add(target.getUniqueId());
				Utils.teleportPlayerToJail(target, jailNumber);
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Jailed " + target.getName() + "."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Jail does not exist."));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Player is already jailed!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "jail" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Jail Command"))
			.arguments(GenericArguments.seq(GenericArguments.player(Text.of("target")), GenericArguments.integer(Text.of("number"))))
			.children(getChildrenList(new AddExecutor(), new RemoveExecutor()))
			.permission("essentialcmds.jail.use")
			.executor(this)
			.build();
	}

	private static class RemoveExecutor extends CommandExecutorBase
	{

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "remove" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("Jail Remove Command"))
				.permission("essentialcmds.jail.remove.use")
				.arguments(GenericArguments.integer(Text.of("number")))
				.executor(this)
				.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			int number = ctx.<Integer> getOne("number").get();
			boolean jailRemoved = Utils.removeJail(number);
			
			if (jailRemoved)
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Removed jail " + number + "."));
			else
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Jail " + number + "doesn't exist."));

			return CommandResult.success();
		}
	}

	private static class AddExecutor extends CommandExecutorBase
	{

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "add" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("Jail Add Command"))
				.permission("essentialcmds.jail.add.use")
				.executor(this)
				.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				Utils.addJail(player.getLocation());
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Set your location as a jail."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be a player to use this command."));
			}

			return CommandResult.success();
		}
	}
} public class JumpExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;

			BlockRay<World> playerBlockRay = BlockRay.from(player).blockLimit(350).build();

			BlockRayHit<World> finalHitRay = null;

			while (playerBlockRay.hasNext())
			{
				BlockRayHit<World> currentHitRay = playerBlockRay.next();

				if (!player.getWorld().getBlockType(currentHitRay.getBlockPosition()).equals(BlockTypes.AIR))
				{
					finalHitRay = currentHitRay;
					break;
				}
			}

			if (finalHitRay == null)
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Could not find the block you're looking at within range!"));
			}
			else
			{
				boolean safely = false;
				// If not passable, then it is a solid block
				if (!finalHitRay.getLocation().getProperty(PassableProperty.class).get().getValue())
				{
					safely = player.setLocationSafely(finalHitRay.getLocation().add(0, 1, 0));
				}
				else
				{
					// If the block below this is tall grass or a tall flower, then teleport down to that
					if (finalHitRay.getLocation().getRelative(Direction.DOWN).getProperty(PassableProperty.class).get().getValue())
					{
						safely = player.setLocationSafely(finalHitRay.getLocation().sub(0, 1, 0));
					}
					else
					{
						// If not then we found our location
						safely = player.setLocationSafely(finalHitRay.getLocation());
					}
				}
				if (safely)
				{
					player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Jumped to the block you were looking at."));
				}
				else
				{
					player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Couldn't safely put you where you are looking."));
				}
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /jump!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "jump" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Jump Command")).permission("essentialcmds.jump.use").executor(this).build();
	}
} public class KickAllExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		String reason = ctx.<String> getOne("reason").get();
		Text reas = TextSerializers.formattingCode('&').deserialize(reason);

		for(Player player : Sponge.getServer().getOnlinePlayers())
		{
			if(!src.equals(player))
				player.kick(reas);
		}

		src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Kicked all players."));
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "kickall" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec
			.builder()
			.description(Text.of("KickAll Command"))
			.permission("essentialcmds.kickall.use")
			.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("reason"))))
			.executor(this)
			.build();
	}
} public class KickExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Game game = EssentialCmds.getEssentialCmds().getGame();
		Server server = game.getServer();
		Player player = ctx.<Player> getOne("player").get();
		Optional<String> reason = ctx.<String> getOne("reason");

		if (server.getPlayer(player.getUniqueId()).isPresent())
		{
			Text finalKickMessage = Text.of(TextColors.GOLD, src.getName() + " kicked " + player.getName());

			if (reason.isPresent())
			{
				Text reas = TextSerializers.formattingCode('&').deserialize(reason.get());
				Text kickMessage = Text.of(TextColors.GOLD, src.getName() + " kicked " + player.getName() + " for ", TextColors.RED);
				finalKickMessage = Text.builder().append(kickMessage).append(reas).build();
				player.kick(reas);
			}
			else
			{
				player.kick();
			}

			MessageChannel.TO_ALL.send(finalKickMessage);
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Player kicked."));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Player doesn't appear to be online!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "kick" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec
			.builder()
			.description(Text.of("Kick Command"))
			.permission("essentialcmds.kick.use")
			.arguments(GenericArguments.seq(
				GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))), 
				GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("reason")))))
			.executor(this)
			.build();
	}
} public class KillExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> p = ctx.<Player> getOne("player");

		if (p.isPresent() && src.hasPermission("essentialcmds.kill.others"))
		{
			p.get().offer(Keys.HEALTH, 0d);
			Utils.setLastTeleportOrDeathLocation(p.get().getUniqueId(), p.get().getLocation());
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Killed player " + p.get().getName()));
			p.get().sendMessage(Text.of(TextColors.RED, "You have been killed by " + src.getName()));
		}
		else if (!p.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				player.offer(Keys.HEALTH, 0d);
				Utils.setLastTeleportOrDeathLocation(player.getUniqueId(), player.getLocation());
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Killed yourself."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot kill yourself, you are not a player!"));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You do not have permission to kill other players!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "kill" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Kill Command"))
			.permission("essentialcmds.kill.use")
			.arguments(GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))))
			.executor(this).build();
	}
} public class KittyCannonExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> optionalTarget = ctx.<Player> getOne("player");

		if (!optionalTarget.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				BlockRay<World> playerBlockRay = BlockRay.from(player).blockLimit(350).build();

				Location<World> spawnLocation = null;
				int i = 0;

				while (playerBlockRay.hasNext())
				{
					// TODO: Come up with a better way of making sure it doesn't hit the player.
					i++;

					BlockRayHit<World> currentHitRay = playerBlockRay.next();

					if (i > 5)
					{
						// We can set the spawn location, so break here.
						spawnLocation = currentHitRay.getLocation();
						break;
					}
				}

				Vector3d velocity = player.getTransform().getRotationAsQuaternion().getDirection();
				spawnEntity(spawnLocation, velocity, player);
				player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Fired kitty!"));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /kittycannon!"));
			}
		}
		else
		{
			Player player = optionalTarget.get();
			Location<World> playerLocation = player.getLocation();
			Vector3d velocity = player.getTransform().getRotationAsQuaternion().getDirection();
			spawnEntity(playerLocation, velocity, src);
			player.sendMessage(Text.of(TextColors.GRAY, src.getName(), TextColors.GOLD, " has fired kittens at you."));
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Attacked " + player.getName() + " with kittens."));
		}

		return CommandResult.success();
	}

	public void spawnEntity(Location<World> location, Vector3d velocity, CommandSource src)
	{
		velocity = velocity.mul(5);
		Extent extent = location.getExtent();
		Entity kitten = extent.createEntity(EntityTypes.OCELOT, location.getPosition());
		kitten.offer(Keys.VELOCITY, velocity);
		extent.spawnEntity(kitten, Cause.of(NamedCause.source(SpawnCause.builder().type(SpawnTypes.CUSTOM).build())));
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "kittycannon" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Kitty Cannon Command"))
			.permission("essentialcmds.kittycannon.use")
			.arguments(GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))))
			.executor(this)
			.build();
	}
} public class LightningExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> optionalTarget = ctx.<Player> getOne("player");

		if (!optionalTarget.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;

				BlockRay<World> playerBlockRay = BlockRay.from(player).blockLimit(350).build();
				BlockRayHit<World> finalHitRay = null;

				while (playerBlockRay.hasNext())
				{
					BlockRayHit<World> currentHitRay = playerBlockRay.next();

					if (!player.getWorld().getBlockType(currentHitRay.getBlockPosition()).equals(BlockTypes.AIR))
					{
						finalHitRay = currentHitRay;
						break;
					}
				}

				Location<World> lightningLocation = null;

				if (finalHitRay == null)
				{
					lightningLocation = player.getLocation();
				}
				else
				{
					lightningLocation = finalHitRay.getLocation();
				}

				spawnEntity(lightningLocation, src);
				player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Created Lightning Strike!"));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /lightning!"));
			}
		}
		else
		{
			Player player = optionalTarget.get();
			Location<World> playerLocation = player.getLocation();
			spawnEntity(playerLocation, src);
			player.sendMessage(Text.of(TextColors.GRAY, src.getName(), TextColors.GOLD, " has struck you with lightning."));
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Struck " + player.getName() + " with lightning."));
		}

		return CommandResult.success();
	}

	public void spawnEntity(Location<World> location, CommandSource src)
	{
		Extent extent = location.getExtent();
		Entity lightning = extent.createEntity(EntityTypes.LIGHTNING, location.getPosition());
		extent.spawnEntity(lightning, Cause.of(NamedCause.source(SpawnCause.builder().type(SpawnTypes.CUSTOM).build())));
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "thor", "smite", "lightning" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Lightning Command")).permission("essentialcmds.lightning.use")
			.arguments(GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))))
			.executor(this).build();
	}
} public class ListExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<PermissionService> optPermissionService = Sponge.getServiceManager().provide(PermissionService.class);

		src.sendMessage(Text.of(TextColors.GOLD, "There are ", TextColors.RED, Sponge.getServer().getOnlinePlayers().size(), TextColors.GOLD, " out of ", TextColors.GRAY, Sponge.getServer().getMaxPlayers(), TextColors.GOLD, " players online."));

		if (optPermissionService.isPresent())
		{
			PermissionService permissionService = optPermissionService.get();
			List<Subject> groups = Lists.newArrayList(permissionService.getGroupSubjects().getAllSubjects());
			Collections.sort(groups, new SubjectComparator());
			Collections.reverse(groups);
			List<UUID> listedPlayers = Lists.newArrayList();

			for (Subject group : groups)
			{
				List<Subject> users = StreamSupport.stream(permissionService.getUserSubjects().getAllSubjects().spliterator(), false).filter(u -> u.isChildOf(group) && u.getCommandSource().isPresent() && u.getCommandSource().get() instanceof Player).collect(Collectors.toList());
				List<Text> onlineUsers = Lists.newArrayList();

				for (Subject user : users)
				{
					Optional<Player> optPlayer;

					try
					{
						optPlayer = Sponge.getServer().getPlayer(UUID.fromString(user.getIdentifier()));
					}
					catch (IllegalArgumentException e)
					{
						optPlayer = Sponge.getServer().getPlayer(user.getIdentifier());
					}

					if (optPlayer.isPresent() && !listedPlayers.contains(optPlayer.get().getUniqueId()))
					{
						listedPlayers.add(optPlayer.get().getUniqueId());
						Text name = Text.builder().append(TextSerializers.FORMATTING_CODE.deserialize(Utils.getNick(optPlayer.get()))).append(Text.of(" ")).build();
						boolean isAFK = false;

						if (EssentialCmds.afkList.containsKey(optPlayer.get().getUniqueId()))
						{
							AFK afk = EssentialCmds.afkList.get(optPlayer.get().getUniqueId());
							isAFK = afk.getAFK();
						}

						if (isAFK)
							onlineUsers.add(Text.builder().append(Text.of(TextColors.GRAY, TextStyles.ITALIC, "[AFK]: ")).append(name).build());
						else
							onlineUsers.add(name);
					}
				}

				if (onlineUsers.size() > 0)
				{
					src.sendMessage(Text.builder().append(Text.of(TextColors.GOLD, group.getIdentifier(), ": ")).append(onlineUsers).build());
				}
			}

			if (listedPlayers.size() < Sponge.getServer().getOnlinePlayers().size())
			{
				List<Player> remainingPlayers = Sponge.getServer().getOnlinePlayers().stream().filter(p -> !listedPlayers.contains(p.getUniqueId())).collect(Collectors.toList());
				List<Text> onlineUsers = Lists.newArrayList();

				for (Player player : remainingPlayers)
				{
					Text name = Text.builder().append(TextSerializers.FORMATTING_CODE.deserialize(Utils.getNick(player))).append(Text.of(" ")).build();
					boolean isAFK = false;

					if (EssentialCmds.afkList.containsKey(player.getUniqueId()))
					{
						AFK afk = EssentialCmds.afkList.get(player.getUniqueId());
						isAFK = afk.getAFK();
					}

					if (isAFK)
						onlineUsers.add(Text.builder().append(Text.of(TextColors.GRAY, TextStyles.ITALIC, "[AFK]: ")).append(name).build());
					else
						onlineUsers.add(name);
				}

				if (onlineUsers.size() > 0)
				{
					src.sendMessage(Text.builder().append(Text.of(TextColors.GOLD, "Default", ": ")).append(onlineUsers).build());
				}
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.GRAY, Sponge.getServer().getOnlinePlayers().toString()));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "list" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("List Command"))
			.permission("essentialcmds.list.use")
			.executor(this)
			.build();
	}
} public class ListHomeExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;

			Set<Object> homes = Utils.getHomes(player.getUniqueId());

			if (homes.size() == 0)
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must first set a home to list your homes!"));
				return;
			}

			PaginationService paginationService = Sponge.getServiceManager().provide(PaginationService.class).get();
			List<Text> homeText = Lists.newArrayList();

			for (Object home : homes)
			{
				String name = String.valueOf(home);

				Text item = Text.builder(name)
					.onClick(TextActions.runCommand("/home " + name))
					.onHover(TextActions.showText(Text.of(TextColors.WHITE, "Teleport to home ", TextColors.GOLD, name)))
					.color(TextColors.DARK_AQUA)
					.style(TextStyles.UNDERLINE)
					.build();

				homeText.add(item);
			}

			PaginationList.Builder paginationBuilder = paginationService.builder().contents(homeText).title(Text.of(TextColors.GREEN, "Showing Homes")).padding(Text.of("-"));
			paginationBuilder.sendTo(src);
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /homes!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "homes" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("List Home Command"))
			.permission("essentialcmds.home.list")
			.executor(this)
			.build();
	}
} public class ListWarpExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;
			Set<Object> warps = Utils.getWarps();

			if (warps.size() == 0)
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "No warps set!"));
				return;
			}

			if (warps.size() > 0)
			{
				PaginationService paginationService = Sponge.getServiceManager().provide(PaginationService.class).get();
				List<Text> warpText = Lists.newArrayList();

				for (Object name : warps)
				{
					if (player.hasPermission("essentialcmds.warp.use." + String.valueOf(name)))
					{
						Text item = Text.builder(String.valueOf(name))
							.onClick(TextActions.runCommand("/warp " + String.valueOf(name)))
							.onHover(TextActions.showText(Text.of(TextColors.WHITE, "Warp to ", TextColors.GOLD, String.valueOf(name))))
							.color(TextColors.DARK_AQUA)
							.style(TextStyles.UNDERLINE)
							.build();

						warpText.add(item);
					}
				}

				PaginationList.Builder paginationBuilder = paginationService.builder().contents(warpText).title(Text.of(TextColors.GREEN, "Showing Warps")).padding(Text.of("-"));
				paginationBuilder.sendTo(src);
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "No warps set!"));
			}
		}
		else if (src instanceof ConsoleSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /warps!"));
		}
		else if (src instanceof CommandBlockSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /warps!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "warps" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("List Warps Command"))
			.permission("essentialcmds.warps.list")
			.executor(this).build();
	}
} public class LoreBase extends CommandExecutorBase
{
	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "lore" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Lore Command"))
			.permission("essentialcmds.lore.use")
			.children(getChildrenList(new Set(), new Add(), new Remove()))
			.build();
	}

	@Override
	public CommandResult execute(CommandSource src, CommandContext args) throws CommandException
	{
		return CommandResult.empty();
	}

	static class Set extends CommandExecutorBase
	{
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			String lore = ctx.<String> getOne("lore").get();

			if (src instanceof Player)
			{
				Player player = (Player) src;

				if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent())
				{
					ItemStack stack = player.getItemInHand(HandTypes.MAIN_HAND).get();
					List<String> loreList = Lists.newArrayList();
					loreList.addAll(Arrays.asList(lore.split("\\s*,\\s*")));
					List<Text> loreTextList = Lists.newArrayList();

					for (String l : loreList)
					{
						loreTextList.add(TextSerializers.FORMATTING_CODE.deserialize(l));
					}

					DataTransactionResult dataTransactionResult = stack.offer(Keys.ITEM_LORE, loreTextList);

					if (dataTransactionResult.isSuccessful())
					{
						player.setItemInHand(HandTypes.MAIN_HAND, stack);
						src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Set lore on item."));
					}
					else
					{
						src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Could not set lore on item."));
					}
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be holding an item!"));
				}
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be a player to name items."));
			}
			return CommandResult.success();
		}

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "set" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec
				.builder()
				.description(Text.of("Set Lore Command"))
				.permission("essentialcmds.lore.set")
				.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("lore"))))
				.executor(this)
				.build();
		}
	}

	static class Add extends CommandExecutorBase
	{
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			String lore = ctx.<String> getOne("lore").get();

			if (src instanceof Player)
			{
				Player player = (Player) src;

				if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent())
				{
					ItemStack stack = player.getItemInHand(HandTypes.MAIN_HAND).get();
					LoreData loreData = stack.getOrCreate(LoreData.class).get();
					Text textLore = TextSerializers.FORMATTING_CODE.deserialize(lore);
					List<Text> newLore = loreData.lore().get();
					newLore.add(textLore);
					DataTransactionResult dataTransactionResult = stack.offer(Keys.ITEM_LORE, newLore);

					if (dataTransactionResult.isSuccessful())
					{
						player.setItemInHand(HandTypes.MAIN_HAND, stack);
						src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Added lore to item."));
					}
					else
					{
						src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Could not add lore to item."));
					}
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be holding an item!"));
				}
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be a player to name items."));
			}
			return CommandResult.success();
		}

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "add" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec
				.builder()
				.description(Text.of("Add Lore Command"))
				.permission("essentialcmds.lore.add")
				.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("lore"))))
				.executor(this)
				.build();
		}
	}

	static class Remove extends CommandExecutorBase
	{
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			int number = ctx.<Integer> getOne("number").get();

			if (src instanceof Player)
			{
				Player player = (Player) src;

				if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent())
				{
					ItemStack stack = player.getItemInHand(HandTypes.MAIN_HAND).get();
					LoreData loreData = stack.getOrCreate(LoreData.class).get();
					List<Text> newLore = loreData.lore().get();
					newLore.remove(number - 1);
					DataTransactionResult dataTransactionResult = stack.offer(Keys.ITEM_LORE, newLore);

					if (dataTransactionResult.isSuccessful())
					{
						player.setItemInHand(HandTypes.MAIN_HAND, stack);
						src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Removed lore from item."));
					}
					else
					{
						src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Could not remove lore from item."));
					}
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be holding an item!"));
				}
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be a player to name items."));
			}
			return CommandResult.success();
		}

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "remove" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec
				.builder()
				.description(Text.of("Remove Lore Command"))
				.permission("essentialcmds.lore.remove")
				.arguments(GenericArguments.onlyOne(GenericArguments.integer(Text.of("number"))))
				.executor(this)
				.build();
		}
	}
} public class MailExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		String message = ctx.<String> getOne("message").get();
		String playerName = ctx.<String> getOne("player").get();

		if (src instanceof Player)
		{
			Player p = (Player) src;
			
			if(p.getName().equalsIgnoreCase(playerName))
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot send mail to yourself!"));
				return CommandResult.success();
			}
			
			Game game = EssentialCmds.getEssentialCmds().getGame();

			MailSendEvent event = new MailSendEvent(p, playerName, message);
			game.getEventManager().post(event);

			p.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Sent Mail to " + playerName));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player to send mail!"));
		}
		
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "mail" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec
			.builder()
			.description(Text.of("Mail Command"))
			.permission("essentialcmds.mail.use")
			.arguments(GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.string(Text.of("player")))),
					GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("message")))).executor(this)
			.build();
	}
} public class MailListExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;
			List<Mail> mail = Utils.getMail(player);

			if (mail.isEmpty())
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You have no new mail!"));
				return;
			}

			PaginationService paginationService = Sponge.getServiceManager().provide(PaginationService.class).get();
			List<Text> mailText = Lists.newArrayList();

			for (Mail newM : mail)
			{
				String name = "New mail from " + newM.getSenderName();
				Text item = Text.builder(name).onClick(TextActions.runCommand("/readmail " + (mail.indexOf(newM)))).onHover(TextActions.showText(Text.of(TextColors.WHITE, "Read mail from ", TextColors.GOLD, newM.getSenderName()))).color(TextColors.DARK_AQUA).style(TextStyles.UNDERLINE).build();

				mailText.add(item);
			}

			PaginationList.Builder paginationBuilder = paginationService.builder().contents(mailText).title(Text.of(TextColors.GREEN, "Showing Mail")).padding(Text.of("-"));
			paginationBuilder.sendTo(src);
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /mailist!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "listmail" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("List Mail Command")).permission("essentialcmds.mail.list").executor(this).build();
	}
} public class MailReadExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		int number = ctx.<Integer> getOne("mail no").get();
		if (src instanceof Player)
		{
			Player player = (Player) src;
			List<Mail> mail = Utils.getMail(player);

			if (mail.isEmpty())
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You have no new mail!"));
				return;
			}

			try
			{
				Mail m = mail.get(number);
				Utils.removeMail(m);
				player.sendMessage(Text.of(TextColors.GOLD, "[Mail]: Message from ", TextColors.WHITE, m.getSenderName() + ": ", TextColors.GRAY, m.getMessage()));
			}
			catch (Exception e)
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "That mail does not exist!"));
			}

		}
		else if (src instanceof ConsoleSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /readmail!"));
		}
		else if (src instanceof CommandBlockSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /readmail!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "readmail" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Read Mail Command")).permission("essentialcmds.mail.read").arguments(GenericArguments.onlyOne(GenericArguments.integer(Text.of("mail no")))).executor(this).build();
	}
} public class MeExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		String message = ctx.<String> getOne("message").get();
		Text finalMessage = Text.builder()
			.append(Text.of(TextColors.DARK_GRAY, "* ", TextColors.DARK_RED, src.getName(), TextColors.GREEN, " "))
			.append(TextSerializers.formattingCode('&').deserialize(message))
			.build();

		if (src instanceof Player && EssentialCmds.muteList.contains(((Player) src).getUniqueId()))
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You are muted!"));
			return;
		}

		MessageChannel.TO_ALL.send(finalMessage);
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "me" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Me Command"))
			.permission("essentialcmds.me.use")
			.arguments(GenericArguments.remainingJoinedStrings(Text.of("message")))
			.executor(this)
			.build();
	}
} public class MobSpawnExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		int amount = ctx.<Integer> getOne("amount").get();
		EntityType type = ctx.<EntityType> getOne("mob").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;

			if (!Living.class.isAssignableFrom(type.getEntityClass()))
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "The mob type you inputted is not a living entity."));
				return CommandResult.success();
			}

			this.spawnEntity(getSpawnLocFromPlayerLoc(player).add(0, 1, 0), player, type, amount);
			player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Spawned mob(s)!"));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /mobspawn!"));
		}

		return CommandResult.success();
	}

	public void spawnEntity(Location<World> location, Player player, EntityType type, int amount)
	{
		for (int i = 1; i <= amount; i++)
		{
			Entity entity = location.getExtent().createEntity(type, location.getPosition());
			location.getExtent().spawnEntity(entity, Cause.of(NamedCause.source(SpawnCause.builder().type(SpawnTypes.CUSTOM).build())));
		}
	}

	public Location<World> getSpawnLocFromPlayerLoc(Player player)
	{
		BlockRay<World> playerBlockRay = BlockRay.from(player).blockLimit(350).build();
		BlockRayHit<World> finalHitRay = null;

		while (playerBlockRay.hasNext())
		{
			BlockRayHit<World> currentHitRay = playerBlockRay.next();

			if (!player.getWorld().getBlockType(currentHitRay.getBlockPosition()).equals(BlockTypes.AIR))
			{
				finalHitRay = currentHitRay;
				break;
			}
		}

		Location<World> spawnLocation = null;

		if (finalHitRay == null)
		{
			spawnLocation = player.getLocation();
		}
		else
		{
			spawnLocation = finalHitRay.getLocation();
		}

		return spawnLocation;
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "mobspawn", "entityspawn" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Mob Spawn Command")).permission("essentialcmds.mobspawn.use").arguments(GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.integer(Text.of("amount")))), GenericArguments.onlyOne(GenericArguments.catalogedElement(Text.of("mob"), EntityType.class))).executor(this).build();
	}
} public class MobSpawnerExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		EntityType entityType = ctx.<EntityType> getOne("mob").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;

			ItemStack mobSpawnerStack = ItemStack.builder().itemType(ItemTypes.MOB_SPAWNER).quantity(1).build();
			Optional<MobSpawnerData> mobSpawnerData = mobSpawnerStack.getOrCreate(MobSpawnerData.class);

			if (mobSpawnerData.isPresent())
			{
				MobSpawnerData data = mobSpawnerData.get();
				data.nextEntityToSpawn().set(entityType, null);

				if (mobSpawnerStack.offer(data).isSuccessful())
				{
					player.setItemInHand(HandTypes.MAIN_HAND, mobSpawnerStack);
					player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Created mob spawner."));
				}
				else
				{
					player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Failed to set mob spawner entity."));
				}
			}
			else
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Failed to create mob spawner."));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /mobspawner!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "spawner", "mobspawner" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Mob Spawner Command"))
			.permission("essentialcmds.mobspawner.use")
			.arguments(GenericArguments.onlyOne(GenericArguments.catalogedElement(Text.of("mob"), EntityType.class)))
			.executor(this).build();
	}
} public class MoreExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;

			if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent())
			{
				ItemStack stack = player.getItemInHand(HandTypes.MAIN_HAND).get();
				stack.setQuantity(64);
				player.setItemInHand(HandTypes.MAIN_HAND, stack);
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Stacked the item in your hand!"));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You're not holding anything to stack!"));
			}
		}
		else if (src instanceof ConsoleSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /more!"));
		}
		else if (src instanceof CommandBlockSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /more!"));
		}
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "more", "stack" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("More Command")).permission("essentialcmds.more.use")
			.executor(this).build();
	}
} public class MotdExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext args)
	{
		Game game = EssentialCmds.getEssentialCmds().getGame();
		Server server = game.getServer();
		src.sendMessage(Text.of(TextColors.GOLD, "[MOTD]: ", server.getMotd()));
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "motd" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("MOTD Command")).permission("essentialcmds.motd.use").executor(new MotdExecutor()).build();
	}
} public class MuteExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		Game game = EssentialCmds.getEssentialCmds().getGame();
		Player p = ctx.<Player> getOne("player").get();

		// Uses the TimespanParser.
		Optional<Long> time = ctx.<Long> getOne("time");

		if (time.isPresent())
		{
			Task.Builder taskBuilder = game.getScheduler().createTaskBuilder();
			taskBuilder.execute(() -> {
				if (EssentialCmds.muteList.contains(p.getUniqueId()))
					EssentialCmds.muteList.remove(p.getUniqueId());
			}).delay(time.get(), TimeUnit.SECONDS).name("EssentialCmds - Remove previous mutes").submit(EssentialCmds.getEssentialCmds());
		}

		EssentialCmds.muteList.add(p.getUniqueId());
		Utils.addMute(p.getUniqueId());
		src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Player muted."));
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "mute" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec
				.builder()
				.description(Text.of("Mute Command"))
				.permission("essentialcmds.mute.use")
				.arguments(
						GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.player(Text.of("player"))),
						GenericArguments.onlyOne(GenericArguments.optional(new TimespanParser(Text.of("time"))))))
				.executor(this).build();
	}
} public class NickExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Player player = ctx.<Player>getOne("player").get();
		String nick = ctx.<String>getOne("nick").get();

		if (src instanceof Player && ((Player) src).getUniqueId() != player.getUniqueId() && src.hasPermission("essentialcmds.nick.others"))
		{
			Utils.setNick(nick, player.getUniqueId());
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Nick successfully set!"));
		}
		else if (src instanceof Player && ((Player) src).getUniqueId() != player.getUniqueId())
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You do not have permission to make changes to other player's nicknames.!"));
		}
		else
		{
			Utils.setNick(nick, player.getUniqueId());
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Nick successfully set!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "nick" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec
			.builder()
			.description(Text.of("Nick Command"))
			.permission("essentialcmds.nick.use")
			.arguments(
				GenericArguments.seq(
					GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))),
					GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("nick")))))
			.executor(this).build();
	}
} public class PardonExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Game game = EssentialCmds.getEssentialCmds().getGame();
		User player = ctx.<User> getOne("player").get();

		BanService srv = game.getServiceManager().provide(BanService.class).get();
		if (!srv.isBanned(player.getProfile()))
		{
			src.sendMessage(Text.of(TextColors.RED, "That player is not currently banned."));
			return CommandResult.empty();
		}

		srv.removeBan(srv.getBanFor(player.getProfile()).get());
		src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, player.getName() + " has been unbanned."));
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "pardon", "unban" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Unban Command"))
			.permission("essentialcmds.unban.use")
			.arguments(GenericArguments.onlyOne(new UserParser(Text.of("player"))))
			.executor(this)
			.build();
	}
} public class PlayerFreezeExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		Player targetPlayer = ctx.<Player> getOne("player").get();
		
		if(targetPlayer.equals(src))
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot freeze yourself!"));
			return;
		}
		
		if(EssentialCmds.frozenPlayers.contains(targetPlayer.getUniqueId()))
		{
			EssentialCmds.frozenPlayers.remove(targetPlayer.getUniqueId());
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Un-froze player."));
		}
		else
		{
			EssentialCmds.frozenPlayers.add(targetPlayer.getUniqueId());
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Froze player."));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "playerfreeze", "freezeplayer" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("Player Freeze Command")).permission("essentialcmds.playerfreeze.use")
				.arguments(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))).executor(this).build();
	}
} public class PowertoolExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		if (src instanceof Player)
		{
			Optional<String> optionalCommand = ctx.<String> getOne("command");
			Player player = (Player) src;

			// TODO: Allow players not holding an item to remove their powertool
			if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent())
			{
				if (optionalCommand.isPresent())
				{
					String command = optionalCommand.get();

					// If there is a powertool for the player, remove it.
					EssentialCmds.powertools.stream()
						.filter(p -> p.getPlayer().equals(player) && p.getItemID().equals(player.getItemInHand(HandTypes.MAIN_HAND).get().getItem().getName()))
						.findFirst().ifPresent(x -> EssentialCmds.powertools.remove(x));
					Powertool powertool = new Powertool(player, player.getItemInHand(HandTypes.MAIN_HAND).get().getItem().getName(), command);
					EssentialCmds.powertools.add(powertool);

					player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Successfully bound command ", TextColors.BLUE, command, TextColors.YELLOW, " to ", TextColors.RED, player.getItemInHand(HandTypes.MAIN_HAND).get().getItem().getName(), TextColors.YELLOW, "!"));
				}
				else
				{
					Optional<Powertool> powertoolToRemove = EssentialCmds.powertools.stream()
						.filter(p -> p.getPlayer().equals(player) && p.getItemID().equals(player.getItemInHand(HandTypes.MAIN_HAND).get().getItem().getName()))
						.findFirst();

					if (powertoolToRemove.isPresent())
					{
						EssentialCmds.powertools.remove(powertoolToRemove.get());
						player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Removed command from this powertool!"));
					}
					else
					{
						player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "There is no command assigned to this!"));
					}
				}
			}
			else
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be holding something to use /powertool!"));
			}

		}
		else if (src instanceof ConsoleSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /powertool!"));
		}
		else if (src instanceof CommandBlockSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /powertool!"));
		}
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "powertool", "pt" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Powertool Command")).permission("essentialcmds.powertool.use")
			.arguments(GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("command")))))
			.executor(this).build();
	}
} public class RemoveRuleExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		int ruleNo = ctx.<Integer> getOne("rule number").get();

		if (ruleNo <= Utils.getRules().size() && ruleNo >= 1)
		{
			Utils.removeRule(ruleNo - 1);
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Removed rule."));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "The number you entered is invalid."));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "removerule", "delrule", "deleterule" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("Home Command")).permission("essentialcmds.rules.remove")
				.arguments(GenericArguments.onlyOne(GenericArguments.integer(Text.of("rule number")))).executor(this).build();
	}
} public class RepairExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;

			if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent())
			{
				ItemStack stack = player.getItemInHand(HandTypes.MAIN_HAND).get();

				if (stack.get(DurabilityData.class).isPresent())
				{
					DurabilityData durabilityData = stack.get(DurabilityData.class).get();
					DataTransactionResult transactionResult = stack.offer(Keys.ITEM_DURABILITY, durabilityData.durability().getMaxValue());

					if (transactionResult.isSuccessful())
					{
						player.setItemInHand(HandTypes.MAIN_HAND, stack);
						src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Repaired item in hand."));
					}
					else
					{
						src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Failed to repair item."));
					}
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "The item you're holding is not reparable."));
				}
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be holding something to repair!"));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /repair!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "repair" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Repair Item in Player's Hand")).permission("essentialcmds.repair.use").executor(this)
			.build();
	}
} public class RespondExecutor extends MessageExecutor
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;
			Optional<Message> om = EssentialCmds.recentlyMessaged.stream().filter(m -> m.getRecipient().getUniqueId().toString().equals(player.getUniqueId().toString())).findFirst();
			if (!om.isPresent())
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "No recent messages found!"));
				return;
			}

			ctx.putArg("recipient", om.get().getSender());

			// Logic is the same as in the MessageExecutor now, so hand off to that.
			super.executeAsync(src, ctx);
		}
		else if (src instanceof ConsoleSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player to use /r!"));
		}
		else if (src instanceof CommandBlockSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player to use /r!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "r" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Respond to Message Command")).permission("essentialcmds.message.respond")
			.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("message"))))
			.executor(this).build();
	}
} public class RocketExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> target = ctx.<Player> getOne("target");
		Optional<String> targets = ctx.<String> getOne("targets");
		
		if (!target.isPresent() && !targets.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				Vector3d velocity = null;

				if (ctx.hasAny("hard"))
				{
					velocity = new Vector3d(0, 4, 0);
				}
				else
				{
					velocity = new Vector3d(0, 2, 0);
				}

				player.offer(Keys.VELOCITY, velocity);
				player.sendMessage(Text.of(TextColors.YELLOW, "Rocketed!"));
			}
		}
		else if(targets.isPresent() && src.hasPermission("essentialcmds.rocket.others"))
		{
			String targ = targets.get();
			
			if(targ.equalsIgnoreCase("a") || targ.equalsIgnoreCase("@a"))
			{
				for(Player player : Sponge.getServer().getOnlinePlayers())
				{
					Vector3d velocity = null;

					if (ctx.hasAny("hard"))
					{
						velocity = new Vector3d(0, 4, 0);
					}
					else
					{
						velocity = new Vector3d(0, 2, 0);
					}

					player.offer(Keys.VELOCITY, velocity);
					player.sendMessage(Text.of(TextColors.YELLOW, "You've been rocketed by " + src.getName() + "."));
				}
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Invalid argument supplied!"));
			}
		}
		else if(target.isPresent() && src.hasPermission("essentialcmds.rocket.others"))
		{
			Player player = target.get();
			Vector3d velocity = null;

			if (ctx.hasAny("hard"))
			{
				velocity = new Vector3d(0, 4, 0);
			}
			else
			{
				velocity = new Vector3d(0, 2, 0);
			}

			player.offer(Keys.VELOCITY, velocity);
			player.sendMessage(Text.of(TextColors.YELLOW, "You've been rocketed by " + src.getName() + "."));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You do not have permission to rocket other players!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "rocket" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder()
				.description(Text.of("Rocket Command"))
				.permission("essentialcmds.rocket.use")
				.arguments(GenericArguments.firstParsing(
						GenericArguments.flags()
								.flag("-hard", "h")
								.buildWith(GenericArguments.firstParsing(GenericArguments.optional(GenericArguments.player(Text.of("target"))),
										GenericArguments.optional(GenericArguments.string(Text.of("targets")))))))
				.executor(this)
				.build();
	}
} public class RuleExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		ArrayList<String> rules = Utils.getRules();
		List<Text> ruleText = Lists.newArrayList();
		
		if (rules.isEmpty())
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "The rules for this server are not defined."));
			return;
		}

		for (String rule : rules)
		{
			ruleText.add(Text.of(TextColors.GRAY, (rules.indexOf(rule) + 1) + ". ", TextColors.GOLD, rule));
		}

		PaginationService paginationService = Sponge.getServiceManager().provide(PaginationService.class).get();
		PaginationList.Builder paginationBuilder = paginationService.builder().contents(ruleText).title(Text.of(TextColors.GOLD, "Rules")).padding(Text.of("-"));
		paginationBuilder.sendTo(src);
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "rules" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Rules Command"))
			.permission("essentialcmds.rules.use")
			.executor(this)
			.build();
	}
} public class SetHomeExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		String homeName = ctx.<String> getOne("home name").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;
			Subject subject = player.getContainingCollection().get(player.getIdentifier());
			String homesAllowed = subject.getOption("homes").orElse("");

			if (homesAllowed != null && !homesAllowed.isEmpty())
			{
				if (homesAllowed.equals("unlimited"))
				{
					if (Utils.isHomeInConfig(player.getUniqueId(), homeName))
					{
						Utils.deleteHome(player, homeName);
					}
					Utils.setHome(player.getUniqueId(), player.getTransform(), player.getWorld().getName(), homeName);
					src.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "Home set."));
				}
				else
				{
					Integer allowedHomes = Integer.parseInt(homesAllowed);

					if (Utils.isHomeInConfig(player.getUniqueId(), homeName))
					{
						allowedHomes++;
					}

					if (allowedHomes > Utils.getHomes(player.getUniqueId()).size())
					{
						if (Utils.isHomeInConfig(player.getUniqueId(), homeName))
						{
							Utils.deleteHome(player, homeName);
						}
						Utils.setHome(player.getUniqueId(), player.getTransform(), player.getWorld().getName(), homeName);
						src.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "Home set."));
					}
					else
					{
						src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You have reached the maximum number of homes you are allowed!"));
					}
				}
			}
			else
			{
				if (Utils.isHomeInConfig(player.getUniqueId(), homeName))
				{
					Utils.deleteHome(player, homeName);
				}
				Utils.setHome(player.getUniqueId(), player.getTransform(), player.getWorld().getName(), homeName);
				src.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "Home set."));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /sethome!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "sethome" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Set Home Command"))
			.permission("essentialcmds.home.set")
			.arguments(GenericArguments.onlyOne(GenericArguments.string(Text.of("home name"))))
			.executor(this)
			.build();
	}
} public class SetNameExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		String name = ctx.<String> getOne("name").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;

			if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent())
			{
				ItemStack stack = player.getItemInHand(HandTypes.MAIN_HAND).get();
				Text textName = TextSerializers.FORMATTING_CODE.deserialize(name);
				DataTransactionResult dataTransactionResult = stack.offer(Keys.DISPLAY_NAME, textName);
				
				if(dataTransactionResult.isSuccessful())
				{
					player.setItemInHand(HandTypes.MAIN_HAND, stack);
					src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Set name on item."));
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Could not set name on item."));
				}
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be holding an item!"));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be a player to name items."));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "setitemname", "setname" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("SetName Command"))
			.permission("essentialcmds.setname.use")
			.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("name"))))
			.executor(this)
			.build();
	}
} public class SetWarpExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		String warpName = ctx.<String> getOne("warp name").get();

		if (src instanceof Player)
		{
			if (Utils.isWarpInConfig(warpName))
			{
				Utils.deleteWarp(warpName);
			}
			Player player = (Player) src;
			Utils.setWarp(player.getTransform(), warpName);
			src.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "Warp set."));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /setwarp!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "setwarp" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Set Warp Command"))
			.permission("essentialcmds.warp.set")
			.arguments(GenericArguments.onlyOne(GenericArguments.string(Text.of("warp name"))))
			.executor(this)
			.build();
	}
} public class SkullExecutor extends CommandExecutorBase
{
	private Game game = getEssentialCmds().getGame();

	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> optionalTarget = ctx.<Player> getOne("player");

		if (!optionalTarget.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;

				// Create the Skull
				ItemStack skullStack = ItemStack.builder().itemType(ItemTypes.SKULL).quantity(1).build();

				// Set it to player skull type
				skullStack.offer(Keys.SKULL_TYPE, SkullTypes.PLAYER);

				// Set the owner to the command executor
				skullStack.offer(Keys.REPRESENTED_PLAYER, player.getProfile());

				// Put it in inventory
				player.getInventory().offer(skullStack);

				player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Created skull of your head. Enjoy!"));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /skull!"));
			}
		}
		else
		{
			if (src instanceof Player)
			{
				Player source = (Player) src;
				Player player = optionalTarget.get();

				// Create the Skull
				ItemStack.Builder builder = game.getRegistry().createBuilder(ItemStack.Builder.class);
				ItemStack skullStack = builder.itemType(ItemTypes.SKULL).quantity(1).build();

				// Set it to player skull type
				skullStack.offer(Keys.SKULL_TYPE, SkullTypes.PLAYER);

				// Set the owner to the specified player
				skullStack.offer(Keys.REPRESENTED_PLAYER, player.getProfile());

				// Put it in inventory
				source.getInventory().offer(skullStack);

				source.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Created skull of player's head. Enjoy!"));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /skull!"));
			}
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "skull", "playerskull", "head" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Skull Command"))
			.permission("essentialcmds.skull.use")
			.arguments(GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))))
			.executor(this)
			.build();
	}
} public class SlapExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> target = ctx.<Player> getOne("target");
		Optional<String> targets = ctx.<String> getOne("targets");

		Random random = new Random();

		if (!target.isPresent() && !targets.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				Vector3d velocity = null;

				if (ctx.hasAny("v"))
				{
					velocity = new Vector3d(random.nextDouble() * 10.0 - 5, random.nextDouble() * 10, random.nextDouble() * 10.0 - 5);
				}
				else if (ctx.hasAny("hard"))
				{
					velocity = new Vector3d(random.nextDouble() * 5.0 - 2.5, random.nextDouble() * 5, random.nextDouble() * 5.0 - 2.5);
				}
				else
				{
					velocity = new Vector3d(random.nextDouble() * 2.0 - 1, random.nextDouble() * 1, random.nextDouble() * 2.0 - 1);
				}

				player.offer(Keys.VELOCITY, velocity);

				if (ctx.hasAny("damage"))
					player.offer(Keys.HEALTH, Math.max(0, player.getHealthData().health().get() - 1));

				player.sendMessage(Text.of(TextColors.YELLOW, "Slapped!"));
			}
		}
		else if (targets.isPresent() && src.hasPermission("essentialcmds.slap.others"))
		{
			String targ = targets.get();

			if (targ.equalsIgnoreCase("a") || targ.equalsIgnoreCase("@a"))
			{
				for (Player player : Sponge.getServer().getOnlinePlayers())
				{
					Vector3d velocity = null;

					if (ctx.hasAny("v"))
					{
						velocity = new Vector3d(random.nextDouble() * 10.0 - 5, random.nextDouble() * 10, random.nextDouble() * 10.0 - 5);
					}
					else if (ctx.hasAny("hard"))
					{
						velocity = new Vector3d(random.nextDouble() * 5.0 - 2.5, random.nextDouble() * 5, random.nextDouble() * 5.0 - 2.5);
					}
					else
					{
						velocity = new Vector3d(random.nextDouble() * 2.0 - 1, random.nextDouble() * 1, random.nextDouble() * 2.0 - 1);
					}

					player.offer(Keys.VELOCITY, velocity);

					if (ctx.hasAny("v"))
						player.offer(Keys.HEALTH, Math.max(0, player.getHealthData().health().get() - 1));

					player.sendMessage(Text.of(TextColors.YELLOW, "You've been slapped by " + src.getName() + "."));
				}
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Invalid argument supplied!"));
			}
		}
		else if (target.isPresent() && src.hasPermission("essentialcmds.slap.others"))
		{
			Player player = target.get();
			Vector3d velocity = null;

			if (ctx.hasAny("v"))
			{
				velocity = new Vector3d(random.nextDouble() * 10.0 - 5, random.nextDouble() * 10, random.nextDouble() * 10.0 - 5);
			}
			else if (ctx.hasAny("hard"))
			{
				velocity = new Vector3d(random.nextDouble() * 5.0 - 2.5, random.nextDouble() * 5, random.nextDouble() * 5.0 - 2.5);
			}
			else
			{
				velocity = new Vector3d(random.nextDouble() * 2.0 - 1, random.nextDouble() * 1, random.nextDouble() * 2.0 - 1);
			}

			player.offer(Keys.VELOCITY, velocity);

			if (ctx.hasAny("v"))
				player.offer(Keys.HEALTH, Math.max(0, player.getHealthData().health().get() - 1));

			player.sendMessage(Text.of(TextColors.YELLOW, "You've been slapped by " + src.getName() + "."));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You do not have permission to slap other players."));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "slap" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Slap Command"))
			.permission("essentialcmds.slap.use")
			.arguments(GenericArguments.firstParsing(GenericArguments.flags()
				.flag("-v", "v")
				.flag("-damage", "d")
				.flag("-hard", "h")
				.buildWith(GenericArguments.firstParsing(GenericArguments.optional(GenericArguments.player(Text.of("target"))), GenericArguments.optional(GenericArguments.string(Text.of("targets")))))))
			.executor(this)
			.build();
	}
} public class StopExecutor extends CommandExecutorBase
{
	@Override
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<String> stopMessage = ctx.<String> getOne("reason");

		if (stopMessage.isPresent())
		{
			Sponge.getServer().shutdown(TextSerializers.FORMATTING_CODE.deserialize(stopMessage.get()));
		}
		else
		{
			Sponge.getServer().shutdown();
		}

		src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Stopped server."));
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "stop", "shutdown" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Stop Command"))
			.permission("essentialcmds.stop.use")
			.arguments(GenericArguments.onlyOne(GenericArguments.optional(GenericArguments.remainingJoinedStrings(Text.of("reason")))))
			.executor(this)
			.build();
	}
} public class SudoExecutor extends CommandExecutorBase
{
	Game game = getEssentialCmds().getGame();

	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Player p = ctx.<Player> getOne("player").get();
		String command = ctx.<String> getOne("command").get();
		if (src instanceof Player)
		{
			Player player = (Player) src;
			CommandManager cmdService = game.getCommandManager();
			if (!(p.hasPermission("sudo.exempt")))
			{
				cmdService.process(p, command);
				player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.GOLD, "Forcing " + p.getName() + " to run /" + command));
				p.sendMessage(Text.of(TextColors.GOLD, "[Sudo]: ", TextColors.WHITE, player.getName() + " has forced you to run /" + command));
			}
			else
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "This player is exempt from sudo!"));
			}
		}
		else if (src instanceof ConsoleSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /sudo!"));
		}
		else if (src instanceof CommandBlockSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /sudo!"));
		}
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "sudo" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec
				.builder()
				.description(Text.of("Sudo Command"))
				.permission("essentialcmds.sudo.use")
				.arguments(
					GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.player(Text.of("player"))),
					GenericArguments.remainingJoinedStrings(Text.of("command")))).executor(this).build();
	}
} public class TPAExecutor extends AsyncCommandExecutorBase
{
	private Game game = getEssentialCmds().getGame();

	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		Player recipient = ctx.<Player> getOne("player").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;
			
			if (recipient == player)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot teleport to yourself!"));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Requested to be teleported to " + recipient.getName() + "."));
				game.getEventManager().post(new TPAEvent(player, recipient));
			}
		}
		else if (src instanceof ConsoleSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /tpa!"));
		}
		else if (src instanceof CommandBlockSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /tpa!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "tpa" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("TPA Command")).permission("essentialcmds.tpa.use")
				.arguments(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))).executor(this).build();
	}
} public class TPAHereExecutor extends AsyncCommandExecutorBase
{
	private Game game = getEssentialCmds().getGame();

	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		Player recipient = ctx.<Player> getOne("player").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;
			if (recipient == player)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot teleport to yourself!"));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Requested for " + recipient.getName() + " to be teleported to you"));
				game.getEventManager().post(new TPAHereEvent(player, recipient));
			}
		}
		else if (src instanceof ConsoleSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /tpahere!"));
		}
		else if (src instanceof CommandBlockSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /tpahere!"));
		}
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "tpahere" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("TPA Here Command")).permission("essentialcmds.tpahere.use")
				.arguments(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))).executor(this)
				.build();
	}
} public class TPChunkExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		int x = ctx.<Integer> getOne("x").get();
		int z = ctx.<Integer> getOne("z").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;
			Utils.setLastTeleportOrDeathLocation(player.getUniqueId(), player.getLocation());

			if (Sponge.getServer().getChunkLayout().isValidChunk(new Vector3i(x, 0, z)))
			{
				Location<World> location = new Location<World>(player.getWorld(), Sponge.getServer().getChunkLayout().forceToWorld(new Vector3i(x, 0, z)));
				player.setLocation(location);
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to chunk."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Invalid chunk!"));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot teleport, you are not a player!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "tpchunk" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec
			.builder()
			.description(Text.of("Teleport Chunk Command"))
			.permission("essentialcmds.teleport.chunk.use")
			.arguments(GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.integer(Text.of("x"))), GenericArguments.onlyOne(GenericArguments.integer(Text.of("z")))))
			.executor(this).build();
	}
} public class TPHereExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Player recipient = ctx.<Player> getOne("player").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;
			if (recipient == player)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot teleport to yourself!"));
			}
			else
			{
				player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.WHITE, recipient.getName() + " has been teleported to your location!"));
				recipient.sendMessage(Text.of(TextColors.GREEN, player.getName(), TextColors.WHITE, " has teleported you to their location!"));
				recipient.setLocation(player.getLocation());
			}

		}
		else if (src instanceof ConsoleSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /tphere!"));
		}
		else if (src instanceof CommandBlockSource)
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /tphere!"));
		}
		
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "tphere" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("TP Here Command")).permission("essentialcmds.tphere.use")
				.arguments(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))).executor(this)
				.build();
	}
} public class TakeExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Player target = ctx.<Player> getOne("target").get();

		if (src instanceof Player)
		{
			Player player = (Player) src;

			if (target.getItemInHand(HandTypes.MAIN_HAND).isPresent())
			{
				player.getInventory().offer(target.getItemInHand(HandTypes.MAIN_HAND).get());
				target.setItemInHand(HandTypes.MAIN_HAND, null);
				player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Took " + target.getName() + "'s held item."));
			}
			else
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Target is not holding anything!"));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player to take other players items!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "take" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("Take Command")).permission("essentialcmds.take.use")
				.arguments(GenericArguments.onlyOne(GenericArguments.player(Text.of("target")))).executor(this).build();
	}
} public class TeleportExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> optionalPlayer = ctx.<Player> getOne("player");
		Optional<Player> optionalTarget = ctx.<Player> getOne("target");

		if (optionalPlayer.isPresent())
		{
			Player player = optionalPlayer.get();

			if (optionalTarget.isPresent())
			{
				if (src.hasPermission("essentialcmds.teleport.others"))
				{
					Utils.setLastTeleportOrDeathLocation(player.getUniqueId(), player.getLocation());
					player.setLocation(optionalTarget.get().getLocation());
					src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported player " + player.getName() + " to " + optionalTarget.get().getName()));
					player.sendMessage(Text.of(TextColors.GOLD, "You have been teleported to " + optionalTarget.get().getName() + " by " + src.getName()));
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You do not have permission to teleport other players."));
				}
			}
			else
			{
				if (src instanceof Player)
				{
					Player targ = (Player) src;
					targ.setLocation(player.getLocation());
					targ.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to player " + player.getName()));
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot teleport, you are not a player!"));
				}
			}
		}
		else
		{
			int x = ctx.<Integer> getOne("x").get();
			int y = ctx.<Integer> getOne("y").get();
			int z = ctx.<Integer> getOne("z").get();
			Optional<String> optionalWorld = ctx.<String> getOne("world");
			Player target = null;

			if (optionalTarget.isPresent() && src.hasPermission("essentialcmds.teleport.others"))
			{
				target = optionalTarget.get();
			}
			else if (optionalTarget.isPresent())
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You do not have permission to teleport other players."));
				return CommandResult.success();
			}
			else
			{
				if (src instanceof Player)
				{
					target = (Player) src;
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot teleport, you are not a player!"));
					return CommandResult.success();
				}
			}

			if (!optionalWorld.isPresent())
			{
				Location<World> location = new Location<>(target.getWorld(), x, y, z);
				target.setLocation(location);
				target.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to location!"));
			}
			else
			{
				Optional<World> world = Sponge.getServer().getWorld(optionalWorld.get());

				if (world.isPresent())
				{
					Location<World> location = new Location<>(world.get(), x, y, z);

					if (!target.getWorld().getUniqueId().equals(world.get().getUniqueId()))
					{
						target.transferToWorld(world.get().getUniqueId(), location.getPosition());
					}
					else
					{
						target.setLocation(location);
					}

					target.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to location!"));
				}
				else
				{
					target.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "World not found!"));
				}
			}
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "tp", "teleport" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec
			.builder()
			.description(Text.of("Teleport Command"))
			.permission("essentialcmds.teleport.use")
			.arguments(GenericArguments.firstParsing(
				GenericArguments.seq(
					GenericArguments.onlyOne(GenericArguments.player(Text.of("player"))), 
					GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("target"))))), 
				GenericArguments.seq(
					GenericArguments.onlyOne(GenericArguments.integer(Text.of("x"))),
					GenericArguments.onlyOne(GenericArguments.integer(Text.of("y"))),
					GenericArguments.onlyOne(GenericArguments.integer(Text.of("z"))), 
					GenericArguments.optional(GenericArguments.string(Text.of("world"))),
					GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("target")))))))
			.executor(this)
			.build();
	}
} public class TeleportPosExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> p = ctx.<Player> getOne("player");
		World world = null;
		if (ctx.hasAny("world")) {
			Optional<WorldProperties> optionalWorldProperties = ctx.<WorldProperties> getOne("world");
			WorldProperties worldProperties = optionalWorldProperties.orElse(null);
			if (worldProperties != null) {
				// check if world is loaded
				Optional<World> optionalWorld = Sponge.getServer().getWorld(worldProperties.getUniqueId());
				world = optionalWorld.orElse(null);
				if (world == null) {
					// attempt to load world
					world = Sponge.getServer().loadWorld(worldProperties).orElse(null);
					if (world == null) {
						src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Could not load world " + worldProperties.getWorldName() + "."));
						return CommandResult.success();
					}
				}
			}
		} else {
			if (p.isPresent()) {
				world = p.get().getWorld();
			} else if (src instanceof Player) {
				world = ((Player) src).getWorld();
			} else {
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "No valid world could be found!"));
				return CommandResult.success();
			}
		}

		int x = ctx.<Integer> getOne("x").get();
		int y = ctx.<Integer> getOne("y").get();
		int z = ctx.<Integer> getOne("z").get();

		if (p.isPresent())
		{
			if (src.hasPermission("teleport.pos.others"))
			{
				Utils.setLastTeleportOrDeathLocation(p.get().getUniqueId(), p.get().getLocation());
				p.get().setLocation(new Location<>(world, x, y, z));
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported player " + p.get().getName() + " to " + x + "," + y + "," + z + "."));
				p.get().sendMessage(Text.of(TextColors.GOLD, "You have been teleported by " + src.getName()));
			}
		}
		else
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				Utils.setLastTeleportOrDeathLocation(player.getUniqueId(), player.getLocation());
				player.setLocation(new Location<>(world, x, y, z));
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to coords."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot teleport, you are not a player!"));
			}
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "tppos", "teleportpos", "teleportposition" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Teleport Position Command")).permission("essentialcmds.teleport.pos.use").arguments(GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.integer(Text.of("x"))), GenericArguments.onlyOne(GenericArguments.integer(Text.of("y"))), GenericArguments.onlyOne(GenericArguments.integer(Text.of("z"))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.world(Text.of("world")))))).executor(this).build();
	}
} public class TempBanExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Game game = EssentialCmds.getEssentialCmds().getGame();
		User player = ctx.<User> getOne("player").get();
		String time = ctx.<String> getOne("time").get();
		String reason = ctx.<String> getOne("reason").orElse("The BanHammer has spoken!");

		BanService srv = game.getServiceManager().provide(BanService.class).get();

		if (srv.isBanned(player.getProfile()))
		{
			src.sendMessage(Text.of(TextColors.RED, "That player has already been banned."));
			return CommandResult.empty();
		}

		srv.addBan(Ban.builder()
			.type(BanTypes.PROFILE)
			.source(src).profile(player.getProfile())
			.expirationDate(getInstantFromString(time))
			.reason(TextSerializers.formattingCode('&').deserialize(reason))
			.build());

		if (player.isOnline())
		{
			player.getPlayer().get().kick(Text.builder()
				.append(Text.of(TextColors.DARK_RED, "You have been tempbanned!\n", TextColors.RED, "Reason: "))
				.append(TextSerializers.formattingCode('&').deserialize(reason), Text.of("\n"))
				.append(Text.of(TextColors.GOLD, "Time: ", TextColors.GRAY, getFormattedString(time)))
				.build());
		}

		src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, player.getName() + " has been banned."));
		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "tempban" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec
			.builder()
			.description(Text.of("TempBan Command"))
			.permission("essentialcmds.tempban.use")
			.arguments(GenericArguments.seq(GenericArguments.onlyOne(new UserParser(Text.of("player"))), GenericArguments.onlyOne(GenericArguments.string(Text.of("time"))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("reason"))))))
			.executor(this)
			.build();
	}

	public Instant getInstantFromString(String time)
	{
		if (time.contains(":"))
		{
			String[] tokens = time.split(":");
			int hours = Integer.parseInt(tokens[0]);
			int minutes = Integer.parseInt(tokens[1]);
			int seconds = Integer.parseInt(tokens[2]);
			int durationInSec = 3600 * hours + 60 * minutes + seconds;
			return Instant.ofEpochSecond((System.currentTimeMillis()) / 1000L + durationInSec);
		}
		else
		{
			return Instant.ofEpochSecond((System.currentTimeMillis()) / 1000L + Integer.parseInt(time));
		}
	}
	
	public String getFormattedString(String time)
	{
		if (time.contains(":"))
		{
			String[] tokens = time.split(":");
			int hours = Integer.parseInt(tokens[0]);
			int minutes = Integer.parseInt(tokens[1]);
			int seconds = Integer.parseInt(tokens[2]);
			return (hours + " hours, " + minutes + " minutes, and " + seconds + " seconds.");
		}
		else
		{
			return (Integer.parseInt(time) + " seconds.");
		}
	}
} public class ThruExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;

			BlockRay<World> playerBlockRay = BlockRay.from(player).blockLimit(25).build();
			BlockRayHit<World> finalHitRay = null;
			Location<World> location = null;

			while (playerBlockRay.hasNext())
			{
				BlockRayHit<World> currentHitRay = playerBlockRay.next();

				if (finalHitRay != null && player.getWorld().getBlockType(currentHitRay.getBlockPosition()).equals(BlockTypes.AIR))
				{
					location = currentHitRay.getLocation();
					break;
				}
				else if (player.getWorld().getBlockType(currentHitRay.getBlockPosition()).equals(BlockTypes.AIR))
				{
					continue;
				}
				else
				{
					finalHitRay = currentHitRay;
				}
			}

			if (finalHitRay != null && location != null)
			{
				if (player.setLocationSafely(location))
				{
					player.sendMessage(Text.of(TextColors.LIGHT_PURPLE, "Whoosh!"));
				}
				else
				{
					player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "No free spot ahead of you found."));
				}
			}
			else if (finalHitRay == null)
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You are not facing a wall."));
			}
			else
			{
				player.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "No free spot ahead of you found."));
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /thru!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "through", "thru" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Thru Command"))
			.permission("essentialcmds.thru.use")
			.executor(this)
			.build();
	}
} public class UnmuteExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		Player p = ctx.<Player> getOne("player").get();

		if (EssentialCmds.muteList.remove(p.getUniqueId()))
		{
			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Player un-muted."));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "This player is not muted."));
		}

		Utils.removeMute(p.getUniqueId());
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "unmute" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("Unmute Command")).permission("essentialcmds.unmute.use")
				.arguments(GenericArguments.onlyOne(GenericArguments.player(Text.of("player")))).executor(this)
				.build();
	}
} public class VanishExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<Player> target = ctx.<Player> getOne("player");

		if (!target.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;

				if (player.get(Keys.INVISIBLE).isPresent() && !player.get(Keys.INVISIBLE).get())
				{
					player.offer(Keys.INVISIBLE, true);
					player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "You are now invisible."));
				}
				else if (player.get(Keys.INVISIBLE).isPresent() && player.get(Keys.INVISIBLE).get())
				{
					player.offer(Keys.INVISIBLE, false);
					player.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "You are now visible."));
				}
			}
			else if (src instanceof ConsoleSource)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /vanish!"));
			}
			else if (src instanceof CommandBlockSource)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /vanish!"));
			}
		}
		else if (target.isPresent() && src.hasPermission("essentialcmds.vanish.others"))
		{
			Player player = target.get();

			if (player.get(Keys.INVISIBLE).isPresent() && !player.get(Keys.INVISIBLE).get())
			{
				player.offer(Keys.INVISIBLE, true);
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Set player invisible."));
				player.sendMessage(Text.of(TextColors.GOLD, src.getName(), " has set you ", TextColors.GRAY, "invisible."));
			}
			else if (player.get(Keys.INVISIBLE).isPresent() && player.get(Keys.INVISIBLE).get())
			{
				player.offer(Keys.INVISIBLE, false);
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Set player visible."));
				player.sendMessage(Text.of(TextColors.GOLD, src.getName(), " has set you ", TextColors.GRAY, "visible."));
			}
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "vanish" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec.builder().description(Text.of("Vanish Command")).permission("essentialcmds.vanish.use")
			.arguments(GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player"))))).executor(this).build();
	}
} public class WarpExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		String warpName = ctx.<String> getOne("warp name").get();
		Optional<Player> optionalPlayer = ctx.<Player> getOne("player");

		if (!optionalPlayer.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;

				if (Utils.isWarpInConfig(warpName))
				{
					Transform<World> warpLocation = Utils.getWarp(warpName);

					if (player.hasPermission("essentialcmds.warp.use." + warpName))
					{
						if (Utils.isTeleportCooldownEnabled() && !player.hasPermission("essentialcmds.teleport.cooldown.override"))
						{
							EssentialCmds.teleportingPlayers.add(player.getUniqueId());
							src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleporting to last location. Please wait " + Utils.getTeleportCooldown() + " seconds."));
							Sponge.getScheduler().createTaskBuilder().execute(() -> {
								if (EssentialCmds.teleportingPlayers.contains(player.getUniqueId()))
								{
									Utils.setLastTeleportOrDeathLocation(player.getUniqueId(), player.getLocation());

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

									src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to warp " + Utils.getConfigWarpName(warpName)));
									EssentialCmds.teleportingPlayers.remove(player.getUniqueId());
								}
							}).delay(Utils.getTeleportCooldown(), TimeUnit.SECONDS).name("EssentialCmds - Back Timer").submit(Sponge.getGame().getPluginManager().getPlugin(PluginInfo.ID).get().getInstance().get());
						}
						else
						{
							Utils.setLastTeleportOrDeathLocation(player.getUniqueId(), player.getLocation());

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

							src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to warp " + warpName));
						}
					}
					else
					{
						src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You do not have permission to use this warp!"));
					}
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Warp " + warpName + " does not exist!"));
				}
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /warp!"));
			}
		}
		else
		{
			Player player = optionalPlayer.get();
			Transform<World> warpLocation = Utils.getWarp(warpName);

			if (Utils.isWarpInConfig(warpName) && warpLocation != null)
			{
				if (src.hasPermission("essentialcmds.warp.use." + warpName) && src.hasPermission("essentialcmds.warp.others"))
				{
					Utils.setLastTeleportOrDeathLocation(player.getUniqueId(), player.getLocation());

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

					src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to warp " + warpName));
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You do not have permission to use this warp!"));
				}
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Warp " + warpName + " does not exist!"));
			}
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "warp" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("Warp Command"))
			.permission("essentialcmds.warp.use")
			.arguments(GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.string(Text.of("warp name"))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player"))))))
			.executor(this)
			.build();
	}
} public class WeatherExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		String weatherString = ctx.<String> getOne("weather").get();
		Optional<Integer> duration = ctx.<Integer> getOne("duration");

		if (src instanceof Player)
		{
			Player player = (Player) src;

			Weather weather;

			if (weatherString.toLowerCase().equals("clear") || weatherString.toLowerCase().equals("sun"))
			{
				weather = Weathers.CLEAR;
				player.sendMessage(Text.of(TextColors.GOLD, "Changing weather to ", TextColors.GRAY, "sunny."));
			}
			else if (weatherString.toLowerCase().equals("rain"))
			{
				weather = Weathers.RAIN;
				player.sendMessage(Text.of(TextColors.GOLD, "Changing weather to ", TextColors.GRAY, "rain."));
			}
			else if (weatherString.toLowerCase().equals("storm") || weatherString.toLowerCase().equals("thunderstorm"))
			{
				weather = Weathers.THUNDER_STORM;
				player.sendMessage(Text.of(TextColors.GOLD, "Changing weather to ", TextColors.GRAY, "storm."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Input invalid: " + weatherString));
				return CommandResult.success();
			}

			if (duration.isPresent())
			{
				player.getWorld().setWeather(weather, duration.get());
			}
			else
			{
				player.getWorld().setWeather(weather);
			}
			return CommandResult.success();
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be a in-game player to do /weather!"));
			return CommandResult.success();
		}
	}

	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "weather" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec() {
		return CommandSpec
				.builder()
				.description(Text.of("Weather Command"))
				.permission("essentialcmds.weather.use")
				.arguments(GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.string(Text.of("weather")))),
						GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.integer(Text.of("duration")))))
				.executor(this).build();
	}
} public class WhoisExecutor extends AsyncCommandExecutorBase
{
	@Override
	public void executeAsync(CommandSource src, CommandContext ctx)
	{
		Optional<Player> optPlayer = ctx.<Player> getOne("player");
		Optional<String> optPlayerName = ctx.<String> getOne("player name");

		if (optPlayer.isPresent())
		{
			Player player = optPlayer.get();
			src.sendMessage(Text.of(TextColors.GOLD, "Real Name: ", TextColors.GRAY, player.getName()));
			src.sendMessage(Text.of(TextColors.GOLD, "UUID: ", TextColors.GRAY, player.getUniqueId().toString()));

			if (Sponge.getServer().getPlayer(player.getUniqueId()).isPresent())
				src.sendMessage(Text.of(TextColors.GOLD, "Current Ontime: ", TextColors.GRAY, getCurrentOnTime(player)));
			else
				src.sendMessage(Text.of(TextColors.GOLD, "Last Time Online: ", TextColors.GRAY, player.getJoinData().lastPlayed().get().toString()));

			src.sendMessage(Text.of(TextColors.GOLD, "Current World: ", TextColors.GRAY, player.getWorld().getName()));
		}
		else if (optPlayerName.isPresent())
		{
			Optional<Player> optionalPlayer = Sponge.getServer().getPlayer(optPlayerName.get());

			if (optionalPlayer.isPresent())
			{
				Player player = optionalPlayer.get();
				src.sendMessage(Text.of(TextColors.GOLD, "Real Name: ", TextColors.GRAY, player.getName()));
				src.sendMessage(Text.of(TextColors.GOLD, "UUID: ", TextColors.GRAY, player.getUniqueId().toString()));

				if (Sponge.getServer().getPlayer(player.getUniqueId()).isPresent())
					src.sendMessage(Text.of(TextColors.GOLD, "Current Ontime: ", TextColors.GRAY, getCurrentOnTime(player)));
				else
					src.sendMessage(Text.of(TextColors.GOLD, "Last Time Online: ", TextColors.GRAY, player.getJoinData().lastPlayed().get().toString()));

				src.sendMessage(Text.of(TextColors.GOLD, "Current World: ", TextColors.GRAY, player.getWorld().getName()));
			}
			else
			{
				Player foundPlayer = null;

				for (Player player : Sponge.getServer().getOnlinePlayers())
				{
					if (Utils.getNick(player).equalsIgnoreCase(optPlayerName.get()))
					{
						foundPlayer = player;
						break;
					}
				}

				if (foundPlayer == null)
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Player not found."));
				}
				else
				{
					src.sendMessage(Text.of(TextColors.GOLD, "Real Name: ", TextColors.GRAY, foundPlayer.getName()));
					src.sendMessage(Text.of(TextColors.GOLD, "UUID: ", TextColors.GRAY, foundPlayer.getUniqueId().toString()));

					if (Sponge.getServer().getPlayer(foundPlayer.getUniqueId()).isPresent())
					{
						src.sendMessage(Text.of(TextColors.GOLD, "Current Ontime: ", TextColors.GRAY, getCurrentOnTime(foundPlayer)));
					}
					else
					{
						src.sendMessage(Text.of(TextColors.GOLD, "Last Time Online: ", TextColors.GRAY, foundPlayer.getJoinData().lastPlayed().get().toString()));
					}

					src.sendMessage(Text.of(TextColors.GOLD, "Current World: ", TextColors.GRAY, foundPlayer.getWorld().getName()));
				}
			}
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You did not specify any arguments."));
		}
	}

	public String getCurrentOnTime(Player player)
	{
		Instant currentTime = Instant.now();
		Instant lastJoined = player.getJoinData().lastPlayed().get();

		long diffInHours = lastJoined.until(currentTime, ChronoUnit.HOURS);
		long diffInMinutes = lastJoined.until(currentTime, ChronoUnit.MINUTES);
		long diffInSeconds = lastJoined.until(currentTime, ChronoUnit.SECONDS);

		return ("In Hours: | " + diffInHours + " | In Minutes: | " + diffInMinutes + " | In Seconds: | " + diffInSeconds + " |");
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "whois", "realname", "seen" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("WhoIs Command")).permission("essentialcmds.whois.use").arguments(GenericArguments.firstParsing(GenericArguments.onlyOne(GenericArguments.player(Text.of("player"))), GenericArguments.onlyOne(GenericArguments.string(Text.of("player name"))))).executor(this).build();
	}
} public class CreateWorldExecutor extends WorldsBase.Create
{
	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "createworld" };
	}
} public class DeleteWorldExecutor extends WorldsBase.Delete
{
	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "deleteworld", "delworld" };
	}
} public class ListWorldExecutor extends WorldsBase.List
{
	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "worlds" };
	}
} public class LoadWorldExecutor extends WorldsBase.Load
{
	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "loadworld", "importworld" };
	}
} public class SetFirstSpawnExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;
			Utils.setFirstSpawn(player.getTransform(), player.getWorld().getName());
			src.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "Set the spawn for new players to your location."));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /setfirstspawn!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "setfirstspawn" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Set First Spawn Command"))
			.permission("essentialcmds.firstspawn.set")
			.executor(this)
			.build();
	}
} public class SetSpawnExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		if (src instanceof Player)
		{
			Player player = (Player) src;
			Utils.setSpawn(player.getTransform(), player.getWorld().getName());
			player.getWorld().getProperties().setSpawnPosition(player.getLocation().getBlockPosition());
			src.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "Spawn set."));
		}
		else
		{
			src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /setspawn!"));
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "setspawn" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder().description(Text.of("Set Spawn Command")).permission("essentialcmds.spawn.set").executor(this).build();
	}
} public class TeleportWorldExecutor extends WorldsBase.Teleport
{
	@Nonnull
	@Override
	public String[] getAliases() {
		return new String[] { "tpworld" };
	}
} public class WorldInfoExecutor extends CommandExecutorBase
{
	public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
	{
		Optional<String> worldName = ctx.<String> getOne("world name");

		if (!worldName.isPresent())
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				World world = player.getWorld();

				player.sendMessage(Text.of(TextColors.GOLD, "World UUID: ", TextColors.GRAY, world.getProperties().getUniqueId()));
				player.sendMessage(Text.of(TextColors.GOLD, "Difficulty: ", TextColors.GRAY, world.getProperties().getDifficulty()));
				player.sendMessage(Text.of(TextColors.GOLD, "Dimension Type: ", TextColors.GRAY, world.getProperties().getDimensionType().getName()));
				player.sendMessage(Text.of(TextColors.GOLD, "Gamemode: ", TextColors.GRAY, world.getProperties().getGameMode()));
				player.sendMessage(Text.of(TextColors.GOLD, "Seed: ", TextColors.GRAY, world.getProperties().getSeed()));
				player.sendMessage(Text.of(TextColors.GOLD, "World Time: ", TextColors.GRAY, world.getProperties().getWorldTime()));
				player.sendMessage(Text.of(TextColors.GOLD, "Are commands allowed: ", TextColors.GRAY, world.getProperties().areCommandsAllowed()));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player to use this command."));
			}
		}
		else
		{
			World world = Sponge.getServer().getWorld(worldName.get()).orElse(null);

			if (world != null)
			{
				src.sendMessage(Text.of(TextColors.GOLD, "World UUID: ", TextColors.GRAY, world.getProperties().getUniqueId()));
				src.sendMessage(Text.of(TextColors.GOLD, "Difficulty: ", TextColors.GRAY, world.getProperties().getDifficulty()));
				src.sendMessage(Text.of(TextColors.GOLD, "Dimension Type: ", TextColors.GRAY, world.getProperties().getDimensionType()));
				src.sendMessage(Text.of(TextColors.GOLD, "Gamemode: ", TextColors.GRAY, world.getProperties().getGameMode()));
				src.sendMessage(Text.of(TextColors.GOLD, "Seed: ", TextColors.GRAY, world.getProperties().getSeed()));
				src.sendMessage(Text.of(TextColors.GOLD, "World Time: ", TextColors.GRAY, world.getProperties().getWorldTime()));
				src.sendMessage(Text.of(TextColors.GOLD, "Are commands allowed: ", TextColors.GRAY, world.getProperties().areCommandsAllowed()));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "World not found!"));
			}
		}

		return CommandResult.success();
	}

	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "worldinfo" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("WorldInfo Command"))
			.permission("essentialcmds.worldinfo.use")
			.arguments(GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("world name")))))
			.executor(this)
			.build();
	}
} public class WorldsBase extends CommandExecutorBase
{
	@Nonnull
	@Override
	public String[] getAliases()
	{
		return new String[] { "world" };
	}

	@Nonnull
	@Override
	public CommandSpec getSpec()
	{
		return CommandSpec.builder()
			.description(Text.of("World Command"))
			.permission("essentialcmds.world.use")
			.children(getChildrenList(new List(), new Gamerule(), new ListGamerules(), new Teleport(), new Spawn(), new SetSpawn(), new Load(), new Create(), new Delete(), new SetDifficulty(), new SetGamemode()))
			.build();
	}

	@Override
	public CommandResult execute(CommandSource src, CommandContext args) throws CommandException
	{
		return CommandResult.empty();
	}

	static class Create extends CommandExecutorBase
	{
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			String name = ctx.<String> getOne("name").get();
			String dimensionInput = ctx.<String> getOne("dimension").get();
			String generatorInput = ctx.<String> getOne("generator").get();
			String difficultyInput = ctx.<String> getOne("difficulty").get();
			GameMode gamemode = ctx.<GameMode> getOne("gamemode").get();
			Difficulty difficulty = null;
			DimensionType dimension = null;
			GeneratorType generator = null;

			if (Sponge.getRegistry().getType(DimensionType.class, dimensionInput).isPresent())
			{
				dimension = Sponge.getRegistry().getType(DimensionType.class, dimensionInput).get();
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Dimension type specified not found."));
				return CommandResult.success();
			}

			if (Sponge.getRegistry().getType(GeneratorType.class, generatorInput).isPresent())
			{
				generator = Sponge.getRegistry().getType(GeneratorType.class, generatorInput).get();
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Generator type specified not found."));
				return CommandResult.success();
			}

			if (Sponge.getRegistry().getType(Difficulty.class, difficultyInput).isPresent())
			{
				difficulty = Sponge.getRegistry().getType(Difficulty.class, difficultyInput).get();
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Difficulty specified not found."));
				return CommandResult.success();
			}

			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Beginning creation of world."));

			WorldArchetype worldSettings = WorldArchetype.builder()
				.enabled(true)
				.loadsOnStartup(true)
				.keepsSpawnLoaded(true)
				.dimension(dimension)
				.generator(generator)
				.gameMode(gamemode)
				.build(name.toLowerCase(), name);

			try
			{
				WorldProperties worldProperties = Sponge.getGame().getServer().createWorldProperties(name, worldSettings);
				Optional<World> world = Sponge.getGame().getServer().loadWorld(worldProperties);

				if (world.isPresent())
				{
					world.get().getProperties().setDifficulty(difficulty);
					src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.GOLD, "World ", TextColors.GRAY, name, TextColors.GOLD, " has been created."));
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "The world could not be created."));
				}
			}
			catch (IOException e)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "The world properties could not be created."));
			}

			return CommandResult.success();
		}

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "create" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec
				.builder()
				.description(Text.of("Create World Command"))
				.permission("essentialcmds.world.create")
				.arguments(GenericArguments.onlyOne(GenericArguments.string(Text.of("name"))), GenericArguments.onlyOne(GenericArguments.string(Text.of("dimension"))), GenericArguments.onlyOne(GenericArguments.string(Text.of("generator"))), GenericArguments.onlyOne(GenericArguments.catalogedElement(Text.of("gamemode"), CatalogTypes.GAME_MODE)), GenericArguments.onlyOne(GenericArguments.string(Text.of("difficulty"))))
				.executor(this).build();
		}
	}

	static class SetDifficulty extends CommandExecutorBase
	{
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			String difficulty = ctx.<String> getOne("difficulty").get();
			Optional<String> worldName = ctx.<String> getOne("world");

			if (worldName.isPresent())
			{
				if (Sponge.getServer().getWorld(worldName.get()).isPresent())
				{
					World world = Sponge.getServer().getWorld(worldName.get()).get();
					Optional<Difficulty> optDifficulty = Sponge.getRegistry().getType(Difficulty.class, difficulty);

					if (optDifficulty.isPresent())
					{
						world.getProperties().setDifficulty(optDifficulty.get());
						src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Set difficulty!"));
					}
					else
					{
						src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Difficulty not found!"));
					}
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "World not found!"));
				}
			}
			else
			{
				if (src instanceof Player)
				{
					Player player = (Player) src;
					World world = player.getWorld();
					Optional<Difficulty> optDifficulty = Sponge.getRegistry().getType(Difficulty.class, difficulty);

					if (optDifficulty.isPresent())
					{
						world.getProperties().setDifficulty(optDifficulty.get());
						src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Set difficulty!"));
					}
					else
					{
						src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Difficulty not found!"));
					}
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player to use /world difficulty!"));
				}
			}

			return CommandResult.success();
		}

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "difficulty" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("Difficulty World Command"))
				.permission("essentialcmds.world.difficulty")
				.arguments(GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.string(Text.of("difficulty"))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.string(Text.of("world"))))))
				.executor(this)
				.build();
		}
	}

	static class ListGamerules extends CommandExecutorBase
	{
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			Optional<String> worldName = ctx.<String> getOne("world");
			World world;

			if (worldName.isPresent())
			{
				if (Sponge.getServer().getWorld(worldName.get()).isPresent())
				{
					world = Sponge.getServer().getWorld(worldName.get()).get();
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "World not found!"));
					return CommandResult.empty();
				}
			}
			else
			{
				if (src instanceof Player)
				{
					Player player = (Player) src;
					world = player.getWorld();
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player to use /world difficulty!"));
					return CommandResult.empty();
				}
			}

			PaginationService paginationService = Sponge.getServiceManager().provide(PaginationService.class).get();
			ArrayList<Text> gameruleText = Lists.newArrayList();

			for (Entry<String, String> gamerule : world.getGameRules().entrySet())
			{
				Text item = Text.builder(gamerule.getKey())
					.onHover(TextActions.showText(Text.of(TextColors.WHITE, "Value ", TextColors.GOLD, gamerule.getValue())))
					.color(TextColors.DARK_AQUA)
					.style(TextStyles.UNDERLINE)
					.build();

				gameruleText.add(item);
			}

			PaginationList.Builder paginationBuilder = paginationService.builder().contents(gameruleText).title(Text.of(TextColors.GREEN, "Showing Gamerules")).padding(Text.of("-"));
			paginationBuilder.sendTo(src);
			return CommandResult.success();
		}

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "listgamerules", "lsgamerules" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("List Gamerules World Command"))
				.permission("essentialcmds.world.listgamerule")
				.arguments(GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.string(Text.of("world")))))
				.executor(this)
				.build();
		}
	}

	static class Gamerule extends CommandExecutorBase
	{
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			String gameRule = ctx.<String> getOne("gamerule").get();
			Optional<String> value = ctx.<String> getOne("value");
			Optional<String> worldName = ctx.<String> getOne("world");
			World world;

			if (worldName.isPresent())
			{
				if (Sponge.getServer().getWorld(worldName.get()).isPresent())
				{
					world = Sponge.getServer().getWorld(worldName.get()).get();
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "World not found!"));
					return CommandResult.empty();
				}
			}
			else
			{
				if (src instanceof Player)
				{
					Player player = (Player) src;
					world = player.getWorld();
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player to use /world difficulty!"));
					return CommandResult.empty();
				}
			}

			if (value.isPresent())
			{
				world.getProperties().setGameRule(gameRule, value.get());
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Updated gamerule value."));
			}
			else
			{
				String val = world.getProperties().getGameRule(gameRule).orElse("none");
				src.sendMessage(Text.of(TextColors.GREEN, "Gamerule ", TextColors.GOLD, gameRule, TextColors.GREEN, " value ", TextColors.GOLD, val));
			}

			return CommandResult.success();
		}

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "gamerule", "setgamerule" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("Gamerule World Command"))
				.permission("essentialcmds.world.gamerule")
				.arguments(GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.string(Text.of("gamerule"))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.string(Text.of("value")))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.string(Text.of("world"))))))
				.executor(this)
				.build();
		}
	}

	static class Delete extends CommandExecutorBase
	{
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			String worldName = ctx.<String> getOne("name").get();
			Game game = EssentialCmds.getEssentialCmds().getGame();

			World foundWorld = null;
			World altWorld = null;

			for (World world : game.getServer().getWorlds())
			{
				if (world.getName().equals(worldName))
				{
					foundWorld = world;
					break;
				}
			}

			for (World world : game.getServer().getWorlds())
			{
				if (!world.getName().equals(worldName))
				{
					altWorld = world;
					break;
				}
			}

			if (foundWorld != null)
			{
				for (Player player : game.getServer().getOnlinePlayers())
				{
					if (player.getWorld().getUniqueId().equals(foundWorld.getUniqueId()) && altWorld != null)
					{
						player.transferToWorld(altWorld.getName(), altWorld.getSpawnLocation().getPosition());

					}
				}

				foundWorld.getProperties().setEnabled(false);
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Disabled world. To fully delete the world, please delete it from your files."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "The world you specified was not found."));
			}

			return CommandResult.success();
		}

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "delete", "del" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder().description(Text.of("Delete World Command")).permission("essentialcmds.world.delete")
				.arguments(GenericArguments.onlyOne(GenericArguments.string(Text.of("name")))).executor(this).build();
		}
	}

	static class List extends AsyncCommandExecutorBase
	{

		@Override
		public void executeAsync(CommandSource src, CommandContext ctx)
		{
			ArrayList<String> worlds = EssentialCmds.getEssentialCmds().getGame().getServer().getWorlds().stream().filter(world -> world.getProperties().isEnabled()).map(World::getName).collect(Collectors.toCollection(ArrayList::new));

			PaginationService paginationService = Sponge.getServiceManager().provide(PaginationService.class).get();
			ArrayList<Text> worldText = Lists.newArrayList();

			for (String name : worlds)
			{
				Text item = Text.builder(name)
					.onClick(TextActions.runCommand("/tpworld " + name))
					.onHover(TextActions.showText(Text.of(TextColors.WHITE, "Teleport to world ", TextColors.GOLD, name)))
					.color(TextColors.DARK_AQUA)
					.style(TextStyles.UNDERLINE)
					.build();

				worldText.add(item);
			}

			PaginationList.Builder paginationBuilder = paginationService.builder().contents(worldText).title(Text.of(TextColors.GREEN, "Showing Worlds")).padding(Text.of("-"));
			paginationBuilder.sendTo(src);
		}

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "list" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("List World Command"))
				.permission("essentialcmds.worlds.list")
				.executor(this)
				.build();
		}
	}

	static class Teleport extends CommandExecutorBase
	{

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "tp", "teleport" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("Teleport World Command"))
				.permission("essentialcmds.tpworld.use")
				.arguments(GenericArguments.seq(GenericArguments.string(Text.of("name")), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.player(Text.of("player"))))))
				.executor(this)
				.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			Optional<Player> optPlayer = ctx.<Player> getOne("player");
			String name = ctx.<String> getOne("name").get();

			if (!optPlayer.isPresent())
			{
				if (src instanceof Player)
				{
					Player player = (Player) src;
					Optional<World> optWorld = Sponge.getGame().getServer().getWorld(name);

					if (optWorld.isPresent())
					{
						Utils.setLastTeleportOrDeathLocation(player.getUniqueId(), player.getLocation());
						Location<World> spawnLocation = optWorld.get().getSpawnLocation();
						player.transferToWorld(name, spawnLocation.getPosition());
						src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to world."));
					}
					else
					{
						src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "World specified does not exist!"));
					}
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot teleport, you are not a player!"));
				}
			}
			else
			{
				Player player = optPlayer.get();

				Optional<World> optWorld = Sponge.getGame().getServer().getWorld(name);

				if (optWorld.isPresent())
				{
					Utils.setLastTeleportOrDeathLocation(player.getUniqueId(), player.getLocation());
					Location<World> spawnLocation = optWorld.get().getSpawnLocation();
					player.transferToWorld(name, spawnLocation.getPosition());
					src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported player to world."));
					player.sendMessage(Text.of(TextColors.GOLD, src.getName(), TextColors.GRAY, " has teleported you to this world."));
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "World specified does not exist!"));
				}
			}

			return CommandResult.success();
		}
	}

	static class Spawn extends CommandExecutorBase
	{

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "spawn" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("World Spawn Command"))
				.permission("essentialcmds.world.spawn.use")
				.executor(this)
				.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				Vector3i spawnPos = player.getWorld().getProperties().getSpawnPosition();
				player.setLocation(new Location<>(player.getWorld(), spawnPos.getX(), spawnPos.getY(), spawnPos.getZ()));
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Teleported to world spawn."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You cannot teleport, you are not a player!"));
			}

			return CommandResult.success();
		}
	}

	static class SetSpawn extends CommandExecutorBase
	{

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "setspawn" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec.builder()
				.description(Text.of("Set World Spawn Command"))
				.permission("essentialcmds.world.spawn.set")
				.executor(new SetWorldSpawnExecutor())
				.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			if (src instanceof Player)
			{
				Player player = (Player) src;
				player.getWorld().getProperties().setSpawnPosition(player.getLocation().getBlockPosition());
				src.sendMessage(Text.of(TextColors.GREEN, "Success: ", TextColors.YELLOW, "World spawn set."));
			}
			else if (src instanceof ConsoleSource || src instanceof CommandBlockSource)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Must be an in-game player to use /world setspawn!"));
			}

			return CommandResult.success();
		}
	}

	static class Load extends CommandExecutorBase
	{

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "load" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec
				.builder()
				.description(Text.of("Load World Command"))
				.permission("essentialcmds.world.load")
				.arguments(GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.string(Text.of("name"))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.string(Text.of("dimension")))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.string(Text.of("generator")))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.catalogedElement(Text.of("gamemode"), CatalogTypes.GAME_MODE))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.string(Text.of("difficulty"))))))
				.executor(this)
				.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			String name = ctx.<String> getOne("name").get();
			Optional<String> dimensionInput = ctx.<String> getOne("dimension");
			Optional<String> generatorInput = ctx.<String> getOne("generator");
			Optional<String> difficultyInput = ctx.<String> getOne("difficulty");
			Optional<GameMode> gamemode = ctx.<GameMode> getOne("gamemode");
			Difficulty difficulty = Difficulties.NORMAL;
			DimensionType dimension = DimensionTypes.OVERWORLD;
			GeneratorType generator = GeneratorTypes.OVERWORLD;

			if (dimensionInput.isPresent() && Sponge.getRegistry().getType(DimensionType.class, dimensionInput.get()).isPresent())
			{
				dimension = Sponge.getRegistry().getType(DimensionType.class, dimensionInput.get()).get();
			}
			else if (dimensionInput.isPresent())
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Dimension type specified not found."));
			}

			if (generatorInput.isPresent() && Sponge.getRegistry().getType(GeneratorType.class, generatorInput.get()).isPresent())
			{
				generator = Sponge.getRegistry().getType(GeneratorType.class, generatorInput.get()).get();
			}
			else if (generatorInput.isPresent())
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Generator type specified not found."));
			}

			if (difficultyInput.isPresent() && Sponge.getRegistry().getType(Difficulty.class, difficultyInput.get()).isPresent())
			{
				difficulty = Sponge.getRegistry().getType(Difficulty.class, difficultyInput.get()).get();
			}
			else if (difficultyInput.isPresent())
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "Difficulty specified not found."));
			}

			src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Beginning loading of world."));

			WorldArchetype worldSettings = WorldArchetype.builder()
				.enabled(true)
				.loadsOnStartup(true)
				.keepsSpawnLoaded(true)
				.dimension(dimension)
				.generator(generator)
				.gameMode(gamemode.orElse(GameModes.SURVIVAL))
				.build(name.toLowerCase(), name);

			try
			{
				WorldProperties worldProperties = Sponge.getGame().getServer().createWorldProperties(name, worldSettings);
				Optional<World> world = Sponge.getGame().getServer().loadWorld(worldProperties);

				if (world.isPresent())
				{
					world.get().getProperties().setDifficulty(difficulty);
					src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.GOLD, "World ", TextColors.GRAY, name, TextColors.GOLD, " has been loaded."));
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "The world could not be created."));
				}
			}
			catch (IOException e)
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "The world properties could not be created."));
			}

			return CommandResult.success();
		}
	}

	static class SetGamemode extends CommandExecutorBase
	{

		@Nonnull
		@Override
		public String[] getAliases()
		{
			return new String[] { "setgamemode" };
		}

		@Nonnull
		@Override
		public CommandSpec getSpec()
		{
			return CommandSpec
				.builder()
				.description(Text.of("SetGamemode World Command"))
				.permission("essentialcmds.world.setgamemode")
				.arguments(GenericArguments.seq(GenericArguments.onlyOne(GenericArguments.catalogedElement(Text.of("gamemode"), CatalogTypes.GAME_MODE))), GenericArguments.optional(GenericArguments.onlyOne(GenericArguments.string(Text.of("world")))))
				.executor(this)
				.build();
		}

		@Override
		public CommandResult execute(CommandSource src, CommandContext ctx) throws CommandException
		{
			GameMode gamemode = ctx.<GameMode> getOne("gamemode").get();
			Optional<String> worldName = ctx.<String> getOne("world");
			World world = null;

			if (worldName.isPresent())
			{
				world = Sponge.getServer().getWorld(worldName.get()).orElse(null);
			}
			else
			{
				if (src instanceof Player)
				{
					Player player = (Player) src;
					world = player.getWorld();
				}
				else
				{
					src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "You must be an in-game player or specify the world name to set its gamemode!"));
				}
			}

			if (world != null)
			{
				world.getProperties().setGameMode(gamemode);
				src.sendMessage(Text.of(TextColors.GREEN, "Success! ", TextColors.YELLOW, "Set gamemode of world."));
			}
			else
			{
				src.sendMessage(Text.of(TextColors.DARK_RED, "Error! ", TextColors.RED, "World not found!"));
			}

			return CommandResult.success();
		}
	}
}
import com.google.common.collect.Sets;
import io.github.hsyyid.essentialcmds.EssentialCmds;
import io.github.hsyyid.essentialcmds.cmdexecutors.AFKExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.AddRuleExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.AsConsoleExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.BackExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.BanExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.BlacklistBase;
import io.github.hsyyid.essentialcmds.cmdexecutors.BlockInfoExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.BroadcastExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.ButcherExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.ClearInventoryExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.DeleteHomeExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.DeleteWarpExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.DirectionExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.EnchantExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.EntityInfoExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.EssentialCmdsExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.ExpExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.FeedExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.FireballExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.FlyExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.GCExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.GamemodeExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.GetPosExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.GodExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.HatExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.HealExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.HelpOpExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.HomeExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.IgniteExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.InvSeeExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.ItemInfoExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.JailExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.JumpExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.KickAllExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.KickExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.KillExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.KittyCannonExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.LightningExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.ListExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.ListHomeExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.ListWarpExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.LockWeatherExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.LoreBase;
import io.github.hsyyid.essentialcmds.cmdexecutors.MailExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.MailListExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.MailReadExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.MeExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.MessageExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.MobSpawnExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.MobSpawnerExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.MoreExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.MotdExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.MuteExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.NickExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.PardonExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.PlayerFreezeExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.PowertoolExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.RTPExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.RemoveRuleExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.RepairExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.RespondExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.RocketExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.RuleExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.SayExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.SetHomeExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.SetNameExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.SetWarpExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.SkullExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.SlapExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.SocialSpyExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.SpeedExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.StopExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.SudoExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TPAAcceptExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TPAAllExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TPADenyExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TPAExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TPAHereExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TPAllExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TPChunkExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TPHereExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TakeExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TeleportExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TeleportPosExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TempBanExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.ThruExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.TimeExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.UnJailExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.UnmuteExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.VanishExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.WarpExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.WeatherExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.WhoisExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.world.CreateWorldExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.world.DeleteWorldExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.world.ListWorldExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.world.LoadWorldExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.world.SetFirstSpawnExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.world.SetSpawnExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.world.SetWorldSpawnExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.world.SpawnExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.world.TeleportWorldExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.world.WorldInfoExecutor;
import io.github.hsyyid.essentialcmds.cmdexecutors.world.WorldsBase;
import org.spongepowered.api.Sponge;
import java.util.Set;
/*
 * 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.internal;



/**
 * Utility class that handles loading and registering commands.
 */
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(),