KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/world/ChunkPos.kt

175 lines
3.7 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package ru.dbotthepony.kstarbound.world
import ru.dbotthepony.kstarbound.math.roundByAbsoluteValue
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_BITS
import ru.dbotthepony.kvector.api.IStruct2d
import ru.dbotthepony.kvector.api.IStruct2i
import ru.dbotthepony.kvector.vector.Vector2i
private fun circulate(value: Int, bounds: Int): Int {
require(bounds > 0) { "Bounds must be positive ($bounds given)" }
if (value >= bounds) {
return value % bounds
} else if (value < 0) {
return bounds + value % bounds
}
return value
}
/**
* Сетка чанков идёт как и сетка тайлов.
*
* * Вправо у нас положительный X
* * Влево у нас отрицательный X
* * Вверх у нас положительный Y
* * Вниз у нас отрицательный Y
*/
class ChunkPos(val x: Int, val y: Int) : Comparable<ChunkPos> {
constructor(pos: IStruct2i) : this(pos.component1(), pos.component2())
val firstBlock get() = Vector2i(tileX, tileY)
val lastBlock get() = Vector2i(((x + 1) shl CHUNK_SIZE_BITS) - 1, ((y + 1) shl CHUNK_SIZE_BITS) - 1)
/**
* Координата тайла на 0 позиции по оси X внутри чанка в мире
*/
val tileX: Int get() = x shl CHUNK_SIZE_BITS
/**
* Координата тайла на 0 позиции по оси Y внутри чанка в мире
*/
val tileY: Int get() = y shl CHUNK_SIZE_BITS
val top: ChunkPos
get() {
return ChunkPos(x, y + 1)
}
val bottom: ChunkPos
get() {
return ChunkPos(x, y - 1)
}
val left: ChunkPos
get() {
return ChunkPos(x - 1, y)
}
val topLeft: ChunkPos
get() {
return ChunkPos(x - 1, y + 1)
}
val topRight: ChunkPos
get() {
return ChunkPos(x + 1, y + 1)
}
val bottomLeft: ChunkPos
get() {
return ChunkPos(x - 1, y - 1)
}
val bottomRight: ChunkPos
get() {
return ChunkPos(x + 1, y - 1)
}
val right: ChunkPos
get() {
return ChunkPos(x + 1, y)
}
override fun equals(other: Any?): Boolean {
if (other is ChunkPos)
return other.x == x && other.y == y
return false
}
override fun hashCode(): Int {
return (y shl 16) xor x
}
override fun toString(): String {
return "ChunkPos[$x $y]"
}
override fun compareTo(other: ChunkPos): Int {
if (x > other.x) {
return 1
} else if (x < other.x) {
return -1
}
return y.compareTo(other.y)
}
fun circular(xWrap: Int): ChunkPos {
val x = circulate(x, xWrap)
if (x == this.x) {
return this
}
return ChunkPos(x, y)
}
fun toLong(): Long {
return toLong(x, y)
}
companion object {
val ZERO = ChunkPos(0, 0)
fun toLong(x: Int, y: Int): Long {
return x.toLong() or (y.toLong() shl 32)
}
fun longFromPosition(x: Int, y: Int): Long {
return toLong(component(x), component(y))
}
fun fromPosition(input: IStruct2i): ChunkPos {
val (x, y) = input
return ChunkPos(component(x), component(y))
}
fun fromPosition(input: IStruct2d): ChunkPos {
val (x, y) = input
return fromPosition(x, y)
}
fun fromPosition(x: Int, y: Int): ChunkPos {
return ChunkPos(component(x), component(y))
}
fun fromPosition(x: Int, y: Int, xWrap: Int): ChunkPos {
return ChunkPos(circulate(component(x), xWrap), component(y))
}
fun fromPosition(x: Double, y: Double): ChunkPos {
return ChunkPos(
component(roundByAbsoluteValue(x)),
component(roundByAbsoluteValue(y))
)
}
fun fromPosition(x: Double, y: Double, xWrap: Int): ChunkPos {
return ChunkPos(
circulate(component(roundByAbsoluteValue(x)), xWrap),
component(roundByAbsoluteValue(y))
)
}
fun component(value: Int): Int {
if (value < 0) {
return -((-value) shr CHUNK_SIZE_BITS) - 1
}
return value shr CHUNK_SIZE_BITS
}
}
}