@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(),
            new DeleteHomeExecutor(),
            new DeleteWarpExecutor(),
            new DeleteWorldExecutor(),
            new DirectionExecutor(),
            new EnchantExecutor(),
            new EntityInfoExecutor(),
            new EssentialCmdsExecutor(),
            new ExpExecutor(),
            new FeedExecutor(),
            new FireballExecutor(),
            new FlyExecutor(),
            new GamemodeExecutor(),
            new GCExecutor(),
            new GetPosExecutor(),
            new HatExecutor(),
            new HomeExecutor(),
            new HealExecutor(),
            new IgniteExecutor(),
            new InvSeeExecutor(),
            new ItemInfoExecutor(),
            new JumpExecutor(),
            new KickExecutor(),
            new KillExecutor(),
            new LightningExecutor(),
            new ListHomeExecutor(),
            new ListWarpExecutor(),
            new ListWorldExecutor(),
            new LoadWorldExecutor(),
            new LockWeatherExecutor(),
            new MailExecutor(),
            new MailListExecutor(),
            new MailReadExecutor(),
            new MessageExecutor(),
            new MobSpawnerExecutor(),
            new MobSpawnExecutor(),
            new MoreExecutor(),
            new MotdExecutor(),
            new MuteExecutor(),
            new NickExecutor(),
            new PardonExecutor(),
            new PlayerFreezeExecutor(),
            new PowertoolExecutor(),
            new RemoveRuleExecutor(),
            new RepairExecutor(),
            new RespondExecutor(),
            new RocketExecutor(),
            new RTPExecutor(),
            new RuleExecutor(),