Skip to content

Instantly share code, notes, and snippets.

@Nicofisi
Created September 8, 2018 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nicofisi/74fe58bbab4d7770393fb3b619862bd8 to your computer and use it in GitHub Desktop.
Save Nicofisi/74fe58bbab4d7770393fb3b619862bd8 to your computer and use it in GitHub Desktop.
Kotlin vs Scala
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) }
}
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))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment