Implement chunk inversion system.

This commit is contained in:
Alex Zenla 2023-04-03 01:01:28 -07:00
parent 56886a24e1
commit 139743a4ba
Signed by: alex
GPG Key ID: C0780728420EBFE5

View File

@ -1,7 +1,11 @@
package gay.pizza.foundation.chaos.modules
import gay.pizza.foundation.chaos.randomPlayer
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
class WorldSwapper(val plugin: Plugin) : ChaosModule {
@ -9,38 +13,91 @@ class WorldSwapper(val plugin: Plugin) : ChaosModule {
override fun name(): String = "World Swapper"
override fun what(): String = "Swaps the world vertically on activation, and un-swaps it on deactivation."
var snapshot: ChunkSnapshot? = null
var chunkInversions = mutableListOf<ChunkInversion>()
override fun activate() {
val player = plugin.server.randomPlayer() ?: return
val chunk = player.world.getChunkAt(player.location)
val localSnapshot = chunk.chunkSnapshot
val baseChunk = player.chunk
recordInvert(baseChunk)
player.teleport(player.location.toHighestLocation())
val chunksToInvert = player.world.loadedChunks.filter { it != baseChunk }.toMutableList()
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 targetBlock = chunk.getBlock(x, y, z)
val inverseY = heightRange.random()
val nextBlock = localSnapshot.getBlockData(x, inverseY, z)
targetBlock.setBlockData(nextBlock, true)
}
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)
}
snapshot = localSnapshot
scheduleOne()
}
fun recordInvert(chunk: Chunk) {
chunkInversions.add(invertChunk(chunk))
}
override fun deactivate() {
val localSnapshot = snapshot ?: return
val world = plugin.server.getWorld(localSnapshot.worldName) ?: return
val chunk = world.getChunkAt(localSnapshot.x, localSnapshot.z)
fun scheduleOne() {
if (chunkInversions.isEmpty()) {
return
}
val inversion = chunkInversions.removeAt(0)
plugin.server.scheduler.runTaskLater(plugin, { ->
inversion.revert()
scheduleOne()
}, 5)
}
scheduleOne()
}
fun invertChunk(chunk: Chunk): ChunkInversion {
val snapshot = chunk.chunkSnapshot
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 = localSnapshot.getBlockData(x, y, z)
chunk.getBlock(x, y, z).blockData = originalBlock
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)
}
private fun invertSetBlockData(block: Block, data: BlockData) {
block.setBlockData(data, false)
}
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
}
}
}
}