Кеш GLShaderProgram, загрузка матриц напрямую в видеопамять,
дополнения TileDef
This commit is contained in:
parent
5953f033f3
commit
f0af2d5a8e
@ -138,48 +138,27 @@ private fun loop() {
|
||||
state.blend = true
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
val rock = ChunkTile(Starbound.getTileDefinition("alienrock")!!)
|
||||
val obsidian = ChunkTile(Starbound.getTileDefinition("obsidian")!!)
|
||||
val corruptdirt = ChunkTile(Starbound.getTileDefinition("corruptdirt")!!)
|
||||
val darkwood = ChunkTile(Starbound.getTileDefinition("darkwood")!!)
|
||||
val chunk = Starbound.world.setTile(Vector2i(2, 2), rock)
|
||||
|
||||
chunk[3, 2] = rock
|
||||
chunk[4, 2] = rock
|
||||
chunk[4, 3] = rock
|
||||
chunk[4, 4] = rock
|
||||
chunk[3, 4] = rock
|
||||
chunk[5, 4] = rock
|
||||
chunk[2, 4] = obsidian
|
||||
chunk[2, 3] = obsidian
|
||||
chunk[1, 4] = corruptdirt
|
||||
chunk[1, 3] = corruptdirt
|
||||
chunk[1, 5] = darkwood
|
||||
chunk[2, 5] = darkwood
|
||||
chunk[3, 5] = darkwood
|
||||
chunk[1, 1] = darkwood
|
||||
chunk[2, 1] = darkwood
|
||||
chunk[3, 1] = darkwood
|
||||
|
||||
for (x in 0 until 1) {
|
||||
for (y in 0 until 4) {
|
||||
//chunk[x, y] = ChunkTile(Starbound.loadTileDefinition("alienrock"))
|
||||
}
|
||||
}
|
||||
val chunk = Starbound.world.getOrMakeChunk(Vector2i(2, 2))
|
||||
|
||||
var x = 0
|
||||
var y = 0
|
||||
|
||||
for (tile in Starbound.tilesAccess.values) {
|
||||
chunk[x++, y] = ChunkTile(tile)
|
||||
chunk[x++, y] = ChunkTile(tile)
|
||||
chunk[x++, y] = ChunkTile(tile)
|
||||
chunk[x++, y] = ChunkTile(tile)
|
||||
chunk[x++, y] = ChunkTile(tile)
|
||||
chunk[x, y + 1] = (tile)
|
||||
chunk[x++, y] = (tile)
|
||||
chunk[x, y + 1] = (tile)
|
||||
chunk[x++, y] = (tile)
|
||||
chunk[x, y + 1] = (tile)
|
||||
chunk[x++, y] = (tile)
|
||||
chunk[x, y + 1] = (tile)
|
||||
chunk[x++, y] = (tile)
|
||||
chunk[x, y + 1] = (tile)
|
||||
chunk[x++, y] = (tile)
|
||||
chunk[x, y + 1] = (tile)
|
||||
|
||||
if (x >= 24) {
|
||||
if (x >= 32) {
|
||||
x = 0
|
||||
y++
|
||||
y += 2
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,37 +173,8 @@ private fun loop() {
|
||||
|
||||
state.matrixStack.clear(viewportMatrixGame.toMutableMatrix())
|
||||
|
||||
// program.use()
|
||||
|
||||
// val time = glfwGetTime()
|
||||
// program["globalColor"] = Uniform3f(sin(time).toFloat(), cos(time).toFloat(), sin(time).toFloat())
|
||||
// program["ourTexture"] = 0
|
||||
|
||||
// texture.bind()
|
||||
// vao.bind()
|
||||
// ebo.bind()
|
||||
// glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
|
||||
// checkForGLError()
|
||||
|
||||
//tileRenderer.renderPiece()
|
||||
|
||||
//state.shaderVertexTexture.use()
|
||||
//state.shaderVertexTexture["_texture"] = 0
|
||||
////state.shaderVertexTexture["_transform"] = Vector3f.FORWARD.rotateAroundThis(PI * glfwGetTime())
|
||||
////state.shaderVertexTexture["_transform"] = state.matrixStack.push().scale((glfwGetTime() % 1000.0).toFloat(), (glfwGetTime() % 1000.0).toFloat(), (glfwGetTime() % 1000.0).toFloat()).last
|
||||
////state.shaderVertexTexture["_transform"] = Matrix4f.perspective(((glfwGetTime() * 16.0) % 180.0).toFloat(), 0.1f, 100f)
|
||||
//state.shaderVertexTexture["_transform"] = state.matrixStack.push().scale(x = 10f, y = 10f).translateWithScale(10f, 10f).last
|
||||
//texture.bind()
|
||||
//texture.textureMinFilter = GL_NEAREST
|
||||
//texture.textureMagFilter = GL_NEAREST
|
||||
//chunkRenderer.bind()
|
||||
//glDrawElements(GL_TRIANGLES, chunkRenderer.indexCount, GL_UNSIGNED_INT, 0)
|
||||
//checkForGLError()
|
||||
|
||||
state.matrixStack.push().scale(x = 20f, y = 20f).translateWithScale(0f, 0f)
|
||||
chunkRenderer.render()
|
||||
//state.matrixStack.translateWithScale(18f)
|
||||
//chunkRenderer.render()
|
||||
|
||||
glfwSwapBuffers(window) // swap the color buffers
|
||||
|
||||
|
@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableMap
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
import ru.dbotthepony.kstarbound.math.Vector2i
|
||||
import ru.dbotthepony.kstarbound.util.Color
|
||||
@ -18,6 +19,9 @@ data class TileDefinition(
|
||||
val itemDrop: String?,
|
||||
val description: String,
|
||||
val shortdescription: String,
|
||||
val blocksLiquidFlow: Boolean,
|
||||
val soil: Boolean,
|
||||
val tillableMod: Int,
|
||||
|
||||
val racialDescription: ImmutableMap<String, String>,
|
||||
val footstepSound: String?,
|
||||
@ -40,6 +44,10 @@ class TileDefinitionBuilder {
|
||||
var description = "..."
|
||||
var shortdescription = "..."
|
||||
|
||||
var blocksLiquidFlow = true
|
||||
var soil = false
|
||||
var tillableMod = 0
|
||||
|
||||
val racialDescription = ArrayList<Pair<String, String>>()
|
||||
|
||||
var footstepSound: String? = null
|
||||
@ -62,6 +70,9 @@ class TileDefinitionBuilder {
|
||||
itemDrop = itemDrop,
|
||||
description = description,
|
||||
shortdescription = shortdescription,
|
||||
blocksLiquidFlow = blocksLiquidFlow,
|
||||
soil = soil,
|
||||
tillableMod = tillableMod,
|
||||
|
||||
footstepSound = footstepSound,
|
||||
health = health,
|
||||
@ -72,6 +83,8 @@ class TileDefinitionBuilder {
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
|
||||
fun fromJson(input: JsonObject): TileDefinitionBuilder {
|
||||
val builder = TileDefinitionBuilder()
|
||||
|
||||
@ -83,12 +96,19 @@ class TileDefinitionBuilder {
|
||||
|
||||
builder.particleColor = Color(input["particleColor"].asJsonArray)
|
||||
builder.itemDrop = input["itemDrop"]?.asString
|
||||
builder.description = input["description"]?.asString ?: "..."
|
||||
builder.shortdescription = input["shortdescription"]?.asString ?: "..."
|
||||
builder.description = input["description"]?.asString ?: builder.description
|
||||
builder.shortdescription = input["shortdescription"]?.asString ?: builder.shortdescription
|
||||
builder.footstepSound = input["footstepSound"]?.asString
|
||||
builder.blocksLiquidFlow = input["footstepSound"]?.asBoolean ?: builder.blocksLiquidFlow
|
||||
builder.soil = input["footstepSound"]?.asBoolean ?: builder.soil
|
||||
builder.health = input["health"].asInt
|
||||
builder.tillableMod = input["health"]?.asInt ?: builder.tillableMod
|
||||
builder.category = input["category"].asString
|
||||
|
||||
if (input["variants"] != null) {
|
||||
LOGGER.warn("Tile {} has `variants` ({}) defined as top level property (expected to be under `renderParameters`)", builder.materialName, input["variants"].asString)
|
||||
}
|
||||
|
||||
for (key in input.keySet()) {
|
||||
if (key.endsWith("Description") && key.length != "Description".length) {
|
||||
builder.racialDescription.add(key.substring(0, key.length - "Description".length) to input[key].asString)
|
||||
@ -98,9 +118,9 @@ class TileDefinitionBuilder {
|
||||
input["renderParameters"]?.asJsonObject?.let {
|
||||
builder.render.texture = it["texture"].asString
|
||||
builder.render.variants = it["variants"].asInt
|
||||
builder.render.lightTransparent = it["lightTransparent"]?.asBoolean ?: false
|
||||
builder.render.occludesBelow = it["occludesBelow"]?.asBoolean ?: true
|
||||
builder.render.multiColored = it["multiColored"]?.asBoolean ?: false
|
||||
builder.render.lightTransparent = it["lightTransparent"]?.asBoolean ?: builder.render.lightTransparent
|
||||
builder.render.occludesBelow = it["occludesBelow"]?.asBoolean ?: builder.render.occludesBelow
|
||||
builder.render.multiColored = it["multiColored"]?.asBoolean ?: builder.render.multiColored
|
||||
builder.render.zLevel = it["zLevel"].asInt
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,16 @@
|
||||
package ru.dbotthepony.kstarbound.gl
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||
import org.lwjgl.opengl.GL41
|
||||
import org.lwjgl.opengl.GL46.*
|
||||
import ru.dbotthepony.kstarbound.api.IStruct3f
|
||||
import ru.dbotthepony.kstarbound.api.IStruct4F
|
||||
import ru.dbotthepony.kstarbound.math.AbstractMatrix3f
|
||||
import ru.dbotthepony.kstarbound.math.AbstractMatrix4f
|
||||
import ru.dbotthepony.kstarbound.math.FloatMatrix
|
||||
import java.util.*
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
class ShaderLinkException(reason: String) : RuntimeException(reason)
|
||||
|
||||
@ -37,11 +43,21 @@ class GLUniformLocation(val program: GLShaderProgram, val name: String, val poin
|
||||
|
||||
if (value.rows == 3 && value.columns == 3) {
|
||||
// Матрица 3x3
|
||||
glProgramUniformMatrix3fv(program.pointer, pointer, false, value.toFloatArray())
|
||||
if (value is AbstractMatrix3f) {
|
||||
glProgramUniformMatrix3fv(program.pointer, pointer, false, value.toFloatBuffer())
|
||||
} else {
|
||||
glProgramUniformMatrix3fv(program.pointer, pointer, false, value.toFloatArray())
|
||||
}
|
||||
|
||||
checkForGLError()
|
||||
} else if (value.rows == 4 && value.columns == 4) {
|
||||
// Матрица 4x4
|
||||
glProgramUniformMatrix4fv(program.pointer, pointer, false, value.toFloatArray())
|
||||
if (value is AbstractMatrix4f) {
|
||||
glProgramUniformMatrix4fv(program.pointer, pointer, false, value.toFloatBuffer())
|
||||
} else {
|
||||
glProgramUniformMatrix4fv(program.pointer, pointer, false, value.toFloatArray())
|
||||
}
|
||||
|
||||
checkForGLError()
|
||||
} else {
|
||||
throw IllegalArgumentException("Can not use matrix with these dimensions: ${value.rows}x${value.columns}")
|
||||
@ -59,16 +75,28 @@ class GLShaderProgram(val state: GLStateTracker, vararg shaders: GLShader) {
|
||||
private val attached = HashSet<GLShader>()
|
||||
val access = object : Collection<GLShader> by attached {}
|
||||
|
||||
private val locationCache = Object2ObjectArrayMap<String, Optional<GLUniformLocation>>()
|
||||
|
||||
/**
|
||||
* Возвращает GLUniformLocation или null, если у данной программы нет такого uniform
|
||||
*
|
||||
* В т.ч. если она была в коде шейдера, но нигде не использовалась (отсечена компилятором)
|
||||
*
|
||||
* Результат поиска кешируется, но для повышения производительности вызывающий код желательно так же
|
||||
* должен кешировать результат (как локальное свойство или переменная, в случае многократного использования)
|
||||
*/
|
||||
operator fun get(name: String): GLUniformLocation? {
|
||||
state.ensureSameThread()
|
||||
check(linked) { "Shader program is not linked!" }
|
||||
|
||||
val location = glGetUniformLocation(pointer, name)
|
||||
return locationCache.computeIfAbsent(name, Object2ObjectFunction {
|
||||
val location = glGetUniformLocation(pointer, name)
|
||||
|
||||
if (location == -1)
|
||||
return null
|
||||
if (location == -1)
|
||||
return@Object2ObjectFunction Optional.empty<GLUniformLocation>()
|
||||
|
||||
return GLUniformLocation(this, name, location)
|
||||
return@Object2ObjectFunction Optional.of(GLUniformLocation(this, name, location))
|
||||
}).orElse(null)
|
||||
}
|
||||
|
||||
operator fun set(name: String, value: Uniform4f) = this[name]?.set(value)
|
||||
|
@ -1,5 +1,8 @@
|
||||
package ru.dbotthepony.kstarbound.math
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.nio.FloatBuffer
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.tan
|
||||
|
||||
@ -74,6 +77,68 @@ interface MutableFloatMatrix<T : MutableFloatMatrix<T>> : FloatMatrix<T> {
|
||||
}
|
||||
|
||||
abstract class AbstractMatrix4f<T : AbstractMatrix4f<T>> : FloatMatrix<T> {
|
||||
companion object {
|
||||
private val directBuffer by lazy { ByteBuffer.allocateDirect(4 * 4 * 4).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer()!! }
|
||||
}
|
||||
|
||||
/**
|
||||
* Наполняет синглтон и возвращает DirectFloatBuffer который необходимо использовать сразу,
|
||||
* нет никаких гарантий что он не будет изменён в дальнейшем
|
||||
*
|
||||
* Функция предназначена исключительно для загрузки данной матрицы в память видеокарты
|
||||
*
|
||||
* Данный буфер всегда будет одним и тем же, но его содержимое обновлено
|
||||
*/
|
||||
fun toFloatBuffer(columnMajor: Boolean = true): FloatBuffer {
|
||||
val directBuffer = directBuffer
|
||||
directBuffer.position(0)
|
||||
|
||||
if (columnMajor) {
|
||||
directBuffer.put(m00)
|
||||
directBuffer.put(m10)
|
||||
directBuffer.put(m20)
|
||||
directBuffer.put(m30)
|
||||
|
||||
directBuffer.put(m01)
|
||||
directBuffer.put(m11)
|
||||
directBuffer.put(m21)
|
||||
directBuffer.put(m31)
|
||||
|
||||
directBuffer.put(m02)
|
||||
directBuffer.put(m12)
|
||||
directBuffer.put(m22)
|
||||
directBuffer.put(m32)
|
||||
|
||||
directBuffer.put(m03)
|
||||
directBuffer.put(m13)
|
||||
directBuffer.put(m23)
|
||||
directBuffer.put(m33)
|
||||
} else {
|
||||
directBuffer.put(m00)
|
||||
directBuffer.put(m01)
|
||||
directBuffer.put(m02)
|
||||
directBuffer.put(m03)
|
||||
|
||||
directBuffer.put(m10)
|
||||
directBuffer.put(m11)
|
||||
directBuffer.put(m12)
|
||||
directBuffer.put(m13)
|
||||
|
||||
directBuffer.put(m20)
|
||||
directBuffer.put(m21)
|
||||
directBuffer.put(m22)
|
||||
directBuffer.put(m23)
|
||||
|
||||
directBuffer.put(m30)
|
||||
directBuffer.put(m31)
|
||||
directBuffer.put(m32)
|
||||
directBuffer.put(m33)
|
||||
}
|
||||
|
||||
directBuffer.position(0)
|
||||
return directBuffer
|
||||
}
|
||||
|
||||
abstract val m00: Float; abstract val m01: Float; abstract val m02: Float; abstract val m03: Float
|
||||
abstract val m10: Float; abstract val m11: Float; abstract val m12: Float; abstract val m13: Float
|
||||
abstract val m20: Float; abstract val m21: Float; abstract val m22: Float; abstract val m23: Float
|
||||
@ -545,6 +610,52 @@ data class MutableMatrix4f(
|
||||
}
|
||||
|
||||
abstract class AbstractMatrix3f<T : AbstractMatrix3f<T>> : FloatMatrix<T> {
|
||||
companion object {
|
||||
private val directBuffer by lazy { ByteBuffer.allocateDirect(4 * 3 * 3).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer()!! }
|
||||
}
|
||||
|
||||
/**
|
||||
* Наполняет синглтон и возвращает DirectFloatBuffer который необходимо использовать сразу,
|
||||
* нет никаких гарантий что он не будет изменён в дальнейшем
|
||||
*
|
||||
* Функция предназначена исключительно для загрузки данной матрицы в память видеокарты
|
||||
*
|
||||
* Данный буфер всегда будет одним и тем же, но его содержимое обновлено
|
||||
*/
|
||||
fun toFloatBuffer(columnMajor: Boolean = true): FloatBuffer {
|
||||
val directBuffer = directBuffer
|
||||
directBuffer.position(0)
|
||||
|
||||
if (columnMajor) {
|
||||
directBuffer.put(m00)
|
||||
directBuffer.put(m10)
|
||||
directBuffer.put(m20)
|
||||
|
||||
directBuffer.put(m01)
|
||||
directBuffer.put(m11)
|
||||
directBuffer.put(m21)
|
||||
|
||||
directBuffer.put(m02)
|
||||
directBuffer.put(m12)
|
||||
directBuffer.put(m22)
|
||||
} else {
|
||||
directBuffer.put(m00)
|
||||
directBuffer.put(m01)
|
||||
directBuffer.put(m02)
|
||||
|
||||
directBuffer.put(m10)
|
||||
directBuffer.put(m11)
|
||||
directBuffer.put(m12)
|
||||
|
||||
directBuffer.put(m20)
|
||||
directBuffer.put(m21)
|
||||
directBuffer.put(m22)
|
||||
}
|
||||
|
||||
directBuffer.position(0)
|
||||
return directBuffer
|
||||
}
|
||||
|
||||
abstract val m00: Float; abstract val m01: Float; abstract val m02: Float
|
||||
abstract val m10: Float; abstract val m11: Float; abstract val m12: Float
|
||||
abstract val m20: Float; abstract val m21: Float; abstract val m22: Float
|
||||
|
@ -1,12 +1,11 @@
|
||||
package ru.dbotthepony.kstarbound.world
|
||||
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
import ru.dbotthepony.kstarbound.defs.TileDefinition
|
||||
import ru.dbotthepony.kstarbound.math.Vector2i
|
||||
|
||||
data class ChunkTile(val def: TileDefinition) {
|
||||
companion object {
|
||||
}
|
||||
var color = -1
|
||||
var forceVariant = -1
|
||||
}
|
||||
|
||||
interface IChunk {
|
||||
@ -16,8 +15,23 @@ interface IChunk {
|
||||
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||
*/
|
||||
operator fun get(x: Int, y: Int): ChunkTile?
|
||||
|
||||
/**
|
||||
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||
*/
|
||||
operator fun get(pos: Vector2i) = get(pos.x, pos.y)
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает фоновый тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||
*/
|
||||
fun getBackground(x: Int, y: Int): ChunkTile?
|
||||
|
||||
/**
|
||||
* Возвращает фоновый тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||
*/
|
||||
fun getBackground(pos: Vector2i) = getBackground(pos.x, pos.y)
|
||||
|
||||
/**
|
||||
* Относительная проверка находится ли координата вне границ чагка
|
||||
*/
|
||||
@ -39,7 +53,6 @@ interface IChunk {
|
||||
return long
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает псевдослучайное нормализированное Double для заданной позиции
|
||||
*
|
||||
@ -49,7 +62,6 @@ interface IChunk {
|
||||
return (randomLongFor(x, y) / 9.223372036854776E18) / 2.0 + 0.5
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает псевдослучайное Long для заданной позиции
|
||||
*
|
||||
@ -105,7 +117,21 @@ interface IChunkSetter {
|
||||
/**
|
||||
* Устанавливает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||
*/
|
||||
operator fun set(x: Int, y: Int, tile: ChunkTile?)
|
||||
operator fun set(x: Int, y: Int, tile: TileDefinition?): ChunkTile?
|
||||
/**
|
||||
* Устанавливает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||
*/
|
||||
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
|
||||
@ -121,11 +147,16 @@ 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)
|
||||
}
|
||||
|
||||
class Chunk(val world: World, override val pos: ChunkPos) : IMutableChunk {
|
||||
open class Chunk(val world: World, override val pos: ChunkPos) : IMutableChunk {
|
||||
/**
|
||||
* Хранит тайлы как x + y * CHUNK_SIZE
|
||||
*/
|
||||
val tiles = arrayOfNulls<ChunkTile>(CHUNK_SIZE * CHUNK_SIZE)
|
||||
private val tiles = arrayOfNulls<ChunkTile>(CHUNK_SIZE * CHUNK_SIZE)
|
||||
|
||||
/**
|
||||
* Хранит фоновые тайлы как x + y * CHUNK_SIZE
|
||||
*/
|
||||
private val backgroundTiles = arrayOfNulls<ChunkTile>(CHUNK_SIZE * CHUNK_SIZE)
|
||||
|
||||
override operator fun get(x: Int, y: Int): ChunkTile? {
|
||||
if (isOutside(x, y))
|
||||
@ -134,13 +165,45 @@ class Chunk(val world: World, override val pos: ChunkPos) : IMutableChunk {
|
||||
return tiles[x or (y shl CHUNK_SHIFT)]
|
||||
}
|
||||
|
||||
override operator fun set(x: Int, y: Int, tile: ChunkTile?) {
|
||||
protected 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 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
|
||||
}
|
||||
@ -149,13 +212,10 @@ class Chunk(val world: World, override val pos: ChunkPos) : IMutableChunk {
|
||||
val EMPTY = object : IMutableChunk {
|
||||
override val pos = ChunkPos(0, 0)
|
||||
|
||||
override fun get(x: Int, y: Int): ChunkTile? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun set(x: Int, y: Int, tile: ChunkTile?) {
|
||||
|
||||
}
|
||||
override fun get(x: Int, y: Int): 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,20 @@
|
||||
package ru.dbotthepony.kstarbound.world
|
||||
|
||||
import ru.dbotthepony.kstarbound.defs.TileDefinition
|
||||
import ru.dbotthepony.kstarbound.math.Vector2i
|
||||
|
||||
class World(val seed: Long = 0L) {
|
||||
val chunkMap = ArrayList<Pair<ChunkPos, Chunk>>()
|
||||
private val chunkMap = ArrayList<Pair<ChunkPos, Chunk>>()
|
||||
private var lastAccessedChunk: Chunk? = null
|
||||
|
||||
fun getChunk(pos: ChunkPos): Chunk? {
|
||||
if (lastAccessedChunk?.pos == pos) {
|
||||
return lastAccessedChunk
|
||||
}
|
||||
|
||||
for ((k, v) in chunkMap) {
|
||||
if (k == pos) {
|
||||
lastAccessedChunk = v
|
||||
return v
|
||||
}
|
||||
}
|
||||
@ -15,9 +22,11 @@ class World(val seed: Long = 0L) {
|
||||
return null
|
||||
}
|
||||
|
||||
fun getChunk(pos: Vector2i) = getChunk(ChunkPos(pos))
|
||||
|
||||
fun getOrMakeChunk(pos: ChunkPos): Chunk {
|
||||
if (lastAccessedChunk?.pos == pos) {
|
||||
return lastAccessedChunk!!
|
||||
}
|
||||
|
||||
for ((k, v) in chunkMap) {
|
||||
if (k == pos) {
|
||||
return v
|
||||
@ -25,17 +34,19 @@ class World(val seed: Long = 0L) {
|
||||
}
|
||||
|
||||
val chunk = Chunk(this, pos)
|
||||
lastAccessedChunk = chunk
|
||||
chunkMap.add(pos to chunk)
|
||||
return chunk
|
||||
}
|
||||
|
||||
fun getChunk(pos: Vector2i) = getChunk(ChunkPos(pos))
|
||||
fun getOrMakeChunk(pos: Vector2i) = getOrMakeChunk(ChunkPos(pos))
|
||||
|
||||
fun getTile(pos: Vector2i): ChunkTile? {
|
||||
return getChunk(pos)?.get(pos.x, pos.y)
|
||||
}
|
||||
|
||||
fun setTile(pos: Vector2i, tile: ChunkTile?): Chunk {
|
||||
fun setTile(pos: Vector2i, tile: TileDefinition?): Chunk {
|
||||
val chunk = getOrMakeChunk(pos)
|
||||
chunk[pos.x and CHUNK_SIZE_FF, pos.y and CHUNK_SIZE_FF] = tile
|
||||
return chunk
|
||||
|
Loading…
Reference in New Issue
Block a user