From 1dbf6796599d529d465c2e7d2c5ce298d7a1be4c Mon Sep 17 00:00:00 2001 From: Moritz Ruth Date: Tue, 29 Dec 2020 22:57:11 +0100 Subject: [PATCH] Add destroy method to World and change chunk loading functions --- .../net/event/PlayerInitializationEvent.kt | 2 +- .../main/kotlin/space/blokk/world/Chunk.kt | 24 ++++++++----------- .../main/kotlin/space/blokk/world/Voxel.kt | 7 ++++-- .../kotlin/space/blokk/world/VoxelLocation.kt | 7 ++++++ .../main/kotlin/space/blokk/world/World.kt | 13 ++++++---- .../space/blokk/testplugin/TestPlugin.kt | 6 ++--- 6 files changed, 35 insertions(+), 24 deletions(-) diff --git a/blokk-api/src/main/kotlin/space/blokk/net/event/PlayerInitializationEvent.kt b/blokk-api/src/main/kotlin/space/blokk/net/event/PlayerInitializationEvent.kt index 91bb786..282aa20 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/event/PlayerInitializationEvent.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/event/PlayerInitializationEvent.kt @@ -12,5 +12,5 @@ import space.blokk.world.VoxelLocation */ class PlayerInitializationEvent(override val target: Session, val settings: Player.Settings) : SessionEvent(), Cancellable { override var cancelled = false - var compassTarget: VoxelLocation = VoxelLocation(0, 0, 0) + var compassTarget: VoxelLocation = VoxelLocation.of(0, 0, 0) } diff --git a/blokk-api/src/main/kotlin/space/blokk/world/Chunk.kt b/blokk-api/src/main/kotlin/space/blokk/world/Chunk.kt index 4b5b80d..2f2729e 100644 --- a/blokk-api/src/main/kotlin/space/blokk/world/Chunk.kt +++ b/blokk-api/src/main/kotlin/space/blokk/world/Chunk.kt @@ -79,28 +79,20 @@ abstract class Chunk( * Returns whether this chunk contains [voxel]. */ // It does not just compare voxel.chunk with this because voxel.chunk may be expensive to create - operator fun contains(voxel: Voxel) = contains(voxel.location) + operator fun contains(voxel: Voxel) = voxel.world == world && contains(voxel.location) abstract fun getData(player: Player?): ChunkData - abstract fun getLightData(player: Player?): ChunkLightData /** - * Loads this chunk into memory. + * Starts loading this chunk into memory. * - * If the chunk is already loaded, this function does nothing. + * Does nothing if the chunk is already loaded or loading. */ - open suspend fun load() {} + open fun startLoading() {} + open suspend fun waitUntilLoaded() {} - val loaded get() = loadState == LoadState.LOADED - - open val loadState: LoadState = LoadState.LOADED - - enum class LoadState { - NOT_LOADED, - LOADING, - LOADED - } + open val loaded = true companion object { const val LENGTH: Int = 16 @@ -108,4 +100,8 @@ abstract class Chunk( const val SECTION_HEIGHT: Int = 16 const val BLOCKS_IN_A_SECTION = AREA * SECTION_HEIGHT } + + interface Unloadable { + suspend fun unload() + } } diff --git a/blokk-api/src/main/kotlin/space/blokk/world/Voxel.kt b/blokk-api/src/main/kotlin/space/blokk/world/Voxel.kt index 1b46cc5..abced5d 100644 --- a/blokk-api/src/main/kotlin/space/blokk/world/Voxel.kt +++ b/blokk-api/src/main/kotlin/space/blokk/world/Voxel.kt @@ -20,7 +20,10 @@ abstract class Voxel { val loaded: Boolean get() = chunk.loaded /** - * Shorthand for [`chunk.load()`][Chunk.load]. + * Loads [chunk] if it is not yet loaded. */ - suspend fun load() = chunk.load() + suspend fun loadAndWait() { + chunk.startLoading() + chunk.waitUntilLoaded() + } } diff --git a/blokk-api/src/main/kotlin/space/blokk/world/VoxelLocation.kt b/blokk-api/src/main/kotlin/space/blokk/world/VoxelLocation.kt index 9709982..dd4946e 100644 --- a/blokk-api/src/main/kotlin/space/blokk/world/VoxelLocation.kt +++ b/blokk-api/src/main/kotlin/space/blokk/world/VoxelLocation.kt @@ -46,6 +46,13 @@ data class VoxelLocation(val x: Int, val y: UByte, val z: Int) { CoordinatePart.Y -> y.toInt() CoordinatePart.Z -> z } + + companion object { + fun of(x: Int, y: Int, z: Int): VoxelLocation { + if (y !in 0..255) throw IllegalArgumentException("y must be in 0..255") + return VoxelLocation(x, y.toUByte(), z) + } + } } diff --git a/blokk-api/src/main/kotlin/space/blokk/world/World.kt b/blokk-api/src/main/kotlin/space/blokk/world/World.kt index 4b1e38e..d10e271 100644 --- a/blokk-api/src/main/kotlin/space/blokk/world/World.kt +++ b/blokk-api/src/main/kotlin/space/blokk/world/World.kt @@ -84,18 +84,23 @@ abstract class World(val uuid: UUID) { radius: Int, hollow: Boolean ): List { - // Implementation example https://git.io/JLysq + // Implementation example: https://git.io/JLysq TODO() } /** - * Spawns an [entity][Entity] in this world. + * Spawns [entity][Entity] in this world. */ abstract fun spawnEntity(entity: Entity) - fun unload() { + suspend fun destroy() = withContext(coroutineContext) { + // TODO: Move or kick players coroutineContext.cancel() - // TODO: Unload chunks + + coroutineScope { + loadedChunks.values.forEach { launch { (it as? Chunk.Unloadable)?.unload() } } + } + threadExecutor.close() } } diff --git a/test-plugin/src/main/kotlin/space/blokk/testplugin/TestPlugin.kt b/test-plugin/src/main/kotlin/space/blokk/testplugin/TestPlugin.kt index dabe668..26a9803 100644 --- a/test-plugin/src/main/kotlin/space/blokk/testplugin/TestPlugin.kt +++ b/test-plugin/src/main/kotlin/space/blokk/testplugin/TestPlugin.kt @@ -24,16 +24,16 @@ class TestPlugin: Plugin("Test", "1.0.0") { Blokk.dimensionRegistry.register(dimension) val world = AnvilWorld(dimension, true) - world.getVoxelsInCube(VoxelLocation(16, 0, 16), VoxelLocation(-16, 0, -16)).forEach { + world.getVoxelsInCube(VoxelLocation.of(16, 0, 16), VoxelLocation.of(-16, 0, -16)).forEach { it.block = if (it.location.x % 16 == 0 || it.location.z % 16 == 0) GreenWool() else RedWool() } - world.getVoxel(VoxelLocation(-1, 2, -1)).block = CraftingTable() + world.getVoxel(VoxelLocation.of(-1, 2, -1)).block = CraftingTable() Blokk.eventBus.on { event -> event.initialWorldAndLocation = WorldAndLocationWithRotation( world, - VoxelLocation(0, 2, 0).atTopCenter().withRotation(0f, 0f) + VoxelLocation.of(0, 2, 0).atTopCenter().withRotation(0f, 0f) ) } }