Add destroy method to World and change chunk loading functions
This commit is contained in:
parent
1a69b3f3a1
commit
1dbf679659
6 changed files with 35 additions and 24 deletions
|
@ -12,5 +12,5 @@ import space.blokk.world.VoxelLocation
|
||||||
*/
|
*/
|
||||||
class PlayerInitializationEvent(override val target: Session, val settings: Player.Settings) : SessionEvent(), Cancellable {
|
class PlayerInitializationEvent(override val target: Session, val settings: Player.Settings) : SessionEvent(), Cancellable {
|
||||||
override var cancelled = false
|
override var cancelled = false
|
||||||
var compassTarget: VoxelLocation = VoxelLocation(0, 0, 0)
|
var compassTarget: VoxelLocation = VoxelLocation.of(0, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,28 +79,20 @@ abstract class Chunk(
|
||||||
* Returns whether this chunk contains [voxel].
|
* Returns whether this chunk contains [voxel].
|
||||||
*/
|
*/
|
||||||
// It does not just compare voxel.chunk with this because voxel.chunk may be expensive to create
|
// 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 getData(player: Player?): ChunkData
|
||||||
|
|
||||||
abstract fun getLightData(player: Player?): ChunkLightData
|
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 loaded = true
|
||||||
|
|
||||||
open val loadState: LoadState = LoadState.LOADED
|
|
||||||
|
|
||||||
enum class LoadState {
|
|
||||||
NOT_LOADED,
|
|
||||||
LOADING,
|
|
||||||
LOADED
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val LENGTH: Int = 16
|
const val LENGTH: Int = 16
|
||||||
|
@ -108,4 +100,8 @@ abstract class Chunk(
|
||||||
const val SECTION_HEIGHT: Int = 16
|
const val SECTION_HEIGHT: Int = 16
|
||||||
const val BLOCKS_IN_A_SECTION = AREA * SECTION_HEIGHT
|
const val BLOCKS_IN_A_SECTION = AREA * SECTION_HEIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Unloadable {
|
||||||
|
suspend fun unload()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,10 @@ abstract class Voxel {
|
||||||
val loaded: Boolean get() = chunk.loaded
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,13 @@ data class VoxelLocation(val x: Int, val y: UByte, val z: Int) {
|
||||||
CoordinatePart.Y -> y.toInt()
|
CoordinatePart.Y -> y.toInt()
|
||||||
CoordinatePart.Z -> z
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -84,18 +84,23 @@ abstract class World(val uuid: UUID) {
|
||||||
radius: Int,
|
radius: Int,
|
||||||
hollow: Boolean
|
hollow: Boolean
|
||||||
): List<Voxel> {
|
): List<Voxel> {
|
||||||
// Implementation example https://git.io/JLysq
|
// Implementation example: https://git.io/JLysq
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawns an [entity][Entity] in this world.
|
* Spawns [entity][Entity] in this world.
|
||||||
*/
|
*/
|
||||||
abstract fun spawnEntity(entity: Entity)
|
abstract fun spawnEntity(entity: Entity)
|
||||||
|
|
||||||
fun unload() {
|
suspend fun destroy() = withContext(coroutineContext) {
|
||||||
|
// TODO: Move or kick players
|
||||||
coroutineContext.cancel()
|
coroutineContext.cancel()
|
||||||
// TODO: Unload chunks
|
|
||||||
|
coroutineScope {
|
||||||
|
loadedChunks.values.forEach { launch { (it as? Chunk.Unloadable)?.unload() } }
|
||||||
|
}
|
||||||
|
|
||||||
threadExecutor.close()
|
threadExecutor.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,16 +24,16 @@ class TestPlugin: Plugin("Test", "1.0.0") {
|
||||||
Blokk.dimensionRegistry.register(dimension)
|
Blokk.dimensionRegistry.register(dimension)
|
||||||
|
|
||||||
val world = AnvilWorld(dimension, true)
|
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()
|
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<SessionAfterLoginEvent> { event ->
|
Blokk.eventBus.on<SessionAfterLoginEvent> { event ->
|
||||||
event.initialWorldAndLocation = WorldAndLocationWithRotation(
|
event.initialWorldAndLocation = WorldAndLocationWithRotation(
|
||||||
world,
|
world,
|
||||||
VoxelLocation(0, 2, 0).atTopCenter().withRotation(0f, 0f)
|
VoxelLocation.of(0, 2, 0).atTopCenter().withRotation(0f, 0f)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue