Skip to content
This repository has been archived by the owner on Apr 14, 2024. It is now read-only.

Commit

Permalink
Make more things use TNTSource + cleanup
Browse files Browse the repository at this point in the history
Also enabled parallel loading
  • Loading branch information
emortal committed Jul 23, 2022
1 parent dd9a63e commit ecda397
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 36 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ Creating a Minestom instance
// In Kotlin
val instance = MinecraftServer.getInstanceManager().createInstanceContainer()
val tntLoader = TNTLoader(instance, FileTNTSource(Path.of("path/to/world.tnt")))
// Shorthand version
val tntLoader = TNTLoader(instance, "path/to/world.tnt")

instance.chunkLoader = tntLoader

// In Java
InstanceContainer instance = MinecraftServer.getInstanceManager().createInstanceContainer();
TNTLoader tntLoader = new TNTLoader(instance, FileTNTSource(Path.of("path/to/world.tnt")));
// Shorthand version
TNTLoader tntLoader = new TNTLoader(instance, "path/to/world.tnt")

instance.setChunkLoader(tntLoader);
```

Expand All @@ -43,9 +49,10 @@ For example:
- /worlds/world/ <- Anvil world folder
- /worlds/world.tnt <- TNT world file (Put this path into the `TNTSource`)

You may also convert an anvil world to TNT manually with `TNT.convertAnvilToTNT(pathToAnvil, tntSaveSource)`

## TNT Sources
The TNTLoader can be loaded from wherever you want (however only has `FileTNTSource` built in)
TNT worlds can be loaded and saved wherever you want (however only `FileTNTSource` is built in)

For example, you could make it read from Redis, MongoDB, MySQL or any sort of datastore.

Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ dependencies {

compileOnly("com.github.Minestom:Minestom:d596992c0e")

compileOnly("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2")
implementation("com.github.luben:zstd-jni:1.5.2-3")
}

Expand Down
56 changes: 27 additions & 29 deletions src/main/kotlin/dev/emortal/tnt/TNT.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package dev.emortal.tnt

import com.github.luben.zstd.Zstd
import dev.emortal.tnt.source.TNTSource
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import net.minestom.server.MinecraftServer
import net.minestom.server.instance.Chunk
import net.minestom.server.instance.block.Block
Expand All @@ -17,12 +20,12 @@ object TNT {

private val LOGGER = LoggerFactory.getLogger(TNT::class.java)

val tntScope = CoroutineScope(Dispatchers.IO)

/**
* Creates a .TNT world from chunks
* @param chunks The chunks to use to create the world
* @param path Where to create the file
* Saves a .TNT world from chunks
*/
fun createTNTFile(chunks: Collection<Chunk>, path: Path) {
fun createTNTFile(chunks: Collection<Chunk>, tntSource: TNTSource) {
val writer = BinaryWriter()

writer.writeInt(chunks.size)
Expand Down Expand Up @@ -82,58 +85,53 @@ object TNT {
val bytes: ByteArray = writer.toByteArray()
val compressed = Zstd.compress(bytes)

tntSource.save(compressed)

writer.close()
writer.flush()

Files.write(path, compressed)
}

fun convertAnvilToTNT(path: Path) {
/**
* Converts an anvil folder to a TNT file
*
* Source support should be added
*/
fun convertAnvilToTNT(pathToAnvil: Path, tntSaveSource: TNTSource) {
val instanceManager = MinecraftServer.getInstanceManager()

val mcaFiles = Files.list(path.parent.resolve(path.nameWithoutExtension).resolve("region")).collect(
val mcaFiles = Files.list(pathToAnvil.resolve("region")).collect(
Collectors.toSet())
println(mcaFiles.size)

val convertInstance = instanceManager.createInstanceContainer()
val loader = ConversionAnvilLoader(path.parent.resolve(path.nameWithoutExtension))
val loader = ConversionAnvilLoader(pathToAnvil)
convertInstance.chunkLoader = loader

val countDownLatch = CountDownLatch((mcaFiles.size) * 1024)
val countDownLatch = CountDownLatch((mcaFiles.size) * 32 * 32) // each MCA file contains 32 chunks
val chunks: MutableSet<Chunk> = ConcurrentHashMap.newKeySet()

mcaFiles.forEach {
val args = it.nameWithoutExtension.split(".").takeLast(2)
val rX = args[0].toInt()
val rZ = args[1].toInt()

for (x in rX * 32 until rX * 32 + 32)
for (x in rX * 32 until rX * 32 + 32) {
for (z in rZ * 32 until rZ * 32 + 32) {
convertInstance.loadChunk(x, z).thenAccept {
var hasBlocks = false
for (x in 0 until 16) {
if (hasBlocks) break
for (y in -64 until 320) {
if (hasBlocks) break
for (z in 0 until 16) {
if (it.getBlock(x, y, z) != Block.AIR) {
hasBlocks = true
break
}
}
}
}

convertInstance.loadChunk(x, z).thenAcceptAsync {
// Ignore chunks that contain no blocks
if (hasBlocks) chunks.add(it)
if (it.sections.any { it.blockPalette().count() > 0 }) chunks.add(it)

countDownLatch.countDown()
}
}
}
}

val before = System.nanoTime()
countDownLatch.await()
println("Took ${(System.nanoTime() - before) / 1_000_000}ms to convert")

createTNTFile(chunks, path)
// TODO: make source independant
createTNTFile(chunks, tntSaveSource)

instanceManager.unregisterInstance(convertInstance)
}
Expand Down
13 changes: 11 additions & 2 deletions src/main/kotlin/dev/emortal/tnt/TNTLoader.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.emortal.tnt

import com.github.luben.zstd.Zstd
import dev.emortal.tnt.source.FileTNTSource
import dev.emortal.tnt.source.TNTSource
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
import net.minestom.server.MinecraftServer
Expand All @@ -18,13 +19,16 @@ import org.jglrxavpok.hephaistos.nbt.CompressedProcesser
import org.jglrxavpok.hephaistos.nbt.NBTCompound
import org.jglrxavpok.hephaistos.nbt.NBTReader
import org.slf4j.LoggerFactory
import java.nio.file.Path
import java.util.concurrent.CompletableFuture


val LOGGER = LoggerFactory.getLogger(TNTLoader::class.java)

class TNTLoader(val instance: Instance, val tntSource: TNTSource, val offset: Point = Pos.ZERO) : IChunkLoader {

constructor(instance: Instance, path: String, offset: Point = Pos.ZERO) : this(instance, FileTNTSource(Path.of(path)), offset)

private val chunksMap = Long2ObjectOpenHashMap<TNTChunk>()

init {
Expand Down Expand Up @@ -81,7 +85,8 @@ class TNTLoader(val instance: Instance, val tntSource: TNTSource, val offset: Po
Block.fromStateId(stateId)!!
}

batch.setBlock(x + offset.blockX(), y + (sectionY * 16) + offset.blockY(), z + offset.blockZ(), block)
// TODO: fix X and Z offset
batch.setBlock(x/* + offset.blockX()*/, y + (sectionY * 16) + offset.blockY(), z/* + offset.blockZ()*/, block)
}
}
}
Expand All @@ -105,19 +110,23 @@ class TNTLoader(val instance: Instance, val tntSource: TNTSource, val offset: Po

val future = CompletableFuture<Chunk?>()

// Copy chunk light from mstChunk to the new chunk
chunk.sections.forEachIndexed { i, it ->
val sec = mstChunk.sections[i]
it.blockLight = sec.blockLight
it.skyLight = sec.skyLight
}
mstChunk.chunkBatch.apply(instance, chunk) { future.complete(chunk) }

instance.saveChunksToStorage()

return future
}

override fun saveChunk(chunk: Chunk): CompletableFuture<Void> {
// no
return CompletableFuture.completedFuture(null)
}

override fun supportsParallelLoading(): Boolean = true

}
11 changes: 8 additions & 3 deletions src/main/kotlin/dev/emortal/tnt/source/FileTNTSource.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,21 @@ class FileTNTSource(val path: Path) : TNTSource {
override fun load(): InputStream {
if (!Files.exists(path)) {
// No world folder
LOGGER.error("Path doesn't exist")

if (Files.isDirectory(path.parent.resolve(path.nameWithoutExtension))) {
LOGGER.info("Path is an anvil world. Converting!")
LOGGER.info("Path is an anvil world. Converting! (This might take a bit)")

TNT.convertAnvilToTNT(path)
TNT.convertAnvilToTNT(path.parent.resolve(path.nameWithoutExtension), FileTNTSource(path))
LOGGER.info("Converted!")
} else {
LOGGER.error("Path doesn't exist!")
}
}

return Files.newInputStream(path)
}

override fun save(bytes: ByteArray) {
Files.write(path, bytes)
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/dev/emortal/tnt/source/TNTSource.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ interface TNTSource {

fun load(): InputStream

//fun save(): InputStream
fun save(bytes: ByteArray)

}

0 comments on commit ecda397

Please sign in to comment.