Created
September 8, 2018 14:04
-
-
Save Nicofisi/74fe58bbab4d7770393fb3b619862bd8 to your computer and use it in GitHub Desktop.
Revisions
-
Nicofisi renamed this gist
Sep 8, 2018 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
Nicofisi created this gist
Sep 8, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,143 @@ package me.nicofisi.spigot.common.commands import arrow.core.Either import arrow.core.Left import arrow.core.None import arrow.core.Option import arrow.core.Right import arrow.core.Some import arrow.core.Try import arrow.core.getOrElse import arrow.core.orElse import arrow.core.toOption import me.nicofisi.spigot.common.colored import org.bukkit.Bukkit import org.bukkit.GameMode import org.bukkit.OfflinePlayer import org.bukkit.World import org.bukkit.entity.Player import java.math.BigInteger import java.util.UUID typealias ParseFailReason = String typealias ParseResult<A> = Either<A, ParseFailReason> interface CType<A> { fun parse(string: String): ParseResult<A> /** * Returns a list of suggestions to send to the player when they press the tab key with the given * string typed, in a place where an object of this type is expected * * @param mustStartWith the string; implementations are allowed to return an empty list when * the length of this string is lower than some given small number */ fun tabSuggestions(mustStartWith: String): List<String> = emptyList() } object TypeBoolean : CType<Boolean> { override fun parse(string: String): ParseResult<Boolean> = when (string) { "yes", "true", "y", "t" -> Left(true) "no", "false", "n", "f" -> Left(false) else -> Right("&sYou typed &p$string in a place where only &pyes &sor &pno &sshould be used".colored) } } object TypeGameMode : CType<GameMode> { override fun parse(string: String): ParseResult<GameMode> = when (string) { "0", "survival", "s" -> Left(GameMode.SURVIVAL) "1", "creative", "c" -> Left(GameMode.CREATIVE) "2", "adventure", "a" -> Left(GameMode.ADVENTURE) "3", "spectator", "sp" -> Left(GameMode.SPECTATOR) else -> Right("&sGame mode called &p$string &sdoesn't exist".colored) } override fun tabSuggestions(mustStartWith: String) = listOf("survival", "creative", "adventure", "spectator") .filter { it.startsWith(mustStartWith.toLowerCase()) } } object TypeInt : CType<Int> { override fun parse(string: String): ParseResult<Int> { return Try { Left(string.toInt()) }.getOrElse { if (Try { BigInteger(string) }.isSuccess()) { Right("&sThe number &p$string &sis too big, it should be at most ${Int.MAX_VALUE}") } else { Right("&p$string &sis not an integer") } } } } object TypeLong : CType<Long> { override fun parse(string: String): ParseResult<Long> { return Try { Left(string.toLong()) }.getOrElse { if (Try { BigInteger(string) }.isSuccess()) { Right("&sThe number &p$string &sis too big, it should be at most ${Long.MAX_VALUE}") } else { Right("&p$string &sis not an integer".colored) } } } } object TypeDouble : CType<Double> { override fun parse(string: String): ParseResult<Double> { return Try { Left(string.toDouble()) }.getOrElse { Right("&p$string is not a floating-point number".colored) } } } object TypeOfflinePlayer : CType<OfflinePlayer> { override fun parse(string: String): ParseResult<OfflinePlayer> { @Suppress("DEPRECATION") // needed here return Option(Bukkit.getOfflinePlayer(string)) .orElse { Try { UUID.fromString(string) }.toOption().flatMap { Option(Bukkit.getOfflinePlayer(it)) } } .map { Left(it) }.getOrElse { Right("&sNo player named &p$string &scould be found".colored) } } // TODO find a way faster way // than Bukkit.getOfflinePlayers.asScala.map(_.getName).filter(_.startsWith(mustStartWith)) } object TypePlayer : CType<Player> { override fun parse(string: String): ParseResult<Player> { return Option(Bukkit.getPlayerExact(string)) .orElse { Try { UUID.fromString(string) }.toOption().flatMap { Option(Bukkit.getPlayer(it)) } } .map { Left(it) }.getOrElse { val players = Bukkit.getOnlinePlayers().filter { it.name.startsWith(string, ignoreCase = true) } when { players.isEmpty() -> Right("&sNo online player could be found whose name starts with &p$string") players.size > 1 -> Right("&sThere are currently a few players online whose names start with &p$string") else -> Left(players.first()) } } } } object TypeString : CType<String> { override fun parse(string: String) = Left(string) } object TypeWorld : CType<World> { override fun parse(string: String): ParseResult<World> { return Option(Bukkit.getWorld(string)).map { Left(it) }.getOrElse { val worlds = Bukkit.getWorlds().filter { it.name.startsWith(string, ignoreCase = true) } when { worlds.isEmpty() -> Right("&sThere aren't any loaded worlds whose names start with &p$string") worlds.size > 1 -> Right("&sThere are currently a few loaded worlds whose names start with &p$string") else -> Left(worlds.first()) } } } override fun tabSuggestions(mustStartWith: String) = Bukkit.getWorlds().map { it.name }.filter { it.startsWith(mustStartWith, ignoreCase = true) } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,125 @@ package me.nicofisi.commonspigotstuff import java.util.UUID import org.bukkit.{Bukkit, GameMode, OfflinePlayer, World} import org.bukkit.entity.Player import scala.collection.JavaConverters._ import scala.util.Try trait CType[A] { type ParseFailReason = String type ParseResult = Either[A, ParseFailReason] def parse(string: String)(implicit info: PluginInfo): ParseResult /** Returns a list of suggestions to send to the player when they press the tab key with the given * string typed, in a place where an object of this type is expected * * @param mustStartWith the string; implementations are allowed to return an empty list when * the length of this string is lower than some given small number */ def tabSuggestions(mustStartWith: String): List[String] = Nil } object TypeBoolean extends CType[Boolean] { override def parse(string: String)(implicit info: PluginInfo): ParseResult = string match { case "yes" | "true" | "y" | "t" => Left(true) case "no" | "false" | "n" | "f" => Left(false) case _ => Right(s"&sYou typed &p$string in a place where only &pyes &sor &pno &sshould be used".colored) } } object TypeGameMode extends CType[GameMode] { override def parse(string: String)(implicit info: PluginInfo): ParseResult = string match { case "0" | "survival" | "s" => Left(GameMode.SURVIVAL) case "1" | "creative" | "c" => Left(GameMode.CREATIVE) case "2" | "adventure" | "a" => Left(GameMode.ADVENTURE) case "3" | "spectator" | "sp" => Left(GameMode.SPECTATOR) case _ => Right(s"&sGame mode called &p$string &sdoesn't exist") } override def tabSuggestions(mustStartWith: String): List[String] = List("survival", "creative", "adventure", "spectator").filter(_.startsWith(mustStartWith.toLowerCase)) } object TypeInt extends CType[Int] { override def parse(string: String)(implicit info: PluginInfo): ParseResult = Try(Left(string.toInt)).getOrElse( if (Try(BigInt(string)).isSuccess) Right(s"&sThe number &p$string &sis too big, it should be at most ${Int.MaxValue}") else Right(s"&p$string &sis not an integer") ) } object TypeLong extends CType[Long] { override def parse(string: String)(implicit info: PluginInfo): ParseResult = Try(Left(string.toLong)).getOrElse( if (Try(BigInt(string)).isSuccess) Right(s"&sThe number &p$string &sis too big, it should be at most ${Long.MaxValue}") else Right(s"&p$string &sis not an integer") ) } object TypeDouble extends CType[Double] { override def parse(string: String)(implicit info: PluginInfo): ParseResult = Try(Left(string.toDouble)).getOrElse( Right(s"&p$string &scouldn't be interpreted as a floating-point number") ) } object TypeOfflinePlayer extends CType[OfflinePlayer] { override def parse(string: String)(implicit info: PluginInfo): ParseResult = { // noinspection ScalaDeprecation Option(Bukkit.getOfflinePlayer(string)) // deprecated but not going to be removed, and we do need it here .orElse(Try(UUID.fromString(string)).toOption.flatMap(uuid => Some(Bukkit.getOfflinePlayer(uuid)))) .map(Left(_)).getOrElse(Right(s"&sNo player named &p$string &scould be found")) } // TODO find a way faster way // than Bukkit.getOfflinePlayers.asScala.map(_.getName).filter(_.startsWith(mustStartWith)) override def tabSuggestions(mustStartWith: String): List[String] = Nil } object TypePlayer extends CType[Player] { override def parse(string: String)(implicit info: PluginInfo): ParseResult = { Option(Bukkit.getPlayerExact(string)) .orElse(Try(UUID.fromString(string)).toOption.flatMap(uuid => Some(Bukkit.getPlayer(uuid)))) .map(Left(_)).getOrElse { val players = Bukkit.getOnlinePlayers.asScala.filter(_.getName.toLowerCase.startsWith(string)) if (players.isEmpty) Right(s"&sNo online player could be found whose name starts with &p$string") else if (players.size > 1) Right(s"&sThere are currently a few players online whose names start with &p$string") else Left(players.head) } } override def tabSuggestions(mustStartWith: String): List[String] = Bukkit.getOnlinePlayers.asScala.toList.map(_.getName).filter(_.toLowerCase.startsWith(mustStartWith.toLowerCase)) } object TypeString extends CType[String] { override def parse(string: String)(implicit info: PluginInfo): ParseResult = Left(string) } object TypeWorld extends CType[World] { override def parse(string: String)(implicit info: PluginInfo): ParseResult = { Option(Bukkit.getWorld(string)).map(Left(_)).getOrElse { val worlds = Bukkit.getWorlds.asScala.filter(_.getName.toLowerCase.startsWith(string)) if (worlds.isEmpty) Right(s"&sThere aren't any loaded worlds whose names start with &p$string") else if (worlds.size > 1) Right(s"&sThere are currently a few loaded worlds whose names start with &p$string") else Left(worlds.head) } } override def tabSuggestions(mustStartWith: String): List[String] = Bukkit.getWorlds.asScala.toList.map(_.getName).filter(_.toLowerCase.startsWith(mustStartWith.toLowerCase)) }