Look at some DB stuff

This commit is contained in:
Dico200
2018-07-28 00:31:55 +01:00
parent 2c1aee89f6
commit 547ffcb0ba
11 changed files with 99 additions and 54 deletions
+7 -5
View File
@@ -1,6 +1,6 @@
package io.dico.parcels2 package io.dico.parcels2
import io.dico.parcels2.math.Vec2i import io.dico.parcels2.util.Vec2i
import io.dico.parcels2.util.getPlayerName import io.dico.parcels2.util.getPlayerName
import io.dico.parcels2.util.hasBuildAnywhere import io.dico.parcels2.util.hasBuildAnywhere
import io.dico.parcels2.util.isValid import io.dico.parcels2.util.isValid
@@ -8,6 +8,7 @@ import io.dico.parcels2.util.uuid
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.OfflinePlayer import org.bukkit.OfflinePlayer
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.joda.time.DateTime
import java.util.* import java.util.*
interface AddedData { interface AddedData {
@@ -148,12 +149,13 @@ enum class AddedStatus {
@Suppress("UsePropertyAccessSyntax") @Suppress("UsePropertyAccessSyntax")
class ParcelOwner(val uuid: UUID? = null, class ParcelOwner(val uuid: UUID? = null,
name: String? = null) { name: String? = null,
val since: DateTime? = null) {
companion object { companion object {
fun create(uuid: UUID?, name: String?): ParcelOwner? { fun create(uuid: UUID?, name: String?, time: DateTime? = null): ParcelOwner? {
return uuid?.let { ParcelOwner(uuid, name) } return uuid?.let { ParcelOwner(uuid, name, time) }
?: name?.let { ParcelOwner(uuid, name) } ?: name?.let { ParcelOwner(uuid, name, time) }
} }
} }
@@ -1,11 +1,11 @@
package io.dico.parcels2 package io.dico.parcels2
import io.dico.parcels2.math.Vec2i
import io.dico.parcels2.math.floor
import io.dico.parcels2.storage.SerializableParcel import io.dico.parcels2.storage.SerializableParcel
import io.dico.parcels2.storage.SerializableWorld import io.dico.parcels2.storage.SerializableWorld
import io.dico.parcels2.storage.Storage import io.dico.parcels2.storage.Storage
import io.dico.parcels2.util.Vec2i
import io.dico.parcels2.util.doAwait import io.dico.parcels2.util.doAwait
import io.dico.parcels2.util.floor
import kotlinx.coroutines.experimental.launch import kotlinx.coroutines.experimental.launch
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.Location import org.bukkit.Location
@@ -1,9 +1,9 @@
package io.dico.parcels2 package io.dico.parcels2
import io.dico.parcels2.math.Vec2i import io.dico.parcels2.util.Vec2i
import io.dico.parcels2.math.clamp import io.dico.parcels2.util.clamp
import io.dico.parcels2.math.even import io.dico.parcels2.util.even
import io.dico.parcels2.math.umod import io.dico.parcels2.util.umod
import org.bukkit.* import org.bukkit.*
import org.bukkit.Bukkit.createBlockData import org.bukkit.Bukkit.createBlockData
import org.bukkit.block.Biome import org.bukkit.block.Biome
@@ -40,8 +40,9 @@ class ParcelEntityTracker(val worlds: Worlds) {
} }
} }
@Suppress("RedundantLambdaArrow")
fun swapParcels(parcel1: Parcel, parcel2: Parcel) { fun swapParcels(parcel1: Parcel, parcel2: Parcel) {
map.editLoop { map.editLoop { ->
if (value === parcel1) { if (value === parcel1) {
value = parcel2 value = parcel2
} else if (value === parcel2) { } else if (value === parcel2) {
@@ -110,7 +110,7 @@ class ParcelListeners(val worlds: Worlds, val entityTracker: ParcelEntityTracker
private inline val Long.columnX get() = and(0xFFFF_FFFFL).toInt() private inline val Long.columnX get() = and(0xFFFF_FFFFL).toInt()
private inline val Long.columnZ get() = ushr(32).and(0xFFFF_FFFFL).toInt() private inline val Long.columnZ get() = ushr(32).and(0xFFFF_FFFFL).toInt()
private inline fun TLongCollection.forEachInline(block: (Long) -> Unit) = iterator().let { while (it.hasNext()) block(it.next()) } private inline fun TLongCollection.troveForEach(block: (Long) -> Unit) = iterator().let { while (it.hasNext()) block(it.next()) }
//@formatter:on //@formatter:on
private fun checkPistonMovement(event: BlockPistonEvent, blocks: List<Block>) { private fun checkPistonMovement(event: BlockPistonEvent, blocks: List<Block>) {
val world = worlds.getWorld(event.block.world) ?: return val world = worlds.getWorld(event.block.world) ?: return
@@ -122,7 +122,7 @@ class ParcelListeners(val worlds: Worlds, val entityTracker: ParcelEntityTracker
it.getRelative(direction).let { columns.add(Column(it.x, it.z)) } it.getRelative(direction).let { columns.add(Column(it.x, it.z)) }
} }
columns.forEachInline { columns.troveForEach {
val ppa = world.parcelAt(it.columnX, it.columnZ) val ppa = world.parcelAt(it.columnX, it.columnZ)
if (ppa.isNullOr { hasBlockVisitors }) { if (ppa.isNullOr { hasBlockVisitors }) {
event.isCancelled = true event.isCancelled = true
@@ -1,5 +1,6 @@
package io.dico.parcels2.storage package io.dico.parcels2.storage
import io.dico.parcels2.AddedData
import io.dico.parcels2.Parcel import io.dico.parcels2.Parcel
import io.dico.parcels2.ParcelData import io.dico.parcels2.ParcelData
import io.dico.parcels2.ParcelOwner import io.dico.parcels2.ParcelOwner
@@ -23,6 +24,8 @@ interface Backing {
*/ */
suspend fun ProducerScope<Pair<Parcel, ParcelData?>>.produceParcelData(parcels: Sequence<Parcel>) suspend fun ProducerScope<Pair<Parcel, ParcelData?>>.produceParcelData(parcels: Sequence<Parcel>)
suspend fun ProducerScope<Pair<SerializableParcel, ParcelData?>>.produceAllParcelData()
suspend fun readParcelData(parcelFor: Parcel): ParcelData? suspend fun readParcelData(parcelFor: Parcel): ParcelData?
suspend fun getOwnedParcels(user: ParcelOwner): List<SerializableParcel> suspend fun getOwnedParcels(user: ParcelOwner): List<SerializableParcel>
@@ -40,4 +43,9 @@ interface Backing {
suspend fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean) suspend fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean)
suspend fun readGlobalPlayerStateData(owner: ParcelOwner): AddedData?
suspend fun setGlobalPlayerState(owner: ParcelOwner, player: UUID, state: Boolean?)
} }
@@ -2,14 +2,14 @@ package io.dico.parcels2.storage
import com.zaxxer.hikari.HikariDataSource import com.zaxxer.hikari.HikariDataSource
import io.dico.parcels2.* import io.dico.parcels2.*
import io.dico.parcels2.math.Vec2i import io.dico.parcels2.util.Vec2i
import io.dico.parcels2.util.synchronized
import io.dico.parcels2.util.toByteArray import io.dico.parcels2.util.toByteArray
import io.dico.parcels2.util.toUUID import io.dico.parcels2.util.toUUID
import kotlinx.coroutines.experimental.channels.ProducerScope import kotlinx.coroutines.experimental.channels.ProducerScope
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SchemaUtils.create import org.jetbrains.exposed.sql.SchemaUtils.create
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.joda.time.DateTime
import java.util.* import java.util.*
import javax.sql.DataSource import javax.sql.DataSource
@@ -29,6 +29,7 @@ object ParcelsT : Table("parcels") {
.references(WorldsT.id) .references(WorldsT.id)
val owner_uuid = binary("owner_uuid", 16).nullable() val owner_uuid = binary("owner_uuid", 16).nullable()
val owner_name = varchar("owner_name", 16).nullable() val owner_name = varchar("owner_name", 16).nullable()
val claim_time = datetime("claim_time").nullable()
} }
object AddedLocalT : Table("parcels_added_local") { object AddedLocalT : Table("parcels_added_local") {
@@ -148,30 +149,18 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
channel.close() 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 { override suspend fun readParcelData(parcelFor: Parcel): ParcelData? = transaction {
val row = getParcelRow(parcelFor) ?: return@transaction null val row = getParcelRow(parcelFor) ?: return@transaction null
rowToParcelData(row)
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]
}
}
} }
// TODO order by some new column // TODO order by some new column
@@ -186,16 +175,8 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
where = { ParcelsT.owner_name eq name } where = { ParcelsT.owner_name eq name }
} }
ParcelsT.select(where) ParcelsT.select(where).orderBy(ParcelsT.claim_time, isAsc = true)
.map { parcelRow -> .mapNotNull(::rowToSerializableParcel)
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() .toList()
} }
@@ -237,6 +218,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
override suspend fun setParcelOwner(parcelFor: Parcel, owner: ParcelOwner?) = transaction { override suspend fun setParcelOwner(parcelFor: Parcel, owner: ParcelOwner?) = transaction {
val binaryUuid = owner?.uuid?.toByteArray() val binaryUuid = owner?.uuid?.toByteArray()
val name = owner?.name val name = owner?.name
val time = owner?.let { DateTime.now() }
val id = if (owner == null) val id = if (owner == null)
getParcelId(parcelFor) ?: return@transaction getParcelId(parcelFor) ?: return@transaction
@@ -246,6 +228,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
ParcelsT.update({ ParcelsT.id eq id }) { ParcelsT.update({ ParcelsT.id eq id }) {
it[ParcelsT.owner_uuid] = binaryUuid it[ParcelsT.owner_uuid] = binaryUuid
it[ParcelsT.owner_name] = name it[ParcelsT.owner_name] = name
it[ParcelsT.claim_time] = time
} }
} }
@@ -282,6 +265,43 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
} }
} }
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]
}
}
} }
@@ -3,7 +3,7 @@ package io.dico.parcels2.storage
import io.dico.parcels2.Parcel import io.dico.parcels2.Parcel
import io.dico.parcels2.ParcelWorld import io.dico.parcels2.ParcelWorld
import io.dico.parcels2.Worlds import io.dico.parcels2.Worlds
import io.dico.parcels2.math.Vec2i import io.dico.parcels2.util.Vec2i
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.World import org.bukkit.World
import java.util.* import java.util.*
@@ -1,5 +1,6 @@
package io.dico.parcels2.storage package io.dico.parcels2.storage
import io.dico.parcels2.AddedData
import io.dico.parcels2.Parcel import io.dico.parcels2.Parcel
import io.dico.parcels2.ParcelData import io.dico.parcels2.ParcelData
import io.dico.parcels2.ParcelOwner import io.dico.parcels2.ParcelOwner
@@ -25,6 +26,8 @@ interface Storage {
fun readParcelData(parcelsFor: Sequence<Parcel>, channelCapacity: Int): ReceiveChannel<Pair<Parcel, ParcelData?>> fun readParcelData(parcelsFor: Sequence<Parcel>, channelCapacity: Int): ReceiveChannel<Pair<Parcel, ParcelData?>>
fun readAllParcelData(channelCapacity: Int): ReceiveChannel<Pair<SerializableParcel, ParcelData?>>
fun getOwnedParcels(user: ParcelOwner): Deferred<List<SerializableParcel>> fun getOwnedParcels(user: ParcelOwner): Deferred<List<SerializableParcel>>
fun getNumParcels(user: ParcelOwner): Deferred<Int> fun getNumParcels(user: ParcelOwner): Deferred<Int>
@@ -40,6 +43,10 @@ interface Storage {
fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean): Job fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean): Job
fun readGlobalPlayerStateData(owner: ParcelOwner): Deferred<AddedData?>
fun setGlobalPlayerState(owner: ParcelOwner, player: UUID, state: Boolean?): Job
} }
class StorageWithCoroutineBacking internal constructor(val backing: Backing) : Storage { class StorageWithCoroutineBacking internal constructor(val backing: Backing) : Storage {
@@ -66,9 +73,11 @@ class StorageWithCoroutineBacking internal constructor(val backing: Backing) : S
override fun readParcelData(parcelFor: Parcel) = defer { backing.readParcelData(parcelFor) } override fun readParcelData(parcelFor: Parcel) = defer { backing.readParcelData(parcelFor) }
override fun readParcelData(parcelsFor: Sequence<Parcel>, channelCapacity: Int) = produce(asyncDispatcher, capacity = channelCapacity) { override fun readParcelData(parcelsFor: Sequence<Parcel>, channelCapacity: Int) =
with(backing) { produceParcelData(parcelsFor) } produce(asyncDispatcher, capacity = channelCapacity) { with(backing) { produceParcelData(parcelsFor) } }
}
override fun readAllParcelData(channelCapacity: Int): ReceiveChannel<Pair<SerializableParcel, ParcelData?>> =
produce(asyncDispatcher, capacity = channelCapacity) { with(backing) { produceAllParcelData() } }
override fun getOwnedParcels(user: ParcelOwner) = defer { backing.getOwnedParcels(user) } override fun getOwnedParcels(user: ParcelOwner) = defer { backing.getOwnedParcels(user) }
@@ -83,4 +92,9 @@ class StorageWithCoroutineBacking internal constructor(val backing: Backing) : S
override fun setParcelAllowsInteractInventory(parcel: Parcel, value: Boolean) = job { backing.setParcelAllowsInteractInventory(parcel, value) } override fun setParcelAllowsInteractInventory(parcel: Parcel, value: Boolean) = job { backing.setParcelAllowsInteractInventory(parcel, value) }
override fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean) = job { backing.setParcelAllowsInteractInputs(parcel, value) } override fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean) = job { backing.setParcelAllowsInteractInputs(parcel, value) }
override fun readGlobalPlayerStateData(owner: ParcelOwner): Deferred<AddedData?> = defer { backing.readGlobalPlayerStateData(owner) }
override fun setGlobalPlayerState(owner: ParcelOwner, player: UUID, state: Boolean?) = job { backing.setGlobalPlayerState(owner, player, state) }
} }
@@ -1,4 +1,4 @@
package io.dico.parcels2.math package io.dico.parcels2.util
fun Double.floor(): Int { fun Double.floor(): Int {
val down = toInt() val down = toInt()
@@ -1,4 +1,4 @@
package io.dico.parcels2.math package io.dico.parcels2.util
data class Vec2i( data class Vec2i(
val x: Int, val x: Int,