mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 10:34:06 +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)
|
return this.bytesPerBlock * (y * this.width + x)
|
||||||
}
|
}*/
|
||||||
@@ -61,70 +61,29 @@ class BlockLayerGenericI16: BlockLayer {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||||
val lsb = ptr[offset]
|
return chunkPool.getTileI16(chunk, ox, oy)
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
|
|
||||||
return lsb.toUint() or msb.toUint().shl(8)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
val offset = getOffset(x, y)
|
val bytes = unsafeGetTile(x, y)
|
||||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0])
|
return byteArrayOf(
|
||||||
|
((bytes ushr 8) and 255).toByte(),
|
||||||
|
(bytes and 255).toByte()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
internal fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||||
val offset = getOffset(x, y)
|
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||||
|
chunkPool.setTileRaw(chunk, ox, oy, tile)
|
||||||
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
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = (0..3).fold(0) { acc, i -> acc or (bytes[i].toUint()).shl(8*i) }
|
||||||
ptr[offset] = bytes[1]
|
unsafeSetTile(x, y, tile)
|
||||||
ptr[offset + 1] = bytes[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,11 +102,10 @@ class BlockLayerGenericI16: 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()
|
||||||
printdbg(this, "BlockLayerI16 with ptr ($ptr) successfully freed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = ptr.toString("BlockLayerI16")
|
override fun toString(): String = "BlockLayerI16 (${width}x$height)"
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient val BYTES_PER_BLOCK = 2L
|
@Transient val BYTES_PER_BLOCK = 2L
|
||||||
|
|||||||
@@ -103,6 +103,9 @@ open class ChunkPool {
|
|||||||
return UnsafePtr(baseAddr, chunkSize)
|
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> {
|
private fun createPointerViewOfChunk(chunkNumber: Long, offsetX: Int, offsetY: Int): Pair<UnsafePtr, Long> {
|
||||||
val baseAddr = pointers[chunkNumber]!!
|
val baseAddr = pointers[chunkNumber]!!
|
||||||
return UnsafePtr(baseAddr, chunkSize) to wordSizeInBytes * (offsetY * CHUNK_W + offsetX)
|
return UnsafePtr(baseAddr, chunkSize) to wordSizeInBytes * (offsetY * CHUNK_W + offsetX)
|
||||||
@@ -264,6 +267,19 @@ open class ChunkPool {
|
|||||||
return out
|
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, ...]`,
|
* 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 {
|
fun getTileRaw(chunkNumber: Long, offX: Int, offY: Int): Int {
|
||||||
checkForChunk(chunkNumber)
|
checkForChunk(chunkNumber)
|
||||||
allocMap.find { it?.chunkNumber == chunkNumber }!!.let { it.lastAccessTime = System.nanoTime() }
|
updateAccessTime(chunkNumber)
|
||||||
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
|
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
|
||||||
val numIn = (0 until wordSizeInBytes.toInt()).fold(0) { acc, off ->
|
val numIn = (0 until wordSizeInBytes.toInt()).fold(0) { acc, off ->
|
||||||
acc or (ptr[ptrOff].toUint().shl(8 * off))
|
acc or (ptr[ptrOff].toUint().shl(8 * off))
|
||||||
@@ -282,6 +298,23 @@ open class ChunkPool {
|
|||||||
return numIn
|
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, ...]`,
|
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
|
||||||
* Return format:
|
* Return format:
|
||||||
@@ -319,6 +352,10 @@ open class ChunkPool {
|
|||||||
return ibits to jbits
|
return ibits to jbits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun chunkNumToFileNum(layerNum: Int, chunkNum: Long): String {
|
fun chunkNumToFileNum(layerNum: Int, chunkNum: Long): String {
|
||||||
val entryID = Common.layerAndChunkNumToEntryID(layerNum, chunkNum)
|
val entryID = Common.layerAndChunkNumToEntryID(layerNum, chunkNum)
|
||||||
|
|||||||
Reference in New Issue
Block a user