summaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt')
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt322
1 files changed, 0 insertions, 322 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt b/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt
deleted file mode 100644
index cbcb6f4..0000000
--- a/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt
+++ /dev/null
@@ -1,322 +0,0 @@
-package io.dico.parcels2.storage
-
-import com.zaxxer.hikari.HikariDataSource
-import io.dico.parcels2.*
-import io.dico.parcels2.util.Vec2i
-import io.dico.parcels2.util.toByteArray
-import io.dico.parcels2.util.toUUID
-import kotlinx.coroutines.experimental.channels.ProducerScope
-import org.jetbrains.exposed.sql.*
-import org.jetbrains.exposed.sql.SchemaUtils.create
-import org.jetbrains.exposed.sql.transactions.transaction
-import org.jetbrains.exposed.sql.vendors.DatabaseDialect
-import org.joda.time.DateTime
-import java.util.*
-import javax.sql.DataSource
-
-object WorldsT : Table("worlds") {
- val id = integer("world_id").autoIncrement().primaryKey()
- val name = varchar("name", 50)
- val uid = binary("uid", 16)
- val index_uid = uniqueIndexR("index_uid", uid)
-}
-
-object ParcelsT : Table("parcels") {
- val id = integer("parcel_id").autoIncrement().primaryKey()
- val px = integer("px")
- val pz = integer("pz")
- val world_id = integer("world_id").references(WorldsT.id)
- val owner_uuid = binary("owner_uuid", 16).nullable()
- val owner_name = varchar("owner_name", 16).nullable()
- val claim_time = datetime("claim_time").nullable()
- val index_location = uniqueIndexR("index_location", world_id, px, pz)
-}
-
-object AddedLocalT : Table("parcels_added_local") {
- val parcel_id = integer("parcel_id").references(ParcelsT.id, ReferenceOption.CASCADE)
- val player_uuid = binary("player_uuid", 16)
- val allowed_flag = bool("allowed_flag")
- val index_pair = uniqueIndexR("index_pair", parcel_id, player_uuid)
-}
-
-object AddedGlobalT : Table("parcels_added_global") {
- val owner_uuid = binary("owner_uuid", 16)
- val player_uuid = binary("player_uuid", 16)
- val allowed_flag = bool("allowed_flag")
- val index_pair = uniqueIndexR("index_pair", owner_uuid, player_uuid)
-}
-
-object ParcelOptionsT : Table("parcel_options") {
- val parcel_id = integer("parcel_id").primaryKey().references(ParcelsT.id, ReferenceOption.CASCADE)
- val interact_inventory = bool("interact_inventory").default(false)
- val interact_inputs = bool("interact_inputs").default(false)
-}
-
-private class ExposedDatabaseException(message: String? = null) : Exception(message)
-
-@Suppress("NOTHING_TO_INLINE")
-class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing {
- override val name get() = "Exposed"
- private var dataSource: DataSource? = null
- private var database: Database? = null
- private var isShutdown: Boolean = false
-
- override val isConnected get() = database != null
-
- companion object {
- init {
- Database.registerDialect("mariadb") {
- Class.forName("org.jetbrains.exposed.sql.vendors.MysqlDialect").newInstance() as DatabaseDialect
- }
- }
- }
-
- override suspend fun init() {
- if (isShutdown) throw IllegalStateException()
- dataSource = dataSourceFactory()
- database = Database.connect(dataSource!!)
- transaction(database) {
- create(WorldsT, ParcelsT, AddedLocalT, ParcelOptionsT)
- }
- }
-
- override suspend fun shutdown() {
- if (isShutdown) throw IllegalStateException()
- dataSource?.let {
- if (it is HikariDataSource) it.close()
- }
- database = null
- isShutdown = true
- }
-
- private fun <T> transaction(statement: Transaction.() -> T) = transaction(database, statement)
-
- private inline fun Transaction.getWorldId(binaryUid: ByteArray): Int? {
- return WorldsT.select { WorldsT.uid eq binaryUid }.firstOrNull()?.let { it[WorldsT.id] }
- }
-
- private inline fun Transaction.getWorldId(worldUid: UUID): Int? {
- return getWorldId(worldUid.toByteArray()!!)
- }
-
- private inline fun Transaction.getOrInitWorldId(worldUid: UUID, worldName: String): Int {
- val binaryUid = worldUid.toByteArray()!!
- return getWorldId(binaryUid)
- ?: WorldsT.insert /*Ignore*/ { it[uid] = binaryUid; it[name] = worldName }.get(WorldsT.id)
- ?: throw ExposedDatabaseException("This should not happen - failed to insert world named $worldName and get its id")
- }
-
- private inline fun Transaction.getParcelId(worldId: Int, parcelX: Int, parcelZ: Int): Int? {
- return ParcelsT.select { (ParcelsT.world_id eq worldId) and (ParcelsT.px eq parcelX) and (ParcelsT.pz eq parcelZ) }
- .firstOrNull()?.let { it[ParcelsT.id] }
- }
-
- private inline fun Transaction.getParcelId(worldUid: UUID, parcelX: Int, parcelZ: Int): Int? {
- return getWorldId(worldUid)?.let { getParcelId(it, parcelX, parcelZ) }
- }
-
- private inline fun Transaction.getOrInitParcelId(worldUid: UUID, worldName: String, parcelX: Int, parcelZ: Int): Int {
- val worldId = getOrInitWorldId(worldUid, worldName)
- return getParcelId(worldId, parcelX, parcelZ)
- ?: ParcelsT.insert /*Ignore*/ { it[world_id] = worldId; it[px] = parcelX; it[pz] = parcelZ }.get(ParcelsT.id)
- ?: throw ExposedDatabaseException("This should not happen - failed to insert parcel at $worldName($parcelX, $parcelZ)")
- }
-
- private inline fun Transaction.getParcelRow(id: Int): ResultRow? {
- return ParcelsT.select { ParcelsT.id eq id }.firstOrNull()
- }
-
- fun Transaction.getWorldId(world: ParcelWorld): Int? {
- return getWorldId(world.world.uid)
- }
-
- fun Transaction.getOrInitWorldId(world: ParcelWorld): Int {
- return world.world.let { getOrInitWorldId(it.uid, it.name) }
- }
-
- fun Transaction.getParcelId(parcel: Parcel): Int? {
- return getParcelId(parcel.world.world.uid, parcel.pos.x, parcel.pos.z)
- }
-
- fun Transaction.getOrInitParcelId(parcel: Parcel): Int {
- return parcel.world.world.let { getOrInitParcelId(it.uid, it.name, parcel.pos.x, parcel.pos.z) }
- }
-
- fun Transaction.getParcelRow(parcel: Parcel): ResultRow? {
- return getParcelId(parcel)?.let { getParcelRow(it) }
- }
-
- override suspend fun ProducerScope<Pair<Parcel, ParcelData?>>.produceParcelData(parcels: Sequence<Parcel>) {
- for (parcel in parcels) {
- val data = readParcelData(parcel)
- channel.send(parcel to data)
- }
- channel.close()
- }
-
- override suspend fun ProducerScope<Pair<SerializableParcel, ParcelData?>>.produceAllParcelData() {
- ParcelsT.selectAll().forEach { row ->
- val parcel = rowToSerializableParcel(row) ?: return@forEach
- val data = rowToParcelData(row)
- channel.send(parcel to data)
- }
- channel.close()
- }
-
- override suspend fun readParcelData(parcelFor: Parcel): ParcelData? = transaction {
- val row = getParcelRow(parcelFor) ?: return@transaction null
- rowToParcelData(row)
- }
-
- override suspend fun getOwnedParcels(user: ParcelOwner): List<SerializableParcel> = transaction {
- val where: SqlExpressionBuilder.() -> Op<Boolean>
-
- if (user.uuid != null) {
- val binaryUuid = user.uuid.toByteArray()
- where = { ParcelsT.owner_uuid eq binaryUuid }
- } else {
- val name = user.name
- where = { ParcelsT.owner_name eq name }
- }
-
- ParcelsT.select(where)
- .orderBy(ParcelsT.claim_time, isAsc = true)
- .mapNotNull(::rowToSerializableParcel)
- .toList()
- }
-
-
- override suspend fun setParcelData(parcelFor: Parcel, data: ParcelData?) {
- if (data == null) {
- transaction {
- getParcelId(parcelFor)?.let { id ->
- ParcelsT.deleteIgnoreWhere() { ParcelsT.id eq id }
-
- // Below should cascade automatically
- /*
- AddedLocalT.deleteIgnoreWhere { AddedLocalT.parcel_id eq id }
- ParcelOptionsT.deleteIgnoreWhere(limit = 1) { ParcelOptionsT.parcel_id eq id }
- */
- }
-
- }
- return
- }
-
- val id = transaction {
- val id = getOrInitParcelId(parcelFor)
- AddedLocalT.deleteIgnoreWhere { AddedLocalT.parcel_id eq id }
- id
- }
-
- setParcelOwner(parcelFor, data.owner)
-
- for ((uuid, status) in data.added) {
- val state = status.asBoolean
- setParcelPlayerState(parcelFor, uuid, state)
- }
-
- setParcelAllowsInteractInputs(parcelFor, data.allowInteractInputs)
- setParcelAllowsInteractInventory(parcelFor, data.allowInteractInventory)
- }
-
- override suspend fun setParcelOwner(parcelFor: Parcel, owner: ParcelOwner?) = transaction {
- val binaryUuid = owner?.uuid?.toByteArray()
- val name = owner?.name
- val time = owner?.let { DateTime.now() }
-
- val id = if (owner == null)
- getParcelId(parcelFor) ?: return@transaction
- else
- getOrInitParcelId(parcelFor)
-
- ParcelsT.update({ ParcelsT.id eq id }) {
- it[ParcelsT.owner_uuid] = binaryUuid
- it[ParcelsT.owner_name] = name
- it[ParcelsT.claim_time] = time
- }
- }
-
- override suspend fun setParcelPlayerState(parcelFor: Parcel, player: UUID, state: Boolean?) = transaction {
- val binaryUuid = player.toByteArray()!!
-
- if (state == null) {
- getParcelId(parcelFor)?.let { id ->
- AddedLocalT.deleteWhere { (AddedLocalT.parcel_id eq id) and (AddedLocalT.player_uuid eq binaryUuid) }
- }
- return@transaction
- }
-
- val id = getOrInitParcelId(parcelFor)
- AddedLocalT.upsert(AddedLocalT.parcel_id) {
- it[AddedLocalT.parcel_id] = id
- it[AddedLocalT.player_uuid] = binaryUuid
- }
- }
-
- override suspend fun setParcelAllowsInteractInventory(parcel: Parcel, value: Boolean): Unit = transaction {
- val id = getOrInitParcelId(parcel)
- /*ParcelOptionsT.upsert(ParcelOptionsT.parcel_id) {
- it[ParcelOptionsT.parcel_id] = id
- it[ParcelOptionsT.interact_inventory] = value
- }*/
-
- ParcelOptionsT.upsert(ParcelOptionsT.parcel_id) {
- it[ParcelOptionsT.parcel_id] = id
- it[ParcelOptionsT.interact_inventory] = value
- }
- }
-
- override suspend fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean): Unit = transaction {
- val id = getOrInitParcelId(parcel)
- ParcelOptionsT.upsert(ParcelOptionsT.parcel_id) {
- it[ParcelOptionsT.parcel_id] = id
- it[ParcelOptionsT.interact_inputs] = value
- }
- }
-
- override suspend fun readGlobalPlayerStateData(owner: ParcelOwner): AddedData? {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
- }
-
- override suspend fun setGlobalPlayerState(owner: ParcelOwner, player: UUID, state: Boolean?) {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
- }
-
- private fun rowToSerializableParcel(row: ResultRow): SerializableParcel? {
- val worldId = row[ParcelsT.world_id]
- val worldRow = WorldsT.select { WorldsT.id eq worldId }.firstOrNull()
- ?: return null
-
- val world = SerializableWorld(worldRow[WorldsT.name], worldRow[WorldsT.uid].toUUID())
- return SerializableParcel(world, Vec2i(row[ParcelsT.px], row[ParcelsT.pz]))
- }
-
- private fun rowToParcelData(row: ResultRow) = ParcelDataHolder().apply {
- owner = ParcelOwner.create(
- uuid = row[ParcelsT.owner_uuid]?.toUUID(),
- name = row[ParcelsT.owner_name],
- time = row[ParcelsT.claim_time]
- )
-
- val parcelId = row[ParcelsT.id]
- AddedLocalT.select { AddedLocalT.parcel_id eq parcelId }.forEach {
- val uuid = it[AddedLocalT.player_uuid].toUUID()!!
- val status = if (it[AddedLocalT.allowed_flag]) AddedStatus.ALLOWED else AddedStatus.BANNED
- setAddedStatus(uuid, status)
- }
-
- ParcelOptionsT.select { ParcelOptionsT.parcel_id eq parcelId }.firstOrNull()?.let {
- allowInteractInputs = it[ParcelOptionsT.interact_inputs]
- allowInteractInventory = it[ParcelOptionsT.interact_inventory]
- }
- }
-
-}
-
-
-
-
-
-
-