More streamlining
This commit is contained in:
parent
96c88aa725
commit
ee21636529
@ -68,11 +68,11 @@ fun main() {
|
|||||||
|
|
||||||
for (y in 0 .. 31) {
|
for (y in 0 .. 31) {
|
||||||
for (x in 0 .. 31) {
|
for (x in 0 .. 31) {
|
||||||
val materialID = reader.readShort()
|
val materialID = reader.readUnsignedShort()
|
||||||
val getMat = Starbound.tilesAccessID[materialID.toInt()]
|
val getMat = Starbound.tilesAccessID[materialID]
|
||||||
|
|
||||||
if (getMat != null) {
|
if (getMat != null) {
|
||||||
chunk.foreground[x, y] = getMat
|
chunk.foreground[x, y].material = getMat
|
||||||
hitTile = true
|
hitTile = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,22 +84,22 @@ fun main() {
|
|||||||
val modifier = reader.readUnsignedShort()
|
val modifier = reader.readUnsignedShort()
|
||||||
val getModifier = Starbound.tileModifiersByIDAccess[modifier]
|
val getModifier = Starbound.tileModifiersByIDAccess[modifier]
|
||||||
|
|
||||||
chunk.foreground[x, y]?.color = colorVariant
|
chunk.foreground[x, y].color = colorVariant
|
||||||
chunk.foreground[x, y]?.setHueShift(colorShift)
|
chunk.foreground[x, y].setHueShift(colorShift)
|
||||||
|
|
||||||
if (getModifier != null && getMat != null) {
|
if (getModifier != null && getMat != null) {
|
||||||
chunk.foreground[x, y]?.modifier = getModifier
|
chunk.foreground[x, y].modifier = getModifier
|
||||||
}
|
}
|
||||||
|
|
||||||
val modifierHueShift = reader.readUnsignedByte()
|
val modifierHueShift = reader.readUnsignedByte()
|
||||||
|
|
||||||
chunk.foreground[x, y]?.setModifierHueShift(modifierHueShift)
|
chunk.foreground[x, y].setModifierHueShift(modifierHueShift)
|
||||||
|
|
||||||
val materialID2 = reader.readShort()
|
val materialID2 = reader.readUnsignedShort()
|
||||||
val getMat2 = Starbound.tilesAccessID[materialID2.toInt()]
|
val getMat2 = Starbound.tilesAccessID[materialID2]
|
||||||
|
|
||||||
if (getMat2 != null) {
|
if (getMat2 != null) {
|
||||||
chunk.background[x, y] = getMat2
|
chunk.background[x, y].material = getMat2
|
||||||
hitTile = true
|
hitTile = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,15 +113,15 @@ fun main() {
|
|||||||
val getModifier2 = Starbound.tileModifiersByIDAccess[modifier2]
|
val getModifier2 = Starbound.tileModifiersByIDAccess[modifier2]
|
||||||
|
|
||||||
if (getModifier2 != null && getMat2 != null) {
|
if (getModifier2 != null && getMat2 != null) {
|
||||||
chunk.background[x, y]?.modifier = getModifier2
|
chunk.background[x, y].modifier = getModifier2
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk.background[x, y]?.color = colorVariant2
|
chunk.background[x, y].color = colorVariant2
|
||||||
chunk.background[x, y]?.setHueShift(colorShift2)
|
chunk.background[x, y].setHueShift(colorShift2)
|
||||||
|
|
||||||
val modifierHueShift2 = reader.readUnsignedByte()
|
val modifierHueShift2 = reader.readUnsignedByte()
|
||||||
|
|
||||||
chunk.background[x, y]?.setModifierHueShift(modifierHueShift2)
|
chunk.background[x, y].setModifierHueShift(modifierHueShift2)
|
||||||
|
|
||||||
val liquid = reader.readUnsignedByte()
|
val liquid = reader.readUnsignedByte()
|
||||||
val liquidLevel = reader.readFloat()
|
val liquidLevel = reader.readFloat()
|
||||||
|
@ -50,28 +50,31 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
|
|||||||
layers.clear()
|
layers.clear()
|
||||||
|
|
||||||
for ((pos, tile) in view.posToTile) {
|
for ((pos, tile) in view.posToTile) {
|
||||||
if (tile != null) {
|
val material = tile.material
|
||||||
state.tileRenderers.getTileRenderer(tile.def.materialName).tesselate(tile, view, layers, pos, background = isBackground)
|
|
||||||
|
|
||||||
val modifier = tile.modifier
|
if (material != null) {
|
||||||
|
state.tileRenderers.getTileRenderer(material.materialName).tesselate(tile, view, layers, pos, background = isBackground)
|
||||||
|
}
|
||||||
|
|
||||||
if (modifier != null) {
|
val modifier = tile.modifier
|
||||||
state.tileRenderers.getModifierRenderer(modifier.modName).tesselate(tile, view, layers, pos, background = isBackground, isModifier = true)
|
|
||||||
}
|
if (modifier != null) {
|
||||||
|
state.tileRenderers.getModifierRenderer(modifier.modName).tesselate(tile, view, layers, pos, background = isBackground, isModifier = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadRenderers(view: ITileChunk) {
|
fun loadRenderers(view: ITileChunk) {
|
||||||
for ((_, tile) in view.posToTile) {
|
for ((_, tile) in view.posToTile) {
|
||||||
if (tile != null) {
|
val material = tile.material
|
||||||
state.tileRenderers.getTileRenderer(tile.def.materialName)
|
val modifier = tile.modifier
|
||||||
|
|
||||||
val modifier = tile.modifier
|
if (material != null) {
|
||||||
|
state.tileRenderers.getTileRenderer(material.materialName)
|
||||||
|
}
|
||||||
|
|
||||||
if (modifier != null) {
|
if (modifier != null) {
|
||||||
state.tileRenderers.getModifierRenderer(modifier.modName)
|
state.tileRenderers.getModifierRenderer(modifier.modName)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,8 @@ import ru.dbotthepony.kstarbound.client.gl.*
|
|||||||
import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList
|
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.TileState
|
|
||||||
import ru.dbotthepony.kstarbound.world.ITileChunk
|
import ru.dbotthepony.kstarbound.world.ITileChunk
|
||||||
|
import ru.dbotthepony.kstarbound.world.ITileState
|
||||||
import ru.dbotthepony.kvector.vector.Color
|
import ru.dbotthepony.kvector.vector.Color
|
||||||
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
@ -171,14 +171,14 @@ private enum class TileRenderTesselateResult {
|
|||||||
private fun vertexTextureBuilder() = HeapVertexBuilder(GLAttributeList.TILE, VertexType.QUADS)
|
private fun vertexTextureBuilder() = HeapVertexBuilder(GLAttributeList.TILE, VertexType.QUADS)
|
||||||
|
|
||||||
private class TileEqualityTester(val definition: TileDefinition) : EqualityRuleTester {
|
private class TileEqualityTester(val definition: TileDefinition) : EqualityRuleTester {
|
||||||
override fun test(thisTile: TileState?, otherTile: TileState?): Boolean {
|
override fun test(thisTile: ITileState, otherTile: ITileState): Boolean {
|
||||||
return otherTile?.def == 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: TileState?, otherTile: TileState?): Boolean {
|
override fun test(thisTile: ITileState, otherTile: ITileState): Boolean {
|
||||||
return otherTile?.modifier == definition
|
return otherTile.modifier == definition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ class TileRenderer(val state: GLStateTracker, val def: IRenderableTile) {
|
|||||||
val bakedBackgroundProgramState = state.tileRenderers.background(texture)
|
val bakedBackgroundProgramState = state.tileRenderers.background(texture)
|
||||||
// private var notifiedDepth = false
|
// private var notifiedDepth = false
|
||||||
|
|
||||||
private fun tesselateAt(self: TileState, piece: RenderPiece, getter: ITileChunk, builder: AbstractVertexBuilder<*>, pos: Vector2i, offset: Vector2i = Vector2i.ZERO, isModifier: Boolean) {
|
private fun tesselateAt(self: ITileState, piece: RenderPiece, getter: ITileChunk, builder: AbstractVertexBuilder<*>, 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()
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ class TileRenderer(val state: GLStateTracker, val def: IRenderableTile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun tesselatePiece(
|
private fun tesselatePiece(
|
||||||
self: TileState,
|
self: ITileState,
|
||||||
matchPiece: RenderMatch,
|
matchPiece: RenderMatch,
|
||||||
getter: ITileChunk,
|
getter: ITileChunk,
|
||||||
layers: TileLayerList,
|
layers: TileLayerList,
|
||||||
@ -289,7 +289,7 @@ class TileRenderer(val state: GLStateTracker, val def: IRenderableTile) {
|
|||||||
*
|
*
|
||||||
* Тесселирует тайлы в нужный VertexBuilder с масштабом согласно константе [PIXELS_IN_STARBOUND_UNITf]
|
* Тесселирует тайлы в нужный VertexBuilder с масштабом согласно константе [PIXELS_IN_STARBOUND_UNITf]
|
||||||
*/
|
*/
|
||||||
fun tesselate(self: TileState, getter: ITileChunk, layers: TileLayerList, pos: Vector2i, background: Boolean = false, isModifier: Boolean = false) {
|
fun tesselate(self: ITileState, getter: ITileChunk, layers: TileLayerList, pos: Vector2i, background: Boolean = false, isModifier: Boolean = false) {
|
||||||
// если у нас нет renderTemplate
|
// если у нас нет renderTemplate
|
||||||
// то мы просто не можем его отрисовать
|
// то мы просто не можем его отрисовать
|
||||||
val template = def.renderTemplate
|
val template = def.renderTemplate
|
||||||
|
@ -12,8 +12,8 @@ import ru.dbotthepony.kstarbound.Starbound
|
|||||||
import ru.dbotthepony.kstarbound.io.EnumAdapter
|
import ru.dbotthepony.kstarbound.io.EnumAdapter
|
||||||
import ru.dbotthepony.kstarbound.io.KConcreteTypeAdapter
|
import ru.dbotthepony.kstarbound.io.KConcreteTypeAdapter
|
||||||
import ru.dbotthepony.kstarbound.util.WriteOnce
|
import ru.dbotthepony.kstarbound.util.WriteOnce
|
||||||
import ru.dbotthepony.kstarbound.world.TileState
|
|
||||||
import ru.dbotthepony.kstarbound.world.ITileGetter
|
import ru.dbotthepony.kstarbound.world.ITileGetter
|
||||||
|
import ru.dbotthepony.kstarbound.world.ITileState
|
||||||
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ data class RenderPiece(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun interface EqualityRuleTester {
|
fun interface EqualityRuleTester {
|
||||||
fun test(thisTile: TileState?, otherTile: TileState?): Boolean
|
fun test(thisTile: ITileState, otherTile: ITileState): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
data class RenderRuleList(
|
data class RenderRuleList(
|
||||||
@ -57,7 +57,7 @@ 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[thisPos], getter[thisPos + offsetPos])
|
||||||
"Connects" -> getter[thisPos + offsetPos] != null
|
"Connects" -> getter[thisPos + offsetPos].material != null
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
if (LOGGED.add(type)) {
|
if (LOGGED.add(type)) {
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.util
|
||||||
|
|
||||||
|
import java.util.stream.Stream
|
||||||
|
import java.util.stream.StreamSupport
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
class NotNullTwoDimensionalArray<T : Any>(clazz: KClass<T>, private val width: Int, private val height: Int, initializer: (Int, Int) -> T) {
|
||||||
|
data class Entry<out T>(
|
||||||
|
val x: Int,
|
||||||
|
val y: Int,
|
||||||
|
val value: T,
|
||||||
|
)
|
||||||
|
|
||||||
|
private val memory: Array<T> = java.lang.reflect.Array.newInstance(clazz.java, width * height) as Array<T>
|
||||||
|
|
||||||
|
init {
|
||||||
|
for (x in 0 until width) {
|
||||||
|
for (y in 0 until height) {
|
||||||
|
memory[x + y * width] = initializer.invoke(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isOutside(x: Int, y: Int): Boolean {
|
||||||
|
return (x !in 0 until width) || (y !in 0 until height)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun get(x: Int, y: Int): T {
|
||||||
|
if (x !in 0 until width) {
|
||||||
|
throw IndexOutOfBoundsException("X $x is out of bounds between 0 and $width")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y !in 0 until height) {
|
||||||
|
throw IndexOutOfBoundsException("Y $y is out of bounds between 0 and $height")
|
||||||
|
}
|
||||||
|
|
||||||
|
return memory[x + y * width]
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(x: Int, y: Int, value: T): T {
|
||||||
|
if (x !in 0 until width) {
|
||||||
|
throw IndexOutOfBoundsException("X $x is out of bounds between 0 and $width")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y !in 0 until height) {
|
||||||
|
throw IndexOutOfBoundsException("Y $y is out of bounds between 0 and $height")
|
||||||
|
}
|
||||||
|
|
||||||
|
val old = memory[x + y * width]
|
||||||
|
memory[x + y * width] = value
|
||||||
|
return old
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stream(): Stream<out T> {
|
||||||
|
return StreamSupport.stream(ArraySpliterator(memory), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun indexedStream(): Stream<out Entry<T>> {
|
||||||
|
return StreamSupport.stream(IndexedArraySpliterator(memory), false).map {
|
||||||
|
val x = it.index % width
|
||||||
|
val y = (it.index - x) / width
|
||||||
|
Entry(x, y, it.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : Any> NotNullTwoDimensionalArray(width: Int, height: Int, noinline initializer: (Int, Int) -> T) = NotNullTwoDimensionalArray(T::class, width, height, initializer)
|
@ -13,6 +13,10 @@ class TwoDimensionalArray<T : Any>(clazz: KClass<T>, private val width: Int, pri
|
|||||||
|
|
||||||
private val memory: Array<T?> = java.lang.reflect.Array.newInstance(clazz.java, width * height) as Array<T?>
|
private val memory: Array<T?> = java.lang.reflect.Array.newInstance(clazz.java, width * height) as Array<T?>
|
||||||
|
|
||||||
|
fun isOutside(x: Int, y: Int): Boolean {
|
||||||
|
return (x !in 0 until width) || (y !in 0 until height)
|
||||||
|
}
|
||||||
|
|
||||||
operator fun get(x: Int, y: Int): T? {
|
operator fun get(x: Int, y: Int): T? {
|
||||||
if (x !in 0 until width) {
|
if (x !in 0 until width) {
|
||||||
throw IndexOutOfBoundsException("X $x is out of bounds between 0 and $width")
|
throw IndexOutOfBoundsException("X $x is out of bounds between 0 and $width")
|
||||||
|
@ -8,126 +8,18 @@ import ru.dbotthepony.kstarbound.defs.liquid.LiquidDefinition
|
|||||||
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.TILE_COLOR_VARIANTS
|
import ru.dbotthepony.kstarbound.defs.tile.TILE_COLOR_VARIANTS
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
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.util2d.AABB
|
import ru.dbotthepony.kvector.util2d.AABB
|
||||||
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
|
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
|
||||||
|
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.collections.HashSet
|
import kotlin.collections.HashSet
|
||||||
|
|
||||||
/**
|
|
||||||
* Представляет из себя класс, который содержит состояние тайла на заданной позиции
|
|
||||||
*/
|
|
||||||
class TileState(val chunk: Chunk<*, *>.TileLayer, val def: TileDefinition) {
|
|
||||||
var color = 0
|
|
||||||
set(value) {
|
|
||||||
if (value != field) {
|
|
||||||
if (!def.renderParameters.multiColored) {
|
|
||||||
throw IllegalStateException("${def.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
|
|
||||||
chunk.incChangeset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Выставляет 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var hueShift = 0f
|
|
||||||
set(value) {
|
|
||||||
var newValue = value % 360f
|
|
||||||
|
|
||||||
if (newValue < 0f) {
|
|
||||||
newValue += 360f
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newValue != field) {
|
|
||||||
field = newValue
|
|
||||||
chunk.incChangeset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var modifierHueShift = 0f
|
|
||||||
set(value) {
|
|
||||||
var newValue = value % 360f
|
|
||||||
|
|
||||||
if (newValue < 0f) {
|
|
||||||
newValue += 360f
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newValue != field) {
|
|
||||||
field = newValue
|
|
||||||
chunk.incChangeset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var modifier: MaterialModifier? = null
|
|
||||||
set(value) {
|
|
||||||
if (value != field) {
|
|
||||||
field = value
|
|
||||||
chunk.incChangeset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
return other is TileState &&
|
|
||||||
other.color == color &&
|
|
||||||
other.modifier === modifier &&
|
|
||||||
other.modifierHueShift == modifierHueShift &&
|
|
||||||
other.hueShift == hueShift &&
|
|
||||||
other.def === def
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return "ChunkTile[$chunk, material = ${def.materialName}, color = $color, modifier = ${modifier?.modName}]"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
var result = chunk.hashCode()
|
|
||||||
result = 31 * result + def.hashCode()
|
|
||||||
result = 31 * result + color
|
|
||||||
result = 31 * result + (modifier?.hashCode() ?: 0)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class LiquidState(val chunk: Chunk<*, *>, val def: LiquidDefinition) {
|
|
||||||
var pressure: Float = 0f
|
|
||||||
var level: Float = 1f
|
|
||||||
var isInfinite: Boolean = false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ccwSortScore(point: Vector2d, axis: Vector2d): Double {
|
private fun ccwSortScore(point: Vector2d, axis: Vector2d): Double {
|
||||||
if (point.x > 0.0) {
|
if (point.x > 0.0) {
|
||||||
return point.dot(axis)
|
return point.dot(axis)
|
||||||
@ -148,14 +40,22 @@ private fun ccwSortScore(point: Vector2d, axis: Vector2d): Double {
|
|||||||
*/
|
*/
|
||||||
abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType, This>>(val world: WorldType, val pos: ChunkPos) {
|
abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType, This>>(val world: WorldType, val pos: ChunkPos) {
|
||||||
/**
|
/**
|
||||||
* Возвращает счётчик изменений чанка
|
* Возвращает общий счётчик изменений чанка
|
||||||
*/
|
*/
|
||||||
var changeset = 0
|
var changeset = 0
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun incChangeset() {
|
/**
|
||||||
changeset++
|
* Возвращает счётчик изменений чанка по тайлам
|
||||||
}
|
*/
|
||||||
|
var tileChangeset = 0
|
||||||
|
private set
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает счётчик изменений чанка по жидкостям
|
||||||
|
*/
|
||||||
|
var liquidChangeset = 0
|
||||||
|
private set
|
||||||
|
|
||||||
val left get() = pos.left
|
val left get() = pos.left
|
||||||
val right get() = pos.right
|
val right get() = pos.right
|
||||||
@ -182,18 +82,153 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
foreground.bakeCollisions()
|
foreground.bakeCollisions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inner class LiquidState(val def: LiquidDefinition) {
|
||||||
|
var pressure: Float = 0f
|
||||||
|
set(value) {
|
||||||
|
if (value != field) {
|
||||||
|
field = value
|
||||||
|
liquidChangeset++
|
||||||
|
changeset++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var level: Float = 1f
|
||||||
|
set(value) {
|
||||||
|
if (value != field) {
|
||||||
|
field = value
|
||||||
|
liquidChangeset++
|
||||||
|
changeset++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var isInfinite: Boolean = false
|
||||||
|
set(value) {
|
||||||
|
if (value != field) {
|
||||||
|
field = value
|
||||||
|
liquidChangeset++
|
||||||
|
changeset++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Возвращает счётчик изменений этого слоя
|
* Возвращает счётчик изменений этого слоя
|
||||||
*/
|
*/
|
||||||
var changeset = 0
|
var changeset = 0
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun incChangeset() {
|
|
||||||
changeset++
|
|
||||||
this@Chunk.changeset++
|
|
||||||
}
|
|
||||||
|
|
||||||
private val collisionCache = ArrayList<AABB>()
|
private val collisionCache = ArrayList<AABB>()
|
||||||
private val collisionCacheView = Collections.unmodifiableCollection(collisionCache)
|
private val collisionCacheView = Collections.unmodifiableCollection(collisionCache)
|
||||||
private var collisionChangeset = -1
|
private var collisionChangeset = -1
|
||||||
@ -223,7 +258,7 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
|
|
||||||
for (y in 0 .. CHUNK_SIZE_FF) {
|
for (y in 0 .. CHUNK_SIZE_FF) {
|
||||||
for (x 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) {
|
if (!seen[x or (y shl CHUNK_SHIFT)] && tiles[x, y].material != null) {
|
||||||
val depthFirst = RectTileFlooderDepthFirst(tiles, seen, x, y)
|
val depthFirst = RectTileFlooderDepthFirst(tiles, seen, x, y)
|
||||||
val sizeFirst = RectTileFlooderSizeFirst(tiles, seen, x, y)
|
val sizeFirst = RectTileFlooderSizeFirst(tiles, seen, x, y)
|
||||||
val xSpanDepth = depthFirst.maxs.x - depthFirst.mins.x
|
val xSpanDepth = depthFirst.maxs.x - depthFirst.mins.x
|
||||||
@ -375,33 +410,10 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
/**
|
/**
|
||||||
* Хранит тайлы как x + y * CHUNK_SIZE
|
* Хранит тайлы как x + y * CHUNK_SIZE
|
||||||
*/
|
*/
|
||||||
private val tiles = arrayOfNulls<TileState>(CHUNK_SIZE * CHUNK_SIZE)
|
private val tiles: NotNullTwoDimensionalArray<TileState> = NotNullTwoDimensionalArray(CHUNK_SIZE, CHUNK_SIZE) { _, _ -> TileState() }
|
||||||
|
|
||||||
override operator fun get(x: Int, y: Int): TileState? {
|
override operator fun get(x: Int, y: Int): TileState {
|
||||||
if (isOutside(x, y))
|
return tiles[x, y]
|
||||||
return null
|
|
||||||
|
|
||||||
return tiles[x or (y shl CHUNK_SHIFT)]
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun set(x: Int, y: Int, tile: TileState?) {
|
|
||||||
if (isOutside(x, y))
|
|
||||||
throw IndexOutOfBoundsException("Trying to set tile ${tile?.def?.materialName} at $x $y, but that is outside of chunk's range")
|
|
||||||
|
|
||||||
changeset++
|
|
||||||
tiles[x or (y shl CHUNK_SHIFT)] = tile
|
|
||||||
markPhysicsDirty()
|
|
||||||
}
|
|
||||||
|
|
||||||
override operator fun set(x: Int, y: Int, tile: TileDefinition?): TileState? {
|
|
||||||
if (isOutside(x, y))
|
|
||||||
throw IndexOutOfBoundsException("Trying to set tile ${tile?.materialName} at $x $y, but that is outside of chunk's range")
|
|
||||||
|
|
||||||
val chunkTile = if (tile != null) TileState(this, tile) else null
|
|
||||||
this[x, y] = chunkTile
|
|
||||||
changeset++
|
|
||||||
markPhysicsDirty()
|
|
||||||
return chunkTile
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun randomLongFor(x: Int, y: Int): Long {
|
override fun randomLongFor(x: Int, y: Int): Long {
|
||||||
@ -418,11 +430,20 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
|
|
||||||
fun setLiquid(x: Int, y: Int, value: LiquidDefinition?): LiquidState? {
|
fun setLiquid(x: Int, y: Int, value: LiquidDefinition?): LiquidState? {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return liquidStates.set(x, y, null)
|
val old = liquidStates.set(x, y, null)
|
||||||
|
|
||||||
|
if (old != null) {
|
||||||
|
changeset++
|
||||||
|
liquidChangeset++
|
||||||
|
}
|
||||||
|
|
||||||
|
return old
|
||||||
}
|
}
|
||||||
|
|
||||||
val state = LiquidState(this, value)
|
val state = LiquidState(value)
|
||||||
liquidStates[x, y] = state
|
liquidStates[x, y] = state
|
||||||
|
changeset++
|
||||||
|
liquidChangeset++
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,13 +496,6 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val EMPTY = object : IMutableTileChunk {
|
|
||||||
override val pos = ChunkPos(0, 0)
|
|
||||||
|
|
||||||
override fun get(x: Int, y: Int): TileState? = null
|
|
||||||
override fun set(x: Int, y: Int, tile: TileDefinition?): TileState? = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private val aabbBase = AABB(
|
private val aabbBase = AABB(
|
||||||
Vector2d.ZERO,
|
Vector2d.ZERO,
|
||||||
Vector2d(CHUNK_SIZE.toDouble(), CHUNK_SIZE.toDouble()),
|
Vector2d(CHUNK_SIZE.toDouble(), CHUNK_SIZE.toDouble()),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.dbotthepony.kstarbound.world
|
package ru.dbotthepony.kstarbound.world
|
||||||
|
|
||||||
|
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
||||||
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
||||||
|
|
||||||
@ -10,6 +11,48 @@ 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 {
|
||||||
/**
|
/**
|
||||||
* Относительная проверка находится ли координата вне границ чанка
|
* Относительная проверка находится ли координата вне границ чанка
|
||||||
@ -26,7 +69,7 @@ interface ITileGetter : ITileMap {
|
|||||||
/**
|
/**
|
||||||
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||||
*/
|
*/
|
||||||
operator fun get(x: Int, y: Int): TileState?
|
operator fun get(x: Int, y: Int): ITileState
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
||||||
@ -38,8 +81,8 @@ interface ITileGetter : ITileMap {
|
|||||||
*
|
*
|
||||||
* Вектор имеет ОТНОСИТЕЛЬНЫЕ значения внутри самого чанка
|
* Вектор имеет ОТНОСИТЕЛЬНЫЕ значения внутри самого чанка
|
||||||
*/
|
*/
|
||||||
val posToTile: Iterator<Pair<Vector2i, TileState?>> get() {
|
val posToTile: Iterator<Pair<Vector2i, ITileState>> get() {
|
||||||
return object : Iterator<Pair<Vector2i, TileState?>> {
|
return object : Iterator<Pair<Vector2i, ITileState>> {
|
||||||
private var x = 0
|
private var x = 0
|
||||||
private var y = 0
|
private var y = 0
|
||||||
|
|
||||||
@ -49,7 +92,7 @@ interface ITileGetter : ITileMap {
|
|||||||
return idx() < CHUNK_SIZE * CHUNK_SIZE
|
return idx() < CHUNK_SIZE * CHUNK_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun next(): Pair<Vector2i, TileState?> {
|
override fun next(): Pair<Vector2i, ITileState> {
|
||||||
if (!hasNext()) {
|
if (!hasNext()) {
|
||||||
throw IllegalStateException("Already iterated everything!")
|
throw IllegalStateException("Already iterated everything!")
|
||||||
}
|
}
|
||||||
@ -114,20 +157,38 @@ interface IChunkPositionable : ITileMap {
|
|||||||
fun randomDoubleFor(pos: Vector2i) = randomDoubleFor(pos.x, pos.y)
|
fun randomDoubleFor(pos: Vector2i) = randomDoubleFor(pos.x, pos.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
interface ITileChunk : ITileGetter, IChunkPositionable
|
||||||
* Предоставляет интерфейс по установке тайлов в чанке
|
|
||||||
*/
|
interface IMutableTileChunk : ITileChunk {
|
||||||
interface ITileSetter : ITileMap {
|
override fun get(x: Int, y: Int): IMutableTileState
|
||||||
/**
|
override fun get(pos: Vector2i): IMutableTileState {
|
||||||
* Устанавливает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
return get(pos.x, pos.y)
|
||||||
*/
|
}
|
||||||
operator fun set(x: Int, y: Int, tile: TileDefinition?): TileState?
|
|
||||||
/**
|
|
||||||
* Устанавливает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
|
||||||
*/
|
|
||||||
operator fun set(pos: Vector2i, tile: TileDefinition?) = set(pos.x, pos.y, tile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ITileGetterSetter : ITileGetter, ITileSetter
|
object EmptyTileState : IMutableTileState {
|
||||||
interface ITileChunk : ITileGetter, IChunkPositionable
|
override var material: TileDefinition?
|
||||||
interface IMutableTileChunk : ITileChunk, ITileSetter
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,38 +22,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): TileState? {
|
override fun get(x: Int, y: Int): ITileState {
|
||||||
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[x, y]
|
return center[x, y]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y < 0) {
|
if (y < 0) {
|
||||||
return bottom?.get(x, y + CHUNK_SIZE)
|
return bottom?.get(x, y + CHUNK_SIZE) ?: EmptyTileState
|
||||||
} else {
|
} else {
|
||||||
return top?.get(x, y - CHUNK_SIZE)
|
return top?.get(x, y - CHUNK_SIZE) ?: EmptyTileState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
return left?.get(x + CHUNK_SIZE, y) ?: EmptyTileState
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y < 0) {
|
if (y < 0) {
|
||||||
return bottomLeft?.get(x + CHUNK_SIZE, y + CHUNK_SIZE)
|
return bottomLeft?.get(x + CHUNK_SIZE, y + CHUNK_SIZE) ?: EmptyTileState
|
||||||
} else {
|
} else {
|
||||||
return topLeft?.get(x + CHUNK_SIZE, y - CHUNK_SIZE)
|
return topLeft?.get(x + CHUNK_SIZE, y - CHUNK_SIZE) ?: EmptyTileState
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (y in 0 ..CHUNK_SIZE_FF) {
|
if (y in 0 ..CHUNK_SIZE_FF) {
|
||||||
return right?.get(x - CHUNK_SIZE, y)
|
return right?.get(x - CHUNK_SIZE, y) ?: EmptyTileState
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y < 0) {
|
if (y < 0) {
|
||||||
return bottomRight?.get(x - CHUNK_SIZE, y + CHUNK_SIZE)
|
return bottomRight?.get(x - CHUNK_SIZE, y + CHUNK_SIZE) ?: EmptyTileState
|
||||||
} else {
|
} else {
|
||||||
return topRight?.get(x - CHUNK_SIZE, y - CHUNK_SIZE)
|
return topRight?.get(x - CHUNK_SIZE, y - CHUNK_SIZE) ?: EmptyTileState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,39 +75,7 @@ class MutableTileView(
|
|||||||
override val bottomLeft: IMutableTileChunk?,
|
override val bottomLeft: IMutableTileChunk?,
|
||||||
override val bottomRight: IMutableTileChunk?,
|
override val bottomRight: IMutableTileChunk?,
|
||||||
) : TileView(center, right, top, topRight, topLeft, left, bottom, bottomLeft, bottomRight), IMutableTileChunk {
|
) : TileView(center, right, top, topRight, topLeft, left, bottom, bottomLeft, bottomRight), IMutableTileChunk {
|
||||||
override fun set(x: Int, y: Int, tile: TileDefinition?): TileState? {
|
override fun get(x: Int, y: Int): IMutableTileState {
|
||||||
if (x in 0 .. CHUNK_SIZE_FF) {
|
return super<TileView>.get(x, y) as IMutableTileState
|
||||||
if (y in 0 .. CHUNK_SIZE_FF) {
|
|
||||||
return center.set(x, y, tile)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y < 0) {
|
|
||||||
return bottom?.set(x, y + CHUNK_SIZE, tile)
|
|
||||||
} else {
|
|
||||||
return top?.set(x, y - CHUNK_SIZE, tile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x < 0) {
|
|
||||||
if (y in 0 .. CHUNK_SIZE_FF) {
|
|
||||||
return left?.set(x + CHUNK_SIZE, y, tile)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y < 0) {
|
|
||||||
return bottomLeft?.set(x + CHUNK_SIZE, y + CHUNK_SIZE, tile)
|
|
||||||
} else {
|
|
||||||
return topLeft?.set(x + CHUNK_SIZE, y - CHUNK_SIZE, tile)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (y in 0 .. CHUNK_SIZE_FF) {
|
|
||||||
return right?.set(x - CHUNK_SIZE, y, tile)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y < 0) {
|
|
||||||
return bottomRight?.set(x - CHUNK_SIZE, y + CHUNK_SIZE, tile)
|
|
||||||
} else {
|
|
||||||
return topRight?.set(x - CHUNK_SIZE, y - CHUNK_SIZE, tile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -323,26 +323,14 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTile(pos: Vector2i): TileState? {
|
fun getTile(pos: Vector2i): ITileState? {
|
||||||
return get(ChunkPos.fromTilePosition(pos))?.foreground?.get(ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y))
|
return get(ChunkPos.fromTilePosition(pos))?.foreground?.get(ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTile(pos: Vector2i, tile: TileDefinition?): ChunkType {
|
fun getBackgroundTile(pos: Vector2i): ITileState? {
|
||||||
val chunk = computeIfAbsent(ChunkPos.fromTilePosition(pos))
|
|
||||||
chunk.foreground[ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y)] = tile
|
|
||||||
return chunk
|
|
||||||
}
|
|
||||||
|
|
||||||
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?.get(ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setBackgroundTile(pos: Vector2i, tile: TileDefinition?): ChunkType {
|
|
||||||
val chunk = computeIfAbsent(ChunkPos.fromTilePosition(pos))
|
|
||||||
chunk.background[ChunkPos.normalizeCoordinate(pos.x), ChunkPos.normalizeCoordinate(pos.y)] = tile
|
|
||||||
return chunk
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Возвращает все чанки, которые пересекаются с заданным [boundingBox]
|
* Возвращает все чанки, которые пересекаются с заданным [boundingBox]
|
||||||
*/
|
*/
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
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.TileState
|
import ru.dbotthepony.kstarbound.world.Chunk
|
||||||
|
import ru.dbotthepony.kstarbound.world.ITileState
|
||||||
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
||||||
|
|
||||||
class RectTileFlooderDepthFirst(
|
class RectTileFlooderDepthFirst(
|
||||||
private val tiles: Array<TileState?>,
|
private val tiles: NotNullTwoDimensionalArray<out ITileState>,
|
||||||
private val seen: BooleanArray,
|
private val seen: BooleanArray,
|
||||||
rootx: Int,
|
rootx: Int,
|
||||||
rooty: Int
|
rooty: Int
|
||||||
@ -23,7 +25,7 @@ class RectTileFlooderDepthFirst(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return !seen[x or (y shl CHUNK_SHIFT)] && tiles[x or (y shl CHUNK_SHIFT)] != null
|
return !seen[x or (y shl CHUNK_SHIFT)] && tiles[x, y].material != null
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -1,12 +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.TileState
|
import ru.dbotthepony.kstarbound.world.ITileState
|
||||||
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
||||||
|
|
||||||
class RectTileFlooderSizeFirst(
|
class RectTileFlooderSizeFirst(
|
||||||
private val tiles: Array<TileState?>,
|
private val tiles: NotNullTwoDimensionalArray<out ITileState>,
|
||||||
private val seen: BooleanArray,
|
private val seen: BooleanArray,
|
||||||
private val rootx: Int,
|
private val rootx: Int,
|
||||||
private val rooty: Int
|
private val rooty: Int
|
||||||
@ -23,7 +24,7 @@ class RectTileFlooderSizeFirst(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return !seen[x or (y shl CHUNK_SHIFT)] && tiles[x or (y shl CHUNK_SHIFT)] != null
|
return !seen[x or (y shl CHUNK_SHIFT)] && tiles[x, y].material != null
|
||||||
}
|
}
|
||||||
|
|
||||||
private var widthPositive = 0
|
private var widthPositive = 0
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
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.TileState
|
import ru.dbotthepony.kstarbound.world.ITileState
|
||||||
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
|
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
|
||||||
|
|
||||||
private data class TileExposure(
|
private data class TileExposure(
|
||||||
@ -14,7 +15,7 @@ private data class TileExposure(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private class TileFlooder(
|
private class TileFlooder(
|
||||||
private val tiles: Array<TileState?>,
|
private val tiles: NotNullTwoDimensionalArray<out ITileState>,
|
||||||
private val seen: BooleanArray,
|
private val seen: BooleanArray,
|
||||||
rootx: Int,
|
rootx: Int,
|
||||||
rooty: Int
|
rooty: Int
|
||||||
@ -33,7 +34,7 @@ private class TileFlooder(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return tiles[x or (y shl CHUNK_SHIFT)] != null
|
return tiles[x, y].material != null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun visit(x: Int, y: Int) {
|
private fun visit(x: Int, y: Int) {
|
||||||
@ -71,4 +72,4 @@ private class TileFlooder(
|
|||||||
init {
|
init {
|
||||||
visit(rootx, rooty)
|
visit(rootx, rooty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user