biomes: correct noise biome accessor

This commit is contained in:
Bixilon 2021-03-27 17:47:44 +01:00
parent 56eec8fb73
commit eaca291c96
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
19 changed files with 284 additions and 52 deletions

View File

@ -13,7 +13,7 @@
package de.bixilon.minosoft.data.world package de.bixilon.minosoft.data.world
import de.bixilon.minosoft.data.mappings.blocks.BlockState import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.world.biome.BiomeAccessor import de.bixilon.minosoft.data.world.biome.source.BiomeSource
import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor
import java.util.* import java.util.*
@ -22,13 +22,13 @@ import java.util.*
*/ */
class Chunk( class Chunk(
var sections: MutableMap<Int, ChunkSection>? = null, var sections: MutableMap<Int, ChunkSection>? = null,
var biomeAccessor: BiomeAccessor? = null, var biomeSource: BiomeSource? = null,
var lightAccessor: LightAccessor? = null, var lightAccessor: LightAccessor? = null,
) { ) {
private val lock = Object() private val lock = Object()
val isFullyLoaded: Boolean val isFullyLoaded: Boolean
get() { get() {
return sections != null && biomeAccessor != null && lightAccessor != null return sections != null && biomeSource != null && lightAccessor != null
} }
fun getBlockState(position: InChunkPosition): BlockState? { fun getBlockState(position: InChunkPosition): BlockState? {
@ -59,8 +59,8 @@ class Chunk(
getSectionOrCreate(sectionHeight).setData(chunkSection) getSectionOrCreate(sectionHeight).setData(chunkSection)
} }
} }
data.biomeAccessor?.let { data.biomeSource?.let {
this.biomeAccessor = it this.biomeSource = it
} }
data.lightAccessor?.let { data.lightAccessor?.let {
this.lightAccessor = it this.lightAccessor = it

View File

@ -13,12 +13,12 @@
package de.bixilon.minosoft.data.world package de.bixilon.minosoft.data.world
import de.bixilon.minosoft.data.world.biome.BiomeAccessor import de.bixilon.minosoft.data.world.biome.source.BiomeSource
import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor
data class ChunkData( data class ChunkData(
var blocks: Map<Int, ChunkSection>? = null, var blocks: Map<Int, ChunkSection>? = null,
var biomeAccessor: BiomeAccessor? = null, var biomeSource: BiomeSource? = null,
var lightAccessor: LightAccessor? = null, var lightAccessor: LightAccessor? = null,
) { ) {
@ -26,8 +26,8 @@ data class ChunkData(
data.blocks?.let { data.blocks?.let {
this.blocks = it this.blocks = it
} }
data.biomeAccessor?.let { data.biomeSource?.let {
this.biomeAccessor = it this.biomeSource = it
} }
data.lightAccessor?.let { data.lightAccessor?.let {
this.lightAccessor = it this.lightAccessor = it

View File

@ -46,6 +46,10 @@ data class InChunkPosition(val x: Int, val y: Int, val z: Int) {
return this + direction?.directionVector return this + direction?.directionVector
} }
fun toVec3i(): Vec3i {
return Vec3i(x, y, z)
}
override fun toString(): String { override fun toString(): String {
return "($x $y $z)" return "($x $y $z)"
} }

View File

@ -17,7 +17,10 @@ import de.bixilon.minosoft.data.Difficulties
import de.bixilon.minosoft.data.entities.block.BlockEntityMetaData import de.bixilon.minosoft.data.entities.block.BlockEntityMetaData
import de.bixilon.minosoft.data.entities.entities.Entity import de.bixilon.minosoft.data.entities.entities.Entity
import de.bixilon.minosoft.data.mappings.Dimension import de.bixilon.minosoft.data.mappings.Dimension
import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.mappings.blocks.BlockState import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.world.biome.accessor.BiomeAccessor
import de.bixilon.minosoft.data.world.biome.accessor.NullBiomeAccessor
import de.bixilon.minosoft.data.world.light.WorldLightAccessor import de.bixilon.minosoft.data.world.light.WorldLightAccessor
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
@ -25,7 +28,7 @@ import java.util.concurrent.ConcurrentHashMap
/** /**
* Collection of chunks and more * Collection of chunks and more
*/ */
class World { class World : BiomeAccessor {
val chunks = ConcurrentHashMap<ChunkPosition, Chunk>() val chunks = ConcurrentHashMap<ChunkPosition, Chunk>()
val entityIdMap = HashBiMap.create<Int, Entity>() val entityIdMap = HashBiMap.create<Int, Entity>()
val entityUUIDMap = HashBiMap.create<UUID, Entity>() val entityUUIDMap = HashBiMap.create<UUID, Entity>()
@ -35,6 +38,8 @@ class World {
var difficulty: Difficulties? = null var difficulty: Difficulties? = null
var difficultyLocked = false var difficultyLocked = false
val worldLightAccessor = WorldLightAccessor(this) val worldLightAccessor = WorldLightAccessor(this)
var hashedSeed = 0L
var biomeAccessor: BiomeAccessor = NullBiomeAccessor
fun getBlockState(blockPosition: BlockPosition): BlockState? { fun getBlockState(blockPosition: BlockPosition): BlockState? {
val chunkLocation = blockPosition.getChunkPosition() val chunkLocation = blockPosition.getChunkPosition()
@ -107,4 +112,8 @@ class World {
setBlockEntityData(blockPosition, entityMetaData) setBlockEntityData(blockPosition, entityMetaData)
} }
} }
override fun getBiome(blockPosition: BlockPosition): Biome? {
return biomeAccessor.getBiome(blockPosition)
}
} }

View File

@ -11,12 +11,12 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.data.world.biome package de.bixilon.minosoft.data.world.biome.accessor
import de.bixilon.minosoft.data.mappings.biomes.Biome import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.world.BlockPosition import de.bixilon.minosoft.data.world.BlockPosition
interface BiomeAccessor { interface BiomeAccessor {
fun getBiome(position: BlockPosition, is3d: Boolean = true): Biome? fun getBiome(blockPosition: BlockPosition): Biome?
} }

View File

@ -0,0 +1,26 @@
/*
* Minosoft
* Copyright (C) 2021 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.biome.accessor
import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.world.BlockPosition
import de.bixilon.minosoft.data.world.World
class BlockBiomeAccessor(private val world: World) : BiomeAccessor {
override fun getBiome(blockPosition: BlockPosition): Biome? {
val biomePosition = blockPosition.getInChunkPosition().toVec3i()
return world.getChunk(blockPosition.getChunkPosition())?.biomeSource?.getBiome(biomePosition)
}
}

View File

@ -11,29 +11,22 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.data.world.biome package de.bixilon.minosoft.data.world.biome.accessor
import de.bixilon.minosoft.data.mappings.biomes.Biome import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.world.BlockPosition import de.bixilon.minosoft.data.world.BlockPosition
import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.data.world.biome.noise.FuzzyNoiseBiomeCalculator
class NoiseBiomeAccessor( class NoiseBiomeAccessor(private val world: World) : BiomeAccessor {
private val biomes: Array<Biome>, private val blockBiomeAccessor = BlockBiomeAccessor(world)
) : BiomeAccessor {
override fun getBiome(position: BlockPosition, is3d: Boolean): Biome? { override fun getBiome(blockPosition: BlockPosition): Biome? {
val inChunk = position.getInChunkSectionPosition() val y = if (world.dimension?.supports3DBiomes == true) {
val y = if (is3d) { blockPosition.y
inChunk.y / 4 * 16
} else { } else {
0 0
} }
val index = (y + ((inChunk.z / 4 * 4) + (inChunk.x / 4))) return FuzzyNoiseBiomeCalculator.getBiome(world.hashedSeed, blockPosition.x, y, blockPosition.z, world)
if (index < 0 || index > biomes.size) {
return null
}
return biomes[index]
// ToDo: This value is pseudo randomly generated. It depends on the seed of the world (received in join game).
} }
} }

View File

@ -11,14 +11,14 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.data.world.biome package de.bixilon.minosoft.data.world.biome.accessor
import de.bixilon.minosoft.data.mappings.biomes.Biome import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.world.BlockPosition import de.bixilon.minosoft.data.world.BlockPosition
class DummyBiomeAccessor(private val biome: Biome) : BiomeAccessor { object NullBiomeAccessor : BiomeAccessor {
override fun getBiome(position: BlockPosition, is3d: Boolean): Biome { override fun getBiome(blockPosition: BlockPosition): Biome? {
return biome return null
} }
} }

View File

@ -0,0 +1,104 @@
package de.bixilon.minosoft.data.world.biome.noise
import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.world.ChunkPosition
import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.util.MMath.square
import glm_.vec3.Vec3i
object FuzzyNoiseBiomeCalculator {
fun getBiome(seed: Long, x: Int, y: Int, z: Int, world: World): Biome? {
val m = x - 2
val n = y - 2
val o = z - 2
val p = m shr 2
val q = n shr 2
val r = o shr 2
val d = (m and 0x03) / 4.0
val e = (n and 0x03) / 4.0
val f = (o and 0x03) / 4.0
var s = 0
var g = Double.POSITIVE_INFINITY
fun calculateFraction(a: Int, mask: Int, first: Int, second: Double): Pair<Int, Double> {
(a and mask == 0).let {
return Pair(
if (it) first else first + 1,
if (it) second else second - 1.0
)
}
}
fun checkMask(mask: Int, value: Int): Int {
return if (s and mask == 0) {
value
} else {
value + 1
}
}
for (i in 0 until 8) {
val (u, xFraction) = calculateFraction(i, 0x04, p, d)
val (v, yFraction) = calculateFraction(i, 0x02, q, e)
val (w, zFraction) = calculateFraction(i, 0x01, r, f)
val d3 = calculateFiddle(seed, u, v, w, xFraction, yFraction, zFraction)
if (g > d3) {
s = i
g = d3
}
}
val biomeX = checkMask(0x04, p)
val biomeY = checkMask(0x02, q)
val biomeZ = checkMask(0x01, r)
return world.getChunk(ChunkPosition(biomeX shr 2, biomeZ shr 2))?.biomeSource?.getBiome(Vec3i(biomeX, biomeY, biomeZ))
}
private fun calculateFiddle(seed: Long, x: Int, y: Int, z: Int, xFraction: Double, yFraction: Double, zFraction: Double): Double {
var ret = seed
ret = next(ret, x)
ret = next(ret, y)
ret = next(ret, z)
ret = next(ret, x)
ret = next(ret, y)
ret = next(ret, z)
val xFractionSalt = distribute(ret)
ret = next(ret, seed)
val yFractionSalt = distribute(ret)
ret = next(ret, seed)
val zFractionSalt = distribute(ret)
return square(xFraction + xFractionSalt) + square(yFraction + yFractionSalt) + square(zFraction + zFractionSalt)
}
private fun distribute(seed: Long): Double {
val d = Math.floorMod(seed shr 24, 1024L).toInt() / 1024.0
return (d - 0.5) * 0.9
}
// https://en.wikipedia.org/wiki/Linear_congruential_generator
private fun next(seed: Long): Long {
return seed * (seed * 6364136223846793005L + 1442695040888963407L)
}
private fun next(seed: Long, salt: Int): Long {
return next(seed) + salt
}
private fun next(seed: Long, salt: Long): Long {
return next(seed) + salt
}
}

View File

@ -0,0 +1,22 @@
/*
* Minosoft
* Copyright (C) 2021 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.biome.source
import de.bixilon.minosoft.data.mappings.biomes.Biome
import glm_.vec3.Vec3i
interface BiomeSource {
fun getBiome(position: Vec3i): Biome?
}

View File

@ -11,16 +11,14 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.data.world.biome package de.bixilon.minosoft.data.world.biome.source
import de.bixilon.minosoft.data.mappings.biomes.Biome import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.world.BlockPosition import glm_.vec3.Vec3i
class XZBiomeAccessor( class DummyBiomeSource(private val biome: Biome) : BiomeSource {
private val biomes: Array<Biome>,
) : BiomeAccessor {
override fun getBiome(position: BlockPosition, is3d: Boolean): Biome { override fun getBiome(position: Vec3i): Biome {
return biomes[(position.x and 0x0F) or ((position.z and 0x0F) shl 4)] return biome
} }
} }

View File

@ -0,0 +1,37 @@
/*
* Minosoft
* Copyright (C) 2021 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.biome.source
import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.util.MMath
import glm_.vec3.Vec3i
class SpatialBiomeArray(private val data: Array<Biome>) : BiomeSource {
override fun getBiome(position: Vec3i): Biome {
val index = (MMath.clamp(position.y, 0, Y_BIT_MASK)) shl 2 * X_SECTION_COUNT + X_SECTION_COUNT or
((position.z and X_BIT_MASK) shl X_SECTION_COUNT) or
(position.x and X_BIT_MASK)
return this.data[index]
}
companion object {
private const val X_SECTION_COUNT = 2
private const val Y_SECTION_COUNT = 6
private const val X_BIT_MASK = (1 shl X_SECTION_COUNT) - 1
private const val Y_BIT_MASK = (1 shl Y_SECTION_COUNT) - 1
}
}

View File

@ -0,0 +1,28 @@
/*
* Minosoft
* Copyright (C) 2021 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.biome.source
import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import glm_.vec3.Vec3i
class XZBiomeArray(private val biomes: Array<Biome>) : BiomeSource {
init {
check(biomes.size == ProtocolDefinition.SECTION_WIDTH_X * ProtocolDefinition.SECTION_WIDTH_Z) { "Biome array size does not match the xz block count!" }
}
override fun getBiome(position: Vec3i): Biome {
return biomes[(position.x and 0x0F) or ((position.z and 0x0F) shl 4)]
}
}

View File

@ -206,14 +206,14 @@ class Camera(
headLocation = Position(cameraPosition) headLocation = Position(cameraPosition)
feetLocation = Position(headLocation.x, headLocation.y - PLAYER_HEIGHT, headLocation.z) feetLocation = Position(headLocation.x, headLocation.y - PLAYER_HEIGHT, headLocation.z)
blockPosition = feetLocation.toBlockPosition() blockPosition = feetLocation.toBlockPosition()
currentBiome = connection.player.world.getChunk(blockPosition.getChunkPosition())?.biomeAccessor?.getBiome(blockPosition, connection.player.world.dimension?.supports3DBiomes ?: false) currentBiome = connection.player.world.getBiome(blockPosition)
chunkPosition = blockPosition.getChunkPosition() chunkPosition = blockPosition.getChunkPosition()
sectionHeight = blockPosition.getSectionHeight() sectionHeight = blockPosition.getSectionHeight()
inChunkSectionPosition = blockPosition.getInChunkSectionPosition() inChunkSectionPosition = blockPosition.getInChunkSectionPosition()
// recalculate sky color for current biome // recalculate sky color for current biome
val blockPosition = Position(cameraPosition).toBlockPosition() val blockPosition = Position(cameraPosition).toBlockPosition()
renderWindow.setSkyColor(connection.player.world.getChunk(blockPosition.getChunkPosition())?.biomeAccessor?.getBiome(blockPosition, connection.player.world.dimension?.supports3DBiomes ?: false)?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR) renderWindow.setSkyColor(connection.player.world.getBiome(blockPosition)?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR)
frustum.recalculate() frustum.recalculate()
renderWindow.worldRenderer.recalculateVisibleChunks() renderWindow.worldRenderer.recalculateVisibleChunks()

View File

@ -54,8 +54,6 @@ class WorldRenderer(
queuedChunks.remove(chunkPosition) queuedChunks.remove(chunkPosition)
} }
val chunk = world.getChunk(chunkPosition) ?: error("Chunk in world is null at $chunkPosition?") val chunk = world.getChunk(chunkPosition) ?: error("Chunk in world is null at $chunkPosition?")
val dimensionSupports3dBiomes = connection.player.world.dimension?.supports3DBiomes ?: false
val meshCollection = ChunkMeshCollection() val meshCollection = ChunkMeshCollection()
for ((sectionHeight, section) in sections) { for ((sectionHeight, section) in sections) {
@ -70,7 +68,8 @@ class WorldRenderer(
neighborBlocks[direction.ordinal] = world.getBlockState(blockPosition + direction) neighborBlocks[direction.ordinal] = world.getBlockState(blockPosition + direction)
} }
val biome = chunk.biomeAccessor!!.getBiome(blockPosition, dimensionSupports3dBiomes)
val biome = world.getBiome(blockPosition)
var tintColor: RGBColor? = null var tintColor: RGBColor? = null

View File

@ -17,7 +17,7 @@ import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker
import de.bixilon.minosoft.data.world.BlockPosition import de.bixilon.minosoft.data.world.BlockPosition
import de.bixilon.minosoft.data.world.ChunkData import de.bixilon.minosoft.data.world.ChunkData
import de.bixilon.minosoft.data.world.ChunkPosition import de.bixilon.minosoft.data.world.ChunkPosition
import de.bixilon.minosoft.data.world.biome.NoiseBiomeAccessor import de.bixilon.minosoft.data.world.biome.source.SpatialBiomeArray
import de.bixilon.minosoft.modding.event.events.BlockEntityMetaDataChangeEvent import de.bixilon.minosoft.modding.event.events.BlockEntityMetaDataChangeEvent
import de.bixilon.minosoft.modding.event.events.ChunkDataChangeEvent import de.bixilon.minosoft.modding.event.events.ChunkDataChangeEvent
import de.bixilon.minosoft.protocol.network.Connection import de.bixilon.minosoft.protocol.network.Connection
@ -83,7 +83,7 @@ class PacketChunkData : ClientboundPacket() {
heightMap = buffer.readNBT() as CompoundTag heightMap = buffer.readNBT() as CompoundTag
} }
if (!isFullChunk) { if (!isFullChunk) {
chunkData!!.biomeAccessor = NoiseBiomeAccessor(buffer.readBiomeArray()) chunkData!!.biomeSource = SpatialBiomeArray(buffer.readBiomeArray())
} }
val size = buffer.readVarInt() val size = buffer.readVarInt()
val lastPos = buffer.position val lastPos = buffer.position

View File

@ -19,6 +19,8 @@ import de.bixilon.minosoft.data.LevelTypes
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
import de.bixilon.minosoft.data.mappings.Dimension import de.bixilon.minosoft.data.mappings.Dimension
import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.world.biome.accessor.BlockBiomeAccessor
import de.bixilon.minosoft.data.world.biome.accessor.NoiseBiomeAccessor
import de.bixilon.minosoft.modding.event.events.JoinGameEvent import de.bixilon.minosoft.modding.event.events.JoinGameEvent
import de.bixilon.minosoft.protocol.network.Connection import de.bixilon.minosoft.protocol.network.Connection
import de.bixilon.minosoft.protocol.packets.ClientboundPacket import de.bixilon.minosoft.protocol.packets.ClientboundPacket
@ -142,6 +144,12 @@ class PacketJoinGame : ClientboundPacket() {
val entity = PlayerEntity(connection, entityId, connection.player.playerUUID, null, null, connection.player.playerName, null, null) val entity = PlayerEntity(connection, entityId, connection.player.playerUUID, null, null, connection.player.playerName, null, null)
connection.player.entity = entity connection.player.entity = entity
connection.player.world.addEntity(entity) connection.player.world.addEntity(entity)
connection.player.world.hashedSeed = hashedSeed
connection.player.world.biomeAccessor = if (connection.version.versionId < ProtocolVersions.V_19W36A) {
BlockBiomeAccessor(connection.player.world)
} else {
NoiseBiomeAccessor(connection.player.world)
}
connection.sender.sendChatMessage("I am alive! ~ Minosoft") connection.sender.sendChatMessage("I am alive! ~ Minosoft")
} }

View File

@ -62,4 +62,8 @@ object MMath {
} }
return intValue return intValue
} }
fun square(d: Double): Double {
return d * d
}
} }

View File

@ -18,7 +18,7 @@ import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.mappings.blocks.BlockState import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.world.ChunkData import de.bixilon.minosoft.data.world.ChunkData
import de.bixilon.minosoft.data.world.ChunkSection import de.bixilon.minosoft.data.world.ChunkSection
import de.bixilon.minosoft.data.world.biome.XZBiomeAccessor import de.bixilon.minosoft.data.world.biome.source.XZBiomeArray
import de.bixilon.minosoft.data.world.light.DummyLightAccessor import de.bixilon.minosoft.data.world.light.DummyLightAccessor
import de.bixilon.minosoft.data.world.palette.Palette.Companion.choosePalette import de.bixilon.minosoft.data.world.palette.Palette.Companion.choosePalette
import de.bixilon.minosoft.protocol.protocol.InByteBuffer import de.bixilon.minosoft.protocol.protocol.InByteBuffer
@ -53,7 +53,7 @@ object ChunkUtil {
} }
val addBlockData = buffer.readBytes(addBitMask.cardinality() * (ProtocolDefinition.BLOCKS_PER_SECTION / 2)) val addBlockData = buffer.readBytes(addBitMask.cardinality() * (ProtocolDefinition.BLOCKS_PER_SECTION / 2))
if (isFullChunk) { if (isFullChunk) {
chunkData.biomeAccessor = readLegacyBiomeArray(buffer) chunkData.biomeSource = readLegacyBiomeArray(buffer)
} }
// parse data // parse data
@ -123,7 +123,7 @@ object ChunkUtil {
skyLight = buffer.readBytes(totalHalfEntries) skyLight = buffer.readBytes(totalHalfEntries)
} }
if (isFullChunk) { if (isFullChunk) {
chunkData.biomeAccessor = readLegacyBiomeArray(buffer) chunkData.biomeSource = readLegacyBiomeArray(buffer)
} }
var arrayPos = 0 var arrayPos = 0
@ -200,14 +200,14 @@ object ChunkUtil {
chunkData.blocks = sectionMap chunkData.blocks = sectionMap
if (buffer.versionId < V_19W36A && isFullChunk) { if (buffer.versionId < V_19W36A && isFullChunk) {
chunkData.biomeAccessor = readLegacyBiomeArray(buffer) chunkData.biomeSource = readLegacyBiomeArray(buffer)
} }
return chunkData return chunkData
} }
private fun readLegacyBiomeArray(buffer: InByteBuffer): XZBiomeAccessor { private fun readLegacyBiomeArray(buffer: InByteBuffer): XZBiomeArray {
val biomes: MutableList<Biome> = mutableListOf() val biomes: MutableList<Biome> = mutableListOf()
for (i in 0 until ProtocolDefinition.SECTION_WIDTH_X * ProtocolDefinition.SECTION_WIDTH_Z) { for (i in 0 until ProtocolDefinition.SECTION_WIDTH_X * ProtocolDefinition.SECTION_WIDTH_Z) {
biomes.add(i, buffer.connection.mapping.biomeRegistry.get(if (buffer.versionId < V_15W35A) { biomes.add(i, buffer.connection.mapping.biomeRegistry.get(if (buffer.versionId < V_15W35A) {
@ -216,6 +216,6 @@ object ChunkUtil {
buffer.readInt() buffer.readInt()
})) }))
} }
return XZBiomeAccessor(biomes.toTypedArray()) return XZBiomeArray(biomes.toTypedArray())
} }
} }