mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-13 03:54:06 +09:00
more chunkpool stuffs
This commit is contained in:
@@ -38,7 +38,7 @@ class BlockLayerFluidI16F16 : BlockLayer {
|
|||||||
this.width = width
|
this.width = width
|
||||||
this.height = height
|
this.height = height
|
||||||
|
|
||||||
chunkPool = ChunkPool(disk, layerNum, BlockLayerGenericI16.BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world))
|
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world))
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -51,87 +51,41 @@ class BlockLayerFluidI16F16 : BlockLayer {
|
|||||||
this.width = width
|
this.width = width
|
||||||
this.height = height
|
this.height = height
|
||||||
|
|
||||||
chunkPool = ChunkPool(disk, layerNum, BlockLayerGenericI16.BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world))
|
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||||
|
|
||||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
|
||||||
|
|
||||||
val ptrDestroyed: Boolean
|
|
||||||
get() = ptr.destroyed
|
|
||||||
|
|
||||||
init {
|
|
||||||
ptr.fillWith(-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an iterator over stored bytes.
|
|
||||||
*
|
|
||||||
* @return an Iterator.
|
|
||||||
*/
|
|
||||||
fun bytesIterator(): Iterator<Byte> {
|
|
||||||
return object : Iterator<Byte> {
|
|
||||||
private var iteratorCount = 0L
|
|
||||||
override fun hasNext(): Boolean {
|
|
||||||
return iteratorCount < width * height * bytesPerBlock
|
|
||||||
}
|
|
||||||
override fun next(): Byte {
|
|
||||||
iteratorCount += 1
|
|
||||||
return ptr[iteratorCount - 1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
val offset = getOffset(x, y)
|
return unsafeGetTile1(x, y).first
|
||||||
val lsb = ptr[offset]
|
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
|
|
||||||
return lsb.toUint() or msb.toUint().shl(8)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Float> {
|
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Float> {
|
||||||
val offset = getOffset(x, y)
|
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||||
val lsb = ptr[offset]
|
return chunkPool.getTileI16F16(chunk, ox, oy)
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
val hbits = (ptr[offset + 2].toUint() or ptr[offset + 3].toUint().shl(8)).toShort()
|
|
||||||
val fill = Float16.toFloat(hbits)
|
|
||||||
|
|
||||||
return lsb.toUint() or msb.toUint().shl(8) to fill
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
val offset = getOffset(x, y)
|
val (tile, fill0) = unsafeGetTile1(x, y)
|
||||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 3], ptr[offset + 2])
|
val fill = Float16.fromFloat(fill0).toUint()
|
||||||
|
return byteArrayOf(
|
||||||
|
((tile ushr 8) and 255).toByte(),
|
||||||
|
(tile and 255).toByte(),
|
||||||
|
((fill ushr 8) and 255).toByte(),
|
||||||
|
(fill and 255).toByte(), )
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
|
internal fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
|
||||||
val offset = getOffset(x, y)
|
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||||
val hbits = Float16.fromFloat(fill).toInt().and(0xFFFF)
|
val fill = Float16.fromFloat(fill).toUint()
|
||||||
|
chunkPool.setTileRaw(chunk, ox, oy, tile0.and(65535) or fill.shl(16))
|
||||||
val tile = if (fill < FLUID_MIN_MASS) 0 else tile0
|
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
val hlsb = hbits.and(0xff).toByte()
|
|
||||||
val hmsb = hbits.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
ptr[offset] = lsb
|
|
||||||
ptr[offset + 1] = msb
|
|
||||||
ptr[offset + 2] = hlsb
|
|
||||||
ptr[offset + 3] = hmsb
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||||
val offset = getOffset(x, y)
|
val tile = bytes[1].toUint().shl(8) or bytes[0].toUint()
|
||||||
ptr[offset] = bytes[1]
|
val fill = Float16.toFloat((bytes[3].toUint().shl(8) or bytes[2].toUint()).toShort())
|
||||||
ptr[offset + 1] = bytes[0]
|
unsafeSetTile(x, y, tile, fill)
|
||||||
ptr[offset + 2] = bytes[3]
|
|
||||||
ptr[offset + 3] = bytes[2]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,13 +104,14 @@ class BlockLayerFluidI16F16 : BlockLayer {
|
|||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
ptr.destroy()
|
chunkPool.dispose()
|
||||||
App.printdbg(this, "BlockLayerI16F16 with ptr ($ptr) successfully freed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = ptr.toString("BlockLayerI16F16")
|
override fun toString(): String = "BlockLayerI16F16 (${width}x$height)"
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient val BYTES_PER_BLOCK = 4L
|
@Transient val BYTES_PER_BLOCK = 4L
|
||||||
|
|
||||||
|
private fun Short.toUint() = this.toInt().and(65535)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class BlockLayerOresI16I8 : BlockLayer {
|
|||||||
this.width = width
|
this.width = width
|
||||||
this.height = height
|
this.height = height
|
||||||
|
|
||||||
chunkPool = ChunkPool(disk, layerNum, BlockLayerGenericI16.BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world))
|
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world))
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -47,95 +47,44 @@ class BlockLayerOresI16I8 : BlockLayer {
|
|||||||
this.width = width
|
this.width = width
|
||||||
this.height = height
|
this.height = height
|
||||||
|
|
||||||
chunkPool = ChunkPool(disk, layerNum, BlockLayerGenericI16.BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world))
|
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||||
|
|
||||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
|
||||||
|
|
||||||
val ptrDestroyed: Boolean
|
|
||||||
get() = ptr.destroyed
|
|
||||||
|
|
||||||
init {
|
|
||||||
ptr.fillWith(0) // there is no NOT-GENERATED for ores, keep it as 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an iterator over stored bytes.
|
|
||||||
*
|
|
||||||
* @return an Iterator.
|
|
||||||
*/
|
|
||||||
fun bytesIterator(): Iterator<Byte> {
|
|
||||||
return object : Iterator<Byte> {
|
|
||||||
private var iteratorCount = 0L
|
|
||||||
override fun hasNext(): Boolean {
|
|
||||||
return iteratorCount < width * height * bytesPerBlock
|
|
||||||
}
|
|
||||||
override fun next(): Byte {
|
|
||||||
iteratorCount += 1
|
|
||||||
return ptr[iteratorCount - 1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
val offset = getOffset(x, y)
|
return unsafeGetTile1(x, y).first
|
||||||
val lsb = ptr[offset]
|
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
val placement = ptr[offset + 2]
|
|
||||||
|
|
||||||
return lsb.toUint() + msb.toUint().shl(8)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Int> {
|
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Int> {
|
||||||
val offset = getOffset(x, y)
|
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||||
val lsb = ptr[offset]
|
return chunkPool.getTileI16I8(chunk, ox, oy)
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
val placement = ptr[offset + 2]
|
|
||||||
|
|
||||||
return lsb.toUint() or msb.toUint().shl(8) to placement.toUint()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
val offset = getOffset(x, y)
|
val (tile, fill) = unsafeGetTile1(x, y)
|
||||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 2])
|
return byteArrayOf(
|
||||||
|
((tile ushr 8) and 255).toByte(),
|
||||||
|
(tile and 255).toByte(),
|
||||||
|
(fill and 255).toByte()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
internal fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||||
val offset = getOffset(x, y)
|
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||||
|
chunkPool.setTileRaw(chunk, ox, oy, tile or placement.shl(16))
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
|
|
||||||
// try {
|
|
||||||
ptr[offset] = lsb
|
|
||||||
ptr[offset + 1] = msb
|
|
||||||
ptr[offset + 2] = placement.toByte()
|
|
||||||
// }
|
|
||||||
// catch (e: IndexOutOfBoundsException) {
|
|
||||||
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
|
|
||||||
// throw e
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||||
val offset = getOffset(x, y)
|
val tile = bytes[1].toUint().shl(8) or bytes[0].toUint()
|
||||||
ptr[offset] = bytes[1]
|
val placement = bytes[2].toUint()
|
||||||
ptr[offset + 1] = bytes[0]
|
unsafeSetTile(x, y, tile, placement)
|
||||||
ptr[offset + 2] = bytes[2]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun unsafeSetTileKeepPlacement(x: Int, y: Int, tile: Int) {
|
internal fun unsafeSetTileKeepPlacement(x: Int, y: Int, tile: Int) {
|
||||||
val offset = getOffset(x, y)
|
val oldPlacement = unsafeGetTile1(x, y).second
|
||||||
|
unsafeSetTile(x, y, tile, oldPlacement)
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
ptr[offset] = lsb
|
|
||||||
ptr[offset + 1] = msb
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,11 +103,10 @@ class BlockLayerOresI16I8 : BlockLayer {
|
|||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
ptr.destroy()
|
chunkPool.dispose()
|
||||||
App.printdbg(this, "BlockLayerI16I8 with ptr ($ptr) successfully freed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = ptr.toString("BlockLayerI16I8")
|
override fun toString(): String = "BlockLayerI16I8 (${width}x$height)"
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient val BYTES_PER_BLOCK = 3L
|
@Transient val BYTES_PER_BLOCK = 3L
|
||||||
|
|||||||
@@ -210,12 +210,17 @@ open class ChunkPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchFromDisk(chunkNumber: Long) {
|
/**
|
||||||
|
* @return `unit` if IO operation was successful, `null` if failed (e.g. file not exists)
|
||||||
|
*/
|
||||||
|
private fun fetchFromDisk(chunkNumber: Long): Unit? {
|
||||||
val fileName = chunkNumToFileNum(layerIndex, chunkNumber)
|
val fileName = chunkNumToFileNum(layerIndex, chunkNumber)
|
||||||
|
|
||||||
// read data from the disk
|
// read data from the disk
|
||||||
if (disk is ClusteredFormatDOM) {
|
return if (disk is ClusteredFormatDOM) {
|
||||||
Clustfile(disk, fileName).let {
|
Clustfile(disk, fileName).let {
|
||||||
|
if (!it.exists()) return@let null
|
||||||
|
|
||||||
val bytes = Common.unzip(it.readBytes())
|
val bytes = Common.unzip(it.readBytes())
|
||||||
val ptr = allocate(chunkNumber)
|
val ptr = allocate(chunkNumber)
|
||||||
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
||||||
@@ -224,13 +229,25 @@ open class ChunkPool {
|
|||||||
}
|
}
|
||||||
else if (disk is DiskSkimmer) {
|
else if (disk is DiskSkimmer) {
|
||||||
val fileID = fileName.toLong()
|
val fileID = fileName.toLong()
|
||||||
disk.getFile(fileID)!!.let {
|
disk.getFile(fileID).let {
|
||||||
|
if (it == null) return@let null
|
||||||
|
|
||||||
val bytes = Common.unzip(it.bytes)
|
val bytes = Common.unzip(it.bytes)
|
||||||
val ptr = allocate(chunkNumber)
|
val ptr = allocate(chunkNumber)
|
||||||
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
||||||
renumber(ptr)
|
renumber(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
throw IllegalStateException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return `unit` if IO operation was successful, `null` if failed (e.g. file not exists)
|
||||||
|
*/
|
||||||
|
private fun createNewChunkFile(chunkNumber: Long): Unit? {
|
||||||
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun storeToDisk(chunkNumber: Long) {
|
private fun storeToDisk(chunkNumber: Long) {
|
||||||
@@ -256,7 +273,7 @@ open class ChunkPool {
|
|||||||
|
|
||||||
private fun checkForChunk(chunkNumber: Long) {
|
private fun checkForChunk(chunkNumber: Long) {
|
||||||
if (!pointers.containsKey(chunkNumber)) {
|
if (!pointers.containsKey(chunkNumber)) {
|
||||||
fetchFromDisk(chunkNumber)
|
fetchFromDisk(chunkNumber) ?: createNewChunkFile(chunkNumber) ?: TODO("handle IO error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user