mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-14 09:56:37 -04:00
sky light handle block breaks, some border light fixes
This commit is contained in:
parent
7ac796f8cf
commit
ca7020a698
@ -23,10 +23,12 @@ interface AbstractSectionLight {
|
||||
|
||||
operator fun get(position: InSectionPosition): LightLevel
|
||||
|
||||
fun traceFrom(direction: Directions)
|
||||
fun traceFrom(position: InSectionPosition, direction: Directions)
|
||||
|
||||
fun clear()
|
||||
fun propagate()
|
||||
fun calculate()
|
||||
|
||||
fun update(array: LightArray)
|
||||
|
||||
|
@ -25,6 +25,7 @@ import de.bixilon.minosoft.data.world.chunk.light.section.border.TopSectionLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel
|
||||
import de.bixilon.minosoft.data.world.positions.InChunkPosition
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
import de.bixilon.minosoft.data.world.positions.SectionHeight
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inSectionHeight
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition.*
|
||||
@ -48,11 +49,7 @@ class ChunkLight(val chunk: Chunk) {
|
||||
val sectionHeight = position.sectionHeight
|
||||
val inSection = position.inSectionPosition
|
||||
|
||||
val light = when (sectionHeight) {
|
||||
chunk.minSection - 1 -> bottom[inSection]
|
||||
chunk.maxSection + 1 -> top[inSection]
|
||||
else -> chunk[sectionHeight]?.light?.get(inSection) ?: LightLevel.EMPTY
|
||||
}
|
||||
val light = chunk.light[sectionHeight]?.get(inSection) ?: LightLevel.EMPTY
|
||||
|
||||
if (position.y >= heightmap[position]) {
|
||||
return light.with(sky = LightLevel.MAX_LEVEL)
|
||||
@ -70,7 +67,7 @@ class ChunkLight(val chunk: Chunk) {
|
||||
|
||||
fun calculate() {
|
||||
for (section in chunk.sections) {
|
||||
section?.light?.calculateBlocks()
|
||||
section?.light?.calculateBlock()
|
||||
}
|
||||
calculateSky()
|
||||
}
|
||||
@ -147,4 +144,10 @@ class ChunkLight(val chunk: Chunk) {
|
||||
traceSkyDown(position, maxOf(bottomY, chunk.minSection - 1), topY)
|
||||
}
|
||||
}
|
||||
|
||||
operator fun get(height: SectionHeight) = when {
|
||||
height < chunk.minSection -> bottom
|
||||
height > chunk.maxSection -> top
|
||||
else -> chunk[height]?.light
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light.section
|
||||
|
||||
import de.bixilon.kutil.exception.Broken
|
||||
import de.bixilon.minosoft.data.Axes
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.registries.blocks.light.LightProperties
|
||||
@ -23,6 +24,7 @@ import de.bixilon.minosoft.data.world.chunk.light.types.LightArray
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel.Companion.MAX_LEVEL
|
||||
import de.bixilon.minosoft.data.world.chunk.update.chunk.SectionLightUpdate
|
||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inSectionHeight
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight
|
||||
@ -40,7 +42,7 @@ class SectionLight(
|
||||
|
||||
when {
|
||||
luminance > previousLuminance -> onIncrease(position, luminance)
|
||||
luminance < previousLuminance -> onDecrease(position)
|
||||
luminance < previousLuminance -> onDecrease(position, previousLuminance)
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,6 +60,8 @@ class SectionLight(
|
||||
|
||||
if (position.z > 0) traceFrom(position.minusZ(), Directions.NORTH) else getNeighbour(Directions.SOUTH)?.traceFrom(position.with(z = SECTION_MAX_Z), Directions.NORTH)
|
||||
if (position.z < SECTION_MAX_Z) traceFrom(position.plusZ(), Directions.SOUTH) else getNeighbour(Directions.NORTH)?.traceFrom(position.with(z = 0), Directions.SOUTH)
|
||||
|
||||
// TODO: This just handles increase in light (i.e. breaking a block), what if a block is placed?
|
||||
}
|
||||
|
||||
fun onBlockChange(position: InSectionPosition, previous: BlockState?, state: BlockState?) {
|
||||
@ -69,8 +73,37 @@ class SectionLight(
|
||||
trace(position, LightLevel(block = luminance, sky = this[position].sky), null)
|
||||
}
|
||||
|
||||
private fun onDecrease(position: InSectionPosition) {
|
||||
// TODO: Trace until next light increase (or level 0), set all those levels to 0 and then force trace all blocks in range (also from neighbours).
|
||||
private fun onDecrease(position: InSectionPosition, luminance: Int) {
|
||||
// TODO: Optimize (trace in direction and then propagate from edges and trace back again)
|
||||
|
||||
val minX = (position.x - luminance).sectionHeight
|
||||
val maxX = (position.x + luminance).sectionHeight
|
||||
|
||||
val minY = (position.y - luminance).sectionHeight
|
||||
val maxY = (position.y + luminance).sectionHeight
|
||||
|
||||
val minZ = (position.z - luminance).sectionHeight
|
||||
val maxZ = (position.z + luminance).sectionHeight
|
||||
|
||||
for (x in minX..maxX) {
|
||||
for (z in minZ..maxZ) {
|
||||
val chunk = section.chunk.neighbours.traceChunk(ChunkPosition(x, z)) ?: continue
|
||||
for (y in minY..maxY) {
|
||||
val neighbour = chunk.light[section.height + y] ?: continue
|
||||
neighbour.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
for (x in minX..maxX) {
|
||||
for (z in minZ..maxZ) {
|
||||
val chunk = section.chunk.neighbours.traceChunk(ChunkPosition(x, z)) ?: continue
|
||||
for (y in minY..maxY) {
|
||||
val neighbour = chunk.light[section.height + y] ?: continue
|
||||
neighbour.propagate()
|
||||
neighbour.calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun getOrPut(direction: Directions): SectionLight? {
|
||||
@ -231,7 +264,7 @@ class SectionLight(
|
||||
event = true
|
||||
}
|
||||
|
||||
fun calculateBlocks() {
|
||||
fun calculateBlock() {
|
||||
if (section.blocks.isEmpty) return
|
||||
val min = section.blocks.minPosition
|
||||
val max = section.blocks.maxPosition
|
||||
@ -263,12 +296,15 @@ class SectionLight(
|
||||
}
|
||||
}
|
||||
|
||||
protected fun getNeighbour(direction: Directions): AbstractSectionLight? {
|
||||
return when (direction) {
|
||||
Directions.UP -> if (section.height == section.chunk.maxSection) section.chunk.light.top else section.chunk[section.height + 1]?.light
|
||||
Directions.DOWN -> if (section.height == section.chunk.minSection) section.chunk.light.bottom else section.chunk[section.height - 1]?.light
|
||||
else -> section.chunk.neighbours[direction]?.get(section.height)?.light
|
||||
}
|
||||
override fun calculate() {
|
||||
calculateSky()
|
||||
calculateBlock()
|
||||
}
|
||||
|
||||
protected fun getNeighbour(direction: Directions) = when (direction) {
|
||||
Directions.UP -> if (section.height == section.chunk.maxSection) section.chunk.light.top else section.chunk[section.height + 1]?.light
|
||||
Directions.DOWN -> if (section.height == section.chunk.minSection) section.chunk.light.bottom else section.chunk[section.height - 1]?.light
|
||||
else -> section.chunk.neighbours[direction]?.get(section.height)?.light
|
||||
}
|
||||
|
||||
private fun propagateVertical() {
|
||||
@ -290,23 +326,20 @@ class SectionLight(
|
||||
}
|
||||
}
|
||||
|
||||
override fun traceFrom(direction: Directions) {
|
||||
if (direction.axis != Axes.Y) Broken()
|
||||
for (xz in 0 until SECTION_WIDTH_X * SECTION_WIDTH_Z) {
|
||||
traceFrom(InSectionPosition(xz), direction)
|
||||
}
|
||||
}
|
||||
|
||||
private fun propagateHorizontal() {
|
||||
val below = if (section.height == section.chunk.minSection) section.chunk.light.bottom else section.chunk[section.height - 1]?.light
|
||||
val above = if (section.height == section.chunk.maxSection) section.chunk.light.top else section.chunk[section.height + 1]?.light
|
||||
|
||||
// TODO: merge both?
|
||||
if (below != null) {
|
||||
for (xz in 0 until SECTION_WIDTH_X * SECTION_WIDTH_Z) {
|
||||
val position = InSectionPosition(xz).with(y = SECTION_MAX_Y)
|
||||
below.traceFrom(position, Directions.UP)
|
||||
}
|
||||
}
|
||||
if (above != null) {
|
||||
for (xz in 0 until SECTION_WIDTH_X * SECTION_WIDTH_Z) {
|
||||
val position = InSectionPosition(xz).with(y = 0)
|
||||
above.traceFrom(position, Directions.DOWN)
|
||||
}
|
||||
}
|
||||
below?.traceFrom(Directions.UP)
|
||||
above?.traceFrom(Directions.DOWN)
|
||||
}
|
||||
|
||||
override fun propagate() {
|
||||
|
@ -107,6 +107,8 @@ abstract class BorderSectionLight(
|
||||
return null
|
||||
}
|
||||
|
||||
override fun calculate() = Unit // TODO: bottom sky light
|
||||
|
||||
protected fun propagateVertical() {
|
||||
for (x in 0 until SECTION_MAX_X) {
|
||||
chunk.neighbours[Directions.NORTH]?.light?.bottom?.traceFrom(InSectionPosition(x, 0, SECTION_MAX_Z), Directions.SOUTH)
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light.section.border
|
||||
|
||||
import de.bixilon.kutil.exception.Broken
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightArray
|
||||
@ -31,6 +32,18 @@ class BottomSectionLight(
|
||||
|
||||
override fun Chunk.getBorderLight() = this.light.bottom
|
||||
|
||||
override fun traceFrom(direction: Directions) {
|
||||
if (direction != Directions.UP) Broken()
|
||||
val above = chunk[chunk.minSection]?.light ?: return
|
||||
for (xz in 0 until SECTION_WIDTH_X * SECTION_WIDTH_Z) {
|
||||
val position = InSectionPosition(xz)
|
||||
val current = LightLevel(light[xz])
|
||||
if (current.block <= 1) return
|
||||
|
||||
val next = current.decrease()
|
||||
above.trace(position.with(y = 0), next, Directions.UP)
|
||||
}
|
||||
}
|
||||
|
||||
override fun trace(position: InSectionPosition, level: LightLevel) {
|
||||
var level = level
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light.section.border
|
||||
|
||||
import de.bixilon.kutil.exception.Broken
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightArray
|
||||
@ -31,6 +32,19 @@ class TopSectionLight(
|
||||
|
||||
override fun Chunk.getBorderLight() = this.light.top
|
||||
|
||||
override fun traceFrom(direction: Directions) {
|
||||
if (direction != Directions.DOWN) Broken()
|
||||
val above = chunk[chunk.maxSection]?.light ?: return
|
||||
for (xz in 0 until SECTION_WIDTH_X * SECTION_WIDTH_Z) {
|
||||
val position = InSectionPosition(xz)
|
||||
val current = LightLevel(light[xz])
|
||||
if (current.block <= 1) return
|
||||
|
||||
val next = current.decrease()
|
||||
above.trace(position.with(y = SECTION_MAX_Y), next, Directions.DOWN)
|
||||
}
|
||||
}
|
||||
|
||||
override fun trace(position: InSectionPosition, level: LightLevel) {
|
||||
val current = LightLevel(light[position.xz])
|
||||
if (current.block >= level.block) return
|
||||
|
Loading…
x
Reference in New Issue
Block a user