Make it compile against updated box2d and kvector

This commit is contained in:
DBotThePony 2023-09-02 20:51:15 +07:00
parent 48e1cd5263
commit 96e782c264
Signed by: DBot
GPG Key ID: DCC23B5715498507
66 changed files with 442 additions and 1022 deletions

View File

@ -2,7 +2,7 @@
import org.gradle.internal.jvm.Jvm import org.gradle.internal.jvm.Jvm
plugins { plugins {
kotlin("jvm") version "1.9.0" kotlin("jvm") version "1.9.10"
java java
application application
} }
@ -80,8 +80,8 @@ dependencies {
implementation("net.java.dev.jna:jna:5.13.0") implementation("net.java.dev.jna:jna:5.13.0")
implementation("com.github.jnr:jnr-ffi:2.2.13") implementation("com.github.jnr:jnr-ffi:2.2.13")
implementation("ru.dbotthepony:kbox2d:2.4.1.+") implementation("ru.dbotthepony:kbox2d:2.4.1.2")
implementation("ru.dbotthepony:kvector:1.3.2") implementation("ru.dbotthepony:kvector:2.2.3")
implementation("com.github.ben-manes.caffeine:caffeine:3.1.5") implementation("com.github.ben-manes.caffeine:caffeine:3.1.5")
} }

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.kstarbound.client.freetype.struct; package ru.dbotthepony.kstarbound.client.freetype.struct;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import ru.dbotthepony.kvector.vector.nint.Vector2i; import ru.dbotthepony.kvector.vector.Vector2i;
@Structure.FieldOrder({"x", "y"}) @Structure.FieldOrder({"x", "y"})
public class FT_Vector extends Structure { public class FT_Vector extends Structure {

View File

@ -8,17 +8,16 @@ import ru.dbotthepony.kstarbound.client.StarboundClient
import ru.dbotthepony.kstarbound.client.render.Animator import ru.dbotthepony.kstarbound.client.render.Animator
import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition
import ru.dbotthepony.kstarbound.io.BTreeDB import ru.dbotthepony.kstarbound.io.BTreeDB
import ru.dbotthepony.kstarbound.lua.LuaState
import ru.dbotthepony.kstarbound.lua.LuaType
import ru.dbotthepony.kstarbound.player.Avatar import ru.dbotthepony.kstarbound.player.Avatar
import ru.dbotthepony.kstarbound.player.Player
import ru.dbotthepony.kstarbound.player.QuestDescriptor import ru.dbotthepony.kstarbound.player.QuestDescriptor
import ru.dbotthepony.kstarbound.player.QuestInstance import ru.dbotthepony.kstarbound.player.QuestInstance
import ru.dbotthepony.kstarbound.util.JVMTimeSource import ru.dbotthepony.kstarbound.util.JVMTimeSource
import ru.dbotthepony.kstarbound.world.ChunkPos import ru.dbotthepony.kstarbound.world.ChunkPos
import ru.dbotthepony.kstarbound.world.TileState
import ru.dbotthepony.kstarbound.world.entities.ItemEntity import ru.dbotthepony.kstarbound.world.entities.ItemEntity
import ru.dbotthepony.kstarbound.world.entities.PlayerEntity import ru.dbotthepony.kstarbound.world.entities.PlayerEntity
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.Vector2f
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.DataInputStream import java.io.DataInputStream
import java.io.File import java.io.File
@ -87,66 +86,12 @@ fun main() {
reader.skipBytes(3) reader.skipBytes(3)
var hitTile = false
t = System.currentTimeMillis() t = System.currentTimeMillis()
for (y in 0 .. 31) { for (y in 0 .. 31) {
for (x in 0 .. 31) { for (x in 0 .. 31) {
val materialID = reader.readUnsignedShort() chunk.foreground.setTile(x, y, TileState.read(starbound.tilesByID::get, starbound.tileModifiersByID::get, reader))
val getMat = starbound.tilesByID[materialID] chunk.background.setTile(x, y, TileState.read(starbound.tilesByID::get, starbound.tileModifiersByID::get, reader))
if (getMat != null) {
chunk.foreground[x, y].material = getMat.value
hitTile = true
}
// reader.skipBytes(1) // Foreground hue shift
// reader.skipBytes(1) // Foreground color variant
val colorShift = reader.readUnsignedByte()
val colorVariant = reader.readUnsignedByte()
val modifier = reader.readUnsignedShort()
val getModifier = starbound.tileModifiersByID[modifier]
chunk.foreground[x, y].color = colorVariant
chunk.foreground[x, y].setHueShift(colorShift)
if (getModifier != null && getMat != null) {
chunk.foreground[x, y].modifier = getModifier.value
}
val modifierHueShift = reader.readUnsignedByte()
chunk.foreground[x, y].setModifierHueShift(modifierHueShift)
val materialID2 = reader.readUnsignedShort()
val getMat2 = starbound.tilesByID[materialID2]
if (getMat2 != null) {
chunk.background[x, y].material = getMat2.value
hitTile = true
}
// reader.skipBytes(1) // Background hue shift
// reader.skipBytes(1) // Background color variant
val colorShift2 = reader.readUnsignedByte()
val colorVariant2 = reader.readUnsignedByte()
val modifier2 = reader.readUnsignedShort()
val getModifier2 = starbound.tileModifiersByID[modifier2]
if (getModifier2 != null && getMat2 != null) {
chunk.background[x, y].modifier = getModifier2.value
}
chunk.background[x, y].color = colorVariant2
chunk.background[x, y].setHueShift(colorShift2)
val modifierHueShift2 = reader.readUnsignedByte()
chunk.background[x, y].setModifierHueShift(modifierHueShift2)
val liquid = reader.readUnsignedByte() val liquid = reader.readUnsignedByte()
val liquidLevel = reader.readFloat() val liquidLevel = reader.readFloat()
@ -172,11 +117,6 @@ fun main() {
} }
set += System.currentTimeMillis() - t set += System.currentTimeMillis() - t
if (hitTile) {
//println(chunk.chunk.posVector2d)
// ent.position = chunk.chunk.posVector2d + Vector2d(16.0, 34.0)
}
} }
} }
} }
@ -227,8 +167,7 @@ fun main() {
//ent.position += Vector2d(y = 14.0, x = -10.0) //ent.position += Vector2d(y = 14.0, x = -10.0)
ent.position = Vector2d(600.0 + 16.0, 721.0 + 48.0) ent.position = Vector2d(600.0 + 16.0, 721.0 + 48.0)
client.camera.pos.x = 578f client.camera.pos = Vector2f(578f, 695f)
client.camera.pos.y = 695f
client.onDrawGUI { client.onDrawGUI {
client.gl.font.render("${ent.position}", y = 100f, scale = 0.25f) client.gl.font.render("${ent.position}", y = 100f, scale = 0.25f)
@ -315,11 +254,10 @@ fun main() {
//client.camera.pos.x = ent.position.x.toFloat() //client.camera.pos.x = ent.position.x.toFloat()
//client.camera.pos.y = ent.position.y.toFloat() //client.camera.pos.y = ent.position.y.toFloat()
client.camera.pos.x += if (client.input.KEY_LEFT_DOWN || client.input.KEY_A_DOWN) -client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f client.camera.pos += Vector2f(
client.camera.pos.x += if (client.input.KEY_RIGHT_DOWN || client.input.KEY_D_DOWN) client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f (if (client.input.KEY_LEFT_DOWN || client.input.KEY_A_DOWN) -client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f) + (if (client.input.KEY_RIGHT_DOWN || client.input.KEY_D_DOWN) client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f),
(if (client.input.KEY_UP_DOWN || client.input.KEY_W_DOWN) client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f) + (if (client.input.KEY_DOWN_DOWN || client.input.KEY_S_DOWN) -client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f)
client.camera.pos.y += if (client.input.KEY_UP_DOWN || client.input.KEY_W_DOWN) client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f )
client.camera.pos.y += if (client.input.KEY_DOWN_DOWN || client.input.KEY_S_DOWN) -client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f
//println(client.camera.velocity.toDoubleVector() * client.frameRenderTime * 0.1) //println(client.camera.velocity.toDoubleVector() * client.frameRenderTime * 0.1)

View File

@ -51,6 +51,7 @@ import ru.dbotthepony.kstarbound.util.JsonArrayCollector
import ru.dbotthepony.kstarbound.io.* import ru.dbotthepony.kstarbound.io.*
import ru.dbotthepony.kstarbound.io.json.AABBTypeAdapter import ru.dbotthepony.kstarbound.io.json.AABBTypeAdapter
import ru.dbotthepony.kstarbound.io.json.AABBiTypeAdapter import ru.dbotthepony.kstarbound.io.json.AABBiTypeAdapter
import ru.dbotthepony.kstarbound.io.json.ColorTypeAdapter
import ru.dbotthepony.kstarbound.io.json.EitherTypeAdapter import ru.dbotthepony.kstarbound.io.json.EitherTypeAdapter
import ru.dbotthepony.kstarbound.io.json.InternedJsonElementAdapter import ru.dbotthepony.kstarbound.io.json.InternedJsonElementAdapter
import ru.dbotthepony.kstarbound.io.json.InternedStringAdapter import ru.dbotthepony.kstarbound.io.json.InternedStringAdapter
@ -79,7 +80,7 @@ import ru.dbotthepony.kstarbound.util.WriteOnce
import ru.dbotthepony.kstarbound.util.filterNotNull import ru.dbotthepony.kstarbound.util.filterNotNull
import ru.dbotthepony.kstarbound.util.set import ru.dbotthepony.kstarbound.util.set
import ru.dbotthepony.kstarbound.util.traverseJsonPath import ru.dbotthepony.kstarbound.util.traverseJsonPath
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.Vector2i
import java.io.* import java.io.*
import java.lang.ref.ReferenceQueue import java.lang.ref.ReferenceQueue
import java.lang.ref.WeakReference import java.lang.ref.WeakReference

View File

@ -15,12 +15,12 @@ import ru.dbotthepony.kstarbound.client.render.TileLayerList
import ru.dbotthepony.kstarbound.defs.tile.LiquidDefinition import ru.dbotthepony.kstarbound.defs.tile.LiquidDefinition
import ru.dbotthepony.kstarbound.world.* import ru.dbotthepony.kstarbound.world.*
import ru.dbotthepony.kstarbound.world.entities.Entity import ru.dbotthepony.kstarbound.world.entities.Entity
import ru.dbotthepony.kvector.matrix.Matrix4fStack import ru.dbotthepony.kvector.arrays.Matrix4fStack
import ru.dbotthepony.kvector.matrix.nfloat.Matrix4f import ru.dbotthepony.kvector.arrays.Matrix4f
import ru.dbotthepony.kvector.util2d.intersectCircleRectangle import ru.dbotthepony.kvector.util2d.intersectCircleRectangle
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.nfloat.Vector2f import ru.dbotthepony.kvector.vector.Vector2f
import ru.dbotthepony.kvector.vector.nfloat.Vector3f import ru.dbotthepony.kvector.vector.Vector3f
import java.io.Closeable import java.io.Closeable
import java.util.LinkedList import java.util.LinkedList
@ -52,7 +52,7 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
layers.clear() layers.clear()
for ((pos, tile) in view.posToTile) { for ((pos, tile) in view.iterate()) {
val material = tile.material val material = tile.material
if (material != null) { if (material != null) {
@ -68,7 +68,7 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
} }
fun loadRenderers(view: ITileChunk) { fun loadRenderers(view: ITileChunk) {
for ((_, tile) in view.posToTile) { for ((_, tile) in view.iterate()) {
val material = tile.material val material = tile.material
val modifier = tile.modifier val modifier = tile.modifier
@ -93,7 +93,7 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
} }
fun render(stack: Matrix4fStack) { fun render(stack: Matrix4fStack) {
val transform = stack.last val transform = stack.last()
for (mesh in bakedMeshes) { for (mesh in bakedMeshes) {
mesh.first.render(transform) mesh.first.render(transform)
@ -199,20 +199,20 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
for (x in this.x * SHADOW_GEOMETRY_SQUARE_SIZE until (this.x + 1) * SHADOW_GEOMETRY_SQUARE_SIZE) { for (x in this.x * SHADOW_GEOMETRY_SQUARE_SIZE until (this.x + 1) * SHADOW_GEOMETRY_SQUARE_SIZE) {
for (y in this.y * SHADOW_GEOMETRY_SQUARE_SIZE until (this.y + 1) * SHADOW_GEOMETRY_SQUARE_SIZE) { for (y in this.y * SHADOW_GEOMETRY_SQUARE_SIZE until (this.y + 1) * SHADOW_GEOMETRY_SQUARE_SIZE) {
if (foreground[x, y].material?.renderParameters?.lightTransparent == false) { if (foreground.getTile(x, y).material?.renderParameters?.lightTransparent == false) {
if (x == 0 || foreground[x - 1, y].material?.renderParameters?.lightTransparent != true) { if (x == 0 || foreground.getTile(x - 1, y).material?.renderParameters?.lightTransparent != true) {
line(builder, x.toFloat(), y + 1f, x.toFloat(), y.toFloat()) line(builder, x.toFloat(), y + 1f, x.toFloat(), y.toFloat())
} }
if (x == CHUNK_SIZE - 1 || foreground[x + 1, y].material?.renderParameters?.lightTransparent != true) { if (x == CHUNK_SIZE - 1 || foreground.getTile(x + 1, y).material?.renderParameters?.lightTransparent != true) {
line(builder, x + 1f, y.toFloat(), x + 1f, y + 1f) line(builder, x + 1f, y.toFloat(), x + 1f, y + 1f)
} }
if (y == 0 || foreground[x, y - 1].material?.renderParameters?.lightTransparent != true) { if (y == 0 || foreground.getTile(x, y - 1).material?.renderParameters?.lightTransparent != true) {
line(builder, x.toFloat(), y.toFloat(), x + 1f, y.toFloat()) line(builder, x.toFloat(), y.toFloat(), x + 1f, y.toFloat())
} }
if (y == CHUNK_SIZE - 1 || foreground[x, y + 1].material?.renderParameters?.lightTransparent != true) { if (y == CHUNK_SIZE - 1 || foreground.getTile(x, y + 1).material?.renderParameters?.lightTransparent != true) {
line(builder, x + 1f, y + 1f, x.toFloat(), y + 1f) line(builder, x + 1f, y + 1f, x.toFloat(), y + 1f)
} }
} }
@ -302,7 +302,7 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
) { ) {
if (!setOnce) { if (!setOnce) {
program.localToWorldTransform = program.localToWorldTransform =
Matrix4f.IDENTITY.translateWithMultiplication( Matrix4f.identity().translateWithMultiplication(
Vector3f(x = renderOrigin.x * CHUNK_SIZEf, Vector3f(x = renderOrigin.x * CHUNK_SIZEf,
y = renderOrigin.y * CHUNK_SIZEf)) y = renderOrigin.y * CHUNK_SIZEf))
@ -338,7 +338,7 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
) { ) {
if (!setOnce) { if (!setOnce) {
program.localToWorldTransform = program.localToWorldTransform =
Matrix4f.IDENTITY.translateWithMultiplication( Matrix4f.identity().translateWithMultiplication(
Vector3f(x = renderOrigin.x * CHUNK_SIZEf, Vector3f(x = renderOrigin.x * CHUNK_SIZEf,
y = renderOrigin.y * CHUNK_SIZEf)) y = renderOrigin.y * CHUNK_SIZEf))
@ -353,7 +353,7 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
fun addLayers(layers: LayeredRenderer) { fun addLayers(layers: LayeredRenderer) {
for ((baked, zLevel) in backgroundRenderer.bakedMeshes) { for ((baked, zLevel) in backgroundRenderer.bakedMeshes) {
layers.add(zLevel + Z_LEVEL_BACKGROUND) { layers.add(zLevel + Z_LEVEL_BACKGROUND) {
it.push().translateWithMultiplication(renderOrigin.x * CHUNK_SIZEf, renderOrigin.y * CHUNK_SIZEf) it.push().last().translateWithMultiplication(renderOrigin.x * CHUNK_SIZEf, renderOrigin.y * CHUNK_SIZEf)
baked.renderStacked(it) baked.renderStacked(it)
it.pop() it.pop()
} }
@ -361,7 +361,7 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
for ((baked, zLevel) in foregroundRenderer.bakedMeshes) { for ((baked, zLevel) in foregroundRenderer.bakedMeshes) {
layers.add(zLevel) { layers.add(zLevel) {
it.push().translateWithMultiplication(renderOrigin.x * CHUNK_SIZEf, renderOrigin.y * CHUNK_SIZEf) it.push().last().translateWithMultiplication(renderOrigin.x * CHUNK_SIZEf, renderOrigin.y * CHUNK_SIZEf)
baked.renderStacked(it) baked.renderStacked(it)
it.pop() it.pop()
} }
@ -370,14 +370,14 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
for (renderer in entityRenderers.values) { for (renderer in entityRenderers.values) {
layers.add(renderer.layer) { layers.add(renderer.layer) {
val relative = renderer.renderPos - posVector2d val relative = renderer.renderPos - posVector2d
it.push().translateWithMultiplication(renderOrigin.x * CHUNK_SIZEf + relative.x.toFloat(), renderOrigin.y * CHUNK_SIZEf + relative.y.toFloat()) it.push().last().translateWithMultiplication(renderOrigin.x * CHUNK_SIZEf + relative.x.toFloat(), renderOrigin.y * CHUNK_SIZEf + relative.y.toFloat())
renderer.render(it) renderer.render(it)
it.pop() it.pop()
} }
} }
layers.add(Z_LEVEL_LIQUID) { layers.add(Z_LEVEL_LIQUID) {
it.push().translateWithMultiplication(renderOrigin.x * CHUNK_SIZEf, renderOrigin.y * CHUNK_SIZEf) it.push().last().translateWithMultiplication(renderOrigin.x * CHUNK_SIZEf, renderOrigin.y * CHUNK_SIZEf)
val types = ArrayList<LiquidDefinition>() val types = ArrayList<LiquidDefinition>()
for (x in 0 until CHUNK_SIZE) { for (x in 0 until CHUNK_SIZE) {
@ -393,7 +393,7 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
val program = state.programs.liquid val program = state.programs.liquid
program.use() program.use()
program.transform = it.last program.transform = it.last()
val builder = program.builder val builder = program.builder

View File

@ -63,7 +63,7 @@ class ClientWorld(
client.gl.blendFunc = old client.gl.blendFunc = old
*/ */
val pos = client.screenToWorld(client.mouseCoordinatesF).toDoubleVector() val pos = client.screenToWorld(client.mouseCoordinatesF)
/*val lightsize = 16 /*val lightsize = 16

View File

@ -12,7 +12,6 @@ import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITf
import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.client.gl.BlendFunc import ru.dbotthepony.kstarbound.client.gl.BlendFunc
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
import ru.dbotthepony.kstarbound.client.gl.ScissorRect
import ru.dbotthepony.kstarbound.client.input.UserInput import ru.dbotthepony.kstarbound.client.input.UserInput
import ru.dbotthepony.kstarbound.client.render.Camera import ru.dbotthepony.kstarbound.client.render.Camera
import ru.dbotthepony.kstarbound.client.render.GPULightRenderer import ru.dbotthepony.kstarbound.client.render.GPULightRenderer
@ -22,12 +21,12 @@ import ru.dbotthepony.kstarbound.client.render.TileRenderers
import ru.dbotthepony.kstarbound.util.JVMTimeSource import ru.dbotthepony.kstarbound.util.JVMTimeSource
import ru.dbotthepony.kstarbound.util.PausableTimeSource import ru.dbotthepony.kstarbound.util.PausableTimeSource
import ru.dbotthepony.kstarbound.util.formatBytesShort import ru.dbotthepony.kstarbound.util.formatBytesShort
import ru.dbotthepony.kvector.matrix.nfloat.Matrix4f import ru.dbotthepony.kvector.arrays.Matrix4f
import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.util2d.AABB
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.nfloat.Vector2f import ru.dbotthepony.kvector.vector.Vector2f
import ru.dbotthepony.kvector.vector.nfloat.Vector3f import ru.dbotthepony.kvector.vector.Vector3f
import java.io.Closeable import java.io.Closeable
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
@ -51,12 +50,14 @@ class StarboundClient(val starbound: Starbound) : Closeable {
*/ */
var viewportMatrixScreen: Matrix4f var viewportMatrixScreen: Matrix4f
private set private set
get() = Matrix4f.unmodifiable(field)
/** /**
* Матрица преобразования мировых координат в нормализованные координаты * Матрица преобразования мировых координат в нормализованные координаты
*/ */
var viewportMatrixWorld: Matrix4f var viewportMatrixWorld: Matrix4f
private set private set
get() = Matrix4f.unmodifiable(field)
private val startupTextList = ArrayList<String>() private val startupTextList = ArrayList<String>()
private var finishStartupRendering = System.currentTimeMillis() + 4000L private var finishStartupRendering = System.currentTimeMillis() + 4000L
@ -76,11 +77,11 @@ class StarboundClient(val starbound: Starbound) : Closeable {
} }
private fun updateViewportMatrixScreen(): Matrix4f { private fun updateViewportMatrixScreen(): Matrix4f {
return Matrix4f.ortho(0f, viewportWidth.toFloat(), 0f, viewportHeight.toFloat(), 0.1f, 100f).translate(Vector3f(z = 2f)).toMatrix4f() return Matrix4f.ortho(0f, viewportWidth.toFloat(), 0f, viewportHeight.toFloat(), 0.1f, 100f).translate(Vector3f(z = 2f))
} }
private fun updateViewportMatrixWorld(): Matrix4f { private fun updateViewportMatrixWorld(): Matrix4f {
return Matrix4f.orthoDirect(0f, viewportWidth.toFloat(), 0f, viewportHeight.toFloat(), 1f, 100f).toMatrix4f() return Matrix4f.orthoDirect(0f, viewportWidth.toFloat(), 0f, viewportHeight.toFloat(), 1f, 100f)
} }
private val xMousePos = ByteBuffer.allocateDirect(8).also { it.order(ByteOrder.LITTLE_ENDIAN) }.asDoubleBuffer() private val xMousePos = ByteBuffer.allocateDirect(8).also { it.order(ByteOrder.LITTLE_ENDIAN) }.asDoubleBuffer()
@ -238,7 +239,7 @@ class StarboundClient(val starbound: Starbound) : Closeable {
init { init {
putDebugLog("Initialized OpenGL context") putDebugLog("Initialized OpenGL context")
gl.clearColor = Color.SLATE_GREY gl.clearColor = RGBAColor.SLATE_GRAY
gl.blend = true gl.blend = true
gl.blendFunc = BlendFunc.MULTIPLY_WITH_ALPHA gl.blendFunc = BlendFunc.MULTIPLY_WITH_ALPHA
@ -317,11 +318,11 @@ class StarboundClient(val starbound: Starbound) : Closeable {
if (frameRenderTime != 0.0 && starbound.initialized) if (frameRenderTime != 0.0 && starbound.initialized)
world.think(frameRenderTime) world.think(frameRenderTime)
gl.clearColor = Color.SLATE_GREY gl.clearColor = RGBAColor.SLATE_GRAY
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT) glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
gl.matrixStack.clear(viewportMatrixWorld.toMutableMatrix4f()) gl.matrixStack.clear(viewportMatrixWorld)
gl.matrixStack.push() gl.matrixStack.push().last()
.translateWithMultiplication(viewportWidth / 2f, viewportHeight / 2f, 2f) // центр экрана + координаты отрисовки мира .translateWithMultiplication(viewportWidth / 2f, viewportHeight / 2f, 2f) // центр экрана + координаты отрисовки мира
.scale(x = settings.zoom * PIXELS_IN_STARBOUND_UNITf, y = settings.zoom * PIXELS_IN_STARBOUND_UNITf) // масштабируем до нужного размера .scale(x = settings.zoom * PIXELS_IN_STARBOUND_UNITf, y = settings.zoom * PIXELS_IN_STARBOUND_UNITf) // масштабируем до нужного размера
.translateWithMultiplication(-camera.pos.x, -camera.pos.y) // перемещаем вид к камере .translateWithMultiplication(-camera.pos.x, -camera.pos.y) // перемещаем вид к камере
@ -351,7 +352,7 @@ class StarboundClient(val starbound: Starbound) : Closeable {
gl.matrixStack.pop() gl.matrixStack.pop()
} }
gl.matrixStack.clear(viewportMatrixScreen.toMutableMatrix4f()) gl.matrixStack.clear(viewportMatrixScreen)
val thisTime = System.currentTimeMillis() val thisTime = System.currentTimeMillis()
@ -363,12 +364,12 @@ class StarboundClient(val starbound: Starbound) : Closeable {
} }
gl.matrixStack.push() gl.matrixStack.push()
gl.matrixStack.translateWithMultiplication(y = viewportHeight.toFloat()) gl.matrixStack.last().translateWithMultiplication(y = viewportHeight.toFloat())
var shade = 255 var shade = 255
for (i in startupTextList.size - 1 downTo 0) { for (i in startupTextList.size - 1 downTo 0) {
val size = gl.font.render(startupTextList[i], alignY = TextAlignY.BOTTOM, scale = 0.4f, color = Color.SHADES_OF_GRAY[shade].copy(a = alpha)) val size = gl.font.render(startupTextList[i], alignY = TextAlignY.BOTTOM, scale = 0.4f, color = RGBAColor(shade / 255f, shade / 255f, shade / 255f, alpha))
gl.matrixStack.translateWithMultiplication(y = -size.height * 1.2f) gl.matrixStack.last().translateWithMultiplication(y = -size.height * 1.2f)
if (shade > 120) { if (shade > 120) {
shade -= 10 shade -= 10

View File

@ -19,15 +19,13 @@ import ru.dbotthepony.kstarbound.client.gl.vertex.VertexBuilder
import ru.dbotthepony.kstarbound.client.render.Box2DRenderer import ru.dbotthepony.kstarbound.client.render.Box2DRenderer
import ru.dbotthepony.kstarbound.client.render.Font import ru.dbotthepony.kstarbound.client.render.Font
import ru.dbotthepony.kvector.api.IStruct4f import ru.dbotthepony.kvector.api.IStruct4f
import ru.dbotthepony.kvector.matrix.Matrix4fStack import ru.dbotthepony.kvector.arrays.Matrix4fStack
import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.util2d.AABB
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import java.io.File import java.io.File
import java.lang.ref.Cleaner import java.lang.ref.Cleaner
import java.lang.ref.WeakReference
import java.time.Duration import java.time.Duration
import java.util.* import java.util.*
import java.util.concurrent.locks.LockSupport
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.properties.ReadWriteProperty import kotlin.properties.ReadWriteProperty
@ -333,7 +331,7 @@ class GLStateTracker(val client: StarboundClient) {
var texture2D: GLTexture2D? by TexturesTracker(80) var texture2D: GLTexture2D? by TexturesTracker(80)
var clearColor by GLStateGenericTracker<IStruct4f>(Color.WHITE) { var clearColor by GLStateGenericTracker<IStruct4f>(RGBAColor.WHITE) {
val (r, g, b, a) = it val (r, g, b, a) = it
glClearColor(r, g, b, a) glClearColor(r, g, b, a)
} }
@ -501,7 +499,7 @@ class GLStateTracker(val client: StarboundClient) {
return obj return obj
} }
inline fun quadWireframe(color: Color = Color.WHITE, lambda: (VertexBuilder) -> Unit) { inline fun quadWireframe(color: RGBAColor = RGBAColor.WHITE, lambda: (VertexBuilder) -> Unit) {
val builder = quadWireframe val builder = quadWireframe
builder.builder.begin() builder.builder.begin()
@ -510,7 +508,7 @@ class GLStateTracker(val client: StarboundClient) {
programs.flat.use() programs.flat.use()
programs.flat.color = color programs.flat.color = color
programs.flat.transform = matrixStack.last programs.flat.transform = matrixStack.last()
builder.draw(GL_LINES) builder.draw(GL_LINES)
} }
@ -523,12 +521,12 @@ class GLStateTracker(val client: StarboundClient) {
builder.upload() builder.upload()
programs.flatColor.use() programs.flatColor.use()
programs.flatColor.transform = matrixStack.last programs.flatColor.transform = matrixStack.last()
builder.draw(GL_TRIANGLES) builder.draw(GL_TRIANGLES)
} }
inline fun quadWireframe(value: AABB, color: Color = Color.WHITE, chain: (VertexBuilder) -> Unit = {}) { inline fun quadWireframe(value: AABB, color: RGBAColor = RGBAColor.WHITE, chain: (VertexBuilder) -> Unit = {}) {
quadWireframe(color) { quadWireframe(color) {
it.quad(value.mins.x.toFloat(), value.mins.y.toFloat(), value.maxs.x.toFloat(), value.maxs.y.toFloat()) it.quad(value.mins.x.toFloat(), value.mins.y.toFloat(), value.maxs.x.toFloat(), value.maxs.y.toFloat())
chain(it) chain(it)

View File

@ -4,7 +4,7 @@ import org.apache.logging.log4j.LogManager
import org.lwjgl.opengl.GL46.* import org.lwjgl.opengl.GL46.*
import org.lwjgl.stb.STBImage import org.lwjgl.stb.STBImage
import ru.dbotthepony.kstarbound.io.ImageData import ru.dbotthepony.kstarbound.io.ImageData
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.Vector2i
import java.io.File import java.io.File
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.nio.ByteBuffer import java.nio.ByteBuffer

View File

@ -4,27 +4,20 @@ import it.unimi.dsi.fastutil.objects.Object2BooleanArrayMap
import it.unimi.dsi.fastutil.objects.Object2BooleanFunction import it.unimi.dsi.fastutil.objects.Object2BooleanFunction
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.ObjectArraySet
import org.lwjgl.opengl.GL46.* import org.lwjgl.opengl.GL46.*
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
import ru.dbotthepony.kstarbound.client.gl.checkForGLError import ru.dbotthepony.kstarbound.client.gl.checkForGLError
import ru.dbotthepony.kvector.api.IFloatMatrix
import ru.dbotthepony.kvector.api.IStruct2f import ru.dbotthepony.kvector.api.IStruct2f
import ru.dbotthepony.kvector.api.IStruct3f import ru.dbotthepony.kvector.api.IStruct3f
import ru.dbotthepony.kvector.api.IStruct4f import ru.dbotthepony.kvector.api.IStruct4f
import ru.dbotthepony.kvector.api.concrete.IMatrix3f import ru.dbotthepony.kvector.arrays.Matrix4f
import ru.dbotthepony.kvector.api.concrete.IMatrix4f import ru.dbotthepony.kvector.arrays.Matrix3f
import ru.dbotthepony.kvector.matrix.nfloat.Matrix3f import ru.dbotthepony.kvector.vector.Vector2f
import ru.dbotthepony.kvector.matrix.nfloat.Matrix4f import ru.dbotthepony.kvector.vector.Vector3f
import ru.dbotthepony.kvector.vector.nfloat.Vector2f import ru.dbotthepony.kvector.vector.Vector4f
import ru.dbotthepony.kvector.vector.nfloat.Vector3f
import ru.dbotthepony.kvector.vector.nfloat.Vector4f
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
import java.nio.FloatBuffer import java.nio.FloatBuffer
import java.util.*
import java.util.stream.Stream
import kotlin.NoSuchElementException import kotlin.NoSuchElementException
import kotlin.properties.ReadWriteProperty import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
@ -178,32 +171,32 @@ open class GLShaderProgram(val state: GLStateTracker, shaders: Iterable<GLStateT
private val buff3x3: FloatBuffer = ByteBuffer.allocateDirect(4 * 3 * 3).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer() private val buff3x3: FloatBuffer = ByteBuffer.allocateDirect(4 * 3 * 3).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer()
private val buff4x4: FloatBuffer = ByteBuffer.allocateDirect(4 * 4 * 4).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer() private val buff4x4: FloatBuffer = ByteBuffer.allocateDirect(4 * 4 * 4).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer()
inner class F3x3Uniform(name: String) : Uniform<IMatrix3f<*>>(name) { inner class F3x3Uniform(name: String) : Uniform<Matrix3f>(name) {
override var value: IMatrix3f<*> = Matrix3f.ZERO override var value: Matrix3f = Matrix3f.zero()
set(value) { set(value) {
state.ensureSameThread() state.ensureSameThread()
if (field != value) { if (field != value) {
buff3x3.position(0) buff3x3.position(0)
value.write(buff3x3) value.storeColumnRow(buff3x3)
buff3x3.position(0) buff3x3.position(0)
glProgramUniformMatrix3fv(pointer, location, false, buff3x3) glProgramUniformMatrix3fv(pointer, location, false, buff3x3)
checkForGLError() checkForGLError()
field = value.toMatrix3f() field = value.copy()
} }
} }
} }
inner class F4x4Uniform(name: String) : Uniform<IMatrix4f<*>>(name) { inner class F4x4Uniform(name: String) : Uniform<Matrix4f>(name) {
private val _value = ByteBuffer.allocate(4 * 4 * 4).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer() private val _value = ByteBuffer.allocate(4 * 4 * 4).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer()
override var value: IMatrix4f<*> = Matrix4f.ZERO override var value: Matrix4f = Matrix4f.zero()
set(value) { set(value) {
state.ensureSameThread() state.ensureSameThread()
buff4x4.position(0) buff4x4.position(0)
value.write(buff4x4) value.storeColumnRow(buff4x4)
buff4x4.position(0) buff4x4.position(0)
_value.position(0) _value.position(0)
@ -212,7 +205,7 @@ open class GLShaderProgram(val state: GLStateTracker, shaders: Iterable<GLStateT
checkForGLError() checkForGLError()
buff4x4.position(0) buff4x4.position(0)
_value.put(buff4x4) _value.put(buff4x4)
field = value.toMatrix4f() field = Matrix4f.unmodifiable(value)
} }
} }
} }

View File

@ -8,8 +8,8 @@ import ru.dbotthepony.kstarbound.client.gl.vertex.StreamVertexBuilder
import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType
import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers
import ru.dbotthepony.kstarbound.client.render.GPULightRenderer import ru.dbotthepony.kstarbound.client.render.GPULightRenderer
import ru.dbotthepony.kvector.matrix.nfloat.Matrix4f import ru.dbotthepony.kvector.arrays.Matrix4f
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
private fun GLStateTracker.shaders(name: String): List<GLStateTracker.Shader> { private fun GLStateTracker.shaders(name: String): List<GLStateTracker.Shader> {
return listOf(internalVertex("shaders/$name.vsh"), internalFragment("shaders/$name.fsh")) return listOf(internalVertex("shaders/$name.vsh"), internalFragment("shaders/$name.fsh"))
@ -103,7 +103,7 @@ class GLColorQuadProgram(state: GLStateTracker) : GLShaderProgram(state, state.s
state.blendFunc = oldFunc state.blendFunc = oldFunc
} }
fun clearColor(color: Color = Color.WHITE) { fun clearColor(color: RGBAColor = RGBAColor.WHITE) {
use() use()
this.color = color this.color = color
@ -117,7 +117,7 @@ class GLColorQuadProgram(state: GLStateTracker) : GLShaderProgram(state, state.s
companion object { companion object {
val FORMAT = GLAttributeList.Builder().push(GLType.VEC2F).build() val FORMAT = GLAttributeList.Builder().push(GLType.VEC2F).build()
val ALPHA = Color(0f, 0f, 0f, 1f) val ALPHA = RGBAColor(0f, 0f, 0f, 1f)
} }
} }
@ -187,8 +187,8 @@ class GLTileProgram(state: GLStateTracker) : GLShaderProgram(state, state.shader
var texture by IUniform("texture0") var texture by IUniform("texture0")
init { init {
transform = Matrix4f.IDENTITY transform = Matrix4f.identity()
color = Color.WHITE color = RGBAColor.WHITE
} }
} }
@ -198,8 +198,8 @@ class GLFontProgram(state: GLStateTracker) : GLShaderProgram(state, state.shader
var texture by IUniform("texture0") var texture by IUniform("texture0")
init { init {
transform = Matrix4f.IDENTITY transform = Matrix4f.identity()
color = Color.WHITE color = RGBAColor.WHITE
} }
} }
@ -208,7 +208,7 @@ class GLFlatProgram(state: GLStateTracker) : GLShaderProgram(state, state.shader
var color by F4Uniform("color") var color by F4Uniform("color")
init { init {
color = Color.WHITE color = RGBAColor.WHITE
} }
} }
@ -217,7 +217,7 @@ class GLTexturedProgram(state: GLStateTracker) : GLShaderProgram(state, listOf(s
var texture by IUniform("texture0") var texture by IUniform("texture0")
init { init {
transform = Matrix4f.IDENTITY transform = Matrix4f.identity()
} }
} }
@ -227,8 +227,8 @@ class GLTexturedColoredProgram(state: GLStateTracker) : GLShaderProgram(state, l
var color by F4Uniform("color") var color by F4Uniform("color")
init { init {
transform = Matrix4f.IDENTITY transform = Matrix4f.identity()
color = Color.WHITE color = RGBAColor.WHITE
} }
} }

View File

@ -49,7 +49,6 @@ private fun indexSize(type: Int): Int {
* *
* Загрузка в память видеокарты происходит напрямую из буферов, через метод [upload] * Загрузка в память видеокарты происходит напрямую из буферов, через метод [upload]
*/ */
@Suppress("unchecked_cast")
class VertexBuilder( class VertexBuilder(
val attributes: GLAttributeList, val attributes: GLAttributeList,
val type: GeometryType, val type: GeometryType,

View File

@ -3,8 +3,8 @@ package ru.dbotthepony.kstarbound.client.render
import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITf import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITf
import ru.dbotthepony.kstarbound.client.ClientWorld import ru.dbotthepony.kstarbound.client.ClientWorld
import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition
import ru.dbotthepony.kvector.matrix.Matrix4fStack import ru.dbotthepony.kvector.arrays.Matrix4fStack
import ru.dbotthepony.kvector.vector.nfloat.Vector3f import ru.dbotthepony.kvector.vector.Vector3f
class Animator( class Animator(
val world: ClientWorld, val world: ClientWorld,
@ -38,10 +38,10 @@ class Animator(
val sprite = mainSprite?.update() ?: return val sprite = mainSprite?.update() ?: return
sprite.texture.bind() sprite.texture.bind()
stack.push().translateWithMultiplication(Vector3f(world.client.camera.pos)) stack.push().last().translateWithMultiplication(Vector3f(world.client.camera.pos))
state.programs.textured.use() state.programs.textured.use()
state.programs.textured.transform = stack.last state.programs.textured.transform = stack.last()
state.activeTexture = 0 state.activeTexture = 0
state.programs.textured.texture = 0 state.programs.textured.texture = 0

View File

@ -5,8 +5,8 @@ import ru.dbotthepony.kbox2d.api.IDebugDraw
import ru.dbotthepony.kbox2d.api.Transform import ru.dbotthepony.kbox2d.api.Transform
import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNIT import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNIT
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import kotlin.math.cos import kotlin.math.cos
import kotlin.math.sin import kotlin.math.sin
@ -17,7 +17,7 @@ class Box2DRenderer(val state: GLStateTracker) : IDebugDraw {
override var drawPairs: Boolean = false override var drawPairs: Boolean = false
override var drawCenterOfMess: Boolean = false override var drawCenterOfMess: Boolean = false
override fun drawPolygon(vertices: List<Vector2d>, color: Color) { override fun drawPolygon(vertices: List<Vector2d>, color: RGBAColor) {
require(vertices.size > 1) { "Vertex list had only ${vertices.size} namings in it" } require(vertices.size > 1) { "Vertex list had only ${vertices.size} namings in it" }
val builder = state.flat2DLines val builder = state.flat2DLines
@ -35,12 +35,12 @@ class Box2DRenderer(val state: GLStateTracker) : IDebugDraw {
state.programs.flat.use() state.programs.flat.use()
state.programs.flat.color = color state.programs.flat.color = color
state.programs.flat.transform = state.matrixStack.last state.programs.flat.transform = state.matrixStack.last()
builder.draw(GL_LINES) builder.draw(GL_LINES)
} }
private fun drawSolid(vertices: List<Vector2d>, color: Color) { private fun drawSolid(vertices: List<Vector2d>, color: RGBAColor) {
require(vertices.size >= 3) { "Vertex list had only ${vertices.size} namings in it" } require(vertices.size >= 3) { "Vertex list had only ${vertices.size} namings in it" }
val builder = state.flat2DTriangles val builder = state.flat2DTriangles
@ -61,17 +61,17 @@ class Box2DRenderer(val state: GLStateTracker) : IDebugDraw {
state.programs.flat.use() state.programs.flat.use()
state.programs.flat.color = color state.programs.flat.color = color
state.programs.flat.transform = state.matrixStack.last state.programs.flat.transform = state.matrixStack.last()
builder.draw(GL_TRIANGLES) builder.draw(GL_TRIANGLES)
} }
override fun drawSolidPolygon(vertices: List<Vector2d>, color: Color) { override fun drawSolidPolygon(vertices: List<Vector2d>, color: RGBAColor) {
drawSolid(vertices, color.copy(a = 0.5f)) drawSolid(vertices, color.copy(alpha = 0.5f))
drawPolygon(vertices, color) drawPolygon(vertices, color)
} }
override fun drawCircle(center: Vector2d, radius: Double, color: Color) { override fun drawCircle(center: Vector2d, radius: Double, color: RGBAColor) {
val vertexList = ArrayList<Vector2d>() val vertexList = ArrayList<Vector2d>()
for (i in 0 until 360 step 15) { for (i in 0 until 360 step 15) {
@ -88,7 +88,7 @@ class Box2DRenderer(val state: GLStateTracker) : IDebugDraw {
drawPolygon(vertexList, color) drawPolygon(vertexList, color)
} }
override fun drawSolidCircle(center: Vector2d, radius: Double, axis: Vector2d, color: Color) { override fun drawSolidCircle(center: Vector2d, radius: Double, axis: Vector2d, color: RGBAColor) {
val vertexList = ArrayList<Vector2d>() val vertexList = ArrayList<Vector2d>()
for (i in 0 until 360 step 15) { for (i in 0 until 360 step 15) {
@ -102,12 +102,12 @@ class Box2DRenderer(val state: GLStateTracker) : IDebugDraw {
)) ))
} }
drawSolidPolygon(vertexList, color.copy(a = 0.5f)) drawSolidPolygon(vertexList, color.copy(alpha = 0.5f))
drawPolygon(vertexList, color) drawPolygon(vertexList, color)
drawPolygon(listOf(center, center + axis * radius), color) drawPolygon(listOf(center, center + axis * radius), color)
} }
override fun drawSegment(p1: Vector2d, p2: Vector2d, color: Color) { override fun drawSegment(p1: Vector2d, p2: Vector2d, color: RGBAColor) {
drawPolygon(listOf(p1, p2), color) drawPolygon(listOf(p1, p2), color)
} }
@ -115,7 +115,7 @@ class Box2DRenderer(val state: GLStateTracker) : IDebugDraw {
TODO("Not yet implemented") TODO("Not yet implemented")
} }
override fun drawPoint(p: Vector2d, size: Double, color: Color) { override fun drawPoint(p: Vector2d, size: Double, color: RGBAColor) {
drawSolid(listOf( drawSolid(listOf(
Vector2d(x = p.x - size / (PIXELS_IN_STARBOUND_UNIT * 2.0), y = p.y - size / (PIXELS_IN_STARBOUND_UNIT * 2.0)), Vector2d(x = p.x - size / (PIXELS_IN_STARBOUND_UNIT * 2.0), y = p.y - size / (PIXELS_IN_STARBOUND_UNIT * 2.0)),
Vector2d(x = p.x + size / (PIXELS_IN_STARBOUND_UNIT * 2.0), y = p.y - size / (PIXELS_IN_STARBOUND_UNIT * 2.0)), Vector2d(x = p.x + size / (PIXELS_IN_STARBOUND_UNIT * 2.0), y = p.y - size / (PIXELS_IN_STARBOUND_UNIT * 2.0)),

View File

@ -2,13 +2,13 @@ package ru.dbotthepony.kstarbound.client.render
import org.lwjgl.glfw.GLFW.* import org.lwjgl.glfw.GLFW.*
import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.StarboundClient
import ru.dbotthepony.kvector.vector.nfloat.MutableVector2f import ru.dbotthepony.kvector.vector.Vector2f
class Camera(val client: StarboundClient) { class Camera(val client: StarboundClient) {
/** /**
* Позиция этой камеры в Starbound Unit'ах * Позиция этой камеры в Starbound Unit'ах
*/ */
val pos = MutableVector2f() var pos = Vector2f()
var pressedLeft = false var pressedLeft = false
private set private set
@ -43,30 +43,31 @@ class Camera(val client: StarboundClient) {
} }
} }
val velocity: MutableVector2f get() { val velocity: Vector2f get() {
val vec = MutableVector2f() var x = 0f
var y = 0f
if (pressedLeft) { if (pressedLeft) {
vec.x -= (FREEVIEW_SENS).toFloat() x -= (FREEVIEW_SENS).toFloat()
} }
if (pressedRight) { if (pressedRight) {
vec.x += (FREEVIEW_SENS).toFloat() x += (FREEVIEW_SENS).toFloat()
} }
if (pressedUp) { if (pressedUp) {
vec.y += (FREEVIEW_SENS).toFloat() y += (FREEVIEW_SENS).toFloat()
} }
if (pressedDown) { if (pressedDown) {
vec.y -= (FREEVIEW_SENS).toFloat() y -= (FREEVIEW_SENS).toFloat()
} }
return vec return Vector2f(x, y)
} }
fun think(delta: Double) { fun think(delta: Double) {
pos + velocity * delta.toFloat() pos += velocity * delta.toFloat()
} }
companion object { companion object {

View File

@ -5,9 +5,8 @@ import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram
import ru.dbotthepony.kstarbound.client.gl.VertexArrayObject import ru.dbotthepony.kstarbound.client.gl.VertexArrayObject
import ru.dbotthepony.kstarbound.client.gl.checkForGLError import ru.dbotthepony.kstarbound.client.gl.checkForGLError
import ru.dbotthepony.kstarbound.client.gl.vertex.VertexBuilder import ru.dbotthepony.kstarbound.client.gl.vertex.VertexBuilder
import ru.dbotthepony.kvector.api.IFloatMatrix import ru.dbotthepony.kvector.arrays.Matrix4f
import ru.dbotthepony.kvector.api.concrete.IMatrix4f import ru.dbotthepony.kvector.arrays.Matrix4fStack
import ru.dbotthepony.kvector.matrix.Matrix4fStack
/** /**
* Служит для быстрой настройки состояния для будущей отрисовки * Служит для быстрой настройки состояния для будущей отрисовки
@ -24,7 +23,7 @@ open class ConfiguredShaderProgram<T : GLShaderProgram>(
) { ) {
private val transformLocation = program.getUniform("transform") as? GLShaderProgram.F4x4Uniform private val transformLocation = program.getUniform("transform") as? GLShaderProgram.F4x4Uniform
open fun setTransform(value: IMatrix4f<*>) { open fun setTransform(value: Matrix4f) {
transformLocation?.value = value transformLocation?.value = value
} }
@ -74,7 +73,7 @@ class ConfiguredStaticMesh(
ebo.unbind() ebo.unbind()
} }
fun render(transform: IMatrix4f<*>? = null) { fun render(transform: Matrix4f? = null) {
check(isValid) { "$this is no longer valid" } check(isValid) { "$this is no longer valid" }
programState.setup() programState.setup()
@ -87,7 +86,7 @@ class ConfiguredStaticMesh(
checkForGLError() checkForGLError()
} }
fun renderStacked(transform: Matrix4fStack) = render(transform.last) fun renderStacked(transform: Matrix4fStack) = render(transform.last())
var isValid = true var isValid = true
private set private set

View File

@ -10,8 +10,8 @@ import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList
import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers
import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType
import ru.dbotthepony.kstarbound.client.gl.vertex.VertexBuilder import ru.dbotthepony.kstarbound.client.gl.vertex.VertexBuilder
import ru.dbotthepony.kvector.matrix.Matrix4fStack import ru.dbotthepony.kvector.arrays.Matrix4fStack
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
private fun breakLines(text: String): List<String> { private fun breakLines(text: String): List<String> {
var nextLineBreak = text.indexOf('\n', 0) var nextLineBreak = text.indexOf('\n', 0)
@ -87,7 +87,7 @@ class Font(
alignX: TextAlignX = TextAlignX.LEFT, alignX: TextAlignX = TextAlignX.LEFT,
alignY: TextAlignY = TextAlignY.TOP, alignY: TextAlignY = TextAlignY.TOP,
color: Color = Color.WHITE, color: RGBAColor = RGBAColor.WHITE,
scale: Float = 1f, scale: Float = 1f,
stack: Matrix4fStack = state.matrixStack, stack: Matrix4fStack = state.matrixStack,
@ -104,13 +104,13 @@ class Font(
stack.push() stack.push()
when (alignY) { when (alignY) {
TextAlignY.TOP -> stack.translateWithMultiplication(x = x, y = lineHeight * scale + y) TextAlignY.TOP -> stack.last().translateWithMultiplication(x = x, y = lineHeight * scale + y)
TextAlignY.CENTER -> stack.translateWithMultiplication(x = x, y = lineHeight * scale - totalY * scale / 2f + y) TextAlignY.CENTER -> stack.last().translateWithMultiplication(x = x, y = lineHeight * scale - totalY * scale / 2f + y)
TextAlignY.BOTTOM -> stack.translateWithMultiplication(x = x, y = lineHeight * scale - totalY * scale + y) TextAlignY.BOTTOM -> stack.last().translateWithMultiplication(x = x, y = lineHeight * scale - totalY * scale + y)
} }
if (scale != 1f) if (scale != 1f)
stack.scale(x = scale, y = scale) stack.last().scale(x = scale, y = scale)
state.programs.font.use() state.programs.font.use()
state.programs.font.color = color state.programs.font.color = color
@ -122,7 +122,7 @@ class Font(
for (line in text) { for (line in text) {
if (line == "") { if (line == "") {
stack.translateWithMultiplication(y = lineHeight) stack.last().translateWithMultiplication(y = lineHeight)
continue continue
} }
@ -133,12 +133,12 @@ class Font(
TextAlignX.CENTER -> { TextAlignX.CENTER -> {
movedX = totalX / 2f - lineWidth(line, space) / 2f movedX = totalX / 2f - lineWidth(line, space) / 2f
stack.translateWithMultiplication(x = movedX) stack.last().translateWithMultiplication(x = movedX)
} }
TextAlignX.RIGHT -> { TextAlignX.RIGHT -> {
movedX = -lineWidth(line, space) movedX = -lineWidth(line, space)
stack.translateWithMultiplication(x = movedX) stack.last().translateWithMultiplication(x = movedX)
} }
} }
@ -149,10 +149,10 @@ class Font(
if (chr == '\t') { if (chr == '\t') {
if (lineGlyphs % 4 == 0) { if (lineGlyphs % 4 == 0) {
advancedX += space.advanceX * 4 advancedX += space.advanceX * 4
stack.translateWithMultiplication(x = space.advanceX * 4) stack.last().translateWithMultiplication(x = space.advanceX * 4)
} else { } else {
advancedX += space.advanceX * (lineGlyphs % 4) advancedX += space.advanceX * (lineGlyphs % 4)
stack.translateWithMultiplication(x = space.advanceX * (lineGlyphs % 4)) stack.last().translateWithMultiplication(x = space.advanceX * (lineGlyphs % 4))
} }
lineGlyphs += lineGlyphs % 4 lineGlyphs += lineGlyphs % 4
@ -166,7 +166,7 @@ class Font(
} }
advancedX = advancedX.coerceAtLeast(lineWidth) advancedX = advancedX.coerceAtLeast(lineWidth)
stack.translateWithMultiplication(x = -lineWidth - movedX, y = lineHeight) stack.last().translateWithMultiplication(x = -lineWidth - movedX, y = lineHeight)
} }
state.VAO = null state.VAO = null
@ -184,7 +184,7 @@ class Font(
alignX: TextAlignX = TextAlignX.LEFT, alignX: TextAlignX = TextAlignX.LEFT,
alignY: TextAlignY = TextAlignY.TOP, alignY: TextAlignY = TextAlignY.TOP,
color: Color = Color.WHITE, color: RGBAColor = RGBAColor.WHITE,
scale: Float = 1f, scale: Float = 1f,
stack: Matrix4fStack = state.matrixStack, stack: Matrix4fStack = state.matrixStack,
@ -209,10 +209,10 @@ class Font(
if (chr == '\t') { if (chr == '\t') {
if (lineGlyphs % 4 == 0) { if (lineGlyphs % 4 == 0) {
lineWidth += space.advanceX * 4 lineWidth += space.advanceX * 4
state.matrixStack.translateWithMultiplication(x = space.advanceX * 4) state.matrixStack.last().translateWithMultiplication(x = space.advanceX * 4)
} else { } else {
lineWidth += space.advanceX * (lineGlyphs % 4) lineWidth += space.advanceX * (lineGlyphs % 4)
state.matrixStack.translateWithMultiplication(x = space.advanceX * (lineGlyphs % 4)) state.matrixStack.last().translateWithMultiplication(x = space.advanceX * (lineGlyphs % 4))
} }
lineGlyphs += lineGlyphs % 4 lineGlyphs += lineGlyphs % 4
@ -334,20 +334,20 @@ class Font(
fun render(stack: Matrix4fStack) { fun render(stack: Matrix4fStack) {
if (isEmpty) { if (isEmpty) {
stack.translateWithMultiplication(advanceX) stack.last().translateWithMultiplication(advanceX)
return return
} }
vao!!.bind() vao!!.bind()
stack.translateWithMultiplication(bearingX, -bearingY) stack.last().translateWithMultiplication(bearingX, -bearingY)
texture!!.bind() texture!!.bind()
state.programs.font.transform = stack.last state.programs.font.transform = stack.last()
glDrawElements(GL_TRIANGLES, indexCount, elementIndexType, 0L) glDrawElements(GL_TRIANGLES, indexCount, elementIndexType, 0L)
checkForGLError() checkForGLError()
stack.translateWithMultiplication(advanceX - bearingX, bearingY) stack.last().translateWithMultiplication(advanceX - bearingX, bearingY)
} }
override fun close() { override fun close() {

View File

@ -16,10 +16,10 @@ import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList
import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType
import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers
import ru.dbotthepony.kstarbound.client.gl.vertex.StreamVertexBuilder import ru.dbotthepony.kstarbound.client.gl.vertex.StreamVertexBuilder
import ru.dbotthepony.kvector.matrix.Matrix4fStack import ru.dbotthepony.kvector.arrays.Matrix4fStack
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.nfloat.Vector2f import ru.dbotthepony.kvector.vector.Vector2f
import ru.dbotthepony.kvector.vector.nfloat.Vector3f import ru.dbotthepony.kvector.vector.Vector3f
// Huge thanks to articles by Scott [slembcke] Lembcke! // Huge thanks to articles by Scott [slembcke] Lembcke!
// https://slembcke.github.io/SuperFastHardShadows // https://slembcke.github.io/SuperFastHardShadows
@ -70,7 +70,7 @@ class GPULightRenderer(val state: GLStateTracker) {
} }
val old = state.clearColor val old = state.clearColor
state.clearColor = Color.BLACK state.clearColor = RGBAColor.BLACK
framebufferRender.bind() framebufferRender.bind()
glClear(GL_COLOR_BUFFER_BIT) glClear(GL_COLOR_BUFFER_BIT)
@ -137,7 +137,7 @@ class GPULightRenderer(val state: GLStateTracker) {
fun renderHardLight( fun renderHardLight(
position: Vector2f, position: Vector2f,
color: Color = Color.WHITE, color: RGBAColor = RGBAColor.WHITE,
radius: Float = 10f, radius: Float = 10f,
lightPenetration: Float = 0.1f, lightPenetration: Float = 0.1f,
stack: Matrix4fStack = state.matrixStack stack: Matrix4fStack = state.matrixStack
@ -164,7 +164,7 @@ class GPULightRenderer(val state: GLStateTracker) {
state.clearColor = old state.clearColor = old
state.programs.hardLightGeometry.use() state.programs.hardLightGeometry.use()
state.programs.hardLightGeometry.transform = (stack.last) state.programs.hardLightGeometry.transform = (stack.last())
state.programs.hardLightGeometry.lightPosition = (position) state.programs.hardLightGeometry.lightPosition = (position)
state.programs.hardLightGeometry.lightPenetration = (1f - lightPenetration) state.programs.hardLightGeometry.lightPenetration = (1f - lightPenetration)
@ -175,7 +175,7 @@ class GPULightRenderer(val state: GLStateTracker) {
} }
state.programs.light.use() state.programs.light.use()
state.programs.light.transform = (stack.last) state.programs.light.transform = (stack.last())
state.programs.light.baselineColor = (color) state.programs.light.baselineColor = (color)
// Свет // Свет
@ -197,7 +197,7 @@ class GPULightRenderer(val state: GLStateTracker) {
fun renderSoftLight( fun renderSoftLight(
position: Vector2f, position: Vector2f,
color: Color = Color.WHITE, color: RGBAColor = RGBAColor.WHITE,
radius: Float = 10f, radius: Float = 10f,
innerRadius: Float = radius / 3f, innerRadius: Float = radius / 3f,
lightPenetration: Float = 0.5f, lightPenetration: Float = 0.5f,
@ -225,7 +225,7 @@ class GPULightRenderer(val state: GLStateTracker) {
state.clearColor = old state.clearColor = old
state.programs.softLightGeometry.use() state.programs.softLightGeometry.use()
state.programs.softLightGeometry.transform = (stack.last) state.programs.softLightGeometry.transform = (stack.last())
state.programs.softLightGeometry.lightPositionAndSize = (Vector3f(position, innerRadius)) state.programs.softLightGeometry.lightPositionAndSize = (Vector3f(position, innerRadius))
state.programs.softLightGeometry.lightPenetration = (lightPenetration) state.programs.softLightGeometry.lightPenetration = (lightPenetration)
@ -241,7 +241,7 @@ class GPULightRenderer(val state: GLStateTracker) {
state.cull = false state.cull = false
state.programs.light.use() state.programs.light.use()
state.programs.light.transform = (stack.last) state.programs.light.transform = (stack.last())
state.programs.light.baselineColor = (color) state.programs.light.baselineColor = (color)
// Свет // Свет
@ -283,8 +283,8 @@ class GPULightRenderer(val state: GLStateTracker) {
} }
companion object { companion object {
val CLEAR_COLOR_HARD = Color(0f, 0f, 0f, 0f) val CLEAR_COLOR_HARD = RGBAColor(0f, 0f, 0f, 0f)
val CLEAR_COLOR_SOFT = Color(0f, 0f, 0f, 0f) val CLEAR_COLOR_SOFT = RGBAColor(0f, 0f, 0f, 0f)
val BLEND_MODE = BlendFunc( val BLEND_MODE = BlendFunc(
BlendFunc.Func.DST_ALPHA, BlendFunc.Func.DST_ALPHA,

View File

@ -1,9 +1,8 @@
package ru.dbotthepony.kstarbound.client.render package ru.dbotthepony.kstarbound.client.render
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import ru.dbotthepony.kvector.matrix.Matrix4fStack import ru.dbotthepony.kvector.arrays.Matrix4fStack
/** /**
* Позволяет вызывать отрисовщики в определённой (послойной) последовательности * Позволяет вызывать отрисовщики в определённой (послойной) последовательности

View File

@ -12,9 +12,10 @@ import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList
import ru.dbotthepony.kstarbound.client.gl.vertex.* import ru.dbotthepony.kstarbound.client.gl.vertex.*
import ru.dbotthepony.kstarbound.defs.tile.* import ru.dbotthepony.kstarbound.defs.tile.*
import ru.dbotthepony.kstarbound.world.ITileChunk import ru.dbotthepony.kstarbound.world.ITileChunk
import ru.dbotthepony.kstarbound.world.ITileState import ru.dbotthepony.kstarbound.world.TileColor
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kstarbound.world.TileState
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.Vector2i
import kotlin.collections.HashMap import kotlin.collections.HashMap
data class TileLayer( data class TileLayer(
@ -152,15 +153,15 @@ class TileRenderers(val client: StarboundClient) {
} }
/** /**
* Возвращает запечённое состояние шейдера shaderVertexTextureColor с данной текстурой * Возвращает запечённое состояние шейдера shaderVertexTextureRGBAColor с данной текстурой
*/ */
fun background(texture: GLTexture2D): ConfiguredShaderProgram<GLTileProgram> { fun background(texture: GLTexture2D): ConfiguredShaderProgram<GLTileProgram> {
return backgroundTilePrograms.computeIfAbsent(texture, ::BackgroundTileProgram) return backgroundTilePrograms.computeIfAbsent(texture, ::BackgroundTileProgram)
} }
companion object { companion object {
val BACKGROUND_COLOR = Color(0.4f, 0.4f, 0.4f) val BACKGROUND_COLOR = RGBAColor(0.4f, 0.4f, 0.4f)
val FOREGROUND_COLOR = Color(1f, 1f, 1f) val FOREGROUND_COLOR = RGBAColor(1f, 1f, 1f)
} }
} }
@ -173,13 +174,13 @@ private enum class TileRenderTesselateResult {
private fun vertexTextureBuilder() = VertexBuilder(GLAttributeList.TILE, GeometryType.QUADS) private fun vertexTextureBuilder() = VertexBuilder(GLAttributeList.TILE, GeometryType.QUADS)
private class TileEqualityTester(val definition: TileDefinition) : EqualityRuleTester { private class TileEqualityTester(val definition: TileDefinition) : EqualityRuleTester {
override fun test(thisTile: ITileState, otherTile: ITileState): Boolean { override fun test(thisTile: TileState, otherTile: TileState): Boolean {
return otherTile.material == definition && thisTile.hueShift == otherTile.hueShift return otherTile.material == definition && thisTile.hueShift == otherTile.hueShift
} }
} }
private class ModifierEqualityTester(val definition: MaterialModifier) : EqualityRuleTester { private class ModifierEqualityTester(val definition: MaterialModifier) : EqualityRuleTester {
override fun test(thisTile: ITileState, otherTile: ITileState): Boolean { override fun test(thisTile: TileState, otherTile: TileState): Boolean {
return otherTile.modifier == definition return otherTile.modifier == definition
} }
} }
@ -200,7 +201,7 @@ class TileRenderer(val renderers: TileRenderers, val def: IRenderableTile) {
val bakedBackgroundProgramState = renderers.background(texture) val bakedBackgroundProgramState = renderers.background(texture)
// private var notifiedDepth = false // private var notifiedDepth = false
private fun tesselateAt(self: ITileState, piece: RenderPiece, getter: ITileChunk, builder: VertexBuilder, pos: Vector2i, offset: Vector2i = Vector2i.ZERO, isModifier: Boolean) { private fun tesselateAt(self: TileState, piece: RenderPiece, getter: ITileChunk, builder: VertexBuilder, pos: Vector2i, offset: Vector2i = Vector2i.ZERO, isModifier: Boolean) {
val fx = pos.x.toFloat() val fx = pos.x.toFloat()
val fy = pos.y.toFloat() val fy = pos.y.toFloat()
@ -230,9 +231,9 @@ class TileRenderer(val renderers: TileRenderers, val def: IRenderableTile) {
maxs += piece.variantStride * variant maxs += piece.variantStride * variant
} }
if (def.renderParameters.multiColored && piece.colorStride != null && self.color != 0) { if (def.renderParameters.multiColored && piece.colorStride != null && self.color != TileColor.DEFAULT) {
mins += piece.colorStride * self.color mins += piece.colorStride * self.color.ordinal
maxs += piece.colorStride * self.color maxs += piece.colorStride * self.color.ordinal
} }
val (u0, v0) = texture.pixelToUV(mins) val (u0, v0) = texture.pixelToUV(mins)
@ -242,7 +243,7 @@ class TileRenderer(val renderers: TileRenderers, val def: IRenderableTile) {
} }
private fun tesselatePiece( private fun tesselatePiece(
self: ITileState, self: TileState,
matchPiece: RenderMatch, matchPiece: RenderMatch,
getter: ITileChunk, getter: ITileChunk,
layers: TileLayerList, layers: TileLayerList,
@ -293,7 +294,7 @@ class TileRenderer(val renderers: TileRenderers, val def: IRenderableTile) {
* *
* Тесселирует тайлы в нужный VertexBuilder с масштабом согласно константе [PIXELS_IN_STARBOUND_UNITf] * Тесселирует тайлы в нужный VertexBuilder с масштабом согласно константе [PIXELS_IN_STARBOUND_UNITf]
*/ */
fun tesselate(self: ITileState, getter: ITileChunk, layers: TileLayerList, pos: Vector2i, background: Boolean = false, isModifier: Boolean = false) { fun tesselate(self: TileState, getter: ITileChunk, layers: TileLayerList, pos: Vector2i, background: Boolean = false, isModifier: Boolean = false) {
// если у нас нет renderTemplate // если у нас нет renderTemplate
// то мы просто не можем его отрисовать // то мы просто не можем его отрисовать
val template = def.renderTemplate.value ?: return val template = def.renderTemplate.value ?: return

View File

@ -5,8 +5,8 @@ import ru.dbotthepony.kstarbound.client.ClientChunk
import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.StarboundClient
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
import ru.dbotthepony.kstarbound.world.entities.Entity import ru.dbotthepony.kstarbound.world.entities.Entity
import ru.dbotthepony.kvector.matrix.Matrix4fStack import ru.dbotthepony.kvector.arrays.Matrix4fStack
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import java.io.Closeable import java.io.Closeable
/** /**

View File

@ -5,7 +5,7 @@ import ru.dbotthepony.kstarbound.client.ClientChunk
import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.StarboundClient
import ru.dbotthepony.kstarbound.client.render.RebindableSprite import ru.dbotthepony.kstarbound.client.render.RebindableSprite
import ru.dbotthepony.kstarbound.world.entities.ItemEntity import ru.dbotthepony.kstarbound.world.entities.ItemEntity
import ru.dbotthepony.kvector.matrix.Matrix4fStack import ru.dbotthepony.kvector.arrays.Matrix4fStack
class ItemRenderer(client: StarboundClient, entity: ItemEntity, chunk: ClientChunk?) : EntityRenderer(client, entity, chunk) { class ItemRenderer(client: StarboundClient, entity: ItemEntity, chunk: ClientChunk?) : EntityRenderer(client, entity, chunk) {
private val def = entity.def private val def = entity.def
@ -16,7 +16,7 @@ class ItemRenderer(client: StarboundClient, entity: ItemEntity, chunk: ClientChu
return return
state.programs.textured.use() state.programs.textured.use()
state.programs.textured.transform = stack.last state.programs.textured.transform = stack.last()
state.activeTexture = 0 state.activeTexture = 0
state.programs.textured.texture = 0 state.programs.textured.texture = 0

View File

@ -10,12 +10,10 @@ import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kstarbound.io.json.InternedJsonElementAdapter
import ru.dbotthepony.kstarbound.io.json.builder.EnumAdapter import ru.dbotthepony.kstarbound.io.json.builder.EnumAdapter
import ru.dbotthepony.kstarbound.io.json.builder.IStringSerializable
import ru.dbotthepony.kstarbound.io.json.Vector2dTypeAdapter import ru.dbotthepony.kstarbound.io.json.Vector2dTypeAdapter
import ru.dbotthepony.kvector.util.linearInterpolation import ru.dbotthepony.kvector.util.linearInterpolation
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
enum class JsonFunctionInterpolation { enum class JsonFunctionInterpolation {
LINEAR { LINEAR {

View File

@ -2,7 +2,7 @@ package ru.dbotthepony.kstarbound.defs
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
@JsonFactory @JsonFactory
data class MovementParameters( data class MovementParameters(

View File

@ -5,7 +5,7 @@ import com.google.common.collect.ImmutableMap
import ru.dbotthepony.kstarbound.defs.image.ImageReference import ru.dbotthepony.kstarbound.defs.image.ImageReference
import ru.dbotthepony.kstarbound.defs.particle.ParticleEmitter import ru.dbotthepony.kstarbound.defs.particle.ParticleEmitter
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
@JsonFactory @JsonFactory
data class AnimationDefinition( data class AnimationDefinition(

View File

@ -14,8 +14,8 @@ import ru.dbotthepony.kstarbound.api.ISBFileLocator
import ru.dbotthepony.kstarbound.client.gl.GLTexture2D import ru.dbotthepony.kstarbound.client.gl.GLTexture2D
import ru.dbotthepony.kstarbound.io.json.stream import ru.dbotthepony.kstarbound.io.json.stream
import ru.dbotthepony.kstarbound.util.PathStack import ru.dbotthepony.kstarbound.util.PathStack
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.Vector2i
import ru.dbotthepony.kvector.vector.nint.Vector4i import ru.dbotthepony.kvector.vector.Vector4i
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
/** /**

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.kstarbound.defs.item.api package ru.dbotthepony.kstarbound.defs.item.api
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
interface IFlashlightDefinition : IItemDefinition, IItemInHandDefinition { interface IFlashlightDefinition : IItemDefinition, IItemInHandDefinition {
/** /**
@ -9,7 +9,7 @@ interface IFlashlightDefinition : IItemDefinition, IItemInHandDefinition {
*/ */
val lightPosition: Vector2d val lightPosition: Vector2d
val lightColor: Color val lightColor: RGBAColor
val beamLevel: Int val beamLevel: Int

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.kstarbound.defs.item.api package ru.dbotthepony.kstarbound.defs.item.api
import ru.dbotthepony.kstarbound.defs.item.api.IItemDefinition import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
interface IItemInHandDefinition : IItemDefinition { interface IItemInHandDefinition : IItemDefinition {
/** /**

View File

@ -4,8 +4,8 @@ import ru.dbotthepony.kstarbound.defs.item.api.IFlashlightDefinition
import ru.dbotthepony.kstarbound.defs.item.api.IItemDefinition import ru.dbotthepony.kstarbound.defs.item.api.IItemDefinition
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.io.json.builder.JsonFlat import ru.dbotthepony.kstarbound.io.json.builder.JsonFlat
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
@JsonFactory @JsonFactory
class FlashlightDefinition( class FlashlightDefinition(
@ -13,7 +13,7 @@ class FlashlightDefinition(
val parent: IItemDefinition, val parent: IItemDefinition,
override val lightPosition: Vector2d, override val lightPosition: Vector2d,
override val lightColor: Color, override val lightColor: RGBAColor,
override val beamLevel: Int, override val beamLevel: Int,
override val beamAmbience: Double, override val beamAmbience: Double,
override val handPosition: Vector2d, override val handPosition: Vector2d,

View File

@ -3,10 +3,9 @@ package ru.dbotthepony.kstarbound.defs.item.impl
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.defs.item.api.IHarvestingToolDefinition import ru.dbotthepony.kstarbound.defs.item.api.IHarvestingToolDefinition
import ru.dbotthepony.kstarbound.defs.item.api.IItemDefinition import ru.dbotthepony.kstarbound.defs.item.api.IItemDefinition
import ru.dbotthepony.kstarbound.io.json.builder.JsonBuilder
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.io.json.builder.JsonFlat import ru.dbotthepony.kstarbound.io.json.builder.JsonFlat
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
@JsonFactory @JsonFactory
class HarvestingToolPrototype( class HarvestingToolPrototype(

View File

@ -5,7 +5,7 @@ import ru.dbotthepony.kstarbound.defs.animation.DestructionAction
import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation
import ru.dbotthepony.kstarbound.util.VirtualProperty import ru.dbotthepony.kstarbound.util.VirtualProperty
import ru.dbotthepony.kstarbound.util.SBPattern import ru.dbotthepony.kstarbound.util.SBPattern
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
@JsonImplementation(ParticleConfig::class) @JsonImplementation(ParticleConfig::class)
interface IParticleConfig : IParticleVariance { interface IParticleConfig : IParticleVariance {

View File

@ -3,9 +3,9 @@ package ru.dbotthepony.kstarbound.defs.particle
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation
import ru.dbotthepony.kstarbound.util.VirtualProperty import ru.dbotthepony.kstarbound.util.VirtualProperty
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.ndouble.Vector4d import ru.dbotthepony.kvector.vector.Vector4d
@JsonImplementation(ParticleVariance::class) @JsonImplementation(ParticleVariance::class)
interface IParticleVariance { interface IParticleVariance {
@ -16,7 +16,7 @@ interface IParticleVariance {
val approach: Vector2d? val approach: Vector2d?
val angularVelocity: Double? val angularVelocity: Double?
val size: Double? val size: Double?
val color: Color? val color: RGBAColor?
companion object { companion object {
fun chain(vararg particles: IParticleVariance): IParticleVariance { fun chain(vararg particles: IParticleVariance): IParticleVariance {

View File

@ -6,9 +6,9 @@ import ru.dbotthepony.kstarbound.defs.animation.DestructionAction
import ru.dbotthepony.kstarbound.defs.image.ImageReference import ru.dbotthepony.kstarbound.defs.image.ImageReference
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.util.SBPattern import ru.dbotthepony.kstarbound.util.SBPattern
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.ndouble.Vector4d import ru.dbotthepony.kvector.vector.Vector4d
@JsonFactory @JsonFactory
data class ParticleConfig( data class ParticleConfig(
@ -29,6 +29,6 @@ data class ParticleConfig(
override val layer: ParticleLayer? = null, override val layer: ParticleLayer? = null,
override val timeToLive: Double? = null, override val timeToLive: Double? = null,
override val variance: IParticleVariance? = null, override val variance: IParticleVariance? = null,
override val color: Color? = null, override val color: RGBAColor? = null,
override val text: SBPattern? = null, override val text: SBPattern? = null,
) : IParticleConfig ) : IParticleConfig

View File

@ -4,9 +4,9 @@ import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.defs.animation.DestructionAction import ru.dbotthepony.kstarbound.defs.animation.DestructionAction
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.util.SBPattern import ru.dbotthepony.kstarbound.util.SBPattern
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.ndouble.Vector4d import ru.dbotthepony.kvector.vector.Vector4d
@JsonFactory @JsonFactory
data class ParticleEmitter( data class ParticleEmitter(
@ -30,6 +30,6 @@ data class ParticleEmitter(
override val layer: ParticleLayer? = null, override val layer: ParticleLayer? = null,
override val timeToLive: Double? = null, override val timeToLive: Double? = null,
override val variance: IParticleVariance? = null, override val variance: IParticleVariance? = null,
override val color: Color? = null, override val color: RGBAColor? = null,
override val text: SBPattern? = null, override val text: SBPattern? = null,
) : IParticleConfig ) : IParticleConfig

View File

@ -1,9 +1,9 @@
package ru.dbotthepony.kstarbound.defs.particle package ru.dbotthepony.kstarbound.defs.particle
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.ndouble.Vector4d import ru.dbotthepony.kvector.vector.Vector4d
@JsonFactory @JsonFactory
data class ParticleVariance( data class ParticleVariance(
@ -14,5 +14,5 @@ data class ParticleVariance(
override val approach: Vector2d? = null, override val approach: Vector2d? = null,
override val angularVelocity: Double? = null, override val angularVelocity: Double? = null,
override val size: Double? = null, override val size: Double? = null,
override val color: Color? = null, override val color: RGBAColor? = null,
) : IParticleVariance ) : IParticleVariance

View File

@ -2,7 +2,7 @@ package ru.dbotthepony.kstarbound.defs.player
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
@JsonFactory @JsonFactory
data class MatterManipulatorConfig( data class MatterManipulatorConfig(

View File

@ -13,8 +13,8 @@ import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition
import ru.dbotthepony.kstarbound.defs.item.api.IItemDefinition import ru.dbotthepony.kstarbound.defs.item.api.IItemDefinition
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.util2d.AABB
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
@JsonFactory @JsonFactory
data class PlayerDefinition( data class PlayerDefinition(
@ -24,7 +24,7 @@ data class PlayerDefinition(
val collectableUnlock: SBPattern, val collectableUnlock: SBPattern,
val species: ImmutableSet<RegistryReference<Species>>, val species: ImmutableSet<RegistryReference<Species>>,
val nametagColor: Color, val nametagColor: RGBAColor,
val ageItemsEvery: Int, val ageItemsEvery: Int,
val defaultItems: ImmutableSet<RegistryReference<IItemDefinition>>, val defaultItems: ImmutableSet<RegistryReference<IItemDefinition>>,

View File

@ -1,8 +1,8 @@
package ru.dbotthepony.kstarbound.defs.player package ru.dbotthepony.kstarbound.defs.player
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
@JsonFactory @JsonFactory
data class SplashConfig( data class SplashConfig(
@ -21,7 +21,7 @@ data class SplashConfig(
val position: Vector2d, val position: Vector2d,
val finalVelocity: Vector2d, val finalVelocity: Vector2d,
val approach: Vector2d, val approach: Vector2d,
val color: Color, val color: RGBAColor,
val size: Double, val size: Double,
val timeToLive: Double, val timeToLive: Double,
val destructionAction: String, val destructionAction: String,

View File

@ -3,7 +3,7 @@ package ru.dbotthepony.kstarbound.defs.player
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap import com.google.common.collect.ImmutableMap
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
@JsonFactory @JsonFactory
data class StatusControllerSettings( data class StatusControllerSettings(

View File

@ -4,7 +4,7 @@ import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.defs.RegistryReference import ru.dbotthepony.kstarbound.defs.RegistryReference
import ru.dbotthepony.kstarbound.defs.StatusEffectDefinition import ru.dbotthepony.kstarbound.defs.StatusEffectDefinition
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
@JsonFactory @JsonFactory
data class LiquidDefinition( data class LiquidDefinition(
@ -12,12 +12,12 @@ data class LiquidDefinition(
val liquidId: Int, val liquidId: Int,
val description: String = "...", val description: String = "...",
val tickDelta: Int = 1, val tickDelta: Int = 1,
val color: Color, val color: RGBAColor,
val itemDrop: String? = null, val itemDrop: String? = null,
val statusEffects: ImmutableList<RegistryReference<StatusEffectDefinition>> = ImmutableList.of(), val statusEffects: ImmutableList<RegistryReference<StatusEffectDefinition>> = ImmutableList.of(),
val interactions: ImmutableList<Interaction> = ImmutableList.of(), val interactions: ImmutableList<Interaction> = ImmutableList.of(),
val texture: String, val texture: String,
val bottomLightMix: Color, val bottomLightMix: RGBAColor,
val textureMovementFactor: Double, val textureMovementFactor: Double,
) { ) {
@JsonFactory @JsonFactory

View File

@ -1,13 +1,8 @@
package ru.dbotthepony.kstarbound.defs.tile package ru.dbotthepony.kstarbound.defs.tile
import com.google.gson.GsonBuilder
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.image.ImageReference import ru.dbotthepony.kstarbound.defs.image.ImageReference
import ru.dbotthepony.kstarbound.io.json.builder.FactoryAdapter
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
const val TILE_COLOR_VARIANTS = 9
@JsonFactory @JsonFactory
data class RenderParameters( data class RenderParameters(
val texture: ImageReference, val texture: ImageReference,

View File

@ -7,8 +7,8 @@ import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.util.WriteOnce import ru.dbotthepony.kstarbound.util.WriteOnce
import ru.dbotthepony.kstarbound.world.ITileGetter import ru.dbotthepony.kstarbound.world.ITileGetter
import ru.dbotthepony.kstarbound.world.ITileState import ru.dbotthepony.kstarbound.world.TileState
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.Vector2i
@JsonFactory @JsonFactory
data class RenderPiece( data class RenderPiece(
@ -20,7 +20,7 @@ data class RenderPiece(
) )
fun interface EqualityRuleTester { fun interface EqualityRuleTester {
fun test(thisTile: ITileState, otherTile: ITileState): Boolean fun test(thisTile: TileState, otherTile: TileState): Boolean
} }
@JsonFactory @JsonFactory
@ -40,8 +40,8 @@ data class RenderRuleList(
) { ) {
private fun doTest(getter: ITileGetter, equalityTester: EqualityRuleTester, thisPos: Vector2i, offsetPos: Vector2i): Boolean { private fun doTest(getter: ITileGetter, equalityTester: EqualityRuleTester, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
return when (type) { return when (type) {
"EqualsSelf" -> equalityTester.test(getter[thisPos], getter[thisPos + offsetPos]) "EqualsSelf" -> equalityTester.test(getter.getTile(thisPos), getter.getTile(thisPos + offsetPos))
"Connects" -> getter[thisPos + offsetPos].material != null "Connects" -> getter.getTile(thisPos + offsetPos).material != null
else -> { else -> {
if (LOGGED.add(type)) { if (LOGGED.add(type)) {

View File

@ -6,13 +6,13 @@ import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.ThingDescription import ru.dbotthepony.kstarbound.defs.ThingDescription
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.io.json.builder.JsonFlat import ru.dbotthepony.kstarbound.io.json.builder.JsonFlat
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
@JsonFactory @JsonFactory
data class TileDefinition( data class TileDefinition(
val materialId: Int, val materialId: Int,
val materialName: String, val materialName: String,
val particleColor: Color? = null, val particleColor: RGBAColor? = null,
val itemDrop: String? = null, val itemDrop: String? = null,
val footstepSound: String? = null, val footstepSound: String? = null,
val miningSounds: ImmutableList<String> = ImmutableList.of(), val miningSounds: ImmutableList<String> = ImmutableList.of(),

View File

@ -4,8 +4,8 @@ import org.lwjgl.stb.STBImage
import org.lwjgl.system.MemoryUtil.memAddress import org.lwjgl.system.MemoryUtil.memAddress
import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNIT import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNIT
import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITi import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITi
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.Vector2i
import ru.dbotthepony.kvector.vector.nint.Vector4i import ru.dbotthepony.kvector.vector.Vector4i
import java.lang.ref.Cleaner import java.lang.ref.Cleaner
import java.nio.ByteBuffer import java.nio.ByteBuffer

View File

@ -5,8 +5,8 @@ import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.util2d.AABB
import ru.dbotthepony.kvector.util2d.AABBi import ru.dbotthepony.kvector.util2d.AABBi
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.Vector2i
object AABBTypeAdapter : TypeAdapter<AABB>() { object AABBTypeAdapter : TypeAdapter<AABB>() {
override fun write(out: JsonWriter, value: AABB) { override fun write(out: JsonWriter, value: AABB) {

View File

@ -1,17 +1,17 @@
package ru.dbotthepony.kstarbound.io package ru.dbotthepony.kstarbound.io.json
import com.google.gson.TypeAdapter import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kvector.vector.Color import ru.dbotthepony.kvector.vector.RGBAColor
object ColorTypeAdapter : TypeAdapter<Color>() { object ColorTypeAdapter : TypeAdapter<RGBAColor>() {
override fun write(out: JsonWriter, value: Color) { override fun write(out: JsonWriter, value: RGBAColor) {
TODO("Not yet implemented") TODO("Not yet implemented")
} }
override fun read(`in`: JsonReader): Color { override fun read(`in`: JsonReader): RGBAColor {
when (val type = `in`.peek()) { when (val type = `in`.peek()) {
JsonToken.BEGIN_ARRAY -> { JsonToken.BEGIN_ARRAY -> {
`in`.beginArray() `in`.beginArray()
@ -23,7 +23,7 @@ object ColorTypeAdapter : TypeAdapter<Color>() {
val alpha = `in`.peek().let { if (it == JsonToken.END_ARRAY) 255.0 else `in`.nextDouble() } val alpha = `in`.peek().let { if (it == JsonToken.END_ARRAY) 255.0 else `in`.nextDouble() }
`in`.endArray() `in`.endArray()
return Color( return RGBAColor(
red.toFloat() / 255f, red.toFloat() / 255f,
green.toFloat() / 255f, green.toFloat() / 255f,
blue.toFloat() / 255f, blue.toFloat() / 255f,
@ -33,7 +33,7 @@ object ColorTypeAdapter : TypeAdapter<Color>() {
val alpha = `in`.peek().let { if (it == JsonToken.END_ARRAY) 1.0 else `in`.nextDouble() } val alpha = `in`.peek().let { if (it == JsonToken.END_ARRAY) 1.0 else `in`.nextDouble() }
`in`.endArray() `in`.endArray()
return Color( return RGBAColor(
red.toFloat(), red.toFloat(),
green.toFloat(), green.toFloat(),
blue.toFloat(), blue.toFloat(),
@ -63,18 +63,18 @@ object ColorTypeAdapter : TypeAdapter<Color>() {
`in`.endObject() `in`.endObject()
if (values == 0) { if (values == 0) {
throw IllegalArgumentException("Object is not a color") throw IllegalArgumentException("Object is not a RGBAColor")
} }
if (red % 1.0 == 0.0 && green % 1.0 == 0.0 && blue % 1.0 == 0.0 && alpha % 1.0 == 0.0) { if (red % 1.0 == 0.0 && green % 1.0 == 0.0 && blue % 1.0 == 0.0 && alpha % 1.0 == 0.0) {
return Color( return RGBAColor(
red.toFloat() / 255f, red.toFloat() / 255f,
green.toFloat() / 255f, green.toFloat() / 255f,
blue.toFloat() / 255f, blue.toFloat() / 255f,
alpha.toFloat() / 255f, alpha.toFloat() / 255f,
) )
} else { } else {
return Color( return RGBAColor(
red.toFloat(), red.toFloat(),
green.toFloat(), green.toFloat(),
blue.toFloat(), blue.toFloat(),
@ -83,10 +83,11 @@ object ColorTypeAdapter : TypeAdapter<Color>() {
} }
} }
JsonToken.NUMBER -> return Color(`in`.nextInt()) JsonToken.NUMBER -> return RGBAColor.rgb(`in`.nextInt())
JsonToken.STRING -> { JsonToken.STRING -> {
val name = `in`.nextString() val name = `in`.nextString()
return Color.PRE_DEFINED_MAP[name] ?: throw IllegalArgumentException("Unknown pre defined color name $name") //return RGBAColor.PRE_DEFINED_MAP[name] ?: throw IllegalArgumentException("Unknown pre defined RGBAColor name $name")
TODO()
} }
else -> throw IllegalArgumentException("Expected array, object or number; got $type") else -> throw IllegalArgumentException("Expected array, object or number; got $type")

View File

@ -3,11 +3,11 @@ package ru.dbotthepony.kstarbound.io.json
import com.google.gson.TypeAdapter import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.ndouble.Vector4d import ru.dbotthepony.kvector.vector.Vector4d
import ru.dbotthepony.kvector.vector.nfloat.Vector2f import ru.dbotthepony.kvector.vector.Vector2f
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.Vector2i
import ru.dbotthepony.kvector.vector.nint.Vector4i import ru.dbotthepony.kvector.vector.Vector4i
object Vector4iTypeAdapter : TypeAdapter<Vector4i>() { object Vector4iTypeAdapter : TypeAdapter<Vector4i>() {
override fun write(out: JsonWriter, value: Vector4i) { override fun write(out: JsonWriter, value: Vector4i) {

View File

@ -13,8 +13,6 @@ import com.kenai.jffi.ClosureManager
import com.kenai.jffi.MemoryIO import com.kenai.jffi.MemoryIO
import com.kenai.jffi.Type import com.kenai.jffi.Type
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
import jnr.ffi.Memory
import jnr.ffi.NativeType
import jnr.ffi.Pointer import jnr.ffi.Pointer
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import org.lwjgl.system.MemoryStack import org.lwjgl.system.MemoryStack
@ -22,9 +20,10 @@ import org.lwjgl.system.MemoryUtil
import ru.dbotthepony.kstarbound.RegistryObject import ru.dbotthepony.kstarbound.RegistryObject
import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.io.json.InternedJsonElementAdapter import ru.dbotthepony.kstarbound.io.json.InternedJsonElementAdapter
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.api.IStruct2i
import ru.dbotthepony.kvector.vector.nint.Vector3i import ru.dbotthepony.kvector.api.IStruct3i
import ru.dbotthepony.kvector.vector.nint.Vector4i import ru.dbotthepony.kvector.api.IStruct4i
import ru.dbotthepony.kvector.vector.Vector2i
import java.io.Closeable import java.io.Closeable
import java.lang.ref.Cleaner import java.lang.ref.Cleaner
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@ -758,7 +757,7 @@ class LuaState private constructor(private val pointer: Pointer, val stringInter
LuaJNR.INSTANCE.lua_pushboolean(this.pointer, if (value) 1 else 0) LuaJNR.INSTANCE.lua_pushboolean(this.pointer, if (value) 1 else 0)
} }
fun push(value: Vector4i) { fun push(value: IStruct4i) {
pushTable(arraySize = 4) pushTable(arraySize = 4)
val table = stackTop val table = stackTop
val (x, y, z, w) = value val (x, y, z, w) = value
@ -780,7 +779,7 @@ class LuaState private constructor(private val pointer: Pointer, val stringInter
setTableValue(table) setTableValue(table)
} }
fun push(value: Vector3i) { fun push(value: IStruct3i) {
pushTable(arraySize = 3) pushTable(arraySize = 3)
val table = stackTop val table = stackTop
val (x, y, z) = value val (x, y, z) = value
@ -798,7 +797,7 @@ class LuaState private constructor(private val pointer: Pointer, val stringInter
setTableValue(table) setTableValue(table)
} }
fun push(value: Vector2i) { fun push(value: IStruct2i) {
pushTable(arraySize = 2) pushTable(arraySize = 2)
val table = stackTop val table = stackTop
val (x, y) = value val (x, y) = value

View File

@ -3,7 +3,7 @@ package ru.dbotthepony.kstarbound.math
import ru.dbotthepony.kstarbound.world.ChunkPos import ru.dbotthepony.kstarbound.world.ChunkPos
import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.util2d.AABB
import ru.dbotthepony.kvector.util2d.AABBi import ru.dbotthepony.kvector.util2d.AABBi
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.Vector2i
fun AABB.encasingIntAABB(): AABBi { fun AABB.encasingIntAABB(): AABBi {
return AABBi( return AABBi(

View File

@ -6,7 +6,7 @@ import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kstarbound.io.json.Vector2dTypeAdapter import ru.dbotthepony.kstarbound.io.json.Vector2dTypeAdapter
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
class Poly(vararg points: Vector2d) { class Poly(vararg points: Vector2d) {
val points: List<Vector2d> = ImmutableList.copyOf(points) val points: List<Vector2d> = ImmutableList.copyOf(points)

View File

@ -5,28 +5,17 @@ import ru.dbotthepony.kbox2d.api.FixtureDef
import ru.dbotthepony.kbox2d.collision.shapes.PolygonShape import ru.dbotthepony.kbox2d.collision.shapes.PolygonShape
import ru.dbotthepony.kbox2d.dynamics.B2Fixture import ru.dbotthepony.kbox2d.dynamics.B2Fixture
import ru.dbotthepony.kstarbound.defs.tile.LiquidDefinition import ru.dbotthepony.kstarbound.defs.tile.LiquidDefinition
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
import ru.dbotthepony.kstarbound.defs.tile.TILE_COLOR_VARIANTS
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
import ru.dbotthepony.kstarbound.util.NotNullTwoDimensionalArray
import ru.dbotthepony.kstarbound.util.TwoDimensionalArray import ru.dbotthepony.kstarbound.util.TwoDimensionalArray
import ru.dbotthepony.kstarbound.world.entities.Entity import ru.dbotthepony.kstarbound.world.entities.Entity
import ru.dbotthepony.kstarbound.world.phys.RectTileFlooderDepthFirst import ru.dbotthepony.kstarbound.world.phys.RectTileFlooderDepthFirst
import ru.dbotthepony.kstarbound.world.phys.RectTileFlooderSizeFirst import ru.dbotthepony.kstarbound.world.phys.RectTileFlooderSizeFirst
import ru.dbotthepony.kvector.arrays.Object2DArray
import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.util2d.AABB
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.HashSet import kotlin.collections.HashSet
private fun ccwSortScore(point: Vector2d, axis: Vector2d): Double {
if (point.x > 0.0) {
return point.dot(axis)
} else {
return -2 - point.dot(axis)
}
}
/** /**
* Чанк мира * Чанк мира
* *
@ -111,117 +100,6 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
} }
inner class TileLayer : IMutableTileChunk { inner class TileLayer : IMutableTileChunk {
inner class TileState(def: TileDefinition? = null) : IMutableTileState {
override var material: TileDefinition? = def
set(value) {
if (value !== field) {
field = value
color = 0
hueShift = 0f
collisionChangeset++
this@TileLayer.changeset++
this@Chunk.changeset++
this@Chunk.tileChangeset++
markPhysicsDirty()
}
}
override var color = 0
set(value) {
val material = material
if (material == null) {
field = 0
return
}
if (value != field) {
if (!material.renderParameters.multiColored) {
throw IllegalStateException("${material.materialName} can't be colored")
}
if (value !in 0 until TILE_COLOR_VARIANTS) {
throw IndexOutOfBoundsException("Tile variant $value is out of possible range 0 to $TILE_COLOR_VARIANTS")
}
field = value
this@TileLayer.changeset++
this@Chunk.changeset++
this@Chunk.tileChangeset++
}
}
override var hueShift = 0f
set(value) {
var newValue = value % 360f
if (newValue < 0f) {
newValue += 360f
}
if (newValue != field) {
field = newValue
this@TileLayer.changeset++
this@Chunk.changeset++
this@Chunk.tileChangeset++
}
}
override var modifierHueShift = 0f
set(value) {
var newValue = value % 360f
if (newValue < 0f) {
newValue += 360f
}
if (newValue != field) {
field = newValue
this@TileLayer.changeset++
this@Chunk.changeset++
this@Chunk.tileChangeset++
}
}
override var modifier: MaterialModifier? = null
set(value) {
if (value != field) {
field = value
modifierHueShift = 0f
this@TileLayer.changeset++
this@Chunk.changeset++
this@Chunk.tileChangeset++
}
}
override fun equals(other: Any?): Boolean {
return other is Chunk<*, *>.TileLayer.TileState &&
other.color == color &&
other.modifier === modifier &&
other.modifierHueShift == modifierHueShift &&
other.hueShift == hueShift &&
other.material === material
}
override fun toString(): String {
return "TileState[${this@TileLayer}, material = ${material?.materialName}, color = $color, modifier = ${modifier?.modName}]"
}
override fun hashCode(): Int {
var result = this@TileLayer.hashCode()
result = 31 * result + material.hashCode()
result = 31 * result + color
result = 31 * result + (modifier?.hashCode() ?: 0)
return result
}
}
/** /**
* Возвращает счётчик изменений этого слоя * Возвращает счётчик изменений этого слоя
*/ */
@ -284,100 +162,6 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
} }
} }
} }
/*
val seen = BooleanArray(CHUNK_SIZE * CHUNK_SIZE)
for (y in 0 .. CHUNK_SIZE_FF) {
for (x in 0 .. CHUNK_SIZE_FF) {
if (!seen[x or (y shl CHUNK_SHIFT)] && tiles[x or (y shl CHUNK_SHIFT)] != null) {
val exposed = TileFlooder(tiles, seen, x, y).exposed
if (exposed.size > 0) {
val vertices = ArrayList<Vector2d>()
var centroid = Vector2d.ZERO
for (pos in exposed) {
centroid += pos.pos
}
centroid /= exposed.size.toDouble()
for (pos in exposed) {
if (pos.left) {
vertices.addU(pos.pos + Vector2d(-0.5, -0.5))
vertices.addU(pos.pos + Vector2d(-0.5, 0.5))
}
if (pos.up) {
vertices.addU(pos.pos + Vector2d(-0.5, 0.5))
vertices.addU(pos.pos + Vector2d(0.5, 0.5))
}
if (pos.right) {
vertices.addU(pos.pos + Vector2d(0.5, 0.5))
vertices.addU(pos.pos + Vector2d(0.5, -0.5))
}
if (pos.down) {
vertices.addU(pos.pos + Vector2d(0.5, -0.5))
vertices.addU(pos.pos + Vector2d(-0.5, -0.5))
}
}
for (i in vertices.indices) {
vertices[i] -= centroid
}
vertices.sortWith { a, b ->
val scoreA = ccwSortScore(a.normalized, Vector2d.POSITIVE_Y)
val scoreB = ccwSortScore(b.normalized, Vector2d.POSITIVE_Y)
if (scoreA == scoreB) {
return@sortWith 0
} else if (scoreA > scoreB) {
return@sortWith 1
} else {
return@sortWith -1
}
}
for (i in vertices.indices) {
vertices[i] += centroid
}
val deflated = ArrayList<Vector2d>()
var edge = vertices[0]
deflated.add(edge)
for (i in 1 until vertices.size) {
if (vertices[i].x == edge.x) {
// expand along X axis
continue
} else if (vertices[i].y == edge.y) {
// expand along Y axis
continue
}
// completely different direction
if (deflated.indexOf(vertices[i - 1]) == -1)
deflated.add(vertices[i - 1])
if (deflated.indexOf(vertices[i]) == -1)
deflated.add(vertices[i])
edge = vertices[i]
}
collisionChains.add(body.createFixture(FixtureDef(
shape = ChainShape().also { it.createLoop(vertices) },
friction = 0.4,
)))
}
}
}
}*/
} }
/** /**
@ -409,12 +193,20 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
/** /**
* Хранит тайлы как x + y * CHUNK_SIZE * Хранит тайлы как x + y * CHUNK_SIZE
*/ */
private val tiles: NotNullTwoDimensionalArray<TileState> = NotNullTwoDimensionalArray(CHUNK_SIZE, CHUNK_SIZE) { _, _ -> TileState() } private val tiles: Object2DArray<TileState> = Object2DArray(CHUNK_SIZE, CHUNK_SIZE, TileState.EMPTY)
override operator fun get(x: Int, y: Int): TileState { override fun getTile(x: Int, y: Int): TileState {
return tiles[x, y] return tiles[x, y]
} }
override fun setTile(x: Int, y: Int, value: TileState) {
tiles[x, y] = value
tileChangeset++
changeset++
collisionChangeset++
this@Chunk.changeset++
}
override fun randomLongFor(x: Int, y: Int): Long { override fun randomLongFor(x: Int, y: Int): Long {
return super.randomLongFor(x, y) xor world.seed return super.randomLongFor(x, y) xor world.seed
} }

View File

@ -1,8 +1,7 @@
package ru.dbotthepony.kstarbound.world package ru.dbotthepony.kstarbound.world
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier import ru.dbotthepony.kvector.api.IStruct2i
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition import ru.dbotthepony.kvector.vector.Vector2i
import ru.dbotthepony.kvector.vector.nint.Vector2i
const val CHUNK_SHIFT = 5 const val CHUNK_SHIFT = 5
const val CHUNK_SIZE = 1 shl CHUNK_SHIFT // 32 const val CHUNK_SIZE = 1 shl CHUNK_SHIFT // 32
@ -11,48 +10,6 @@ const val CHUNK_SIZE_FF = CHUNK_SIZE - 1
const val CHUNK_SIZEf = CHUNK_SIZE.toFloat() const val CHUNK_SIZEf = CHUNK_SIZE.toFloat()
const val CHUNK_SIZEd = CHUNK_SIZE.toDouble() const val CHUNK_SIZEd = CHUNK_SIZE.toDouble()
interface ITileState {
val material: TileDefinition?
val modifier: MaterialModifier?
val color: Int
val hueShift: Float
val modifierHueShift: Float
}
interface IMutableTileState : ITileState {
override var material: TileDefinition?
override var modifier: MaterialModifier?
override var color: Int
override var hueShift: Float
override var modifierHueShift: Float
/**
* Выставляет hue shift как байтовое значение в диапазоне 0 .. 255
*/
fun setHueShift(value: Int) {
if (value < 0) {
hueShift = 0f
} else if (value > 255) {
hueShift = 360f
} else {
hueShift = (value / 255f) * 360f
}
}
/**
* Выставляет hue shift как байтовое значение в диапазоне 0 .. 255
*/
fun setModifierHueShift(value: Int) {
if (value < 0) {
modifierHueShift = 0f
} else if (value > 255) {
modifierHueShift = 360f
} else {
modifierHueShift = (value / 255f) * 360f
}
}
}
interface ITileMap { interface ITileMap {
/** /**
* Относительная проверка находится ли координата вне границ чанка * Относительная проверка находится ли координата вне границ чанка
@ -63,52 +20,49 @@ interface ITileMap {
} }
/** /**
* Предоставляет интерфейс для доступа к тайлам в чанке * Предоставляет интерфейс для доступа к тайлам
*/ */
interface ITileGetter : ITileMap { interface ITileGetter : ITileMap {
/** /**
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка * Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
*/ */
operator fun get(x: Int, y: Int): ITileState fun getTile(x: Int, y: Int): TileState
/** /**
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка * Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
*/ */
operator fun get(pos: Vector2i) = get(pos.x, pos.y) fun getTile(pos: IStruct2i) = getTile(pos.component1(), pos.component2())
}
/** interface ITileSetter : ITileMap {
* Возвращает итератор пар <Vector2i, Тайл?> fun setTile(x: Int, y: Int, value: TileState)
* fun setTile(pos: IStruct2i, value: TileState) = setTile(pos.component1(), pos.component2(), value)
* Вектор имеет ОТНОСИТЕЛЬНЫЕ значения внутри самого чанка }
*/
val posToTile: Iterator<Pair<Vector2i, ITileState>> get() {
return object : Iterator<Pair<Vector2i, ITileState>> {
private var x = 0
private var y = 0
private fun idx() = x + CHUNK_SIZE * y fun ITileGetter.iterate(fromX: Int = 0, fromY: Int = 0, toX: Int = fromX + CHUNK_SIZE, toY: Int = fromY + CHUNK_SIZE): Iterator<Pair<Vector2i, TileState>> {
return object : Iterator<Pair<Vector2i, TileState>> {
private var x = fromX
private var y = fromY
override fun hasNext(): Boolean { override fun hasNext(): Boolean {
return idx() < CHUNK_SIZE * CHUNK_SIZE return x < toX && y < toY
}
override fun next(): Pair<Vector2i, TileState> {
if (!hasNext())
throw NoSuchElementException()
val tile = getTile(x, y)
val pos = Vector2i(x, y)
x++
if (x >= toX) {
y++
x = 0
} }
override fun next(): Pair<Vector2i, ITileState> { return pos to tile
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
}
} }
} }
} }
@ -158,37 +112,4 @@ interface IChunkPositionable : ITileMap {
} }
interface ITileChunk : ITileGetter, IChunkPositionable interface ITileChunk : ITileGetter, IChunkPositionable
interface IMutableTileChunk : ITileChunk, ITileSetter
interface IMutableTileChunk : ITileChunk {
override fun get(x: Int, y: Int): IMutableTileState
override fun get(pos: Vector2i): IMutableTileState {
return get(pos.x, pos.y)
}
}
object EmptyTileState : IMutableTileState {
override var material: TileDefinition?
get() = null
set(value) {}
override var modifier: MaterialModifier?
get() = null
set(value) {}
override var color: Int
get() = 0
set(value) {}
override var hueShift: Float
get() = 0f
set(value) {}
override var modifierHueShift: Float
get() = 0f
set(value) {}
}
object EmptyTileChunk : IMutableTileChunk {
override val pos: ChunkPos
get() = ChunkPos.ZERO
override fun get(x: Int, y: Int): IMutableTileState {
return EmptyTileState
}
}

View File

@ -3,7 +3,7 @@ package ru.dbotthepony.kstarbound.world
import ru.dbotthepony.kstarbound.math.roundByAbsoluteValue import ru.dbotthepony.kstarbound.math.roundByAbsoluteValue
import ru.dbotthepony.kvector.api.IStruct2d import ru.dbotthepony.kvector.api.IStruct2d
import ru.dbotthepony.kvector.api.IStruct2i import ru.dbotthepony.kvector.api.IStruct2i
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.Vector2i
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
private fun circulate(value: Int, bounds: Int): Int { private fun circulate(value: Int, bounds: Int): Int {

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.kstarbound.world package ru.dbotthepony.kstarbound.world
import ru.dbotthepony.kstarbound.util.NotNullTwoDimensionalArray import ru.dbotthepony.kstarbound.util.NotNullTwoDimensionalArray
import ru.dbotthepony.kstarbound.util.TwoDimensionalArray import ru.dbotthepony.kvector.arrays.Object2DArray
/** /**
* Предоставляет доступ к чанку и его соседям * Предоставляет доступ к чанку и его соседям
@ -31,13 +31,13 @@ class RigidTileView(
override val pos: ChunkPos = view.pos override val pos: ChunkPos = view.pos
private val memory: NotNullTwoDimensionalArray<ITileState> private val memory: Object2DArray<TileState>
init { init {
memory = NotNullTwoDimensionalArray(CHUNK_SIZE * 3, CHUNK_SIZE * 3) { a, b -> view[a - CHUNK_SIZE, b - CHUNK_SIZE] } memory = Object2DArray(CHUNK_SIZE * 3, CHUNK_SIZE * 3) { a, b -> view.getTile(a - CHUNK_SIZE, b - CHUNK_SIZE) }
} }
override fun get(x: Int, y: Int): ITileState { override fun getTile(x: Int, y: Int): TileState {
return memory[x + CHUNK_SIZE, y + CHUNK_SIZE] return memory[x + CHUNK_SIZE, y + CHUNK_SIZE]
} }
} }

View File

@ -0,0 +1,86 @@
package ru.dbotthepony.kstarbound.world
import ru.dbotthepony.kstarbound.RegistryObject
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
import java.io.DataInputStream
enum class TileColor {
DEFAULT,
RED,
BLUE,
GREEN,
YELLOW,
BROWN,
PURPLE,
BLACK,
WHITE;
companion object {
private val values = values()
fun of(index: Int): TileColor {
return values.getOrElse(index) { DEFAULT }
}
}
}
data class TileState(
val material: TileDefinition? = null,
val modifier: MaterialModifier? = null,
val color: TileColor = TileColor.DEFAULT,
val hueShift: Float = 0f,
val modifierHueShift: Float = 0f,
) {
private fun with(
material: TileDefinition? = this.material,
modifier: MaterialModifier? = this.modifier,
color: TileColor = this.color,
hueShift: Float = this.hueShift,
modifierHueShift: Float = this.modifierHueShift,
): TileState {
if (this.material === material && this.modifier === modifier && this.color == color && this.hueShift == hueShift && this.modifierHueShift == modifierHueShift) {
return this
} else {
return TileState(material, modifier, color, hueShift, modifierHueShift)
}
}
fun withHueShift(hueShift: Int): TileState {
if (hueShift < 0) {
return with(hueShift = 0f)
} else if (hueShift >= 255) {
return with(hueShift = 360f)
} else {
return with(hueShift = hueShift / 255f * 360f)
}
}
fun withModifierHueShift(hueShift: Int): TileState {
if (hueShift < 0) {
return with(modifierHueShift = 0f)
} else if (hueShift >= 255) {
return with(modifierHueShift = 360f)
} else {
return with(modifierHueShift = hueShift / 255f * 360f)
}
}
companion object {
val EMPTY = TileState()
fun read(
materialAccess: (Int) -> RegistryObject<TileDefinition>?,
modifierAccess: (Int) -> RegistryObject<MaterialModifier>?,
stream: DataInputStream
): TileState {
val mat = materialAccess(stream.readUnsignedShort())
val hue = stream.read()
val color = stream.read()
val mod = modifierAccess(stream.readUnsignedShort())
val modHue = stream.read()
return TileState(mat?.value, mod?.value, TileColor.of(color), hue / 255f * 360f, modHue / 255f * 360f)
}
}
}

View File

@ -1,7 +1,5 @@
package ru.dbotthepony.kstarbound.world package ru.dbotthepony.kstarbound.world
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
/** /**
* Предоставляет доступ к чанку и его соседям * Предоставляет доступ к чанку и его соседям
* *
@ -23,38 +21,38 @@ open class TileView(
open val bottomLeft: ITileChunk?, open val bottomLeft: ITileChunk?,
open val bottomRight: ITileChunk?, open val bottomRight: ITileChunk?,
) : ITileChunk { ) : ITileChunk {
override fun get(x: Int, y: Int): ITileState { override fun getTile(x: Int, y: Int): TileState {
if (x in 0 ..CHUNK_SIZE_FF) { if (x in 0 ..CHUNK_SIZE_FF) {
if (y in 0 ..CHUNK_SIZE_FF) { if (y in 0 ..CHUNK_SIZE_FF) {
return center?.get(x, y) ?: EmptyTileState return center?.getTile(x, y) ?: TileState.EMPTY
} }
if (y < 0) { if (y < 0) {
return bottom?.get(x, y + CHUNK_SIZE) ?: EmptyTileState return bottom?.getTile(x, y + CHUNK_SIZE) ?: TileState.EMPTY
} else { } else {
return top?.get(x, y - CHUNK_SIZE) ?: EmptyTileState return top?.getTile(x, y - CHUNK_SIZE) ?: TileState.EMPTY
} }
} }
if (x < 0) { if (x < 0) {
if (y in 0 ..CHUNK_SIZE_FF) { if (y in 0 ..CHUNK_SIZE_FF) {
return left?.get(x + CHUNK_SIZE, y) ?: EmptyTileState return left?.getTile(x + CHUNK_SIZE, y) ?: TileState.EMPTY
} }
if (y < 0) { if (y < 0) {
return bottomLeft?.get(x + CHUNK_SIZE, y + CHUNK_SIZE) ?: EmptyTileState return bottomLeft?.getTile(x + CHUNK_SIZE, y + CHUNK_SIZE) ?: TileState.EMPTY
} else { } else {
return topLeft?.get(x + CHUNK_SIZE, y - CHUNK_SIZE) ?: EmptyTileState return topLeft?.getTile(x + CHUNK_SIZE, y - CHUNK_SIZE) ?: TileState.EMPTY
} }
} else { } else {
if (y in 0 ..CHUNK_SIZE_FF) { if (y in 0 ..CHUNK_SIZE_FF) {
return right?.get(x - CHUNK_SIZE, y) ?: EmptyTileState return right?.getTile(x - CHUNK_SIZE, y) ?: TileState.EMPTY
} }
if (y < 0) { if (y < 0) {
return bottomRight?.get(x - CHUNK_SIZE, y + CHUNK_SIZE) ?: EmptyTileState return bottomRight?.getTile(x - CHUNK_SIZE, y + CHUNK_SIZE) ?: TileState.EMPTY
} else { } else {
return topRight?.get(x - CHUNK_SIZE, y - CHUNK_SIZE) ?: EmptyTileState return topRight?.getTile(x - CHUNK_SIZE, y - CHUNK_SIZE) ?: TileState.EMPTY
} }
} }
} }
@ -74,7 +72,7 @@ class MutableTileView(
override val bottomLeft: IMutableTileChunk?, override val bottomLeft: IMutableTileChunk?,
override val bottomRight: IMutableTileChunk?, override val bottomRight: IMutableTileChunk?,
) : TileView(pos, center, right, top, topRight, topLeft, left, bottom, bottomLeft, bottomRight), IMutableTileChunk { ) : TileView(pos, center, right, top, topRight, topLeft, left, bottom, bottomLeft, bottomRight), IMutableTileChunk {
override fun get(x: Int, y: Int): IMutableTileState { override fun setTile(x: Int, y: Int, value: TileState) {
return super<TileView>.get(x, y) as IMutableTileState TODO()
} }
} }

View File

@ -1,8 +1,6 @@
package ru.dbotthepony.kstarbound.world package ru.dbotthepony.kstarbound.world
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import it.unimi.dsi.fastutil.objects.Object2DoubleAVLTreeMap
import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
import ru.dbotthepony.kbox2d.api.ContactImpulse import ru.dbotthepony.kbox2d.api.ContactImpulse
@ -15,35 +13,24 @@ import ru.dbotthepony.kbox2d.dynamics.contact.AbstractContact
import ru.dbotthepony.kstarbound.METRES_IN_STARBOUND_UNIT import ru.dbotthepony.kstarbound.METRES_IN_STARBOUND_UNIT
import ru.dbotthepony.kstarbound.math.* import ru.dbotthepony.kstarbound.math.*
import ru.dbotthepony.kstarbound.util.Timer import ru.dbotthepony.kstarbound.util.Timer
import ru.dbotthepony.kstarbound.world.entities.CollisionResolution
import ru.dbotthepony.kstarbound.world.entities.Entity import ru.dbotthepony.kstarbound.world.entities.Entity
import ru.dbotthepony.kvector.narray.Double2Dimensional import ru.dbotthepony.kvector.arrays.Double2DArray
import ru.dbotthepony.kvector.narray.Int2Dimensional import ru.dbotthepony.kvector.arrays.Int2DArray
import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.util2d.AABB
import ru.dbotthepony.kvector.util2d.AABBi import ru.dbotthepony.kvector.util2d.AABBi
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.Vector2i
import java.util.LinkedList import java.util.LinkedList
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.absoluteValue
import kotlin.math.cos import kotlin.math.cos
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.math.sin import kotlin.math.sin
const val EARTH_FREEFALL_ACCELERATION = 9.8312 / METRES_IN_STARBOUND_UNIT const val EARTH_FREEFALL_ACCELERATION = 9.8312 / METRES_IN_STARBOUND_UNIT
data class WorldSweepResult(
val hitPosition: Vector2d,
val collisionTime: Double,
val hitAnything: Boolean,
val hitNormal: Vector2d
)
private const val EPSILON = 0.00001
data class RayCastResult( data class RayCastResult(
val traversedTiles: List<Pair<Vector2i, ITileState>>, val traversedTiles: List<Pair<Vector2i, TileState>>,
val hitTile: Pair<Vector2i, ITileState>?, val hitTile: Pair<Vector2i, TileState>?,
val fraction: Double val fraction: Double
) )
@ -101,7 +88,7 @@ enum class RayFilterResult {
} }
fun interface TileRayFilter { fun interface TileRayFilter {
fun test(state: ITileState, fraction: Double, position: Vector2i): RayFilterResult fun test(state: TileState, fraction: Double, position: Vector2i): RayFilterResult
} }
/** /**
@ -373,12 +360,12 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
return lastChunk return lastChunk
} }
fun getTile(pos: Vector2i): ITileState? { fun getTile(pos: Vector2i): TileState? {
return get(ChunkPos.fromTilePosition(pos))?.foreground?.get(ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y)) return get(ChunkPos.fromTilePosition(pos))?.foreground?.getTile(ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y))
} }
fun getBackgroundTile(pos: Vector2i): ITileState? { fun getBackgroundTile(pos: Vector2i): TileState? {
return get(ChunkPos.fromTilePosition(pos))?.background?.get(ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y)) return get(ChunkPos.fromTilePosition(pos))?.background?.getTile(ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y))
} }
/** /**
@ -397,16 +384,16 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
val dir = rayEnd - rayStart val dir = rayEnd - rayStart
val inc = 0.5 / dir.length val inc = 0.5 / dir.length
val tiles = LinkedList<Pair<Vector2i, ITileState>>() val tiles = LinkedList<Pair<Vector2i, TileState>>()
var prev = Vector2i(Int.MIN_VALUE, Int.MAX_VALUE) var prev = Vector2i(Int.MIN_VALUE, Int.MAX_VALUE)
var hitTile: Pair<Vector2i, ITileState>? = null var hitTile: Pair<Vector2i, TileState>? = null
while (t < 1.0) { while (t < 1.0) {
val (x, y) = rayStart + dir * t val (x, y) = rayStart + dir * t
val tilePos = Vector2i(x.roundToInt(), y.roundToInt()) val tilePos = Vector2i(x.roundToInt(), y.roundToInt())
if (tilePos != prev) { if (tilePos != prev) {
val tile = getTile(tilePos) ?: EmptyTileState val tile = getTile(tilePos) ?: TileState.EMPTY
when (filter.test(tile, t, tilePos)) { when (filter.test(tile, t, tilePos)) {
RayFilterResult.HIT -> { RayFilterResult.HIT -> {
@ -442,7 +429,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
length: Double, length: Double,
filter: TileRayFilter = AnythingRayFilter filter: TileRayFilter = AnythingRayFilter
): RayCastResult { ): RayCastResult {
return castRayNaive(rayPosition, rayPosition + direction.normalized * length, filter) return castRayNaive(rayPosition, rayPosition + direction.unitVector * length, filter)
} }
/** /**
@ -490,8 +477,8 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
intensity: Double, intensity: Double,
falloffByTile: Double = 2.0, falloffByTile: Double = 2.0,
falloffByTravel: Double = 1.0, falloffByTravel: Double = 1.0,
): Double2Dimensional { ): Double2DArray {
val combinedResult = Double2Dimensional(intensity.roundToInt() * 2, intensity.roundToInt() * 2) val combinedResult = Double2DArray.allocate(intensity.roundToInt() * 2, intensity.roundToInt() * 2)
val baselineX = position.x.roundToInt() - intensity.roundToInt() val baselineX = position.x.roundToInt() - intensity.roundToInt()
val baselineY = position.y.roundToInt() - intensity.roundToInt() val baselineY = position.y.roundToInt() - intensity.roundToInt()
@ -554,7 +541,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
intensity: Double, intensity: Double,
falloffByTile: Double = 2.0, falloffByTile: Double = 2.0,
falloffByTravel: Double = 2.0, falloffByTravel: Double = 2.0,
): Double2Dimensional { ): Double2DArray {
return CachedGetter().rayLightCircleNaive(position, intensity, falloffByTile, falloffByTravel) return CachedGetter().rayLightCircleNaive(position, intensity, falloffByTile, falloffByTravel)
} }
@ -600,12 +587,12 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
return RigidTileView(getBackgroundView(pos)) return RigidTileView(getBackgroundView(pos))
} }
fun getTile(pos: Vector2i): ITileState? { fun getTile(pos: Vector2i): TileState? {
return get(ChunkPos.fromTilePosition(pos))?.foreground?.get(ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y)) return get(ChunkPos.fromTilePosition(pos))?.foreground?.getTile(ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y))
} }
fun getBackgroundTile(pos: Vector2i): ITileState? { fun getBackgroundTile(pos: Vector2i): TileState? {
return get(ChunkPos.fromTilePosition(pos))?.background?.get(ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y)) return get(ChunkPos.fromTilePosition(pos))?.background?.getTile(ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y))
} }
/** /**
@ -642,168 +629,6 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
return output return output
} }
/**
* Производит проверку на пересечение [worldaabb] с геометрией мира при попытке пройти в [_deltaMovement]
*/
fun sweep(
worldaabb: AABB,
_deltaMovement: Vector2d,
collisionResolution: CollisionResolution,
delta: Double
): WorldSweepResult {
var deltaMovement = _deltaMovement
val potentialAABB = worldaabb + deltaMovement
val combined = worldaabb.combine(potentialAABB)
val collected = collect((combined).encasingChunkPosAABB())
.map { it.foreground.collisionLayers() }
.flatten()
.sortedWith { o1, o2 ->
val a = o1.distance(worldaabb)
val b = o2.distance(worldaabb)
if (a == b)
return@sortedWith 0
if (a > b)
return@sortedWith 1
return@sortedWith -1
}
var hitAnything = false
var hitNormal = Vector2d.ZERO
if (collected.isNotEmpty()) {
for (iteration in 0 .. 100) {
var collided = false
for (aabb in collected) {
// залез в блоки?
/*if (potentialAABB.intersectWeak(aabb)) {
val push = worldaabb.pushOutFrom(aabb)
println("into tiles")
if (push.length > 0.0) {
if (iteration == 0) {
collided = true
continue
} else {
hitAnything = true
deltaMovement -= push * delta * 5.0
potentialAABB = worldaabb + deltaMovement
combined = worldaabb.combine(potentialAABB)
collided = true
continue
}
}
}*/
// ранний тест (отсечение заведомо не пересекаемой геометрии)
if (!aabb.intersect(combined)) {
continue
}
// обычный тест коллизии
val (normal, collisionTime) = worldaabb.sweep(aabb, deltaMovement)
if (collisionTime != 1.0) {
hitAnything = true
collided = true
hitNormal = normal
if (weakDoubleZeroing(collisionTime) == 0.0) {
// Мы ВПЛОТНУЮ стоим к другой геометрии (пересекаемся одной из осей)
deltaMovement = Vector2d.ZERO
} else {
val remainingTime = 1.0 - collisionTime
when (collisionResolution) {
CollisionResolution.STOP -> {
// val weak = weakDoubleZeroing(collisionTime, epsilon = EPSILON)
for (i in 100 downTo 1) {
val move = deltaMovement * collisionTime * (i / 100.0)
// сегодня, в программе
// погрешность плавающей запятой
if (!(worldaabb + move).intersect(aabb)) {
deltaMovement = move
break
} // ЭтО чО вАщЕ ТакОе?
}
}
CollisionResolution.PUSH -> {
var dot = deltaMovement.pseudoDot(normal)
val magnitude = deltaMovement.length * weakDoubleZeroing(remainingTime, epsilon = EPSILON)
if (dot > 0.0) {
dot = 1.0
} else {
dot = -1.0
}
deltaMovement = Vector2d(dot * normal.y * magnitude, dot * normal.x * magnitude)
}
CollisionResolution.SLIDE -> {
val dot = deltaMovement.pseudoDot(normal) * remainingTime
if (weakDoubleZeroing(dot) != 0.0) {
deltaMovement = Vector2d(dot * normal.y, dot * normal.x)
} else {
// Граничный случай: Направления идеально противоположны.
// Обрабатываем как CollisionResolution.STOP
// val weak = weakDoubleZeroing(collisionTime, epsilon = EPSILON)
for (i in 100 downTo 1) {
val move = deltaMovement * collisionTime * (i / 100.0)
// сегодня, в программе
// погрешность плавающей запятой
if (!(worldaabb + move).intersect(aabb)) {
deltaMovement = move
break
} // ЭтО чО вАщЕ ТакОе?
}
}
}
CollisionResolution.BOUNCE -> {
deltaMovement *= weakDoubleZeroing(remainingTime, epsilon = EPSILON)
if (normal.x.absoluteValue > 0.00001 && normal.y.absoluteValue > 0.00001) {
deltaMovement *= Vector2d.NEGATIVE_XY
} else if (normal.x.absoluteValue > 0.00001) {
deltaMovement *= Vector2d.NEGATIVE_X
} else if (normal.y.absoluteValue > 0.00001) {
deltaMovement *= Vector2d.NEGATIVE_Y
}
}
}
}
}
}
if (!collided) {
//println("resolved in $iteration")
break
}
}
}
return WorldSweepResult(
hitAnything = hitAnything,
hitNormal = hitNormal,
collisionTime = worldaabb.centre.distance(deltaMovement) / worldaabb.centre.distance(_deltaMovement),
hitPosition = deltaMovement,
)
}
/** /**
* Возвращает, застрянет ли сущность будет с коллизией [worldaabb] * Возвращает, застрянет ли сущность будет с коллизией [worldaabb]
*/ */
@ -840,7 +665,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
// Свет // Свет
private fun floodLightInto( private fun floodLightInto(
lightmap: Int2Dimensional, lightmap: Int2DArray,
view: RigidTileView, view: RigidTileView,
thisIntensity: Int, thisIntensity: Int,
lightBlockerStrength: Int, lightBlockerStrength: Int,
@ -853,7 +678,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
return 1 return 1
} }
val tile = view[worldPosX, worldPosY] val tile = view.getTile(worldPosX, worldPosY)
val newIntensity: Int val newIntensity: Int
@ -918,12 +743,12 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
lightPosition: Vector2i, lightPosition: Vector2i,
lightIntensity: Int, lightIntensity: Int,
lightBlockerStrength: Int = 4, lightBlockerStrength: Int = 4,
): Int2Dimensional { ): Int2DArray {
require(lightIntensity >= 1) { "Invalid light intensity $lightIntensity" } require(lightIntensity >= 1) { "Invalid light intensity $lightIntensity" }
require(lightBlockerStrength >= 1) { "Invalid light blocker strength $lightBlockerStrength" } require(lightBlockerStrength >= 1) { "Invalid light blocker strength $lightBlockerStrength" }
require(lightIntensity <= CHUNK_SIZE) { "Too intensive light! $lightIntensity" } require(lightIntensity <= CHUNK_SIZE) { "Too intensive light! $lightIntensity" }
val lightmap = Int2Dimensional(lightIntensity * 2 + 1, lightIntensity * 2 + 1) val lightmap = Int2DArray.allocate(lightIntensity * 2 + 1, lightIntensity * 2 + 1)
val view = getRigidForegroundView(ChunkPos.fromTilePosition(lightPosition)) val view = getRigidForegroundView(ChunkPos.fromTilePosition(lightPosition))

View File

@ -7,8 +7,8 @@ import ru.dbotthepony.kbox2d.collision.shapes.PolygonShape
import ru.dbotthepony.kbox2d.dynamics.B2Fixture import ru.dbotthepony.kbox2d.dynamics.B2Fixture
import ru.dbotthepony.kstarbound.world.World import ru.dbotthepony.kstarbound.world.World
import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.util2d.AABB
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.ndouble.times import ru.dbotthepony.kvector.vector.times
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
enum class Move { enum class Move {

View File

@ -4,7 +4,7 @@ import ru.dbotthepony.kstarbound.defs.DamageType
import ru.dbotthepony.kstarbound.world.Chunk import ru.dbotthepony.kstarbound.world.Chunk
import ru.dbotthepony.kstarbound.world.ChunkPos import ru.dbotthepony.kstarbound.world.ChunkPos
import ru.dbotthepony.kstarbound.world.World import ru.dbotthepony.kstarbound.world.World
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
/** /**
* Интерфейс служит лишь для убирания жёсткой зависимости от класса Entity * Интерфейс служит лишь для убирания жёсткой зависимости от класса Entity

View File

@ -3,7 +3,7 @@ package ru.dbotthepony.kstarbound.world.entities
import ru.dbotthepony.kbox2d.api.* import ru.dbotthepony.kbox2d.api.*
import ru.dbotthepony.kbox2d.dynamics.contact.AbstractContact import ru.dbotthepony.kbox2d.dynamics.contact.AbstractContact
import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.util2d.AABB
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
enum class CollisionResolution { enum class CollisionResolution {
STOP, STOP,
@ -74,7 +74,7 @@ abstract class MovementController<T : IEntity>(val entity: T) : IContactListener
*/ */
open val onGround: Boolean get() { open val onGround: Boolean get() {
for (contact in body.contactEdgeIterator) { for (contact in body.contactEdgeIterator) {
if (contact.contact.manifold.localNormal.dot(world.gravity.normalized) >= 0.97) { if (contact.contact.manifold.localNormal.dot(world.gravity.unitVector) >= 0.97) {
return true return true
} }
} }

View File

@ -4,11 +4,9 @@ import ru.dbotthepony.kbox2d.api.ContactImpulse
import ru.dbotthepony.kbox2d.api.FixtureDef import ru.dbotthepony.kbox2d.api.FixtureDef
import ru.dbotthepony.kbox2d.api.Manifold import ru.dbotthepony.kbox2d.api.Manifold
import ru.dbotthepony.kbox2d.collision.shapes.PolygonShape import ru.dbotthepony.kbox2d.collision.shapes.PolygonShape
import ru.dbotthepony.kbox2d.dynamics.B2Fixture
import ru.dbotthepony.kbox2d.dynamics.contact.AbstractContact import ru.dbotthepony.kbox2d.dynamics.contact.AbstractContact
import ru.dbotthepony.kstarbound.world.World import ru.dbotthepony.kstarbound.world.World
import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.vector.Vector2d
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
class PlayerMovementController(entity: PlayerEntity) : WalkableMovementController<PlayerEntity>(entity) { class PlayerMovementController(entity: PlayerEntity) : WalkableMovementController<PlayerEntity>(entity) {
public override var moveDirection = Move.STAND_STILL public override var moveDirection = Move.STAND_STILL

View File

@ -1,14 +1,13 @@
package ru.dbotthepony.kstarbound.world.phys package ru.dbotthepony.kstarbound.world.phys
import ru.dbotthepony.kstarbound.util.NotNullTwoDimensionalArray
import ru.dbotthepony.kstarbound.world.CHUNK_SHIFT import ru.dbotthepony.kstarbound.world.CHUNK_SHIFT
import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF
import ru.dbotthepony.kstarbound.world.Chunk import ru.dbotthepony.kstarbound.world.TileState
import ru.dbotthepony.kstarbound.world.ITileState import ru.dbotthepony.kvector.arrays.Object2DArray
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.vector.Vector2i
class RectTileFlooderDepthFirst( class RectTileFlooderDepthFirst(
private val tiles: NotNullTwoDimensionalArray<out ITileState>, private val tiles: Object2DArray<out TileState>,
private val seen: BooleanArray, private val seen: BooleanArray,
rootx: Int, rootx: Int,
rooty: Int rooty: Int

View File

@ -1,13 +1,13 @@
package ru.dbotthepony.kstarbound.world.phys package ru.dbotthepony.kstarbound.world.phys
import ru.dbotthepony.kstarbound.util.NotNullTwoDimensionalArray
import ru.dbotthepony.kstarbound.world.CHUNK_SHIFT import ru.dbotthepony.kstarbound.world.CHUNK_SHIFT
import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF
import ru.dbotthepony.kstarbound.world.ITileState import ru.dbotthepony.kstarbound.world.TileState
import ru.dbotthepony.kvector.vector.nint.Vector2i import ru.dbotthepony.kvector.arrays.Object2DArray
import ru.dbotthepony.kvector.vector.Vector2i
class RectTileFlooderSizeFirst( class RectTileFlooderSizeFirst(
private val tiles: NotNullTwoDimensionalArray<out ITileState>, private val tiles: Object2DArray<out TileState>,
private val seen: BooleanArray, private val seen: BooleanArray,
private val rootx: Int, private val rootx: Int,
private val rooty: Int private val rooty: Int

View File

@ -3,8 +3,8 @@ package ru.dbotthepony.kstarbound.world.phys
import ru.dbotthepony.kstarbound.util.NotNullTwoDimensionalArray import ru.dbotthepony.kstarbound.util.NotNullTwoDimensionalArray
import ru.dbotthepony.kstarbound.world.CHUNK_SHIFT import ru.dbotthepony.kstarbound.world.CHUNK_SHIFT
import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF
import ru.dbotthepony.kstarbound.world.ITileState import ru.dbotthepony.kstarbound.world.TileState
import ru.dbotthepony.kvector.vector.ndouble.Vector2d import ru.dbotthepony.kvector.vector.Vector2d
private data class TileExposure( private data class TileExposure(
var pos: Vector2d, var pos: Vector2d,
@ -15,7 +15,7 @@ private data class TileExposure(
) )
private class TileFlooder( private class TileFlooder(
private val tiles: NotNullTwoDimensionalArray<out ITileState>, private val tiles: NotNullTwoDimensionalArray<out TileState>,
private val seen: BooleanArray, private val seen: BooleanArray,
rootx: Int, rootx: Int,
rooty: Int rooty: Int

View File

@ -5,14 +5,7 @@ import org.junit.jupiter.api.Test
import ru.dbotthepony.kstarbound.math.* import ru.dbotthepony.kstarbound.math.*
import ru.dbotthepony.kstarbound.world.CHUNK_SIZE import ru.dbotthepony.kstarbound.world.CHUNK_SIZE
import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF
import ru.dbotthepony.kstarbound.world.CHUNK_SIZEd
import ru.dbotthepony.kstarbound.world.ChunkPos import ru.dbotthepony.kstarbound.world.ChunkPos
import ru.dbotthepony.kvector.matrix.multiplyMatrix
import ru.dbotthepony.kvector.narray.Double2Dimensional
import ru.dbotthepony.kvector.util2d.AABB
import ru.dbotthepony.kvector.util2d.AABBi
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
import ru.dbotthepony.kvector.vector.nint.Vector2i
object MathTests { object MathTests {
@Test @Test
@ -55,46 +48,6 @@ object MathTests {
check(roundTowardsPositiveInfinity(-1.6) == -1) check(roundTowardsPositiveInfinity(-1.6) == -1)
} }
@Test
@DisplayName("AABB Basic Math")
fun basicAABB() {
val a = AABB.rectangle(Vector2d.ZERO, 1.0, 1.0)
check(a.intersect(AABB.rectangle(Vector2d(-1.0), 1.0, 1.0)))
check(!a.intersectWeak(AABB.rectangle(Vector2d(-1.0), 1.0, 1.0)))
check(!a.intersect(AABB.rectangle(Vector2d(-2.0), 1.0, 1.0)))
check(!a.intersectWeak(AABB.rectangle(Vector2d(-2.0), 1.0, 1.0)))
check(a.intersect(AABB.rectangle(Vector2d(-0.9), 1.0, 1.0)))
check(a.intersectWeak(AABB.rectangle(Vector2d(-0.9), 1.0, 1.0)))
val bigA = AABB.rectangle(Vector2d.ZERO, 200.0, 200.0)
val smallB = AABB.rectangle(Vector2d.ZERO, 1.0, 1.0)
check(bigA.intersect(smallB))
check(smallB.intersect(bigA))
check(bigA.intersectWeak(smallB))
check(smallB.intersectWeak(bigA))
check(AABB.rectangle(Vector2d.ZERO, 1.0, 1.0) == AABB(Vector2d(-0.5, -0.5), Vector2d(0.5, 0.5)))
val combineA = AABB(Vector2d(0.0, 0.0), Vector2d(2.0, 2.0))
val combineB = AABB(Vector2d(2.0, 5.0), Vector2d(4.0, 6.0))
check(combineA.combine(combineB) == AABB(Vector2d(0.0, 0.0), Vector2d(4.0, 6.0))) { combineA.combine(combineB).toString() }
}
@Test
@DisplayName("AABB transformation to AABBi")
fun transformAABB() {
check(AABB.rectangle(Vector2d.ZERO, 2.0, 2.0).encasingIntAABB() == AABBi(Vector2i(-1, -1), Vector2i(1, 1)))
check(AABB.rectangle(Vector2d.ZERO, 2.0, 2.0).encasingChunkPosAABB() == AABBi(Vector2i(-1, -1), Vector2i(0, 0))) { AABB.rectangle(Vector2d.ZERO, 2.0, 2.0).encasingChunkPosAABB()}
check(AABB.rectangle(Vector2d(x = CHUNK_SIZEd - 0.1), 2.0, 2.0).encasingChunkPosAABB() == AABBi(Vector2i(0, -1), Vector2i(1, 0))) { "${AABB.rectangle(Vector2d(x = CHUNK_SIZEd - 0.1), 2.0, 2.0)} ${AABB.rectangle(Vector2d(x = CHUNK_SIZEd - 0.1), 2.0, 2.0).encasingChunkPosAABB()}" }
check(AABB.rectangle(Vector2d(x = CHUNK_SIZEd + 0.1), 2.0, 2.0).encasingChunkPosAABB() == AABBi(Vector2i(0, -1), Vector2i(1, 0))) { "${AABB.rectangle(Vector2d(x = CHUNK_SIZEd + 0.1), 2.0, 2.0)} ${AABB.rectangle(Vector2d(x = CHUNK_SIZEd + 0.1), 2.0, 2.0).encasingChunkPosAABB()}" }
}
@Test @Test
@DisplayName("ChunkPos class tests") @DisplayName("ChunkPos class tests")
fun chunkPosTests() { fun chunkPosTests() {
@ -115,46 +68,4 @@ object MathTests {
check(ChunkPos.fromTilePosition(0, -CHUNK_SIZE_FF) == ChunkPos(0, -1)) { ChunkPos.fromTilePosition(0, -CHUNK_SIZE_FF) } check(ChunkPos.fromTilePosition(0, -CHUNK_SIZE_FF) == ChunkPos(0, -1)) { ChunkPos.fromTilePosition(0, -CHUNK_SIZE_FF) }
check(ChunkPos.fromTilePosition(0, -CHUNK_SIZE) == ChunkPos(0, -2)) { ChunkPos.fromTilePosition(0, -CHUNK_SIZE) } check(ChunkPos.fromTilePosition(0, -CHUNK_SIZE) == ChunkPos(0, -2)) { ChunkPos.fromTilePosition(0, -CHUNK_SIZE) }
} }
@Test
fun testMatrixMult() {
val matrix1 = Double2Dimensional(4, 2)
val matrix2 = Double2Dimensional(3, 4)
matrix1[0, 0] = 3.0
matrix1[1, 0] = 2.0
matrix1[2, 0] = 1.0
matrix1[3, 0] = 5.0
matrix1[0, 1] = 9.0
matrix1[1, 1] = 1.0
matrix1[2, 1] = 3.0
matrix1[3, 1] = 0.0
matrix2[0, 0] = 2.0
matrix2[1, 0] = 9.0
matrix2[2, 0] = 0.0
matrix2[0, 1] = 1.0
matrix2[1, 1] = 3.0
matrix2[2, 1] = 5.0
matrix2[0, 2] = 2.0
matrix2[1, 2] = 4.0
matrix2[2, 2] = 7.0
matrix2[0, 3] = 8.0
matrix2[1, 3] = 1.0
matrix2[2, 3] = 5.0
val product = multiplyMatrix(matrix1, matrix2)
check(product[0, 0] == 50.0)
check(product[1, 0] == 42.0)
check(product[2, 0] == 42.0)
check(product[0, 1] == 25.0)
check(product[1, 1] == 96.0)
check(product[2, 1] == 26.0)
}
} }

View File

@ -1,31 +0,0 @@
package ru.dbotthepony.kstarbound.test
import jdk.jfr.Description
import org.junit.jupiter.api.Test
import ru.dbotthepony.kvector.matrix.nfloat.Matrix3f
object MatrixTest {
@Test
@Description("Matrix test")
fun test() {
val a = Matrix3f.rm(
4f, 2f, 0f,
0f, 8f, 1f,
0f, 1f, 0f
)
val b = Matrix3f.rm(
4f, 2f, 1f,
2f, 0f, 4f,
9f, 4f, 2f
)
val c = Matrix3f.rm(
20f, 8f, 12f,
25f, 4f, 34f,
2f, 0f, 4f
)
require(a * b == c) { "${a * b} != $c" }
}
}