diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt index d0a14e04..78fe9ca5 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt @@ -123,7 +123,26 @@ fun main() { chunk.background[x, y]?.setModifierHueShift(modifierHueShift2) - reader.skipBytes(17) + val liquid = reader.readUnsignedByte() + val liquidLevel = reader.readFloat() + val liquidPressure = reader.readFloat() + val liquidIsInfinite = reader.readBoolean() + val collisionMap = reader.readUnsignedByte() + val dungeonId = reader.readUnsignedShort() + val biome = reader.readUnsignedByte() + val envBiome = reader.readUnsignedByte() + val indestructible = reader.readBoolean() + val unknown = reader.readUnsignedByte() + + val getLiquid = Starbound.liquidByIDAccess[liquid] + + if (getLiquid != null) { + val state = chunk.setLiquid(x, y, getLiquid)!! + + state.isInfinite = liquidIsInfinite + state.pressure = liquidPressure + state.level = liquidLevel + } } } @@ -144,8 +163,8 @@ fun main() { //ent.position += Vector2d(y = 14.0, x = -10.0) ent.position = Vector2d(600.0 + 16.0, 721.0 + 48.0) - client.camera.pos.x = 616f - client.camera.pos.y = 721f + client.camera.pos.x = 578f + client.camera.pos.y = 695f client.onDrawGUI { client.gl.font.render("${ent.position}", y = 100f, scale = 0.25f) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientChunk.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientChunk.kt index 04ba733b..9eb3c240 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientChunk.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientChunk.kt @@ -1,15 +1,18 @@ package ru.dbotthepony.kstarbound.client +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap import ru.dbotthepony.kstarbound.client.gl.GLStateTracker import ru.dbotthepony.kstarbound.client.render.ConfiguredStaticMesh import ru.dbotthepony.kstarbound.client.render.EntityRenderer import ru.dbotthepony.kstarbound.client.render.ILayeredRenderer import ru.dbotthepony.kstarbound.client.render.TileLayerList +import ru.dbotthepony.kstarbound.defs.liquid.LiquidDefinition import ru.dbotthepony.kstarbound.world.* import ru.dbotthepony.kstarbound.world.entities.Entity import ru.dbotthepony.kvector.matrix.Matrix4fStack import ru.dbotthepony.kvector.vector.ndouble.Vector2d import java.io.Closeable +import java.util.IdentityHashMap import java.util.LinkedList /** @@ -19,6 +22,7 @@ import java.util.LinkedList * первыми (на самом дальнем плане) */ const val Z_LEVEL_BACKGROUND = 60000 +const val Z_LEVEL_LIQUID = 10000 class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk(world, pos), Closeable { val state: GLStateTracker get() = world.client.gl @@ -223,7 +227,7 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk Unit, Int>>() init { @@ -241,10 +245,50 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk + val types = ArrayList() + + for (x in 0 until CHUNK_SIZE) { + for (y in 0 until CHUNK_SIZE) { + val state = getLiquid(x, y) + + if (state != null && !types.any { it === state.def }) { + types.add(state.def) + } + } + } + + val program = state.programs.liquid + + program.use() + program.transform.set(it.last) + + val builder = program.builder + + for (type in types) { + builder.begin() + + for (x in 0 until CHUNK_SIZE) { + for (y in 0 until CHUNK_SIZE) { + val state = getLiquid(x, y) + + if (state != null && state.def === type) { + builder.quad(x.toFloat(), y.toFloat(), x + 1f, y + state.level) + } + } + } + + program.baselineColor.set(type.color) + + builder.upload() + builder.draw() + } + } to Z_LEVEL_LIQUID) + layerQueue.sortBy { return@sortBy it.second } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientWorld.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientWorld.kt index 247e1945..50ed9277 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientWorld.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientWorld.kt @@ -101,7 +101,7 @@ class ClientWorld( val determineRenderers = ArrayList() for (chunk in collectPositionAware(size.encasingChunkPosAABB())) { - determineRenderers.add(chunk.second.BakedLayeredRenderer(chunk.first)) + determineRenderers.add(chunk.second.OneShotRenderer(chunk.first)) chunk.second.bake() } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt index cdfd20f7..6eaae01c 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt @@ -5,8 +5,9 @@ import org.lwjgl.opengl.GL import org.lwjgl.opengl.GL46.* import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.client.freetype.FreeType +import ru.dbotthepony.kstarbound.client.gl.program.GLPrograms import ru.dbotthepony.kstarbound.client.gl.shader.GLShader -import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram +import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableColorableProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableProgram import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList @@ -76,6 +77,8 @@ interface GLStreamBuilderList { class GLStateTracker { init { + check(TRACKERS.get() == null) { "Already has state tracker existing at this thread!" } + TRACKERS.set(this) // This line is critical for LWJGL's interoperation with GLFW's // OpenGL context, or any context that is managed externally. // LWJGL detects the context that is current in the current thread, @@ -393,13 +396,17 @@ class GLStateTracker { } } + val quadWireframe by lazy { + StreamVertexBuilder(this, GLAttributeList.VEC2F, VertexType.QUADS_AS_LINES_WIREFRAME, 16384) + } + val matrixStack = Matrix4fStack() val freeType = FreeType() val font = Font(this) inline fun quadWireframe(color: Color = Color.WHITE, lambda: (StreamVertexBuilder) -> Unit) { - val builder = flat2DQuadWireframe.small + val builder = quadWireframe builder.begin() lambda.invoke(builder) @@ -423,5 +430,6 @@ class GLStateTracker { companion object { private val LOGGER = LogManager.getLogger(GLStateTracker::class.java) + private val TRACKERS = ThreadLocal() } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLInternalProgram.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLInternalProgram.kt new file mode 100644 index 00000000..bd816843 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLInternalProgram.kt @@ -0,0 +1,30 @@ +package ru.dbotthepony.kstarbound.client.gl.program + +import ru.dbotthepony.kstarbound.client.gl.GLStateTracker +import ru.dbotthepony.kstarbound.client.gl.shader.GLShader + +private fun loadShaders( + vertex: Collection, + fragment: Collection +): Array { + val result = arrayOfNulls(vertex.size + fragment.size) + var i = 0 + + for (name in vertex) { + result[i++] = GLShader.internalVertex("shaders/$name.vsh") + } + + for (name in fragment) { + result[i++] = GLShader.internalFragment("shaders/$name.fsh") + } + + return result as Array +} + +open class GLInternalProgram( + state: GLStateTracker, + vertex: Collection, + fragment: Collection +) : GLShaderProgram(state, *loadShaders(vertex, fragment)) { + constructor(state: GLStateTracker, name: String) : this(state, listOf(name), listOf(name)) +} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLShaderProgram.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLShaderProgram.kt similarity index 91% rename from src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLShaderProgram.kt rename to src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLShaderProgram.kt index c392d4fc..1d1cb4e2 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLShaderProgram.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLShaderProgram.kt @@ -1,10 +1,12 @@ -package ru.dbotthepony.kstarbound.client.gl.shader +package ru.dbotthepony.kstarbound.client.gl.program -import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import org.lwjgl.opengl.GL46.* import ru.dbotthepony.kstarbound.client.gl.GLStateTracker +import ru.dbotthepony.kstarbound.client.gl.shader.GLShader +import ru.dbotthepony.kstarbound.client.gl.shader.GLUniformLocation +import ru.dbotthepony.kstarbound.client.gl.shader.ShaderLinkException import ru.dbotthepony.kvector.api.IFloatMatrix import ru.dbotthepony.kvector.api.IStruct3f import ru.dbotthepony.kvector.api.IStruct4f @@ -12,6 +14,10 @@ import java.util.* import kotlin.collections.HashSet open class GLShaderProgram(val state: GLStateTracker, vararg shaders: GLShader) { + init { + state.ensureSameThread() + } + val pointer = glCreateProgram() var linked = false private set diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/Programs.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/Programs.kt similarity index 56% rename from src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/Programs.kt rename to src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/Programs.kt index a9f4de23..28f6222a 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/Programs.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/Programs.kt @@ -1,8 +1,13 @@ -package ru.dbotthepony.kstarbound.client.gl +package ru.dbotthepony.kstarbound.client.gl.program +import ru.dbotthepony.kstarbound.client.gl.GLStateTracker +import ru.dbotthepony.kstarbound.client.gl.GLType import ru.dbotthepony.kstarbound.client.gl.shader.GLShader -import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableColorableProgram +import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableProgram +import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList +import ru.dbotthepony.kstarbound.client.gl.vertex.StreamVertexBuilder +import ru.dbotthepony.kstarbound.client.gl.vertex.VertexType import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty @@ -10,6 +15,8 @@ private class SimpleProgram(private val name: String, priva private var value: T? = null override fun getValue(thisRef: GLPrograms, property: KProperty<*>): T { + thisRef.state.ensureSameThread() + val value = value if (value != null) { @@ -34,8 +41,26 @@ private class SimpleProgram(private val name: String, priva } } +class GLLiquidProgram(state: GLStateTracker) : GLInternalProgram(state, "liquid") { + init { + link() + } + + val baselineColor = this["baselineColor"]!! + val transform = this["transform"]!! + + val builder by lazy { + StreamVertexBuilder(state, FORMAT, VertexType.QUADS, 16384) + } + + companion object { + val FORMAT = GLAttributeList.Builder().push(GLType.VEC2F).build() + } +} + class GLPrograms(val state: GLStateTracker) { val tile by SimpleProgram("tile", ::GLTransformableColorableProgram) val font by SimpleProgram("font", ::GLTransformableColorableProgram) val flat by SimpleProgram("flat", ::GLTransformableColorableProgram) + val liquid by lazy { GLLiquidProgram(state) } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLTransformableProgram.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLTransformableProgram.kt index a9803500..e8892fb3 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLTransformableProgram.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLTransformableProgram.kt @@ -1,6 +1,7 @@ package ru.dbotthepony.kstarbound.client.gl.shader import ru.dbotthepony.kstarbound.client.gl.GLStateTracker +import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram import ru.dbotthepony.kvector.matrix.nfloat.Matrix4f open class GLTransformableProgram(state: GLStateTracker, vararg shaders: GLShader) : GLShaderProgram(state, *shaders) { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLUniformLocation.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLUniformLocation.kt index 1e3b41ac..c09795d3 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLUniformLocation.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLUniformLocation.kt @@ -2,6 +2,7 @@ package ru.dbotthepony.kstarbound.client.gl.shader import org.lwjgl.opengl.GL41.* import ru.dbotthepony.kstarbound.client.gl.checkForGLError +import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram import ru.dbotthepony.kvector.api.IFloatMatrix import ru.dbotthepony.kvector.api.IStruct3f import ru.dbotthepony.kvector.api.IStruct4f @@ -14,6 +15,7 @@ class GLUniformLocation(val program: GLShaderProgram, val name: String, val poin program.state.ensureSameThread() val (v0, v1, v2, v3) = value glProgramUniform4f(program.pointer, pointer, v0, v1, v2, v3) + checkForGLError() return this } @@ -21,12 +23,14 @@ class GLUniformLocation(val program: GLShaderProgram, val name: String, val poin program.state.ensureSameThread() val (v0, v1, v2) = value glProgramUniform3f(program.pointer, pointer, v0, v1, v2) + checkForGLError() return this } fun set(value: Int): GLUniformLocation { program.state.ensureSameThread() glProgramUniform1i(program.pointer, pointer, value) + checkForGLError() return this } @@ -56,4 +60,4 @@ class GLUniformLocation(val program: GLShaderProgram, val name: String, val poin return this } -} \ No newline at end of file +} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/GLAttributeList.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/GLAttributeList.kt index c9b1119a..be9df708 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/GLAttributeList.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/GLAttributeList.kt @@ -87,9 +87,8 @@ class GLAttributeList(builder: Builder) { val VERTEX_TEXTURE = Builder().push(GLType.VEC3F).push(GLType.VEC2F).build() - val VERTEX_HSV_TEXTURE = Builder() - .push(GLType.VEC3F, GLType.VEC2F, GLType.FLOAT).build() - val VERTEX_2D_TEXTURE = Builder().push(GLType.VEC2F).push(GLType.VEC2F).build() + + val TILE = Builder().push(GLType.VEC3F, GLType.VEC2F, GLType.FLOAT).build() } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/ConfiguredShaderProgram.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/ConfiguredShaderProgram.kt index fa2e0a18..b9270131 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/ConfiguredShaderProgram.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/ConfiguredShaderProgram.kt @@ -1,7 +1,7 @@ package ru.dbotthepony.kstarbound.client.render import org.lwjgl.opengl.GL46.* -import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram +import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram import ru.dbotthepony.kstarbound.client.gl.VertexArrayObject import ru.dbotthepony.kstarbound.client.gl.checkForGLError import ru.dbotthepony.kstarbound.client.gl.vertex.AbstractVertexBuilder diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt index 28e1af4c..97904950 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt @@ -168,7 +168,7 @@ private enum class TileRenderTesselateResult { HALT } -private fun vertexTextureBuilder() = HeapVertexBuilder(GLAttributeList.VERTEX_HSV_TEXTURE, VertexType.QUADS) +private fun vertexTextureBuilder() = HeapVertexBuilder(GLAttributeList.TILE, VertexType.QUADS) private class TileEqualityTester(val definition: TileDefinition) : EqualityRuleTester { override fun test(thisTile: TileState?, otherTile: TileState?): Boolean { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/util/ArraySpliterator.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/util/ArraySpliterator.kt new file mode 100644 index 00000000..af21917c --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/util/ArraySpliterator.kt @@ -0,0 +1,45 @@ +package ru.dbotthepony.kstarbound.util + +import java.util.Spliterator +import java.util.function.Consumer + +class ArraySpliterator(private val source: Array, private val offset: Int = 0, private val size: Int = source.size) : Spliterator { + init { + require(offset + size <= source.size) { "Invalid dimensions for spliterator: offset = $offset, size = $size, source has size of ${source.size}" } + } + + private var index = 0 + + override fun tryAdvance(action: Consumer): Boolean { + if (index < size) { + action.accept(source[offset + index++]) + return true + } + + return false + } + + override fun trySplit(): Spliterator? { + if (index + 1 >= size) { + return null + } + + val splitSize = size / 2 + + if (splitSize == 0) { + return null + } + + val pointer = index + offset + index += splitSize + return ArraySpliterator(source, pointer, splitSize) + } + + override fun estimateSize(): Long { + return (size - index).toLong() + } + + override fun characteristics(): Int { + return Spliterator.ORDERED or Spliterator.SIZED + } +} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/util/IndexedArraySpliterator.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/util/IndexedArraySpliterator.kt new file mode 100644 index 00000000..7bd140dd --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/util/IndexedArraySpliterator.kt @@ -0,0 +1,48 @@ +package ru.dbotthepony.kstarbound.util + +import java.util.Spliterator +import java.util.function.Consumer + +class IndexedArraySpliterator(private val source: Array, private val offset: Int = 0, private val size: Int = source.size) : Spliterator.Entry> { + inner class Entry(val index: Int, val value: T) + + init { + require(offset + size <= source.size) { "Invalid dimensions for spliterator: offset = $offset, size = $size, source has size of ${source.size}" } + } + + private var index = 0 + + override fun tryAdvance(action: Consumer.Entry>): Boolean { + if (index < size) { + val pointer = offset + index++ + action.accept(Entry(pointer, source[pointer])) + return true + } + + return false + } + + override fun trySplit(): Spliterator.Entry>? { + if (index + 1 >= size) { + return null + } + + val splitSize = size / 2 + + if (splitSize == 0) { + return null + } + + val pointer = index + offset + index += splitSize + return IndexedArraySpliterator(source, pointer, splitSize) + } + + override fun estimateSize(): Long { + return (size - index).toLong() + } + + override fun characteristics(): Int { + return Spliterator.ORDERED or Spliterator.SIZED + } +} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/util/TwoDimensionalArray.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/util/TwoDimensionalArray.kt index 4e0dca75..98c89027 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/util/TwoDimensionalArray.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/util/TwoDimensionalArray.kt @@ -1,8 +1,16 @@ package ru.dbotthepony.kstarbound.util +import java.util.stream.Stream +import java.util.stream.StreamSupport import kotlin.reflect.KClass class TwoDimensionalArray(clazz: KClass, private val width: Int, private val height: Int) { + data class Entry( + val x: Int, + val y: Int, + val value: T, + ) + private val memory: Array = java.lang.reflect.Array.newInstance(clazz.java, width * height) as Array operator fun get(x: Int, y: Int): T? { @@ -17,7 +25,7 @@ class TwoDimensionalArray(clazz: KClass, private val width: Int, pri return memory[x + y * width] } - operator fun set(x: Int, y: Int, value: T): T? { + operator fun set(x: Int, y: Int, value: T?): T? { if (x !in 0 until width) { throw IndexOutOfBoundsException("X $x is out of bounds between 0 and $width") } @@ -30,6 +38,18 @@ class TwoDimensionalArray(clazz: KClass, private val width: Int, pri memory[x + y * width] = value return old } + + fun stream(): Stream { + return StreamSupport.stream(ArraySpliterator(memory), false) + } + + fun indexedStream(): Stream> { + return StreamSupport.stream(IndexedArraySpliterator(memory), false).map { + val x = it.index % width + val y = (it.index - x) / width + Entry(x, y, it.value) + } + } } inline fun TwoDimensionalArray(width: Int, height: Int) = TwoDimensionalArray(T::class, width, height) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt index 0905cd0f..f554a393 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt @@ -122,7 +122,7 @@ class TileState(val chunk: Chunk<*, *>.TileLayer, val def: TileDefinition) { } } -data class LiquidState(val chunk: Chunk<*, *>.TileLayer, val def: LiquidDefinition) { +data class LiquidState(val chunk: Chunk<*, *>, val def: LiquidDefinition) { var pressure: Float = 0f var level: Float = 1f var isInfinite: Boolean = false @@ -414,6 +414,18 @@ abstract class Chunk, This : Chunk = TwoDimensionalArray(CHUNK_SIZE, CHUNK_SIZE) + fun getLiquid(x: Int, y: Int) = liquidStates[x, y] + + fun setLiquid(x: Int, y: Int, value: LiquidDefinition?): LiquidState? { + if (value == null) { + return liquidStates.set(x, y, null) + } + + val state = LiquidState(this, value) + liquidStates[x, y] = state + return state + } + protected val entities = HashSet() val entitiesAccess: Set = Collections.unmodifiableSet(entities) diff --git a/src/main/resources/shaders/liquid.fsh b/src/main/resources/shaders/liquid.fsh new file mode 100644 index 00000000..f8429d5d --- /dev/null +++ b/src/main/resources/shaders/liquid.fsh @@ -0,0 +1,10 @@ + +#version 460 + +out vec4 resultColor; + +uniform vec4 baselineColor; + +void main() { + resultColor = vec4(baselineColor); +} diff --git a/src/main/resources/shaders/liquid.vsh b/src/main/resources/shaders/liquid.vsh new file mode 100644 index 00000000..ebeb16f6 --- /dev/null +++ b/src/main/resources/shaders/liquid.vsh @@ -0,0 +1,10 @@ + +#version 460 + +layout (location = 0) in vec2 vertexPos; + +uniform mat4 transform; + +void main() { + gl_Position = transform * vec4(vertexPos, 5.0, 1.0); +} diff --git a/src/test/kotlin/ru/dbotthepony/kstarbound/test/MiscTests.kt b/src/test/kotlin/ru/dbotthepony/kstarbound/test/MiscTests.kt new file mode 100644 index 00000000..0a99e845 --- /dev/null +++ b/src/test/kotlin/ru/dbotthepony/kstarbound/test/MiscTests.kt @@ -0,0 +1,38 @@ +package ru.dbotthepony.kstarbound.test + +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import ru.dbotthepony.kstarbound.util.ArraySpliterator +import java.rmi.UnexpectedException + +object MiscTests { + @Test + @DisplayName("Array Spliterator test") + fun arraySpliterator() { + val base = arrayOf(1, 2, 3, 4) + val spliterator = ArraySpliterator(base) + + assertTrue(spliterator.tryAdvance { assertEquals(1, it) }) + assertTrue(spliterator.tryAdvance { assertEquals(2, it) }) + assertTrue(spliterator.tryAdvance { assertEquals(3, it) }) + assertTrue(spliterator.tryAdvance { assertEquals(4, it) }) + assertFalse(spliterator.tryAdvance { throw UnexpectedException("Unreachable code") }) + } + + @Test + @DisplayName("Array Spliterator split test") + fun arraySpliteratorSplit() { + val base = arrayOf(1, 2, 3, 4, 5, 6) + val spliterator = ArraySpliterator(base) + + var i = 0 + + val splitted = spliterator.trySplit()!! + + splitted.forEachRemaining { assertEquals(++i, it) } + spliterator.forEachRemaining { assertEquals(++i, it) } + + assertEquals(6, i) + } +}