summaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt')
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt b/src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt
new file mode 100644
index 0000000..e5b7d9d
--- /dev/null
+++ b/src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt
@@ -0,0 +1,118 @@
+package io.dico.parcels2.storage.migration.plotme
+
+import com.zaxxer.hikari.HikariDataSource
+import io.dico.parcels2.*
+import io.dico.parcels2.storage.Storage
+import io.dico.parcels2.storage.migration.Migration
+import io.dico.parcels2.util.Vec2i
+import io.dico.parcels2.util.isValid
+import io.dico.parcels2.util.toUUID
+import io.dico.parcels2.util.uuid
+import kotlinx.coroutines.experimental.asCoroutineDispatcher
+import kotlinx.coroutines.experimental.launch
+import org.bukkit.Bukkit
+import org.jetbrains.exposed.sql.*
+import org.slf4j.LoggerFactory
+import java.io.ByteArrayOutputStream
+import java.sql.Blob
+import java.util.UUID
+import java.util.concurrent.Executors
+import javax.sql.DataSource
+
+class PlotmeMigration(val parcelProvider: ParcelProvider,
+ val worldMapper: Map<String, String>,
+ val dataSourceFactory: () -> DataSource) : Migration {
+ private var dataSource: DataSource? = null
+ private var database: Database? = null
+ private var isShutdown: Boolean = false
+ private val dispatcher = Executors.newSingleThreadExecutor { Thread(it, "PlotMe Migration Thread") }.asCoroutineDispatcher()
+ private val mlogger = LoggerFactory.getLogger("PlotMe Migrator")
+
+ private fun <T> transaction(statement: Transaction.() -> T) = org.jetbrains.exposed.sql.transactions.transaction(database!!, statement)
+
+ override fun migrateTo(storage: Storage) {
+ launch(context = dispatcher) {
+ init()
+ doWork(storage)
+ shutdown()
+ }
+ }
+
+ fun init() {
+ if (isShutdown) throw IllegalStateException()
+ dataSource = dataSourceFactory()
+ database = Database.connect(dataSource!!)
+ }
+
+ fun shutdown() {
+ if (isShutdown) throw IllegalStateException()
+ dataSource?.let {
+ (it as? HikariDataSource)?.close()
+ }
+ database = null
+ isShutdown = true
+ }
+
+ val parcelsCache = hashMapOf<String, MutableMap<Vec2i, ParcelData>>()
+
+ private fun getMap(worldName: String): MutableMap<Vec2i, ParcelData>? {
+ val mapped = worldMapper[worldName] ?: return null
+ return parcelsCache.computeIfAbsent(mapped) { mutableMapOf() }
+ }
+
+ private fun getData(worldName: String, position: Vec2i): ParcelData? {
+ return getMap(worldName)?.computeIfAbsent(position) { ParcelDataHolder() }
+ }
+
+ fun doWork(target: Storage): Unit = transaction {
+ if (!PlotmePlotsT.exists()) {
+ mlogger.warn("Plotme tables don't appear to exist. Exiting.")
+ return@transaction
+ }
+ parcelsCache.clear()
+
+ iterPlotmeTable(PlotmePlotsT) { data, row ->
+ // in practice, owner_uuid is not null for any plot currently. It will convert well.
+ data.owner = ParcelOwner(row[owner_uuid]?.toUUID(), row[owner_name])
+ }
+
+ iterPlotmeTable(PlotmeAllowedT) { data, row ->
+ val uuid = row[player_uuid]?.toUUID()
+ ?: Bukkit.getOfflinePlayer(row[player_name]).takeIf { it.isValid }?.uuid
+ ?: return@iterPlotmeTable
+
+ data.setAddedStatus(uuid, AddedStatus.ALLOWED)
+ }
+
+ iterPlotmeTable(PlotmeDeniedT) { data, row ->
+ val uuid = row[PlotmeAllowedT.player_uuid]?.toUUID()
+ ?: Bukkit.getOfflinePlayer(row[PlotmeAllowedT.player_name]).takeIf { it.isValid }?.uuid
+ ?: return@iterPlotmeTable
+
+ data.setAddedStatus(uuid, AddedStatus.BANNED)
+ }
+
+ for ((worldName, map) in parcelsCache) {
+ val world = ParcelWorldId(worldName)
+ for ((pos, data) in map) {
+ val parcel = ParcelId(world, pos)
+ target.setParcelData(parcel, data)
+ }
+ }
+
+ }
+
+ private fun Blob.toUUID(): UUID {
+ val out = ByteArrayOutputStream(16)
+ binaryStream.copyTo(out, bufferSize = 16)
+ return out.toByteArray().toUUID()
+ }
+
+ private inline fun <T : PlotmeTable> iterPlotmeTable(table: T, block: T.(ParcelData, ResultRow) -> Unit) {
+ table.selectAll().forEach { row ->
+ val data = getData(row[table.world_name], Vec2i(row[table.px], row[table.pz])) ?: return@forEach
+ table.block(data, row)
+ }
+ }
+
+} \ No newline at end of file