get light from edge chunks

This commit is contained in:
Bixilon 2022-09-07 15:42:10 +02:00
parent 959d682eb0
commit db07729325
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
5 changed files with 55 additions and 21 deletions

View File

@ -12,7 +12,7 @@ Minosoft is an open source minecraft client, written from scratch in kotlin (and
## Feature overview
- Rendering
- Connect with any version to any server (1.7 - latest)
- Connect with any version to any server (1.7 - 1.19)
- ~~Modding~~
- Bleeding edge performance (e.g. incredible start time)
- Free (as far as we consider original minecraft as free) and open source
@ -125,11 +125,11 @@ Support for macOS is a delicate topic. Let's say it works for now, but it is not
## Building
1. Install Maven and java 11+ (On Ubuntu based distributions: `sudo apt install maven openjdk-11-jdk`). For Windows users, download and install java from oracle or openjdk. Also download maven and follow along
1. Install Maven and java 11+ (e.g. `sudo apt install maven openjdk-11-jdk`). For Windows users, download and install java from oracle or openjdk. Also download maven and follow along
2. Clone this repository (`git clone https://gitlab.bixilon.de/bixilon/minosoft.git`)
3. Change directory (`cd minosoft`)
4. Optional: Checkout a current feature branch (Warning: might be unstable; might not even build) (`git checkout <branch>`)
5. Build and run Minosoft with `mvn clean verify exec:java`. If any errors occur, feel free to open an issue. In this early stage it might be helpful to delete the config file
5. Build and run Minosoft with `mvn clean verify exec:java`. If any errors occur, feel free to open an issue. In this early stage it might be helpful to delete its configuration files
6. (Optional) Build a fat jar with `mvn package`. You'll find the jar with all dependencies in `target/`. Then you don't need to recompile everytime
## Code mirrors

View File

@ -376,24 +376,27 @@ class World(
val neighboursPositions = getChunkNeighbourPositions(chunkPosition)
val neighbours = getChunkNeighbours(neighboursPositions)
if (neighbours.received) {
val neighboursReceived = neighbours.received
if (neighboursReceived) {
chunk.neighbours = neighbours.cast()
if (!chunk.biomesInitialized && cacheBiomeAccessor != null && chunk.biomeSource != null && neighbours.canBuildBiomeCache) {
chunk.buildBiomeCache()
}
}
if (checkNeighbours) {
for (index in 0 until 8) {
val neighbour = neighbours[index] ?: continue
onChunkUpdate(neighboursPositions[index], neighbour, false)
}
}
if (neighboursReceived) {
chunk.recalculateLight()
connection.fireEvent(ChunkDataChangeEvent(connection, EventInitiators.UNKNOWN, chunkPosition, chunk))
}
if (!checkNeighbours) {
return
}
for (index in 0 until 8) {
val neighbour = neighbours[index] ?: continue
onChunkUpdate(neighboursPositions[index], neighbour, false)
}
}
fun getBrightness(position: Vec3i): Float {

View File

@ -59,14 +59,13 @@ class Chunk(
val heightmap = IntArray(ProtocolDefinition.SECTION_WIDTH_X * ProtocolDefinition.SECTION_WIDTH_Z)
var neighbours: Array<Chunk>? = null
set(value) {
@Synchronized set(value) {
if (field.contentEquals(value)) {
return
}
field = value
if (value != null) {
updateSectionNeighbours(value)
recalculateLight()
}
}
@ -104,6 +103,7 @@ class Chunk(
if (blockEntity == null) {
getOrPutBlockEntity(x, y, z)
}
// ToDo: Remove section if isEmpty
val neighbours = this.neighbours ?: return
@ -250,12 +250,16 @@ class Chunk(
if (cacheBiomeAccessor != null && biomesInitialized) {
section.buildBiomeCache(chunkPosition, sectionHeight, this, neighbours, cacheBiomeAccessor)
}
section.neighbours = ChunkUtil.getDirectNeighbours(neighbours, this, sectionHeight)
for (neighbour in neighbours) {
val neighbourNeighbours = neighbour.neighbours ?: continue
neighbour.updateNeighbours(neighbourNeighbours, sectionHeight)
}
}
sections[sectionIndex] = section
// check light of neighbours to check if their light needs to be traced into our own chunk
section.light.propagateFromNeighbours()
}
return section
}

View File

@ -42,7 +42,7 @@ class SectionLight(
private fun startDecreaseTrace(x: Int, y: Int, z: Int) {
// that is kind of hacky, but far easier and kind of faster
val light = this.light[getIndex(x, y, z)].toInt() and 0x0F
val light = this.light[getIndex(x, y, z)].toInt() and BLOCK_LIGHT_MASK
decreaseLight(x, y, z, light, true) // just clear the light
decreaseLight(x, y, z, light, false) // increase the light in all sections
@ -96,7 +96,7 @@ class SectionLight(
}
// get block or next luminance level
val currentLight = light[index].toInt() and 0x0F // we just care about block light
val currentLight = light[index].toInt() and BLOCK_LIGHT_MASK // we just care about block light
if (currentLight >= nextLuminance) {
// light is already higher, no need to trace
return
@ -202,4 +202,30 @@ class SectionLight(
override operator fun get(index: Int): Byte {
return light[index]
}
fun propagateFromNeighbours() {
val neighbours = section.neighbours ?: return
// ToDo(p): this::traceIncrease checks als the block light level, not needed
for (x in 0 until ProtocolDefinition.SECTION_WIDTH_X) {
for (z in 0 until ProtocolDefinition.SECTION_WIDTH_Z) {
neighbours[Directions.O_DOWN]?.let { traceIncrease(x, 0, z, it.light[x, ProtocolDefinition.SECTION_MAX_Y, z].toInt() and BLOCK_LIGHT_MASK) }
neighbours[Directions.O_UP]?.let { traceIncrease(x, ProtocolDefinition.SECTION_MAX_Y, z, it.light[x, 0, z].toInt() and BLOCK_LIGHT_MASK) }
}
for (y in 0 until ProtocolDefinition.SECTION_HEIGHT_Y) {
neighbours[Directions.O_NORTH]?.let { traceIncrease(x, y, 0, it.light[x, y, ProtocolDefinition.SECTION_MAX_Z].toInt() and BLOCK_LIGHT_MASK) }
neighbours[Directions.O_SOUTH]?.let { traceIncrease(x, y, ProtocolDefinition.SECTION_MAX_Z, it.light[x, y, 0].toInt() and BLOCK_LIGHT_MASK) }
}
}
for (z in 0 until ProtocolDefinition.SECTION_WIDTH_Z) {
for (y in 0 until ProtocolDefinition.SECTION_HEIGHT_Y) {
neighbours[Directions.O_WEST]?.let { traceIncrease(0, y, z, it.light[ProtocolDefinition.SECTION_MAX_Z, y, z].toInt() and BLOCK_LIGHT_MASK) }
neighbours[Directions.O_UP]?.let { traceIncrease(ProtocolDefinition.SECTION_MAX_X, y, z, it.light[0, y, z].toInt() and BLOCK_LIGHT_MASK) }
}
}
}
companion object {
const val BLOCK_LIGHT_MASK = 0x0F
const val SKY_LIGHT_MASK = 0xF0
}
}

View File

@ -51,11 +51,12 @@ public final class ProtocolDefinition {
public static final Pattern MINECRAFT_NAME_VALIDATOR = Pattern.compile("\\w{3,16}");
public static final int SECTION_WIDTH_X = 16;
public static final int SECTION_LENGTH = 16;
public static final int SECTION_WIDTH_X = SECTION_LENGTH;
public static final int SECTION_MAX_X = SECTION_WIDTH_X - 1;
public static final int SECTION_WIDTH_Z = 16;
public static final int SECTION_WIDTH_Z = SECTION_LENGTH;
public static final int SECTION_MAX_Z = SECTION_WIDTH_Z - 1;
public static final int SECTION_HEIGHT_Y = 16;
public static final int SECTION_HEIGHT_Y = SECTION_LENGTH;
public static final int SECTION_MAX_Y = SECTION_HEIGHT_Y - 1;
public static final int BLOCKS_PER_SECTION = SECTION_WIDTH_X * SECTION_HEIGHT_Y * SECTION_WIDTH_X;
public static final Vec3i CHUNK_SECTION_SIZE = new Vec3i(ProtocolDefinition.SECTION_WIDTH_X, ProtocolDefinition.SECTION_HEIGHT_Y, ProtocolDefinition.SECTION_WIDTH_Z);