mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 11:54:59 -04:00
Merge branch '1.18' into 'world-renderer'
Support for 1.18 See merge request bixilon/minosoft!28
This commit is contained in:
commit
0dca6587c6
@ -24,9 +24,11 @@ data class DimensionProperties(
|
|||||||
val minY: Int = 0,
|
val minY: Int = 0,
|
||||||
val hasCeiling: Boolean = false,
|
val hasCeiling: Boolean = false,
|
||||||
val ultraWarm: Boolean = false,
|
val ultraWarm: Boolean = false,
|
||||||
val height: Int = 256,
|
@Deprecated("Height does not differ from logical height in 1.18")
|
||||||
|
val dataHeight: Int = 256,
|
||||||
val supports3DBiomes: Boolean = true,
|
val supports3DBiomes: Boolean = true,
|
||||||
) {
|
) {
|
||||||
|
val height = logicalHeight + minY
|
||||||
val lowestSection = if (minY < 0) {
|
val lowestSection = if (minY < 0) {
|
||||||
(minY + 1) / ProtocolDefinition.SECTION_HEIGHT_Y - 1
|
(minY + 1) / ProtocolDefinition.SECTION_HEIGHT_Y - 1
|
||||||
} else {
|
} else {
|
||||||
@ -37,9 +39,9 @@ data class DimensionProperties(
|
|||||||
} else {
|
} else {
|
||||||
height / ProtocolDefinition.SECTION_HEIGHT_Y
|
height / ProtocolDefinition.SECTION_HEIGHT_Y
|
||||||
}
|
}
|
||||||
val sections = highestSection - lowestSection
|
|
||||||
|
|
||||||
val lightLevels = FloatArray(16)
|
val lightLevels = FloatArray(16)
|
||||||
|
val sections = highestSection - lowestSection
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val ambientLight = 0.0f // ToDo: 0.1 in nether
|
val ambientLight = 0.0f // ToDo: 0.1 in nether
|
||||||
@ -69,7 +71,7 @@ data class DimensionProperties(
|
|||||||
minY = data["min_y"]?.toInt() ?: 0,
|
minY = data["min_y"]?.toInt() ?: 0,
|
||||||
hasCeiling = data["has_ceiling"]?.toBoolean() ?: false,
|
hasCeiling = data["has_ceiling"]?.toBoolean() ?: false,
|
||||||
ultraWarm = data["ultrawarm"]?.toBoolean() ?: false,
|
ultraWarm = data["ultrawarm"]?.toBoolean() ?: false,
|
||||||
height = data["height"]?.toInt() ?: 256,
|
dataHeight = data["height"]?.toInt() ?: 256,
|
||||||
supports3DBiomes = data["supports_3d_biomes"]?.toBoolean() ?: true,
|
supports3DBiomes = data["supports_3d_biomes"]?.toBoolean() ?: true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ import java.util.*
|
|||||||
|
|
||||||
data class StatusEffect(
|
data class StatusEffect(
|
||||||
override val resourceLocation: ResourceLocation,
|
override val resourceLocation: ResourceLocation,
|
||||||
val category: StatusEffectCategories,
|
val category: StatusEffectCategories?,
|
||||||
override val translationKey: ResourceLocation?,
|
override val translationKey: ResourceLocation?,
|
||||||
val color: RGBColor,
|
val color: RGBColor,
|
||||||
val attributes: Map<ResourceLocation, EntityAttributeModifier>,
|
val attributes: Map<ResourceLocation, EntityAttributeModifier>,
|
||||||
@ -55,7 +55,7 @@ data class StatusEffect(
|
|||||||
|
|
||||||
return StatusEffect(
|
return StatusEffect(
|
||||||
resourceLocation = resourceLocation,
|
resourceLocation = resourceLocation,
|
||||||
category = StatusEffectCategories[data["category"].unsafeCast<String>()],
|
category = data["category"]?.unsafeCast<String>()?.let { return@let StatusEffectCategories[it] },
|
||||||
translationKey = data["translation_key"]?.toResourceLocation(),
|
translationKey = data["translation_key"]?.toResourceLocation(),
|
||||||
color = data["color"].unsafeCast<Int>().asRGBColor(),
|
color = data["color"].unsafeCast<Int>().asRGBColor(),
|
||||||
attributes = attributes.toMap(),
|
attributes = attributes.toMap(),
|
||||||
|
@ -154,7 +154,7 @@ open class Item(
|
|||||||
"SkullItem" -> SkullItem(resourceLocation, registries, data)
|
"SkullItem" -> SkullItem(resourceLocation, registries, data)
|
||||||
"NetherStarItem" -> NetherStarItem(resourceLocation, registries, data)
|
"NetherStarItem" -> NetherStarItem(resourceLocation, registries, data)
|
||||||
"FireworkItem" -> FireworkItem(resourceLocation, registries, data)
|
"FireworkItem" -> FireworkItem(resourceLocation, registries, data)
|
||||||
"FireworkChargeItem" -> FireworkChargeItem(resourceLocation, registries, data)
|
"FireworkChargeItem", "FireworkRocketItem" -> FireworkChargeItem(resourceLocation, registries, data)
|
||||||
"EnchantedBookItem" -> EnchantedBookItem(resourceLocation, registries, data)
|
"EnchantedBookItem" -> EnchantedBookItem(resourceLocation, registries, data)
|
||||||
"ArmorStandItem" -> ArmorStandItem(resourceLocation, registries, data)
|
"ArmorStandItem" -> ArmorStandItem(resourceLocation, registries, data)
|
||||||
"DyeableHorseArmorItem" -> DyeableHorseArmorItem(resourceLocation, registries, data)
|
"DyeableHorseArmorItem" -> DyeableHorseArmorItem(resourceLocation, registries, data)
|
||||||
|
@ -16,7 +16,6 @@ package de.bixilon.minosoft.data.registries.registries.registry
|
|||||||
import de.bixilon.minosoft.util.collections.Clearable
|
import de.bixilon.minosoft.util.collections.Clearable
|
||||||
|
|
||||||
interface AbstractRegistry<T> : Iterable<T>, Clearable, Parentable<AbstractRegistry<T>> {
|
interface AbstractRegistry<T> : Iterable<T>, Clearable, Parentable<AbstractRegistry<T>> {
|
||||||
|
|
||||||
val size: Int
|
val size: Int
|
||||||
|
|
||||||
operator fun get(any: Any?): T?
|
operator fun get(any: Any?): T?
|
||||||
|
@ -17,8 +17,8 @@ import de.bixilon.minosoft.data.registries.blocks.BlockState
|
|||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
||||||
|
|
||||||
class BlockStateRegistry(var flattened: Boolean) : AbstractRegistry<BlockState> {
|
class BlockStateRegistry(var flattened: Boolean) : AbstractRegistry<BlockState?> {
|
||||||
override var parent: AbstractRegistry<BlockState>? = null
|
override var parent: AbstractRegistry<BlockState?>? = null
|
||||||
private val idMap: MutableMap<Int, BlockState> = mutableMapOf()
|
private val idMap: MutableMap<Int, BlockState> = mutableMapOf()
|
||||||
|
|
||||||
override val size: Int
|
override val size: Int
|
||||||
@ -66,7 +66,7 @@ class BlockStateRegistry(var flattened: Boolean) : AbstractRegistry<BlockState>
|
|||||||
return forceGet(id)
|
return forceGet(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getId(value: BlockState): Int {
|
override fun getId(value: BlockState?): Int {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ class Chunk(
|
|||||||
data.blocks?.let {
|
data.blocks?.let {
|
||||||
for ((index, blocks) in it.withIndex()) {
|
for ((index, blocks) in it.withIndex()) {
|
||||||
blocks ?: continue
|
blocks ?: continue
|
||||||
val section = getOrPut(index - lowestSection)
|
val section = getOrPut(index + lowestSection)
|
||||||
section.blocks = blocks
|
section.blocks = blocks
|
||||||
}
|
}
|
||||||
blocksInitialized = true
|
blocksInitialized = true
|
||||||
@ -148,7 +148,7 @@ class Chunk(
|
|||||||
|
|
||||||
var section = sections[sectionIndex]
|
var section = sections[sectionIndex]
|
||||||
if (section == null) {
|
if (section == null) {
|
||||||
section = ChunkSection(connection.registries)
|
section = ChunkSection()
|
||||||
val neighbours: Array<Chunk> = world.getChunkNeighbours(chunkPosition).unsafeCast()
|
val neighbours: Array<Chunk> = world.getChunkNeighbours(chunkPosition).unsafeCast()
|
||||||
val cacheBiomeAccessor = world.cacheBiomeAccessor
|
val cacheBiomeAccessor = world.cacheBiomeAccessor
|
||||||
if (cacheBiomeAccessor != null && biomesInitialized && neighboursLoaded) {
|
if (cacheBiomeAccessor != null && biomesInitialized && neighboursLoaded) {
|
||||||
|
@ -16,11 +16,11 @@ package de.bixilon.minosoft.data.world
|
|||||||
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
||||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||||
import de.bixilon.minosoft.data.world.biome.source.BiomeSource
|
import de.bixilon.minosoft.data.world.biome.source.BiomeSource
|
||||||
import de.bixilon.minosoft.data.world.container.RegistrySectionDataProvider
|
import de.bixilon.minosoft.data.world.container.SectionDataProvider
|
||||||
import glm_.vec3.Vec3i
|
import glm_.vec3.Vec3i
|
||||||
|
|
||||||
class ChunkData(
|
class ChunkData(
|
||||||
var blocks: Array<RegistrySectionDataProvider<BlockState?>?>? = null,
|
var blocks: Array<SectionDataProvider<BlockState?>?>? = null,
|
||||||
var blockEntities: Map<Vec3i, BlockEntity>? = null,
|
var blockEntities: Map<Vec3i, BlockEntity>? = null,
|
||||||
var biomeSource: BiomeSource? = null,
|
var biomeSource: BiomeSource? = null,
|
||||||
var light: Array<ByteArray?>? = null,
|
var light: Array<ByteArray?>? = null,
|
||||||
|
@ -15,9 +15,7 @@ package de.bixilon.minosoft.data.world
|
|||||||
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
||||||
import de.bixilon.minosoft.data.registries.biomes.Biome
|
import de.bixilon.minosoft.data.registries.biomes.Biome
|
||||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
|
||||||
import de.bixilon.minosoft.data.world.biome.accessor.NoiseBiomeAccessor
|
import de.bixilon.minosoft.data.world.biome.accessor.NoiseBiomeAccessor
|
||||||
import de.bixilon.minosoft.data.world.container.RegistrySectionDataProvider
|
|
||||||
import de.bixilon.minosoft.data.world.container.SectionDataProvider
|
import de.bixilon.minosoft.data.world.container.SectionDataProvider
|
||||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.of
|
import de.bixilon.minosoft.gui.rendering.util.VecUtil.of
|
||||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||||
@ -30,14 +28,12 @@ import glm_.vec3.Vec3i
|
|||||||
* Collection of 16x16x16 blocks
|
* Collection of 16x16x16 blocks
|
||||||
*/
|
*/
|
||||||
class ChunkSection(
|
class ChunkSection(
|
||||||
var blocks: RegistrySectionDataProvider<BlockState?>,
|
var blocks: SectionDataProvider<BlockState?> = SectionDataProvider(checkSize = true),
|
||||||
var biomes: RegistrySectionDataProvider<Biome>,
|
var biomes: SectionDataProvider<Biome> = SectionDataProvider(checkSize = false),
|
||||||
var blockEntities: SectionDataProvider<BlockEntity?>,
|
var blockEntities: SectionDataProvider<BlockEntity?> = SectionDataProvider(checkSize = false),
|
||||||
var light: ByteArray, // packed (skyLight: 0xF0, blockLight: 0x0F)
|
var light: ByteArray = ByteArray(ProtocolDefinition.BLOCKS_PER_SECTION), // packed (skyLight: 0xF0, blockLight: 0x0F)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
constructor(registries: Registries) : this(RegistrySectionDataProvider<BlockState?>(registries.blockStateRegistry.unsafeCast(), checkSize = true), RegistrySectionDataProvider(registries.biomeRegistry, checkSize = false), SectionDataProvider(checkSize = false), ByteArray(ProtocolDefinition.BLOCKS_PER_SECTION))
|
|
||||||
|
|
||||||
fun tick(connection: PlayConnection, chunkPosition: Vec2i, sectionHeight: Int) {
|
fun tick(connection: PlayConnection, chunkPosition: Vec2i, sectionHeight: Int) {
|
||||||
if (blockEntities.isEmpty) {
|
if (blockEntities.isEmpty) {
|
||||||
return
|
return
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.registries.biomes.Biome
|
||||||
|
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight
|
||||||
|
|
||||||
|
class PalettedBiomeArray(
|
||||||
|
private val containers: Array<Array<Biome>?>,
|
||||||
|
private val lowestSection: Int,
|
||||||
|
val edgeBits: Int,
|
||||||
|
) : BiomeSource {
|
||||||
|
private val mask = (1 shl edgeBits) - 1
|
||||||
|
|
||||||
|
override fun getBiome(x: Int, y: Int, z: Int): Biome? {
|
||||||
|
return containers.getOrNull(y.sectionHeight - lowestSection)?.get(((((y.sectionHeight and mask) shl edgeBits) or (z and mask)) shl edgeBits) or (x and mask))
|
||||||
|
}
|
||||||
|
}
|
@ -15,14 +15,15 @@ package de.bixilon.minosoft.data.world.container
|
|||||||
|
|
||||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY
|
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
|
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
||||||
import de.bixilon.minosoft.util.ReadWriteLock
|
import de.bixilon.minosoft.util.ReadWriteLock
|
||||||
import glm_.vec3.Vec3i
|
import glm_.vec3.Vec3i
|
||||||
|
|
||||||
open class SectionDataProvider<T>(
|
class SectionDataProvider<T>(
|
||||||
data: Array<Any?>? = null,
|
data: Array<T>? = null,
|
||||||
val checkSize: Boolean = false,
|
val checkSize: Boolean = false,
|
||||||
) : Iterable<T> {
|
) : Iterable<T> {
|
||||||
protected var data = data
|
protected var data: Array<Any?>? = data?.unsafeCast()
|
||||||
private set
|
private set
|
||||||
protected val lock = ReadWriteLock() // lock while reading (blocks writing)
|
protected val lock = ReadWriteLock() // lock while reading (blocks writing)
|
||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
@ -191,9 +192,9 @@ open class SectionDataProvider<T>(
|
|||||||
unlock()
|
unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun copy(): SectionDataProvider<T> {
|
fun copy(): SectionDataProvider<T> {
|
||||||
acquire()
|
acquire()
|
||||||
val clone = SectionDataProvider<T>(data?.clone())
|
val clone = SectionDataProvider<T>(data?.clone()?.unsafeCast())
|
||||||
release()
|
release()
|
||||||
|
|
||||||
return clone
|
return clone
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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.container.palette
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.world.container.palette.data.PaletteData
|
||||||
|
import de.bixilon.minosoft.data.world.container.palette.palettes.Palette
|
||||||
|
|
||||||
|
class PalettedContainer<T>(
|
||||||
|
private val edgeBits: Int,
|
||||||
|
val palette: Palette<T>,
|
||||||
|
val data: PaletteData,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun get(x: Int, y: Int, z: Int): T {
|
||||||
|
return palette.get(data.get((((y shl edgeBits) or z) shl edgeBits) or x))
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified V : T> unpack(): Array<V> {
|
||||||
|
val array: Array<V?> = arrayOfNulls(data.size)
|
||||||
|
for (i in array.indices) {
|
||||||
|
array[i] = palette.get(data.get(i)) as V
|
||||||
|
}
|
||||||
|
return array as Array<V>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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.container.palette
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.registries.registries.registry.AbstractRegistry
|
||||||
|
import de.bixilon.minosoft.data.world.container.palette.data.PaletteData
|
||||||
|
import de.bixilon.minosoft.data.world.container.palette.palettes.PaletteFactory
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
|
|
||||||
|
object PalettedContainerReader {
|
||||||
|
|
||||||
|
fun <T> read(buffer: PlayInByteBuffer, registry: AbstractRegistry<T>, paletteFactory: PaletteFactory): PalettedContainer<T> {
|
||||||
|
val bits = buffer.readUnsignedByte()
|
||||||
|
|
||||||
|
val palette = paletteFactory.createPalette(registry, bits)
|
||||||
|
palette.read(buffer)
|
||||||
|
|
||||||
|
val paletteData = PaletteData.create(buffer.versionId, palette.bits, paletteFactory.containerSize)
|
||||||
|
paletteData.read(buffer)
|
||||||
|
|
||||||
|
return PalettedContainer(paletteFactory.edgeBits, palette, paletteData)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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.container.palette.data
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_1_16
|
||||||
|
|
||||||
|
class ArrayPaletteData(
|
||||||
|
val versionId: Int,
|
||||||
|
val elementBits: Int,
|
||||||
|
override val size: Int,
|
||||||
|
) : PaletteData {
|
||||||
|
init {
|
||||||
|
check(elementBits in 0..32)
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var data: LongArray
|
||||||
|
|
||||||
|
|
||||||
|
override fun read(buffer: PlayInByteBuffer) {
|
||||||
|
data = buffer.readLongArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
override operator fun get(index: Int): Int {
|
||||||
|
val individualValueMask = (1 shl elementBits) - 1
|
||||||
|
|
||||||
|
var blockId: Long = if (versionId < V_1_16) { // ToDo: When did this changed? is just a guess
|
||||||
|
val startLong = index * elementBits / Long.SIZE_BITS
|
||||||
|
val startOffset = index * elementBits % Long.SIZE_BITS
|
||||||
|
val endLong = ((index + 1) * elementBits - 1) / Long.SIZE_BITS
|
||||||
|
|
||||||
|
if (startLong == endLong) {
|
||||||
|
data[startLong] ushr startOffset
|
||||||
|
} else {
|
||||||
|
val endOffset = Long.SIZE_BITS - startOffset
|
||||||
|
data[startLong] ushr startOffset or (data[endLong] shl endOffset)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val startLong = index / (Long.SIZE_BITS / elementBits)
|
||||||
|
val startOffset = index % (Long.SIZE_BITS / elementBits) * elementBits
|
||||||
|
data[startLong] ushr startOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
blockId = blockId and individualValueMask.toLong()
|
||||||
|
|
||||||
|
return blockId.toInt()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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.container.palette.data
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
|
|
||||||
|
class EmptyPaletteData(override val size: Int) : PaletteData {
|
||||||
|
|
||||||
|
override fun get(index: Int): Int {
|
||||||
|
if (index in 0 until size) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
throw IndexOutOfBoundsException("Index $index > $size")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(buffer: PlayInByteBuffer) {
|
||||||
|
check(buffer.readVarInt() == 0) { "No data expected!" }
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2020 Moritz Zwerger
|
* 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 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.
|
||||||
*
|
*
|
||||||
@ -10,25 +10,24 @@
|
|||||||
*
|
*
|
||||||
* 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.palette
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
package de.bixilon.minosoft.data.world.container.palette.data
|
||||||
|
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
|
|
||||||
interface Palette {
|
interface PaletteData {
|
||||||
|
val size: Int
|
||||||
|
|
||||||
fun blockById(id: Int): BlockState?
|
fun get(index: Int): Int
|
||||||
|
|
||||||
val bitsPerBlock: Int
|
fun read(buffer: PlayInByteBuffer)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun choosePalette(bitsPerBlock: Int, buffer: PlayInByteBuffer): Palette {
|
fun create(versionId: Int, bits: Int, size: Int): PaletteData {
|
||||||
if (bitsPerBlock <= 4) {
|
return when (bits) {
|
||||||
return IndirectPalette(4, buffer)
|
0 -> EmptyPaletteData(size)
|
||||||
} else if (bitsPerBlock <= 8) {
|
else -> ArrayPaletteData(versionId, bits, size)
|
||||||
return IndirectPalette(bitsPerBlock, buffer)
|
|
||||||
}
|
}
|
||||||
return DirectPalette(buffer)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,34 +11,23 @@
|
|||||||
* 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.container
|
package de.bixilon.minosoft.data.world.container.palette.palettes
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.registries.registries.registry.AbstractRegistry
|
import de.bixilon.minosoft.data.registries.registries.registry.AbstractRegistry
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
|
|
||||||
class RegistrySectionDataProvider<T>(
|
class ArrayPalette<T>(private val registry: AbstractRegistry<T>, override val bits: Int) : Palette<T> {
|
||||||
val registry: AbstractRegistry<T>,
|
private var array: Array<Any?> = arrayOfNulls(0)
|
||||||
data: Array<Any?>? = null,
|
|
||||||
checkSize: Boolean = false,
|
override fun read(buffer: PlayInByteBuffer) {
|
||||||
) : SectionDataProvider<T>(data, checkSize = checkSize) {
|
array = arrayOfNulls(buffer.readVarInt())
|
||||||
|
for (i in array.indices) {
|
||||||
|
array[i] = registry[buffer.readVarInt()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun setIdData(ids: IntArray) {
|
override fun get(index: Int): T {
|
||||||
val data: Array<Any?> = arrayOfNulls(ProtocolDefinition.BLOCKS_PER_SECTION)
|
return array[index] as T
|
||||||
|
|
||||||
for ((index, id) in ids.withIndex()) {
|
|
||||||
data[index] = registry[id]
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(data as Array<T>)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun copy(): RegistrySectionDataProvider<T> {
|
|
||||||
acquire()
|
|
||||||
val clone = RegistrySectionDataProvider(registry, data?.clone())
|
|
||||||
release()
|
|
||||||
|
|
||||||
return clone
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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.container.palette.palettes
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.registries.registries.registry.AbstractRegistry
|
||||||
|
|
||||||
|
object BiomePaletteFactory : PaletteFactory {
|
||||||
|
override val edgeBits = 2
|
||||||
|
|
||||||
|
override fun <T : Any?> createPalette(registry: AbstractRegistry<T>, bits: Int): Palette<T> {
|
||||||
|
return when (bits) {
|
||||||
|
0 -> SingularPalette(registry)
|
||||||
|
1, 2, 3 -> ArrayPalette(registry, bits)
|
||||||
|
else -> RegistryPalette(registry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.container.palette.palettes
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.registries.registries.registry.AbstractRegistry
|
||||||
|
|
||||||
|
object BlockStatePaletteFactory : PaletteFactory {
|
||||||
|
override val edgeBits = 4
|
||||||
|
|
||||||
|
override fun <T : Any?> createPalette(registry: AbstractRegistry<T>, bits: Int): Palette<T> {
|
||||||
|
return when (bits) {
|
||||||
|
0 -> SingularPalette(registry)
|
||||||
|
1, 2, 3, 4 -> ArrayPalette(registry, 4)
|
||||||
|
5, 6, 7, 8 -> ArrayPalette(registry, bits)
|
||||||
|
else -> RegistryPalette(registry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* 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.container.palette.palettes
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
|
|
||||||
|
interface Palette<T> {
|
||||||
|
val bits: Int
|
||||||
|
|
||||||
|
fun read(buffer: PlayInByteBuffer)
|
||||||
|
|
||||||
|
fun get(index: Int): T
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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.container.palette.palettes
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.registries.registries.registry.AbstractRegistry
|
||||||
|
|
||||||
|
interface PaletteFactory {
|
||||||
|
val edgeBits: Int
|
||||||
|
val containerSize: Int
|
||||||
|
get() = 1 shl (edgeBits * 3)
|
||||||
|
|
||||||
|
fun <T> createPalette(registry: AbstractRegistry<T>, bits: Int): Palette<T>
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.container.palette.palettes
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.registries.registries.registry.AbstractRegistry
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
|
import de.bixilon.minosoft.util.MMath
|
||||||
|
|
||||||
|
class RegistryPalette<T>(private val registry: AbstractRegistry<T>) : Palette<T> {
|
||||||
|
override val bits = MMath.ceilLog2(registry.size)
|
||||||
|
|
||||||
|
override fun read(buffer: PlayInByteBuffer) {}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun get(index: Int): T {
|
||||||
|
return registry[index] as T
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.container.palette.palettes
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.registries.registries.registry.AbstractRegistry
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
|
|
||||||
|
class SingularPalette<T>(private val registry: AbstractRegistry<T>) : Palette<T> {
|
||||||
|
override val bits: Int = 0
|
||||||
|
var item: T? = null
|
||||||
|
private set
|
||||||
|
|
||||||
|
override fun read(buffer: PlayInByteBuffer) {
|
||||||
|
item = registry[buffer.readVarInt()]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun get(index: Int): T {
|
||||||
|
return item as T
|
||||||
|
}
|
||||||
|
}
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Minosoft
|
|
||||||
* Copyright (C) 2020 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.palette
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
|
||||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
|
|
||||||
import kotlin.math.ceil
|
|
||||||
import kotlin.math.ln
|
|
||||||
|
|
||||||
class DirectPalette(buffer: PlayInByteBuffer) : Palette {
|
|
||||||
private var connection: PlayConnection = buffer.connection
|
|
||||||
|
|
||||||
init {
|
|
||||||
if (buffer.versionId < ProtocolVersions.V_17W47A) {
|
|
||||||
buffer.readVarInt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun blockById(id: Int): BlockState? {
|
|
||||||
return connection.registries.blockStateRegistry[id]
|
|
||||||
}
|
|
||||||
|
|
||||||
override val bitsPerBlock: Int
|
|
||||||
get() {
|
|
||||||
if (this.connection.version.versionId < ProtocolVersions.V_18W10D) {
|
|
||||||
return 13
|
|
||||||
}
|
|
||||||
return ceil(ln(connection.registries.blockStateRegistry.size.toDouble()) / ln(2.0)).toInt()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Minosoft
|
|
||||||
* Copyright (C) 2020 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.palette
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.config.StaticConfiguration
|
|
||||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
|
||||||
import de.bixilon.minosoft.util.logging.Log
|
|
||||||
|
|
||||||
class IndirectPalette(
|
|
||||||
override val bitsPerBlock: Int,
|
|
||||||
buffer: PlayInByteBuffer,
|
|
||||||
) : Palette {
|
|
||||||
private val connection = buffer.connection
|
|
||||||
private var palette = buffer.readVarIntArray()
|
|
||||||
|
|
||||||
override fun blockById(id: Int): BlockState? {
|
|
||||||
var blockId = id
|
|
||||||
if (blockId < palette.size) {
|
|
||||||
blockId = palette[blockId]
|
|
||||||
}
|
|
||||||
val block = connection.registries.blockStateRegistry[blockId]
|
|
||||||
|
|
||||||
if (StaticConfiguration.DEBUG_MODE && block == null && blockId != ProtocolDefinition.AIR_BLOCK_ID) {
|
|
||||||
val blockName: String = if (connection.version.isFlattened()) {
|
|
||||||
blockId.toString()
|
|
||||||
} else {
|
|
||||||
"${blockId shr 4}:${blockId and 0x0F} ($blockId)"
|
|
||||||
}
|
|
||||||
Log.warn("Server sent unknown block: $blockName")
|
|
||||||
}
|
|
||||||
return block
|
|
||||||
}
|
|
||||||
}
|
|
@ -232,6 +232,7 @@ class AudioPlayer(
|
|||||||
Log.log(LogMessageType.AUDIO_LOADING, LogLevels.INFO) { "Unloaded OpenAL!" }
|
Log.log(LogMessageType.AUDIO_LOADING, LogLevels.INFO) { "Unloaded OpenAL!" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Refactoring needed")
|
||||||
private fun loadSounds() {
|
private fun loadSounds() {
|
||||||
Log.log(LogMessageType.AUDIO_LOADING, LogLevels.VERBOSE) { "Loading sounds.json" }
|
Log.log(LogMessageType.AUDIO_LOADING, LogLevels.VERBOSE) { "Loading sounds.json" }
|
||||||
val data = connection.assetsManager.readJsonAsset(SOUNDS_INDEX_FILE)
|
val data = connection.assetsManager.readJsonAsset(SOUNDS_INDEX_FILE)
|
||||||
|
@ -24,7 +24,6 @@ import de.bixilon.minosoft.gui.rendering.system.base.shader.Shader
|
|||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureManager
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureManager
|
||||||
import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct
|
import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
import org.lwjgl.system.MemoryUtil.memAllocFloat
|
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.nio.FloatBuffer
|
import java.nio.FloatBuffer
|
||||||
|
|
||||||
@ -88,9 +87,9 @@ interface RenderSystem {
|
|||||||
|
|
||||||
fun createShader(resourceLocation: ResourceLocation): Shader
|
fun createShader(resourceLocation: ResourceLocation): Shader
|
||||||
|
|
||||||
fun createVertexBuffer(structure: MeshStruct, data: FloatBuffer, primitiveType: PrimitiveTypes = PrimitiveTypes.TRIANGLE): FloatVertexBuffer
|
fun createVertexBuffer(structure: MeshStruct, data: FloatBuffer, primitiveType: PrimitiveTypes = preferredPrimitiveType): FloatVertexBuffer
|
||||||
fun createIntUniformBuffer(bindingIndex: Int = 0, data: IntArray = IntArray(0)): IntUniformBuffer
|
fun createIntUniformBuffer(bindingIndex: Int = 0, data: IntArray = IntArray(0)): IntUniformBuffer
|
||||||
fun createFloatUniformBuffer(bindingIndex: Int = 0, data: FloatBuffer = memAllocFloat(0)): FloatUniformBuffer
|
fun createFloatUniformBuffer(bindingIndex: Int = 0, data: FloatBuffer): FloatUniformBuffer
|
||||||
|
|
||||||
fun createTextureManager(): TextureManager
|
fun createTextureManager(): TextureManager
|
||||||
|
|
||||||
|
@ -2,15 +2,13 @@ package de.bixilon.minosoft.gui.rendering.system.base.phases
|
|||||||
|
|
||||||
import de.bixilon.minosoft.gui.rendering.Renderer
|
import de.bixilon.minosoft.gui.rendering.Renderer
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.BlendingFunctions
|
import de.bixilon.minosoft.gui.rendering.system.base.BlendingFunctions
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.RenderingCapabilities
|
|
||||||
|
|
||||||
interface TranslucentDrawable : Renderer {
|
interface TranslucentDrawable : Renderer {
|
||||||
val skipTranslucent: Boolean
|
val skipTranslucent: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
|
|
||||||
fun setupTranslucent() {
|
fun setupTranslucent() {
|
||||||
renderSystem.reset(blending = true) // ToDo: This is just a translucent workaround
|
renderSystem.reset(blending = true)
|
||||||
renderSystem.enable(RenderingCapabilities.BLENDING)
|
|
||||||
renderSystem.setBlendFunc(BlendingFunctions.SOURCE_ALPHA, BlendingFunctions.ONE_MINUS_SOURCE_ALPHA, BlendingFunctions.ONE, BlendingFunctions.ZERO)
|
renderSystem.setBlendFunc(BlendingFunctions.SOURCE_ALPHA, BlendingFunctions.ONE_MINUS_SOURCE_ALPHA, BlendingFunctions.ONE, BlendingFunctions.ZERO)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ class ClientSettingsC2SP(
|
|||||||
val skinParts: Set<SkinParts> = setOf(*SkinParts.VALUES),
|
val skinParts: Set<SkinParts> = setOf(*SkinParts.VALUES),
|
||||||
val mainHand: Hands = Hands.MAIN,
|
val mainHand: Hands = Hands.MAIN,
|
||||||
val disableTextFiltering: Boolean = true,
|
val disableTextFiltering: Boolean = true,
|
||||||
|
val allowListing: Boolean = true,
|
||||||
) : PlayC2SPacket {
|
) : PlayC2SPacket {
|
||||||
|
|
||||||
override fun write(buffer: PlayOutByteBuffer) {
|
override fun write(buffer: PlayOutByteBuffer) {
|
||||||
@ -53,10 +54,13 @@ class ClientSettingsC2SP(
|
|||||||
if (buffer.versionId >= ProtocolVersions.V_21W07A) {
|
if (buffer.versionId >= ProtocolVersions.V_21W07A) {
|
||||||
buffer.writeBoolean(disableTextFiltering)
|
buffer.writeBoolean(disableTextFiltering)
|
||||||
}
|
}
|
||||||
|
if (buffer.versionId >= ProtocolVersions.V_21W44A) {
|
||||||
|
buffer.writeBoolean(allowListing)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun log() {
|
override fun log() {
|
||||||
Log.log(LogMessageType.NETWORK_PACKETS_OUT, LogLevels.VERBOSE) { "Client settings (locale=$locale, renderDistance=$viewDistance)" }
|
Log.log(LogMessageType.NETWORK_PACKETS_OUT, LogLevels.VERBOSE) { "Client settings (locale=$locale, viewDistance=$viewDistance)" }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class SkinParts {
|
enum class SkinParts {
|
||||||
|
@ -18,6 +18,7 @@ import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
|||||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
|
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_21W37A
|
||||||
import de.bixilon.minosoft.util.logging.Log
|
import de.bixilon.minosoft.util.logging.Log
|
||||||
import de.bixilon.minosoft.util.logging.LogLevels
|
import de.bixilon.minosoft.util.logging.LogLevels
|
||||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||||
@ -30,7 +31,11 @@ class BlockEntityMetaDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
} else {
|
} else {
|
||||||
buffer.readBlockPosition()
|
buffer.readBlockPosition()
|
||||||
}
|
}
|
||||||
val type = buffer.connection.registries.blockEntityMetaDataTypeRegistry[buffer.readUnsignedByte()].resourceLocation
|
val type = if (buffer.versionId >= V_21W37A) {
|
||||||
|
buffer.connection.registries.blockEntityTypeRegistry[buffer.readVarInt()].resourceLocation
|
||||||
|
} else {
|
||||||
|
buffer.connection.registries.blockEntityMetaDataTypeRegistry[buffer.readUnsignedByte()].resourceLocation
|
||||||
|
}
|
||||||
val nbt = buffer.readNBT().asCompound()
|
val nbt = buffer.readNBT().asCompound()
|
||||||
|
|
||||||
override fun handle(connection: PlayConnection) {
|
override fun handle(connection: PlayConnection) {
|
||||||
|
@ -20,11 +20,10 @@ import de.bixilon.minosoft.data.world.biome.source.SpatialBiomeArray
|
|||||||
import de.bixilon.minosoft.datafixer.BlockEntityFixer.fix
|
import de.bixilon.minosoft.datafixer.BlockEntityFixer.fix
|
||||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.of
|
import de.bixilon.minosoft.gui.rendering.util.VecUtil.of
|
||||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY
|
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY
|
||||||
import de.bixilon.minosoft.modding.event.events.ChunkDataChangeEvent
|
|
||||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
|
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*
|
||||||
import de.bixilon.minosoft.util.KUtil.toInt
|
import de.bixilon.minosoft.util.KUtil.toInt
|
||||||
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
||||||
import de.bixilon.minosoft.util.Util
|
import de.bixilon.minosoft.util.Util
|
||||||
@ -49,16 +48,16 @@ class ChunkDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
val dimension = buffer.connection.world.dimension!!
|
val dimension = buffer.connection.world.dimension!!
|
||||||
chunkPosition = Vec2i(buffer.readInt(), buffer.readInt())
|
chunkPosition = buffer.readChunkPosition()
|
||||||
if (buffer.versionId < ProtocolVersions.V_20W45A) {
|
if (buffer.versionId < V_20W45A) {
|
||||||
isFullChunk = !buffer.readBoolean()
|
isFullChunk = !buffer.readBoolean()
|
||||||
}
|
}
|
||||||
if (buffer.versionId < ProtocolVersions.V_14W26A) {
|
if (buffer.versionId < V_14W26A) { // ToDo
|
||||||
val sectionBitMask = BitSet.valueOf(buffer.readByteArray(2))
|
val sectionBitMask = BitSet.valueOf(buffer.readByteArray(2))
|
||||||
val addBitMask = BitSet.valueOf(buffer.readByteArray(2))
|
val addBitMask = BitSet.valueOf(buffer.readByteArray(2))
|
||||||
|
|
||||||
// decompress chunk data
|
// decompress chunk data
|
||||||
val decompressed: PlayInByteBuffer = if (buffer.versionId < ProtocolVersions.V_14W28A) {
|
val decompressed: PlayInByteBuffer = if (buffer.versionId < V_14W28A) {
|
||||||
Util.decompress(buffer.readByteArray(buffer.readInt()), buffer.connection)
|
Util.decompress(buffer.readByteArray(buffer.readInt()), buffer.connection)
|
||||||
} else {
|
} else {
|
||||||
buffer
|
buffer
|
||||||
@ -70,56 +69,78 @@ class ChunkDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
this.chunkData.replace(chunkData)
|
this.chunkData.replace(chunkData)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (buffer.versionId >= ProtocolVersions.V_1_16_PRE7 && buffer.versionId < ProtocolVersions.V_1_16_2_PRE2) {
|
if (buffer.versionId in V_1_16_PRE7 until V_1_16_2_PRE2) {
|
||||||
buffer.readBoolean() // ToDo: ignore old data???
|
buffer.readBoolean() // ToDo: ignore old data???
|
||||||
}
|
}
|
||||||
val sectionBitMask: BitSet = when {
|
val sectionBitMask = when {
|
||||||
buffer.versionId < ProtocolVersions.V_15W34C -> {
|
buffer.versionId < V_15W34C -> BitSet.valueOf(buffer.readByteArray(2))
|
||||||
BitSet.valueOf(buffer.readByteArray(2))
|
buffer.versionId < V_15W36D -> BitSet.valueOf(buffer.readByteArray(4))
|
||||||
}
|
buffer.versionId < V_21W03A -> BitSet.valueOf(longArrayOf(buffer.readVarInt().toLong()))
|
||||||
buffer.versionId < ProtocolVersions.V_15W36D -> {
|
buffer.versionId < V_21W37A -> BitSet.valueOf(buffer.readLongArray())
|
||||||
BitSet.valueOf(buffer.readByteArray(4))
|
else -> null
|
||||||
}
|
|
||||||
buffer.versionId < ProtocolVersions.V_21W03A -> {
|
|
||||||
BitSet.valueOf(longArrayOf(buffer.readVarInt().toLong()))
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
BitSet.valueOf(buffer.readLongArray())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (buffer.versionId >= ProtocolVersions.V_18W44A) {
|
if (buffer.versionId >= V_18W44A) {
|
||||||
heightMap = buffer.readNBT()?.compoundCast()
|
heightMap = buffer.readNBT()?.compoundCast()
|
||||||
}
|
}
|
||||||
if (!isFullChunk) {
|
if (!isFullChunk && buffer.versionId < V_21W37A) {
|
||||||
this.chunkData.biomeSource = SpatialBiomeArray(buffer.readBiomeArray())
|
this.chunkData.biomeSource = SpatialBiomeArray(buffer.readBiomeArray())
|
||||||
}
|
}
|
||||||
val size = buffer.readVarInt()
|
val size = buffer.readVarInt()
|
||||||
val lastPos = buffer.pointer
|
val lastBufferPosition = buffer.pointer
|
||||||
val chunkData = ChunkUtil.readChunkPacket(buffer, dimension, sectionBitMask, null, !isFullChunk, dimension.hasSkyLight)
|
|
||||||
if (chunkData == null) {
|
if (buffer.versionId < V_21W37A) {
|
||||||
unloadChunk = true
|
val chunkData = ChunkUtil.readChunkPacket(buffer, dimension, sectionBitMask!!, null, !isFullChunk, dimension.hasSkyLight)
|
||||||
} else {
|
if (chunkData == null) {
|
||||||
this.chunkData.replace(chunkData)
|
unloadChunk = true
|
||||||
}
|
} else {
|
||||||
// set position of the byte buffer, because of some reasons HyPixel makes some weird stuff and sends way to much 0 bytes. (~ 190k), thanks @pokechu22
|
this.chunkData.replace(chunkData)
|
||||||
buffer.pointer = size + lastPos
|
|
||||||
if (buffer.versionId >= ProtocolVersions.V_1_9_4) {
|
|
||||||
val blockEntities: MutableMap<Vec3i, BlockEntity> = mutableMapOf()
|
|
||||||
val positionOffset = Vec3i.of(chunkPosition, dimension.lowestSection, Vec3i.EMPTY)
|
|
||||||
val blockEntitiesCount = buffer.readVarInt()
|
|
||||||
for (i in 0 until blockEntitiesCount) {
|
|
||||||
val nbt = buffer.readNBT().asCompound()
|
|
||||||
val position = Vec3i(nbt["x"]!!.toInt(), nbt["y"]!!.toInt(), nbt["z"]!!.toInt()) - positionOffset
|
|
||||||
val resourceLocation = ResourceLocation(nbt["id"].unsafeCast()).fix()
|
|
||||||
val type = buffer.connection.registries.blockEntityTypeRegistry[resourceLocation] ?: let {
|
|
||||||
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.WARN) { "Unknown block entity: $resourceLocation" }
|
|
||||||
null
|
|
||||||
} ?: continue
|
|
||||||
val entity = type.build(buffer.connection)
|
|
||||||
entity.updateNBT(nbt)
|
|
||||||
blockEntities[position] = entity
|
|
||||||
}
|
}
|
||||||
this.chunkData.blockEntities = blockEntities
|
} else {
|
||||||
|
this.chunkData.replace(ChunkUtil.readPaletteChunk(buffer, dimension, null, isFullChunk = true, containsSkyLight = false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// set position to expected read positions; the server sometimes sends a bunch of useless zeros (~ 190k), thanks @pokechu22
|
||||||
|
buffer.pointer = size + lastBufferPosition
|
||||||
|
|
||||||
|
// block entities
|
||||||
|
when {
|
||||||
|
buffer.versionId < V_1_9_4 -> {
|
||||||
|
}
|
||||||
|
buffer.versionId < V_21W37A -> {
|
||||||
|
val blockEntities: MutableMap<Vec3i, BlockEntity> = mutableMapOf()
|
||||||
|
val positionOffset = Vec3i.of(chunkPosition, dimension.lowestSection, Vec3i.EMPTY)
|
||||||
|
for (i in 0 until buffer.readVarInt()) {
|
||||||
|
val nbt = buffer.readNBT().asCompound()
|
||||||
|
val position = Vec3i(nbt["x"]!!.toInt(), nbt["y"]!!.toInt(), nbt["z"]!!.toInt()) - positionOffset
|
||||||
|
val resourceLocation = ResourceLocation(nbt["id"].unsafeCast()).fix()
|
||||||
|
val type = buffer.connection.registries.blockEntityTypeRegistry[resourceLocation] ?: let {
|
||||||
|
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.WARN) { "Unknown block entity: $resourceLocation" }
|
||||||
|
null
|
||||||
|
} ?: continue
|
||||||
|
val entity = type.build(buffer.connection)
|
||||||
|
entity.updateNBT(nbt)
|
||||||
|
blockEntities[position] = entity
|
||||||
|
}
|
||||||
|
this.chunkData.blockEntities = blockEntities
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val blockEntities: MutableMap<Vec3i, BlockEntity> = mutableMapOf()
|
||||||
|
|
||||||
|
for (i in 0 until buffer.readVarInt()) {
|
||||||
|
val xz = buffer.readUnsignedByte()
|
||||||
|
val y = buffer.readShort()
|
||||||
|
val type = buffer.connection.registries.blockEntityTypeRegistry[buffer.readVarInt()]
|
||||||
|
val nbt = buffer.readNBT()?.asCompound() ?: continue
|
||||||
|
val entity = type.build(buffer.connection)
|
||||||
|
entity.updateNBT(nbt)
|
||||||
|
blockEntities[Vec3i(xz shr 4, y, xz and 0x0F)] = entity
|
||||||
|
}
|
||||||
|
this.chunkData.blockEntities = blockEntities
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer.versionId >= V_21W37A) {
|
||||||
|
this.chunkData.replace(ChunkLightDataS2CP(buffer) { chunkPosition }.chunkData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,7 +152,6 @@ class ChunkDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
}
|
}
|
||||||
val chunk = connection.world.getOrCreateChunk(chunkPosition)
|
val chunk = connection.world.getOrCreateChunk(chunkPosition)
|
||||||
chunk.setData(chunkData)
|
chunk.setData(chunkData)
|
||||||
connection.fireEvent(ChunkDataChangeEvent(connection, this))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun log() {
|
override fun log() {
|
||||||
|
@ -27,8 +27,8 @@ import de.bixilon.minosoft.util.logging.LogMessageType
|
|||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class ChunkLightDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
class ChunkLightDataS2CP(buffer: PlayInByteBuffer, chunkPositionGetter: () -> Vec2i = { Vec2i(buffer.readVarInt(), buffer.readVarInt()) }) : PlayS2CPacket() {
|
||||||
val chunkPosition: Vec2i = Vec2i(buffer.readVarInt(), buffer.readVarInt())
|
val chunkPosition: Vec2i = chunkPositionGetter()
|
||||||
var trustEdges: Boolean = false
|
var trustEdges: Boolean = false
|
||||||
private set
|
private set
|
||||||
val chunkData: ChunkData
|
val chunkData: ChunkData
|
||||||
|
@ -70,6 +70,8 @@ class JoinGameS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
private set
|
private set
|
||||||
var world: ResourceLocation? = null
|
var world: ResourceLocation? = null
|
||||||
private set
|
private set
|
||||||
|
var simulationDistance: Int = -1
|
||||||
|
private set
|
||||||
|
|
||||||
init {
|
init {
|
||||||
entityId = buffer.readInt()
|
entityId = buffer.readInt()
|
||||||
@ -131,6 +133,9 @@ class JoinGameS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
if (buffer.versionId >= ProtocolVersions.V_19W13A) {
|
if (buffer.versionId >= ProtocolVersions.V_19W13A) {
|
||||||
viewDistance = buffer.readVarInt()
|
viewDistance = buffer.readVarInt()
|
||||||
}
|
}
|
||||||
|
if (buffer.versionId >= ProtocolVersions.V_21W40A) {
|
||||||
|
simulationDistance = buffer.readVarInt()
|
||||||
|
}
|
||||||
if (buffer.versionId >= ProtocolVersions.V_20W20A) {
|
if (buffer.versionId >= ProtocolVersions.V_20W20A) {
|
||||||
buffer.readBoolean() // isDebug
|
buffer.readBoolean() // isDebug
|
||||||
if (buffer.readBoolean()) {
|
if (buffer.readBoolean()) {
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020 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.protocol.packets.s2c.play
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
|
import de.bixilon.minosoft.util.logging.Log
|
||||||
|
import de.bixilon.minosoft.util.logging.LogLevels
|
||||||
|
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||||
|
|
||||||
|
class SimulationDistanceSetS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||||
|
val simulationDistance: Int = buffer.readVarInt()
|
||||||
|
|
||||||
|
override fun log() {
|
||||||
|
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Simulation distance set (viewDistance=$simulationDistance)" }
|
||||||
|
}
|
||||||
|
}
|
@ -163,6 +163,12 @@ open class InByteBuffer {
|
|||||||
return array
|
return array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun readLongArray(target: LongArray, size: Int = readVarInt()) {
|
||||||
|
for (i in 0 until size) {
|
||||||
|
target[i] = readLong()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun readVarLong(): Long {
|
fun readVarLong(): Long {
|
||||||
var byteCount = 0
|
var byteCount = 0
|
||||||
|
@ -275,6 +275,7 @@ class PacketTypes {
|
|||||||
PLAY_ADVANCEMENT_PROGRESS({ TODO() }),
|
PLAY_ADVANCEMENT_PROGRESS({ TODO() }),
|
||||||
PLAY_VIBRATION_SIGNAL({ VibrationSignalS2CP(it) }),
|
PLAY_VIBRATION_SIGNAL({ VibrationSignalS2CP(it) }),
|
||||||
PLAY_PING({ PingS2CP(it) }),
|
PLAY_PING({ PingS2CP(it) }),
|
||||||
|
PLAY_SIMULATION_DISTANCE({ SimulationDistanceSetS2CP(it) }),
|
||||||
;
|
;
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -16,6 +16,19 @@ package de.bixilon.minosoft.protocol.protocol;
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class ProtocolVersions {
|
public class ProtocolVersions {
|
||||||
public static final int
|
public static final int
|
||||||
|
V_1_18_PRE5 = 807,
|
||||||
|
V_1_18_PRE4 = 806,
|
||||||
|
V_1_18_PRE3 = 805,
|
||||||
|
V_1_18_PRE2 = 804,
|
||||||
|
V_1_18_PRE1 = 803,
|
||||||
|
V_21W44A = 802,
|
||||||
|
V_21W43A = 801,
|
||||||
|
V_21W42A = 800,
|
||||||
|
V_21W41A = 799,
|
||||||
|
V_21W40A = 798,
|
||||||
|
V_21W39A = 797,
|
||||||
|
V_21W38A = 796,
|
||||||
|
V_21W37A = 795,
|
||||||
V_1_17_1 = 794,
|
V_1_17_1 = 794,
|
||||||
V_1_17_1_RC2 = 793,
|
V_1_17_1_RC2 = 793,
|
||||||
V_1_17_1_RC1 = 792,
|
V_1_17_1_RC1 = 792,
|
||||||
|
@ -15,9 +15,12 @@ package de.bixilon.minosoft.util
|
|||||||
|
|
||||||
import de.bixilon.minosoft.util.KUtil.decide
|
import de.bixilon.minosoft.util.KUtil.decide
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
|
import kotlin.math.ceil
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
|
import kotlin.math.ln
|
||||||
|
|
||||||
object MMath {
|
object MMath {
|
||||||
|
private const val LN_2 = 0.69314718056 // ln(2.0)
|
||||||
|
|
||||||
fun clamp(value: Vec2i, min: Vec2i, max: Vec2i): Vec2i {
|
fun clamp(value: Vec2i, min: Vec2i, max: Vec2i): Vec2i {
|
||||||
value.x = clamp(value.x, min.x, max.x)
|
value.x = clamp(value.x, min.x, max.x)
|
||||||
@ -118,4 +121,8 @@ object MMath {
|
|||||||
val int = this.toInt()
|
val int = this.toInt()
|
||||||
return (this > int).decide(int + 1, int)
|
return (this > int).decide(int + 1, int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ceilLog2(value: Int): Int {
|
||||||
|
return ceil(ln(value.toDouble()) / LN_2).toInt()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,18 @@ import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
|
|||||||
import de.bixilon.minosoft.data.world.Chunk
|
import de.bixilon.minosoft.data.world.Chunk
|
||||||
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.source.PalettedBiomeArray
|
||||||
import de.bixilon.minosoft.data.world.biome.source.XZBiomeArray
|
import de.bixilon.minosoft.data.world.biome.source.XZBiomeArray
|
||||||
import de.bixilon.minosoft.data.world.container.RegistrySectionDataProvider
|
import de.bixilon.minosoft.data.world.container.SectionDataProvider
|
||||||
import de.bixilon.minosoft.data.world.palette.Palette.Companion.choosePalette
|
import de.bixilon.minosoft.data.world.container.palette.PalettedContainer
|
||||||
|
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
|
||||||
|
import de.bixilon.minosoft.data.world.container.palette.palettes.SingularPalette
|
||||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.abs
|
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.abs
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*
|
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*
|
||||||
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -63,13 +67,13 @@ object ChunkUtil {
|
|||||||
|
|
||||||
// parse data
|
// parse data
|
||||||
var arrayPosition = 0
|
var arrayPosition = 0
|
||||||
val sectionBlocks: Array<RegistrySectionDataProvider<BlockState?>?> = arrayOfNulls(dimension.sections)
|
val sectionBlocks: Array<SectionDataProvider<BlockState?>?> = arrayOfNulls(dimension.sections)
|
||||||
for ((sectionIndex, sectionHeight) in (dimension.lowestSection until dimension.highestSection).withIndex()) {
|
for ((sectionIndex, sectionHeight) in (dimension.lowestSection until dimension.highestSection).withIndex()) {
|
||||||
if (!sectionBitMask[sectionIndex]) {
|
if (!sectionBitMask[sectionIndex]) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val blocks = arrayOfNulls<BlockState>(ProtocolDefinition.BLOCKS_PER_SECTION)
|
val blocks: Array<BlockState?> = arrayOfNulls(ProtocolDefinition.BLOCKS_PER_SECTION)
|
||||||
|
|
||||||
for (blockNumber in 0 until ProtocolDefinition.BLOCKS_PER_SECTION) {
|
for (blockNumber in 0 until ProtocolDefinition.BLOCKS_PER_SECTION) {
|
||||||
var blockId = (blockData[arrayPosition].toInt() and 0xFF) shl 4
|
var blockId = (blockData[arrayPosition].toInt() and 0xFF) shl 4
|
||||||
@ -95,7 +99,7 @@ object ChunkUtil {
|
|||||||
|
|
||||||
blocks[blockNumber] = buffer.connection.registries.blockStateRegistry[blockId] ?: continue
|
blocks[blockNumber] = buffer.connection.registries.blockStateRegistry[blockId] ?: continue
|
||||||
}
|
}
|
||||||
sectionBlocks[sectionHeight] = RegistrySectionDataProvider(buffer.connection.registries.blockStateRegistry.unsafeCast(), blocks.unsafeCast(), true)
|
sectionBlocks[sectionHeight] = SectionDataProvider(blocks, true)
|
||||||
}
|
}
|
||||||
chunkData.blocks = sectionBlocks
|
chunkData.blocks = sectionBlocks
|
||||||
return chunkData
|
return chunkData
|
||||||
@ -129,7 +133,7 @@ object ChunkUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var arrayPos = 0
|
var arrayPos = 0
|
||||||
val sectionBlocks: Array<RegistrySectionDataProvider<BlockState?>?> = arrayOfNulls(dimension.sections)
|
val sectionBlocks: Array<SectionDataProvider<BlockState?>?> = arrayOfNulls(dimension.sections)
|
||||||
for ((sectionIndex, sectionHeight) in (dimension.lowestSection until dimension.highestSection).withIndex()) { // max sections per chunks in chunk column
|
for ((sectionIndex, sectionHeight) in (dimension.lowestSection until dimension.highestSection).withIndex()) { // max sections per chunks in chunk column
|
||||||
if (!sectionBitMask[sectionIndex]) {
|
if (!sectionBitMask[sectionIndex]) {
|
||||||
continue
|
continue
|
||||||
@ -140,56 +144,38 @@ object ChunkUtil {
|
|||||||
val block = buffer.connection.registries.blockStateRegistry[blockId] ?: continue
|
val block = buffer.connection.registries.blockStateRegistry[blockId] ?: continue
|
||||||
blocks[blockNumber] = block
|
blocks[blockNumber] = block
|
||||||
}
|
}
|
||||||
sectionBlocks[sectionHeight] = RegistrySectionDataProvider(buffer.connection.registries.blockStateRegistry.unsafeCast(), blocks.unsafeCast(), true)
|
sectionBlocks[sectionHeight] = SectionDataProvider(blocks, true)
|
||||||
}
|
}
|
||||||
chunkData.blocks = sectionBlocks
|
chunkData.blocks = sectionBlocks
|
||||||
return chunkData
|
return chunkData
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readPaletteChunk(buffer: PlayInByteBuffer, dimension: DimensionProperties, sectionBitMask: BitSet, isFullChunk: Boolean, containsSkyLight: Boolean = false): ChunkData {
|
fun readPaletteChunk(buffer: PlayInByteBuffer, dimension: DimensionProperties, sectionBitMask: BitSet?, isFullChunk: Boolean, containsSkyLight: Boolean = false): ChunkData {
|
||||||
val chunkData = ChunkData()
|
val chunkData = ChunkData()
|
||||||
val sectionBlocks: Array<RegistrySectionDataProvider<BlockState?>?> = arrayOfNulls(dimension.sections)
|
val sectionBlocks: Array<SectionDataProvider<BlockState?>?> = arrayOfNulls(dimension.sections)
|
||||||
val light: Array<ByteArray?> = arrayOfNulls(dimension.sections)
|
val light: Array<ByteArray?> = arrayOfNulls(dimension.sections)
|
||||||
var lightReceived = 0
|
var lightReceived = 0
|
||||||
|
val biomes: Array<Array<Biome>?> = arrayOfNulls(dimension.sections)
|
||||||
|
|
||||||
for ((sectionIndex, sectionHeight) in (dimension.lowestSection until sectionBitMask.length()).withIndex()) { // max sections per chunks in chunk column
|
for ((sectionIndex, sectionHeight) in (dimension.lowestSection until (sectionBitMask?.length() ?: dimension.highestSection)).withIndex()) { // max sections per chunks in chunk column
|
||||||
if (!sectionBitMask[sectionIndex]) {
|
if (sectionBitMask?.get(sectionIndex) == false) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (buffer.versionId >= V_18W43A) {
|
if (buffer.versionId >= V_18W43A) {
|
||||||
buffer.readShort() // block count
|
buffer.readShort() // non-air block count
|
||||||
}
|
}
|
||||||
|
|
||||||
val palette = choosePalette(buffer.readUnsignedByte(), buffer)
|
|
||||||
|
|
||||||
val individualValueMask = (1 shl palette.bitsPerBlock) - 1
|
val blockContainer: PalettedContainer<BlockState?> = PalettedContainerReader.read(buffer, buffer.connection.registries.blockStateRegistry, paletteFactory = BlockStatePaletteFactory)
|
||||||
|
|
||||||
val data = buffer.readLongArray()
|
if (blockContainer.palette !is SingularPalette<*> || blockContainer.palette.item != null) {
|
||||||
|
sectionBlocks[sectionHeight - dimension.lowestSection] = SectionDataProvider(blockContainer.unpack(), checkSize = true)
|
||||||
val blocks = arrayOfNulls<BlockState>(ProtocolDefinition.BLOCKS_PER_SECTION)
|
|
||||||
for (blockNumber in 0 until ProtocolDefinition.BLOCKS_PER_SECTION) {
|
|
||||||
var blockId: Long = if (buffer.versionId < V_1_16) { // ToDo: When did this changed? is just a guess
|
|
||||||
val startLong = blockNumber * palette.bitsPerBlock / Long.SIZE_BITS
|
|
||||||
val startOffset = blockNumber * palette.bitsPerBlock % Long.SIZE_BITS
|
|
||||||
val endLong = ((blockNumber + 1) * palette.bitsPerBlock - 1) / Long.SIZE_BITS
|
|
||||||
|
|
||||||
if (startLong == endLong) {
|
|
||||||
data[startLong] ushr startOffset
|
|
||||||
} else {
|
|
||||||
val endOffset = Long.SIZE_BITS - startOffset
|
|
||||||
data[startLong] ushr startOffset or (data[endLong] shl endOffset)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val startLong = blockNumber / (Long.SIZE_BITS / palette.bitsPerBlock)
|
|
||||||
val startOffset = blockNumber % (Long.SIZE_BITS / palette.bitsPerBlock) * palette.bitsPerBlock
|
|
||||||
data[startLong] ushr startOffset
|
|
||||||
}
|
|
||||||
|
|
||||||
blockId = blockId and individualValueMask.toLong()
|
|
||||||
|
|
||||||
val block = palette.blockById(blockId.toInt()) ?: continue
|
|
||||||
blocks[blockNumber] = block
|
|
||||||
}
|
}
|
||||||
|
if (buffer.versionId >= V_21W37A) {
|
||||||
|
val biomeContainer: PalettedContainer<Biome> = PalettedContainerReader.read(buffer, buffer.connection.registries.biomeRegistry, paletteFactory = BiomePaletteFactory)
|
||||||
|
biomes[sectionHeight - dimension.lowestSection] = biomeContainer.unpack()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (buffer.versionId < V_18W43A) {
|
if (buffer.versionId < V_18W43A) {
|
||||||
val blockLight = buffer.readByteArray(ProtocolDefinition.BLOCKS_PER_SECTION / 2)
|
val blockLight = buffer.readByteArray(ProtocolDefinition.BLOCKS_PER_SECTION / 2)
|
||||||
@ -200,14 +186,15 @@ object ChunkUtil {
|
|||||||
light[sectionHeight - dimension.lowestSection] = LightUtil.mergeLight(blockLight, skyLight ?: LightUtil.EMPTY_LIGHT_ARRAY)
|
light[sectionHeight - dimension.lowestSection] = LightUtil.mergeLight(blockLight, skyLight ?: LightUtil.EMPTY_LIGHT_ARRAY)
|
||||||
lightReceived++
|
lightReceived++
|
||||||
}
|
}
|
||||||
sectionBlocks[sectionHeight - dimension.lowestSection] = RegistrySectionDataProvider(buffer.connection.registries.blockStateRegistry.unsafeCast(), blocks.unsafeCast(), true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chunkData.blocks = sectionBlocks
|
chunkData.blocks = sectionBlocks
|
||||||
if (lightReceived > 0) {
|
if (lightReceived > 0) {
|
||||||
chunkData.light = light
|
chunkData.light = light
|
||||||
}
|
}
|
||||||
if (buffer.versionId < V_19W36A && isFullChunk) {
|
if (buffer.versionId >= V_21W37A) {
|
||||||
|
chunkData.biomeSource = PalettedBiomeArray(biomes, dimension.lowestSection, BiomePaletteFactory.edgeBits)
|
||||||
|
} else if (buffer.versionId < V_19W36A && isFullChunk) {
|
||||||
chunkData.biomeSource = readLegacyBiomeArray(buffer)
|
chunkData.biomeSource = readLegacyBiomeArray(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ object LightUtil {
|
|||||||
val EMPTY_LIGHT_ARRAY = ByteArray(ProtocolDefinition.BLOCKS_PER_SECTION / 2)
|
val EMPTY_LIGHT_ARRAY = ByteArray(ProtocolDefinition.BLOCKS_PER_SECTION / 2)
|
||||||
|
|
||||||
fun readLightPacket(buffer: PlayInByteBuffer, skyLightMask: BitSet, blockLightMask: BitSet, dimension: DimensionProperties): ChunkData {
|
fun readLightPacket(buffer: PlayInByteBuffer, skyLightMask: BitSet, blockLightMask: BitSet, dimension: DimensionProperties): ChunkData {
|
||||||
|
// ToDo
|
||||||
val skyLight = if (dimension.hasSkyLight || buffer.versionId > V_1_16) { // ToDo: find out version
|
val skyLight = if (dimension.hasSkyLight || buffer.versionId > V_1_16) { // ToDo: find out version
|
||||||
readLightArray(buffer, skyLightMask, dimension)
|
readLightArray(buffer, skyLightMask, dimension)
|
||||||
} else {
|
} else {
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user