setTile on ChunkPool

This commit is contained in:
minjaesong
2024-10-22 22:49:47 +09:00
parent 39cfc3a4d9
commit 83906e7930
3 changed files with 53 additions and 58 deletions

View File

@@ -16,6 +16,6 @@ abstract class BlockLayer : Disposable {
}
inline fun BlockLayer.getOffset(x: Int, y: Int): Long {
/*inline fun BlockLayer.getOffset(x: Int, y: Int): Long {
return this.bytesPerBlock * (y * this.width + x)
}
}*/

View File

@@ -61,70 +61,29 @@ class BlockLayerGenericI16: BlockLayer {
})
}
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 {
val offset = getOffset(x, y)
val lsb = ptr[offset]
val msb = ptr[offset + 1]
return lsb.toUint() or msb.toUint().shl(8)
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
return chunkPool.getTileI16(chunk, ox, oy)
}
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
val offset = getOffset(x, y)
return byteArrayOf(ptr[offset + 1], ptr[offset + 0])
val bytes = unsafeGetTile(x, y)
return byteArrayOf(
((bytes ushr 8) and 255).toByte(),
(bytes and 255).toByte()
)
}
internal fun unsafeSetTile(x: Int, y: Int, tile: Int) {
val offset = getOffset(x, y)
val lsb = tile.and(0xff).toByte()
val msb = tile.ushr(8).and(0xff).toByte()
// try {
ptr[offset] = lsb
ptr[offset + 1] = msb
// }
// catch (e: IndexOutOfBoundsException) {
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
// throw e
// }
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
chunkPool.setTileRaw(chunk, ox, oy, tile)
}
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
val offset = getOffset(x, y)
ptr[offset] = bytes[1]
ptr[offset + 1] = bytes[0]
val tile = (0..3).fold(0) { acc, i -> acc or (bytes[i].toUint()).shl(8*i) }
unsafeSetTile(x, y, tile)
}
/**
@@ -143,11 +102,10 @@ class BlockLayerGenericI16: BlockLayer {
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
override fun dispose() {
ptr.destroy()
printdbg(this, "BlockLayerI16 with ptr ($ptr) successfully freed")
chunkPool.dispose()
}
override fun toString(): String = ptr.toString("BlockLayerI16")
override fun toString(): String = "BlockLayerI16 (${width}x$height)"
companion object {
@Transient val BYTES_PER_BLOCK = 2L

View File

@@ -103,6 +103,9 @@ open class ChunkPool {
return UnsafePtr(baseAddr, chunkSize)
}
/**
* Returns a pointer and the offset from the pointer. The offset is given in bytes, but always word-aligned (if block offset is `(2, 0)`, the returning offset will be `8`, assuming word size of 4)
*/
private fun createPointerViewOfChunk(chunkNumber: Long, offsetX: Int, offsetY: Int): Pair<UnsafePtr, Long> {
val baseAddr = pointers[chunkNumber]!!
return UnsafePtr(baseAddr, chunkSize) to wordSizeInBytes * (offsetY * CHUNK_W + offsetX)
@@ -264,6 +267,19 @@ open class ChunkPool {
return out
}
fun worldXYChunkNumAndOffset(worldx: Int, worldy: Int): Triple<Long, Int, Int> {
val chunkX = worldx / CHUNK_W
val chunkY = worldy / CHUNK_H
val chunkOx = worldx % CHUNK_W
val chunkOy = worldy % CHUNK_H
val chunkNum = LandUtil.chunkXYtoChunkNum(world, chunkX, chunkY)
return Triple(chunkNum, chunkOx, chunkOy)
}
private fun updateAccessTime(chunkNumber: Long) {
allocMap.find { it?.chunkNumber == chunkNumber }!!.let { it.lastAccessTime = System.nanoTime() }
}
/**
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
@@ -274,7 +290,7 @@ open class ChunkPool {
*/
fun getTileRaw(chunkNumber: Long, offX: Int, offY: Int): Int {
checkForChunk(chunkNumber)
allocMap.find { it?.chunkNumber == chunkNumber }!!.let { it.lastAccessTime = System.nanoTime() }
updateAccessTime(chunkNumber)
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
val numIn = (0 until wordSizeInBytes.toInt()).fold(0) { acc, off ->
acc or (ptr[ptrOff].toUint().shl(8 * off))
@@ -282,6 +298,23 @@ open class ChunkPool {
return numIn
}
/**
* Given the bytes of Int `B3_B2_B1_B0`
* Saved as:
* - word size is 4: `[B0, B1, B2, B3]`
* - word size is 3: `[B0, B1, B2]` (B3 is ignored)
* - word size is 2: `[B0, B1]` (B2 and B3 are ignored)
*/
fun setTileRaw(chunkNumber: Long, offX: Int, offY: Int, bytes: Int) {
checkForChunk(chunkNumber)
updateAccessTime(chunkNumber)
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
for (i in 0 until wordSizeInBytes.toInt()) {
val b = bytes.ushr(8*i).and(255)
ptr[ptrOff + i] = b.toByte()
}
}
/**
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
* Return format:
@@ -319,6 +352,10 @@ open class ChunkPool {
return ibits to jbits
}
fun dispose() {
}
companion object {
fun chunkNumToFileNum(layerNum: Int, chunkNum: Long): String {
val entryID = Common.layerAndChunkNumToEntryID(layerNum, chunkNum)