From 4cfd3122729d0a3e18773664db4b27b0aa23de5c Mon Sep 17 00:00:00 2001 From: Moritz Zwerger Date: Thu, 13 Mar 2025 23:34:59 +0100 Subject: [PATCH] check light propagation directions --- .../world/chunk/light/section/SectionLight.kt | 73 +++++++++++++------ .../section/border/BottomSectionLight.kt | 3 +- .../light/section/border/TopSectionLight.kt | 3 +- 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/SectionLight.kt b/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/SectionLight.kt index e62f9b4f4..b78d5ac8b 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/SectionLight.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/SectionLight.kt @@ -14,13 +14,14 @@ package de.bixilon.minosoft.data.world.chunk.light.section import de.bixilon.minosoft.data.direction.Directions +import de.bixilon.minosoft.data.registries.blocks.light.TransparentProperty import de.bixilon.minosoft.data.registries.blocks.state.BlockState import de.bixilon.minosoft.data.world.chunk.ChunkSection 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.update.chunk.SectionLightUpdate import de.bixilon.minosoft.data.world.positions.InSectionPosition -import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition.* class SectionLight( private val section: ChunkSection, @@ -44,45 +45,71 @@ class SectionLight( } private fun onIncrease(position: InSectionPosition, luminance: Int) { - trace(position, LightLevel(block = luminance, sky = 0)) // TODO: sky light + trace(position, LightLevel(block = luminance, sky = 0), null) // TODO: sky light } 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). } - fun trace(position: InSectionPosition, level: LightLevel) { + fun trace(position: InSectionPosition, level: LightLevel, direction: Directions?) { val light = this[position] if (light.block >= level.block) return // light is already same or higher, no need to increase - this[position] = level - val state = section.blocks[position] + val lightProperties = state?.block?.getLightProperties(state) ?: TransparentProperty + + if (direction != null && lightProperties.propagatesLight(direction.inverted)) { + // light can not pass into from that side + return + } + + this[position] = level + if (!lightProperties.propagatesLight) return + if (level.block <= 1) return // can not decrease any further + val next = level.decrease() - // TODO: sky (trace and heightmap), check if light propagates in a direction + // TODO: sky (trace and heightmap) - if (position.x > 0) trace(position.minusX(), next) else section.neighbours?.get(Directions.O_WEST)?.light?.trace(position.with(x = ProtocolDefinition.SECTION_MAX_X), next) - if (position.x < ProtocolDefinition.SECTION_MAX_X) trace(position.plusX(), next) else section.neighbours?.get(Directions.O_EAST)?.light?.trace(position.with(x = 0), next) - - if (position.y > 0) { - trace(position.minusY(), next) - } else if (section.height > section.chunk.minSection) { - section.neighbours?.get(Directions.O_DOWN)?.light?.trace(position.with(y = ProtocolDefinition.SECTION_MAX_Y), next) - } else { - section.chunk.light.bottom.trace(position.with(y = ProtocolDefinition.SECTION_MAX_Y), next) + if (lightProperties.propagatesLight(Directions.WEST)) { + val neighbour = if (position.x > 0) this else section.neighbours?.get(Directions.O_WEST)?.light + neighbour?.trace(if (position.x > 0) position.minusX() else position.with(x = SECTION_MAX_X), next, Directions.WEST) } - if (position.y < ProtocolDefinition.SECTION_MAX_Y) { - trace(position.plusY(), next) - } else if (section.height < section.chunk.maxSection) { - section.neighbours?.get(Directions.O_UP)?.light?.trace(position.with(y = 0), next) - } else { - section.chunk.light.top.trace(position.with(y = 0), next) + if (lightProperties.propagatesLight(Directions.EAST)) { + val neighbour = if (position.x < SECTION_MAX_X) this else section.neighbours?.get(Directions.O_EAST)?.light + neighbour?.trace(if (position.x < SECTION_MAX_X) position.plusX() else position.with(x = 0), next, Directions.EAST) } - if (position.z > 0) trace(position.minusZ(), next) else section.neighbours?.get(Directions.O_NORTH)?.light?.trace(position.with(z = ProtocolDefinition.SECTION_MAX_Y), next) - if (position.z < ProtocolDefinition.SECTION_MAX_Z) trace(position.plusZ(), next) else section.neighbours?.get(Directions.O_SOUTH)?.light?.trace(position.with(z = 0), next) + + if (lightProperties.propagatesLight(Directions.UP)) { + if (position.y > 0) { + trace(position.minusY(), next, Directions.UP) + } else if (section.height > section.chunk.minSection) { + section.neighbours?.get(Directions.O_DOWN)?.light?.trace(position.with(y = SECTION_MAX_Y), next, Directions.UP) + } else { + section.chunk.light.bottom.trace(position.with(y = SECTION_MAX_Y), next) + } + } + if (lightProperties.propagatesLight(Directions.DOWN)) { + if (position.y < SECTION_MAX_Y) { + trace(position.plusY(), next, Directions.DOWN) + } else if (section.height < section.chunk.maxSection) { + section.neighbours?.get(Directions.O_UP)?.light?.trace(position.with(y = 0), next, Directions.DOWN) + } else { + section.chunk.light.top.trace(position.with(y = 0), next) + } + } + + if (lightProperties.propagatesLight(Directions.NORTH)) { + val neighbour = if (position.z > 0) this else section.neighbours?.get(Directions.O_NORTH)?.light + neighbour?.trace(if (position.z > 0) position.minusZ() else position.with(z = SECTION_MAX_Z), next, Directions.NORTH) + } + if (lightProperties.propagatesLight(Directions.SOUTH)) { + val neighbour = if (position.z < SECTION_MAX_Z) this else section.neighbours?.get(Directions.O_SOUTH)?.light + neighbour?.trace(if (position.z < SECTION_MAX_Z) position.plusZ() else position.with(z = 0), next, Directions.SOUTH) + } } diff --git a/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/border/BottomSectionLight.kt b/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/border/BottomSectionLight.kt index 8eff83b38..0c91ec26f 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/border/BottomSectionLight.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/border/BottomSectionLight.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.data.world.chunk.light.section.border import de.bixilon.kutil.array.ArrayUtil.getFirst +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 import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel @@ -42,7 +43,7 @@ class BottomSectionLight( val next = current.decrease() - chunk.sections.getFirst()?.light?.trace(position.with(y = ProtocolDefinition.SECTION_MAX_Y), next) + chunk.sections.getFirst()?.light?.trace(position.with(y = ProtocolDefinition.SECTION_MAX_Y), next, Directions.UP) traceVertical(position, next) } diff --git a/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/border/TopSectionLight.kt b/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/border/TopSectionLight.kt index 79925948a..5252c4c27 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/border/TopSectionLight.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/chunk/light/section/border/TopSectionLight.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.data.world.chunk.light.section.border import de.bixilon.kutil.array.ArrayUtil.getLast +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 import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel @@ -40,7 +41,7 @@ class TopSectionLight( val next = LightLevel(block = current.block, sky = 0) // remove sky light, its always max - chunk.sections.getLast()?.light?.trace(position.with(y = ProtocolDefinition.SECTION_MAX_Y), next) + chunk.sections.getLast()?.light?.trace(position.with(y = ProtocolDefinition.SECTION_MAX_Y), next, Directions.DOWN) traceVertical(position, next) }