10/10 commit messages btw
This commit is contained in:
@@ -64,7 +64,7 @@ class DefaultParcelContainer(val world: ParcelWorld) : ParcelContainer {
|
||||
}
|
||||
}
|
||||
|
||||
fun allParcels(): Sequence<Parcel> = sequence {
|
||||
fun getAllParcels(): Iterator<Parcel> = iterator {
|
||||
for (array in parcels) {
|
||||
yieldAll(array.iterator())
|
||||
}
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
package io.dico.parcels2.defaultimpl
|
||||
|
||||
import io.dico.parcels2.*
|
||||
import io.dico.parcels2.blockvisitor.*
|
||||
import io.dico.parcels2.blockvisitor.RegionTraverser
|
||||
import io.dico.parcels2.options.DefaultGeneratorOptions
|
||||
import io.dico.parcels2.util.math.Region
|
||||
import io.dico.parcels2.util.math.Vec2i
|
||||
import io.dico.parcels2.util.math.Vec3i
|
||||
import io.dico.parcels2.util.math.even
|
||||
import io.dico.parcels2.util.math.umod
|
||||
import io.dico.parcels2.util.math.get
|
||||
import io.dico.parcels2.util.math.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.CoroutineStart.UNDISPATCHED
|
||||
import kotlinx.coroutines.launch
|
||||
import org.bukkit.*
|
||||
import org.bukkit.block.Biome
|
||||
import org.bukkit.block.BlockFace
|
||||
import org.bukkit.block.Skull
|
||||
import org.bukkit.block.data.BlockData
|
||||
import org.bukkit.block.data.type.Slab
|
||||
import org.bukkit.block.data.type.WallSign
|
||||
import java.util.Random
|
||||
@@ -118,12 +110,13 @@ class DefaultParcelGenerator(
|
||||
}
|
||||
|
||||
override fun makeParcelLocatorAndBlockManager(
|
||||
worldId: ParcelWorldId,
|
||||
parcelProvider: ParcelProvider,
|
||||
container: ParcelContainer,
|
||||
coroutineScope: CoroutineScope,
|
||||
jobDispatcher: JobDispatcher
|
||||
): Pair<ParcelLocator, ParcelBlockManager> {
|
||||
return ParcelLocatorImpl(worldId, container) to ParcelBlockManagerImpl(worldId, coroutineScope, jobDispatcher)
|
||||
val impl = ParcelLocatorAndBlockManagerImpl(parcelProvider, container, coroutineScope, jobDispatcher)
|
||||
return impl to impl
|
||||
}
|
||||
|
||||
private inline fun <T> convertBlockLocationToId(x: Int, z: Int, mapper: (Int, Int) -> T): T? {
|
||||
@@ -139,11 +132,25 @@ class DefaultParcelGenerator(
|
||||
return null
|
||||
}
|
||||
|
||||
private inner class ParcelLocatorImpl(
|
||||
val worldId: ParcelWorldId,
|
||||
val container: ParcelContainer
|
||||
) : ParcelLocator {
|
||||
override val world: World = this@DefaultParcelGenerator.world
|
||||
@Suppress("DEPRECATION")
|
||||
private inner class ParcelLocatorAndBlockManagerImpl(
|
||||
val parcelProvider: ParcelProvider,
|
||||
val container: ParcelContainer,
|
||||
coroutineScope: CoroutineScope,
|
||||
override val jobDispatcher: JobDispatcher
|
||||
) : ParcelBlockManagerBase(), ParcelLocator, CoroutineScope by coroutineScope {
|
||||
|
||||
override val world: World get() = this@DefaultParcelGenerator.world
|
||||
val worldId = parcelProvider.getWorld(world)?.id ?: ParcelWorldId(world)
|
||||
override val parcelTraverser: RegionTraverser = RegionTraverser.convergingTo(o.floorHeight)
|
||||
|
||||
private val cornerWallType = when {
|
||||
o.wallType is Slab -> (o.wallType.clone() as Slab).apply { type = Slab.Type.DOUBLE }
|
||||
o.wallType.material.name.endsWith("CARPET") -> {
|
||||
Bukkit.createBlockData(Material.getMaterial(o.wallType.material.name.substringBefore("CARPET") + "WOOL"))
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun getParcelAt(x: Int, z: Int): Parcel? {
|
||||
return convertBlockLocationToId(x, z, container::getParcelById)
|
||||
@@ -152,112 +159,113 @@ class DefaultParcelGenerator(
|
||||
override fun getParcelIdAt(x: Int, z: Int): ParcelId? {
|
||||
return convertBlockLocationToId(x, z) { idx, idz -> ParcelId(worldId, idx, idz) }
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private inner class ParcelBlockManagerImpl(
|
||||
val worldId: ParcelWorldId,
|
||||
coroutineScope: CoroutineScope,
|
||||
override val jobDispatcher: JobDispatcher
|
||||
) : ParcelBlockManagerBase(), CoroutineScope by coroutineScope {
|
||||
override val world: World = this@DefaultParcelGenerator.world
|
||||
override val parcelTraverser: RegionTraverser = RegionTraverser.convergingTo(o.floorHeight)
|
||||
|
||||
/*override*/ fun getBottomBlock(parcel: ParcelId): Vec2i = Vec2i(
|
||||
sectionSize * (parcel.x - 1) + pathOffset + o.offsetX,
|
||||
sectionSize * (parcel.z - 1) + pathOffset + o.offsetZ
|
||||
)
|
||||
private fun checkParcelId(parcel: ParcelId): ParcelId {
|
||||
if (!parcel.worldId.equals(worldId)) {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
return parcel
|
||||
}
|
||||
|
||||
override fun getHomeLocation(parcel: ParcelId): Location {
|
||||
val bottom = getBottomBlock(parcel)
|
||||
val x = bottom.x + (o.parcelSize - 1) / 2.0
|
||||
val z = bottom.z - 2
|
||||
return Location(world, x + 0.5, o.floorHeight + 1.0, z + 0.5, 0F, 0F)
|
||||
override fun getRegionOrigin(parcel: ParcelId): Vec2i {
|
||||
checkParcelId(parcel)
|
||||
return Vec2i(
|
||||
sectionSize * (parcel.x - 1) + pathOffset + o.offsetX,
|
||||
sectionSize * (parcel.z - 1) + pathOffset + o.offsetZ
|
||||
)
|
||||
}
|
||||
|
||||
override fun getRegion(parcel: ParcelId): Region {
|
||||
val bottom = getBottomBlock(parcel)
|
||||
val origin = getRegionOrigin(parcel)
|
||||
return Region(
|
||||
Vec3i(bottom.x, 0, bottom.z),
|
||||
Vec3i(origin.x, 0, origin.z),
|
||||
Vec3i(o.parcelSize, maxHeight, o.parcelSize)
|
||||
)
|
||||
}
|
||||
|
||||
private fun getRegionConsideringWorld(parcel: ParcelId): Region {
|
||||
if (parcel.worldId != worldId) {
|
||||
(parcel.worldId as? ParcelWorld)?.let {
|
||||
return it.blockManager.getRegion(parcel)
|
||||
}
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
return getRegion(parcel)
|
||||
override fun getHomeLocation(parcel: ParcelId): Location {
|
||||
val origin = getRegionOrigin(parcel)
|
||||
val x = origin.x + (o.parcelSize - 1) / 2.0
|
||||
val z = origin.z - 2
|
||||
return Location(world, x + 0.5, o.floorHeight + 1.0, z + 0.5, 0F, 0F)
|
||||
}
|
||||
|
||||
override fun setOwnerBlock(parcel: ParcelId, owner: PlayerProfile?) {
|
||||
val b = getBottomBlock(parcel)
|
||||
override fun getParcelForInfoBlockInteraction(block: Vec3i, type: Material, face: BlockFace): Parcel? {
|
||||
if (block.y != o.floorHeight + 1) return null
|
||||
|
||||
val expectedParcelOrigin = when (type) {
|
||||
Material.WALL_SIGN -> Vec2i(block.x + 1, block.z + 2)
|
||||
o.wallType.material, cornerWallType?.material -> {
|
||||
if (face != BlockFace.NORTH || world[block + Vec3i.convert(BlockFace.NORTH)].type == Material.WALL_SIGN) {
|
||||
return null
|
||||
}
|
||||
|
||||
Vec2i(block.x + 1, block.z + 1)
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
|
||||
return getParcelAt(expectedParcelOrigin.x, expectedParcelOrigin.z)
|
||||
?.takeIf { expectedParcelOrigin == getRegionOrigin(it.id) }
|
||||
?.also { parcel ->
|
||||
if (type != Material.WALL_SIGN && parcel.owner != null) {
|
||||
updateParcelInfo(parcel.id, parcel.owner)
|
||||
parcel.isOwnerSignOutdated = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun isParcelInfoSectionLoaded(parcel: ParcelId): Boolean {
|
||||
val wallBlockChunk = getRegionOrigin(parcel).add(-1, -1).toChunk()
|
||||
return world.isChunkLoaded(wallBlockChunk.x, wallBlockChunk.z)
|
||||
}
|
||||
|
||||
override fun updateParcelInfo(parcel: ParcelId, owner: PlayerProfile?) {
|
||||
val b = getRegionOrigin(parcel)
|
||||
|
||||
val wallBlock = world.getBlockAt(b.x - 1, o.floorHeight + 1, b.z - 1)
|
||||
val signBlock = world.getBlockAt(b.x - 2, o.floorHeight + 1, b.z - 1)
|
||||
val signBlock = world.getBlockAt(b.x - 1, o.floorHeight + 1, b.z - 2)
|
||||
val skullBlock = world.getBlockAt(b.x - 1, o.floorHeight + 2, b.z - 1)
|
||||
|
||||
if (owner == null) {
|
||||
wallBlock.blockData = o.wallType
|
||||
signBlock.type = Material.AIR
|
||||
skullBlock.type = Material.AIR
|
||||
|
||||
} else {
|
||||
|
||||
val wallBlockType: BlockData = if (o.wallType is Slab)
|
||||
(o.wallType.clone() as Slab).apply { type = Slab.Type.DOUBLE }
|
||||
else
|
||||
o.wallType
|
||||
|
||||
wallBlock.blockData = wallBlockType
|
||||
cornerWallType?.let { wallBlock.blockData = it }
|
||||
signBlock.blockData = (Bukkit.createBlockData(Material.WALL_SIGN) as WallSign).apply { facing = BlockFace.NORTH }
|
||||
|
||||
val sign = signBlock.state as org.bukkit.block.Sign
|
||||
sign.setLine(0, "${parcel.x},${parcel.z}")
|
||||
sign.setLine(2, owner.name)
|
||||
sign.setLine(2, owner.name ?: "")
|
||||
sign.update()
|
||||
|
||||
skullBlock.type = Material.AIR
|
||||
skullBlock.type = Material.PLAYER_HEAD
|
||||
val skull = skullBlock.state as Skull
|
||||
if (owner is PlayerProfile.Real) {
|
||||
skull.owningPlayer = Bukkit.getOfflinePlayer(owner.uuid)
|
||||
} else {
|
||||
skull.owner = owner.name
|
||||
|
||||
} else if (!skull.setOwner(owner.name)) {
|
||||
skullBlock.type = Material.AIR
|
||||
return
|
||||
}
|
||||
skull.rotation = BlockFace.WEST
|
||||
|
||||
skull.rotation = BlockFace.SOUTH
|
||||
skull.update()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getParcel(parcelId: ParcelId): Parcel? {
|
||||
// todo dont rely on this cast
|
||||
val world = worldId as? ParcelWorld ?: return null
|
||||
return world.getParcelById(parcelId)
|
||||
private fun trySubmitBlockVisitor(vararg parcels: ParcelId, function: JobFunction): Job? {
|
||||
parcels.forEach { checkParcelId(it) }
|
||||
return parcelProvider.trySubmitBlockVisitor(Permit(), parcels, function)
|
||||
}
|
||||
|
||||
override fun submitBlockVisitor(vararg parcelIds: ParcelId, task: JobFunction): Job {
|
||||
val parcels = parcelIds.mapNotNull { getParcel(it) }
|
||||
if (parcels.isEmpty()) return jobDispatcher.dispatch(task)
|
||||
if (parcels.any { it.hasBlockVisitors }) throw IllegalArgumentException("This parcel already has a block visitor")
|
||||
|
||||
val worker = jobDispatcher.dispatch(task)
|
||||
|
||||
for (parcel in parcels) {
|
||||
launch(start = UNDISPATCHED) {
|
||||
parcel.withBlockVisitorPermit {
|
||||
worker.awaitCompletion()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return worker
|
||||
}
|
||||
|
||||
override fun setBiome(parcel: ParcelId, biome: Biome): Job = submitBlockVisitor(parcel) {
|
||||
override fun setBiome(parcel: ParcelId, biome: Biome) = trySubmitBlockVisitor(checkParcelId(parcel)) {
|
||||
val world = world
|
||||
val b = getBottomBlock(parcel)
|
||||
val b = getRegionOrigin(parcel)
|
||||
val parcelSize = o.parcelSize
|
||||
for (x in b.x until b.x + parcelSize) {
|
||||
for (z in b.z until b.z + parcelSize) {
|
||||
@@ -267,7 +275,7 @@ class DefaultParcelGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearParcel(parcel: ParcelId): Job = submitBlockVisitor(parcel) {
|
||||
override fun clearParcel(parcel: ParcelId) = trySubmitBlockVisitor(checkParcelId(parcel)) {
|
||||
val region = getRegion(parcel)
|
||||
val blocks = parcelTraverser.traverseRegion(region)
|
||||
val blockCount = region.blockCount.toDouble()
|
||||
@@ -291,22 +299,6 @@ class DefaultParcelGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
override fun swapParcels(parcel1: ParcelId, parcel2: ParcelId): Job = submitBlockVisitor(parcel1, parcel2) {
|
||||
var region1 = getRegionConsideringWorld(parcel1)
|
||||
var region2 = getRegionConsideringWorld(parcel2)
|
||||
|
||||
val size = region1.size.clampMax(region2.size)
|
||||
if (size != region1.size) {
|
||||
region1 = region1.withSize(size)
|
||||
region2 = region2.withSize(size)
|
||||
}
|
||||
|
||||
val schematicOf1 = delegateWork(0.25) { Schematic().apply { load(world, region1) } }
|
||||
val schematicOf2 = delegateWork(0.25) { Schematic().apply { load(world, region2) } }
|
||||
delegateWork(0.25) { with(schematicOf1) { paste(world, region2.origin) } }
|
||||
delegateWork(0.25) { with(schematicOf2) { paste(world, region1.origin) } }
|
||||
}
|
||||
|
||||
override fun getParcelsWithOwnerBlockIn(chunk: Chunk): Collection<Vec2i> {
|
||||
/*
|
||||
* Get the offsets for the world out of the way
|
||||
|
||||
@@ -3,59 +3,84 @@ package io.dico.parcels2.defaultimpl
|
||||
import io.dico.parcels2.*
|
||||
import io.dico.parcels2.Privilege.*
|
||||
import io.dico.parcels2.util.ext.alsoIfTrue
|
||||
import io.dico.parcels2.util.isServerThread
|
||||
import io.dico.parcels2.util.math.Vec2i
|
||||
import org.bukkit.Material
|
||||
import org.joda.time.DateTime
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.lang.IllegalStateException
|
||||
|
||||
class ParcelImpl(
|
||||
class ParcelImpl (
|
||||
override val world: ParcelWorld,
|
||||
override val x: Int,
|
||||
override val z: Int
|
||||
) : Parcel, ParcelId {
|
||||
override val id: ParcelId = this
|
||||
override val id: ParcelId get() = this
|
||||
override val pos get() = Vec2i(x, z)
|
||||
override var data: ParcelDataHolder = ParcelDataHolder(); private set
|
||||
override val hasBlockVisitors get() = blockVisitors.get() > 0
|
||||
override var data = ParcelDataHolder(); private set
|
||||
override val worldId: ParcelWorldId get() = world.id
|
||||
|
||||
override fun copyDataIgnoringDatabase(data: ParcelData) {
|
||||
this.data = ((data as? Parcel)?.data ?: data) as ParcelDataHolder
|
||||
}
|
||||
override fun copyData(newData: ParcelDataHolder, callerIsDatabase: Boolean) {
|
||||
if (callerIsDatabase) {
|
||||
data = newData
|
||||
return
|
||||
}
|
||||
|
||||
val ownerChanged = owner != newData.owner
|
||||
if (ownerChanged) {
|
||||
updateOwnerSign(true, false, true)
|
||||
}
|
||||
|
||||
|
||||
val ownerSignWasOutdated = if (callerIsDatabase) newData.isOwnerSignOutdated else isOwnerSignOutdated
|
||||
val ownerChanged = owner != newData.owner
|
||||
|
||||
data = newData
|
||||
|
||||
if (ownerChanged && isServerThread()) {
|
||||
updateOwnerSign(true, false, updateDatabase = callerIsDatabase)
|
||||
} else {
|
||||
newData.isOwnerSignOutdated = ownerChanged || ownerSignWasOutdated
|
||||
}
|
||||
|
||||
override fun copyData(data: ParcelData) {
|
||||
copyDataIgnoringDatabase(data)
|
||||
world.storage.setParcelData(this, data)
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
copyDataIgnoringDatabase(ParcelDataHolder())
|
||||
world.storage.setParcelData(this, null)
|
||||
}
|
||||
|
||||
|
||||
override var owner: PlayerProfile?
|
||||
get() = data.owner
|
||||
set(value) {
|
||||
if (data.owner != value) {
|
||||
world.storage.setParcelOwner(this, value)
|
||||
world.blockManager.setOwnerBlock(this, value)
|
||||
data.owner = value
|
||||
updateOwnerSign(true, false, true)
|
||||
}
|
||||
}
|
||||
|
||||
override val lastClaimTime: DateTime?
|
||||
get() = data.lastClaimTime
|
||||
|
||||
override var ownerSignOutdated: Boolean
|
||||
get() = data.ownerSignOutdated
|
||||
override var isOwnerSignOutdated: Boolean
|
||||
get() = data.isOwnerSignOutdated
|
||||
set(value) {
|
||||
if (data.ownerSignOutdated != value) {
|
||||
if (data.isOwnerSignOutdated != value) {
|
||||
world.storage.setParcelOwnerSignOutdated(this, value)
|
||||
data.ownerSignOutdated = value
|
||||
data.isOwnerSignOutdated = value
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateOwnerSign(force: Boolean) {
|
||||
updateOwnerSign(false, force, true)
|
||||
}
|
||||
|
||||
private fun updateOwnerSign(ownerChanged: Boolean, force: Boolean, updateDatabase: Boolean) {
|
||||
if (!ownerChanged && !isOwnerSignOutdated && !force) return
|
||||
|
||||
val update = force || world.blockManager.isParcelInfoSectionLoaded(this)
|
||||
if (update) world.blockManager.updateParcelInfo(this, owner)
|
||||
|
||||
if (updateDatabase) isOwnerSignOutdated = !update
|
||||
else data.isOwnerSignOutdated = !update
|
||||
}
|
||||
|
||||
|
||||
override val privilegeMap: PrivilegeMap
|
||||
get() = data.privilegeMap
|
||||
@@ -106,7 +131,24 @@ class ParcelImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override val hasBlockVisitors: Boolean
|
||||
get() = permit != null
|
||||
|
||||
private var permit: Permit? = null
|
||||
|
||||
fun acquireBlockVisitorPermit(with: Permit): Boolean {
|
||||
if (permit === with) return true
|
||||
if (permit != null) return false
|
||||
permit = with
|
||||
return true
|
||||
}
|
||||
|
||||
fun releaseBlockVisitorPermit(with: Permit) {
|
||||
if (permit !== with) throw IllegalStateException()
|
||||
permit = null
|
||||
}
|
||||
|
||||
/*
|
||||
private var blockVisitors = AtomicInteger(0)
|
||||
|
||||
override suspend fun withBlockVisitorPermit(block: suspend () -> Unit) {
|
||||
@@ -116,9 +158,9 @@ class ParcelImpl(
|
||||
} finally {
|
||||
blockVisitors.getAndDecrement()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
override fun toString() = toStringExt()
|
||||
override fun toString() = parcelIdToString()
|
||||
|
||||
override val infoString: String
|
||||
get() = getInfoString()
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package io.dico.parcels2.defaultimpl
|
||||
|
||||
import io.dico.parcels2.*
|
||||
import io.dico.parcels2.blockvisitor.Schematic
|
||||
import io.dico.parcels2.util.schedule
|
||||
import kotlinx.coroutines.Unconfined
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.WorldCreator
|
||||
@@ -44,10 +46,11 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
|
||||
private fun loadWorlds0() {
|
||||
if (Bukkit.getWorlds().isEmpty()) {
|
||||
plugin.schedule(::loadWorlds0)
|
||||
plugin.logger.warning("Scheduling to load worlds in the next tick, \nbecause no bukkit worlds are loaded yet")
|
||||
plugin.logger.warning("Scheduling to load worlds in the next tick because no bukkit worlds are loaded yet")
|
||||
return
|
||||
}
|
||||
|
||||
val newlyCreatedWorlds = mutableListOf<ParcelWorld>()
|
||||
for ((worldName, worldOptions) in options.worlds.entries) {
|
||||
var parcelWorld = _worlds[worldName]
|
||||
if (parcelWorld != null) continue
|
||||
@@ -56,19 +59,20 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
|
||||
val worldExists = Bukkit.getWorld(worldName) != null
|
||||
val bukkitWorld =
|
||||
if (worldExists) Bukkit.getWorld(worldName)!!
|
||||
else WorldCreator(worldName).generator(generator).createWorld().also { logger.info("Creating world $worldName") }
|
||||
else {
|
||||
logger.info("Creating world $worldName")
|
||||
WorldCreator(worldName).generator(generator).createWorld()
|
||||
}
|
||||
|
||||
parcelWorld = ParcelWorldImpl(
|
||||
bukkitWorld, generator, worldOptions.runtime, plugin.storage,
|
||||
plugin.globalPrivileges, ::DefaultParcelContainer, plugin, plugin.jobDispatcher
|
||||
)
|
||||
parcelWorld = ParcelWorldImpl(plugin, bukkitWorld, generator, worldOptions.runtime,::DefaultParcelContainer)
|
||||
|
||||
if (!worldExists) {
|
||||
val time = DateTime.now()
|
||||
plugin.storage.setWorldCreationTime(parcelWorld.id, time)
|
||||
parcelWorld.creationTime = time
|
||||
newlyCreatedWorlds.add(parcelWorld)
|
||||
} else {
|
||||
launch(context = Unconfined) {
|
||||
GlobalScope.launch(context = Dispatchers.Unconfined) {
|
||||
parcelWorld.creationTime = plugin.storage.getWorldCreationTime(parcelWorld.id).await() ?: DateTime.now()
|
||||
}
|
||||
}
|
||||
@@ -76,11 +80,11 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
|
||||
_worlds[worldName] = parcelWorld
|
||||
}
|
||||
|
||||
loadStoredData()
|
||||
loadStoredData(newlyCreatedWorlds.toSet())
|
||||
}
|
||||
|
||||
private fun loadStoredData() {
|
||||
plugin.launch {
|
||||
private fun loadStoredData(newlyCreatedWorlds: Collection<ParcelWorld> = emptyList()) {
|
||||
plugin.launch(Dispatchers.Default) {
|
||||
val migration = plugin.options.migration
|
||||
if (migration.enabled) {
|
||||
migration.instance?.newInstance()?.apply {
|
||||
@@ -96,11 +100,14 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
|
||||
}
|
||||
|
||||
logger.info("Loading all parcel data...")
|
||||
val channel = plugin.storage.transmitAllParcelData()
|
||||
while (true) {
|
||||
val (id, data) = channel.receiveOrNull() ?: break
|
||||
val parcel = getParcelById(id) ?: continue
|
||||
data?.let { parcel.copyDataIgnoringDatabase(it) }
|
||||
|
||||
val job1 = launch {
|
||||
val channel = plugin.storage.transmitAllParcelData()
|
||||
while (true) {
|
||||
val (id, data) = channel.receiveOrNull() ?: break
|
||||
val parcel = getParcelById(id) ?: continue
|
||||
data?.let { parcel.copyData(it, callerIsDatabase = true) }
|
||||
}
|
||||
}
|
||||
|
||||
val channel2 = plugin.storage.transmitAllGlobalPrivileges()
|
||||
@@ -113,11 +120,61 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
|
||||
(plugin.globalPrivileges[profile] as PrivilegesHolder).copyPrivilegesFrom(data)
|
||||
}
|
||||
|
||||
job1.join()
|
||||
|
||||
logger.info("Loading data completed")
|
||||
_dataIsLoaded = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun acquireBlockVisitorPermit(parcelId: ParcelId, with: Permit): Boolean {
|
||||
val parcel = getParcelById(parcelId) as? ParcelImpl ?: return true
|
||||
return parcel.acquireBlockVisitorPermit(with)
|
||||
}
|
||||
|
||||
override fun releaseBlockVisitorPermit(parcelId: ParcelId, with: Permit) {
|
||||
val parcel = getParcelById(parcelId) as? ParcelImpl ?: return
|
||||
parcel.releaseBlockVisitorPermit(with)
|
||||
}
|
||||
|
||||
override fun trySubmitBlockVisitor(permit: Permit, vararg parcelIds: ParcelId, function: JobFunction): Job? {
|
||||
val withPermit = parcelIds.filter { acquireBlockVisitorPermit(it, permit) }
|
||||
if (withPermit.size != parcelIds.size) {
|
||||
withPermit.forEach { releaseBlockVisitorPermit(it, permit) }
|
||||
return null
|
||||
}
|
||||
|
||||
val job = plugin.jobDispatcher.dispatch(function)
|
||||
|
||||
plugin.launch {
|
||||
job.awaitCompletion()
|
||||
withPermit.forEach { releaseBlockVisitorPermit(it, permit) }
|
||||
}
|
||||
|
||||
return job
|
||||
}
|
||||
|
||||
override fun swapParcels(parcelId1: ParcelId, parcelId2: ParcelId): Job? {
|
||||
val blockManager1 = getWorldById(parcelId1.worldId)?.blockManager ?: return null
|
||||
val blockManager2 = getWorldById(parcelId2.worldId)?.blockManager ?: return null
|
||||
|
||||
return trySubmitBlockVisitor(Permit(), parcelId1, parcelId2) {
|
||||
var region1 = blockManager1.getRegion(parcelId1)
|
||||
var region2 = blockManager2.getRegion(parcelId2)
|
||||
|
||||
val size = region1.size.clampMax(region2.size)
|
||||
if (size != region1.size) {
|
||||
region1 = region1.withSize(size)
|
||||
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) } }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
fun loadWorlds(options: Options) {
|
||||
for ((worldName, worldOptions) in options.worlds.entries) {
|
||||
|
||||
@@ -3,30 +3,27 @@
|
||||
package io.dico.parcels2.defaultimpl
|
||||
|
||||
import io.dico.parcels2.*
|
||||
import io.dico.parcels2.blockvisitor.JobDispatcher
|
||||
import io.dico.parcels2.options.RuntimeWorldOptions
|
||||
import io.dico.parcels2.storage.Storage
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.bukkit.GameRule
|
||||
import org.bukkit.World
|
||||
import org.joda.time.DateTime
|
||||
import java.util.UUID
|
||||
|
||||
class ParcelWorldImpl(override val world: World,
|
||||
override val generator: ParcelGenerator,
|
||||
override var options: RuntimeWorldOptions,
|
||||
override val storage: Storage,
|
||||
override val globalPrivileges: GlobalPrivilegesManager,
|
||||
containerFactory: ParcelContainerFactory,
|
||||
coroutineScope: CoroutineScope,
|
||||
jobDispatcher: JobDispatcher)
|
||||
: ParcelWorld,
|
||||
ParcelWorldId,
|
||||
ParcelContainer, /* missing delegation */
|
||||
ParcelLocator /* missing delegation */ {
|
||||
|
||||
class ParcelWorldImpl(
|
||||
val plugin: ParcelsPlugin,
|
||||
override val world: World,
|
||||
override val generator: ParcelGenerator,
|
||||
override var options: RuntimeWorldOptions,
|
||||
containerFactory: ParcelContainerFactory
|
||||
) : ParcelWorld, ParcelWorldId, ParcelContainer, ParcelLocator {
|
||||
override val id: ParcelWorldId get() = this
|
||||
override val uid: UUID? get() = world.uid
|
||||
|
||||
override val storage get() = plugin.storage
|
||||
override val globalPrivileges get() = plugin.globalPrivileges
|
||||
|
||||
init {
|
||||
if (generator.world != world) {
|
||||
throw IllegalArgumentException()
|
||||
@@ -39,52 +36,40 @@ class ParcelWorldImpl(override val world: World,
|
||||
override val blockManager: ParcelBlockManager
|
||||
|
||||
init {
|
||||
val pair = generator.makeParcelLocatorAndBlockManager(id, container, coroutineScope, jobDispatcher)
|
||||
locator = pair.first
|
||||
blockManager = pair.second
|
||||
|
||||
val (locator, blockManager) = generator.makeParcelLocatorAndBlockManager(plugin.parcelProvider, container, plugin, plugin.jobDispatcher)
|
||||
this.locator = locator
|
||||
this.blockManager = blockManager
|
||||
enforceOptions()
|
||||
}
|
||||
|
||||
fun enforceOptions() {
|
||||
if (options.dayTime) {
|
||||
world.setGameRuleValue("doDaylightCycle", "false")
|
||||
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false)
|
||||
world.setTime(6000)
|
||||
}
|
||||
|
||||
if (options.noWeather) {
|
||||
world.setStorm(false)
|
||||
world.setThundering(false)
|
||||
world.weatherDuration = Integer.MAX_VALUE
|
||||
world.weatherDuration = Int.MAX_VALUE
|
||||
}
|
||||
|
||||
world.setGameRuleValue("doTileDrops", "${options.doTileDrops}")
|
||||
world.setGameRule(GameRule.DO_TILE_DROPS, options.doTileDrops)
|
||||
}
|
||||
|
||||
// Updated by ParcelProviderImpl
|
||||
// Accessed by ParcelProviderImpl
|
||||
override var creationTime: DateTime? = null
|
||||
|
||||
/*
|
||||
Interface delegation needs to be implemented manually because JetBrains has yet to fix it.
|
||||
*/
|
||||
|
||||
// ParcelLocator interface
|
||||
override fun getParcelAt(x: Int, z: Int): Parcel? {
|
||||
return locator.getParcelAt(x, z)
|
||||
}
|
||||
override fun getParcelAt(x: Int, z: Int): Parcel? = locator.getParcelAt(x, z)
|
||||
|
||||
override fun getParcelIdAt(x: Int, z: Int): ParcelId? {
|
||||
return locator.getParcelIdAt(x, z)
|
||||
}
|
||||
override fun getParcelIdAt(x: Int, z: Int): ParcelId? = locator.getParcelIdAt(x, z)
|
||||
|
||||
// ParcelContainer interface
|
||||
override fun getParcelById(x: Int, z: Int): Parcel? {
|
||||
return container.getParcelById(x, z)
|
||||
}
|
||||
override fun getParcelById(x: Int, z: Int): Parcel? = container.getParcelById(x, z)
|
||||
|
||||
override fun nextEmptyParcel(): Parcel? {
|
||||
return container.nextEmptyParcel()
|
||||
}
|
||||
override fun getParcelById(id: ParcelId): Parcel? = container.getParcelById(id)
|
||||
|
||||
override fun toString() = toStringExt()
|
||||
override fun nextEmptyParcel(): Parcel? = container.nextEmptyParcel()
|
||||
|
||||
override fun toString() = parcelWorldIdToString()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user