diff --git a/common-all/src/main/kotlin/gay/pizza/foundation/common/CommonExtensions.kt b/common-all/src/main/kotlin/gay/pizza/foundation/common/CommonExtensions.kt new file mode 100644 index 0000000..dd5c956 --- /dev/null +++ b/common-all/src/main/kotlin/gay/pizza/foundation/common/CommonExtensions.kt @@ -0,0 +1,3 @@ +package gay.pizza.foundation.common + +fun Array.without(value: T): List = filter { it != value } diff --git a/foundation-chaos/build.gradle.kts b/foundation-chaos/build.gradle.kts index 7a4a0df..c2aada8 100644 --- a/foundation-chaos/build.gradle.kts +++ b/foundation-chaos/build.gradle.kts @@ -3,6 +3,7 @@ plugins { } dependencies { + implementation(project(":common-all")) implementation(project(":common-plugin")) compileOnly(project(":foundation-shared")) } diff --git a/foundation-chaos/src/main/kotlin/gay/pizza/foundation/chaos/modules/ChaosHelpers.kt b/foundation-chaos/src/main/kotlin/gay/pizza/foundation/chaos/modules/ChaosHelpers.kt new file mode 100644 index 0000000..afb774f --- /dev/null +++ b/foundation-chaos/src/main/kotlin/gay/pizza/foundation/chaos/modules/ChaosHelpers.kt @@ -0,0 +1,71 @@ +package gay.pizza.foundation.chaos.modules + +import org.bukkit.Chunk +import org.bukkit.ChunkSnapshot +import org.bukkit.World +import org.bukkit.block.Block +import org.bukkit.entity.Player +import org.bukkit.plugin.Plugin +import org.bukkit.scheduler.BukkitScheduler + +val World.heightRange + get() = minHeight until maxHeight + +inline fun forEachChunkPosition(crossinline each: (Int, Int) -> Unit) { + for (x in 0..15) { + for (z in 0..15) { + each(x, z) + } + } +} + +inline fun Chunk.forEachPosition(crossinline each: (Int, Int, Int) -> Unit) { + for (x in 0..15) { + for (z in 0..15) { + for (y in world.heightRange) { + each(x, y, z) + } + } + } +} + +inline fun Chunk.forEachBlock(crossinline each: (Int, Int, Int, Block) -> Unit) { + forEachPosition { x, y, z -> + each(x, y, z, getBlock(x, y, z)) + } +} + +fun Chunk.applyChunkSnapshot(snapshot: ChunkSnapshot) { + forEachPosition { x, y, z -> + val blockData = snapshot.getBlockData(x, y, z) + val block = getBlock(x, y, z) + block.blockData = blockData + } +} + +fun Player.teleportHighestLocation() { + teleport(location.toHighestLocation().add(0.0, 1.0, 0.0)) +} + +fun BukkitScheduler.scheduleUntilEmpty( + plugin: Plugin, + items: MutableList, + ticksBetween: Long, + callback: (T) -> Unit +) { + fun performOne() { + if (items.isEmpty()) { + return + } + val item = items.removeAt(0) + callback(item) + + if (items.isNotEmpty()) { + runTaskLater(plugin, { -> + performOne() + }, ticksBetween) + } + } + + performOne() +} diff --git a/foundation-chaos/src/main/kotlin/gay/pizza/foundation/chaos/modules/ChunkEnterRotate.kt b/foundation-chaos/src/main/kotlin/gay/pizza/foundation/chaos/modules/ChunkEnterRotate.kt index 522f814..9fdbb54 100644 --- a/foundation-chaos/src/main/kotlin/gay/pizza/foundation/chaos/modules/ChunkEnterRotate.kt +++ b/foundation-chaos/src/main/kotlin/gay/pizza/foundation/chaos/modules/ChunkEnterRotate.kt @@ -23,20 +23,15 @@ class ChunkEnterRotate : ChaosModule { } rotateChunk(currentChunk) if (!player.isFlying) { - player.teleport(player.location.toHighestLocation().add(0.0, 1.0, 0.0)) + player.teleportHighestLocation() } } private fun rotateChunk(chunk: Chunk) { val snapshot = chunk.chunkSnapshot - for (x in 0..15) { - for (z in 0..15) { - for (y in chunk.world.minHeight until chunk.world.maxHeight) { - val rotatedBlock = chunk.getBlock(z, y, x) - val originalBlockData = snapshot.getBlockData(x, y, z) - rotatedBlock.blockData = originalBlockData - } - } + chunk.forEachBlock { x, y, z, rotatedBlock -> + val originalBlockData = snapshot.getBlockData(z, y, x) + rotatedBlock.blockData = originalBlockData } } } diff --git a/foundation-chaos/src/main/kotlin/gay/pizza/foundation/chaos/modules/WorldSwapper.kt b/foundation-chaos/src/main/kotlin/gay/pizza/foundation/chaos/modules/WorldSwapper.kt index f8e361f..47faef0 100644 --- a/foundation-chaos/src/main/kotlin/gay/pizza/foundation/chaos/modules/WorldSwapper.kt +++ b/foundation-chaos/src/main/kotlin/gay/pizza/foundation/chaos/modules/WorldSwapper.kt @@ -1,9 +1,9 @@ package gay.pizza.foundation.chaos.modules import gay.pizza.foundation.chaos.randomPlayer +import gay.pizza.foundation.common.without import org.bukkit.Chunk import org.bukkit.ChunkSnapshot -import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.data.BlockData import org.bukkit.plugin.Plugin @@ -20,22 +20,12 @@ class WorldSwapper(val plugin: Plugin) : ChaosModule { val baseChunk = player.chunk recordInvert(baseChunk) player.teleport(player.location.toHighestLocation()) - val chunksToInvert = player.world.loadedChunks.filter { it != baseChunk }.toMutableList() + val chunksToInvert = player.world.loadedChunks.without(baseChunk).toMutableList() println("Inverting ${chunksToInvert.size} chunks...") - fun scheduleOne() { - if (chunksToInvert.isEmpty()) { - return - } - - val chunk = chunksToInvert.removeAt(0) - plugin.server.scheduler.runTaskLater(plugin, { -> - recordInvert(chunk) - scheduleOne() - }, 5) + plugin.server.scheduler.scheduleUntilEmpty(plugin, chunksToInvert, 5) { chunk -> + recordInvert(chunk) } - - scheduleOne() } fun recordInvert(chunk: Chunk) { @@ -60,20 +50,18 @@ class WorldSwapper(val plugin: Plugin) : ChaosModule { fun invertChunk(chunk: Chunk): ChunkInversion { val snapshot = chunk.chunkSnapshot - for (x in 0..15) { - for (z in 0..15) { - var sy = chunk.world.minHeight - var ey = chunk.world.maxHeight - while (sy != ey) { - sy++ - ey-- - val targetBlock = chunk.getBlock(x, sy, z) - val targetBlockData = targetBlock.blockData.clone() - val nextBlock = chunk.getBlock(x, ey, z) - val nextBlockData = nextBlock.blockData.clone() - invertSetBlockData(targetBlock, nextBlockData) - invertSetBlockData(nextBlock, targetBlockData) - } + forEachChunkPosition { x, z -> + var sy = chunk.world.minHeight + var ey = chunk.world.maxHeight + while (sy != ey) { + sy++ + ey-- + val targetBlock = chunk.getBlock(x, sy, z) + val targetBlockData = targetBlock.blockData.clone() + val nextBlock = chunk.getBlock(x, ey, z) + val nextBlockData = nextBlock.blockData.clone() + invertSetBlockData(targetBlock, nextBlockData) + invertSetBlockData(nextBlock, targetBlockData) } } return ChunkInversion(plugin, snapshot) @@ -83,23 +71,11 @@ class WorldSwapper(val plugin: Plugin) : ChaosModule { block.setBlockData(data, false) } - class ChunkInversion( - val plugin: Plugin, - val snapshot: ChunkSnapshot - ) { + class ChunkInversion(val plugin: Plugin, val snapshot: ChunkSnapshot) { fun revert() { val world = plugin.server.getWorld(snapshot.worldName) ?: return val chunk = world.getChunkAt(snapshot.x, snapshot.z) - - for (x in 0..15) { - for (z in 0..15) { - val heightRange = chunk.world.minHeight + 1 until chunk.world.maxHeight - for (y in heightRange) { - val originalBlock = snapshot.getBlockData(x, y, z) - chunk.getBlock(x, y, z).blockData = originalBlock - } - } - } + chunk.applyChunkSnapshot(snapshot) } } }