Cleaner version of previous commit
This commit is contained in:
parent
3647643351
commit
3398ba62ee
@ -18,7 +18,7 @@ import ru.dbotthepony.kstarbound.world.*
|
|||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEd
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEd
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEf
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEf
|
||||||
import ru.dbotthepony.kstarbound.world.api.ITileChunk
|
import ru.dbotthepony.kstarbound.world.api.ITileAccess
|
||||||
import ru.dbotthepony.kstarbound.world.entities.Entity
|
import ru.dbotthepony.kstarbound.world.entities.Entity
|
||||||
import ru.dbotthepony.kvector.arrays.Matrix4fStack
|
import ru.dbotthepony.kvector.arrays.Matrix4fStack
|
||||||
import ru.dbotthepony.kvector.arrays.Matrix4f
|
import ru.dbotthepony.kvector.arrays.Matrix4f
|
||||||
@ -41,7 +41,7 @@ const val Z_LEVEL_LIQUID = 10000
|
|||||||
class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, ClientChunk>(world, pos), Closeable {
|
class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, ClientChunk>(world, pos), Closeable {
|
||||||
val state: GLStateTracker get() = world.client.gl
|
val state: GLStateTracker get() = world.client.gl
|
||||||
|
|
||||||
private inner class TileLayerRenderer(private val view: ITileChunk, private val isBackground: Boolean) : AutoCloseable {
|
private inner class TileLayerRenderer(private val view: ITileAccess, private val isBackground: Boolean) : AutoCloseable {
|
||||||
private val layers = TileLayerList()
|
private val layers = TileLayerList()
|
||||||
val bakedMeshes = LinkedList<Pair<ConfiguredStaticMesh, Int>>()
|
val bakedMeshes = LinkedList<Pair<ConfiguredStaticMesh, Int>>()
|
||||||
var isDirty = true
|
var isDirty = true
|
||||||
@ -153,8 +153,8 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
|
|||||||
val debugCollisions get() = world.client.settings.debugCollisions
|
val debugCollisions get() = world.client.settings.debugCollisions
|
||||||
val posVector2d = Vector2d(x = pos.x * CHUNK_SIZEd, y = pos.y * CHUNK_SIZEd)
|
val posVector2d = Vector2d(x = pos.x * CHUNK_SIZEd, y = pos.y * CHUNK_SIZEd)
|
||||||
|
|
||||||
private val foregroundRenderer = TileLayerRenderer(localizedForegroundView, isBackground = false)
|
private val foregroundRenderer = TileLayerRenderer(worldForegroundView, isBackground = false)
|
||||||
private val backgroundRenderer = TileLayerRenderer(localizedBackgroundView, isBackground = true)
|
private val backgroundRenderer = TileLayerRenderer(worldBackgroundView, isBackground = true)
|
||||||
|
|
||||||
override fun foregroundChanges() {
|
override fun foregroundChanges() {
|
||||||
super.foregroundChanges()
|
super.foregroundChanges()
|
||||||
@ -221,20 +221,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 (foregroundView.getTile(x, y).material?.renderParameters?.lightTransparent == false) {
|
if (localForegroundView.getTile(x, y).material?.renderParameters?.lightTransparent == false) {
|
||||||
if (x == 0 || foregroundView.getTile(x - 1, y).material?.renderParameters?.lightTransparent != true) {
|
if (x == 0 || localForegroundView.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 || foregroundView.getTile(x + 1, y).material?.renderParameters?.lightTransparent != true) {
|
if (x == CHUNK_SIZE - 1 || localForegroundView.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 || foregroundView.getTile(x, y - 1).material?.renderParameters?.lightTransparent != true) {
|
if (y == 0 || localForegroundView.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 || foregroundView.getTile(x, y + 1).material?.renderParameters?.lightTransparent != true) {
|
if (y == CHUNK_SIZE - 1 || localForegroundView.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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ 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.api.ITileAccess
|
import ru.dbotthepony.kstarbound.world.api.ITileAccess
|
||||||
import ru.dbotthepony.kstarbound.world.api.ITileChunk
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.ITileState
|
import ru.dbotthepony.kstarbound.world.api.ITileState
|
||||||
import ru.dbotthepony.kstarbound.world.api.TileColor
|
import ru.dbotthepony.kstarbound.world.api.TileColor
|
||||||
import ru.dbotthepony.kvector.vector.RGBAColor
|
import ru.dbotthepony.kvector.vector.RGBAColor
|
||||||
@ -202,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: ITileState, piece: RenderPiece, getter: ITileAccess, 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()
|
||||||
|
|
||||||
@ -246,7 +245,7 @@ class TileRenderer(val renderers: TileRenderers, val def: IRenderableTile) {
|
|||||||
private fun tesselatePiece(
|
private fun tesselatePiece(
|
||||||
self: ITileState,
|
self: ITileState,
|
||||||
matchPiece: RenderMatch,
|
matchPiece: RenderMatch,
|
||||||
getter: ITileChunk,
|
getter: ITileAccess,
|
||||||
layers: TileLayerList,
|
layers: TileLayerList,
|
||||||
pos: Vector2i,
|
pos: Vector2i,
|
||||||
thisBuilder: VertexBuilder,
|
thisBuilder: VertexBuilder,
|
||||||
@ -295,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: ITileState, getter: ITileAccess, layers: TileLayerList, pos: Vector2i, background: Boolean = false, isModifier: Boolean = false) {
|
||||||
// если у нас нет renderTemplate
|
// если у нас нет renderTemplate
|
||||||
// то мы просто не можем его отрисовать
|
// то мы просто не можем его отрисовать
|
||||||
val template = def.renderTemplate.value ?: return
|
val template = def.renderTemplate.value ?: return
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
package ru.dbotthepony.kstarbound.world
|
|
||||||
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.BackgroundChunkView
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.ForegroundChunkView
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.IChunk
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.IChunkCell
|
|
||||||
import ru.dbotthepony.kvector.arrays.Object2DArray
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Предоставляет доступ к чанку и его соседям
|
|
||||||
*
|
|
||||||
* В основном для использования в местах, где нужен не мир, а определённый чанк мира,
|
|
||||||
* и при этом координаты проверяются относительно чанка и могут спокойно выйти за его пределы,
|
|
||||||
* с желанием получить тайл из соседнего чанка
|
|
||||||
*/
|
|
||||||
class CellView(
|
|
||||||
override val pos: ChunkPos,
|
|
||||||
|
|
||||||
val left: IChunk?,
|
|
||||||
val center: IChunk?,
|
|
||||||
val right: IChunk?,
|
|
||||||
|
|
||||||
val topRight: IChunk?,
|
|
||||||
val top: IChunk?,
|
|
||||||
val topLeft: IChunk?,
|
|
||||||
|
|
||||||
val bottomLeft: IChunk?,
|
|
||||||
val bottom: IChunk?,
|
|
||||||
val bottomRight: IChunk?,
|
|
||||||
) : IChunk {
|
|
||||||
val backgroundView = BackgroundChunkView(this)
|
|
||||||
val foregroundView = ForegroundChunkView(this)
|
|
||||||
|
|
||||||
override fun getCell(x: Int, y: Int): IChunkCell {
|
|
||||||
val ix = x + CHUNK_SIZE
|
|
||||||
val iy = y + CHUNK_SIZE
|
|
||||||
|
|
||||||
if (ix in 0 until CHUNK_SIZE * 3 - 1 && iy in 0 until CHUNK_SIZE * 3 - 1) {
|
|
||||||
return indices[ix, iy].invoke(this) ?: IChunkCell.Companion
|
|
||||||
} else {
|
|
||||||
return IChunkCell.Companion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val indices = Object2DArray.nulls<(CellView) -> IChunkCell?>(CHUNK_SIZE * 3, CHUNK_SIZE * 3) as Object2DArray<(CellView) -> IChunkCell?>
|
|
||||||
|
|
||||||
private fun put(half: (CellView) -> IChunk?, x: Int, y: Int) {
|
|
||||||
for (ix in 0 until CHUNK_SIZE) {
|
|
||||||
for (iy in 0 until CHUNK_SIZE) {
|
|
||||||
indices[x + ix, y + iy] = { half(it)?.getCell(ix, iy) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
put(CellView::bottomLeft, 0, 0)
|
|
||||||
put(CellView::bottom, CHUNK_SIZE, 0)
|
|
||||||
put(CellView::bottomRight, CHUNK_SIZE * 2, 0)
|
|
||||||
|
|
||||||
put(CellView::left, 0, CHUNK_SIZE)
|
|
||||||
put(CellView::center, CHUNK_SIZE, CHUNK_SIZE)
|
|
||||||
put(CellView::right, CHUNK_SIZE * 2, CHUNK_SIZE)
|
|
||||||
|
|
||||||
put(CellView::topLeft, 0, CHUNK_SIZE * 2)
|
|
||||||
put(CellView::top, CHUNK_SIZE, CHUNK_SIZE * 2)
|
|
||||||
put(CellView::topRight, CHUNK_SIZE * 2, CHUNK_SIZE * 2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,19 +7,17 @@ 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.MaterialModifier
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
||||||
import ru.dbotthepony.kstarbound.world.api.BackgroundChunkView
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.BackgroundLocalizedView
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_BITS
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_BITS
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEd
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEd
|
||||||
import ru.dbotthepony.kstarbound.world.api.ForegroundChunkView
|
import ru.dbotthepony.kstarbound.world.api.ICellAccess
|
||||||
import ru.dbotthepony.kstarbound.world.api.ForegroundLocalizedView
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.IChunk
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.IChunkCell
|
import ru.dbotthepony.kstarbound.world.api.IChunkCell
|
||||||
import ru.dbotthepony.kstarbound.world.api.ILiquidState
|
import ru.dbotthepony.kstarbound.world.api.ILiquidState
|
||||||
import ru.dbotthepony.kstarbound.world.api.ITileState
|
import ru.dbotthepony.kstarbound.world.api.ITileState
|
||||||
|
import ru.dbotthepony.kstarbound.world.api.OffsetCellAccess
|
||||||
import ru.dbotthepony.kstarbound.world.api.TileColor
|
import ru.dbotthepony.kstarbound.world.api.TileColor
|
||||||
|
import ru.dbotthepony.kstarbound.world.api.TileView
|
||||||
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
|
||||||
@ -40,7 +38,7 @@ import kotlin.collections.HashSet
|
|||||||
*
|
*
|
||||||
* Весь игровой мир будет измеряться в Starbound Unit'ах
|
* Весь игровой мир будет измеряться в Starbound Unit'ах
|
||||||
*/
|
*/
|
||||||
abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType, This>>(val world: WorldType, final override val pos: ChunkPos) : IChunk {
|
abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType, This>>(val world: WorldType, val pos: ChunkPos) : ICellAccess {
|
||||||
var changeset = 0
|
var changeset = 0
|
||||||
private set
|
private set
|
||||||
var tileChangeset = 0
|
var tileChangeset = 0
|
||||||
@ -57,6 +55,35 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
var backgroundChangeset = 0
|
var backgroundChangeset = 0
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
protected val cells = Object2DArray(CHUNK_SIZE, CHUNK_SIZE, ::Cell)
|
||||||
|
|
||||||
|
override fun getCell(x: Int, y: Int): IChunkCell {
|
||||||
|
return cells[x, y]
|
||||||
|
}
|
||||||
|
|
||||||
|
// local cells' tile access
|
||||||
|
val localBackgroundView = TileView.background(this)
|
||||||
|
val localForegroundView = TileView.foreground(this)
|
||||||
|
|
||||||
|
// relative world cells access (accessing 0, 0 will lookup cell in world, relative to this chunk)
|
||||||
|
val worldView = OffsetCellAccess(world.chunkMap, pos)
|
||||||
|
val worldBackgroundView = TileView.background(worldView)
|
||||||
|
val worldForegroundView = TileView.foreground(worldView)
|
||||||
|
|
||||||
|
val aabb = aabbBase + Vector2d(pos.x * CHUNK_SIZE.toDouble(), pos.y * CHUNK_SIZE.toDouble())
|
||||||
|
|
||||||
|
var isPhysicsDirty = false
|
||||||
|
|
||||||
|
private val collisionCache = ArrayList<AABB>()
|
||||||
|
private val collisionCacheView = Collections.unmodifiableCollection(collisionCache)
|
||||||
|
|
||||||
|
private val body = world.physics.createBody(BodyDef(
|
||||||
|
position = pos.firstTile.toDoubleVector(),
|
||||||
|
userData = this
|
||||||
|
))
|
||||||
|
|
||||||
|
private val collisionChains = ArrayList<B2Fixture>()
|
||||||
|
|
||||||
protected open fun foregroundChanges() {
|
protected open fun foregroundChanges() {
|
||||||
changeset++
|
changeset++
|
||||||
cellChangeset++
|
cellChangeset++
|
||||||
@ -86,10 +113,6 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
world.chunkMap[pos.bottomRight]?.let(block)
|
world.chunkMap[pos.bottomRight]?.let(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
val aabb = aabbBase + Vector2d(pos.x * CHUNK_SIZE.toDouble(), pos.y * CHUNK_SIZE.toDouble())
|
|
||||||
|
|
||||||
var isPhysicsDirty = false
|
|
||||||
|
|
||||||
fun markPhysicsDirty() {
|
fun markPhysicsDirty() {
|
||||||
if (isPhysicsDirty)
|
if (isPhysicsDirty)
|
||||||
return
|
return
|
||||||
@ -98,21 +121,6 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
world.dirtyPhysicsChunks.add(this as This)
|
world.dirtyPhysicsChunks.add(this as This)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected val cells = Object2DArray(CHUNK_SIZE, CHUNK_SIZE, ::Cell)
|
|
||||||
|
|
||||||
val backgroundView = BackgroundChunkView(this)
|
|
||||||
val foregroundView = ForegroundChunkView(this)
|
|
||||||
|
|
||||||
val localizedBackgroundView = BackgroundLocalizedView(pos, world.chunkMap)
|
|
||||||
val localizedForegroundView = ForegroundLocalizedView(pos, world.chunkMap)
|
|
||||||
|
|
||||||
override fun getCell(x: Int, y: Int): IChunkCell {
|
|
||||||
return cells[x, y]
|
|
||||||
}
|
|
||||||
|
|
||||||
private val collisionCache = ArrayList<AABB>()
|
|
||||||
private val collisionCacheView = Collections.unmodifiableCollection(collisionCache)
|
|
||||||
|
|
||||||
inner class Cell(val x: Int, val y: Int) : IChunkCell {
|
inner class Cell(val x: Int, val y: Int) : IChunkCell {
|
||||||
inner class Tile(private val foreground: Boolean) : ITileState {
|
inner class Tile(private val foreground: Boolean) : ITileState {
|
||||||
private fun change() {
|
private fun change() {
|
||||||
@ -254,13 +262,6 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
get() = false
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private val body = world.physics.createBody(BodyDef(
|
|
||||||
position = pos.firstTile.toDoubleVector(),
|
|
||||||
userData = this
|
|
||||||
))
|
|
||||||
|
|
||||||
private val collisionChains = ArrayList<B2Fixture>()
|
|
||||||
|
|
||||||
fun bakeCollisions() {
|
fun bakeCollisions() {
|
||||||
if (collisionChangeset == changeset)
|
if (collisionChangeset == changeset)
|
||||||
return
|
return
|
||||||
@ -320,7 +321,7 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 world.chunkMap.randomLongFor(x or pos.x shl CHUNK_SIZE_BITS, y or pos.y shl CHUNK_SIZE_BITS)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected val entities = HashSet<Entity>()
|
protected val entities = HashSet<Entity>()
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package ru.dbotthepony.kstarbound.world
|
package ru.dbotthepony.kstarbound.world
|
||||||
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
||||||
import ru.dbotthepony.kstarbound.world.api.IChunk
|
import ru.dbotthepony.kstarbound.world.api.ICellAccess
|
||||||
import ru.dbotthepony.kstarbound.world.api.IChunkCell
|
import ru.dbotthepony.kstarbound.world.api.IChunkCell
|
||||||
import ru.dbotthepony.kstarbound.world.api.ITileAccess
|
import ru.dbotthepony.kstarbound.world.api.ITileAccess
|
||||||
import ru.dbotthepony.kstarbound.world.api.ITileState
|
import ru.dbotthepony.kstarbound.world.api.ITileState
|
||||||
import ru.dbotthepony.kvector.vector.Vector2i
|
import ru.dbotthepony.kvector.vector.Vector2i
|
||||||
|
|
||||||
fun IChunk.iterate(fromX: Int = 0, fromY: Int = 0, toX: Int = fromX + CHUNK_SIZE, toY: Int = fromY + CHUNK_SIZE): Iterator<Pair<Vector2i, IChunkCell>> {
|
fun ICellAccess.iterate(fromX: Int = 0, fromY: Int = 0, toX: Int = fromX + CHUNK_SIZE, toY: Int = fromY + CHUNK_SIZE): Iterator<Pair<Vector2i, IChunkCell>> {
|
||||||
return object : Iterator<Pair<Vector2i, IChunkCell>> {
|
return object : Iterator<Pair<Vector2i, IChunkCell>> {
|
||||||
private var x = fromX
|
private var x = fromX
|
||||||
private var y = fromY
|
private var y = fromY
|
||||||
|
@ -14,7 +14,6 @@ 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 RayCastResult(
|
data class RayCastResult(
|
||||||
|
@ -11,13 +11,12 @@ import ru.dbotthepony.kbox2d.dynamics.B2World
|
|||||||
import ru.dbotthepony.kbox2d.dynamics.contact.AbstractContact
|
import ru.dbotthepony.kbox2d.dynamics.contact.AbstractContact
|
||||||
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.api.BackgroundAccessView
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_BITS
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_BITS
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_MASK
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_MASK
|
||||||
import ru.dbotthepony.kstarbound.world.api.ForegroundAccessView
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.ICellAccess
|
import ru.dbotthepony.kstarbound.world.api.ICellAccess
|
||||||
import ru.dbotthepony.kstarbound.world.api.IChunkCell
|
import ru.dbotthepony.kstarbound.world.api.IChunkCell
|
||||||
|
import ru.dbotthepony.kstarbound.world.api.TileView
|
||||||
import ru.dbotthepony.kstarbound.world.entities.Entity
|
import ru.dbotthepony.kstarbound.world.entities.Entity
|
||||||
import ru.dbotthepony.kvector.api.IStruct2d
|
import ru.dbotthepony.kvector.api.IStruct2d
|
||||||
import ru.dbotthepony.kvector.api.IStruct2i
|
import ru.dbotthepony.kvector.api.IStruct2i
|
||||||
@ -128,8 +127,12 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
fun inBounds(x: Int, y: Int) = this.x.inBounds(x) && this.y.inBounds(y)
|
fun inBounds(x: Int, y: Int) = this.x.inBounds(x) && this.y.inBounds(y)
|
||||||
fun inBounds(value: IStruct2i) = this.x.inBounds(value.component1()) && this.y.inBounds(value.component2())
|
fun inBounds(value: IStruct2i) = this.x.inBounds(value.component1()) && this.y.inBounds(value.component2())
|
||||||
|
|
||||||
val backgroundView = BackgroundAccessView(this)
|
override fun randomLongFor(x: Int, y: Int): Long {
|
||||||
val foregroundView = ForegroundAccessView(this)
|
return super.randomLongFor(x, y) xor seed
|
||||||
|
}
|
||||||
|
|
||||||
|
val background = TileView.background(this)
|
||||||
|
val foreground = TileView.foreground(this)
|
||||||
|
|
||||||
abstract operator fun get(x: Int, y: Int): ChunkType?
|
abstract operator fun get(x: Int, y: Int): ChunkType?
|
||||||
operator fun get(pos: ChunkPos) = get(pos.x, pos.y)
|
operator fun get(pos: ChunkPos) = get(pos.x, pos.y)
|
||||||
@ -394,21 +397,6 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
|
|
||||||
protected abstract fun chunkFactory(pos: ChunkPos): ChunkType
|
protected abstract fun chunkFactory(pos: ChunkPos): ChunkType
|
||||||
|
|
||||||
fun getView(pos: ChunkPos): CellView {
|
|
||||||
return CellView(
|
|
||||||
pos = pos,
|
|
||||||
center = chunkMap[pos],
|
|
||||||
left = chunkMap[pos.left],
|
|
||||||
top = chunkMap[pos.top],
|
|
||||||
topLeft = chunkMap[pos.topLeft],
|
|
||||||
topRight = chunkMap[pos.topRight],
|
|
||||||
right = chunkMap[pos.right],
|
|
||||||
bottom = chunkMap[pos.bottom],
|
|
||||||
bottomLeft = chunkMap[pos.bottomLeft],
|
|
||||||
bottomRight = chunkMap[pos.bottomRight],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Возвращает все чанки, которые пересекаются с заданным [boundingBox]
|
* Возвращает все чанки, которые пересекаются с заданным [boundingBox]
|
||||||
*/
|
*/
|
||||||
@ -480,7 +468,6 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
|
|
||||||
private fun floodLightInto(
|
private fun floodLightInto(
|
||||||
lightmap: Int2DArray,
|
lightmap: Int2DArray,
|
||||||
view: CellView,
|
|
||||||
thisIntensity: Int,
|
thisIntensity: Int,
|
||||||
lightBlockerStrength: Int,
|
lightBlockerStrength: Int,
|
||||||
posX: Int,
|
posX: Int,
|
||||||
@ -492,7 +479,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
val tile = view.getCell(worldPosX, worldPosY)
|
val tile = chunkMap.getCell(worldPosX, worldPosY)
|
||||||
|
|
||||||
val newIntensity: Int
|
val newIntensity: Int
|
||||||
|
|
||||||
@ -508,7 +495,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
var c = 1
|
var c = 1
|
||||||
|
|
||||||
c += floodLightInto(
|
c += floodLightInto(
|
||||||
lightmap, view, newIntensity, lightBlockerStrength,
|
lightmap, newIntensity, lightBlockerStrength,
|
||||||
posX + 1,
|
posX + 1,
|
||||||
worldPosX + 1,
|
worldPosX + 1,
|
||||||
posY,
|
posY,
|
||||||
@ -516,7 +503,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
)
|
)
|
||||||
|
|
||||||
c += floodLightInto(
|
c += floodLightInto(
|
||||||
lightmap, view, newIntensity, lightBlockerStrength,
|
lightmap, newIntensity, lightBlockerStrength,
|
||||||
posX - 1,
|
posX - 1,
|
||||||
worldPosX - 1,
|
worldPosX - 1,
|
||||||
posY,
|
posY,
|
||||||
@ -524,7 +511,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
)
|
)
|
||||||
|
|
||||||
c += floodLightInto(
|
c += floodLightInto(
|
||||||
lightmap, view, newIntensity, lightBlockerStrength,
|
lightmap, newIntensity, lightBlockerStrength,
|
||||||
posX,
|
posX,
|
||||||
worldPosX,
|
worldPosX,
|
||||||
posY + 1,
|
posY + 1,
|
||||||
@ -532,7 +519,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
)
|
)
|
||||||
|
|
||||||
c += floodLightInto(
|
c += floodLightInto(
|
||||||
lightmap, view, newIntensity, lightBlockerStrength,
|
lightmap, newIntensity, lightBlockerStrength,
|
||||||
posX,
|
posX,
|
||||||
worldPosX,
|
worldPosX,
|
||||||
posY - 1,
|
posY - 1,
|
||||||
@ -564,17 +551,14 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
|
|
||||||
val lightmap = Int2DArray.allocate(lightIntensity * 2 + 1, lightIntensity * 2 + 1)
|
val lightmap = Int2DArray.allocate(lightIntensity * 2 + 1, lightIntensity * 2 + 1)
|
||||||
|
|
||||||
val view = getView(ChunkPos.fromPosition(lightPosition))
|
|
||||||
|
|
||||||
floodLightInto(
|
floodLightInto(
|
||||||
lightmap,
|
lightmap,
|
||||||
view,
|
|
||||||
lightIntensity,
|
lightIntensity,
|
||||||
lightBlockerStrength,
|
lightBlockerStrength,
|
||||||
lightIntensity,
|
lightIntensity,
|
||||||
lightPosition.x - view.pos.tileX,
|
lightPosition.x,
|
||||||
lightIntensity,
|
lightIntensity,
|
||||||
lightPosition.y - view.pos.tileY,
|
lightPosition.y,
|
||||||
)
|
)
|
||||||
|
|
||||||
return lightmap
|
return lightmap
|
||||||
|
@ -1,9 +1,51 @@
|
|||||||
package ru.dbotthepony.kstarbound.world.api
|
package ru.dbotthepony.kstarbound.world.api
|
||||||
|
|
||||||
|
import ru.dbotthepony.kstarbound.world.ChunkPos
|
||||||
import ru.dbotthepony.kvector.api.IStruct2i
|
import ru.dbotthepony.kvector.api.IStruct2i
|
||||||
|
import ru.dbotthepony.kvector.vector.Vector2i
|
||||||
|
|
||||||
interface ICellAccess {
|
interface ICellAccess {
|
||||||
// relative
|
// relative
|
||||||
fun getCell(x: Int, y: Int): IChunkCell
|
fun getCell(x: Int, y: Int): IChunkCell
|
||||||
fun getCell(pos: IStruct2i) = getCell(pos.component1(), pos.component2())
|
fun getCell(pos: IStruct2i) = getCell(pos.component1(), pos.component2())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает псевдослучайное Long для заданной позиции
|
||||||
|
*
|
||||||
|
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
||||||
|
*/
|
||||||
|
fun randomLongFor(x: Int, y: Int): Long {
|
||||||
|
var long = x * 738548L + y * 2191293543L
|
||||||
|
long = long xor 8339437585692L
|
||||||
|
long = (long ushr 4) or (long shl 52)
|
||||||
|
long *= 7848344324L
|
||||||
|
long = (long ushr 12) or (long shl 44)
|
||||||
|
return long
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает псевдослучайное нормализированное Double для заданной позиции
|
||||||
|
*
|
||||||
|
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
||||||
|
*/
|
||||||
|
fun randomDoubleFor(x: Int, y: Int): Double {
|
||||||
|
return (randomLongFor(x, y) / 9.223372036854776E18) / 2.0 + 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
fun randomLongFor(pos: Vector2i) = randomLongFor(pos.x, pos.y)
|
||||||
|
fun randomDoubleFor(pos: Vector2i) = randomDoubleFor(pos.x, pos.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
class OffsetCellAccess(private val parent: ICellAccess, private val x: Int, private val y: Int) : ICellAccess {
|
||||||
|
constructor(parent: ICellAccess, offset: IStruct2i) : this(parent, offset.component1(), offset.component2())
|
||||||
|
constructor(parent: ICellAccess, offset: ChunkPos) : this(parent, offset.firstTile)
|
||||||
|
|
||||||
|
override fun getCell(x: Int, y: Int): IChunkCell {
|
||||||
|
return parent.getCell(x + this.x, y + this.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun randomLongFor(x: Int, y: Int) = parent.randomLongFor(x + this.x, y + this.y)
|
||||||
|
override fun randomDoubleFor(x: Int, y: Int) = parent.randomDoubleFor(x + this.x, y + this.y)
|
||||||
|
override fun randomLongFor(pos: Vector2i) = parent.randomLongFor(pos.x + this.x, pos.y + this.y)
|
||||||
|
override fun randomDoubleFor(pos: Vector2i) = parent.randomDoubleFor(pos.x + this.x, pos.y + this.y)
|
||||||
}
|
}
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
package ru.dbotthepony.kstarbound.world.api
|
|
||||||
|
|
||||||
import ru.dbotthepony.kstarbound.world.ChunkPos
|
|
||||||
import ru.dbotthepony.kvector.api.IStruct2i
|
|
||||||
import ru.dbotthepony.kvector.vector.Vector2i
|
|
||||||
|
|
||||||
interface IChunk : ICellAccess {
|
|
||||||
val pos: ChunkPos
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает псевдослучайное Long для заданной позиции
|
|
||||||
*
|
|
||||||
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
|
||||||
*/
|
|
||||||
fun randomLongFor(x: Int, y: Int): Long {
|
|
||||||
var long = (x or (pos.x shl CHUNK_SIZE_BITS)) * 738548L + (y or (pos.y shl CHUNK_SIZE_BITS)) * 2191293543L
|
|
||||||
long = long xor 8339437585692L
|
|
||||||
long = (long ushr 4) or (long shl 52)
|
|
||||||
long *= 7848344324L
|
|
||||||
long = (long ushr 12) or (long shl 44)
|
|
||||||
return long
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает псевдослучайное нормализированное Double для заданной позиции
|
|
||||||
*
|
|
||||||
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
|
||||||
*/
|
|
||||||
fun randomDoubleFor(x: Int, y: Int): Double {
|
|
||||||
return (randomLongFor(x, y) / 9.223372036854776E18) / 2.0 + 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает псевдослучайное Long для заданной позиции
|
|
||||||
*
|
|
||||||
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
|
||||||
*/
|
|
||||||
fun randomLongFor(pos: Vector2i) = randomLongFor(pos.x, pos.y)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает псевдослучайное нормализированное Double для заданной позиции
|
|
||||||
*
|
|
||||||
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
|
||||||
*/
|
|
||||||
fun randomDoubleFor(pos: Vector2i) = randomDoubleFor(pos.x, pos.y)
|
|
||||||
}
|
|
@ -10,40 +10,50 @@ interface ITileAccess : ICellAccess {
|
|||||||
fun getTile(pos: IStruct2i) = getTile(pos.component1(), pos.component2())
|
fun getTile(pos: IStruct2i) = getTile(pos.component1(), pos.component2())
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ITileChunk : IChunk, ITileAccess
|
sealed class TileView(parent: ICellAccess) : ITileAccess, ICellAccess by parent {
|
||||||
|
private class Foreground(parent: ICellAccess) : TileView(parent) {
|
||||||
|
override fun getTile(x: Int, y: Int): ITileState {
|
||||||
|
return getCell(x, y).foreground
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ForegroundChunkView(private val parent: IChunk) : ITileChunk, IChunk by parent {
|
private class Background(parent: ICellAccess) : TileView(parent) {
|
||||||
override fun getTile(x: Int, y: Int): ITileState {
|
override fun getTile(x: Int, y: Int): ITileState {
|
||||||
return parent.getCell(x, y).foreground
|
return getCell(x, y).background
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BackgroundChunkView(private val parent: IChunk) : ITileChunk, IChunk by parent {
|
companion object {
|
||||||
override fun getTile(x: Int, y: Int): ITileState {
|
fun foreground(parent: ICellAccess, xOffset: Int = 0, yOffset: Int = 0): TileView {
|
||||||
return parent.getCell(x, y).background
|
if (xOffset == 0 && yOffset == 0) {
|
||||||
}
|
return Foreground(parent)
|
||||||
}
|
} else {
|
||||||
|
return Foreground(OffsetCellAccess(parent, xOffset, yOffset))
|
||||||
class ForegroundLocalizedView(override val pos: ChunkPos, private val parent: ICellAccess) : ITileChunk, ICellAccess by parent {
|
}
|
||||||
override fun getTile(x: Int, y: Int): ITileState {
|
}
|
||||||
return parent.getCell(pos.tileX + x, pos.tileY + y).foreground
|
|
||||||
}
|
fun foreground(parent: ICellAccess, offset: IStruct2i): TileView {
|
||||||
}
|
return Foreground(OffsetCellAccess(parent, offset))
|
||||||
|
}
|
||||||
class BackgroundLocalizedView(override val pos: ChunkPos, private val parent: ICellAccess) : ITileChunk, ICellAccess by parent {
|
|
||||||
override fun getTile(x: Int, y: Int): ITileState {
|
fun foreground(parent: ICellAccess, offset: ChunkPos): TileView {
|
||||||
return parent.getCell(pos.tileX + x, pos.tileY + y).background
|
return Foreground(OffsetCellAccess(parent, offset))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
fun background(parent: ICellAccess, xOffset: Int = 0, yOffset: Int = 0): TileView {
|
||||||
class ForegroundAccessView(private val parent: ICellAccess) : ITileAccess, ICellAccess by parent {
|
if (xOffset == 0 && yOffset == 0) {
|
||||||
override fun getTile(x: Int, y: Int): ITileState {
|
return Background(parent)
|
||||||
return parent.getCell(x, y).foreground
|
} else {
|
||||||
}
|
return Background(OffsetCellAccess(parent, xOffset, yOffset))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
class BackgroundAccessView(private val parent: ICellAccess) : ITileAccess, ICellAccess by parent {
|
|
||||||
override fun getTile(x: Int, y: Int): ITileState {
|
fun background(parent: ICellAccess, offset: IStruct2i): TileView {
|
||||||
return parent.getCell(x, y).background
|
return Background(OffsetCellAccess(parent, offset))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun background(parent: ICellAccess, offset: ChunkPos): TileView {
|
||||||
|
return Background(OffsetCellAccess(parent, offset))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user