summaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/dico/parcels2/defaultimpl
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/defaultimpl')
-rw-r--r--src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelContainer.kt2
-rw-r--r--src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt31
-rw-r--r--src/main/kotlin/io/dico/parcels2/defaultimpl/GlobalPrivilegesManagerImpl.kt54
-rw-r--r--src/main/kotlin/io/dico/parcels2/defaultimpl/InfoBuilder.kt174
-rw-r--r--src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt81
-rw-r--r--src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelWorldImpl.kt2
6 files changed, 209 insertions, 135 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelContainer.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelContainer.kt
index 1193af3..f3cd8d7 100644
--- a/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelContainer.kt
+++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelContainer.kt
@@ -45,7 +45,7 @@ class DefaultParcelContainer(val world: ParcelWorld) : ParcelContainer {
}
}
- override fun nextEmptyParcel(): Parcel? {
+ override suspend fun nextEmptyParcel(): Parcel? {
return walkInCircle().find { it.owner == null }
}
diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt
index 9e43c05..73b6b4d 100644
--- a/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt
+++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt
@@ -11,6 +11,7 @@ import org.bukkit.block.BlockFace
import org.bukkit.block.Skull
import org.bukkit.block.data.type.Slab
import org.bukkit.block.data.type.WallSign
+import org.bukkit.entity.Player
import java.util.Random
private val airType = Bukkit.createBlockData(Material.AIR)
@@ -285,17 +286,29 @@ class DefaultParcelGenerator(
val floorType = o.floorType
val fillType = o.fillType
- for ((index, vec) in blocks.withIndex()) {
- markSuspensionPoint()
- val y = vec.y
- val blockType = when {
- y > floorHeight -> airType
- y == floorHeight -> floorType
- else -> fillType
+ delegateWork(0.95) {
+ for ((index, vec) in blocks.withIndex()) {
+ markSuspensionPoint()
+ val y = vec.y
+ val blockType = when {
+ y > floorHeight -> airType
+ y == floorHeight -> floorType
+ else -> fillType
+ }
+ world[vec].blockData = blockType
+ setProgress((index + 1) / blockCount)
+ }
+ }
+
+ delegateWork {
+ val entities = getEntities(region)
+ for ((index, entity) in entities.withIndex()) {
+ if (entity is Player) continue
+ entity.remove()
+ setProgress((index + 1) / entities.size.toDouble())
}
- world[vec].blockData = blockType
- setProgress((index + 1) / blockCount)
}
+
}
override fun getParcelsWithOwnerBlockIn(chunk: Chunk): Collection<Vec2i> {
diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/GlobalPrivilegesManagerImpl.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/GlobalPrivilegesManagerImpl.kt
index 769cee6..670dd94 100644
--- a/src/main/kotlin/io/dico/parcels2/defaultimpl/GlobalPrivilegesManagerImpl.kt
+++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/GlobalPrivilegesManagerImpl.kt
@@ -1,28 +1,28 @@
-@file:Suppress("UNCHECKED_CAST")
-
-package io.dico.parcels2.defaultimpl
-
-import io.dico.parcels2.*
-import io.dico.parcels2.util.ext.alsoIfTrue
-import java.util.Collections
-
-class GlobalPrivilegesManagerImpl(val plugin: ParcelsPlugin) : GlobalPrivilegesManager {
- private val map = mutableMapOf<PlayerProfile, GlobalPrivileges>()
-
- override fun get(owner: PlayerProfile.Real): GlobalPrivileges {
- return map[owner] ?: GlobalPrivilegesImpl(owner).also { map[owner] = it }
- }
-
- private inner class GlobalPrivilegesImpl(override val keyOfOwner: PlayerProfile.Real) : PrivilegesHolder(), GlobalPrivileges {
- override var privilegeOfStar: Privilege
- get() = super<GlobalPrivileges>.privilegeOfStar
- set(value) = run { super<GlobalPrivileges>.privilegeOfStar = value }
-
- override fun setRawStoredPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean {
- return super.setRawStoredPrivilege(key, privilege).alsoIfTrue {
- plugin.storage.setGlobalPrivilege(keyOfOwner, key, privilege)
- }
- }
- }
-
+@file:Suppress("UNCHECKED_CAST")
+
+package io.dico.parcels2.defaultimpl
+
+import io.dico.parcels2.*
+import io.dico.parcels2.util.ext.alsoIfTrue
+import java.util.Collections
+
+class GlobalPrivilegesManagerImpl(val plugin: ParcelsPlugin) : GlobalPrivilegesManager {
+ private val map = mutableMapOf<PlayerProfile, GlobalPrivileges>()
+
+ override fun get(owner: PlayerProfile.Real): GlobalPrivileges {
+ return map[owner] ?: GlobalPrivilegesImpl(owner).also { map[owner] = it }
+ }
+
+ private inner class GlobalPrivilegesImpl(override val keyOfOwner: PlayerProfile.Real) : PrivilegesHolder(), GlobalPrivileges {
+ override var privilegeOfStar: Privilege
+ get() = super<GlobalPrivileges>.privilegeOfStar
+ set(value) = run { super<GlobalPrivileges>.privilegeOfStar = value }
+
+ override fun setRawStoredPrivilege(key: PrivilegeKey, privilege: Privilege): Boolean {
+ return super.setRawStoredPrivilege(key, privilege).alsoIfTrue {
+ plugin.storage.setGlobalPrivilege(keyOfOwner, key, privilege)
+ }
+ }
+ }
+
} \ No newline at end of file
diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/InfoBuilder.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/InfoBuilder.kt
index a3704c7..99df82a 100644
--- a/src/main/kotlin/io/dico/parcels2/defaultimpl/InfoBuilder.kt
+++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/InfoBuilder.kt
@@ -1,88 +1,88 @@
-package io.dico.parcels2.defaultimpl
-
-import io.dico.dicore.Formatting
-import io.dico.parcels2.Privilege
-import io.dico.parcels2.PrivilegeKey
-import io.dico.parcels2.RawPrivileges
-import io.dico.parcels2.filterProfilesWithPrivilegeTo
-
-object InfoBuilder {
- val infoStringColor1 = Formatting.GREEN
- val infoStringColor2 = Formatting.AQUA
-
- inline fun StringBuilder.appendField(field: StringBuilder.() -> Unit, value: StringBuilder.() -> Unit) {
- append(infoStringColor1)
- field()
- append(": ")
- append(infoStringColor2)
- value()
- append(' ')
- }
-
- inline fun StringBuilder.appendField(name: String, value: StringBuilder.() -> Unit) {
- appendField({ append(name) }, value)
- }
-
- inline fun StringBuilder.appendFieldWithCount(name: String, count: Int, value: StringBuilder.() -> Unit) {
- appendField({
- append(name)
- append('(')
- append(infoStringColor2)
- append(count)
- append(infoStringColor1)
- append(')')
- }, value)
- }
-
- fun StringBuilder.appendProfilesWithPrivilege(fieldName: String, local: RawPrivileges, global: RawPrivileges?, privilege: Privilege) {
- val map = linkedMapOf<PrivilegeKey, Privilege>()
- local.filterProfilesWithPrivilegeTo(map, privilege)
- val localCount = map.size
- global?.filterProfilesWithPrivilegeTo(map, privilege)
- appendPrivilegeProfiles(fieldName, map, localCount)
- }
-
- fun StringBuilder.appendPrivilegeProfiles(fieldName: String, map: LinkedHashMap<PrivilegeKey, Privilege>, localCount: Int) {
- if (map.isEmpty()) return
-
- appendFieldWithCount(fieldName, map.size) {
- // first [localCount] entries are local
- val separator = "$infoStringColor1, $infoStringColor2"
- val iterator = map.iterator()
-
- if (localCount != 0) {
- appendPrivilegeEntry(false, iterator.next().toPair())
- repeat(localCount - 1) {
- append(separator)
- appendPrivilegeEntry(false, iterator.next().toPair())
- }
-
- } else if (iterator.hasNext()) {
- // ensure there is never a leading or trailing separator
- appendPrivilegeEntry(true, iterator.next().toPair())
- }
-
- iterator.forEach { next ->
- append(separator)
- appendPrivilegeEntry(true, next.toPair())
- }
- }
- }
-
- fun StringBuilder.appendPrivilegeEntry(global: Boolean, pair: Pair<PrivilegeKey, Privilege>) {
- val (key, priv) = pair
-
- append(key.notNullName)
-
- // suffix. Maybe T should be M for mod or something. T means they have CAN_MANAGE privilege.
- append(
- when {
- global && priv == Privilege.CAN_MANAGE -> " (G) (T)"
- global -> " (G)"
- priv == Privilege.CAN_MANAGE -> " (T)"
- else -> ""
- }
- )
- }
-
+package io.dico.parcels2.defaultimpl
+
+import io.dico.dicore.Formatting
+import io.dico.parcels2.Privilege
+import io.dico.parcels2.PrivilegeKey
+import io.dico.parcels2.RawPrivileges
+import io.dico.parcels2.filterProfilesWithPrivilegeTo
+
+object InfoBuilder {
+ val infoStringColor1 = Formatting.GREEN
+ val infoStringColor2 = Formatting.AQUA
+
+ inline fun StringBuilder.appendField(field: StringBuilder.() -> Unit, value: StringBuilder.() -> Unit) {
+ append(infoStringColor1)
+ field()
+ append(": ")
+ append(infoStringColor2)
+ value()
+ append(' ')
+ }
+
+ inline fun StringBuilder.appendField(name: String, value: StringBuilder.() -> Unit) {
+ appendField({ append(name) }, value)
+ }
+
+ inline fun StringBuilder.appendFieldWithCount(name: String, count: Int, value: StringBuilder.() -> Unit) {
+ appendField({
+ append(name)
+ append('(')
+ append(infoStringColor2)
+ append(count)
+ append(infoStringColor1)
+ append(')')
+ }, value)
+ }
+
+ fun StringBuilder.appendProfilesWithPrivilege(fieldName: String, local: RawPrivileges, global: RawPrivileges?, privilege: Privilege) {
+ val map = linkedMapOf<PrivilegeKey, Privilege>()
+ local.filterProfilesWithPrivilegeTo(map, privilege)
+ val localCount = map.size
+ global?.filterProfilesWithPrivilegeTo(map, privilege)
+ appendPrivilegeProfiles(fieldName, map, localCount)
+ }
+
+ fun StringBuilder.appendPrivilegeProfiles(fieldName: String, map: LinkedHashMap<PrivilegeKey, Privilege>, localCount: Int) {
+ if (map.isEmpty()) return
+
+ appendFieldWithCount(fieldName, map.size) {
+ // first [localCount] entries are local
+ val separator = "$infoStringColor1, $infoStringColor2"
+ val iterator = map.iterator()
+
+ if (localCount != 0) {
+ appendPrivilegeEntry(false, iterator.next().toPair())
+ repeat(localCount - 1) {
+ append(separator)
+ appendPrivilegeEntry(false, iterator.next().toPair())
+ }
+
+ } else if (iterator.hasNext()) {
+ // ensure there is never a leading or trailing separator
+ appendPrivilegeEntry(true, iterator.next().toPair())
+ }
+
+ iterator.forEach { next ->
+ append(separator)
+ appendPrivilegeEntry(true, next.toPair())
+ }
+ }
+ }
+
+ fun StringBuilder.appendPrivilegeEntry(global: Boolean, pair: Pair<PrivilegeKey, Privilege>) {
+ val (key, priv) = pair
+
+ append(key.notNullName)
+
+ // suffix. Maybe T should be M for mod or something. T means they have CAN_MANAGE privilege.
+ append(
+ when {
+ global && priv == Privilege.CAN_MANAGE -> " (G) (T)"
+ global -> " (G)"
+ priv == Privilege.CAN_MANAGE -> " (T)"
+ else -> ""
+ }
+ )
+ }
+
} \ No newline at end of file
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)
}
}
diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelWorldImpl.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelWorldImpl.kt
index 531a25f..cb322d4 100644
--- a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelWorldImpl.kt
+++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelWorldImpl.kt
@@ -69,7 +69,7 @@ class ParcelWorldImpl(
override fun getParcelById(id: ParcelId): Parcel? = container.getParcelById(id)
- override fun nextEmptyParcel(): Parcel? = container.nextEmptyParcel()
+ override suspend fun nextEmptyParcel(): Parcel? = container.nextEmptyParcel()
override fun toString() = parcelWorldIdToString()
}