mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-08-03 05:30:55 +00:00
Implement Chunk Export
This commit is contained in:
@ -6,6 +6,7 @@ import cloud.kubelet.foundation.heimdall.buffer.BufferFlushThread
|
|||||||
import cloud.kubelet.foundation.heimdall.buffer.EventBuffer
|
import cloud.kubelet.foundation.heimdall.buffer.EventBuffer
|
||||||
import cloud.kubelet.foundation.heimdall.event.*
|
import cloud.kubelet.foundation.heimdall.event.*
|
||||||
import cloud.kubelet.foundation.heimdall.model.HeimdallConfig
|
import cloud.kubelet.foundation.heimdall.model.HeimdallConfig
|
||||||
|
import cloud.kubelet.foundation.heimdall.export.ExportChunksCommand
|
||||||
import com.charleskorn.kaml.Yaml
|
import com.charleskorn.kaml.Yaml
|
||||||
import com.zaxxer.hikari.HikariConfig
|
import com.zaxxer.hikari.HikariConfig
|
||||||
import com.zaxxer.hikari.HikariDataSource
|
import com.zaxxer.hikari.HikariDataSource
|
||||||
@ -38,6 +39,9 @@ class FoundationHeimdallPlugin : JavaPlugin(), Listener {
|
|||||||
private val legacyComponentSerializer = LegacyComponentSerializer.builder().build()
|
private val legacyComponentSerializer = LegacyComponentSerializer.builder().build()
|
||||||
|
|
||||||
override fun onEnable() {
|
override fun onEnable() {
|
||||||
|
val exportChunksCommand = getCommand("export_all_chunks") ?: throw Exception("Failed to get export_all_chunks command")
|
||||||
|
exportChunksCommand.setExecutor(ExportChunksCommand(this))
|
||||||
|
|
||||||
val foundation = server.pluginManager.getPlugin("Foundation") as FoundationCorePlugin
|
val foundation = server.pluginManager.getPlugin("Foundation") as FoundationCorePlugin
|
||||||
|
|
||||||
val configPath = Util.copyDefaultConfig<FoundationHeimdallPlugin>(
|
val configPath = Util.copyDefaultConfig<FoundationHeimdallPlugin>(
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
package cloud.kubelet.foundation.heimdall.export
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.encodeToStream
|
||||||
|
import org.bukkit.Chunk
|
||||||
|
import org.bukkit.ChunkSnapshot
|
||||||
|
import org.bukkit.Server
|
||||||
|
import org.bukkit.World
|
||||||
|
import org.bukkit.plugin.Plugin
|
||||||
|
import java.io.File
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import java.util.zip.GZIPOutputStream
|
||||||
|
|
||||||
|
class ChunkExporter(private val plugin: Plugin, private val server: Server, val world: World) {
|
||||||
|
private val json = Json {
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportLoadedChunksAsync() {
|
||||||
|
exportChunkListAsync(world.loadedChunks.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportChunkListAsync(chunks: List<Chunk>) {
|
||||||
|
val listOfChunks = chunks.toMutableList()
|
||||||
|
doExportChunkList(listOfChunks, AtomicBoolean(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doExportChunkList(chunks: MutableList<Chunk>, check: AtomicBoolean) {
|
||||||
|
check.set(false)
|
||||||
|
val chunk = chunks.removeFirstOrNull()
|
||||||
|
if (chunk == null) {
|
||||||
|
plugin.slF4JLogger.info("Chunk Export Complete")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val snapshot = chunk.chunkSnapshot
|
||||||
|
server.scheduler.runTaskAsynchronously(plugin) { ->
|
||||||
|
saveChunkSnapshotAndScheduleNext(snapshot, chunks, check)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveChunkSnapshotAndScheduleNext(snapshot: ChunkSnapshot, chunks: MutableList<Chunk>, check: AtomicBoolean) {
|
||||||
|
exportChunkSnapshot(snapshot)
|
||||||
|
if (!check.getAndSet(true)) {
|
||||||
|
plugin.server.scheduler.runTask(plugin) { -> doExportChunkList(chunks, check) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportChunkSnapshot(snapshot: ChunkSnapshot) {
|
||||||
|
val sections = mutableListOf<ExportedChunkSection>()
|
||||||
|
val yRange = world.minHeight until world.maxHeight
|
||||||
|
val chunkRange = 0..15
|
||||||
|
for (x in chunkRange) {
|
||||||
|
for (z in chunkRange) {
|
||||||
|
sections.add(exportChunkSection(snapshot, yRange, x, z))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val exported = ExportedChunk(snapshot.x, snapshot.z, sections)
|
||||||
|
saveChunkSnapshot(snapshot, exported)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveChunkSnapshot(snapshot: ChunkSnapshot, chunk: ExportedChunk) {
|
||||||
|
val file = File("exported_chunks/${snapshot.worldName}_chunk_${snapshot.x}_${snapshot.z}.json.gz")
|
||||||
|
if (!file.parentFile.exists()) {
|
||||||
|
file.parentFile.mkdirs()
|
||||||
|
}
|
||||||
|
|
||||||
|
val fileOutputStream = file.outputStream()
|
||||||
|
val gzipOutputStream = GZIPOutputStream(fileOutputStream)
|
||||||
|
json.encodeToStream(ExportedChunk.serializer(), chunk, gzipOutputStream)
|
||||||
|
gzipOutputStream.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportChunkSection(snapshot: ChunkSnapshot, yRange: IntRange, x: Int, z: Int): ExportedChunkSection {
|
||||||
|
val blocks = mutableListOf<ExportedBlock>()
|
||||||
|
for (y in yRange) {
|
||||||
|
val blockData = snapshot.getBlockData(x, y, z)
|
||||||
|
val block = ExportedBlock(blockData.material.key.toString())
|
||||||
|
blocks.add(block)
|
||||||
|
}
|
||||||
|
return ExportedChunkSection(x, z, blocks)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package cloud.kubelet.foundation.heimdall.export
|
||||||
|
|
||||||
|
import org.bukkit.command.Command
|
||||||
|
import org.bukkit.command.CommandExecutor
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
import org.bukkit.plugin.Plugin
|
||||||
|
|
||||||
|
class ExportChunksCommand(private val plugin: Plugin) : CommandExecutor {
|
||||||
|
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
|
||||||
|
plugin.slF4JLogger.info("Exporting All Chunks")
|
||||||
|
for (world in sender.server.worlds) {
|
||||||
|
val export = ChunkExporter(plugin, sender.server, world)
|
||||||
|
export.exportLoadedChunksAsync()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package cloud.kubelet.foundation.heimdall.export
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ExportedBlock(
|
||||||
|
val type: String
|
||||||
|
)
|
@ -0,0 +1,10 @@
|
|||||||
|
package cloud.kubelet.foundation.heimdall.export
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ExportedChunk(
|
||||||
|
val x: Int,
|
||||||
|
val z: Int,
|
||||||
|
val sections: List<ExportedChunkSection>
|
||||||
|
)
|
@ -0,0 +1,10 @@
|
|||||||
|
package cloud.kubelet.foundation.heimdall.export
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ExportedChunkSection(
|
||||||
|
val x: Int,
|
||||||
|
val z: Int,
|
||||||
|
val blocks: List<ExportedBlock>
|
||||||
|
)
|
@ -8,3 +8,8 @@ depend:
|
|||||||
- Foundation
|
- Foundation
|
||||||
authors:
|
authors:
|
||||||
- kubelet
|
- kubelet
|
||||||
|
commands:
|
||||||
|
export_all_chunks:
|
||||||
|
description: Export All Chunks
|
||||||
|
usage: /export_all_chunks
|
||||||
|
permission: foundation.heimdall.command.export_all_chunks
|
||||||
|
@ -20,11 +20,12 @@ class BlockChangelog(
|
|||||||
slice.isTimeWithinSliceRange(it.time)
|
slice.isTimeWithinSliceRange(it.time)
|
||||||
}
|
}
|
||||||
|
|
||||||
val changeTimeRange: ChangelogSlice
|
val fullTimeSlice: ChangelogSlice
|
||||||
get() = ChangelogSlice(changes.minOf { it.time }, changes.maxOf { it.time })
|
get() = ChangelogSlice(changes.minOf { it.time }, changes.maxOf { it.time })
|
||||||
|
|
||||||
fun calculateChangelogSlices(interval: Duration, limit: Int? = null): List<ChangelogSlice> {
|
fun calculateChangelogSlices(interval: Duration, limit: Int? = null): List<ChangelogSlice> {
|
||||||
val (start, end) = changeTimeRange
|
val start = fullTimeSlice.rootStartTime
|
||||||
|
val end = fullTimeSlice.sliceEndTime
|
||||||
var intervals = mutableListOf<Instant>()
|
var intervals = mutableListOf<Instant>()
|
||||||
var current = start
|
var current = start
|
||||||
while (!current.isAfter(end)) {
|
while (!current.isAfter(end)) {
|
||||||
|
Reference in New Issue
Block a user