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 hasCeiling: 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 height = logicalHeight + minY
|
||||
val lowestSection = if (minY < 0) {
|
||||
(minY + 1) / ProtocolDefinition.SECTION_HEIGHT_Y - 1
|
||||
} else {
|
||||
@ -37,9 +39,9 @@ data class DimensionProperties(
|
||||
} else {
|
||||
height / ProtocolDefinition.SECTION_HEIGHT_Y
|
||||
}
|
||||
val sections = highestSection - lowestSection
|
||||
|
||||
val lightLevels = FloatArray(16)
|
||||
val sections = highestSection - lowestSection
|
||||
|
||||
init {
|
||||
val ambientLight = 0.0f // ToDo: 0.1 in nether
|
||||
@ -69,7 +71,7 @@ data class DimensionProperties(
|
||||
minY = data["min_y"]?.toInt() ?: 0,
|
||||
hasCeiling = data["has_ceiling"]?.toBoolean() ?: false,
|
||||
ultraWarm = data["ultrawarm"]?.toBoolean() ?: false,
|
||||
height = data["height"]?.toInt() ?: 256,
|
||||
dataHeight = data["height"]?.toInt() ?: 256,
|
||||
supports3DBiomes = data["supports_3d_biomes"]?.toBoolean() ?: true,
|
||||
)
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ import java.util.*
|
||||
|
||||
data class StatusEffect(
|
||||
override val resourceLocation: ResourceLocation,
|
||||
val category: StatusEffectCategories,
|
||||
val category: StatusEffectCategories?,
|
||||
override val translationKey: ResourceLocation?,
|
||||
val color: RGBColor,
|
||||
val attributes: Map<ResourceLocation, EntityAttributeModifier>,
|
||||
@ -55,7 +55,7 @@ data class StatusEffect(
|
||||
|
||||
return StatusEffect(
|
||||
resourceLocation = resourceLocation,
|
||||
category = StatusEffectCategories[data["category"].unsafeCast<String>()],
|
||||
category = data["category"]?.unsafeCast<String>()?.let { return@let StatusEffectCategories[it] },
|
||||
translationKey = data["translation_key"]?.toResourceLocation(),
|
||||
color = data["color"].unsafeCast<Int>().asRGBColor(),
|
||||
attributes = attributes.toMap(),
|
||||
|
@ -154,7 +154,7 @@ open class Item(
|
||||
"SkullItem" -> SkullItem(resourceLocation, registries, data)
|
||||
"NetherStarItem" -> NetherStarItem(resourceLocation, registries, data)
|
||||
"FireworkItem" -> FireworkItem(resourceLocation, registries, data)
|
||||
"FireworkChargeItem" -> FireworkChargeItem(resourceLocation, registries, data)
|
||||
"FireworkChargeItem", "FireworkRocketItem" -> FireworkChargeItem(resourceLocation, registries, data)
|
||||
"EnchantedBookItem" -> EnchantedBookItem(resourceLocation, registries, data)
|
||||
"ArmorStandItem" -> ArmorStandItem(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
|
||||
|
||||
interface AbstractRegistry<T> : Iterable<T>, Clearable, Parentable<AbstractRegistry<T>> {
|
||||
|
||||
val size: Int
|
||||
|
||||
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.util.KUtil.toSynchronizedMap
|
||||
|
||||
class BlockStateRegistry(var flattened: Boolean) : AbstractRegistry<BlockState> {
|
||||
override var parent: AbstractRegistry<BlockState>? = null
|
||||
class BlockStateRegistry(var flattened: Boolean) : AbstractRegistry<BlockState?> {
|
||||
override var parent: AbstractRegistry<BlockState?>? = null
|
||||
private val idMap: MutableMap<Int, BlockState> = mutableMapOf()
|
||||
|
||||
override val size: Int
|
||||
@ -66,7 +66,7 @@ class BlockStateRegistry(var flattened: Boolean) : AbstractRegistry<BlockState>
|
||||
return forceGet(id)
|
||||
}
|
||||
|
||||
override fun getId(value: BlockState): Int {
|
||||
override fun getId(value: BlockState?): Int {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ class Chunk(
|
||||
data.blocks?.let {
|
||||
for ((index, blocks) in it.withIndex()) {
|
||||
blocks ?: continue
|
||||
val section = getOrPut(index - lowestSection)
|
||||
val section = getOrPut(index + lowestSection)
|
||||
section.blocks = blocks
|
||||
}
|
||||
blocksInitialized = true
|
||||
@ -148,7 +148,7 @@ class Chunk(
|
||||
|
||||
var section = sections[sectionIndex]
|
||||
if (section == null) {
|
||||
section = ChunkSection(connection.registries)
|
||||
section = ChunkSection()
|
||||
val neighbours: Array<Chunk> = world.getChunkNeighbours(chunkPosition).unsafeCast()
|
||||
val cacheBiomeAccessor = world.cacheBiomeAccessor
|
||||
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.registries.blocks.BlockState
|
||||
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
|
||||
|
||||
class ChunkData(
|
||||
var blocks: Array<RegistrySectionDataProvider<BlockState?>?>? = null,
|
||||
var blocks: Array<SectionDataProvider<BlockState?>?>? = null,
|
||||
var blockEntities: Map<Vec3i, BlockEntity>? = null,
|
||||
var biomeSource: BiomeSource? = 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.registries.biomes.Biome
|
||||
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.container.RegistrySectionDataProvider
|
||||
import de.bixilon.minosoft.data.world.container.SectionDataProvider
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.of
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
@ -30,14 +28,12 @@ import glm_.vec3.Vec3i
|
||||
* Collection of 16x16x16 blocks
|
||||
*/
|
||||
class ChunkSection(
|
||||
var blocks: RegistrySectionDataProvider<BlockState?>,
|
||||
var biomes: RegistrySectionDataProvider<Biome>,
|
||||
var blockEntities: SectionDataProvider<BlockEntity?>,
|
||||
var light: ByteArray, // packed (skyLight: 0xF0, blockLight: 0x0F)
|
||||
var blocks: SectionDataProvider<BlockState?> = SectionDataProvider(checkSize = true),
|
||||
var biomes: SectionDataProvider<Biome> = SectionDataProvider(checkSize = false),
|
||||
var blockEntities: SectionDataProvider<BlockEntity?> = SectionDataProvider(checkSize = false),
|
||||
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) {
|
||||
if (blockEntities.isEmpty) {
|
||||
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.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
||||
import de.bixilon.minosoft.util.ReadWriteLock
|
||||
import glm_.vec3.Vec3i
|
||||
|
||||
open class SectionDataProvider<T>(
|
||||
data: Array<Any?>? = null,
|
||||
class SectionDataProvider<T>(
|
||||
data: Array<T>? = null,
|
||||
val checkSize: Boolean = false,
|
||||
) : Iterable<T> {
|
||||
protected var data = data
|
||||
protected var data: Array<Any?>? = data?.unsafeCast()
|
||||
private set
|
||||
protected val lock = ReadWriteLock() // lock while reading (blocks writing)
|
||||
var count: Int = 0
|
||||
@ -191,9 +192,9 @@ open class SectionDataProvider<T>(
|
||||
unlock()
|
||||
}
|
||||
|
||||
open fun copy(): SectionDataProvider<T> {
|
||||
fun copy(): SectionDataProvider<T> {
|
||||
acquire()
|
||||
val clone = SectionDataProvider<T>(data?.clone())
|
||||
val clone = SectionDataProvider<T>(data?.clone()?.unsafeCast())
|
||||
release()
|
||||
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
@ -10,25 +10,24 @@
|
||||
*
|
||||
* 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
|
||||
|
||||
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 {
|
||||
fun choosePalette(bitsPerBlock: Int, buffer: PlayInByteBuffer): Palette {
|
||||
if (bitsPerBlock <= 4) {
|
||||
return IndirectPalette(4, buffer)
|
||||
} else if (bitsPerBlock <= 8) {
|
||||
return IndirectPalette(bitsPerBlock, buffer)
|
||||
fun create(versionId: Int, bits: Int, size: Int): PaletteData {
|
||||
return when (bits) {
|
||||
0 -> EmptyPaletteData(size)
|
||||
else -> ArrayPaletteData(versionId, bits, size)
|
||||
}
|
||||
return DirectPalette(buffer)
|
||||
}
|
||||
}
|
||||
}
|
@ -11,34 +11,23 @@
|
||||
* 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.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||
|
||||
class RegistrySectionDataProvider<T>(
|
||||
val registry: AbstractRegistry<T>,
|
||||
data: Array<Any?>? = null,
|
||||
checkSize: Boolean = false,
|
||||
) : SectionDataProvider<T>(data, checkSize = checkSize) {
|
||||
class ArrayPalette<T>(private val registry: AbstractRegistry<T>, override val bits: Int) : Palette<T> {
|
||||
private var array: Array<Any?> = arrayOfNulls(0)
|
||||
|
||||
override fun read(buffer: PlayInByteBuffer) {
|
||||
array = arrayOfNulls(buffer.readVarInt())
|
||||
for (i in array.indices) {
|
||||
array[i] = registry[buffer.readVarInt()]
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun setIdData(ids: IntArray) {
|
||||
val data: Array<Any?> = arrayOfNulls(ProtocolDefinition.BLOCKS_PER_SECTION)
|
||||
|
||||
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
|
||||
override fun get(index: Int): T {
|
||||
return array[index] as T
|
||||
}
|
||||
}
|
@ -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!" }
|
||||
}
|
||||
|
||||
@Deprecated("Refactoring needed")
|
||||
private fun loadSounds() {
|
||||
Log.log(LogMessageType.AUDIO_LOADING, LogLevels.VERBOSE) { "Loading sounds.json" }
|
||||
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.util.mesh.MeshStruct
|
||||
import glm_.vec2.Vec2i
|
||||
import org.lwjgl.system.MemoryUtil.memAllocFloat
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.FloatBuffer
|
||||
|
||||
@ -88,9 +87,9 @@ interface RenderSystem {
|
||||
|
||||
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 createFloatUniformBuffer(bindingIndex: Int = 0, data: FloatBuffer = memAllocFloat(0)): FloatUniformBuffer
|
||||
fun createFloatUniformBuffer(bindingIndex: Int = 0, data: FloatBuffer): FloatUniformBuffer
|
||||
|
||||
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.system.base.BlendingFunctions
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.RenderingCapabilities
|
||||
|
||||
interface TranslucentDrawable : Renderer {
|
||||
val skipTranslucent: Boolean
|
||||
get() = false
|
||||
|
||||
fun setupTranslucent() {
|
||||
renderSystem.reset(blending = true) // ToDo: This is just a translucent workaround
|
||||
renderSystem.enable(RenderingCapabilities.BLENDING)
|
||||
renderSystem.reset(blending = true)
|
||||
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 mainHand: Hands = Hands.MAIN,
|
||||
val disableTextFiltering: Boolean = true,
|
||||
val allowListing: Boolean = true,
|
||||
) : PlayC2SPacket {
|
||||
|
||||
override fun write(buffer: PlayOutByteBuffer) {
|
||||
@ -53,10 +54,13 @@ class ClientSettingsC2SP(
|
||||
if (buffer.versionId >= ProtocolVersions.V_21W07A) {
|
||||
buffer.writeBoolean(disableTextFiltering)
|
||||
}
|
||||
if (buffer.versionId >= ProtocolVersions.V_21W44A) {
|
||||
buffer.writeBoolean(allowListing)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -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.protocol.PlayInByteBuffer
|
||||
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.LogLevels
|
||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
@ -30,7 +31,11 @@ class BlockEntityMetaDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||
} else {
|
||||
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()
|
||||
|
||||
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.gui.rendering.util.VecUtil.of
|
||||
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.packets.s2c.PlayS2CPacket
|
||||
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.unsafeCast
|
||||
import de.bixilon.minosoft.util.Util
|
||||
@ -49,16 +48,16 @@ class ChunkDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||
|
||||
init {
|
||||
val dimension = buffer.connection.world.dimension!!
|
||||
chunkPosition = Vec2i(buffer.readInt(), buffer.readInt())
|
||||
if (buffer.versionId < ProtocolVersions.V_20W45A) {
|
||||
chunkPosition = buffer.readChunkPosition()
|
||||
if (buffer.versionId < V_20W45A) {
|
||||
isFullChunk = !buffer.readBoolean()
|
||||
}
|
||||
if (buffer.versionId < ProtocolVersions.V_14W26A) {
|
||||
if (buffer.versionId < V_14W26A) { // ToDo
|
||||
val sectionBitMask = BitSet.valueOf(buffer.readByteArray(2))
|
||||
val addBitMask = BitSet.valueOf(buffer.readByteArray(2))
|
||||
|
||||
// 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)
|
||||
} else {
|
||||
buffer
|
||||
@ -70,44 +69,47 @@ class ChunkDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||
this.chunkData.replace(chunkData)
|
||||
}
|
||||
} 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???
|
||||
}
|
||||
val sectionBitMask: BitSet = when {
|
||||
buffer.versionId < ProtocolVersions.V_15W34C -> {
|
||||
BitSet.valueOf(buffer.readByteArray(2))
|
||||
val sectionBitMask = when {
|
||||
buffer.versionId < V_15W34C -> 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 < V_21W37A -> BitSet.valueOf(buffer.readLongArray())
|
||||
else -> null
|
||||
}
|
||||
buffer.versionId < ProtocolVersions.V_15W36D -> {
|
||||
BitSet.valueOf(buffer.readByteArray(4))
|
||||
}
|
||||
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()
|
||||
}
|
||||
if (!isFullChunk) {
|
||||
if (!isFullChunk && buffer.versionId < V_21W37A) {
|
||||
this.chunkData.biomeSource = SpatialBiomeArray(buffer.readBiomeArray())
|
||||
}
|
||||
val size = buffer.readVarInt()
|
||||
val lastPos = buffer.pointer
|
||||
val chunkData = ChunkUtil.readChunkPacket(buffer, dimension, sectionBitMask, null, !isFullChunk, dimension.hasSkyLight)
|
||||
val lastBufferPosition = buffer.pointer
|
||||
|
||||
if (buffer.versionId < V_21W37A) {
|
||||
val chunkData = ChunkUtil.readChunkPacket(buffer, dimension, sectionBitMask!!, null, !isFullChunk, dimension.hasSkyLight)
|
||||
if (chunkData == null) {
|
||||
unloadChunk = true
|
||||
} else {
|
||||
this.chunkData.replace(chunkData)
|
||||
}
|
||||
// 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
|
||||
buffer.pointer = size + lastPos
|
||||
if (buffer.versionId >= ProtocolVersions.V_1_9_4) {
|
||||
} 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)
|
||||
val blockEntitiesCount = buffer.readVarInt()
|
||||
for (i in 0 until blockEntitiesCount) {
|
||||
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()
|
||||
@ -121,6 +123,25 @@ class ChunkDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||
}
|
||||
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)
|
||||
chunk.setData(chunkData)
|
||||
connection.fireEvent(ChunkDataChangeEvent(connection, this))
|
||||
}
|
||||
|
||||
override fun log() {
|
||||
|
@ -27,8 +27,8 @@ import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
import glm_.vec2.Vec2i
|
||||
import java.util.*
|
||||
|
||||
class ChunkLightDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||
val chunkPosition: Vec2i = Vec2i(buffer.readVarInt(), buffer.readVarInt())
|
||||
class ChunkLightDataS2CP(buffer: PlayInByteBuffer, chunkPositionGetter: () -> Vec2i = { Vec2i(buffer.readVarInt(), buffer.readVarInt()) }) : PlayS2CPacket() {
|
||||
val chunkPosition: Vec2i = chunkPositionGetter()
|
||||
var trustEdges: Boolean = false
|
||||
private set
|
||||
val chunkData: ChunkData
|
||||
|
@ -70,6 +70,8 @@ class JoinGameS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||
private set
|
||||
var world: ResourceLocation? = null
|
||||
private set
|
||||
var simulationDistance: Int = -1
|
||||
private set
|
||||
|
||||
init {
|
||||
entityId = buffer.readInt()
|
||||
@ -131,6 +133,9 @@ class JoinGameS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||
if (buffer.versionId >= ProtocolVersions.V_19W13A) {
|
||||
viewDistance = buffer.readVarInt()
|
||||
}
|
||||
if (buffer.versionId >= ProtocolVersions.V_21W40A) {
|
||||
simulationDistance = buffer.readVarInt()
|
||||
}
|
||||
if (buffer.versionId >= ProtocolVersions.V_20W20A) {
|
||||
buffer.readBoolean() // isDebug
|
||||
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
|
||||
}
|
||||
|
||||
fun readLongArray(target: LongArray, size: Int = readVarInt()) {
|
||||
for (i in 0 until size) {
|
||||
target[i] = readLong()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun readVarLong(): Long {
|
||||
var byteCount = 0
|
||||
|
@ -275,6 +275,7 @@ class PacketTypes {
|
||||
PLAY_ADVANCEMENT_PROGRESS({ TODO() }),
|
||||
PLAY_VIBRATION_SIGNAL({ VibrationSignalS2CP(it) }),
|
||||
PLAY_PING({ PingS2CP(it) }),
|
||||
PLAY_SIMULATION_DISTANCE({ SimulationDistanceSetS2CP(it) }),
|
||||
;
|
||||
|
||||
init {
|
||||
|
@ -16,6 +16,19 @@ package de.bixilon.minosoft.protocol.protocol;
|
||||
@SuppressWarnings("unused")
|
||||
public class ProtocolVersions {
|
||||
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_RC2 = 793,
|
||||
V_1_17_1_RC1 = 792,
|
||||
|
@ -15,9 +15,12 @@ package de.bixilon.minosoft.util
|
||||
|
||||
import de.bixilon.minosoft.util.KUtil.decide
|
||||
import glm_.vec2.Vec2i
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
import kotlin.math.ln
|
||||
|
||||
object MMath {
|
||||
private const val LN_2 = 0.69314718056 // ln(2.0)
|
||||
|
||||
fun clamp(value: Vec2i, min: Vec2i, max: Vec2i): Vec2i {
|
||||
value.x = clamp(value.x, min.x, max.x)
|
||||
@ -118,4 +121,8 @@ object MMath {
|
||||
val int = this.toInt()
|
||||
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.ChunkData
|
||||
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.container.RegistrySectionDataProvider
|
||||
import de.bixilon.minosoft.data.world.palette.Palette.Companion.choosePalette
|
||||
import de.bixilon.minosoft.data.world.container.SectionDataProvider
|
||||
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.protocol.protocol.PlayInByteBuffer
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*
|
||||
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
||||
import glm_.vec2.Vec2i
|
||||
import java.util.*
|
||||
|
||||
@ -63,13 +67,13 @@ object ChunkUtil {
|
||||
|
||||
// parse data
|
||||
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()) {
|
||||
if (!sectionBitMask[sectionIndex]) {
|
||||
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) {
|
||||
var blockId = (blockData[arrayPosition].toInt() and 0xFF) shl 4
|
||||
@ -95,7 +99,7 @@ object ChunkUtil {
|
||||
|
||||
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
|
||||
return chunkData
|
||||
@ -129,7 +133,7 @@ object ChunkUtil {
|
||||
}
|
||||
|
||||
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
|
||||
if (!sectionBitMask[sectionIndex]) {
|
||||
continue
|
||||
@ -140,56 +144,38 @@ object ChunkUtil {
|
||||
val block = buffer.connection.registries.blockStateRegistry[blockId] ?: continue
|
||||
blocks[blockNumber] = block
|
||||
}
|
||||
sectionBlocks[sectionHeight] = RegistrySectionDataProvider(buffer.connection.registries.blockStateRegistry.unsafeCast(), blocks.unsafeCast(), true)
|
||||
sectionBlocks[sectionHeight] = SectionDataProvider(blocks, true)
|
||||
}
|
||||
chunkData.blocks = sectionBlocks
|
||||
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 sectionBlocks: Array<RegistrySectionDataProvider<BlockState?>?> = arrayOfNulls(dimension.sections)
|
||||
val sectionBlocks: Array<SectionDataProvider<BlockState?>?> = arrayOfNulls(dimension.sections)
|
||||
val light: Array<ByteArray?> = arrayOfNulls(dimension.sections)
|
||||
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
|
||||
if (!sectionBitMask[sectionIndex]) {
|
||||
for ((sectionIndex, sectionHeight) in (dimension.lowestSection until (sectionBitMask?.length() ?: dimension.highestSection)).withIndex()) { // max sections per chunks in chunk column
|
||||
if (sectionBitMask?.get(sectionIndex) == false) {
|
||||
continue
|
||||
}
|
||||
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()
|
||||
|
||||
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)
|
||||
if (blockContainer.palette !is SingularPalette<*> || blockContainer.palette.item != null) {
|
||||
sectionBlocks[sectionHeight - dimension.lowestSection] = SectionDataProvider(blockContainer.unpack(), checkSize = true)
|
||||
}
|
||||
} else {
|
||||
val startLong = blockNumber / (Long.SIZE_BITS / palette.bitsPerBlock)
|
||||
val startOffset = blockNumber % (Long.SIZE_BITS / palette.bitsPerBlock) * palette.bitsPerBlock
|
||||
data[startLong] ushr startOffset
|
||||
if (buffer.versionId >= V_21W37A) {
|
||||
val biomeContainer: PalettedContainer<Biome> = PalettedContainerReader.read(buffer, buffer.connection.registries.biomeRegistry, paletteFactory = BiomePaletteFactory)
|
||||
biomes[sectionHeight - dimension.lowestSection] = biomeContainer.unpack()
|
||||
}
|
||||
|
||||
blockId = blockId and individualValueMask.toLong()
|
||||
|
||||
val block = palette.blockById(blockId.toInt()) ?: continue
|
||||
blocks[blockNumber] = block
|
||||
}
|
||||
|
||||
if (buffer.versionId < V_18W43A) {
|
||||
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)
|
||||
lightReceived++
|
||||
}
|
||||
sectionBlocks[sectionHeight - dimension.lowestSection] = RegistrySectionDataProvider(buffer.connection.registries.blockStateRegistry.unsafeCast(), blocks.unsafeCast(), true)
|
||||
}
|
||||
|
||||
chunkData.blocks = sectionBlocks
|
||||
if (lightReceived > 0) {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ object LightUtil {
|
||||
val EMPTY_LIGHT_ARRAY = ByteArray(ProtocolDefinition.BLOCKS_PER_SECTION / 2)
|
||||
|
||||
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
|
||||
readLightArray(buffer, skyLightMask, dimension)
|
||||
} 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