mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 19:35:00 -04:00
some light cleanup, datatype: light level (inlined)
This commit is contained in:
parent
d6223cf873
commit
f0d70af460
@ -31,7 +31,7 @@ import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
||||
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
|
||||
import de.bixilon.minosoft.data.world.World
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.ChunkLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.section.ChunkLight
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours
|
||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
|
@ -22,7 +22,7 @@ import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
|
||||
import de.bixilon.minosoft.data.world.World
|
||||
import de.bixilon.minosoft.data.world.biome.WorldBiomes
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.ChunkLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.section.ChunkLight
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours
|
||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
|
@ -31,6 +31,7 @@ object DebugOptions {
|
||||
const val FORCE_CHECK_UPDATES = false
|
||||
|
||||
const val VERIFY_COORDINATES = true
|
||||
const val VERIFY_LIGHT_LEVEL = true
|
||||
|
||||
// Add a test to ensure that all options are disabled!!!
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2024 Moritz Zwerger
|
||||
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
@ -22,8 +22,8 @@ import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.data.text.BaseComponent
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.data.world.chunk.light.SectionLight.Companion.BLOCK_LIGHT_MASK
|
||||
import de.bixilon.minosoft.data.world.chunk.light.SectionLight.Companion.SKY_LIGHT_MASK
|
||||
import de.bixilon.minosoft.data.text.TextComponent
|
||||
import de.bixilon.minosoft.data.text.formatting.color.ChatColors
|
||||
import de.bixilon.minosoft.protocol.network.session.play.PlaySession
|
||||
|
||||
open class CropBlock(resourceLocation: ResourceLocation, registries: Registries, data: Map<String, Any>) : PlantBlock(resourceLocation, registries, data), BlockWawlaProvider {
|
||||
@ -35,14 +35,11 @@ open class CropBlock(resourceLocation: ResourceLocation, registries: Registries,
|
||||
override fun getWawlaInformation(session: PlaySession, target: BlockTarget): ChatComponent {
|
||||
val light = session.world.getLight(target.blockPosition)
|
||||
|
||||
val blockLight = light and BLOCK_LIGHT_MASK
|
||||
val skyLight = (light and SKY_LIGHT_MASK) shr 4
|
||||
|
||||
val component = BaseComponent("Light: ")
|
||||
|
||||
component += if (blockLight < MIN_LIGHT_LEVEL) "§4$blockLight§r" else "§a$blockLight§r"
|
||||
component += TextComponent(light.block).color(if (light.block < MIN_LIGHT_LEVEL) ChatColors.RED else ChatColors.GREEN)
|
||||
|
||||
component += " ($skyLight)"
|
||||
component += " (${light.sky})"
|
||||
|
||||
return component
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2023 Moritz Zwerger
|
||||
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
@ -21,6 +21,7 @@ import de.bixilon.minosoft.data.text.TextComponent
|
||||
import de.bixilon.minosoft.data.text.formatting.TextFormattable
|
||||
import org.checkerframework.common.value.qual.IntRange
|
||||
|
||||
// TODO: JvmInline value class
|
||||
class RGBColor(val rgba: Int) : TextFormattable {
|
||||
val ansi: String get() = ANSI.rgb(red, green, blue)
|
||||
|
||||
|
@ -28,8 +28,8 @@ import de.bixilon.minosoft.data.world.audio.WorldAudioPlayer
|
||||
import de.bixilon.minosoft.data.world.biome.WorldBiomes
|
||||
import de.bixilon.minosoft.data.world.border.WorldBorder
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.ChunkLightUtil.hasSkyLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.SectionLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.section.ChunkLightUtil.hasSkyLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel
|
||||
import de.bixilon.minosoft.data.world.chunk.manager.ChunkManager
|
||||
import de.bixilon.minosoft.data.world.difficulty.WorldDifficulty
|
||||
import de.bixilon.minosoft.data.world.entities.WorldEntities
|
||||
@ -177,17 +177,17 @@ class World(
|
||||
return !iterator.hasCollisions(entity, aabb, fluids)
|
||||
}
|
||||
|
||||
fun getLight(position: BlockPosition): Int {
|
||||
return chunks[position.chunkPosition]?.light?.get(position.inChunkPosition) ?: 0x00
|
||||
fun getLight(position: BlockPosition): LightLevel {
|
||||
return chunks[position.chunkPosition]?.light?.get(position.inChunkPosition) ?: LightLevel.EMPTY
|
||||
}
|
||||
|
||||
fun getBrightness(position: BlockPosition): Float {
|
||||
val light = getLight(position)
|
||||
var level = light and SectionLight.BLOCK_LIGHT_MASK
|
||||
val level = getLight(position)
|
||||
var max = level.block
|
||||
if (dimension.hasSkyLight()) {
|
||||
level = maxOf(level, light and SectionLight.SKY_LIGHT_MASK shr 4)
|
||||
max = maxOf(max, level.sky)
|
||||
}
|
||||
return dimension.ambientLight[level]
|
||||
return dimension.ambientLight[max]
|
||||
}
|
||||
|
||||
fun recalculateLight(heightmap: Boolean = false) {
|
||||
|
@ -16,7 +16,7 @@ import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.SectionLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.section.SectionLight
|
||||
import de.bixilon.minosoft.data.world.container.SectionDataProvider
|
||||
import de.bixilon.minosoft.data.world.container.biome.BiomeSectionDataProvider
|
||||
import de.bixilon.minosoft.data.world.container.block.BlockSectionDataProvider
|
||||
|
@ -21,7 +21,7 @@ import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.entity.BlockWithEntity
|
||||
import de.bixilon.minosoft.data.world.biome.source.BiomeSource
|
||||
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
||||
import de.bixilon.minosoft.data.world.chunk.light.ChunkLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.section.ChunkLight
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours
|
||||
import de.bixilon.minosoft.data.world.chunk.update.block.ChunkLocalBlockUpdate
|
||||
import de.bixilon.minosoft.data.world.chunk.update.block.SingleBlockUpdate
|
||||
|
@ -19,7 +19,7 @@ import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.entity.BlockWithEntity
|
||||
import de.bixilon.minosoft.data.world.biome.source.BiomeSource
|
||||
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
||||
import de.bixilon.minosoft.data.world.chunk.light.LightArray
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightArray
|
||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||
import de.bixilon.minosoft.data.world.positions.InChunkPosition
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light
|
||||
|
||||
import de.bixilon.minosoft.config.DebugOptions
|
||||
|
||||
object LightUtil {
|
||||
|
||||
inline fun assertLight(condition: Boolean) {
|
||||
if (!DebugOptions.VERIFY_LIGHT_LEVEL) return
|
||||
if (!condition) throw AssertionError("Invalid light level!")
|
||||
}
|
||||
}
|
@ -11,13 +11,14 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light
|
||||
package de.bixilon.minosoft.data.world.chunk.light.section
|
||||
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
|
||||
abstract class AbstractSectionLight {
|
||||
open var update = false
|
||||
|
||||
|
||||
abstract operator fun get(position: InSectionPosition): Byte
|
||||
abstract operator fun get(position: InSectionPosition): LightLevel
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light
|
||||
package de.bixilon.minosoft.data.world.chunk.light.section
|
||||
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||
@ -19,7 +19,10 @@ import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.heightmap.FixedHeightmap
|
||||
import de.bixilon.minosoft.data.world.chunk.heightmap.LightHeightmap
|
||||
import de.bixilon.minosoft.data.world.chunk.light.ChunkLightUtil.hasSkyLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.section.ChunkLightUtil.hasSkyLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.section.border.BottomSectionLight
|
||||
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.chunk.neighbours.ChunkNeighbourArray
|
||||
import de.bixilon.minosoft.data.world.chunk.update.AbstractWorldUpdate
|
||||
import de.bixilon.minosoft.data.world.chunk.update.chunk.ChunkLightUpdate
|
||||
@ -31,8 +34,8 @@ class ChunkLight(val chunk: Chunk) {
|
||||
private val session = chunk.session
|
||||
val heightmap = if (chunk.world.dimension.hasSkyLight()) LightHeightmap(chunk) else FixedHeightmap.MAX_VALUE
|
||||
|
||||
val bottom = BorderSectionLight(false, chunk)
|
||||
val top = BorderSectionLight(true, chunk)
|
||||
val bottom = BottomSectionLight(chunk)
|
||||
val top = TopSectionLight(chunk)
|
||||
|
||||
val sky = ChunkSkyLight(this)
|
||||
|
||||
@ -101,19 +104,19 @@ class ChunkLight(val chunk: Chunk) {
|
||||
}
|
||||
|
||||
|
||||
operator fun get(position: InChunkPosition): Int {
|
||||
operator fun get(position: InChunkPosition): LightLevel {
|
||||
val sectionHeight = position.sectionHeight
|
||||
val inSection = position.inSectionPosition
|
||||
|
||||
val light = when (sectionHeight) {
|
||||
chunk.minSection - 1 -> bottom[inSection].toInt()
|
||||
chunk.maxSection + 1 -> return top[inSection].toInt() or SectionLight.SKY_LIGHT_MASK // top has always sky=15
|
||||
else -> chunk[sectionHeight]?.light?.get(inSection)?.toInt() ?: 0x00
|
||||
} and 0xFF
|
||||
chunk.minSection - 1 -> bottom[inSection]
|
||||
chunk.maxSection + 1 -> return top[inSection].with(sky = LightLevel.MAX_LEVEL) // top has always sky=15; TODO: only if dimension has skylight?
|
||||
else -> chunk[sectionHeight]?.light?.get(inSection) ?: LightLevel.EMPTY
|
||||
}
|
||||
|
||||
if (position.y >= heightmap[position]) {
|
||||
// set sky=15
|
||||
return light or SectionLight.SKY_LIGHT_MASK
|
||||
return light.with(sky = LightLevel.MAX_LEVEL)
|
||||
}
|
||||
return light
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2023 Moritz Zwerger
|
||||
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
@ -11,7 +11,7 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light
|
||||
package de.bixilon.minosoft.data.world.chunk.light.section
|
||||
|
||||
import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
|
||||
|
@ -11,10 +11,10 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light
|
||||
package de.bixilon.minosoft.data.world.chunk.light.section
|
||||
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.world.chunk.light.ChunkLightUtil.hasSkyLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.section.ChunkLightUtil.hasSkyLight
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbourArray
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
import de.bixilon.minosoft.data.world.positions.SectionHeight
|
@ -11,13 +11,15 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light
|
||||
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.ChunkSkyLight.Companion.NEIGHBOUR_TRACE_LEVEL
|
||||
import de.bixilon.minosoft.data.world.chunk.light.section.ChunkSkyLight.Companion.NEIGHBOUR_TRACE_LEVEL
|
||||
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.neighbours.ChunkNeighbourArray
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
@ -54,7 +56,7 @@ class SectionLight(
|
||||
|
||||
private fun startDecreaseTrace(position: InSectionPosition) {
|
||||
// that is kind of hacky, but far easier and kind of faster
|
||||
val light = this.light[position].toInt() and BLOCK_LIGHT_MASK
|
||||
val light = this.light[position].block
|
||||
|
||||
decreaseLight(position, light, true) // just clear the light
|
||||
decreaseLight(position, light, false) // increase the light in all sections
|
||||
@ -132,13 +134,13 @@ class SectionLight(
|
||||
}
|
||||
|
||||
// get block or next luminance level
|
||||
val blockSkyLight = this.light[position].toInt()
|
||||
val currentLight = blockSkyLight and BLOCK_LIGHT_MASK // we just care about block light
|
||||
val level = this.light[position]
|
||||
val currentLight = level.block // we just care about block light
|
||||
if (currentLight >= nextLuminance) {
|
||||
// light is already higher, no need to trace
|
||||
return
|
||||
}
|
||||
this.light[position] = ((blockSkyLight and SKY_LIGHT_MASK) or nextLuminance) // keep the sky light set
|
||||
this.light[position] = level.with(block = nextLuminance) // keep the sky light set
|
||||
if (!update) {
|
||||
update = true
|
||||
}
|
||||
@ -269,13 +271,13 @@ class SectionLight(
|
||||
for (y in 0 until ProtocolDefinition.SECTION_HEIGHT_Y) {
|
||||
for (z in 0 until ProtocolDefinition.SECTION_WIDTH_Z) {
|
||||
val totalY = baseY + y
|
||||
neighbours[Directions.O_WEST]?.light?.get(InSectionPosition(ProtocolDefinition.SECTION_MAX_Z, y, z))?.toInt()?.let { light ->
|
||||
(light and BLOCK_LIGHT_MASK).let { if (it > 1) traceBlockIncrease(InSectionPosition(0, y, z), it - 1, Directions.EAST) }
|
||||
(light and SKY_LIGHT_MASK shr 4).let { if (it > 1) traceSkyLightIncrease(InSectionPosition(0, y, z), it - 1, Directions.EAST, totalY) }
|
||||
neighbours[Directions.O_WEST]?.light?.get(InSectionPosition(ProtocolDefinition.SECTION_MAX_Z, y, z))?.let { light ->
|
||||
light.block.let { if (it > 1) traceBlockIncrease(InSectionPosition(0, y, z), it - 1, Directions.EAST) }
|
||||
light.sky.let { if (it > 1) traceSkyLightIncrease(InSectionPosition(0, y, z), it - 1, Directions.EAST, totalY) }
|
||||
}
|
||||
neighbours[Directions.O_EAST]?.light?.get(InSectionPosition(0, y, z))?.toInt()?.let { light ->
|
||||
(light and BLOCK_LIGHT_MASK).let { if (it > 1) traceBlockIncrease(InSectionPosition(ProtocolDefinition.SECTION_MAX_X, y, z), it - 1, Directions.WEST) }
|
||||
(light and SKY_LIGHT_MASK shr 4).let { if (it > 1) traceSkyLightIncrease(InSectionPosition(ProtocolDefinition.SECTION_MAX_X, y, z), it - 1, Directions.WEST, totalY) }
|
||||
neighbours[Directions.O_EAST]?.light?.get(InSectionPosition(0, y, z))?.let { light ->
|
||||
light.block.let { if (it > 1) traceBlockIncrease(InSectionPosition(ProtocolDefinition.SECTION_MAX_X, y, z), it - 1, Directions.WEST) }
|
||||
light.sky.let { if (it > 1) traceSkyLightIncrease(InSectionPosition(ProtocolDefinition.SECTION_MAX_X, y, z), it - 1, Directions.WEST, totalY) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -284,13 +286,13 @@ class SectionLight(
|
||||
private fun propagateZ(baseY: Int, neighbours: Array<ChunkSection?>, x: Int) {
|
||||
for (y in 0 until ProtocolDefinition.SECTION_HEIGHT_Y) {
|
||||
val totalY = baseY + y
|
||||
neighbours[Directions.O_NORTH]?.light?.get(InSectionPosition(x, y, ProtocolDefinition.SECTION_MAX_Z))?.toInt()?.let { light ->
|
||||
(light and BLOCK_LIGHT_MASK).let { if (it > 1) traceBlockIncrease(InSectionPosition(x, y, 0), it - 1, Directions.SOUTH) }
|
||||
(light and SKY_LIGHT_MASK shr 4).let { if (it > 1) traceSkyLightIncrease(InSectionPosition(x, y, 0), it - 1, Directions.SOUTH, totalY) }
|
||||
neighbours[Directions.O_NORTH]?.light?.get(InSectionPosition(x, y, ProtocolDefinition.SECTION_MAX_Z))?.let { light ->
|
||||
light.block.let { if (it > 1) traceBlockIncrease(InSectionPosition(x, y, 0), it - 1, Directions.SOUTH) }
|
||||
light.sky.let { if (it > 1) traceSkyLightIncrease(InSectionPosition(x, y, 0), it - 1, Directions.SOUTH, totalY) }
|
||||
}
|
||||
neighbours[Directions.O_SOUTH]?.light?.get(InSectionPosition(x, y, 0))?.toInt()?.let { light ->
|
||||
(light and BLOCK_LIGHT_MASK).let { if (it > 1) traceBlockIncrease(InSectionPosition(x, y, ProtocolDefinition.SECTION_MAX_Z), it - 1, Directions.NORTH) }
|
||||
(light and SKY_LIGHT_MASK shr 4).let { if (it > 1) traceSkyLightIncrease(InSectionPosition(x, y, ProtocolDefinition.SECTION_MAX_Z), it - 1, Directions.NORTH, totalY) }
|
||||
neighbours[Directions.O_SOUTH]?.light?.get(InSectionPosition(x, y, 0))?.let { light ->
|
||||
light.block.let { if (it > 1) traceBlockIncrease(InSectionPosition(x, y, ProtocolDefinition.SECTION_MAX_Z), it - 1, Directions.NORTH) }
|
||||
light.sky.let { if (it > 1) traceSkyLightIncrease(InSectionPosition(x, y, ProtocolDefinition.SECTION_MAX_Z), it - 1, Directions.NORTH, totalY) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -298,13 +300,13 @@ class SectionLight(
|
||||
private fun propagateY(neighbours: Array<ChunkSection?>, x: Int, baseY: Int) {
|
||||
// ToDo: Border light
|
||||
for (z in 0 until ProtocolDefinition.SECTION_WIDTH_Z) {
|
||||
neighbours[Directions.O_DOWN]?.light?.get(InSectionPosition(x, ProtocolDefinition.SECTION_MAX_Y, z))?.toInt()?.let { light ->
|
||||
(light and BLOCK_LIGHT_MASK).let { if (it > 1) traceBlockIncrease(InSectionPosition(x, 0, z), it - 1, Directions.UP) }
|
||||
(light and SKY_LIGHT_MASK shr 4).let { if (it > 1) traceSkyLightIncrease(InSectionPosition(x, 0, z), it - 1, Directions.UP, baseY + 0) } // ToDo: Is that possible?
|
||||
neighbours[Directions.O_DOWN]?.light?.get(InSectionPosition(x, ProtocolDefinition.SECTION_MAX_Y, z))?.let { light ->
|
||||
light.block.let { if (it > 1) traceBlockIncrease(InSectionPosition(x, 0, z), it - 1, Directions.UP) }
|
||||
light.sky.let { if (it > 1) traceSkyLightIncrease(InSectionPosition(x, 0, z), it - 1, Directions.UP, baseY + 0) } // ToDo: Is that possible?
|
||||
}
|
||||
neighbours[Directions.O_UP]?.light?.get(InSectionPosition(x, 0, z))?.toInt()?.let { light ->
|
||||
(light and BLOCK_LIGHT_MASK).let { if (it > 1) traceBlockIncrease(InSectionPosition(x, ProtocolDefinition.SECTION_MAX_Y, z), it - 1, Directions.DOWN) }
|
||||
(light and SKY_LIGHT_MASK shr 4).let { if (it > 1) traceSkyLightIncrease(InSectionPosition(x, ProtocolDefinition.SECTION_MAX_Y, z), it - 1, Directions.DOWN, baseY + ProtocolDefinition.SECTION_MAX_Y) }
|
||||
neighbours[Directions.O_UP]?.light?.get(InSectionPosition(x, 0, z))?.let { light ->
|
||||
light.block.let { if (it > 1) traceBlockIncrease(InSectionPosition(x, ProtocolDefinition.SECTION_MAX_Y, z), it - 1, Directions.DOWN) }
|
||||
light.sky.let { if (it > 1) traceSkyLightIncrease(InSectionPosition(x, ProtocolDefinition.SECTION_MAX_Y, z), it - 1, Directions.DOWN, baseY + ProtocolDefinition.SECTION_MAX_Y) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -317,8 +319,8 @@ class SectionLight(
|
||||
return
|
||||
}
|
||||
val chunkNeighbours = chunk.neighbours.neighbours
|
||||
val currentLight = this[position].toInt()
|
||||
if (((currentLight and SKY_LIGHT_MASK) shr 4) >= nextLevel) {
|
||||
val light = this[position]
|
||||
if (light.sky >= nextLevel) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -333,7 +335,7 @@ class SectionLight(
|
||||
|
||||
val neighbours = this.section.neighbours ?: return
|
||||
|
||||
this.light[position] = ((currentLight and BLOCK_LIGHT_MASK) or (nextLevel shl 4)).toByte()
|
||||
this.light[position] = light.with(sky = nextLevel)
|
||||
|
||||
if (!update) {
|
||||
update = true
|
||||
@ -411,7 +413,7 @@ class SectionLight(
|
||||
|
||||
val neighbours = this.section.neighbours ?: return
|
||||
|
||||
this.light[position] = ((this[position].toInt() and BLOCK_LIGHT_MASK) or (ProtocolDefinition.MAX_LIGHT_LEVEL_I shl 4)).toByte()
|
||||
this.light[position] = this.light[position].with(sky = ProtocolDefinition.MAX_LIGHT_LEVEL_I)
|
||||
|
||||
if (!update) {
|
||||
update = true
|
||||
@ -434,59 +436,46 @@ class SectionLight(
|
||||
fun propagateFromNeighbours(position: InSectionPosition) {
|
||||
val neighbours = section.neighbours ?: return
|
||||
|
||||
// TODO: those 2 values are boxed in wrapper classes (slow!)
|
||||
var skyLight = 0
|
||||
var blockLight = 0
|
||||
var level = LightLevel(0, 0)
|
||||
|
||||
|
||||
fun pushLight(light: Byte) {
|
||||
val nextSkyLight = light.toInt() and SKY_LIGHT_MASK shr 4
|
||||
if (nextSkyLight > skyLight) {
|
||||
skyLight = nextSkyLight
|
||||
}
|
||||
val nextBlockLight = light.toInt() and BLOCK_LIGHT_MASK
|
||||
if (nextBlockLight > blockLight) {
|
||||
blockLight = nextBlockLight
|
||||
}
|
||||
}
|
||||
|
||||
// ToDo: check if light can exit block at side or can enter block at neighbour
|
||||
|
||||
if (position.x > 0) {
|
||||
pushLight(this[position.minusX()])
|
||||
level = level.max(this[position.minusX()])
|
||||
} else {
|
||||
neighbours[Directions.O_WEST]?.light?.get(position.with(x = ProtocolDefinition.SECTION_MAX_X))?.let { pushLight(it) }
|
||||
neighbours[Directions.O_WEST]?.light?.get(position.with(x = ProtocolDefinition.SECTION_MAX_X))?.let { level = level.max(it) }
|
||||
}
|
||||
if (position.x < ProtocolDefinition.SECTION_MAX_X) {
|
||||
pushLight(this[position.plusX()])
|
||||
level = level.max(this[position.plusX()])
|
||||
} else {
|
||||
neighbours[Directions.O_EAST]?.light?.get(position.with(x = 0))?.let { pushLight(it) }
|
||||
neighbours[Directions.O_EAST]?.light?.get(position.with(x = 0))?.let { level = level.max(it) }
|
||||
}
|
||||
|
||||
if (position.y > 0) {
|
||||
pushLight(this[position.minusY()])
|
||||
level = level.max(this[position.minusY()])
|
||||
} else {
|
||||
neighbours[Directions.O_DOWN]?.light?.get(position.with(y = ProtocolDefinition.SECTION_MAX_Y))?.let { pushLight(it) }
|
||||
neighbours[Directions.O_DOWN]?.light?.get(position.with(y = ProtocolDefinition.SECTION_MAX_Y))?.let { level = level.max(it) }
|
||||
}
|
||||
|
||||
if (position.y < ProtocolDefinition.SECTION_MAX_Y) {
|
||||
pushLight(this[position.plusY()])
|
||||
level = level.max(this[position.plusY()])
|
||||
} else {
|
||||
neighbours[Directions.O_UP]?.light?.get(position.with(y = 0))?.let { pushLight(it) }
|
||||
neighbours[Directions.O_UP]?.light?.get(position.with(y = 0))?.let { level = level.max(it) }
|
||||
}
|
||||
|
||||
if (position.z > 0) {
|
||||
pushLight(this[position.minusZ()])
|
||||
level = level.max(this[position.minusZ()])
|
||||
} else {
|
||||
neighbours[Directions.O_NORTH]?.light?.get(position.with(z = ProtocolDefinition.SECTION_MAX_Z))?.let { pushLight(it) }
|
||||
neighbours[Directions.O_NORTH]?.light?.get(position.with(z = ProtocolDefinition.SECTION_MAX_Z))?.let { level = level.max(it) }
|
||||
}
|
||||
if (position.z < ProtocolDefinition.SECTION_MAX_Z) {
|
||||
pushLight(this[position.plusZ()])
|
||||
level = level.max(this[position.plusZ()])
|
||||
} else {
|
||||
neighbours[Directions.O_SOUTH]?.light?.get(position.with(z = 0))?.let { pushLight(it) }
|
||||
neighbours[Directions.O_SOUTH]?.light?.get(position.with(z = 0))?.let { level = level.max(it) }
|
||||
}
|
||||
|
||||
traceBlockIncrease(position, blockLight - 1, null)
|
||||
traceBlockIncrease(position, level.block - 1, null)
|
||||
|
||||
val totalY = section.height * ProtocolDefinition.SECTION_HEIGHT_Y + position.y
|
||||
section.chunk.let {
|
||||
@ -495,16 +484,11 @@ class SectionLight(
|
||||
if (!it.neighbours.complete) return@let
|
||||
val minHeight = it.light.sky.getNeighbourMinHeight(chunkNeighbours, position.x, position.z)
|
||||
if (totalY > minHeight) {
|
||||
skyLight = ProtocolDefinition.MAX_LIGHT_LEVEL_I
|
||||
level = level.with(sky = ProtocolDefinition.MAX_LIGHT_LEVEL_I)
|
||||
}
|
||||
}
|
||||
traceSkyLightIncrease(position, skyLight - 1, null, totalY)
|
||||
traceSkyLightIncrease(position, level.sky - 1, null, totalY)
|
||||
}
|
||||
|
||||
override fun get(position: InSectionPosition) = light[position]
|
||||
|
||||
companion object {
|
||||
const val BLOCK_LIGHT_MASK = 0x0F
|
||||
const val SKY_LIGHT_MASK = 0xF0
|
||||
}
|
||||
}
|
@ -11,45 +11,47 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light
|
||||
package de.bixilon.minosoft.data.world.chunk.light.section.border
|
||||
|
||||
import de.bixilon.kutil.array.ArrayUtil.getFirst
|
||||
import de.bixilon.kutil.array.ArrayUtil.getLast
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.section.AbstractSectionLight
|
||||
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.positions.InSectionPosition
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import java.util.*
|
||||
|
||||
class BorderSectionLight(
|
||||
val top: Boolean,
|
||||
abstract class BorderSectionLight(
|
||||
val chunk: Chunk,
|
||||
) : AbstractSectionLight() {
|
||||
val light = ByteArray(ProtocolDefinition.SECTION_WIDTH_X * ProtocolDefinition.SECTION_WIDTH_Z)
|
||||
|
||||
override fun get(position: InSectionPosition): Byte {
|
||||
if ((top && position.y == 0) || (!top && position.y == ProtocolDefinition.SECTION_MAX_Y)) {
|
||||
return light[position.xz]
|
||||
}
|
||||
return 0x00
|
||||
protected abstract fun getNearestSection(): ChunkSection?
|
||||
protected abstract fun Chunk.getBorderLight(): BorderSectionLight
|
||||
|
||||
protected inline operator fun get(index: Int) = LightLevel(this.light[index])
|
||||
protected inline operator fun set(index: Int, value: LightLevel) {
|
||||
this.light[index] = value.index
|
||||
}
|
||||
|
||||
private fun updateY() {
|
||||
// we can not further increase the light
|
||||
if (top) {
|
||||
chunk.sections.getLast()?.light?.apply { if (!update) update = true }
|
||||
} else {
|
||||
chunk.sections.getFirst()?.light?.apply { if (!update) update = true }
|
||||
}
|
||||
val section = getNearestSection()
|
||||
section?.light?.apply { if (!update) update = true }
|
||||
}
|
||||
|
||||
fun traceBlockIncrease(x: Int, z: Int, nextLuminance: Int) {
|
||||
val index = z shl 4 or x
|
||||
val currentLight = light[index].toInt() and SectionLight.BLOCK_LIGHT_MASK
|
||||
if (currentLight >= nextLuminance) {
|
||||
val currentLight = this[index]
|
||||
if (currentLight.block >= nextLuminance) {
|
||||
// light is already higher, no need to trace
|
||||
return
|
||||
}
|
||||
this.light[index] = ((this.light[index].toInt() and SectionLight.SKY_LIGHT_MASK) or nextLuminance).toByte()
|
||||
this[index] = currentLight.with(block = nextLuminance)
|
||||
|
||||
if (!update) {
|
||||
update = true
|
||||
@ -61,7 +63,7 @@ class BorderSectionLight(
|
||||
}
|
||||
val neighbourLuminance = nextLuminance - 1
|
||||
|
||||
if (top) {
|
||||
if (this is TopSectionLight) { // TODO: slow check
|
||||
chunk.sections.getLast()?.light?.traceBlockIncrease(InSectionPosition(x, ProtocolDefinition.SECTION_MAX_Y, z), neighbourLuminance, Directions.DOWN)
|
||||
} else {
|
||||
chunk.sections.getFirst()?.light?.traceBlockIncrease(InSectionPosition(x, 0, z), neighbourLuminance, Directions.UP)
|
||||
@ -90,19 +92,15 @@ class BorderSectionLight(
|
||||
}
|
||||
}
|
||||
|
||||
private fun Chunk.getBorderLight(): BorderSectionLight {
|
||||
return if (top) light.top else light.bottom
|
||||
}
|
||||
|
||||
fun traceSkyIncrease(x: Int, z: Int, nextLevel: Int) {
|
||||
// TODO: check heightmap
|
||||
val index = z shl 4 or x
|
||||
val light = light[index].toInt()
|
||||
if ((light and SectionLight.SKY_LIGHT_MASK shr 4) >= nextLevel) {
|
||||
val light = this[index]
|
||||
if (light.sky >= nextLevel) {
|
||||
// light is already higher, no need to trace
|
||||
return
|
||||
}
|
||||
this.light[index] = ((light and SectionLight.BLOCK_LIGHT_MASK) or (nextLevel shl 4)).toByte()
|
||||
this[index] = light.with(sky = nextLevel)
|
||||
|
||||
if (!update) {
|
||||
update = true
|
||||
@ -114,7 +112,7 @@ class BorderSectionLight(
|
||||
}
|
||||
val neighbourLevel = nextLevel - 1
|
||||
|
||||
if (top) {
|
||||
if (this is TopSectionLight) { // TOOD: slow check
|
||||
chunk.sections.getLast()?.light?.traceSkyLightIncrease(InSectionPosition(x, ProtocolDefinition.SECTION_MAX_Y, z), neighbourLevel, Directions.DOWN, chunk.maxSection * ProtocolDefinition.SECTION_HEIGHT_Y + ProtocolDefinition.SECTION_MAX_Y)
|
||||
} else {
|
||||
chunk.sections.getFirst()?.light?.traceSkyLightIncrease(InSectionPosition(x, 0, z), neighbourLevel, Directions.UP, chunk.minSection * ProtocolDefinition.SECTION_HEIGHT_Y)
|
||||
@ -170,9 +168,7 @@ class BorderSectionLight(
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
for (i in light.indices) {
|
||||
light[i] = 0x00
|
||||
}
|
||||
Arrays.fill(this.light, 0x00)
|
||||
}
|
||||
|
||||
fun update(array: LightArray) {
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light.section.border
|
||||
|
||||
import de.bixilon.kutil.array.ArrayUtil.getFirst
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
|
||||
class BottomSectionLight(
|
||||
chunk: Chunk,
|
||||
) : BorderSectionLight(chunk) {
|
||||
|
||||
override fun get(position: InSectionPosition): LightLevel {
|
||||
if (position.y != ProtocolDefinition.SECTION_MAX_Y) return LightLevel.EMPTY
|
||||
return LightLevel(this.light[position.xz])
|
||||
}
|
||||
|
||||
override fun getNearestSection() = chunk.sections.getFirst()
|
||||
override fun Chunk.getBorderLight() = this.light.bottom
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light.section.border
|
||||
|
||||
import de.bixilon.kutil.array.ArrayUtil.getLast
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
|
||||
class TopSectionLight(
|
||||
chunk: Chunk,
|
||||
) : BorderSectionLight(chunk) {
|
||||
|
||||
override fun get(position: InSectionPosition): LightLevel {
|
||||
if (position.y != 0) return LightLevel.EMPTY
|
||||
return LightLevel(this.light[position.xz])
|
||||
}
|
||||
|
||||
override fun getNearestSection() = chunk.sections.getLast()
|
||||
override fun Chunk.getBorderLight() = this.light.top
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light
|
||||
package de.bixilon.minosoft.data.world.chunk.light.types
|
||||
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
@ -20,13 +20,9 @@ import java.util.*
|
||||
@JvmInline
|
||||
value class LightArray(inline val array: ByteArray = ByteArray(ProtocolDefinition.BLOCKS_PER_SECTION)) {
|
||||
|
||||
inline operator fun get(position: InSectionPosition) = array[position.index]
|
||||
inline operator fun set(position: InSectionPosition, value: Byte) {
|
||||
array[position.index] = value
|
||||
}
|
||||
|
||||
inline operator fun set(position: InSectionPosition, value: Int) {
|
||||
array[position.index] = value.toByte()
|
||||
inline operator fun get(position: InSectionPosition) = LightLevel(array[position.index])
|
||||
inline operator fun set(position: InSectionPosition, value: LightLevel) {
|
||||
array[position.index] = value.index
|
||||
}
|
||||
|
||||
inline fun clear() = Arrays.fill(array, 0.toByte())
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.world.chunk.light.types
|
||||
|
||||
|
||||
import de.bixilon.minosoft.data.world.chunk.light.LightUtil.assertLight
|
||||
|
||||
@JvmInline
|
||||
value class LightLevel(val index: Byte) {
|
||||
|
||||
constructor(block: Int, sky: Int) : this(((block shl BLOCK_SHIFT) or (sky shl SKY_SHIFT)).toByte()) {
|
||||
assertLight(block >= MIN_LEVEL)
|
||||
assertLight(block <= MAX_LEVEL)
|
||||
|
||||
assertLight(sky >= MIN_LEVEL)
|
||||
assertLight(sky <= MAX_LEVEL)
|
||||
}
|
||||
|
||||
inline val block: Int get() = (index.toInt() ushr BLOCK_SHIFT) and BLOCK_MASK
|
||||
inline val sky: Int get() = (index.toInt() ushr SKY_SHIFT) and SKY_MASK
|
||||
|
||||
|
||||
inline fun with(block: Int = this.block, sky: Int = this.sky) = LightLevel(block, sky)
|
||||
|
||||
inline fun max(other: LightLevel) = LightLevel(maxOf(block, other.block), maxOf(sky, other.sky))
|
||||
|
||||
companion object {
|
||||
const val BLOCK_SHIFT = 0
|
||||
const val BLOCK_MASK = 0x0F
|
||||
const val SKY_SHIFT = 4
|
||||
const val SKY_MASK = 0x0F
|
||||
|
||||
|
||||
const val MIN_LEVEL = 0
|
||||
const val MAX_LEVEL = 15
|
||||
|
||||
val EMPTY = LightLevel(0, 0)
|
||||
val MAX = LightLevel(0, 0)
|
||||
}
|
||||
}
|
@ -162,7 +162,7 @@ class FluidSectionMesher(
|
||||
|
||||
|
||||
val light = chunk.light[InChunkPosition(x, position.y, z)]
|
||||
addFluidVertices(meshToUse, positions, texturePositions, texture, tint, light)
|
||||
addFluidVertices(meshToUse, positions, texturePositions, texture, tint, light.index.toInt())
|
||||
rendered = true
|
||||
}
|
||||
// ToDo: Sides: Minecraft uses (for water) an overlay texture (with cullface) that is used, when the face fits to a non opaque block
|
||||
@ -226,7 +226,7 @@ class FluidSectionMesher(
|
||||
|
||||
val meshToUse = mesh[model.flowing.transparency]
|
||||
val fluidLight = chunk.light[InChunkPosition(x, offsetY + y, z)]
|
||||
addFluidVertices(meshToUse, positions, texturePositions, model.flowing, tint, fluidLight)
|
||||
addFluidVertices(meshToUse, positions, texturePositions, model.flowing, tint, fluidLight.index.toInt())
|
||||
rendered = true
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ import de.bixilon.minosoft.data.registries.blocks.types.fluid.FluidBlock
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.properties.offset.OffsetBlock
|
||||
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.SectionLight.Companion.SKY_LIGHT_MASK
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbourArray
|
||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||
import de.bixilon.minosoft.data.world.positions.InChunkPosition
|
||||
@ -109,15 +109,15 @@ class SolidSectionMesher(
|
||||
setX(neighbourBlocks, inChunk, neighbours, light, neighbourChunks, section, chunk)
|
||||
|
||||
val maxHeight = chunk.light.heightmap[inSection.xz]
|
||||
light[SELF_LIGHT_INDEX] = section.light[inSection]
|
||||
light[SELF_LIGHT_INDEX] = section.light[inSection].index
|
||||
if (position.y > maxHeight) {
|
||||
light[O_UP] = (light[O_UP].toInt() or SKY_LIGHT_MASK).toByte()
|
||||
light[O_UP] = (light[O_UP].toInt() or MAX_SKY_LIGHT).toByte()
|
||||
}
|
||||
if (position.y >= maxHeight) {
|
||||
light[SELF_LIGHT_INDEX] = (light[SELF_LIGHT_INDEX].toInt() or SKY_LIGHT_MASK).toByte()
|
||||
light[SELF_LIGHT_INDEX] = (light[SELF_LIGHT_INDEX].toInt() or MAX_SKY_LIGHT).toByte()
|
||||
}
|
||||
if (position.y - 1 >= maxHeight) {
|
||||
light[O_DOWN] = (light[O_DOWN].toInt() or SKY_LIGHT_MASK).toByte()
|
||||
light[O_DOWN] = (light[O_DOWN].toInt() or MAX_SKY_LIGHT).toByte()
|
||||
}
|
||||
// TODO: cull neighbours
|
||||
|
||||
@ -154,21 +154,21 @@ class SolidSectionMesher(
|
||||
neighbourBlocks[O_DOWN] = bedrock
|
||||
} else {
|
||||
neighbourBlocks[O_DOWN] = neighbours[O_DOWN]?.blocks?.let { it[position.with(y = ProtocolDefinition.SECTION_MAX_Y)] }
|
||||
light[O_DOWN] = (if (lowest) chunk.light.bottom else neighbours[O_DOWN]?.light)?.get(position.with(y = ProtocolDefinition.SECTION_MAX_Y)) ?: 0x00
|
||||
light[O_DOWN] = (if (lowest) chunk.light.bottom else neighbours[O_DOWN]?.light)?.get(position.with(y = ProtocolDefinition.SECTION_MAX_Y))?.index ?: 0x00
|
||||
}
|
||||
} else {
|
||||
neighbourBlocks[O_DOWN] = section.blocks[position.minusY()]
|
||||
light[O_DOWN] = section.light[position.minusY()]
|
||||
light[O_DOWN] = section.light[position.minusY()].index
|
||||
}
|
||||
}
|
||||
|
||||
fun checkUp(highest: Boolean, position: InSectionPosition, neighbourBlocks: Array<BlockState?>, neighbours: Array<ChunkSection?>, light: ByteArray, section: ChunkSection, chunk: Chunk) {
|
||||
if (position.y == ProtocolDefinition.SECTION_MAX_Y) {
|
||||
neighbourBlocks[O_UP] = neighbours[O_UP]?.blocks?.let { it[position.with(y = 0)] }
|
||||
light[O_UP] = (if (highest) chunk.light.top else neighbours[O_UP]?.light)?.get(position.with(y = 0)) ?: 0x00
|
||||
light[O_UP] = (if (highest) chunk.light.top else neighbours[O_UP]?.light)?.get(position.with(y = 0))?.index ?: 0x00
|
||||
} else {
|
||||
neighbourBlocks[O_UP] = section.blocks[position.plusY()]
|
||||
light[O_UP] = section.light[position.plusY()]
|
||||
light[O_UP] = section.light[position.plusY()].index
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,14 +202,15 @@ class SolidSectionMesher(
|
||||
private inline fun setNeighbour(blocks: Array<BlockState?>, position: InChunkPosition, light: ByteArray, section: ChunkSection?, chunk: Chunk?, direction: Int) {
|
||||
val inSection = position.inSectionPosition
|
||||
blocks[direction] = section?.blocks?.let { it[inSection] }
|
||||
var level = section?.light?.get(inSection) ?: 0x00
|
||||
var level = section?.light?.get(inSection)?.index ?: 0x00
|
||||
if (chunk != null && position.y >= chunk.light.heightmap[position.xz]) {
|
||||
level = (level.toInt() or SKY_LIGHT_MASK).toByte() // set sky light to 0x0F
|
||||
level = (level.toInt() or MAX_SKY_LIGHT).toByte() // set sky light to 0x0F
|
||||
}
|
||||
light[direction] = level
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SELF_LIGHT_INDEX = 6 // after all directions
|
||||
const val MAX_SKY_LIGHT = LightLevel.SKY_MASK shl LightLevel.SKY_SHIFT
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import de.bixilon.kutil.math.interpolation.Interpolator
|
||||
import de.bixilon.minosoft.data.entities.entities.Entity
|
||||
import de.bixilon.minosoft.data.text.formatting.color.ChatColors
|
||||
import de.bixilon.minosoft.data.text.formatting.color.ColorUtil
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel
|
||||
import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.entities.easteregg.EntityEasterEggs.FLIP_ROTATION
|
||||
import de.bixilon.minosoft.gui.rendering.entities.easteregg.EntityEasterEggs.isFlipped
|
||||
@ -89,17 +90,17 @@ abstract class EntityRenderer<E : Entity>(
|
||||
this.distance = (entity.renderInfo.eyePosition - renderer.session.camera.entity.renderInfo.eyePosition).length2()
|
||||
}
|
||||
|
||||
private fun getCurrentLight(): Int {
|
||||
var light = entity.physics.positionInfo.chunk?.light?.get(entity.physics.positionInfo.position.inChunkPosition) ?: return 0xFF
|
||||
private fun getCurrentLight(): LightLevel {
|
||||
var light = with(entity.physics.positionInfo) { chunk?.light?.get(position.inChunkPosition) } ?: return LightLevel.MAX
|
||||
if (entity.isOnFire) {
|
||||
light = light or 0xF0
|
||||
light = light.with(block = LightLevel.MAX_LEVEL)
|
||||
}
|
||||
return light
|
||||
}
|
||||
|
||||
protected open fun updateLight(delta: Float) {
|
||||
if (this.light.delta >= 1.0f) {
|
||||
val rgb = renderer.context.light.map.buffer[getCurrentLight()]
|
||||
val rgb = renderer.context.light.map.buffer[getCurrentLight().index.toInt()]
|
||||
this.light.push(rgb)
|
||||
}
|
||||
this.light.add(delta, 0.1f)
|
||||
|
@ -32,7 +32,6 @@ import de.bixilon.minosoft.data.text.BaseComponent
|
||||
import de.bixilon.minosoft.data.text.TextComponent
|
||||
import de.bixilon.minosoft.data.text.formatting.color.ChatColors
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.SectionLight
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.ChunkRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.events.ResizeWindowEvent
|
||||
@ -299,7 +298,7 @@ class DebugHUDElement(guiRenderer: GUIRenderer) : Element(guiRenderer), Layouted
|
||||
|
||||
this@DebugWorldInfo += AutoTextElement(guiRenderer, 1) { BaseComponent("Sky properties ", entity.session.world.dimension.effects) }
|
||||
this@DebugWorldInfo += AutoTextElement(guiRenderer, 1) { BaseComponent("Biome ", biome) }
|
||||
this@DebugWorldInfo += AutoTextElement(guiRenderer, 1) { with(entity.session.world.getLight(entity.renderInfo.eyePosition.blockPosition)) { BaseComponent("Light block=", (this and SectionLight.BLOCK_LIGHT_MASK), ", sky=", ((this and SectionLight.SKY_LIGHT_MASK) shr 4)) } }
|
||||
this@DebugWorldInfo += AutoTextElement(guiRenderer, 1) { with(entity.session.world.getLight(entity.renderInfo.eyePosition.blockPosition)) { BaseComponent("Light block=", this.block, ", sky=", this.sky) } }
|
||||
this@DebugWorldInfo += AutoTextElement(guiRenderer, 1) { BaseComponent("Fully loaded: ", chunk.neighbours.complete) }
|
||||
|
||||
lastChunk.value = chunk
|
||||
|
@ -17,7 +17,7 @@ import de.bixilon.kotlinglm.vec3.Vec3d
|
||||
import de.bixilon.minosoft.data.registries.particle.data.ParticleData
|
||||
import de.bixilon.minosoft.data.text.formatting.color.ChatColors
|
||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||
import de.bixilon.minosoft.data.world.chunk.light.SectionLight
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightLevel
|
||||
import de.bixilon.minosoft.gui.rendering.particle.types.Particle
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.blockPosition
|
||||
import de.bixilon.minosoft.protocol.network.session.play.PlaySession
|
||||
@ -34,26 +34,20 @@ abstract class RenderParticle(session: PlaySession, position: Vec3d, velocity: V
|
||||
this.light = retrieveLight()
|
||||
}
|
||||
|
||||
private fun retrieveLight(): Int {
|
||||
private fun retrieveLight(): LightLevel {
|
||||
val aabb = aabb + position
|
||||
var maxBlockLight = emittingLight
|
||||
var maxSkyLight = 0
|
||||
var maxLevel = LightLevel.EMPTY.with(emittingLight)
|
||||
|
||||
val chunkPosition = position.blockPosition.chunkPosition
|
||||
val chunk = getChunk() ?: return maxBlockLight
|
||||
val chunk = getChunk() ?: return maxLevel
|
||||
|
||||
for (position in aabb.positions()) {
|
||||
val next = chunk.neighbours.traceChunk(position.chunkPosition - chunkPosition)
|
||||
|
||||
val light = next?.light?.get(position.inChunkPosition) ?: SectionLight.SKY_LIGHT_MASK
|
||||
if (light and SectionLight.BLOCK_LIGHT_MASK > maxBlockLight) {
|
||||
maxBlockLight = light and SectionLight.BLOCK_LIGHT_MASK
|
||||
}
|
||||
if (light and SectionLight.SKY_LIGHT_MASK > maxSkyLight) {
|
||||
maxSkyLight = light and SectionLight.SKY_LIGHT_MASK
|
||||
}
|
||||
val light = next?.light?.get(position.inChunkPosition) ?: LightLevel(0, LightLevel.MAX_LEVEL) // No chunk is given, assume there is light (otherwise particle might looks badly dark)
|
||||
maxLevel = maxLevel.max(light)
|
||||
}
|
||||
|
||||
return maxBlockLight or maxSkyLight
|
||||
return maxLevel
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2024 Moritz Zwerger
|
||||
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
@ -32,6 +32,6 @@ abstract class TextureParticle(session: PlaySession, position: Vec3d, velocity:
|
||||
when {
|
||||
texture.transparency == TextureTransparencies.TRANSLUCENT || color.alpha != 255 -> translucentMesh
|
||||
else -> mesh
|
||||
}.addVertex(getCameraPosition(time), scale, texture, color, light = light)
|
||||
}.addVertex(getCameraPosition(time), scale, texture, color, light = light.index.toInt())
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2024 Moritz Zwerger
|
||||
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
@ -32,6 +32,6 @@ abstract class AdvancedTextureParticle(session: PlaySession, position: Vec3d, ve
|
||||
when {
|
||||
texture.transparency == TextureTransparencies.TRANSLUCENT || color.alpha != 255 -> translucentMesh
|
||||
else -> mesh
|
||||
}.addVertex(getCameraPosition(time), scale, texture, color, minUV.array, maxUV.array, light)
|
||||
}.addVertex(getCameraPosition(time), scale, texture, color, minUV.array, maxUV.array, light.index.toInt())
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import de.bixilon.minosoft.data.world.biome.source.XZBiomeArray
|
||||
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.ChunkPrototype
|
||||
import de.bixilon.minosoft.data.world.chunk.light.LightArray
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightArray
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbourArray
|
||||
import de.bixilon.minosoft.data.world.container.palette.PalettedContainerReader
|
||||
import de.bixilon.minosoft.data.world.container.palette.palettes.BiomePaletteFactory
|
||||
|
@ -15,7 +15,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play.block.chunk.light
|
||||
|
||||
import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.ChunkPrototype
|
||||
import de.bixilon.minosoft.data.world.chunk.light.LightArray
|
||||
import de.bixilon.minosoft.data.world.chunk.light.types.LightArray
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_1_16
|
||||
|
Loading…
x
Reference in New Issue
Block a user