From 3398ba62eea0ffe6b0e94267cb45ccc5415cbb66 Mon Sep 17 00:00:00 2001 From: DBotThePony <dbotthepony@yandex.ru> Date: Mon, 4 Sep 2023 08:35:31 +0700 Subject: [PATCH] Cleaner version of previous commit --- .../kstarbound/client/ClientChunk.kt | 18 ++--- .../kstarbound/client/render/TileRenderer.kt | 7 +- .../dbotthepony/kstarbound/world/CellView.kt | 71 ----------------- .../ru/dbotthepony/kstarbound/world/Chunk.kt | 67 ++++++++-------- .../dbotthepony/kstarbound/world/Helpers.kt | 4 +- .../kstarbound/world/Raycasting.kt | 1 - .../ru/dbotthepony/kstarbound/world/World.kt | 44 ++++------- .../kstarbound/world/api/ICellAccess.kt | 42 ++++++++++ .../kstarbound/world/api/IChunk.kt | 46 ----------- .../kstarbound/world/api/ITileAccess.kt | 78 +++++++++++-------- 10 files changed, 148 insertions(+), 230 deletions(-) delete mode 100644 src/main/kotlin/ru/dbotthepony/kstarbound/world/CellView.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/kstarbound/world/api/IChunk.kt diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientChunk.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientChunk.kt index 46f9de2a..9c7e5ba8 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientChunk.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/ClientChunk.kt @@ -18,7 +18,7 @@ import ru.dbotthepony.kstarbound.world.* import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEd 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.kvector.arrays.Matrix4fStack 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 { 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() val bakedMeshes = LinkedList<Pair<ConfiguredStaticMesh, Int>>() var isDirty = true @@ -153,8 +153,8 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client val debugCollisions get() = world.client.settings.debugCollisions val posVector2d = Vector2d(x = pos.x * CHUNK_SIZEd, y = pos.y * CHUNK_SIZEd) - private val foregroundRenderer = TileLayerRenderer(localizedForegroundView, isBackground = false) - private val backgroundRenderer = TileLayerRenderer(localizedBackgroundView, isBackground = true) + private val foregroundRenderer = TileLayerRenderer(worldForegroundView, isBackground = false) + private val backgroundRenderer = TileLayerRenderer(worldBackgroundView, isBackground = true) override fun 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 (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 (x == 0 || foregroundView.getTile(x - 1, y).material?.renderParameters?.lightTransparent != true) { + if (localForegroundView.getTile(x, y).material?.renderParameters?.lightTransparent == false) { + if (x == 0 || localForegroundView.getTile(x - 1, y).material?.renderParameters?.lightTransparent != true) { 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) } - 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()) } - 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) } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt index d86cdf9f..170b6468 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt @@ -12,7 +12,6 @@ import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList import ru.dbotthepony.kstarbound.client.gl.vertex.* import ru.dbotthepony.kstarbound.defs.tile.* 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.TileColor import ru.dbotthepony.kvector.vector.RGBAColor @@ -202,7 +201,7 @@ class TileRenderer(val renderers: TileRenderers, val def: IRenderableTile) { val bakedBackgroundProgramState = renderers.background(texture) // 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 fy = pos.y.toFloat() @@ -246,7 +245,7 @@ class TileRenderer(val renderers: TileRenderers, val def: IRenderableTile) { private fun tesselatePiece( self: ITileState, matchPiece: RenderMatch, - getter: ITileChunk, + getter: ITileAccess, layers: TileLayerList, pos: Vector2i, thisBuilder: VertexBuilder, @@ -295,7 +294,7 @@ class TileRenderer(val renderers: TileRenderers, val def: IRenderableTile) { * * Тесселирует тайлы в нужный 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 // то мы просто не можем его отрисовать val template = def.renderTemplate.value ?: return diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/CellView.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/CellView.kt deleted file mode 100644 index f45ad5e9..00000000 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/CellView.kt +++ /dev/null @@ -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) - } - } -} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt index e9803ab0..b0c18bf6 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt @@ -7,19 +7,17 @@ import ru.dbotthepony.kbox2d.dynamics.B2Fixture import ru.dbotthepony.kstarbound.defs.tile.LiquidDefinition import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier 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 import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEd -import ru.dbotthepony.kstarbound.world.api.ForegroundChunkView -import ru.dbotthepony.kstarbound.world.api.ForegroundLocalizedView -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.ILiquidState 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.TileView import ru.dbotthepony.kstarbound.world.entities.Entity import ru.dbotthepony.kstarbound.world.phys.RectTileFlooderDepthFirst import ru.dbotthepony.kstarbound.world.phys.RectTileFlooderSizeFirst @@ -40,7 +38,7 @@ import kotlin.collections.HashSet * * Весь игровой мир будет измеряться в 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 private set var tileChangeset = 0 @@ -57,6 +55,35 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType, var backgroundChangeset = 0 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() { changeset++ cellChangeset++ @@ -86,10 +113,6 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType, 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() { if (isPhysicsDirty) return @@ -98,21 +121,6 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType, 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 Tile(private val foreground: Boolean) : ITileState { private fun change() { @@ -254,13 +262,6 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType, get() = false } - private val body = world.physics.createBody(BodyDef( - position = pos.firstTile.toDoubleVector(), - userData = this - )) - - private val collisionChains = ArrayList<B2Fixture>() - fun bakeCollisions() { if (collisionChangeset == changeset) return @@ -320,7 +321,7 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType, } 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>() diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Helpers.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Helpers.kt index 62ee1749..6d729610 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Helpers.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Helpers.kt @@ -1,13 +1,13 @@ package ru.dbotthepony.kstarbound.world 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.ITileAccess import ru.dbotthepony.kstarbound.world.api.ITileState 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>> { private var x = fromX private var y = fromY diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Raycasting.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Raycasting.kt index 86d794b8..86e939a2 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Raycasting.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Raycasting.kt @@ -14,7 +14,6 @@ import kotlin.math.cos import kotlin.math.roundToInt import kotlin.math.sin - const val EARTH_FREEFALL_ACCELERATION = 9.8312 / METRES_IN_STARBOUND_UNIT data class RayCastResult( diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt index c0fc5be3..09acddd5 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt @@ -11,13 +11,12 @@ import ru.dbotthepony.kbox2d.dynamics.B2World import ru.dbotthepony.kbox2d.dynamics.contact.AbstractContact import ru.dbotthepony.kstarbound.math.* 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_BITS 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.IChunkCell +import ru.dbotthepony.kstarbound.world.api.TileView import ru.dbotthepony.kstarbound.world.entities.Entity import ru.dbotthepony.kvector.api.IStruct2d 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(value: IStruct2i) = this.x.inBounds(value.component1()) && this.y.inBounds(value.component2()) - val backgroundView = BackgroundAccessView(this) - val foregroundView = ForegroundAccessView(this) + override fun randomLongFor(x: Int, y: Int): Long { + 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? 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 - 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] */ @@ -480,7 +468,6 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun private fun floodLightInto( lightmap: Int2DArray, - view: CellView, thisIntensity: Int, lightBlockerStrength: Int, posX: Int, @@ -492,7 +479,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun return 1 } - val tile = view.getCell(worldPosX, worldPosY) + val tile = chunkMap.getCell(worldPosX, worldPosY) val newIntensity: Int @@ -508,7 +495,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun var c = 1 c += floodLightInto( - lightmap, view, newIntensity, lightBlockerStrength, + lightmap, newIntensity, lightBlockerStrength, posX + 1, worldPosX + 1, posY, @@ -516,7 +503,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun ) c += floodLightInto( - lightmap, view, newIntensity, lightBlockerStrength, + lightmap, newIntensity, lightBlockerStrength, posX - 1, worldPosX - 1, posY, @@ -524,7 +511,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun ) c += floodLightInto( - lightmap, view, newIntensity, lightBlockerStrength, + lightmap, newIntensity, lightBlockerStrength, posX, worldPosX, posY + 1, @@ -532,7 +519,7 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun ) c += floodLightInto( - lightmap, view, newIntensity, lightBlockerStrength, + lightmap, newIntensity, lightBlockerStrength, posX, worldPosX, 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 view = getView(ChunkPos.fromPosition(lightPosition)) - floodLightInto( lightmap, - view, lightIntensity, lightBlockerStrength, lightIntensity, - lightPosition.x - view.pos.tileX, + lightPosition.x, lightIntensity, - lightPosition.y - view.pos.tileY, + lightPosition.y, ) return lightmap diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/ICellAccess.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/ICellAccess.kt index 876f2cf6..6d579164 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/ICellAccess.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/ICellAccess.kt @@ -1,9 +1,51 @@ 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 ICellAccess { // relative fun getCell(x: Int, y: Int): IChunkCell 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) } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/IChunk.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/IChunk.kt deleted file mode 100644 index d4b0d489..00000000 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/IChunk.kt +++ /dev/null @@ -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) -} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/ITileAccess.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/ITileAccess.kt index 41d4952d..c3243470 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/ITileAccess.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/ITileAccess.kt @@ -10,40 +10,50 @@ interface ITileAccess : ICellAccess { 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 { - override fun getTile(x: Int, y: Int): ITileState { - return parent.getCell(x, y).foreground - } -} - -class BackgroundChunkView(private val parent: IChunk) : ITileChunk, IChunk by parent { - override fun getTile(x: Int, y: Int): ITileState { - return parent.getCell(x, y).background - } -} - -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 - } -} - -class BackgroundLocalizedView(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).background - } -} - -class ForegroundAccessView(private val parent: ICellAccess) : ITileAccess, ICellAccess by parent { - override fun getTile(x: Int, y: Int): ITileState { - return parent.getCell(x, y).foreground - } -} - -class BackgroundAccessView(private val parent: ICellAccess) : ITileAccess, ICellAccess by parent { - override fun getTile(x: Int, y: Int): ITileState { - return parent.getCell(x, y).background + private class Background(parent: ICellAccess) : TileView(parent) { + override fun getTile(x: Int, y: Int): ITileState { + return getCell(x, y).background + } + } + + companion object { + fun foreground(parent: ICellAccess, xOffset: Int = 0, yOffset: Int = 0): TileView { + if (xOffset == 0 && yOffset == 0) { + return Foreground(parent) + } else { + return Foreground(OffsetCellAccess(parent, xOffset, yOffset)) + } + } + + fun foreground(parent: ICellAccess, offset: IStruct2i): TileView { + return Foreground(OffsetCellAccess(parent, offset)) + } + + fun foreground(parent: ICellAccess, offset: ChunkPos): TileView { + return Foreground(OffsetCellAccess(parent, offset)) + } + + fun background(parent: ICellAccess, xOffset: Int = 0, yOffset: Int = 0): TileView { + if (xOffset == 0 && yOffset == 0) { + return Background(parent) + } else { + return Background(OffsetCellAccess(parent, xOffset, yOffset)) + } + } + + fun background(parent: ICellAccess, offset: IStruct2i): TileView { + return Background(OffsetCellAccess(parent, offset)) + } + + fun background(parent: ICellAccess, offset: ChunkPos): TileView { + return Background(OffsetCellAccess(parent, offset)) + } } }