1.0.0.3 - new modules
Added utility, menu, thirdparty and exposed modules A few little fixes
This commit is contained in:
1 parent
e5a7e08e56
commit
9655d10025
63 files changed
+5334
-12
No files matched your search
@@ -0,0 +1,64 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.io.File
|
||||
import java.sql.SQLException
|
||||
|
||||
public interface DatabaseTypeConfigHeader {
|
||||
public val type: String
|
||||
public val hostname: String
|
||||
public val port: Short
|
||||
public val database: String
|
||||
public val user: String
|
||||
public val password: String
|
||||
}
|
||||
|
||||
@Serializable
|
||||
public data class DatabaseTypeConfig(
|
||||
override var type: String = "H2",
|
||||
override var hostname: String = "localhost",
|
||||
override var port: Short = 3306,
|
||||
override var database: String = "kbapi_database",
|
||||
override var user: String = "root",
|
||||
override var password: String = "12345",
|
||||
) : DatabaseTypeConfigHeader
|
||||
|
||||
public fun databaseTypeFrom(dataFolder: File, config: DatabaseTypeConfig): DatabaseType {
|
||||
val type = DatabaseType.byName(config.type)
|
||||
if (type != null) {
|
||||
return when (type) {
|
||||
DatabaseType.H2::class -> DatabaseType.H2(
|
||||
dataFolder,
|
||||
config.database,
|
||||
)
|
||||
DatabaseType.SQLite::class -> DatabaseType.SQLite(
|
||||
dataFolder,
|
||||
config.database,
|
||||
)
|
||||
DatabaseType.MySQL::class -> DatabaseType.MySQL(
|
||||
config.hostname,
|
||||
config.port,
|
||||
config.database,
|
||||
config.user,
|
||||
config.password,
|
||||
)
|
||||
DatabaseType.PostgreSQL::class -> DatabaseType.PostgreSQL(
|
||||
config.hostname,
|
||||
config.port,
|
||||
config.database,
|
||||
config.user,
|
||||
config.password,
|
||||
)
|
||||
DatabaseType.SQLServer::class -> DatabaseType.SQLServer(
|
||||
config.hostname,
|
||||
config.port,
|
||||
config.database,
|
||||
config.user,
|
||||
config.password,
|
||||
)
|
||||
else -> throw SQLException("SQL type not finded or supported.")
|
||||
}
|
||||
} else {
|
||||
throw SQLException("SQL type not finded or supported.")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig
|
||||
import com.zaxxer.hikari.HikariDataSource
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
import java.net.URLClassLoader
|
||||
import java.sql.SQLException
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
private const val KEY_FILE = "{file}"
|
||||
|
||||
public sealed class DatabaseType(
|
||||
public val name: String,
|
||||
public val jdbc: String,
|
||||
public val driverClass: String,
|
||||
public val driverLink: String,
|
||||
) {
|
||||
|
||||
public companion object {
|
||||
public val fileDatabases: Map<String, KClass<out DatabaseType>> =
|
||||
mapOf("h2" to H2::class, "sqlite" to SQLite::class)
|
||||
public val remoteDatabases: Map<String, KClass<out DatabaseType>> =
|
||||
mapOf("mysql" to MySQL::class, "postgresql" to PostgreSQL::class, "sqlserver" to SQLServer::class)
|
||||
public val databases: Map<String, KClass<out DatabaseType>> = fileDatabases + remoteDatabases
|
||||
|
||||
public fun byName(name: String): KClass<out DatabaseType>? = databases[name.toLowerCase()]
|
||||
}
|
||||
|
||||
public abstract fun dataSource(): HikariDataSource
|
||||
|
||||
public abstract fun config(): HikariConfig
|
||||
|
||||
public abstract class FileDatabaseType(
|
||||
name: String,
|
||||
jdbc: String,
|
||||
driverClass: String,
|
||||
driverLink: String,
|
||||
public val dataFolder: File,
|
||||
public val file: String,
|
||||
public val databaseExtension: String,
|
||||
public val needFileCreation: Boolean,
|
||||
) : DatabaseType(name, jdbc, driverClass, driverLink) {
|
||||
|
||||
private val realFile = File(dataFolder, "$file.$databaseExtension")
|
||||
|
||||
override fun dataSource(): HikariDataSource {
|
||||
if (needFileCreation && !realFile.exists()) realFile.createNewFile()
|
||||
|
||||
loadDependency()
|
||||
|
||||
return HikariDataSource(config())
|
||||
}
|
||||
|
||||
override fun config(): HikariConfig = HikariConfig().apply {
|
||||
driverClassName = driverClass
|
||||
jdbcUrl = jdbc.replace(KEY_FILE, realFile.path)
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class RemoteDatabaseType(
|
||||
name: String,
|
||||
jdbc: String,
|
||||
driverClass: String,
|
||||
driverLink: String,
|
||||
public val hostname: String,
|
||||
public val port: Short,
|
||||
public val database: String,
|
||||
public val username: String,
|
||||
public val password: String,
|
||||
) : DatabaseType(name, jdbc, driverClass, driverLink) {
|
||||
override fun dataSource(): HikariDataSource {
|
||||
loadDependency()
|
||||
|
||||
return HikariDataSource(config())
|
||||
}
|
||||
|
||||
override fun config(): HikariConfig = HikariConfig().apply {
|
||||
driverClassName = driverClass
|
||||
jdbcUrl = jdbc
|
||||
username = this@RemoteDatabaseType.username
|
||||
password = this@RemoteDatabaseType.password
|
||||
}
|
||||
}
|
||||
|
||||
public class H2(
|
||||
dataFolder: File,
|
||||
file: String,
|
||||
) : FileDatabaseType(
|
||||
"H2",
|
||||
"jdbc:h2:file:./$KEY_FILE",
|
||||
"org.h2.Driver",
|
||||
"https://repo1.maven.org/maven2/com/h2database/h2/1.4.199/h2-1.4.199.jar",
|
||||
dataFolder,
|
||||
file,
|
||||
"h2.db",
|
||||
false,
|
||||
)
|
||||
|
||||
public class SQLite(
|
||||
dataFolder: File,
|
||||
file: String,
|
||||
) : FileDatabaseType(
|
||||
"SQLite",
|
||||
"jdbc:sqlite:./$KEY_FILE",
|
||||
"org.sqlite.JDBC",
|
||||
"https://bitbucket.org/xerial/sqlite-jdbc/downloads/sqlite-jdbc-3.23.1.jar",
|
||||
dataFolder,
|
||||
file,
|
||||
"sqlite.db",
|
||||
true,
|
||||
) {
|
||||
// https://github.com/brettwooldridge/HikariCP/issues/393#issuecomment-135580191
|
||||
override fun config(): HikariConfig {
|
||||
return super.config().apply {
|
||||
connectionTestQuery = "SELECT 1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MySQL(
|
||||
hostname: String,
|
||||
port: Short,
|
||||
database: String,
|
||||
username: String,
|
||||
password: String,
|
||||
) : RemoteDatabaseType(
|
||||
"MySQL",
|
||||
"jdbc:mysql://$hostname:$port/$database",
|
||||
"com.mysql.jdbc.Driver",
|
||||
"https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.11/mysql-connector-java-8.0.11.jar",
|
||||
hostname, port, database,
|
||||
username, password,
|
||||
)
|
||||
|
||||
public class PostgreSQL(
|
||||
hostname: String,
|
||||
port: Short,
|
||||
database: String,
|
||||
username: String,
|
||||
password: String,
|
||||
) : RemoteDatabaseType(
|
||||
"PostgreSQL",
|
||||
"jdbc:postgresql://$hostname:$port/$database",
|
||||
"org.postgresql.Driver",
|
||||
"https://jdbc.postgresql.org/download/postgresql-42.2.2.jre7.jar",
|
||||
hostname, port, database,
|
||||
username, password,
|
||||
)
|
||||
|
||||
public class SQLServer(
|
||||
hostname: String,
|
||||
port: Short,
|
||||
database: String,
|
||||
username: String,
|
||||
password: String,
|
||||
) : RemoteDatabaseType(
|
||||
"SQLServer",
|
||||
"jdbc:sqlserver://$hostname:$port;databaseName=$database",
|
||||
"com.microsoft.sqlserver.jdbc.SQLServerDriver",
|
||||
"https://repo1.maven.org/maven2/com/microsoft/sqlserver/mssql-jdbc/6.4.0.jre8/mssql-jdbc-6.4.0.jre8.jar",
|
||||
hostname, port, database,
|
||||
username, password,
|
||||
)
|
||||
|
||||
private val libsFolder = File("klibs").apply { mkdirs() }
|
||||
private val jarFile = File(libsFolder, "$name-Driver.jar")
|
||||
|
||||
protected fun loadDependency() {
|
||||
try {
|
||||
Class.forName(driverClass)
|
||||
} catch (e: ClassNotFoundException) {
|
||||
if (jarFile.exists()) {
|
||||
loadDriver()
|
||||
} else {
|
||||
try {
|
||||
downloadDriver()
|
||||
} catch (e: Exception) {
|
||||
throw SQLException("Cant download the driver dependencie of $name")
|
||||
}
|
||||
try {
|
||||
loadDriver()
|
||||
Class.forName(driverClass)
|
||||
} catch (e: Exception) {
|
||||
jarFile.delete()
|
||||
throw SQLException("Cant load the driver dependencies of $name")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadDriver() {
|
||||
val url = jarFile.toURI().toURL()
|
||||
val classLoader = DatabaseType::class.java.classLoader as URLClassLoader
|
||||
val method = URLClassLoader::class.java.getDeclaredMethod("addURL", URL::class.java)
|
||||
method.isAccessible = true
|
||||
method.invoke(classLoader, url)
|
||||
}
|
||||
|
||||
private fun downloadDriver() {
|
||||
val input = URL(driverLink).openStream()
|
||||
if (jarFile.exists()) {
|
||||
if (jarFile.isDirectory) {
|
||||
throw IOException("File '" + jarFile.name + "' is a directory")
|
||||
}
|
||||
|
||||
if (!jarFile.canWrite()) {
|
||||
throw IOException("File '" + jarFile.name + "' cannot be written")
|
||||
}
|
||||
} else {
|
||||
val parent = jarFile.parentFile
|
||||
if (parent != null && !parent.exists() && !parent.mkdirs()) {
|
||||
throw IOException("File '" + jarFile.name + "' could not be created")
|
||||
}
|
||||
}
|
||||
|
||||
val output = FileOutputStream(jarFile)
|
||||
|
||||
val buffer = ByteArray(4096)
|
||||
var n = input.read(buffer)
|
||||
while (-1 != n) {
|
||||
output.write(buffer, 0, n)
|
||||
|
||||
n = input.read(buffer)
|
||||
}
|
||||
|
||||
input.close()
|
||||
output.close()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed.delegate
|
||||
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.block.Block
|
||||
import org.jetbrains.exposed.dao.Entity
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public fun Entity<*>.block(column: Column<String>): ExposedDelegate<Block> = BlockExposedDelegate(column)
|
||||
|
||||
@JvmName("blockNullable")
|
||||
public fun Entity<*>.block(column: Column<String?>): ExposedDelegate<Block?> = BlockExposedDelegateNullable(column)
|
||||
|
||||
public fun Entity<*>.block(
|
||||
worldColumn: Column<String>,
|
||||
xColumn: Column<Int>,
|
||||
yColumn: Column<Int>,
|
||||
zColumn: Column<Int>,
|
||||
): ExposedDelegate<Block> = BlockMultiColumnExposedDelegate(worldColumn, xColumn, yColumn, zColumn)
|
||||
|
||||
@JvmName("blockNullable")
|
||||
public fun Entity<*>.nullableBlock(
|
||||
worldColumn: Column<String?>,
|
||||
xColumn: Column<Int?>,
|
||||
yColumn: Column<Int?>,
|
||||
zColumn: Column<Int?>,
|
||||
): ExposedDelegate<Block?> = BlockMultiColumnExposedDelegateNullable(worldColumn, xColumn, yColumn, zColumn)
|
||||
|
||||
public class BlockExposedDelegate(
|
||||
public val column: Column<String>,
|
||||
) : ExposedDelegate<Block> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Block {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data.split(";")
|
||||
val worldName = slices[0]
|
||||
val world = requireNotNull(Bukkit.getWorld(worldName)) { "World '$worldName' retrieving from database unavailable." }
|
||||
return world.getBlockAt(
|
||||
slices[1].toInt(),
|
||||
slices[2].toInt(),
|
||||
slices[3].toInt(),
|
||||
)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Block,
|
||||
) {
|
||||
val parsed = value.run { "${world.name};$x;$y;$z" }
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class BlockExposedDelegateNullable(
|
||||
public val column: Column<String?>,
|
||||
) : ExposedDelegate<Block?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Block? {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data?.split(";")
|
||||
return slices?.let {
|
||||
val worldName = it[0]
|
||||
val world = requireNotNull(Bukkit.getWorld(worldName)) { "World '$worldName' retrieving from database unavailable." }
|
||||
world.getBlockAt(
|
||||
it[1].toInt(),
|
||||
it[2].toInt(),
|
||||
it[3].toInt(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Block?,
|
||||
) {
|
||||
val parsed = value?.run { "${world.name};$x;$y;$z" }
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class BlockMultiColumnExposedDelegate(
|
||||
public val worldColumn: Column<String>,
|
||||
public val xColumn: Column<Int>,
|
||||
public val yColumn: Column<Int>,
|
||||
public val zColumn: Column<Int>,
|
||||
) : ExposedDelegate<Block> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Block {
|
||||
val worldName = entity.run { worldColumn.getValue(this, desc) }
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val y = entity.run { yColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
|
||||
val world = requireNotNull(Bukkit.getWorld(worldName)) { "World '$worldName' retrieving from database unavailable." }
|
||||
|
||||
return world.getBlockAt(x, y, z)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Block,
|
||||
) {
|
||||
entity.apply {
|
||||
value.apply {
|
||||
worldColumn.setValue(entity, desc, world.name)
|
||||
xColumn.setValue(entity, desc, x)
|
||||
yColumn.setValue(entity, desc, y)
|
||||
zColumn.setValue(entity, desc, z)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BlockMultiColumnExposedDelegateNullable(
|
||||
public val worldColumn: Column<String?>,
|
||||
public val xColumn: Column<Int?>,
|
||||
public val yColumn: Column<Int?>,
|
||||
public val zColumn: Column<Int?>,
|
||||
) : ExposedDelegate<Block?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Block? {
|
||||
val worldName = entity.run { worldColumn.getValue(this, desc) }
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val y = entity.run { yColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
|
||||
return if (
|
||||
worldName != null &&
|
||||
x != null && y != null && z != null
|
||||
) {
|
||||
val world = requireNotNull(Bukkit.getWorld(worldName)) { "World '$worldName' retrieving from database unavailable." }
|
||||
|
||||
world.getBlockAt(x, y, z)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Block?,
|
||||
) {
|
||||
entity.apply {
|
||||
worldColumn.setValue(entity, desc, value?.world?.name)
|
||||
xColumn.setValue(entity, desc, value?.x)
|
||||
yColumn.setValue(entity, desc, value?.y)
|
||||
zColumn.setValue(entity, desc, value?.z)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed.delegate
|
||||
|
||||
import tech.carcadex.kotlinbukkitkit.utility.types.BlockPos
|
||||
import org.jetbrains.exposed.dao.Entity
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public fun Entity<*>.blockPos(column: Column<String>): ExposedDelegate<BlockPos> = BlockPosExposedDelegate(column)
|
||||
|
||||
@JvmName("blockPosNullable")
|
||||
public fun Entity<*>.blockPos(column: Column<String?>): ExposedDelegate<BlockPos?> = BlockPosExposedDelegateNullable(column)
|
||||
|
||||
public fun Entity<*>.blockPos(
|
||||
xColumn: Column<Int>,
|
||||
yColumn: Column<Int>,
|
||||
zColumn: Column<Int>,
|
||||
): ExposedDelegate<BlockPos> = BlockPosMultiColumnExposedDelegate(xColumn, yColumn, zColumn)
|
||||
|
||||
@JvmName("blockPosNullable")
|
||||
public fun Entity<*>.nullableBlockPos(
|
||||
xColumn: Column<Int?>,
|
||||
yColumn: Column<Int?>,
|
||||
zColumn: Column<Int?>,
|
||||
): ExposedDelegate<BlockPos?> = BlockPosMultiColumnExposedDelegateNullable(xColumn, yColumn, zColumn)
|
||||
|
||||
public class BlockPosExposedDelegate(
|
||||
public val column: Column<String>,
|
||||
) : ExposedDelegate<BlockPos> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): BlockPos {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data.split(";")
|
||||
return BlockPos(
|
||||
slices[0].toInt(),
|
||||
slices[1].toInt(),
|
||||
slices[2].toInt(),
|
||||
)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: BlockPos,
|
||||
) {
|
||||
val parsed = value.run { "$x;$y;$z" }
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class BlockPosExposedDelegateNullable(
|
||||
public val column: Column<String?>,
|
||||
) : ExposedDelegate<BlockPos?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): BlockPos? {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data?.split(";")
|
||||
return slices?.let {
|
||||
BlockPos(
|
||||
it[0].toInt(),
|
||||
it[1].toInt(),
|
||||
it[2].toInt(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: BlockPos?,
|
||||
) {
|
||||
val parsed = value?.run { "$x;$y;$z" }
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class BlockPosMultiColumnExposedDelegate(
|
||||
public val xColumn: Column<Int>,
|
||||
public val yColumn: Column<Int>,
|
||||
public val zColumn: Column<Int>,
|
||||
) : ExposedDelegate<BlockPos> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): BlockPos {
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val y = entity.run { yColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
|
||||
return BlockPos(x, y, z)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: BlockPos,
|
||||
) {
|
||||
entity.apply {
|
||||
value.apply {
|
||||
xColumn.setValue(entity, desc, x)
|
||||
yColumn.setValue(entity, desc, y)
|
||||
zColumn.setValue(entity, desc, z)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BlockPosMultiColumnExposedDelegateNullable(
|
||||
public val xColumn: Column<Int?>,
|
||||
public val yColumn: Column<Int?>,
|
||||
public val zColumn: Column<Int?>,
|
||||
) : ExposedDelegate<BlockPos?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): BlockPos? {
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val y = entity.run { yColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
|
||||
return if (
|
||||
x != null && y != null && z != null
|
||||
) {
|
||||
BlockPos(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: BlockPos?,
|
||||
) {
|
||||
entity.apply {
|
||||
xColumn.setValue(entity, desc, value?.x)
|
||||
yColumn.setValue(entity, desc, value?.y)
|
||||
zColumn.setValue(entity, desc, value?.z)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed.delegate
|
||||
|
||||
import org.jetbrains.exposed.dao.Entity
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public fun <T> ExposedDelegate<T>.cached(): ExposedDelegate<T> = CachedExposedDelegate(this)
|
||||
|
||||
public class CachedExposedDelegate<T>(
|
||||
private val delegate: ExposedDelegate<T>,
|
||||
) : ExposedDelegate<T> {
|
||||
private var cache: T? = null
|
||||
private var isCached: Boolean = false
|
||||
|
||||
override fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): T {
|
||||
if (!isCached) {
|
||||
cache = delegate.getValue(entity, desc)
|
||||
isCached = true
|
||||
}
|
||||
|
||||
return cache!!
|
||||
}
|
||||
|
||||
override fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: T,
|
||||
) {
|
||||
delegate.setValue(entity, desc, value)
|
||||
cache = value
|
||||
isCached = true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed.delegate
|
||||
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.Chunk
|
||||
import org.jetbrains.exposed.dao.Entity
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public fun Entity<*>.chunk(column: Column<String>): ExposedDelegate<Chunk> = ChunkExposedDelegate(column)
|
||||
|
||||
@JvmName("chunkNullable")
|
||||
public fun Entity<*>.chunk(column: Column<String?>): ExposedDelegate<Chunk?> = ChunkExposedDelegateNullable(column)
|
||||
|
||||
public fun Entity<*>.chunk(
|
||||
worldColumn: Column<String>,
|
||||
xColumn: Column<Int>,
|
||||
zColumn: Column<Int>,
|
||||
): ExposedDelegate<Chunk> = ChunkMultiColumnExposedDelegate(worldColumn, xColumn, zColumn)
|
||||
|
||||
@JvmName("chunkNullable")
|
||||
public fun Entity<*>.chunk(
|
||||
worldColumn: Column<String?>,
|
||||
xColumn: Column<Int?>,
|
||||
zColumn: Column<Int?>,
|
||||
): ExposedDelegate<Chunk?> = ChunkMultiColumnExposedDelegateNullable(worldColumn, xColumn, zColumn)
|
||||
|
||||
public class ChunkExposedDelegate(
|
||||
public val column: Column<String>,
|
||||
) : ExposedDelegate<Chunk> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Chunk {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data.split(";")
|
||||
val worldName = slices[0]
|
||||
val world = requireNotNull(Bukkit.getWorld(worldName)) { "World '$worldName' retrieving from database unavailable." }
|
||||
return world.getChunkAt(
|
||||
slices[1].toInt(),
|
||||
slices[2].toInt(),
|
||||
)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Chunk,
|
||||
) {
|
||||
val parsed = value.run { "${world.name};$x;$z" }
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class ChunkExposedDelegateNullable(
|
||||
public val column: Column<String?>,
|
||||
) : ExposedDelegate<Chunk?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Chunk? {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data?.split(";")
|
||||
return slices?.let {
|
||||
val worldName = it[0]
|
||||
val world = requireNotNull(Bukkit.getWorld(worldName)) { "World '$worldName' retrieving from database unavailable." }
|
||||
world.getChunkAt(
|
||||
it[1].toInt(),
|
||||
it[2].toInt(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Chunk?,
|
||||
) {
|
||||
val parsed = value?.run { "${world.name};$x;$z" }
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class ChunkMultiColumnExposedDelegate(
|
||||
public val worldColumn: Column<String>,
|
||||
public val xColumn: Column<Int>,
|
||||
public val zColumn: Column<Int>,
|
||||
) : ExposedDelegate<Chunk> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Chunk {
|
||||
val worldName = entity.run { worldColumn.getValue(this, desc) }
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
|
||||
val world = requireNotNull(Bukkit.getWorld(worldName)) { "World '$worldName' retrieving from database unavailable." }
|
||||
|
||||
return world.getChunkAt(x, z)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Chunk,
|
||||
) {
|
||||
entity.apply {
|
||||
value.apply {
|
||||
worldColumn.setValue(entity, desc, world.name)
|
||||
xColumn.setValue(entity, desc, x)
|
||||
zColumn.setValue(entity, desc, z)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ChunkMultiColumnExposedDelegateNullable(
|
||||
public val worldColumn: Column<String?>,
|
||||
public val xColumn: Column<Int?>,
|
||||
public val zColumn: Column<Int?>,
|
||||
) : ExposedDelegate<Chunk?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Chunk? {
|
||||
val worldName = entity.run { worldColumn.getValue(this, desc) }
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
|
||||
return if (
|
||||
worldName != null &&
|
||||
x != null && z != null
|
||||
) {
|
||||
val world = requireNotNull(Bukkit.getWorld(worldName)) { "World '$worldName' retrieving from database unavailable." }
|
||||
|
||||
world.getChunkAt(x, z)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Chunk?,
|
||||
) {
|
||||
entity.apply {
|
||||
worldColumn.setValue(entity, desc, value?.world?.name)
|
||||
xColumn.setValue(entity, desc, value?.x)
|
||||
zColumn.setValue(entity, desc, value?.z)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed.delegate
|
||||
|
||||
import tech.carcadex.kotlinbukkitkit.utility.types.ChunkPos
|
||||
import org.jetbrains.exposed.dao.Entity
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public fun Entity<*>.chunkPos(column: Column<String>): ExposedDelegate<ChunkPos> = ChunkPosExposedDelegate(column)
|
||||
|
||||
@JvmName("chunkPosNullable")
|
||||
public fun Entity<*>.chunkPos(column: Column<String?>): ExposedDelegate<ChunkPos?> = ChunkPosExposedDelegateNullable(column)
|
||||
|
||||
public fun Entity<*>.chunkPos(
|
||||
xColumn: Column<Int>,
|
||||
zColumn: Column<Int>,
|
||||
): ExposedDelegate<ChunkPos> = ChunkPosMultiColumnExposedDelegate(xColumn, zColumn)
|
||||
|
||||
@JvmName("chunkPosNullable")
|
||||
public fun Entity<*>.chunkPos(
|
||||
xColumn: Column<Int?>,
|
||||
zColumn: Column<Int?>,
|
||||
): ExposedDelegate<ChunkPos?> = ChunkPosMultiColumnExposedDelegateNullable(xColumn, zColumn)
|
||||
|
||||
public class ChunkPosExposedDelegate(
|
||||
public val column: Column<String>,
|
||||
) : ExposedDelegate<ChunkPos> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): ChunkPos {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data.split(";")
|
||||
return ChunkPos(
|
||||
slices[0].toInt(),
|
||||
slices[1].toInt(),
|
||||
)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: ChunkPos,
|
||||
) {
|
||||
val parsed = value.run { "$x;$z" }
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class ChunkPosExposedDelegateNullable(
|
||||
public val column: Column<String?>,
|
||||
) : ExposedDelegate<ChunkPos?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): ChunkPos? {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data?.split(";")
|
||||
return slices?.let {
|
||||
ChunkPos(
|
||||
it[0].toInt(),
|
||||
it[1].toInt(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: ChunkPos?,
|
||||
) {
|
||||
val parsed = value?.run { "$x;$z" }
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class ChunkPosMultiColumnExposedDelegate(
|
||||
public val xColumn: Column<Int>,
|
||||
public val zColumn: Column<Int>,
|
||||
) : ExposedDelegate<ChunkPos> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): ChunkPos {
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
|
||||
return ChunkPos(x, z)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: ChunkPos,
|
||||
) {
|
||||
entity.apply {
|
||||
value.apply {
|
||||
xColumn.setValue(entity, desc, x)
|
||||
zColumn.setValue(entity, desc, z)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ChunkPosMultiColumnExposedDelegateNullable(
|
||||
public val xColumn: Column<Int?>,
|
||||
public val zColumn: Column<Int?>,
|
||||
) : ExposedDelegate<ChunkPos?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): ChunkPos? {
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
|
||||
return if (
|
||||
x != null && z != null
|
||||
) {
|
||||
ChunkPos(
|
||||
x,
|
||||
z,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: ChunkPos?,
|
||||
) {
|
||||
entity.apply {
|
||||
xColumn.setValue(entity, desc, value?.x)
|
||||
zColumn.setValue(entity, desc, value?.z)
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed.delegate
|
||||
|
||||
import org.jetbrains.exposed.dao.Entity
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public interface ExposedDelegate<T> {
|
||||
|
||||
public operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): T
|
||||
|
||||
public operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: T,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed.delegate
|
||||
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.util.io.BukkitObjectInputStream
|
||||
import org.bukkit.util.io.BukkitObjectOutputStream
|
||||
import org.jetbrains.exposed.dao.Entity
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import org.jetbrains.exposed.sql.statements.api.ExposedBlob
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* NOTE: This not save NBT and could break version to version, if you pretend
|
||||
* to upgrade your server and this keep the same, I can't guarantee that.
|
||||
*/
|
||||
public fun Entity<*>.itemStack(column: Column<ExposedBlob>): ExposedDelegate<ItemStack> = ItemStackExposedDelegate(column)
|
||||
|
||||
@JvmName("itemStackNullable")
|
||||
public fun Entity<*>.itemStack(column: Column<ExposedBlob?>): ExposedDelegate<ItemStack?> = ItemStackExposedDelegateNullable(column)
|
||||
|
||||
public class ItemStackExposedDelegate(
|
||||
public val column: Column<ExposedBlob>,
|
||||
) : ExposedDelegate<ItemStack> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): ItemStack {
|
||||
val blob = entity.run { column.getValue(this, desc) }
|
||||
return toItemStack(blob.bytes)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: ItemStack,
|
||||
) {
|
||||
val byteArray = toByteArray(value)
|
||||
val blob = ExposedBlob(byteArray)
|
||||
entity.apply { column.setValue(this, desc, blob) }
|
||||
}
|
||||
}
|
||||
|
||||
public class ItemStackExposedDelegateNullable(
|
||||
public val column: Column<ExposedBlob?>,
|
||||
) : ExposedDelegate<ItemStack?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): ItemStack? {
|
||||
val blob = entity.run { column.getValue(this, desc) }
|
||||
return blob?.bytes?.let { toItemStack(it) }
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: ItemStack?,
|
||||
) {
|
||||
val byteArray = value?.let { toByteArray(it) }
|
||||
val blob = byteArray?.let { ExposedBlob(it) }
|
||||
entity.apply { column.setValue(this, desc, blob) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun toByteArray(item: ItemStack): ByteArray {
|
||||
val outputStream = ByteArrayOutputStream()
|
||||
|
||||
BukkitObjectOutputStream(outputStream).use {
|
||||
it.writeObject(item)
|
||||
}
|
||||
|
||||
return outputStream.toByteArray()
|
||||
}
|
||||
|
||||
private fun toItemStack(byteArray: ByteArray): ItemStack {
|
||||
return ByteArrayInputStream(byteArray).use {
|
||||
BukkitObjectInputStream(it).use {
|
||||
it.readObject() as ItemStack
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed.delegate
|
||||
|
||||
import tech.carcadex.kotlinbukkitkit.extensions.world
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.Location
|
||||
import org.jetbrains.exposed.dao.Entity
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public fun Entity<*>.location(column: Column<String>): ExposedDelegate<Location> = LocationExposedDelegate(column)
|
||||
|
||||
@JvmName("locationNullable")
|
||||
public fun Entity<*>.location(column: Column<String?>): ExposedDelegate<Location?> = LocationExposedDelegateNullable(column)
|
||||
|
||||
public fun Entity<*>.location(
|
||||
worldColumn: Column<String>,
|
||||
xColumn: Column<Double>,
|
||||
yColumn: Column<Double>,
|
||||
zColumn: Column<Double>,
|
||||
yawColumn: Column<Float>,
|
||||
pitchColumn: Column<Float>,
|
||||
): ExposedDelegate<Location> = LocationMultiColumnExposedDelegate(worldColumn, xColumn, yColumn, zColumn, yawColumn, pitchColumn)
|
||||
|
||||
@JvmName("locationNullable")
|
||||
public fun Entity<*>.location(
|
||||
worldColumn: Column<String?>,
|
||||
xColumn: Column<Double?>,
|
||||
yColumn: Column<Double?>,
|
||||
zColumn: Column<Double?>,
|
||||
yawColumn: Column<Float?>,
|
||||
pitchColumn: Column<Float?>,
|
||||
): ExposedDelegate<Location?> = LocationMultiColumnExposedDelegateNullable(worldColumn, xColumn, yColumn, zColumn, yawColumn, pitchColumn)
|
||||
|
||||
public class LocationExposedDelegate(
|
||||
public val column: Column<String>,
|
||||
) : ExposedDelegate<Location> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Location {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data.split(";")
|
||||
return Location(
|
||||
Bukkit.getWorld(slices[0]),
|
||||
slices[1].toDouble(),
|
||||
slices[2].toDouble(),
|
||||
slices[3].toDouble(),
|
||||
slices[4].toFloat(),
|
||||
slices[5].toFloat(),
|
||||
)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Location,
|
||||
) {
|
||||
val world = requireNotNull(value.world) { "Location with nullable world can't be stored in database" }
|
||||
val parsed = value.run { "${world.name};$x;$y;$z;$yaw;$pitch" }
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class LocationExposedDelegateNullable(
|
||||
public val column: Column<String?>,
|
||||
) : ExposedDelegate<Location?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Location? {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data?.split(";")
|
||||
return slices?.let {
|
||||
Location(
|
||||
Bukkit.getWorld(it[0]),
|
||||
it[1].toDouble(),
|
||||
it[2].toDouble(),
|
||||
it[3].toDouble(),
|
||||
it[4].toFloat(),
|
||||
it[5].toFloat(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Location?,
|
||||
) {
|
||||
val parsed = value?.run {
|
||||
val world = requireNotNull(world) { "Location with nullable world can't be stored in database" }
|
||||
"${world.name};$x;$y;$z;$yaw;$pitch"
|
||||
}
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class LocationMultiColumnExposedDelegate(
|
||||
public val worldColumn: Column<String>,
|
||||
public val xColumn: Column<Double>,
|
||||
public val yColumn: Column<Double>,
|
||||
public val zColumn: Column<Double>,
|
||||
public val yawColumn: Column<Float>,
|
||||
public val pitchColumn: Column<Float>,
|
||||
) : ExposedDelegate<Location> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Location {
|
||||
val worldName = entity.run { worldColumn.getValue(this, desc) }
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val y = entity.run { yColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
val yaw = entity.run { yawColumn.getValue(this, desc) }
|
||||
val pitch = entity.run { pitchColumn.getValue(this, desc) }
|
||||
|
||||
return Location(
|
||||
Bukkit.getWorld(worldName),
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
yaw,
|
||||
pitch,
|
||||
)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Location,
|
||||
) {
|
||||
entity.apply {
|
||||
value.apply {
|
||||
val world = requireNotNull(world) { "Location with nullable world can't be stored in database" }
|
||||
worldColumn.setValue(entity, desc, world.name)
|
||||
xColumn.setValue(entity, desc, x)
|
||||
yColumn.setValue(entity, desc, y)
|
||||
zColumn.setValue(entity, desc, z)
|
||||
yawColumn.setValue(entity, desc, yaw)
|
||||
pitchColumn.setValue(entity, desc, pitch)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LocationMultiColumnExposedDelegateNullable(
|
||||
public val worldColumn: Column<String?>,
|
||||
public val xColumn: Column<Double?>,
|
||||
public val yColumn: Column<Double?>,
|
||||
public val zColumn: Column<Double?>,
|
||||
public val yawColumn: Column<Float?>,
|
||||
public val pitchColumn: Column<Float?>,
|
||||
) : ExposedDelegate<Location?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): Location? {
|
||||
val worldName = entity.run { worldColumn.getValue(this, desc) }
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val y = entity.run { yColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
val yaw = entity.run { yawColumn.getValue(this, desc) }
|
||||
val pitch = entity.run { pitchColumn.getValue(this, desc) }
|
||||
|
||||
return if (
|
||||
worldName != null &&
|
||||
x != null && y != null && z != null &&
|
||||
yaw != null && pitch != null
|
||||
) {
|
||||
Location(Bukkit.getWorld(worldName), x, y, z, yaw, pitch)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: Location?,
|
||||
) {
|
||||
entity.apply {
|
||||
worldColumn.setValue(entity, desc, value?.world?.name)
|
||||
xColumn.setValue(entity, desc, value?.x)
|
||||
yColumn.setValue(entity, desc, value?.y)
|
||||
zColumn.setValue(entity, desc, value?.z)
|
||||
yawColumn.setValue(entity, desc, value?.yaw)
|
||||
pitchColumn.setValue(entity, desc, value?.pitch)
|
||||
}
|
||||
}
|
||||
}
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed.delegate
|
||||
|
||||
import tech.carcadex.kotlinbukkitkit.utility.types.LocationPos
|
||||
import org.jetbrains.exposed.dao.Entity
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public fun Entity<*>.locationPos(column: Column<String>): ExposedDelegate<LocationPos> = LocationPosExposedDelegate(column)
|
||||
|
||||
@JvmName("locationPosNullable")
|
||||
public fun Entity<*>.locationPos(column: Column<String?>): ExposedDelegate<LocationPos?> = LocationPosExposedDelegateNullable(column)
|
||||
|
||||
public fun Entity<*>.locationPos(
|
||||
xColumn: Column<Double>,
|
||||
yColumn: Column<Double>,
|
||||
zColumn: Column<Double>,
|
||||
yawColumn: Column<Float>,
|
||||
pitchColumn: Column<Float>,
|
||||
): ExposedDelegate<LocationPos> = LocationPosMultiColumnExposedDelegate(xColumn, yColumn, zColumn, yawColumn, pitchColumn)
|
||||
|
||||
@JvmName("locationPosNullable")
|
||||
public fun Entity<*>.locationPos(
|
||||
xColumn: Column<Double?>,
|
||||
yColumn: Column<Double?>,
|
||||
zColumn: Column<Double?>,
|
||||
yawColumn: Column<Float?>,
|
||||
pitchColumn: Column<Float?>,
|
||||
): ExposedDelegate<LocationPos?> = LocationPosMultiColumnExposedDelegateNullable(xColumn, yColumn, zColumn, yawColumn, pitchColumn)
|
||||
|
||||
public class LocationPosExposedDelegate(
|
||||
public val column: Column<String>,
|
||||
) : ExposedDelegate<LocationPos> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): LocationPos {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data.split(";")
|
||||
return LocationPos(
|
||||
slices[0].toDouble(),
|
||||
slices[1].toDouble(),
|
||||
slices[2].toDouble(),
|
||||
slices[3].toFloat(),
|
||||
slices[4].toFloat(),
|
||||
)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: LocationPos,
|
||||
) {
|
||||
val parsed = value.run { "$x;$y;$z;$yaw;$pitch" }
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class LocationPosExposedDelegateNullable(
|
||||
public val column: Column<String?>,
|
||||
) : ExposedDelegate<LocationPos?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): LocationPos? {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
val slices = data?.split(";")
|
||||
return slices?.let {
|
||||
LocationPos(
|
||||
it[0].toDouble(),
|
||||
it[1].toDouble(),
|
||||
it[2].toDouble(),
|
||||
it[3].toFloat(),
|
||||
it[4].toFloat(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: LocationPos?,
|
||||
) {
|
||||
val parsed = value?.run { "$x;$y;$z;$yaw;$pitch" }
|
||||
entity.apply { column.setValue(this, desc, parsed) }
|
||||
}
|
||||
}
|
||||
|
||||
public class LocationPosMultiColumnExposedDelegate(
|
||||
public val xColumn: Column<Double>,
|
||||
public val yColumn: Column<Double>,
|
||||
public val zColumn: Column<Double>,
|
||||
public val yawColumn: Column<Float>,
|
||||
public val pitchColumn: Column<Float>,
|
||||
) : ExposedDelegate<LocationPos> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): LocationPos {
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val y = entity.run { yColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
val yaw = entity.run { yawColumn.getValue(this, desc) }
|
||||
val pitch = entity.run { pitchColumn.getValue(this, desc) }
|
||||
|
||||
return LocationPos(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
yaw,
|
||||
pitch,
|
||||
)
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: LocationPos,
|
||||
) {
|
||||
entity.apply {
|
||||
value.apply {
|
||||
xColumn.setValue(entity, desc, x)
|
||||
yColumn.setValue(entity, desc, y)
|
||||
zColumn.setValue(entity, desc, z)
|
||||
yawColumn.setValue(entity, desc, yaw)
|
||||
pitchColumn.setValue(entity, desc, pitch)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LocationPosMultiColumnExposedDelegateNullable(
|
||||
public val xColumn: Column<Double?>,
|
||||
public val yColumn: Column<Double?>,
|
||||
public val zColumn: Column<Double?>,
|
||||
public val yawColumn: Column<Float?>,
|
||||
public val pitchColumn: Column<Float?>,
|
||||
) : ExposedDelegate<LocationPos?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): LocationPos? {
|
||||
val x = entity.run { xColumn.getValue(this, desc) }
|
||||
val y = entity.run { yColumn.getValue(this, desc) }
|
||||
val z = entity.run { zColumn.getValue(this, desc) }
|
||||
val yaw = entity.run { yawColumn.getValue(this, desc) }
|
||||
val pitch = entity.run { pitchColumn.getValue(this, desc) }
|
||||
|
||||
return if (
|
||||
x != null && y != null && z != null &&
|
||||
yaw != null && pitch != null
|
||||
) {
|
||||
LocationPos(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
yaw,
|
||||
pitch,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: LocationPos?,
|
||||
) {
|
||||
entity.apply {
|
||||
xColumn.setValue(entity, desc, value?.x)
|
||||
yColumn.setValue(entity, desc, value?.y)
|
||||
zColumn.setValue(entity, desc, value?.z)
|
||||
yawColumn.setValue(entity, desc, value?.yaw)
|
||||
pitchColumn.setValue(entity, desc, value?.pitch)
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed.delegate
|
||||
|
||||
import tech.carcadex.kotlinbukkitkit.extensions.offlinePlayer
|
||||
import org.bukkit.OfflinePlayer
|
||||
import org.jetbrains.exposed.dao.Entity
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import java.util.*
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public fun Entity<*>.offlinePlayer(column: Column<UUID>): ExposedDelegate<OfflinePlayer> = OfflinePlayerExposedDelegate(column)
|
||||
|
||||
@JvmName("offlinePlayerNullable")
|
||||
public fun Entity<*>.offlinePlayer(column: Column<UUID?>): ExposedDelegate<OfflinePlayer?> = OfflinePlayerExposedDelegateNullable(column)
|
||||
|
||||
public class OfflinePlayerExposedDelegate(
|
||||
public val column: Column<UUID>,
|
||||
) : ExposedDelegate<OfflinePlayer> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): OfflinePlayer {
|
||||
val uuid = entity.run { column.getValue(this, desc) }
|
||||
return offlinePlayer(uuid)
|
||||
}
|
||||
override operator fun <ID : Comparable<ID>> setValue(entity: Entity<ID>, desc: KProperty<*>, value: OfflinePlayer) {
|
||||
entity.apply { column.setValue(this, desc, value.uniqueId) }
|
||||
}
|
||||
}
|
||||
|
||||
public class OfflinePlayerExposedDelegateNullable(
|
||||
public val column: Column<UUID?>,
|
||||
) : ExposedDelegate<OfflinePlayer?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): OfflinePlayer? {
|
||||
val uuid = entity.run { column.getValue(this, desc) }
|
||||
return uuid?.let { offlinePlayer(it) }
|
||||
}
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: OfflinePlayer?,
|
||||
) {
|
||||
entity.apply { column.setValue(this, desc, value?.uniqueId) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package tech.carcadex.kotlinbukkitkit.exposed.delegate
|
||||
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.World
|
||||
import org.jetbrains.exposed.dao.Entity
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public fun Entity<*>.world(column: Column<String>): ExposedDelegate<World> = WorldExposedDelegate(column)
|
||||
|
||||
@JvmName("worldNullable")
|
||||
public fun Entity<*>.world(column: Column<String?>): ExposedDelegate<World?> = WorldExposedDelegateNullable(column)
|
||||
|
||||
public class WorldExposedDelegate(
|
||||
public val column: Column<String>,
|
||||
) : ExposedDelegate<World> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): World {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
return requireNotNull(Bukkit.getWorld(data)) { "World '$data' retrieving from database not loaded at server." }
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: World,
|
||||
) {
|
||||
entity.apply { column.setValue(this, desc, value.name) }
|
||||
}
|
||||
}
|
||||
|
||||
public class WorldExposedDelegateNullable(
|
||||
public val column: Column<String?>,
|
||||
) : ExposedDelegate<World?> {
|
||||
override operator fun <ID : Comparable<ID>> getValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
): World? {
|
||||
val data = entity.run { column.getValue(this, desc) }
|
||||
return data?.let { Bukkit.getWorld(it) }
|
||||
}
|
||||
|
||||
override operator fun <ID : Comparable<ID>> setValue(
|
||||
entity: Entity<ID>,
|
||||
desc: KProperty<*>,
|
||||
value: World?,
|
||||
) {
|
||||
entity.apply { column.setValue(this, desc, value?.name) }
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user