summaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt')
-rw-r--r--src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt81
1 files changed, 71 insertions, 10 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt
index 48a7fee..7748fc7 100644
--- a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt
+++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt
@@ -2,12 +2,18 @@ package io.dico.parcels2.defaultimpl
import io.dico.parcels2.*
import io.dico.parcels2.blockvisitor.Schematic
+import io.dico.parcels2.util.math.Region
+import io.dico.parcels2.util.math.Vec3d
+import io.dico.parcels2.util.math.Vec3i
import io.dico.parcels2.util.schedule
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.bukkit.Bukkit
+import org.bukkit.World
import org.bukkit.WorldCreator
+import org.bukkit.entity.Entity
+import org.bukkit.util.Vector
import org.joda.time.DateTime
class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
@@ -45,7 +51,7 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
private fun loadWorlds0() {
if (Bukkit.getWorlds().isEmpty()) {
- plugin.schedule(::loadWorlds0)
+ plugin.schedule { loadWorlds0() }
plugin.logger.warning("Scheduling to load worlds in the next tick because no bukkit worlds are loaded yet")
return
}
@@ -64,7 +70,8 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
WorldCreator(worldName).generator(generator).createWorld()
}
- parcelWorld = ParcelWorldImpl(plugin, bukkitWorld, generator, worldOptions.runtime,::DefaultParcelContainer)
+ parcelWorld =
+ ParcelWorldImpl(plugin, bukkitWorld, generator, worldOptions.runtime, ::DefaultParcelContainer)
if (!worldExists) {
val time = DateTime.now()
@@ -73,7 +80,8 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
newlyCreatedWorlds.add(parcelWorld)
} else {
GlobalScope.launch(context = Dispatchers.Unconfined) {
- parcelWorld.creationTime = plugin.storage.getWorldCreationTime(parcelWorld.id).await() ?: DateTime.now()
+ parcelWorld.creationTime = plugin.storage.getWorldCreationTime(parcelWorld.id).await() ?:
+ DateTime.now()
}
}
@@ -84,7 +92,7 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
}
private fun loadStoredData(newlyCreatedWorlds: Collection<ParcelWorld> = emptyList()) {
- plugin.launch(Dispatchers.Default) {
+ plugin.launch {
val migration = plugin.options.migration
if (migration.enabled) {
migration.instance?.newInstance()?.apply {
@@ -155,10 +163,32 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
}
override fun swapParcels(parcelId1: ParcelId, parcelId2: ParcelId): Job? {
- val blockManager1 = getWorldById(parcelId1.worldId)?.blockManager ?: return null
- val blockManager2 = getWorldById(parcelId2.worldId)?.blockManager ?: return null
+ val world1 = getWorldById(parcelId1.worldId) ?: return null
+ val world2 = getWorldById(parcelId2.worldId) ?: return null
+ val blockManager1 = world1.blockManager
+ val blockManager2 = world2.blockManager
+
+ class CopyTarget(val world: World, val region: Region)
+ class CopySource(val origin: Vec3i, val schematic: Schematic, val entities: Collection<Entity>)
+
+ suspend fun JobScope.copy(source: CopySource, target: CopyTarget) {
+ with(source.schematic) { paste(target.world, target.region.origin) }
+
+ for (entity in source.entities) {
+ entity.velocity = Vector(0, 0, 0)
+ val location = entity.location
+ location.world = target.world
+ val coords = target.region.origin + (Vec3d(entity.location) - source.origin)
+ coords.copyInto(location)
+ entity.teleport(location)
+ }
+ }
return trySubmitBlockVisitor(Permit(), parcelId1, parcelId2) {
+ val temporaryParcel = world1.nextEmptyParcel()
+ ?: world2.nextEmptyParcel()
+ ?: return@trySubmitBlockVisitor
+
var region1 = blockManager1.getRegion(parcelId1)
var region2 = blockManager2.getRegion(parcelId2)
@@ -168,10 +198,41 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
region2 = region2.withSize(size)
}
- val schematicOf1 = delegateWork(0.25) { Schematic().apply { load(blockManager1.world, region1) } }
- val schematicOf2 = delegateWork(0.25) { Schematic().apply { load(blockManager2.world, region2) } }
- delegateWork(0.25) { with(schematicOf1) { paste(blockManager2.world, region2.origin) } }
- delegateWork(0.25) { with(schematicOf2) { paste(blockManager1.world, region1.origin) } }
+ // Teleporting entities safely requires a different approach:
+ // * Copy schematic1 into temporary location
+ // * Teleport entities1 into temporary location
+ // * Copy schematic2 into parcel1
+ // * Teleport entities2 into parcel1
+ // * Copy schematic1 into parcel2
+ // * Teleport entities1 into parcel2
+ // * Clear temporary location
+
+ lateinit var source1: CopySource
+ lateinit var source2: CopySource
+
+ delegateWork(0.30) {
+ val schematicOf1 = delegateWork(0.50) { Schematic().apply { load(blockManager1.world, region1) } }
+ val schematicOf2 = delegateWork(0.50) { Schematic().apply { load(blockManager2.world, region2) } }
+
+ source1 = CopySource(region1.origin, schematicOf1, blockManager1.getEntities(region1))
+ source2 = CopySource(region2.origin, schematicOf2, blockManager2.getEntities(region2))
+ }
+
+ val target1 = CopyTarget(blockManager1.world, region1)
+ val target2 = CopyTarget(blockManager2.world, region2)
+ val targetTemp = CopyTarget(
+ temporaryParcel.world.world,
+ temporaryParcel.world.blockManager.getRegion(temporaryParcel.id)
+ )
+
+ delegateWork {
+ delegateWork(1.0 / 3.0) { copy(source1, targetTemp) }
+ delegateWork(1.0 / 3.0) { copy(source2, target1) }
+ delegateWork(1.0 / 3.0) { copy(source1, target2) }
+ }
+
+ // Separate job. Whatever
+ temporaryParcel.world.blockManager.clearParcel(temporaryParcel.id)
}
}