mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
setTile on ChunkPool
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}*/
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user