mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-09 15:29:20 -04:00
make it build
This commit is contained in:
parent
dd9aee9c21
commit
6abc316d0d
@ -35,7 +35,6 @@ 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.neighbours.ChunkNeighbours
|
||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
||||
import de.bixilon.minosoft.modding.event.master.EventMaster
|
||||
import de.bixilon.minosoft.protocol.network.session.Session
|
||||
import de.bixilon.minosoft.protocol.network.session.play.PlaySession
|
||||
@ -80,7 +79,7 @@ object LightTestingUtil {
|
||||
}
|
||||
|
||||
fun createChunkWithNeighbours(): Chunk {
|
||||
val chunk = createEmptyChunk(Vec2i.EMPTY)
|
||||
val chunk = createEmptyChunk(ChunkPosition.EMPTY)
|
||||
var index = 0
|
||||
for (x in -1..1) {
|
||||
for (z in -1..1) {
|
||||
|
@ -18,6 +18,7 @@ import de.bixilon.minosoft.data.registries.biomes.Biome
|
||||
import de.bixilon.minosoft.data.world.World
|
||||
import de.bixilon.minosoft.data.world.biome.source.SpatialBiomeArray
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||
import de.bixilon.minosoft.data.world.positions.InChunkPosition
|
||||
|
||||
class VoronoiBiomeAccessor(
|
||||
@ -37,9 +38,9 @@ class VoronoiBiomeAccessor(
|
||||
val biomeY = unpackY(offset)
|
||||
val biomeZ = unpackZ(offset)
|
||||
|
||||
val biomeChunk = chunk.neighbours.trace(biomeX shr 4, biomeZ shr 4)
|
||||
val biomeChunk = chunk.neighbours.traceChunk(ChunkPosition(biomeX shr 4, biomeZ shr 4))
|
||||
|
||||
return biomeChunk?.biomeSource?.get(biomeX and 0x0F, biomeY, biomeZ and 0x0F)
|
||||
return biomeChunk?.biomeSource?.get(InChunkPosition(biomeX and 0x0F, biomeY, biomeZ and 0x0F))
|
||||
}
|
||||
|
||||
fun getBiomeOffset(seed: Long, x: Int, y: Int, z: Int): Int {
|
||||
|
@ -21,9 +21,9 @@ 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
|
||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
import de.bixilon.minosoft.protocol.network.session.play.PlaySession
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@ -70,59 +70,16 @@ class ChunkSection(
|
||||
blockEntities.clear()
|
||||
}
|
||||
|
||||
fun traceBlock(offset: BlockPosition): BlockState?
|
||||
fun traceBlock(origin: InSectionPosition, offset: BlockPosition) = traceBlock(offset - origin)
|
||||
fun traceBlock(origin: InSectionPosition, direction: Directions) = traceBlock((BlockPosition(origin) + direction))
|
||||
|
||||
|
||||
@Deprecated("")
|
||||
fun traceBlock(x: Int, y: Int, z: Int, direction: Directions) = when (direction) {
|
||||
Directions.DOWN -> {
|
||||
if (y == 0) {
|
||||
neighbours?.get(Directions.O_DOWN)?.blocks?.let { it[x, ProtocolDefinition.SECTION_MAX_Y, z] }
|
||||
} else {
|
||||
blocks[x, y - 1, z]
|
||||
}
|
||||
}
|
||||
|
||||
Directions.UP -> {
|
||||
if (y == ProtocolDefinition.SECTION_MAX_Y) {
|
||||
neighbours?.get(Directions.O_UP)?.blocks?.let { it[x, 0, z] }
|
||||
} else {
|
||||
blocks[x, y + 1, z]
|
||||
}
|
||||
}
|
||||
|
||||
Directions.NORTH -> {
|
||||
if (z == 0) {
|
||||
neighbours?.get(Directions.O_NORTH)?.blocks?.let { it[x, y, ProtocolDefinition.SECTION_MAX_Z] }
|
||||
} else {
|
||||
blocks[x, y, z - 1]
|
||||
}
|
||||
}
|
||||
|
||||
Directions.SOUTH -> {
|
||||
if (z == ProtocolDefinition.SECTION_MAX_Z) {
|
||||
neighbours?.get(Directions.O_SOUTH)?.blocks?.let { it[x, y, 0] }
|
||||
} else {
|
||||
blocks[x, y, z + 1]
|
||||
}
|
||||
}
|
||||
|
||||
Directions.WEST -> {
|
||||
if (x == 0) {
|
||||
neighbours?.get(Directions.O_WEST)?.blocks?.let { it[ProtocolDefinition.SECTION_MAX_X, y, z] }
|
||||
} else {
|
||||
blocks[x - 1, y, z]
|
||||
}
|
||||
}
|
||||
|
||||
Directions.EAST -> {
|
||||
if (x == ProtocolDefinition.SECTION_MAX_X) {
|
||||
neighbours?.get(Directions.O_EAST)?.blocks?.let { it[0, y, z] }
|
||||
} else {
|
||||
blocks[x + 1, y, z]
|
||||
}
|
||||
fun traceBlock(offset: BlockPosition): BlockState? {
|
||||
val chunkOffset = offset.chunkPosition
|
||||
val height = offset.sectionHeight
|
||||
if (chunkOffset == ChunkPosition.EMPTY && height == 0) {
|
||||
return blocks[offset.inSectionPosition]
|
||||
}
|
||||
val chunk = this.chunk.neighbours.traceChunk(chunkOffset) ?: return null
|
||||
return chunk[offset.inChunkPosition]
|
||||
}
|
||||
|
||||
fun traceBlock(origin: InSectionPosition, offset: BlockPosition) = traceBlock(offset - origin)
|
||||
fun traceBlock(origin: InSectionPosition, direction: Directions) = traceBlock((BlockPosition(origin.x, origin.y, origin.z) + direction))
|
||||
}
|
||||
|
@ -167,9 +167,9 @@ class Chunk(
|
||||
var section = sections[index] // get another time, it might have changed already
|
||||
if (section == null) {
|
||||
section = ChunkSection(sectionHeight, chunk = this)
|
||||
val neighbours = this.neighbours.get()
|
||||
if (neighbours != null) {
|
||||
this.neighbours.completeSection(neighbours, section, sectionHeight, world.biomes.noise)
|
||||
val neighbours = this.neighbours
|
||||
if (neighbours.complete) {
|
||||
this.neighbours.completeSection(section, sectionHeight, world.biomes.noise)
|
||||
}
|
||||
|
||||
sections[index] = section
|
||||
@ -181,10 +181,10 @@ class Chunk(
|
||||
sections[index + 1]?.neighbours?.set(Directions.O_DOWN, section)
|
||||
}
|
||||
|
||||
if (neighbours != null) {
|
||||
for (neighbour in neighbours) {
|
||||
val neighbourNeighbours = neighbour.neighbours.get() ?: continue
|
||||
neighbour.neighbours.update(neighbourNeighbours, sectionHeight)
|
||||
if (neighbours.complete) {
|
||||
for (neighbour in neighbours.neighbours.array) {
|
||||
if (neighbour == null || !neighbour.neighbours.complete) continue
|
||||
neighbour.neighbours.update(sectionHeight)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ abstract class ChunkHeightmap(protected val chunk: Chunk) : Heightmap {
|
||||
|
||||
override fun get(index: Int) = heightmap[index]
|
||||
override fun get(x: Int, z: Int) = this[(z shl 4) or x]
|
||||
override fun get(position: InChunkPosition) = get(position.x, position.z)
|
||||
|
||||
|
||||
protected abstract fun passes(state: BlockState): HeightmapPass
|
||||
@ -47,7 +48,7 @@ abstract class ChunkHeightmap(protected val chunk: Chunk) : Heightmap {
|
||||
val sections = chunk.sections
|
||||
|
||||
var y = Int.MIN_VALUE
|
||||
val index = (z shl 4) or x
|
||||
val index = position.xz
|
||||
|
||||
sectionLoop@ for (sectionIndex in (position.y.sectionHeight - chunk.minSection) downTo 0) {
|
||||
if (sectionIndex >= sections.size) {
|
||||
@ -88,7 +89,7 @@ abstract class ChunkHeightmap(protected val chunk: Chunk) : Heightmap {
|
||||
|
||||
override fun onBlockChange(position: InChunkPosition, state: BlockState?) {
|
||||
chunk.lock.lock()
|
||||
val index = (z shl 4) or x
|
||||
val index = position.xz
|
||||
|
||||
val previous = heightmap[index]
|
||||
|
||||
|
@ -17,7 +17,6 @@ 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.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
|
||||
@ -71,23 +70,23 @@ class BorderSectionLight(
|
||||
if (z > 0) {
|
||||
traceBlockIncrease(x, z - 1, neighbourLuminance)
|
||||
} else {
|
||||
chunk.neighbours[ChunkNeighbours.NORTH]?.getBorderLight()?.traceBlockIncrease(x, ProtocolDefinition.SECTION_MAX_Z, neighbourLuminance)
|
||||
chunk.neighbours[Directions.NORTH]?.getBorderLight()?.traceBlockIncrease(x, ProtocolDefinition.SECTION_MAX_Z, neighbourLuminance)
|
||||
}
|
||||
if (z < ProtocolDefinition.SECTION_MAX_Z) {
|
||||
traceBlockIncrease(x, z + 1, neighbourLuminance)
|
||||
} else {
|
||||
chunk.neighbours[ChunkNeighbours.SOUTH]?.getBorderLight()?.traceBlockIncrease(x, 0, neighbourLuminance)
|
||||
chunk.neighbours[Directions.SOUTH]?.getBorderLight()?.traceBlockIncrease(x, 0, neighbourLuminance)
|
||||
}
|
||||
|
||||
if (x > 0) {
|
||||
traceBlockIncrease(x - 1, z, neighbourLuminance)
|
||||
} else {
|
||||
chunk.neighbours[ChunkNeighbours.WEST]?.getBorderLight()?.traceBlockIncrease(ProtocolDefinition.SECTION_MAX_X, z, neighbourLuminance)
|
||||
chunk.neighbours[Directions.WEST]?.getBorderLight()?.traceBlockIncrease(ProtocolDefinition.SECTION_MAX_X, z, neighbourLuminance)
|
||||
}
|
||||
if (x < ProtocolDefinition.SECTION_MAX_X) {
|
||||
traceBlockIncrease(x + 1, z, neighbourLuminance)
|
||||
} else {
|
||||
chunk.neighbours[ChunkNeighbours.EAST]?.getBorderLight()?.traceBlockIncrease(0, z, neighbourLuminance)
|
||||
chunk.neighbours[Directions.EAST]?.getBorderLight()?.traceBlockIncrease(0, z, neighbourLuminance)
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,49 +123,49 @@ class BorderSectionLight(
|
||||
if (z > 0) {
|
||||
traceSkyIncrease(x, z - 1, neighbourLevel)
|
||||
} else {
|
||||
chunk.neighbours.get(ChunkNeighbours.NORTH)?.getBorderLight()?.traceSkyIncrease(x, ProtocolDefinition.SECTION_MAX_Z, neighbourLevel)
|
||||
chunk.neighbours[Directions.NORTH]?.getBorderLight()?.traceSkyIncrease(x, ProtocolDefinition.SECTION_MAX_Z, neighbourLevel)
|
||||
}
|
||||
if (z < ProtocolDefinition.SECTION_MAX_Y) {
|
||||
traceSkyIncrease(x, z + 1, neighbourLevel)
|
||||
} else {
|
||||
chunk.neighbours.get(ChunkNeighbours.SOUTH)?.getBorderLight()?.traceSkyIncrease(x, 0, neighbourLevel)
|
||||
chunk.neighbours[Directions.SOUTH]?.getBorderLight()?.traceSkyIncrease(x, 0, neighbourLevel)
|
||||
}
|
||||
|
||||
if (x > 0) {
|
||||
traceSkyIncrease(x - 1, z, neighbourLevel)
|
||||
} else {
|
||||
chunk.neighbours.get(ChunkNeighbours.WEST)?.getBorderLight()?.traceSkyIncrease(ProtocolDefinition.SECTION_MAX_X, z, neighbourLevel)
|
||||
chunk.neighbours[Directions.WEST]?.getBorderLight()?.traceSkyIncrease(ProtocolDefinition.SECTION_MAX_X, z, neighbourLevel)
|
||||
}
|
||||
if (x < ProtocolDefinition.SECTION_MAX_X) {
|
||||
traceSkyIncrease(x + 1, z, neighbourLevel)
|
||||
} else {
|
||||
chunk.neighbours.get(ChunkNeighbours.EAST)?.getBorderLight()?.traceSkyIncrease(0, z, neighbourLevel)
|
||||
chunk.neighbours[Directions.EAST]?.getBorderLight()?.traceSkyIncrease(0, z, neighbourLevel)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun decreaseCheckLevel(x: Int, z: Int, light: Int, reset: Boolean) {
|
||||
decreaseCheckX(z, light, reset)
|
||||
val neighbours = chunk.neighbours.get() ?: return
|
||||
val neighbours = chunk.neighbours
|
||||
|
||||
if (x - light < 0) {
|
||||
neighbours[ChunkNeighbours.WEST].getBorderLight().decreaseCheckX(z, light - x, reset)
|
||||
neighbours[Directions.WEST]?.getBorderLight()?.decreaseCheckX(z, light - x, reset)
|
||||
}
|
||||
if (x + light > ProtocolDefinition.SECTION_MAX_X) {
|
||||
neighbours[ChunkNeighbours.EAST].getBorderLight().decreaseCheckX(z, light - (ProtocolDefinition.SECTION_MAX_X - x), reset)
|
||||
neighbours[Directions.EAST]?.getBorderLight()?.decreaseCheckX(z, light - (ProtocolDefinition.SECTION_MAX_X - x), reset)
|
||||
}
|
||||
}
|
||||
|
||||
private fun decreaseCheckX(z: Int, light: Int, reset: Boolean) {
|
||||
val neighbours = chunk.neighbours.get() ?: return
|
||||
val neighbours = chunk.neighbours
|
||||
if (reset) reset()
|
||||
|
||||
if (z - light < 0) {
|
||||
val neighbour = neighbours[ChunkNeighbours.NORTH].getBorderLight()
|
||||
if (reset) neighbour.reset()
|
||||
val neighbour = neighbours[Directions.NORTH]?.getBorderLight()
|
||||
if (reset) neighbour?.reset()
|
||||
}
|
||||
if (z + light > ProtocolDefinition.SECTION_MAX_Z) {
|
||||
val neighbour = neighbours[ChunkNeighbours.SOUTH].getBorderLight()
|
||||
if (reset) neighbour.reset()
|
||||
val neighbour = neighbours[Directions.SOUTH]?.getBorderLight()
|
||||
if (reset) neighbour?.reset()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ class ChunkLight(val chunk: Chunk) {
|
||||
for (chunkX in -1..1) {
|
||||
for (chunkZ in -1..1) {
|
||||
val offset = ChunkPosition(chunkX, chunkZ)
|
||||
if (offset.xz == 0) continue
|
||||
if (offset == ChunkPosition.EMPTY) continue
|
||||
|
||||
val nextPosition = chunkPosition + offset
|
||||
val chunk = neighbours[neighbourIndex++]
|
||||
|
@ -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.
|
||||
*
|
||||
@ -14,9 +14,9 @@
|
||||
package de.bixilon.minosoft.data.world.chunk.light
|
||||
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
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.neighbours.ChunkNeighbours
|
||||
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
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inSectionHeight
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight
|
||||
@ -39,7 +39,7 @@ class ChunkSkyLight(val light: ChunkLight) {
|
||||
val baseY = sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y
|
||||
|
||||
for (y in topY downTo bottomY) {
|
||||
section.light.traceSkyLightIncrease(x, y, z, NEIGHBOUR_TRACE_LEVEL, target, baseY + y)
|
||||
section.light.traceSkyLightIncrease(InSectionPosition(x, y, z), NEIGHBOUR_TRACE_LEVEL, target, baseY + y)
|
||||
}
|
||||
section.light.update = true
|
||||
}
|
||||
@ -81,10 +81,10 @@ class ChunkSkyLight(val light: ChunkLight) {
|
||||
}
|
||||
val section = chunk[y.sectionHeight] ?: return
|
||||
|
||||
section.light.traceSkyLightDown(x, y.inSectionHeight, z, Directions.DOWN, y)
|
||||
section.light.traceSkyLightDown(InSectionPosition(x, y.inSectionHeight, z), Directions.DOWN, y)
|
||||
}
|
||||
|
||||
private fun floodFill(neighbours: Array<Chunk>, x: Int, z: Int) {
|
||||
private fun floodFill(neighbours: ChunkNeighbourArray, x: Int, z: Int) {
|
||||
val heightmapIndex = (z shl 4) or x
|
||||
val maxHeight = light.heightmap[heightmapIndex]
|
||||
|
||||
@ -94,39 +94,40 @@ class ChunkSkyLight(val light: ChunkLight) {
|
||||
if (x > 0) {
|
||||
trace(x - 1, light.heightmap[heightmapIndex - 1], maxHeight, z, Directions.WEST)
|
||||
} else {
|
||||
val neighbour = neighbours[ChunkNeighbours.WEST].light
|
||||
neighbour.sky.trace(ProtocolDefinition.SECTION_MAX_X, neighbour.heightmap[(z shl 4) or ProtocolDefinition.SECTION_MAX_X], maxHeight, z, Directions.WEST)
|
||||
val neighbour = neighbours[Directions.WEST]?.light
|
||||
neighbour?.sky?.trace(ProtocolDefinition.SECTION_MAX_X, neighbour.heightmap[(z shl 4) or ProtocolDefinition.SECTION_MAX_X], maxHeight, z, Directions.WEST)
|
||||
}
|
||||
|
||||
if (x < ProtocolDefinition.SECTION_MAX_X) {
|
||||
trace(x + 1, light.heightmap[heightmapIndex + 1], maxHeight, z, Directions.EAST)
|
||||
} else {
|
||||
val neighbour = neighbours[ChunkNeighbours.EAST].light
|
||||
neighbour.sky.trace(0, neighbour.heightmap[(z shl 4) or 0], maxHeight, z, Directions.EAST)
|
||||
val neighbour = neighbours[Directions.EAST]?.light
|
||||
neighbour?.sky?.trace(0, neighbour.heightmap[(z shl 4) or 0], maxHeight, z, Directions.EAST)
|
||||
}
|
||||
|
||||
if (z > 0) {
|
||||
trace(x, light.heightmap[((z - 1) shl 4) or x], maxHeight, z - 1, Directions.NORTH)
|
||||
} else {
|
||||
val neighbour = neighbours[ChunkNeighbours.NORTH].light
|
||||
neighbour.sky.trace(x, neighbour.heightmap[(ProtocolDefinition.SECTION_MAX_Z shl 4) or x], maxHeight, ProtocolDefinition.SECTION_MAX_Z, Directions.NORTH)
|
||||
val neighbour = neighbours[Directions.NORTH]?.light
|
||||
neighbour?.sky?.trace(x, neighbour.heightmap[(ProtocolDefinition.SECTION_MAX_Z shl 4) or x], maxHeight, ProtocolDefinition.SECTION_MAX_Z, Directions.NORTH)
|
||||
}
|
||||
|
||||
if (z < ProtocolDefinition.SECTION_MAX_Z) {
|
||||
trace(x, light.heightmap[((z + 1) shl 4) or x], maxHeight, z + 1, Directions.SOUTH)
|
||||
} else {
|
||||
val neighbour = neighbours[ChunkNeighbours.SOUTH].light
|
||||
neighbour.sky.trace(x, neighbour.heightmap[(0 shl 4) or x], maxHeight, 0, Directions.SOUTH)
|
||||
val neighbour = neighbours[Directions.SOUTH]?.light
|
||||
neighbour?.sky?.trace(x, neighbour.heightmap[(0 shl 4) or x], maxHeight, 0, Directions.SOUTH)
|
||||
}
|
||||
}
|
||||
|
||||
fun floodFill(x: Int, z: Int) {
|
||||
val neighbours = chunk.neighbours.get() ?: return
|
||||
floodFill(neighbours, x, z)
|
||||
if (!this.chunk.neighbours.complete) return
|
||||
floodFill(chunk.neighbours.neighbours, x, z)
|
||||
}
|
||||
|
||||
private fun floodFill() {
|
||||
val neighbours = this.chunk.neighbours.get() ?: return
|
||||
val neighbours = this.chunk.neighbours.neighbours
|
||||
if (!this.chunk.neighbours.complete) return
|
||||
for (z in 0 until ProtocolDefinition.SECTION_WIDTH_Z) {
|
||||
for (x in 0 until ProtocolDefinition.SECTION_WIDTH_X) {
|
||||
floodFill(neighbours, x, z)
|
||||
@ -142,30 +143,30 @@ class ChunkSkyLight(val light: ChunkLight) {
|
||||
calculate()
|
||||
}
|
||||
|
||||
fun getNeighbourMinHeight(neighbours: Array<Chunk>, x: Int, z: Int, heightmapIndex: Int = (z shl 4) or x): Int {
|
||||
fun getNeighbourMinHeight(neighbours: ChunkNeighbourArray, x: Int, z: Int, heightmapIndex: Int = (z shl 4) or x): Int {
|
||||
return minOf(
|
||||
if (x > 0) {
|
||||
light.heightmap[heightmapIndex - 1]
|
||||
} else {
|
||||
neighbours[ChunkNeighbours.WEST].light.heightmap[(z shl 4) or ProtocolDefinition.SECTION_MAX_X]
|
||||
neighbours[Directions.WEST]?.light?.heightmap?.get((z shl 4) or ProtocolDefinition.SECTION_MAX_X) ?: 0
|
||||
},
|
||||
|
||||
if (x < ProtocolDefinition.SECTION_MAX_X) {
|
||||
light.heightmap[heightmapIndex + 1]
|
||||
} else {
|
||||
neighbours[ChunkNeighbours.EAST].light.heightmap[(z shl 4) or 0]
|
||||
neighbours[Directions.EAST]?.light?.heightmap?.get((z shl 4) or 0) ?: 0
|
||||
},
|
||||
|
||||
if (z > 0) {
|
||||
light.heightmap[((z - 1) shl 4) or x]
|
||||
} else {
|
||||
neighbours[ChunkNeighbours.NORTH].light.heightmap[(ProtocolDefinition.SECTION_MAX_Z shl 4) or x]
|
||||
neighbours[Directions.NORTH]?.light?.heightmap?.get((ProtocolDefinition.SECTION_MAX_Z shl 4) or x) ?: 0
|
||||
},
|
||||
|
||||
if (z < ProtocolDefinition.SECTION_MAX_Z) {
|
||||
light.heightmap[((z + 1) shl 4) or x]
|
||||
} else {
|
||||
neighbours[ChunkNeighbours.SOUTH].light.heightmap[(0 shl 4) or x]
|
||||
neighbours[Directions.SOUTH]?.light?.heightmap?.get((0 shl 4) or x) ?: 0
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -17,9 +17,8 @@ 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.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.light.ChunkSkyLight.Companion.NEIGHBOUR_TRACE_LEVEL
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbourArray
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
|
||||
@ -144,7 +143,7 @@ class SectionLight(
|
||||
update = true
|
||||
}
|
||||
val chunk = section.chunk
|
||||
val chunkNeighbours = chunk.neighbours.get() ?: return
|
||||
val chunkNeighbours = chunk.neighbours.neighbours
|
||||
val neighbours = section.neighbours ?: return
|
||||
|
||||
if (nextLuminance == 1) {
|
||||
@ -183,28 +182,28 @@ class SectionLight(
|
||||
if (position.z > 0) {
|
||||
traceBlockIncrease(position.minusZ(), neighbourLuminance, Directions.NORTH)
|
||||
} else {
|
||||
neighbours[Directions.O_NORTH, ChunkNeighbours.NORTH, chunkNeighbours]?.light?.traceBlockIncrease(position.with(z = ProtocolDefinition.SECTION_MAX_Z), neighbourLuminance, Directions.NORTH)
|
||||
neighbours[Directions.O_NORTH, Directions.NORTH, chunkNeighbours]?.light?.traceBlockIncrease(position.with(z = ProtocolDefinition.SECTION_MAX_Z), neighbourLuminance, Directions.NORTH)
|
||||
}
|
||||
}
|
||||
if (target == null || (target != Directions.NORTH && lightProperties.propagatesLight(Directions.SOUTH))) {
|
||||
if (position.z < ProtocolDefinition.SECTION_MAX_Y) {
|
||||
traceBlockIncrease(position.plusZ(), neighbourLuminance, Directions.SOUTH)
|
||||
} else {
|
||||
neighbours[Directions.O_SOUTH, ChunkNeighbours.SOUTH, chunkNeighbours]?.light?.traceBlockIncrease(position.with(z = 0), neighbourLuminance, Directions.SOUTH)
|
||||
neighbours[Directions.O_SOUTH, Directions.SOUTH, chunkNeighbours]?.light?.traceBlockIncrease(position.with(z = 0), neighbourLuminance, Directions.SOUTH)
|
||||
}
|
||||
}
|
||||
if (target == null || (target != Directions.EAST && lightProperties.propagatesLight(Directions.WEST))) {
|
||||
if (position.x > 0) {
|
||||
traceBlockIncrease(position.minusX(), neighbourLuminance, Directions.WEST)
|
||||
} else {
|
||||
neighbours[Directions.O_WEST, ChunkNeighbours.WEST, chunkNeighbours]?.light?.traceBlockIncrease(position.with(x = ProtocolDefinition.SECTION_MAX_X), neighbourLuminance, Directions.WEST)
|
||||
neighbours[Directions.O_WEST, Directions.WEST, chunkNeighbours]?.light?.traceBlockIncrease(position.with(x = ProtocolDefinition.SECTION_MAX_X), neighbourLuminance, Directions.WEST)
|
||||
}
|
||||
}
|
||||
if (target == null || (target != Directions.WEST && lightProperties.propagatesLight(Directions.EAST))) {
|
||||
if (position.x < ProtocolDefinition.SECTION_MAX_X) {
|
||||
traceBlockIncrease(position.plusX(), neighbourLuminance, Directions.EAST)
|
||||
} else {
|
||||
neighbours[Directions.O_EAST, ChunkNeighbours.EAST, chunkNeighbours]?.light?.traceBlockIncrease(position.with(x = 0), neighbourLuminance, Directions.EAST)
|
||||
neighbours[Directions.O_EAST, Directions.EAST, chunkNeighbours]?.light?.traceBlockIncrease(position.with(x = 0), neighbourLuminance, Directions.EAST)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -317,7 +316,7 @@ class SectionLight(
|
||||
// this light level will be 15, don't care
|
||||
return
|
||||
}
|
||||
val chunkNeighbours = chunk.neighbours.get() ?: return
|
||||
val chunkNeighbours = chunk.neighbours.neighbours
|
||||
val currentLight = this[position].toInt()
|
||||
if (((currentLight and SKY_LIGHT_MASK) shr 4) >= nextLevel) {
|
||||
return
|
||||
@ -372,28 +371,28 @@ class SectionLight(
|
||||
if (position.z > 0) {
|
||||
traceSkyLightIncrease(position.minusZ(), nextNeighbourLevel, Directions.NORTH, totalY)
|
||||
} else {
|
||||
neighbours[Directions.O_NORTH, ChunkNeighbours.NORTH, chunkNeighbours]?.light?.traceSkyLightIncrease(position.with(z = ProtocolDefinition.SECTION_MAX_Z), nextNeighbourLevel, Directions.NORTH, totalY)
|
||||
neighbours[Directions.O_NORTH, Directions.NORTH, chunkNeighbours]?.light?.traceSkyLightIncrease(position.with(z = ProtocolDefinition.SECTION_MAX_Z), nextNeighbourLevel, Directions.NORTH, totalY)
|
||||
}
|
||||
}
|
||||
if (target != Directions.NORTH && (target == null || lightProperties.propagatesLight(Directions.SOUTH))) {
|
||||
if (position.z < ProtocolDefinition.SECTION_MAX_Z) {
|
||||
traceSkyLightIncrease(position.plusZ(), nextNeighbourLevel, Directions.SOUTH, totalY)
|
||||
} else {
|
||||
neighbours[Directions.O_SOUTH, ChunkNeighbours.SOUTH, chunkNeighbours]?.light?.traceSkyLightIncrease(position.with(z = 0), nextNeighbourLevel, Directions.SOUTH, totalY)
|
||||
neighbours[Directions.O_SOUTH, Directions.SOUTH, chunkNeighbours]?.light?.traceSkyLightIncrease(position.with(z = 0), nextNeighbourLevel, Directions.SOUTH, totalY)
|
||||
}
|
||||
}
|
||||
if (target != Directions.EAST && (target == null || lightProperties.propagatesLight(Directions.WEST))) {
|
||||
if (position.x > 0) {
|
||||
traceSkyLightIncrease(position.minusX(), nextNeighbourLevel, Directions.WEST, totalY)
|
||||
} else {
|
||||
neighbours[Directions.O_WEST, ChunkNeighbours.WEST, chunkNeighbours]?.light?.traceSkyLightIncrease(position.with(x = ProtocolDefinition.SECTION_MAX_X), nextNeighbourLevel, Directions.WEST, totalY)
|
||||
neighbours[Directions.O_WEST, Directions.WEST, chunkNeighbours]?.light?.traceSkyLightIncrease(position.with(x = ProtocolDefinition.SECTION_MAX_X), nextNeighbourLevel, Directions.WEST, totalY)
|
||||
}
|
||||
}
|
||||
if (target != Directions.WEST && (target == null || lightProperties.propagatesLight(Directions.EAST))) {
|
||||
if (position.x < ProtocolDefinition.SECTION_MAX_X) {
|
||||
traceSkyLightIncrease(position.plusX(), nextNeighbourLevel, Directions.EAST, totalY)
|
||||
} else {
|
||||
neighbours[Directions.O_EAST, ChunkNeighbours.EAST, chunkNeighbours]?.light?.traceSkyLightIncrease(position.with(x = 0), nextNeighbourLevel, Directions.EAST, totalY)
|
||||
neighbours[Directions.O_EAST, Directions.EAST, chunkNeighbours]?.light?.traceSkyLightIncrease(position.with(x = 0), nextNeighbourLevel, Directions.EAST, totalY)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -428,8 +427,8 @@ class SectionLight(
|
||||
}
|
||||
}
|
||||
|
||||
private inline operator fun Array<ChunkSection?>.get(direction: Int, neighbour: Int, neighbours: Array<Chunk>): ChunkSection? {
|
||||
return this[direction] ?: neighbours[neighbour].getOrPut(section.sectionHeight, false)
|
||||
private inline operator fun Array<ChunkSection?>.get(direction: Int, neighbour: Directions, neighbours: ChunkNeighbourArray): ChunkSection? {
|
||||
return this[direction] ?: neighbours[neighbour]?.getOrPut(section.sectionHeight, false)
|
||||
}
|
||||
|
||||
fun propagateFromNeighbours(position: InSectionPosition) {
|
||||
@ -492,7 +491,8 @@ class SectionLight(
|
||||
val totalY = section.sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y + position.y
|
||||
section.chunk.let {
|
||||
// check if neighbours are above heightmap, if so set light level to max
|
||||
val chunkNeighbours = it.neighbours.get() ?: return@let
|
||||
val chunkNeighbours = it.neighbours.neighbours
|
||||
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
|
||||
|
@ -21,7 +21,7 @@ import de.bixilon.minosoft.data.world.biome.source.DummyBiomeSource
|
||||
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.manager.size.WorldSizeManager
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours
|
||||
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.WorldUpdateEvent
|
||||
import de.bixilon.minosoft.data.world.chunk.update.chunk.ChunkCreateUpdate
|
||||
@ -57,9 +57,9 @@ class ChunkManager(val world: World, chunkCapacity: Int = 0, prototypeCapacity:
|
||||
}
|
||||
val updates = hashSetOf<AbstractWorldUpdate>(ChunkUnloadUpdate(position, chunk))
|
||||
|
||||
for ((index, neighbour) in chunk.neighbours.neighbours.withIndex()) {
|
||||
for ((index, neighbour) in chunk.neighbours.neighbours.array.withIndex()) {
|
||||
if (neighbour == null) continue
|
||||
val offset = ChunkNeighbours.OFFSETS[index]
|
||||
val offset = ChunkPosition(ChunkNeighbourArray.OFFSETS[index])
|
||||
val neighbourPosition = position + offset
|
||||
neighbour.neighbours.remove(-offset)
|
||||
updates += NeighbourChangeUpdate(neighbourPosition, neighbour)
|
||||
@ -137,10 +137,10 @@ class ChunkManager(val world: World, chunkCapacity: Int = 0, prototypeCapacity:
|
||||
val updates = HashSet<AbstractWorldUpdate>(9, 1.0f)
|
||||
updates += ChunkCreateUpdate(chunk.position, chunk)
|
||||
|
||||
for (index in 0 until ChunkNeighbours.COUNT) {
|
||||
val offset = ChunkNeighbours.OFFSETS[index]
|
||||
for (index in 0 until ChunkNeighbourArray.COUNT) {
|
||||
val offset = ChunkPosition(ChunkNeighbourArray.OFFSETS[index])
|
||||
val neighbour = this.chunks.unsafe[chunk.position + offset] ?: continue
|
||||
chunk.neighbours[index] = neighbour
|
||||
chunk.neighbours[offset] = neighbour
|
||||
neighbour.neighbours[-offset] = chunk
|
||||
|
||||
}
|
||||
@ -148,7 +148,7 @@ class ChunkManager(val world: World, chunkCapacity: Int = 0, prototypeCapacity:
|
||||
// TODO: fire event
|
||||
|
||||
|
||||
for (neighbour in chunk.neighbours) {
|
||||
for (neighbour in chunk.neighbours.neighbours.array) {
|
||||
if (neighbour == null) continue
|
||||
updates += NeighbourChangeUpdate(neighbour.position, neighbour)
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.neighbours
|
||||
|
||||
import de.bixilon.minosoft.data.Axes
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||
|
||||
@JvmInline
|
||||
value class ChunkNeighbourArray(val array: Array<Chunk?>) {
|
||||
|
||||
constructor() : this(arrayOfNulls(OFFSETS.size))
|
||||
|
||||
|
||||
private operator fun get(index: Int) = array[index]
|
||||
private operator fun set(index: Int, chunk: Chunk?) {
|
||||
array[index] = chunk
|
||||
}
|
||||
|
||||
operator fun get(direction: Directions): Chunk? {
|
||||
if (direction.axis == Axes.Y) throw IllegalArgumentException("Chunk neighbours are 2D!")
|
||||
return this[BY_DIRECTION[direction.ordinal - Directions.SIDE_OFFSET]]
|
||||
}
|
||||
|
||||
operator fun get(offset: ChunkPosition) = this[offset.neighbourIndex]
|
||||
|
||||
operator fun set(offset: ChunkPosition, chunk: Chunk?) {
|
||||
this[offset.neighbourIndex] = chunk
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
const val COUNT = 8
|
||||
private val BY_DIRECTION = intArrayOf(3, 4, 1, 6)
|
||||
|
||||
/**
|
||||
* 0 | 3 | 5
|
||||
* 1 | - | 6
|
||||
* 2 | 4 | 7
|
||||
*/
|
||||
private val _0 = ChunkPosition(-1, -1)
|
||||
private val _1 = ChunkPosition(-1, +0)
|
||||
private val _2 = ChunkPosition(-1, +1)
|
||||
private val _3 = ChunkPosition(+0, -1)
|
||||
private val _4 = ChunkPosition(+0, +1)
|
||||
private val _5 = ChunkPosition(+1, -1)
|
||||
private val _6 = ChunkPosition(+1, +0)
|
||||
private val _7 = ChunkPosition(+1, +1)
|
||||
|
||||
|
||||
val OFFSETS = longArrayOf(_0.raw, _1.raw, _2.raw, _3.raw, _4.raw, _5.raw, _6.raw, _7.raw)
|
||||
|
||||
private val ChunkPosition.neighbourIndex: Int
|
||||
get() = when (this) { // TODO: use some hash table
|
||||
_0 -> 0
|
||||
_1 -> 1
|
||||
_2 -> 2
|
||||
_3 -> 3
|
||||
_4 -> 4
|
||||
_5 -> 5
|
||||
_6 -> 6
|
||||
_7 -> 7
|
||||
else -> throw IllegalArgumentException("Invalid chunk offset: $this")
|
||||
}
|
||||
}
|
||||
}
|
@ -25,84 +25,69 @@ import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||
import de.bixilon.minosoft.data.world.positions.InChunkPosition
|
||||
import de.bixilon.minosoft.data.world.positions.SectionHeight
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.play.block.chunk.ChunkUtil
|
||||
import kotlin.math.abs
|
||||
|
||||
class ChunkNeighbours(val chunk: Chunk) : Iterable<Chunk?> {
|
||||
val neighbours: Array<Chunk?> = arrayOfNulls(COUNT)
|
||||
class ChunkNeighbours(val chunk: Chunk) {
|
||||
val neighbours = ChunkNeighbourArray()
|
||||
private var count = 0
|
||||
|
||||
val complete: Boolean get() = count == COUNT
|
||||
val complete: Boolean get() = count == ChunkNeighbourArray.COUNT
|
||||
|
||||
fun get(): Array<Chunk>? {
|
||||
if (count == COUNT) { // TODO: Race condition!
|
||||
if (complete) { // TODO: Race condition!
|
||||
return neighbours.unsafeCast()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@Deprecated("index")
|
||||
operator fun set(index: Int, chunk: Chunk) {
|
||||
operator fun set(offset: ChunkPosition, chunk: Chunk) {
|
||||
this.chunk.lock.lock()
|
||||
val current = neighbours[index]
|
||||
neighbours[index] = chunk
|
||||
val current = neighbours[offset]
|
||||
neighbours[offset] = chunk
|
||||
if (current == null) {
|
||||
count++
|
||||
if (count == COUNT) {
|
||||
complete(get()!!)
|
||||
if (complete) {
|
||||
complete()
|
||||
}
|
||||
}
|
||||
this.chunk.lock.unlock()
|
||||
}
|
||||
|
||||
operator fun set(offset: ChunkPosition, chunk: Chunk) {
|
||||
set(getIndex(offset), chunk)
|
||||
}
|
||||
|
||||
@Deprecated("index")
|
||||
fun remove(index: Int) {
|
||||
fun remove(offset: ChunkPosition) {
|
||||
chunk.lock.lock()
|
||||
val current = neighbours[index]
|
||||
neighbours[index] = null
|
||||
val current = neighbours[offset]
|
||||
if (current != null) {
|
||||
neighbours[offset] = null
|
||||
count--
|
||||
}
|
||||
chunk.lock.unlock()
|
||||
}
|
||||
|
||||
fun remove(offset: ChunkPosition) {
|
||||
remove(getIndex(offset))
|
||||
}
|
||||
|
||||
fun completeSection(neighbours: Array<Chunk>, section: ChunkSection, sectionHeight: SectionHeight, noise: NoiseBiomeAccessor?) {
|
||||
fun completeSection(section: ChunkSection, sectionHeight: SectionHeight, noise: NoiseBiomeAccessor?) {
|
||||
section.neighbours = ChunkUtil.getDirectNeighbours(neighbours, chunk, sectionHeight)
|
||||
}
|
||||
|
||||
private fun complete(neighbours: Array<Chunk>) {
|
||||
private fun complete() {
|
||||
val noise = chunk.world.biomes.noise
|
||||
for ((index, section) in chunk.sections.withIndex()) {
|
||||
if (section == null) continue
|
||||
val sectionHeight = index + chunk.minSection
|
||||
completeSection(neighbours, section, sectionHeight, noise)
|
||||
completeSection(section, sectionHeight, noise)
|
||||
}
|
||||
chunk.light.recalculate(false)
|
||||
chunk.light.propagateFromNeighbours(fireEvent = false, fireSameChunkEvent = false)
|
||||
}
|
||||
|
||||
@Deprecated("index")
|
||||
operator fun get(index: Int): Chunk? {
|
||||
return neighbours[index]
|
||||
operator fun get(direction: Directions): Chunk? {
|
||||
return neighbours[direction]
|
||||
}
|
||||
|
||||
operator fun get(offset: ChunkPosition): Chunk {
|
||||
if (offset.xz == 0) return chunk
|
||||
return this[getIndex(offset)] // TODO: trace
|
||||
operator fun get(offset: ChunkPosition): Chunk? {
|
||||
if (offset == ChunkPosition.EMPTY) return chunk
|
||||
return traceChunk(offset)
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<Chunk?> {
|
||||
return neighbours.iterator()
|
||||
}
|
||||
|
||||
|
||||
fun update(neighbours: Array<Chunk>, sectionHeight: Int) {
|
||||
fun update(sectionHeight: Int) {
|
||||
for (nextSectionHeight in sectionHeight - 1..sectionHeight + 1) {
|
||||
if (nextSectionHeight < chunk.minSection || nextSectionHeight > chunk.maxSection) {
|
||||
continue
|
||||
@ -114,29 +99,18 @@ class ChunkNeighbours(val chunk: Chunk) : Iterable<Chunk?> {
|
||||
}
|
||||
}
|
||||
|
||||
fun traceChunk(offset: ChunkPosition): Chunk = when {
|
||||
offsetX == 0 -> when {
|
||||
offsetZ == 0 -> chunk
|
||||
offsetZ < 0 -> neighbours[3]?.neighbours?.trace(offsetX, offsetZ + 1)
|
||||
offsetZ > 0 -> neighbours[4]?.neighbours?.trace(offsetX, offsetZ - 1)
|
||||
fun traceChunk(offset: ChunkPosition): Chunk? {
|
||||
if (offset == ChunkPosition.EMPTY) return chunk
|
||||
if (abs(offset.x) <= 1 && abs(offset.z) <= 1) return this.neighbours[offset]
|
||||
|
||||
// TODO: optimize diagonal trace
|
||||
return when {
|
||||
offset.z < 0 -> neighbours[Directions.NORTH]?.neighbours?.traceChunk(offset.plusZ())
|
||||
offset.z > 0 -> neighbours[Directions.SOUTH]?.neighbours?.traceChunk(offset.minusZ())
|
||||
offset.x < 0 -> neighbours[Directions.WEST]?.neighbours?.traceChunk(offset.plusX())
|
||||
offset.x > 0 -> neighbours[Directions.WEST]?.neighbours?.traceChunk(offset.minusX())
|
||||
else -> Broken()
|
||||
}
|
||||
|
||||
offsetX < 0 -> when {
|
||||
offsetZ == 0 -> neighbours[1]?.neighbours?.trace(offsetX + 1, offsetZ)
|
||||
offsetZ < 0 -> neighbours[0]?.neighbours?.trace(offsetX + 1, offsetZ + 1)
|
||||
offsetZ > 0 -> neighbours[2]?.neighbours?.trace(offsetX + 1, offsetZ - 1)
|
||||
else -> Broken()
|
||||
}
|
||||
|
||||
offsetX > 0 -> when {
|
||||
offsetZ == 0 -> neighbours[6]?.neighbours?.trace(offsetX - 1, offsetZ)
|
||||
offsetZ < 0 -> neighbours[5]?.neighbours?.trace(offsetX - 1, offsetZ + 1)
|
||||
offsetZ > 0 -> neighbours[7]?.neighbours?.trace(offsetX - 1, offsetZ - 1)
|
||||
else -> Broken()
|
||||
}
|
||||
|
||||
else -> Broken()
|
||||
}
|
||||
|
||||
fun traceBlock(position: BlockPosition): BlockState? {
|
||||
@ -148,30 +122,4 @@ class ChunkNeighbours(val chunk: Chunk) : Iterable<Chunk?> {
|
||||
|
||||
fun traceBlock(origin: InChunkPosition, offset: BlockPosition) = traceBlock(offset - origin)
|
||||
fun traceBlock(origin: InChunkPosition, direction: Directions) = traceBlock((BlockPosition(origin) + direction))
|
||||
|
||||
companion object {
|
||||
const val COUNT = 8
|
||||
const val NORTH = 3
|
||||
const val SOUTH = 4
|
||||
const val WEST = 1
|
||||
const val EAST = 6
|
||||
|
||||
|
||||
/**
|
||||
* 0 | 3 | 5
|
||||
* 1 | - | 6
|
||||
* 2 | 4 | 7
|
||||
*/
|
||||
|
||||
val OFFSETS = arrayOf(
|
||||
ChunkPosition(-1, -1), // 0
|
||||
ChunkPosition(-1, +0), // 1
|
||||
ChunkPosition(-1, +1), // 2
|
||||
ChunkPosition(+0, -1), // 3
|
||||
ChunkPosition(+0, +1), // 4
|
||||
ChunkPosition(+1, -1), // 5
|
||||
ChunkPosition(+1, +0), // 6
|
||||
ChunkPosition(+1, +1), // 7
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ open class SectionDataProvider<T>(
|
||||
private set
|
||||
val isEmpty: Boolean
|
||||
get() = count == 0
|
||||
var minPosition = InSectionPosition(ProtocolDefinition.SECTION_WIDTH_X, ProtocolDefinition.SECTION_HEIGHT_Y, ProtocolDefinition.SECTION_WIDTH_Z)
|
||||
var minPosition = InSectionPosition(ProtocolDefinition.SECTION_MAX_X, ProtocolDefinition.SECTION_MAX_Y, ProtocolDefinition.SECTION_MAX_Z)
|
||||
private set
|
||||
var maxPosition = InSectionPosition(0, 0, 0)
|
||||
private set
|
||||
|
@ -27,67 +27,61 @@ value class BlockPosition(
|
||||
inline val index: Long,
|
||||
) : TextFormattable {
|
||||
|
||||
init {
|
||||
TODO()
|
||||
}
|
||||
|
||||
constructor() : this(0, 0, 0)
|
||||
constructor(x: Int, y: Int, z: Int) : this((y and 0xFFF shl SHIFT_Y) or (z shl SHIFT_Z) or (x shl SHIFT_X)) {
|
||||
assertPosition(x, 0, ProtocolDefinition.SECTION_MAX_X)
|
||||
assertPosition(y, ProtocolDefinition.CHUNK_MIN_Y, ProtocolDefinition.CHUNK_MAX_Y)
|
||||
assertPosition(z, 0, ProtocolDefinition.SECTION_MAX_Z)
|
||||
constructor(x: Int, y: Int, z: Int) : this(((y and MASK_Y).toLong() shl SHIFT_Y) or ((z and MASK_Z).toLong() shl SHIFT_Z) or ((x and MASK_X).toLong() shl SHIFT_X)) {
|
||||
assertPosition(x, -MAX_X, MAX_X)
|
||||
assertPosition(y, -MAX_Y, MAX_Y)
|
||||
assertPosition(z, -MAX_Z, MAX_Z)
|
||||
}
|
||||
constructor(position: InChunkPosition) : this(position.x, position.y, position.z)
|
||||
constructor(position: InSectionPosition) : this(position.x, position.y, position.z)
|
||||
|
||||
inline val x: Int get() = (index and MASK_X) shr SHIFT_X
|
||||
inline val y: Int get() = (index and MASK_Y) shr SHIFT_Y
|
||||
inline val z: Int get() = (index and MASK_Z) shr SHIFT_Z
|
||||
inline val xz: Int get() = (index and MASK_Z or MASK_X)
|
||||
inline val x: Int get() = (index shr SHIFT_X).toInt() and MASK_X
|
||||
inline val y: Int get() = (index shr SHIFT_Y).toInt() and MASK_Y
|
||||
inline val z: Int get() = (index shr SHIFT_Z).toInt() and MASK_Z
|
||||
|
||||
|
||||
inline fun plusX(): BlockPosition {
|
||||
assertPosition(this.x < ProtocolDefinition.SECTION_MAX_X)
|
||||
assertPosition(this.x < MAX_X)
|
||||
return BlockPosition(index + X * 1)
|
||||
}
|
||||
|
||||
inline fun plusX(x: Int): BlockPosition {
|
||||
assertPosition(this.x + x, 0, ProtocolDefinition.SECTION_MAX_X)
|
||||
assertPosition(this.x + x, -MAX_X, MAX_X)
|
||||
return BlockPosition(index + X * x)
|
||||
}
|
||||
|
||||
inline fun minusX(): BlockPosition {
|
||||
assertPosition(this.x > 0)
|
||||
assertPosition(this.x > -MAX_X)
|
||||
return BlockPosition(index - X * 1)
|
||||
}
|
||||
|
||||
inline fun plusY(): BlockPosition {
|
||||
assertPosition(this.y < ProtocolDefinition.CHUNK_MAX_Y)
|
||||
assertPosition(this.y < MAX_Y)
|
||||
return BlockPosition(index + Y * 1)
|
||||
}
|
||||
|
||||
inline fun plusY(y: Int): BlockPosition {
|
||||
assertPosition(this.y + y, ProtocolDefinition.CHUNK_MIN_Y, ProtocolDefinition.CHUNK_MAX_Y)
|
||||
assertPosition(this.y + y, -MAX_Y, MAX_Y)
|
||||
return BlockPosition(index + Y * y)
|
||||
}
|
||||
|
||||
inline fun minusY(): BlockPosition {
|
||||
assertPosition(this.y > ProtocolDefinition.CHUNK_MIN_Y)
|
||||
assertPosition(this.y > -MAX_Y)
|
||||
return BlockPosition(index - Y * 1)
|
||||
}
|
||||
|
||||
inline fun plusZ(): BlockPosition {
|
||||
assertPosition(this.z < ProtocolDefinition.SECTION_MAX_Z)
|
||||
assertPosition(this.z < MAX_Y)
|
||||
return BlockPosition(index + Z * 1)
|
||||
}
|
||||
|
||||
inline fun plusZ(z: Int): BlockPosition {
|
||||
assertPosition(this.z + z, 0, ProtocolDefinition.SECTION_MAX_Z)
|
||||
assertPosition(this.z + z, -MAX_Z, MAX_Z)
|
||||
return BlockPosition(index + Z * z)
|
||||
}
|
||||
|
||||
inline fun minusZ(): BlockPosition {
|
||||
assertPosition(this.z > 0)
|
||||
assertPosition(this.z > -MAX_Z)
|
||||
return BlockPosition(index - Z * 1)
|
||||
}
|
||||
|
||||
@ -123,19 +117,26 @@ value class BlockPosition(
|
||||
override fun toString() = "b($x $y $z)"
|
||||
|
||||
companion object {
|
||||
const val MASK_X = 0x00F
|
||||
const val BITS_X = 26
|
||||
const val MASK_X = (1 shl BITS_X) - 1
|
||||
const val SHIFT_X = 0
|
||||
|
||||
const val MASK_Z = 0x0F0
|
||||
const val SHIFT_Z = 4
|
||||
const val BITS_Z = 26
|
||||
const val MASK_Z = (1 shl BITS_Z) - 1
|
||||
const val SHIFT_Z = BITS_X
|
||||
|
||||
const val MASK_Y = 0xFFF00
|
||||
const val SHIFT_Y = 8
|
||||
const val BITS_Y = 12
|
||||
const val MASK_Y = (1 shl BITS_Y) - 1
|
||||
const val SHIFT_Y = BITS_X + BITS_Z
|
||||
|
||||
const val X = 1 shl SHIFT_X
|
||||
const val Z = 1 shl SHIFT_Z
|
||||
const val Y = 1 shl SHIFT_Y
|
||||
|
||||
const val MAX_X = 0
|
||||
const val MAX_Y = 0
|
||||
const val MAX_Z = 0
|
||||
|
||||
|
||||
val EMPTY = BlockPosition(0, 0, 0)
|
||||
|
||||
|
@ -32,7 +32,7 @@ object BlockPositionUtil {
|
||||
inline fun assertPosition(value: Int, min: Int, max: Int) {
|
||||
if (!DebugOptions.VERIFY_COORDINATES) return
|
||||
if (value < min) throw AssertionError("coordinate out of range: $value < $min")
|
||||
if (value > min) throw AssertionError("coordinate out of range: $value > $max")
|
||||
if (value > max) throw AssertionError("coordinate out of range: $value > $max")
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,9 +13,9 @@
|
||||
|
||||
package de.bixilon.minosoft.data.world.positions
|
||||
|
||||
import de.bixilon.kutil.exception.Broken
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.text.formatting.TextFormattable
|
||||
import de.bixilon.minosoft.data.world.positions.BlockPositionUtil.assertPosition
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.KUtil.format
|
||||
|
||||
@ -23,53 +23,45 @@ import de.bixilon.minosoft.util.KUtil.format
|
||||
value class ChunkPosition(
|
||||
inline val raw: Long,
|
||||
) : TextFormattable {
|
||||
init {
|
||||
TODO()
|
||||
}
|
||||
|
||||
constructor() : this(0, 0)
|
||||
|
||||
constructor(x: Int, z: Int) : this((z shl SHIFT_Z) or (x shl SHIFT_X)) {
|
||||
assert(x >= 0)
|
||||
assert(x <= ProtocolDefinition.SECTION_MAX_X)
|
||||
assert(z >= 0)
|
||||
assert(z <= ProtocolDefinition.SECTION_MAX_Z)
|
||||
constructor(x: Int, z: Int) : this((z.toLong() shl SHIFT_Z) or (x.toLong() shl SHIFT_X)) {
|
||||
assertPosition(x, -MAX_X, MAX_X)
|
||||
assertPosition(z, -MAX_Z, MAX_Z)
|
||||
}
|
||||
|
||||
inline val x: Int get() = (raw and MASK_X) shr SHIFT_X
|
||||
inline val z: Int get() = (raw and MASK_Z) shr SHIFT_Z
|
||||
inline val xz: Int get() = (raw and MASK_Z or MASK_X)
|
||||
inline val x: Int get() = (raw ushr SHIFT_X).toInt() and MASK_X
|
||||
inline val z: Int get() = (raw ushr SHIFT_Z).toInt() and MASK_Z
|
||||
|
||||
|
||||
inline fun plusX(): ChunkPosition {
|
||||
assert(this.x < ProtocolDefinition.SECTION_MAX_X)
|
||||
assertPosition(this.x < MAX_X)
|
||||
return ChunkPosition(raw + X * 1)
|
||||
}
|
||||
|
||||
inline fun plusX(x: Int): ChunkPosition {
|
||||
assert(this.x + x < ProtocolDefinition.SECTION_MAX_X)
|
||||
assert(this.x + x > 0)
|
||||
assertPosition(this.x + x, -MAX_X, MAX_X)
|
||||
return ChunkPosition(raw + X * x)
|
||||
}
|
||||
|
||||
inline fun minusX(): ChunkPosition {
|
||||
assert(this.x > 0)
|
||||
assert(this.x > -MAX_X)
|
||||
return ChunkPosition(raw - X * 1)
|
||||
}
|
||||
|
||||
inline fun plusZ(): ChunkPosition {
|
||||
assert(this.z < ProtocolDefinition.SECTION_MAX_Z)
|
||||
assert(this.z < MAX_Z)
|
||||
return ChunkPosition(raw + Z * 1)
|
||||
}
|
||||
|
||||
inline fun plusZ(z: Int): ChunkPosition {
|
||||
assert(this.z + z < ProtocolDefinition.SECTION_MAX_Z)
|
||||
assert(this.z + z > 0)
|
||||
assertPosition(this.z + z, -MAX_Z, MAX_Z)
|
||||
return ChunkPosition(raw + Z * z)
|
||||
}
|
||||
|
||||
inline fun minusZ(): ChunkPosition {
|
||||
assert(this.z > 0)
|
||||
assert(this.z > -MAX_Z)
|
||||
return ChunkPosition(raw - Z * 1)
|
||||
}
|
||||
|
||||
@ -98,28 +90,21 @@ value class ChunkPosition(
|
||||
override fun toString() = "c($x $z)"
|
||||
|
||||
|
||||
val index: Int
|
||||
get() = when {
|
||||
x == -1 && z == -1 -> 0
|
||||
x == -1 && z == 0 -> 1
|
||||
x == -1 && z == 1 -> 2
|
||||
x == 0 && z == -1 -> 3
|
||||
x == 0 && z == 1 -> 4
|
||||
x == 1 && z == -1 -> 5
|
||||
x == 1 && z == 0 -> 6
|
||||
x == 1 && z == 1 -> 7
|
||||
else -> Broken("Can not get neighbour chunk from offset $this")
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MASK_X = 0x00F
|
||||
const val BITS_X = 32
|
||||
const val MASK_X = (1 shl BITS_X) - 1
|
||||
const val SHIFT_X = 0
|
||||
|
||||
const val MASK_Z = 0x0F0
|
||||
const val SHIFT_Z = 4
|
||||
const val BITS_Z = 32
|
||||
const val MASK_Z = (1 shl BITS_Z) - 1
|
||||
const val SHIFT_Z = BITS_X
|
||||
|
||||
const val X = 1 shl SHIFT_X
|
||||
const val Z = 1 shl SHIFT_Z
|
||||
const val X = 1L shl SHIFT_X
|
||||
const val Z = 1L shl SHIFT_Z
|
||||
|
||||
|
||||
const val MAX_X = Int.MAX_VALUE
|
||||
const val MAX_Z = Int.MAX_VALUE
|
||||
|
||||
|
||||
val EMPTY = ChunkPosition(0, 0)
|
||||
|
@ -28,16 +28,16 @@ value class InChunkPosition(
|
||||
|
||||
constructor() : this(0, 0, 0)
|
||||
|
||||
constructor(x: Int, y: Int, z: Int) : this((y and 0xFFF shl SHIFT_Y) or (z shl SHIFT_Z) or (x shl SHIFT_X)) {
|
||||
constructor(x: Int, y: Int, z: Int) : this(((y and 0xFFF) shl SHIFT_Y) or (z shl SHIFT_Z) or (x shl SHIFT_X)) {
|
||||
assertPosition(x, 0, ProtocolDefinition.SECTION_MAX_X)
|
||||
assertPosition(y, ProtocolDefinition.CHUNK_MIN_Y, ProtocolDefinition.CHUNK_MAX_Y)
|
||||
assertPosition(z, 0, ProtocolDefinition.SECTION_MAX_Z)
|
||||
}
|
||||
|
||||
inline val x: Int get() = (index and MASK_X) shr SHIFT_X
|
||||
inline val y: Int get() = (index and MASK_Y) shr SHIFT_Y
|
||||
inline val z: Int get() = (index and MASK_Z) shr SHIFT_Z
|
||||
inline val xz: Int get() = (index and MASK_Z or MASK_X)
|
||||
inline val x: Int get() = (index shr SHIFT_X) and MASK_X
|
||||
inline val y: Int get() = (index and (MASK_Y shl SHIFT_Y)) shl 20 shr 20
|
||||
inline val z: Int get() = (index shr SHIFT_Z) and MASK_Z
|
||||
inline val xz: Int get() = index and ((MASK_X shl SHIFT_X) or (MASK_Z shl SHIFT_Z))
|
||||
|
||||
|
||||
inline fun plusX(): InChunkPosition {
|
||||
@ -99,14 +99,17 @@ value class InChunkPosition(
|
||||
inline val sectionHeight get() = y.sectionHeight
|
||||
|
||||
companion object {
|
||||
const val MASK_X = 0x00F
|
||||
const val BITS_X = 4
|
||||
const val MASK_X = (1 shl BITS_X) - 1
|
||||
const val SHIFT_X = 0
|
||||
|
||||
const val MASK_Z = 0x0F0
|
||||
const val SHIFT_Z = 4
|
||||
const val BITS_Z = 4
|
||||
const val MASK_Z = (1 shl BITS_Z) - 1
|
||||
const val SHIFT_Z = BITS_X
|
||||
|
||||
const val MASK_Y = 0xFFF00
|
||||
const val SHIFT_Y = 8
|
||||
const val BITS_Y = 12
|
||||
const val MASK_Y = (1 shl BITS_Y) - 1
|
||||
const val SHIFT_Y = BITS_X + BITS_Z
|
||||
|
||||
const val X = 1 shl SHIFT_X
|
||||
const val Z = 1 shl SHIFT_Z
|
||||
|
@ -32,11 +32,11 @@ value class InSectionPosition(
|
||||
assertPosition(z, 0, ProtocolDefinition.SECTION_MAX_Z)
|
||||
}
|
||||
|
||||
inline val x: Int get() = (index and MASK_X) shr SHIFT_X
|
||||
inline val y: Int get() = (index and MASK_Y) shr SHIFT_Y
|
||||
inline val z: Int get() = (index and MASK_Z) shr SHIFT_Z
|
||||
inline val x: Int get() = (index shr SHIFT_X) and MASK_X
|
||||
inline val y: Int get() = (index shr SHIFT_Y) and MASK_Y
|
||||
inline val z: Int get() = (index shr SHIFT_Z) and MASK_Z
|
||||
|
||||
inline val xz: Int get() = index and (MASK_X or MASK_Z)
|
||||
inline val xz: Int get() = index and ((MASK_X shl SHIFT_X) or (MASK_Z shl SHIFT_Z))
|
||||
|
||||
|
||||
inline fun plusX(): InSectionPosition {
|
||||
@ -95,14 +95,17 @@ value class InSectionPosition(
|
||||
override fun toString() = "s($x $y $z)"
|
||||
|
||||
companion object {
|
||||
const val MASK_X = 0x00F
|
||||
const val BITS_X = 4
|
||||
const val MASK_X = (1 shl BITS_X) - 1
|
||||
const val SHIFT_X = 0
|
||||
|
||||
const val MASK_Z = 0x0F0
|
||||
const val SHIFT_Z = 4
|
||||
const val BITS_Z = 4
|
||||
const val MASK_Z = (1 shl BITS_Z) - 1
|
||||
const val SHIFT_Z = BITS_X
|
||||
|
||||
const val MASK_Y = 0xF00
|
||||
const val SHIFT_Y = 8
|
||||
const val BITS_Y = 4
|
||||
const val MASK_Y = (1 shl BITS_Y) - 1
|
||||
const val SHIFT_Y = BITS_X + BITS_Z
|
||||
|
||||
const val X = 1 shl SHIFT_X
|
||||
const val Z = 1 shl SHIFT_Z
|
||||
|
@ -156,7 +156,7 @@ class Frustum(
|
||||
return containsRegion(min.x, min.y, min.z, max.x, max.y, max.z)
|
||||
}
|
||||
|
||||
fun containsChunkSection(chunkPosition: ChunkPosition, sectionHeight: Int, minPosition: InSectionPosition = CHUNK_NIN_POSITION, maxPosition: InSectionPosition = ProtocolDefinition.CHUNK_SECTION_SIZE): Boolean {
|
||||
fun containsChunkSection(chunkPosition: ChunkPosition, sectionHeight: Int, minPosition: InSectionPosition = SECTION_MIN_POSITION, maxPosition: InSectionPosition = SECTION_MAX_POSITION): Boolean {
|
||||
val offset = camera.offset.offset
|
||||
val baseX = ((chunkPosition.x shl 4) - offset.x).toFloat()
|
||||
val baseY = ((sectionHeight shl 4) - offset.y).toFloat()
|
||||
@ -215,7 +215,8 @@ class Frustum(
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val CHUNK_NIN_POSITION = InSectionPosition(0, 0, 0)
|
||||
companion object {
|
||||
val SECTION_MIN_POSITION = InSectionPosition(0, 0, 0)
|
||||
val SECTION_MAX_POSITION = InSectionPosition(ProtocolDefinition.SECTION_MAX_X, ProtocolDefinition.SECTION_MAX_Y, ProtocolDefinition.SECTION_MAX_Z)
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import de.bixilon.kutil.observer.DataObserver.Companion.observe
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.registries.shapes.aabb.AABB
|
||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours
|
||||
import de.bixilon.minosoft.data.world.chunk.update.WorldUpdateEvent
|
||||
import de.bixilon.minosoft.data.world.chunk.update.chunk.ChunkCreateUpdate
|
||||
import de.bixilon.minosoft.data.world.chunk.update.chunk.ChunkUnloadUpdate
|
||||
@ -31,10 +30,10 @@ import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||
import de.bixilon.minosoft.gui.rendering.camera.Camera
|
||||
import de.bixilon.minosoft.gui.rendering.camera.frustum.Frustum
|
||||
import de.bixilon.minosoft.gui.rendering.events.VisibilityGraphChangeEvent
|
||||
import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.play.block.chunk.ChunkUtil.isInViewDistance
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet
|
||||
|
||||
/**
|
||||
@ -149,7 +148,7 @@ class WorldVisibilityGraph(
|
||||
return frustum.containsAABB(aabb)
|
||||
}
|
||||
|
||||
fun isSectionVisible(chunkPosition: ChunkPosition, sectionHeight: Int, minPosition: InSectionPosition = DEFAULT_MIN_POSITION, maxPosition: InSectionPosition = ProtocolDefinition.CHUNK_SECTION_SIZE, checkChunk: Boolean = true): Boolean {
|
||||
fun isSectionVisible(chunkPosition: ChunkPosition, sectionHeight: Int, minPosition: InSectionPosition = Frustum.SECTION_MIN_POSITION, maxPosition: InSectionPosition = Frustum.SECTION_MIN_POSITION, checkChunk: Boolean = true): Boolean {
|
||||
if (checkChunk && !isChunkVisible(chunkPosition)) {
|
||||
return false
|
||||
}
|
||||
@ -249,7 +248,7 @@ class WorldVisibilityGraph(
|
||||
|
||||
if (directionX <= 0 && (section?.occlusion?.isOccluded(inverted, Directions.WEST) != true) && chunkPosition.x > chunkMin.x) {
|
||||
val next = chunkPosition.minusX()
|
||||
val nextChunk = chunk.neighbours[ChunkNeighbours.WEST]
|
||||
val nextChunk = chunk.neighbours[Directions.WEST]
|
||||
if (nextChunk != null) {
|
||||
val nextVisibilities = getVisibility(next) ?: return
|
||||
if (!nextVisibilities[visibilitySectionIndex]) {
|
||||
@ -261,7 +260,7 @@ class WorldVisibilityGraph(
|
||||
|
||||
if (directionX >= 0 && (section?.occlusion?.isOccluded(inverted, Directions.EAST) != true) && chunkPosition.x < chunkMax.x) {
|
||||
val next = chunkPosition.plusX()
|
||||
val nextChunk = chunk.neighbours[ChunkNeighbours.EAST]
|
||||
val nextChunk = chunk.neighbours[Directions.EAST]
|
||||
if (nextChunk != null) {
|
||||
val nextVisibilities = getVisibility(next) ?: return
|
||||
if (!nextVisibilities[visibilitySectionIndex]) {
|
||||
@ -286,7 +285,7 @@ class WorldVisibilityGraph(
|
||||
|
||||
if (directionZ <= 0 && (section?.occlusion?.isOccluded(inverted, Directions.NORTH) != true) && chunkPosition.z > chunkMin.z) {
|
||||
val next = chunkPosition.minusZ()
|
||||
val nextChunk = chunk.neighbours[ChunkNeighbours.NORTH]
|
||||
val nextChunk = chunk.neighbours[Directions.NORTH]
|
||||
if (nextChunk != null) {
|
||||
val nextVisibilities = getVisibility(next) ?: return
|
||||
if (!nextVisibilities[visibilitySectionIndex]) {
|
||||
@ -298,7 +297,7 @@ class WorldVisibilityGraph(
|
||||
|
||||
if (directionZ >= 0 && (section?.occlusion?.isOccluded(inverted, Directions.SOUTH) != true) && chunkPosition.z < chunkMax.z) {
|
||||
val next = chunkPosition.plusZ()
|
||||
val nextChunk = chunk.neighbours[ChunkNeighbours.SOUTH]
|
||||
val nextChunk = chunk.neighbours[Directions.SOUTH]
|
||||
if (nextChunk != null) {
|
||||
val nextVisibilities = getVisibility(next) ?: return
|
||||
if (!nextVisibilities[visibilitySectionIndex]) {
|
||||
@ -371,8 +370,4 @@ class WorldVisibilityGraph(
|
||||
calculateGraph()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val DEFAULT_MIN_POSITION = InSectionPosition.EMPTY
|
||||
}
|
||||
}
|
||||
|
@ -32,15 +32,15 @@ class ChunkMesher(
|
||||
renderer.unload(item)
|
||||
return null
|
||||
}
|
||||
val neighbours = item.chunk.neighbours.get()
|
||||
if (neighbours == null) {
|
||||
val neighbours = item.chunk.neighbours
|
||||
if (!neighbours.complete) {
|
||||
renderer.unload(item)
|
||||
return null
|
||||
}
|
||||
val sectionNeighbours = ChunkUtil.getDirectNeighbours(neighbours, item.chunk, item.section.sectionHeight)
|
||||
val sectionNeighbours = ChunkUtil.getDirectNeighbours(neighbours.neighbours, item.chunk, item.section.sectionHeight)
|
||||
val mesh = ChunkMeshes(renderer.context, item.chunkPosition, item.sectionHeight, item.section.smallMesh)
|
||||
try {
|
||||
solid.mesh(item.chunkPosition, item.sectionHeight, item.chunk, item.section, neighbours, sectionNeighbours, mesh)
|
||||
solid.mesh(item.chunkPosition, item.sectionHeight, item.chunk, item.section, neighbours.neighbours, sectionNeighbours, mesh)
|
||||
|
||||
if (item.section.blocks.hasFluid) {
|
||||
fluid.mesh(item.chunkPosition, item.sectionHeight, item.chunk, item.section, mesh)
|
||||
|
@ -254,7 +254,7 @@ class FluidSectionMesher(
|
||||
for (side in 0 until 4) {
|
||||
val now = BlockPosition(x = position.x - (side and 0x01), y = position.y, z = position.z - (side shr 1 and 0x01))
|
||||
val offset = position.chunkPosition - providedChunk.position
|
||||
val chunk = neighbours[offset]
|
||||
val chunk = neighbours[offset] ?: continue
|
||||
|
||||
val inChunk = now.inChunkPosition
|
||||
|
||||
|
@ -30,7 +30,7 @@ import de.bixilon.minosoft.data.registries.blocks.types.properties.offset.Offset
|
||||
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
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours
|
||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbourArray
|
||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||
import de.bixilon.minosoft.data.world.positions.InChunkPosition
|
||||
@ -59,7 +59,7 @@ class SolidSectionMesher(
|
||||
profile.light::ambientOcclusion.observe(this, true) { this.ambientOcclusion = it }
|
||||
}
|
||||
|
||||
fun mesh(chunkPosition: ChunkPosition, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbourChunks: Array<Chunk>, neighbours: Array<ChunkSection?>, mesh: ChunkMeshes) {
|
||||
fun mesh(chunkPosition: ChunkPosition, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbourChunks: ChunkNeighbourArray, neighbours: Array<ChunkSection?>, mesh: ChunkMeshes) {
|
||||
val random = if (profile.antiMoirePattern) Random(0L) else null
|
||||
|
||||
|
||||
@ -188,13 +188,13 @@ class SolidSectionMesher(
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun setZ(neighbourBlocks: Array<BlockState?>, position: InSectionPosition, neighbours: Array<ChunkSection?>, light: ByteArray, neighbourChunks: Array<Chunk>, section: ChunkSection, chunk: Chunk) {
|
||||
private inline fun setZ(neighbourBlocks: Array<BlockState?>, position: InSectionPosition, neighbours: Array<ChunkSection?>, light: ByteArray, neighbourChunks: ChunkNeighbourArray, section: ChunkSection, chunk: Chunk) {
|
||||
if (position.z == 0) {
|
||||
setNeighbour(neighbourBlocks, position.with(z = ProtocolDefinition.SECTION_MAX_Z), light, neighbours[O_NORTH], neighbourChunks[ChunkNeighbours.NORTH], O_NORTH)
|
||||
setNeighbour(neighbourBlocks, position.with(z = ProtocolDefinition.SECTION_MAX_Z), light, neighbours[O_NORTH], neighbourChunks[Directions.NORTH]!!, O_NORTH) // TODO: bad assert
|
||||
setNeighbour(neighbourBlocks, position.plusZ(), light, section, chunk, O_SOUTH)
|
||||
} else if (position.z == ProtocolDefinition.SECTION_MAX_Z) {
|
||||
setNeighbour(neighbourBlocks, position.minusZ(), light, section, chunk, O_NORTH)
|
||||
setNeighbour(neighbourBlocks, position.with(z = 0), light, neighbours[O_SOUTH], neighbourChunks[ChunkNeighbours.SOUTH], O_SOUTH)
|
||||
setNeighbour(neighbourBlocks, position.with(z = 0), light, neighbours[O_SOUTH], neighbourChunks[Directions.SOUTH]!!, O_SOUTH)// TODO: bad assert
|
||||
} else {
|
||||
setNeighbour(neighbourBlocks, position.minusZ(), light, section, chunk, O_NORTH)
|
||||
setNeighbour(neighbourBlocks, position.plusZ(), light, section, chunk, O_SOUTH)
|
||||
@ -202,12 +202,12 @@ class SolidSectionMesher(
|
||||
}
|
||||
|
||||
|
||||
private inline fun setX(neighbourBlocks: Array<BlockState?>, position: InSectionPosition, neighbours: Array<ChunkSection?>, light: ByteArray, neighbourChunks: Array<Chunk>, section: ChunkSection, chunk: Chunk) {
|
||||
private inline fun setX(neighbourBlocks: Array<BlockState?>, position: InSectionPosition, neighbours: Array<ChunkSection?>, light: ByteArray, neighbourChunks: ChunkNeighbourArray, section: ChunkSection, chunk: Chunk) {
|
||||
if (position.x == 0) {
|
||||
setNeighbour(neighbourBlocks, position.with(x = ProtocolDefinition.SECTION_MAX_X), light, neighbours[O_WEST], neighbourChunks[ChunkNeighbours.WEST], O_WEST)
|
||||
setNeighbour(neighbourBlocks, position.with(x = ProtocolDefinition.SECTION_MAX_X), light, neighbours[O_WEST], neighbourChunks[Directions.WEST]!!, O_WEST) // TODO: bad assert
|
||||
setNeighbour(neighbourBlocks, position.plusX(), light, section, chunk, O_EAST)
|
||||
} else if (position.x == ProtocolDefinition.SECTION_MAX_X) {
|
||||
setNeighbour(neighbourBlocks, position.with(x = 0), light, neighbours[O_EAST], neighbourChunks[ChunkNeighbours.EAST], O_EAST)
|
||||
setNeighbour(neighbourBlocks, position.with(x = 0), light, neighbours[O_EAST], neighbourChunks[Directions.EAST]!!, O_EAST) // TODO: bad assert
|
||||
setNeighbour(neighbourBlocks, position.minusX(), light, section, chunk, O_WEST)
|
||||
} else {
|
||||
setNeighbour(neighbourBlocks, position.minusX(), light, section, chunk, O_WEST)
|
||||
|
@ -15,6 +15,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play.block.chunk
|
||||
|
||||
import de.bixilon.kutil.cast.CastUtil.unsafeCast
|
||||
import de.bixilon.minosoft.config.StaticConfiguration
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.registries.biomes.Biome
|
||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||
import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
|
||||
@ -24,7 +25,7 @@ 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.neighbours.ChunkNeighbours
|
||||
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
|
||||
import de.bixilon.minosoft.data.world.container.palette.palettes.BlockStatePaletteFactory
|
||||
@ -226,80 +227,18 @@ object ChunkUtil {
|
||||
return XZBiomeArray(biomes)
|
||||
}
|
||||
|
||||
val Array<Chunk?>.fullyLoaded: Boolean
|
||||
get() {
|
||||
for (neighbour in this) {
|
||||
if (neighbour == null) return false
|
||||
if (neighbour.neighbours.complete) {
|
||||
continue
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
fun getChunkNeighbourPositions(chunkPosition: ChunkPosition): Array<ChunkPosition> {
|
||||
return arrayOf(
|
||||
chunkPosition + ChunkNeighbours.OFFSETS[0],
|
||||
chunkPosition + ChunkNeighbours.OFFSETS[1],
|
||||
chunkPosition + ChunkNeighbours.OFFSETS[2],
|
||||
chunkPosition + ChunkNeighbours.OFFSETS[3],
|
||||
chunkPosition + ChunkNeighbours.OFFSETS[4],
|
||||
chunkPosition + ChunkNeighbours.OFFSETS[5],
|
||||
chunkPosition + ChunkNeighbours.OFFSETS[6],
|
||||
chunkPosition + ChunkNeighbours.OFFSETS[7],
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param neighbourChunks: **Fully loaded** direct neighbour chunks
|
||||
*/
|
||||
fun getDirectNeighbours(neighbourChunks: Array<Chunk>, chunk: Chunk, sectionHeight: SectionHeight): Array<ChunkSection?> {
|
||||
fun getDirectNeighbours(neighbourChunks: ChunkNeighbourArray, chunk: Chunk, sectionHeight: SectionHeight): Array<ChunkSection?> {
|
||||
return arrayOf(
|
||||
chunk[sectionHeight - 1],
|
||||
chunk[sectionHeight + 1],
|
||||
neighbourChunks[3][sectionHeight],
|
||||
neighbourChunks[4][sectionHeight],
|
||||
neighbourChunks[1][sectionHeight],
|
||||
neighbourChunks[6][sectionHeight],
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param neighbourChunks: **Fully loaded** direct neighbour chunks
|
||||
*/
|
||||
fun getAllNeighbours(neighbourChunks: Array<Chunk>, chunk: Chunk, sectionHeight: SectionHeight): Array<ChunkSection?> {
|
||||
return arrayOf(
|
||||
neighbourChunks[0][sectionHeight - 1], // 0, (-1 | -1)
|
||||
neighbourChunks[1][sectionHeight - 1], // 1, (-1 | +0)
|
||||
neighbourChunks[2][sectionHeight - 1], // 2, (-1 | +1)
|
||||
neighbourChunks[3][sectionHeight - 1], // 3, (+0 | -1)
|
||||
chunk[sectionHeight - 1], // 4, (+0 | +0)
|
||||
neighbourChunks[4][sectionHeight - 1], // 5, (+0 | +1)
|
||||
neighbourChunks[5][sectionHeight - 1], // 6, (-1 | -1)
|
||||
neighbourChunks[6][sectionHeight - 1], // 7, (-1 | -1)
|
||||
neighbourChunks[7][sectionHeight - 1], // 8, (-1 | -1)
|
||||
|
||||
neighbourChunks[0][sectionHeight + 0], // 9, (-1 | -1)
|
||||
neighbourChunks[1][sectionHeight + 0], // 10, (-1 | +0)
|
||||
neighbourChunks[2][sectionHeight + 0], // 11, (-1 | +1)
|
||||
neighbourChunks[3][sectionHeight + 0], // 12, (+0 | -1)
|
||||
chunk[sectionHeight + 0], // 13, (+0 | +0)
|
||||
neighbourChunks[4][sectionHeight + 0], // 14, (+0 | +1)
|
||||
neighbourChunks[5][sectionHeight + 0], // 15, (+1 | -1)
|
||||
neighbourChunks[6][sectionHeight + 0], // 16, (+1 | +0)
|
||||
neighbourChunks[7][sectionHeight + 0], // 17, (+1 | +1)
|
||||
|
||||
neighbourChunks[0][sectionHeight + 1], // 18, (-1 | -1)
|
||||
neighbourChunks[1][sectionHeight + 1], // 19, (-1 | +0)
|
||||
neighbourChunks[2][sectionHeight + 1], // 20, (-1 | +1)
|
||||
neighbourChunks[3][sectionHeight + 1], // 21, (+0 | -1)
|
||||
chunk[sectionHeight + 1], // 22, (+0 | +0)
|
||||
neighbourChunks[4][sectionHeight + 1], // 23, (+0 | +1)
|
||||
neighbourChunks[5][sectionHeight + 1], // 24, (+1 | -1)
|
||||
neighbourChunks[6][sectionHeight + 1], // 25, (+1 | +0)
|
||||
neighbourChunks[7][sectionHeight + 1], // 26, (+1 | +1)
|
||||
neighbourChunks[Directions.NORTH]!![sectionHeight],
|
||||
neighbourChunks[Directions.SOUTH]!![sectionHeight],
|
||||
neighbourChunks[Directions.WEST]!![sectionHeight],
|
||||
neighbourChunks[Directions.EAST]!![sectionHeight],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@ package de.bixilon.minosoft.protocol.protocol;
|
||||
|
||||
import de.bixilon.minosoft.data.text.formatting.color.ChatColors;
|
||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor;
|
||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -48,8 +47,6 @@ public final class ProtocolDefinition {
|
||||
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;
|
||||
@Deprecated
|
||||
public static final InSectionPosition CHUNK_SECTION_SIZE = new InSectionPosition(SECTION_WIDTH_X, SECTION_HEIGHT_Y, SECTION_WIDTH_Z);
|
||||
|
||||
public static final int CHUNK_MIN_Y = -2048;
|
||||
public static final int CHUNK_MIN_SECTION = CHUNK_MIN_Y / SECTION_HEIGHT_Y;
|
||||
|
@ -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.
|
||||
*
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.registries.shapes.aabb
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3i
|
||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
@ -33,7 +33,7 @@ class AABBIteratorTest {
|
||||
val positions = aabb.positions()
|
||||
assertEquals(1, positions.size)
|
||||
assertTrue(positions.hasNext())
|
||||
assertEquals(Vec3i(0, 0, 0), positions.next())
|
||||
assertEquals(BlockPosition(0, 0, 0), positions.next())
|
||||
assertFalse(positions.hasNext())
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ class AABBIteratorTest {
|
||||
|
||||
val positions = aabb.positions()
|
||||
assertEquals(24, positions.size)
|
||||
val set: MutableSet<Vec3i> = mutableSetOf()
|
||||
val set: MutableSet<BlockPosition> = mutableSetOf()
|
||||
|
||||
for (position in positions) {
|
||||
set += position
|
||||
@ -51,30 +51,30 @@ class AABBIteratorTest {
|
||||
assertEquals(24, set.size)
|
||||
|
||||
assertEquals(setOf(
|
||||
Vec3i(0, 0, 0),
|
||||
Vec3i(0, 0, 1),
|
||||
Vec3i(0, 0, 2),
|
||||
Vec3i(0, 0, 3),
|
||||
Vec3i(0, 1, 0),
|
||||
Vec3i(0, 1, 1),
|
||||
Vec3i(0, 1, 2),
|
||||
Vec3i(0, 1, 3),
|
||||
Vec3i(0, 2, 0),
|
||||
Vec3i(0, 2, 1),
|
||||
Vec3i(0, 2, 2),
|
||||
Vec3i(0, 2, 3),
|
||||
Vec3i(1, 0, 0),
|
||||
Vec3i(1, 0, 1),
|
||||
Vec3i(1, 0, 2),
|
||||
Vec3i(1, 0, 3),
|
||||
Vec3i(1, 1, 0),
|
||||
Vec3i(1, 1, 1),
|
||||
Vec3i(1, 1, 2),
|
||||
Vec3i(1, 1, 3),
|
||||
Vec3i(1, 2, 0),
|
||||
Vec3i(1, 2, 1),
|
||||
Vec3i(1, 2, 2),
|
||||
Vec3i(1, 2, 3),
|
||||
BlockPosition(0, 0, 0),
|
||||
BlockPosition(0, 0, 1),
|
||||
BlockPosition(0, 0, 2),
|
||||
BlockPosition(0, 0, 3),
|
||||
BlockPosition(0, 1, 0),
|
||||
BlockPosition(0, 1, 1),
|
||||
BlockPosition(0, 1, 2),
|
||||
BlockPosition(0, 1, 3),
|
||||
BlockPosition(0, 2, 0),
|
||||
BlockPosition(0, 2, 1),
|
||||
BlockPosition(0, 2, 2),
|
||||
BlockPosition(0, 2, 3),
|
||||
BlockPosition(1, 0, 0),
|
||||
BlockPosition(1, 0, 1),
|
||||
BlockPosition(1, 0, 2),
|
||||
BlockPosition(1, 0, 3),
|
||||
BlockPosition(1, 1, 0),
|
||||
BlockPosition(1, 1, 1),
|
||||
BlockPosition(1, 1, 2),
|
||||
BlockPosition(1, 1, 3),
|
||||
BlockPosition(1, 2, 0),
|
||||
BlockPosition(1, 2, 1),
|
||||
BlockPosition(1, 2, 2),
|
||||
BlockPosition(1, 2, 3),
|
||||
), set)
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ class AABBIteratorTest {
|
||||
val positions = aabb.positions()
|
||||
assertEquals(1, positions.size)
|
||||
assertTrue(positions.hasNext())
|
||||
assertEquals(Vec3i(0, 0, 0), positions.next())
|
||||
assertEquals(BlockPosition(0, 0, 0), positions.next())
|
||||
assertFalse(positions.hasNext())
|
||||
}
|
||||
|
||||
@ -96,9 +96,9 @@ class AABBIteratorTest {
|
||||
val positions = aabb.positions()
|
||||
assertEquals(2, positions.size)
|
||||
assertTrue(positions.hasNext())
|
||||
assertEquals(Vec3i(0, 0, 0), positions.next())
|
||||
assertEquals(BlockPosition(0, 0, 0), positions.next())
|
||||
assertTrue(positions.hasNext())
|
||||
assertEquals(Vec3i(1, 0, 0), positions.next())
|
||||
assertEquals(BlockPosition(1, 0, 0), positions.next())
|
||||
assertFalse(positions.hasNext())
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ class AABBIteratorTest {
|
||||
for (x in -2 until 2) {
|
||||
for (y in -2 until 2) {
|
||||
for (z in -2 until 2) {
|
||||
assertEquals(Vec3i(x, y, z), positions.next())
|
||||
assertEquals(BlockPosition(x, y, z), positions.next())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,100 +22,106 @@ class InChunkPositionTest {
|
||||
|
||||
@Test
|
||||
fun `init correct min`() {
|
||||
val position = InSectionPosition(0, -2048, 0)
|
||||
val position = InChunkPosition(0, -2048, 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `init correct max`() {
|
||||
val position = InSectionPosition(15, 2047, 15)
|
||||
val position = InChunkPosition(15, 2047, 15)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `init badly`() {
|
||||
assertThrows<AssertionError> { InSectionPosition(-1, -5000, -1) }
|
||||
assertThrows<AssertionError> { InChunkPosition(-1, -5000, -1) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct x`() {
|
||||
val position = InSectionPosition(2, 0xF, 0xF)
|
||||
val position = InChunkPosition(2, 0xF, 0xF)
|
||||
assertEquals(position.x, 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct plus x`() {
|
||||
val position = InSectionPosition(2, 0xF, 0xF)
|
||||
val position = InChunkPosition(2, 0xF, 0xF)
|
||||
assertEquals(position.plusX().x, 3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct plus 2 x`() {
|
||||
val position = InSectionPosition(2, 0xF, 0xF)
|
||||
val position = InChunkPosition(2, 0xF, 0xF)
|
||||
assertEquals(position.plusX(2).x, 4)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct minus x`() {
|
||||
val position = InSectionPosition(2, 0xF, 0xF)
|
||||
val position = InChunkPosition(2, 0xF, 0xF)
|
||||
assertEquals(position.minusX().x, 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct y`() {
|
||||
val position = InSectionPosition(0xF, 3, 0xF)
|
||||
val position = InChunkPosition(0xF, 3, 0xF)
|
||||
assertEquals(position.y, 3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct negative y`() {
|
||||
val position = InSectionPosition(0xF, -1000, 0xF)
|
||||
val position = InChunkPosition(0xF, -1000, 0xF)
|
||||
assertEquals(position.y, -1000)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct positive y`() {
|
||||
val position = InSectionPosition(0xF, 1000, 0xF)
|
||||
val position = InChunkPosition(0xF, 1000, 0xF)
|
||||
assertEquals(position.y, 1000)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct plus y`() {
|
||||
val position = InSectionPosition(0xF, 2, 0xF)
|
||||
val position = InChunkPosition(0xF, 2, 0xF)
|
||||
assertEquals(position.plusY().y, 3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct plus 2 y`() {
|
||||
val position = InSectionPosition(0xF, 2, 0xF)
|
||||
val position = InChunkPosition(0xF, 2, 0xF)
|
||||
assertEquals(position.plusY(2).y, 4)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct minus y`() {
|
||||
val position = InSectionPosition(0xF, 2, 0xF)
|
||||
val position = InChunkPosition(0xF, 2, 0xF)
|
||||
assertEquals(position.minusY().y, 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct minus y 2`() {
|
||||
val position = InChunkPosition(0xF, -3, 0xF)
|
||||
assertEquals(position.minusY().y, -4)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct z`() {
|
||||
val position = InSectionPosition(0xF, 0xF, 4)
|
||||
val position = InChunkPosition(0xF, 0xF, 4)
|
||||
assertEquals(position.z, 4)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct plus z`() {
|
||||
val position = InSectionPosition(0xF, 0xF, 2)
|
||||
val position = InChunkPosition(0xF, 0xF, 2)
|
||||
assertEquals(position.plusZ().z, 3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct plus 2 z`() {
|
||||
val position = InSectionPosition(0xF, 0xF, 2)
|
||||
val position = InChunkPosition(0xF, 0xF, 2)
|
||||
assertEquals(position.plusZ(2).z, 4)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `correct minus z`() {
|
||||
val position = InSectionPosition(0xF, 0xF, 2)
|
||||
val position = InChunkPosition(0xF, 0xF, 2)
|
||||
assertEquals(position.minusZ().z, 1)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user