Улучшено дерево наследия чанков
This commit is contained in:
parent
76e5357b32
commit
3962eec095
@ -144,17 +144,17 @@ private fun loop() {
|
|||||||
var y = 0
|
var y = 0
|
||||||
|
|
||||||
for (tile in Starbound.tilesAccess.values) {
|
for (tile in Starbound.tilesAccess.values) {
|
||||||
chunk[x, y + 1] = tile
|
chunk.foreground[x, y + 1] = tile
|
||||||
chunk[x++, y] = tile
|
chunk.foreground[x++, y] = tile
|
||||||
chunk[x, y + 1] = tile
|
chunk.foreground[x, y + 1] = tile
|
||||||
chunk[x++, y] = tile
|
chunk.foreground[x++, y] = tile
|
||||||
chunk[x, y + 1] = tile
|
chunk.foreground[x, y + 1] = tile
|
||||||
chunk[x++, y] = tile
|
chunk.foreground[x++, y] = tile
|
||||||
chunk[x, y + 1] = tile
|
chunk.foreground[x, y + 1] = tile
|
||||||
chunk[x++, y] = tile
|
chunk.foreground[x++, y] = tile
|
||||||
chunk[x, y + 1] = tile
|
chunk.foreground[x, y + 1] = tile
|
||||||
chunk[x++, y] = tile
|
chunk.foreground[x++, y] = tile
|
||||||
chunk[x, y + 1] = tile
|
chunk.foreground[x, y + 1] = tile
|
||||||
|
|
||||||
if (x >= 32) {
|
if (x >= 32) {
|
||||||
x = 0
|
x = 0
|
||||||
|
@ -9,8 +9,7 @@ import org.apache.logging.log4j.LogManager
|
|||||||
import ru.dbotthepony.kstarbound.Starbound
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
import ru.dbotthepony.kstarbound.math.Vector2i
|
import ru.dbotthepony.kstarbound.math.Vector2i
|
||||||
import ru.dbotthepony.kstarbound.util.Color
|
import ru.dbotthepony.kstarbound.util.Color
|
||||||
import ru.dbotthepony.kstarbound.world.IChunk
|
import ru.dbotthepony.kstarbound.world.ITileGetter
|
||||||
import ru.dbotthepony.kstarbound.world.ITileAccess
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
data class TileDefinition(
|
data class TileDefinition(
|
||||||
@ -181,7 +180,7 @@ sealed class RenderRule(params: Map<String, Any>) {
|
|||||||
val matchHue = params["matchHue"] as? Boolean ?: false
|
val matchHue = params["matchHue"] as? Boolean ?: false
|
||||||
val inverse = params["inverse"] as? Boolean ?: false
|
val inverse = params["inverse"] as? Boolean ?: false
|
||||||
|
|
||||||
abstract fun test(getter: ITileAccess, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean
|
abstract fun test(getter: ITileGetter, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun factory(name: String, params: Map<String, Any>): RenderRule {
|
fun factory(name: String, params: Map<String, Any>): RenderRule {
|
||||||
@ -221,7 +220,7 @@ sealed class RenderRule(params: Map<String, Any>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class RenderRuleEqualsSelf(params: Map<String, Any>) : RenderRule(params) {
|
class RenderRuleEqualsSelf(params: Map<String, Any>) : RenderRule(params) {
|
||||||
override fun test(getter: ITileAccess, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
override fun test(getter: ITileGetter, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
||||||
val otherTile = getter[thisPos + offsetPos] ?: return inverse
|
val otherTile = getter[thisPos + offsetPos] ?: return inverse
|
||||||
|
|
||||||
if (inverse)
|
if (inverse)
|
||||||
@ -232,13 +231,13 @@ class RenderRuleEqualsSelf(params: Map<String, Any>) : RenderRule(params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class RenderRuleShadows(params: Map<String, Any>) : RenderRule(params) {
|
class RenderRuleShadows(params: Map<String, Any>) : RenderRule(params) {
|
||||||
override fun test(getter: ITileAccess, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
override fun test(getter: ITileGetter, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
||||||
return false // TODO
|
return false // TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RenderRuleConnects(params: Map<String, Any>) : RenderRule(params) {
|
class RenderRuleConnects(params: Map<String, Any>) : RenderRule(params) {
|
||||||
override fun test(getter: ITileAccess, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
override fun test(getter: ITileGetter, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
||||||
if (inverse)
|
if (inverse)
|
||||||
return getter[thisPos + offsetPos] == null
|
return getter[thisPos + offsetPos] == null
|
||||||
|
|
||||||
@ -247,13 +246,13 @@ class RenderRuleConnects(params: Map<String, Any>) : RenderRule(params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AlwaysPassingRenderRule(params: Map<String, Any>) : RenderRule(params) {
|
class AlwaysPassingRenderRule(params: Map<String, Any>) : RenderRule(params) {
|
||||||
override fun test(getter: ITileAccess, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
override fun test(getter: ITileGetter, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
||||||
return inverse
|
return inverse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AlwaysFailingRenderRule(params: Map<String, Any>) : RenderRule(params) {
|
class AlwaysFailingRenderRule(params: Map<String, Any>) : RenderRule(params) {
|
||||||
override fun test(getter: ITileAccess, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
override fun test(getter: ITileGetter, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
||||||
return !inverse
|
return !inverse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,7 +273,7 @@ data class TileRenderRule(
|
|||||||
val join: RenderRuleCombination,
|
val join: RenderRuleCombination,
|
||||||
val pieces: List<RenderRule>
|
val pieces: List<RenderRule>
|
||||||
) {
|
) {
|
||||||
fun test(getter: ITileAccess, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
fun test(getter: ITileGetter, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
||||||
if (join == RenderRuleCombination.ANY) {
|
if (join == RenderRuleCombination.ANY) {
|
||||||
for (piece in pieces) {
|
for (piece in pieces) {
|
||||||
if (piece.test(getter, thisRef, thisPos, offsetPos)) {
|
if (piece.test(getter, thisRef, thisPos, offsetPos)) {
|
||||||
@ -338,7 +337,7 @@ data class TileRenderMatchPositioned(
|
|||||||
/**
|
/**
|
||||||
* Состояние [condition] на [thisPos] с [offset]
|
* Состояние [condition] на [thisPos] с [offset]
|
||||||
*/
|
*/
|
||||||
fun test(getter: ITileAccess, thisRef: TileDefinition, thisPos: Vector2i): Boolean {
|
fun test(getter: ITileGetter, thisRef: TileDefinition, thisPos: Vector2i): Boolean {
|
||||||
return condition.test(getter, thisRef, thisPos, offset)
|
return condition.test(getter, thisRef, thisPos, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,7 +372,7 @@ data class TileRenderMatchPiece(
|
|||||||
*
|
*
|
||||||
* [subMatches] стоит итерировать только если это вернуло true
|
* [subMatches] стоит итерировать только если это вернуло true
|
||||||
*/
|
*/
|
||||||
fun test(getter: ITileAccess, thisRef: TileDefinition, thisPos: Vector2i): Boolean {
|
fun test(getter: ITileGetter, thisRef: TileDefinition, thisPos: Vector2i): Boolean {
|
||||||
for (matcher in matchAllPoints) {
|
for (matcher in matchAllPoints) {
|
||||||
if (!matcher.test(getter, thisRef, thisPos)) {
|
if (!matcher.test(getter, thisRef, thisPos)) {
|
||||||
return false
|
return false
|
||||||
|
@ -32,10 +32,10 @@ class ChunkRenderer(val state: GLStateTracker, val chunk: Chunk) : AutoCloseable
|
|||||||
layers.clear()
|
layers.clear()
|
||||||
|
|
||||||
// TODO: Синхронизация (ибо обновления игровой логики будут в потоке вне рендер потока)
|
// TODO: Синхронизация (ибо обновления игровой логики будут в потоке вне рендер потока)
|
||||||
for ((pos, tile) in chunk.posToTile) {
|
for ((pos, tile) in chunk.foreground.posToTile) {
|
||||||
if (tile != null) {
|
if (tile != null) {
|
||||||
val renderer = state.tileRenderers.get(tile.def.materialName)
|
val renderer = state.tileRenderers.get(tile.def.materialName)
|
||||||
renderer.tesselate(chunk, layers, pos)
|
renderer.tesselate(chunk.foreground, layers, pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ class ChunkRenderer(val state: GLStateTracker, val chunk: Chunk) : AutoCloseable
|
|||||||
unloadUnused()
|
unloadUnused()
|
||||||
|
|
||||||
// TODO: Синхронизация (ибо обновления игровой логики будут в потоке вне рендер потока)
|
// TODO: Синхронизация (ибо обновления игровой логики будут в потоке вне рендер потока)
|
||||||
for ((pos, tile) in chunk.posToTile) {
|
for ((pos, tile) in chunk.foreground.posToTile) {
|
||||||
if (tile != null) {
|
if (tile != null) {
|
||||||
state.tileRenderers.get(tile.def.materialName)
|
state.tileRenderers.get(tile.def.materialName)
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
package ru.dbotthepony.kstarbound.render
|
package ru.dbotthepony.kstarbound.render
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
import org.lwjgl.glfw.GLFW.glfwGetTime
|
|
||||||
import org.lwjgl.opengl.GL46.*
|
import org.lwjgl.opengl.GL46.*
|
||||||
import ru.dbotthepony.kstarbound.Starbound
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
import ru.dbotthepony.kstarbound.defs.TileDefinition
|
import ru.dbotthepony.kstarbound.defs.TileDefinition
|
||||||
import ru.dbotthepony.kstarbound.defs.TileRenderMatchPiece
|
import ru.dbotthepony.kstarbound.defs.TileRenderMatchPiece
|
||||||
import ru.dbotthepony.kstarbound.defs.TileRenderPiece
|
import ru.dbotthepony.kstarbound.defs.TileRenderPiece
|
||||||
import ru.dbotthepony.kstarbound.gl.*
|
import ru.dbotthepony.kstarbound.gl.*
|
||||||
import ru.dbotthepony.kstarbound.math.Matrix4f
|
|
||||||
import ru.dbotthepony.kstarbound.math.Vector2i
|
import ru.dbotthepony.kstarbound.math.Vector2i
|
||||||
import ru.dbotthepony.kstarbound.world.IChunk
|
import ru.dbotthepony.kstarbound.world.ITileChunk
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
data class TileLayer(
|
data class TileLayer(
|
||||||
@ -113,7 +111,7 @@ class TileRenderer(val state: GLStateTracker, val tile: TileDefinition) {
|
|||||||
val bakedProgramState = state.tileRenderers.simpleProgram(texture)
|
val bakedProgramState = state.tileRenderers.simpleProgram(texture)
|
||||||
// private var notifiedDepth = false
|
// private var notifiedDepth = false
|
||||||
|
|
||||||
private fun tesselateAt(piece: TileRenderPiece, getter: IChunk, builder: VertexBuilder, pos: Vector2i, offset: Vector2i = Vector2i.ZERO) {
|
private fun tesselateAt(piece: TileRenderPiece, getter: ITileChunk, builder: VertexBuilder, pos: Vector2i, offset: Vector2i = Vector2i.ZERO) {
|
||||||
val fx = pos.x.toFloat()
|
val fx = pos.x.toFloat()
|
||||||
val fy = pos.y.toFloat()
|
val fy = pos.y.toFloat()
|
||||||
|
|
||||||
@ -157,7 +155,7 @@ class TileRenderer(val state: GLStateTracker, val tile: TileDefinition) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tesselatePiece(matchPiece: TileRenderMatchPiece, getter: IChunk, layers: TileLayerList, pos: Vector2i, thisBuilder: VertexBuilder): TileRenderTesselateResult {
|
private fun tesselatePiece(matchPiece: TileRenderMatchPiece, getter: ITileChunk, layers: TileLayerList, pos: Vector2i, thisBuilder: VertexBuilder): TileRenderTesselateResult {
|
||||||
if (matchPiece.test(getter, tile, pos)) {
|
if (matchPiece.test(getter, tile, pos)) {
|
||||||
for (renderPiece in matchPiece.pieces) {
|
for (renderPiece in matchPiece.pieces) {
|
||||||
if (renderPiece.piece.texture != null) {
|
if (renderPiece.piece.texture != null) {
|
||||||
@ -196,7 +194,7 @@ class TileRenderer(val state: GLStateTracker, val tile: TileDefinition) {
|
|||||||
*
|
*
|
||||||
* Тесселирует тайлы в границы -1f .. CHUNK_SIZEf + 1f на основе [pos]
|
* Тесселирует тайлы в границы -1f .. CHUNK_SIZEf + 1f на основе [pos]
|
||||||
*/
|
*/
|
||||||
fun tesselate(getter: IChunk, layers: TileLayerList, pos: Vector2i) {
|
fun tesselate(getter: ITileChunk, layers: TileLayerList, pos: Vector2i) {
|
||||||
// если у нас нет renderTemplate
|
// если у нас нет renderTemplate
|
||||||
// то мы просто не можем его отрисовать
|
// то мы просто не можем его отрисовать
|
||||||
tile.render.renderTemplate ?: return
|
tile.render.renderTemplate ?: return
|
||||||
|
@ -3,12 +3,27 @@ package ru.dbotthepony.kstarbound.world
|
|||||||
import ru.dbotthepony.kstarbound.defs.TileDefinition
|
import ru.dbotthepony.kstarbound.defs.TileDefinition
|
||||||
import ru.dbotthepony.kstarbound.math.Vector2i
|
import ru.dbotthepony.kstarbound.math.Vector2i
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Представляет из себя класс, который содержит состояние тайла на заданной позиции
|
||||||
|
*/
|
||||||
data class ChunkTile(val def: TileDefinition) {
|
data class ChunkTile(val def: TileDefinition) {
|
||||||
var color = -1
|
var color = -1
|
||||||
var forceVariant = -1
|
var forceVariant = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ITileAccess {
|
interface ITileMap {
|
||||||
|
/**
|
||||||
|
* Относительная проверка находится ли координата вне границ чанка
|
||||||
|
*/
|
||||||
|
fun isOutside(x: Int, y: Int): Boolean {
|
||||||
|
return x !in 0 until CHUNK_SIZE || y !in 0 until CHUNK_SIZE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Предоставляет интерфейс для доступа к тайлам в чанке
|
||||||
|
*/
|
||||||
|
interface ITileGetter : ITileMap {
|
||||||
/**
|
/**
|
||||||
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||||
*/
|
*/
|
||||||
@ -18,35 +33,57 @@ interface ITileAccess {
|
|||||||
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||||
*/
|
*/
|
||||||
operator fun get(pos: Vector2i) = get(pos.x, pos.y)
|
operator fun get(pos: Vector2i) = get(pos.x, pos.y)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает итератор пар <Vector2i, Тайл?>
|
||||||
|
*
|
||||||
|
* Вектор имеет ОТНОСИТЕЛЬНЫЕ значения внутри самого чанка
|
||||||
|
*/
|
||||||
|
val posToTile: Iterator<Pair<Vector2i, ChunkTile?>> get() {
|
||||||
|
return object : Iterator<Pair<Vector2i, ChunkTile?>> {
|
||||||
|
private var x = 0
|
||||||
|
private var y = 0
|
||||||
|
|
||||||
|
private fun idx() = x + CHUNK_SIZE * y
|
||||||
|
|
||||||
|
override fun hasNext(): Boolean {
|
||||||
|
return idx() < CHUNK_SIZE * CHUNK_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun next(): Pair<Vector2i, ChunkTile?> {
|
||||||
|
if (!hasNext()) {
|
||||||
|
throw IllegalStateException("Already iterated everything!")
|
||||||
|
}
|
||||||
|
|
||||||
|
val tile = this@ITileGetter[x, y]
|
||||||
|
val pos = Vector2i(x, y)
|
||||||
|
|
||||||
|
x++
|
||||||
|
|
||||||
|
if (x >= CHUNK_SIZE) {
|
||||||
|
y++
|
||||||
|
x = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos to tile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IChunk : ITileAccess {
|
/**
|
||||||
|
* Интерфейс предоставляет из себя описание класса, который имеет координаты чанка
|
||||||
|
*/
|
||||||
|
interface IChunkPositionable : ITileMap {
|
||||||
val pos: ChunkPos
|
val pos: ChunkPos
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает фоновый тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
|
||||||
*/
|
|
||||||
fun getBackground(x: Int, y: Int): ChunkTile?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает фоновый тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
|
||||||
*/
|
|
||||||
fun getBackground(pos: Vector2i) = getBackground(pos.x, pos.y)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Относительная проверка находится ли координата вне границ чагка
|
|
||||||
*/
|
|
||||||
fun isOutside(x: Int, y: Int): Boolean {
|
|
||||||
return x !in 0 until CHUNK_SIZE || y !in 0 until CHUNK_SIZE
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Возвращает псевдослучайное Long для заданной позиции
|
* Возвращает псевдослучайное Long для заданной позиции
|
||||||
*
|
*
|
||||||
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
||||||
*/
|
*/
|
||||||
fun randomLongFor(x: Int, y: Int): Long {
|
fun randomLongFor(x: Int, y: Int): Long {
|
||||||
var long = x * 738548L + y * 2191293543L
|
var long = (x or (pos.x shl CHUNK_SHIFT)) * 738548L + (y or (pos.y shl CHUNK_SHIFT)) * 2191293543L
|
||||||
long = long xor 8339437585692L
|
long = long xor 8339437585692L
|
||||||
long = (long ushr 4) or (long shl 52)
|
long = (long ushr 4) or (long shl 52)
|
||||||
long *= 7848344324L
|
long *= 7848344324L
|
||||||
@ -76,45 +113,12 @@ interface IChunk : ITileAccess {
|
|||||||
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
||||||
*/
|
*/
|
||||||
fun randomDoubleFor(pos: Vector2i) = randomDoubleFor(pos.x, pos.y)
|
fun randomDoubleFor(pos: Vector2i) = randomDoubleFor(pos.x, pos.y)
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает итератор пар <Vector2i, Тайл?>
|
|
||||||
*
|
|
||||||
* Вектор имеет ОТНОСИТЕЛЬНЫЕ значения внутри самого чанка
|
|
||||||
*/
|
|
||||||
val posToTile: Iterator<Pair<Vector2i, ChunkTile?>> get() {
|
|
||||||
return object : Iterator<Pair<Vector2i, ChunkTile?>> {
|
|
||||||
private var x = 0
|
|
||||||
private var y = 0
|
|
||||||
|
|
||||||
private fun idx() = x + CHUNK_SIZE * y
|
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
|
||||||
return idx() < CHUNK_SIZE * CHUNK_SIZE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun next(): Pair<Vector2i, ChunkTile?> {
|
|
||||||
if (!hasNext()) {
|
|
||||||
throw IllegalStateException("Already iterated everything!")
|
|
||||||
}
|
|
||||||
|
|
||||||
val tile = this@IChunk[x, y]
|
|
||||||
val pos = Vector2i(x, y)
|
|
||||||
|
|
||||||
x++
|
|
||||||
|
|
||||||
if (x >= CHUNK_SIZE) {
|
|
||||||
y++
|
|
||||||
x = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos to tile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IChunkSetter {
|
/**
|
||||||
|
* Предоставляет интерфейс по установке тайлов в чанке
|
||||||
|
*/
|
||||||
|
interface ITileSetter : ITileMap {
|
||||||
/**
|
/**
|
||||||
* Устанавливает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
* Устанавливает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||||
*/
|
*/
|
||||||
@ -123,19 +127,11 @@ interface IChunkSetter {
|
|||||||
* Устанавливает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
* Устанавливает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||||
*/
|
*/
|
||||||
operator fun set(pos: Vector2i, tile: TileDefinition?) = set(pos.x, pos.y, tile)
|
operator fun set(pos: Vector2i, tile: TileDefinition?) = set(pos.x, pos.y, tile)
|
||||||
|
|
||||||
/**
|
|
||||||
* Устанавливает фоновый тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
|
||||||
*/
|
|
||||||
fun setBackground(x: Int, y: Int, tile: TileDefinition?): ChunkTile?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Устанавливает фоновый тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
|
||||||
*/
|
|
||||||
fun setBackground(pos: Vector2i, tile: TileDefinition?) = setBackground(pos.x, pos.y, tile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMutableChunk : IChunk, IChunkSetter
|
interface ITileGetterSetter : ITileGetter, ITileSetter
|
||||||
|
interface ITileChunk : ITileGetter, IChunkPositionable
|
||||||
|
interface IMutableTileChunk : ITileChunk, ITileSetter
|
||||||
|
|
||||||
const val CHUNK_SHIFT = 6
|
const val CHUNK_SHIFT = 6
|
||||||
const val CHUNK_SIZE = 1 shl CHUNK_SHIFT // 64
|
const val CHUNK_SIZE = 1 shl CHUNK_SHIFT // 64
|
||||||
@ -148,75 +144,53 @@ data class ChunkPos(val x: Int, val y: Int) {
|
|||||||
val lastBlock get() = Vector2i(((x + 1) shl CHUNK_SHIFT) - 1, ((y + 1) shl CHUNK_SHIFT) - 1)
|
val lastBlock get() = Vector2i(((x + 1) shl CHUNK_SHIFT) - 1, ((y + 1) shl CHUNK_SHIFT) - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
open class Chunk(val world: World, override val pos: ChunkPos) : IMutableChunk {
|
open class Chunk(val world: World, val pos: ChunkPos) {
|
||||||
/**
|
inner class ChunkTileLayer : IMutableTileChunk {
|
||||||
* Хранит тайлы как x + y * CHUNK_SIZE
|
override val pos: ChunkPos
|
||||||
*/
|
get() = this@Chunk.pos
|
||||||
private val tiles = arrayOfNulls<ChunkTile>(CHUNK_SIZE * CHUNK_SIZE)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Хранит фоновые тайлы как x + y * CHUNK_SIZE
|
* Хранит тайлы как x + y * CHUNK_SIZE
|
||||||
*/
|
*/
|
||||||
private val backgroundTiles = arrayOfNulls<ChunkTile>(CHUNK_SIZE * CHUNK_SIZE)
|
private val tiles = arrayOfNulls<ChunkTile>(CHUNK_SIZE * CHUNK_SIZE)
|
||||||
|
|
||||||
override operator fun get(x: Int, y: Int): ChunkTile? {
|
override operator fun get(x: Int, y: Int): ChunkTile? {
|
||||||
if (isOutside(x, y))
|
if (isOutside(x, y))
|
||||||
return null
|
return null
|
||||||
|
|
||||||
return tiles[x or (y shl CHUNK_SHIFT)]
|
return tiles[x or (y shl CHUNK_SHIFT)]
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(x: Int, y: Int, tile: ChunkTile?) {
|
||||||
|
if (isOutside(x, y))
|
||||||
|
throw IndexOutOfBoundsException("Trying to set tile ${tile?.def?.materialName} at $x $y, but that is outside of chunk's range")
|
||||||
|
|
||||||
|
tiles[x or (y shl CHUNK_SHIFT)] = tile
|
||||||
|
}
|
||||||
|
|
||||||
|
override operator fun set(x: Int, y: Int, tile: TileDefinition?): ChunkTile? {
|
||||||
|
if (isOutside(x, y))
|
||||||
|
throw IndexOutOfBoundsException("Trying to set tile ${tile?.materialName} at $x $y, but that is outside of chunk's range")
|
||||||
|
|
||||||
|
val chunkTile = if (tile != null) ChunkTile(tile) else null
|
||||||
|
this[x, y] = chunkTile
|
||||||
|
return chunkTile
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun randomLongFor(x: Int, y: Int): Long {
|
||||||
|
return super.randomLongFor(x, y) xor world.seed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected operator fun set(x: Int, y: Int, tile: ChunkTile?) {
|
val foreground = ChunkTileLayer()
|
||||||
if (isOutside(x, y))
|
val background = ChunkTileLayer()
|
||||||
throw IndexOutOfBoundsException("Trying to set tile ${tile?.def?.materialName} at $x $y, but that is outside of chunk's range")
|
|
||||||
|
|
||||||
tiles[x or (y shl CHUNK_SHIFT)] = tile
|
|
||||||
}
|
|
||||||
|
|
||||||
override operator fun set(x: Int, y: Int, tile: TileDefinition?): ChunkTile? {
|
|
||||||
if (isOutside(x, y))
|
|
||||||
throw IndexOutOfBoundsException("Trying to set tile ${tile?.materialName} at $x $y, but that is outside of chunk's range")
|
|
||||||
|
|
||||||
val chunkTile = if (tile != null) ChunkTile(tile) else null
|
|
||||||
this[x, y] = chunkTile
|
|
||||||
return chunkTile
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getBackground(x: Int, y: Int): ChunkTile? {
|
|
||||||
if (isOutside(x, y))
|
|
||||||
return null
|
|
||||||
|
|
||||||
return backgroundTiles[x or (y shl CHUNK_SHIFT)]
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun setBackground(x: Int, y: Int, tile: ChunkTile?) {
|
|
||||||
if (isOutside(x, y))
|
|
||||||
throw IndexOutOfBoundsException("Trying to set background tile ${tile?.def?.materialName} at $x $y, but that is outside of chunk's range")
|
|
||||||
|
|
||||||
backgroundTiles[x or (y shl CHUNK_SHIFT)] = tile
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setBackground(x: Int, y: Int, tile: TileDefinition?): ChunkTile? {
|
|
||||||
if (isOutside(x, y))
|
|
||||||
throw IndexOutOfBoundsException("Trying to set background tile ${tile?.materialName} at $x $y, but that is outside of chunk's range")
|
|
||||||
|
|
||||||
val chunkTile = if (tile != null) ChunkTile(tile) else null
|
|
||||||
setBackground(x, y, chunkTile)
|
|
||||||
return chunkTile
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun randomLongFor(x: Int, y: Int): Long {
|
|
||||||
return super.randomLongFor(x, y) xor world.seed
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val EMPTY = object : IMutableChunk {
|
val EMPTY = object : IMutableTileChunk {
|
||||||
override val pos = ChunkPos(0, 0)
|
override val pos = ChunkPos(0, 0)
|
||||||
|
|
||||||
override fun get(x: Int, y: Int): ChunkTile? = null
|
override fun get(x: Int, y: Int): ChunkTile? = null
|
||||||
override fun set(x: Int, y: Int, tile: TileDefinition?): ChunkTile? = null
|
override fun set(x: Int, y: Int, tile: TileDefinition?): ChunkTile? = null
|
||||||
override fun getBackground(x: Int, y: Int): ChunkTile? = null
|
|
||||||
override fun setBackground(x: Int, y: Int, tile: TileDefinition?): ChunkTile? = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,12 +43,22 @@ class World(val seed: Long = 0L) {
|
|||||||
fun getOrMakeChunk(pos: Vector2i) = getOrMakeChunk(ChunkPos(pos))
|
fun getOrMakeChunk(pos: Vector2i) = getOrMakeChunk(ChunkPos(pos))
|
||||||
|
|
||||||
fun getTile(pos: Vector2i): ChunkTile? {
|
fun getTile(pos: Vector2i): ChunkTile? {
|
||||||
return getChunk(pos)?.get(pos.x, pos.y)
|
return getChunk(pos)?.foreground?.get(pos.x, pos.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTile(pos: Vector2i, tile: TileDefinition?): Chunk {
|
fun setTile(pos: Vector2i, tile: TileDefinition?): Chunk {
|
||||||
val chunk = getOrMakeChunk(pos)
|
val chunk = getOrMakeChunk(pos)
|
||||||
chunk[pos.x and CHUNK_SIZE_FF, pos.y and CHUNK_SIZE_FF] = tile
|
chunk.foreground[pos.x and CHUNK_SIZE_FF, pos.y and CHUNK_SIZE_FF] = tile
|
||||||
|
return chunk
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBackgroundTile(pos: Vector2i): ChunkTile? {
|
||||||
|
return getChunk(pos)?.background?.get(pos.x, pos.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setBackgroundTile(pos: Vector2i, tile: TileDefinition?): Chunk {
|
||||||
|
val chunk = getOrMakeChunk(pos)
|
||||||
|
chunk.background[pos.x and CHUNK_SIZE_FF, pos.y and CHUNK_SIZE_FF] = tile
|
||||||
return chunk
|
return chunk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user