summaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/dico/parcels2/storage
diff options
context:
space:
mode:
authorDico200 <dico.karssiens@gmail.com>2018-07-23 02:23:46 +0200
committerDico200 <dico.karssiens@gmail.com>2018-07-23 02:23:46 +0200
commit42026191ec3a1f6468d8a46304d6ce5cd2d0689c (patch)
tree9af249ea52a7485e665828ca8654f846d55ec204 /src/main/kotlin/io/dico/parcels2/storage
parent13b73dad61e8624322df7fb9ddf9bab90db9cc95 (diff)
Initial exposed backing implementation
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/storage')
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/Backing.kt20
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/Exposed.kt90
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt281
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt36
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/Jackson.kt11
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/SerializableTypes.kt2
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/Storage.kt29
7 files changed, 356 insertions, 113 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/storage/Backing.kt b/src/main/kotlin/io/dico/parcels2/storage/Backing.kt
index cd33b3d..0f8829d 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/Backing.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/Backing.kt
@@ -3,7 +3,6 @@ package io.dico.parcels2.storage
import io.dico.parcels2.Parcel
import io.dico.parcels2.ParcelData
import io.dico.parcels2.ParcelOwner
-import io.dico.parcels2.storage.SerializableParcel
import kotlinx.coroutines.experimental.channels.ProducerScope
import java.util.*
@@ -15,23 +14,26 @@ interface Backing {
suspend fun shutdown()
+
/**
- * This producer function is capable of constantly reading plots from a potentially infinite sequence,
- * and provide plotdata for it as read from the database.
+ * This producer function is capable of constantly reading parcels from a potentially infinite sequence,
+ * and provide parcel data for it as read from the database.
*/
-
suspend fun ProducerScope<Pair<Parcel, ParcelData?>>.produceParcelData(parcels: Sequence<Parcel>)
- suspend fun readParcelData(plotFor: Parcel): ParcelData?
+ suspend fun readParcelData(parcelFor: Parcel): ParcelData?
suspend fun getOwnedParcels(user: ParcelOwner): List<SerializableParcel>
- suspend fun setParcelOwner(plotFor: Parcel, owner: ParcelOwner?)
- suspend fun setParcelPlayerState(plotFor: Parcel, player: UUID, state: Boolean?)
+ suspend fun setParcelData(parcelFor: Parcel, data: ParcelData?)
+
+ suspend fun setParcelOwner(parcelFor: Parcel, owner: ParcelOwner?)
+
+ suspend fun setParcelPlayerState(parcelFor: Parcel, player: UUID, state: Boolean?)
- suspend fun setParcelAllowsInteractInventory(plot: Parcel, value: Boolean)
+ suspend fun setParcelAllowsInteractInventory(parcel: Parcel, value: Boolean)
- suspend fun setParcelAllowsInteractInputs(plot: Parcel, value: Boolean)
+ suspend fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean)
} \ No newline at end of file
diff --git a/src/main/kotlin/io/dico/parcels2/storage/Exposed.kt b/src/main/kotlin/io/dico/parcels2/storage/Exposed.kt
deleted file mode 100644
index cbb5887..0000000
--- a/src/main/kotlin/io/dico/parcels2/storage/Exposed.kt
+++ /dev/null
@@ -1,90 +0,0 @@
-package io.dico.parcels2.storage
-
-import com.zaxxer.hikari.HikariDataSource
-import io.dico.parcels2.Parcel
-import io.dico.parcels2.ParcelData
-import io.dico.parcels2.ParcelOwner
-import kotlinx.coroutines.experimental.channels.ProducerScope
-import org.jetbrains.exposed.sql.Database
-import org.jetbrains.exposed.sql.ReferenceOption
-import org.jetbrains.exposed.sql.Table
-import org.jetbrains.exposed.sql.transactions.transaction
-import java.util.*
-import javax.sql.DataSource
-import org.jetbrains.exposed.sql.SchemaUtils.create
-
-object ParcelsTable : Table() {
- val id = integer("id").autoIncrement().primaryKey()
- val px = integer("px")
- val pz = integer("pz")
- val world_uuid = binary("world_uuid", 16).also { uniqueIndex("location", it, px, pz) }
- val world = varchar("world", 32).nullable()
- val owner_uuid = binary("owner_uuid", 16).nullable()
- val owner = varchar("owner", 16).nullable()
-}
-
-object ParcelsAddedTable : Table() {
- val id = integer("id").references(ParcelsTable.id, ReferenceOption.CASCADE)
- val player_uuid = binary("player_uuid", 16).also { uniqueIndex("pair", id, it) }
- val allowed_flag = bool("allowed_flag")
-}
-
-object PlayerAddedTable : Table() {
- val owner_uuid = binary("owner_uuid", 16)
- val player_uuid = binary("player_uuid", 16).also { uniqueIndex("pair", owner_uuid, it) }
- val allowed_flag = bool("allowed_flag")
-}
-
-class ExposedBacking(val dataSource: DataSource) : Backing {
- override val name get() = "Exposed"
- lateinit var database: Database
-
- override suspend fun init() {
- database = Database.connect(dataSource)
- transaction(database) {
- create(ParcelsTable, ParcelsAddedTable)
- }
- }
-
- override suspend fun shutdown() {
- if (dataSource is HikariDataSource) {
- dataSource.close()
- }
- }
-
- override suspend fun ProducerScope<Pair<Parcel, ParcelData?>>.produceParcelData(parcels: Sequence<Parcel>) {
- TODO()
- }
-
- override suspend fun readParcelData(plotFor: Parcel): ParcelData? {
- TODO()
- }
-
- override suspend fun getOwnedParcels(user: ParcelOwner): List<SerializableParcel> {
- TODO()
- }
-
- override suspend fun setParcelOwner(plotFor: Parcel, owner: ParcelOwner?) {
- TODO()
- }
-
- override suspend fun setParcelPlayerState(plotFor: Parcel, player: UUID, state: Boolean?) {
- TODO()
- }
-
- override suspend fun setParcelAllowsInteractInventory(plot: Parcel, value: Boolean) {
- TODO()
- }
-
- override suspend fun setParcelAllowsInteractInputs(plot: Parcel, value: Boolean) {
- TODO()
- }
-
-}
-
-
-
-
-
-
-
diff --git a/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt b/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt
new file mode 100644
index 0000000..e79c7e0
--- /dev/null
+++ b/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt
@@ -0,0 +1,281 @@
+package io.dico.parcels2.storage
+
+import com.zaxxer.hikari.HikariDataSource
+import io.dico.parcels2.*
+import io.dico.parcels2.math.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 java.util.*
+import javax.sql.DataSource
+
+object WorldsT : Table("worlds") {
+ val id = integer("id").autoIncrement().primaryKey()
+ val name = varchar("name", 50)
+ val uid = binary("uid", 16)
+ .also { uniqueIndex("index_uid", it) }
+}
+
+object ParcelsT : Table("parcels") {
+ val id = integer("id").autoIncrement().primaryKey()
+ val px = integer("px")
+ val pz = integer("pz")
+ val world_id = integer("id")
+ .also { uniqueIndex("index_location", it, px, pz) }
+ .references(WorldsT.id)
+ val owner_uuid = binary("owner_uuid", 16).nullable()
+ val owner_name = varchar("owner_name", 16).nullable()
+}
+
+object AddedLocalT : Table("parcels_added_local") {
+ val parcel_id = integer("parcel_id")
+ .references(ParcelsT.id, ReferenceOption.CASCADE)
+ val player_uuid = binary("player_uuid", 16)
+ .also { uniqueIndex("index_pair", parcel_id, it) }
+ val allowed_flag = bool("allowed_flag")
+}
+
+object AddedGlobalT : Table("parcels_added_global") {
+ val owner_uuid = binary("owner_uuid", 16)
+ val player_uuid = binary("player_uuid", 16)
+ .also { uniqueIndex("index_pair", owner_uuid, it) }
+ val allowed_flag = bool("allowed_flag")
+}
+
+object ParcelOptionsT : Table("parcel_options") {
+ val parcel_id = integer("parcel_id")
+ .also { uniqueIndex("index_parcel_id", it) }
+ .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(val dataSource: DataSource) : Backing {
+ override val name get() = "Exposed"
+ lateinit var database: Database
+
+ override suspend fun init() {
+ database = Database.connect(dataSource)
+ transaction(database) {
+ create(ParcelsT, AddedLocalT)
+ }
+ }
+
+ override suspend fun shutdown() {
+ if (dataSource is HikariDataSource) {
+ dataSource.close()
+ }
+ }
+
+ 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.insertIgnore { 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.insertIgnore { 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 readParcelData(parcelFor: Parcel): ParcelData? = transaction {
+ val row = getParcelRow(parcelFor) ?: return@transaction null
+
+ ParcelDataHolder().apply {
+
+ owner = ParcelOwner.create(
+ uuid = row[ParcelsT.owner_uuid]?.toUUID(),
+ name = row[ParcelsT.owner_name]
+ )
+
+ 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]
+ }
+
+ }
+
+ }
+
+ 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)
+ .map { parcelRow ->
+ val worldId = parcelRow[ParcelsT.world_id]
+ val worldRow = WorldsT.select({ WorldsT.id eq worldId }).firstOrNull()
+ ?: return@map null
+
+ val world = SerializableWorld(worldRow[WorldsT.name], worldRow[WorldsT.uid].toUUID())
+ SerializableParcel(world, Vec2i(parcelRow[ParcelsT.px], parcelRow[ParcelsT.pz]))
+ }
+ .filterNotNull()
+ .toList()
+ }
+
+
+ override suspend fun setParcelData(parcelFor: Parcel, data: ParcelData?) {
+ if (data == null) {
+ transaction {
+ getParcelId(parcelFor)?.let { id ->
+ ParcelsT.deleteIgnoreWhere(limit = 1) { 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 id = if (owner == null)
+ getParcelId(parcelFor) ?: return@transaction
+ else
+ getOrInitParcelId(parcelFor)
+
+ ParcelsT.update({ ParcelsT.id eq id }, limit = 1) {
+ it[ParcelsT.owner_uuid] = binaryUuid
+ it[ParcelsT.owner_name] = name
+ }
+ }
+
+ 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.insertOrUpdate(AddedLocalT.allowed_flag) {
+ 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.insertOrUpdate(ParcelOptionsT.interact_inventory) {
+ 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.insertOrUpdate(ParcelOptionsT.interact_inputs) {
+ it[ParcelOptionsT.parcel_id] = id
+ it[ParcelOptionsT.interact_inputs] = value
+ }
+ }
+
+}
+
+
+
+
+
+
+
diff --git a/src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt b/src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt
new file mode 100644
index 0000000..f429d7e
--- /dev/null
+++ b/src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt
@@ -0,0 +1,36 @@
+package io.dico.parcels2.storage
+
+import org.jetbrains.exposed.sql.Column
+import org.jetbrains.exposed.sql.Table
+import org.jetbrains.exposed.sql.Transaction
+import org.jetbrains.exposed.sql.statements.InsertStatement
+import org.jetbrains.exposed.sql.transactions.TransactionManager
+
+/*
+ * insertOrUpdate from https://github.com/JetBrains/Exposed/issues/167#issuecomment-403837917
+ */
+inline fun <T : Table> T.insertOrUpdate(vararg onDuplicateUpdateKeys: Column<*>, body: T.(InsertStatement<Number>) -> Unit) =
+ InsertOrUpdate<Number>(onDuplicateUpdateKeys, this).apply {
+ body(this)
+ execute(TransactionManager.current())
+ }
+
+class InsertOrUpdate<Key : Any>(
+ private val onDuplicateUpdateKeys: Array<out Column<*>>,
+ table: Table,
+ isIgnore: Boolean = false
+) : InsertStatement<Key>(table, isIgnore) {
+ override fun prepareSQL(transaction: Transaction): String {
+ val onUpdateSQL = if (onDuplicateUpdateKeys.isNotEmpty()) {
+ " ON DUPLICATE KEY UPDATE " + onDuplicateUpdateKeys.joinToString { "${transaction.identity(it)}=VALUES(${transaction.identity(it)})" }
+ } else ""
+ return super.prepareSQL(transaction) + onUpdateSQL
+ }
+}
+
+
+
+
+
+
+
diff --git a/src/main/kotlin/io/dico/parcels2/storage/Jackson.kt b/src/main/kotlin/io/dico/parcels2/storage/Jackson.kt
index b5bdbeb..08ca810 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/Jackson.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/Jackson.kt
@@ -22,12 +22,15 @@ val yamlObjectMapper = ObjectMapper(YAMLFactory()).apply {
with(kotlinModule) {
setSerializerModifier(object : BeanSerializerModifier() {
@Suppress("UNCHECKED_CAST")
- override fun modifySerializer(config: SerializationConfig?, beanDesc: BeanDescription?, serializer: JsonSerializer<*>?): JsonSerializer<*> {
- if (GeneratorOptions::class.isSuperclassOf(beanDesc?.beanClass?.kotlin as KClass<*>)) {
- return GeneratorOptionsSerializer(serializer as JsonSerializer<GeneratorOptions>)
+ override fun modifySerializer(config: SerializationConfig?, beanDesc: BeanDescription, serializer: JsonSerializer<*>): JsonSerializer<*> {
+
+ val newSerializer = if (GeneratorOptions::class.isSuperclassOf(beanDesc.beanClass.kotlin)) {
+ GeneratorOptionsSerializer(serializer as JsonSerializer<GeneratorOptions>)
+ } else {
+ serializer
}
- return super.modifySerializer(config, beanDesc, serializer)
+ return super.modifySerializer(config, beanDesc, newSerializer)
}
})
diff --git a/src/main/kotlin/io/dico/parcels2/storage/SerializableTypes.kt b/src/main/kotlin/io/dico/parcels2/storage/SerializableTypes.kt
index 4e467b1..121e251 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/SerializableTypes.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/SerializableTypes.kt
@@ -22,7 +22,7 @@ data class SerializableWorld(val name: String? = null,
* Used by storage backing options to encompass the location of a parcel
*/
data class SerializableParcel(val world: SerializableWorld,
- val coord: Vec2i) {
+ val pos: Vec2i) {
val parcel: Parcel? by lazy { TODO() }
} \ No newline at end of file
diff --git a/src/main/kotlin/io/dico/parcels2/storage/Storage.kt b/src/main/kotlin/io/dico/parcels2/storage/Storage.kt
index 36f5400..67c4b05 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/Storage.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/Storage.kt
@@ -19,12 +19,16 @@ interface Storage {
fun shutdown(): Deferred<Unit>
+
fun readParcelData(parcelFor: Parcel): Deferred<ParcelData?>
fun readParcelData(parcelsFor: Sequence<Parcel>, channelCapacity: Int): ReceiveChannel<Pair<Parcel, ParcelData?>>
fun getOwnedParcels(user: ParcelOwner): Deferred<List<SerializableParcel>>
+
+ fun setParcelData(parcelFor: Parcel, data: ParcelData?): Deferred<Unit>
+
fun setParcelOwner(parcelFor: Parcel, owner: ParcelOwner?): Deferred<Unit>
fun setParcelPlayerState(parcelFor: Parcel, player: UUID, state: Boolean?): Deferred<Unit>
@@ -41,25 +45,32 @@ class StorageWithCoroutineBacking internal constructor(val backing: Backing) : S
val poolSize: Int get() = 4
override val asyncDispatcher = Executors.newFixedThreadPool(poolSize) { Thread(it, "Parcels2_StorageThread") }.asCoroutineDispatcher()
- private fun <T> future(block: suspend CoroutineScope.() -> T) = async(context = asyncDispatcher, start = CoroutineStart.ATOMIC, block = block)
+ @Suppress("NOTHING_TO_INLINE")
+ private inline fun <T> defer(noinline block: suspend CoroutineScope.() -> T): Deferred<T> {
+ return async(context = asyncDispatcher, start = CoroutineStart.ATOMIC, block = block)
+ }
- override fun init() = future { backing.init() }
+ override fun init() = defer { backing.init() }
- override fun shutdown() = future { backing.shutdown() }
+ override fun shutdown() = defer { backing.shutdown() }
- override fun readParcelData(parcelFor: Parcel) = future { backing.readParcelData(parcelFor) }
+
+ override fun readParcelData(parcelFor: Parcel) = defer { backing.readParcelData(parcelFor) }
override fun readParcelData(parcelsFor: Sequence<Parcel>, channelCapacity: Int) = produce(asyncDispatcher, capacity = channelCapacity) {
with(backing) { produceParcelData(parcelsFor) }
}
- override fun getOwnedParcels(user: ParcelOwner) = future { backing.getOwnedParcels(user) }
- override fun setParcelOwner(parcelFor: Parcel, owner: ParcelOwner?) = future { backing.setParcelOwner(parcelFor, owner) }
+ override fun setParcelData(parcelFor: Parcel, data: ParcelData?) = defer { backing.setParcelData(parcelFor, data) }
+
+ override fun getOwnedParcels(user: ParcelOwner) = defer { backing.getOwnedParcels(user) }
+
+ override fun setParcelOwner(parcelFor: Parcel, owner: ParcelOwner?) = defer { backing.setParcelOwner(parcelFor, owner) }
- override fun setParcelPlayerState(parcelFor: Parcel, player: UUID, state: Boolean?) = future { backing.setParcelPlayerState(parcelFor, player, state) }
+ override fun setParcelPlayerState(parcelFor: Parcel, player: UUID, state: Boolean?) = defer { backing.setParcelPlayerState(parcelFor, player, state) }
- override fun setParcelAllowsInteractInventory(parcel: Parcel, value: Boolean) = future { backing.setParcelAllowsInteractInventory(parcel, value) }
+ override fun setParcelAllowsInteractInventory(parcel: Parcel, value: Boolean) = defer { backing.setParcelAllowsInteractInventory(parcel, value) }
- override fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean) = future { backing.setParcelAllowsInteractInputs(parcel, value) }
+ override fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean) = defer { backing.setParcelAllowsInteractInputs(parcel, value) }
}