wip: 21w37a

* Still todo: Parse "new" chunk format
This commit is contained in:
Bixilon 2021-11-11 23:26:41 +01:00
parent ce850dc802
commit 44e8b358a2
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
11 changed files with 104 additions and 70 deletions

View File

@ -37,9 +37,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

View File

@ -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(),

View File

@ -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)

View File

@ -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) {

View File

@ -20,11 +20,12 @@ 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.V_18W44A
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_21W37A
import de.bixilon.minosoft.util.KUtil.toInt
import de.bixilon.minosoft.util.KUtil.unsafeCast
import de.bixilon.minosoft.util.Util
@ -49,77 +50,104 @@ class ChunkDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
init {
val dimension = buffer.connection.world.dimension!!
chunkPosition = Vec2i(buffer.readInt(), buffer.readInt())
chunkPosition = buffer.readChunkPosition()
if (buffer.versionId < ProtocolVersions.V_20W45A) {
isFullChunk = !buffer.readBoolean()
}
if (buffer.versionId < ProtocolVersions.V_14W26A) {
val sectionBitMask = BitSet.valueOf(buffer.readByteArray(2))
val addBitMask = BitSet.valueOf(buffer.readByteArray(2))
when {
buffer.versionId < ProtocolVersions.V_14W26A -> {
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) {
Util.decompress(buffer.readByteArray(buffer.readInt()), buffer.connection)
} else {
buffer
}
val chunkData = ChunkUtil.readChunkPacket(decompressed, dimension, sectionBitMask, addBitMask, !isFullChunk, dimension.hasSkyLight)
if (chunkData == null) {
unloadChunk = true
} else {
this.chunkData.replace(chunkData)
}
} else {
if (buffer.versionId >= ProtocolVersions.V_1_16_PRE7 && buffer.versionId < ProtocolVersions.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))
// decompress chunk data
val decompressed: PlayInByteBuffer = if (buffer.versionId < ProtocolVersions.V_14W28A) {
Util.decompress(buffer.readByteArray(buffer.readInt()), buffer.connection)
} else {
buffer
}
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())
val chunkData = ChunkUtil.readChunkPacket(decompressed, dimension, sectionBitMask, addBitMask, !isFullChunk, dimension.hasSkyLight)
if (chunkData == null) {
unloadChunk = true
} else {
this.chunkData.replace(chunkData)
}
}
if (buffer.versionId >= ProtocolVersions.V_18W44A) {
buffer.versionId < V_21W37A -> {
if (buffer.versionId >= ProtocolVersions.V_1_16_PRE7 && buffer.versionId < ProtocolVersions.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))
}
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 >= V_18W44A) {
heightMap = buffer.readNBT()?.compoundCast()
}
if (!isFullChunk) {
this.chunkData.biomeSource = SpatialBiomeArray(buffer.readBiomeArray())
}
val size = buffer.readVarInt()
val lastBufferPosition = buffer.pointer
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 + lastBufferPosition
if (buffer.versionId >= ProtocolVersions.V_1_9_4) {
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 -> {
heightMap = buffer.readNBT()?.compoundCast()
}
if (!isFullChunk) {
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)
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) {
val sectionBuffer = PlayInByteBuffer(buffer.readByteArray(), buffer.connection)
for (sectionHeight in dimension.lowestSection until dimension.highestSection) {
val nonAirBlocks = sectionBuffer.readShort()
// ToDo: BlockStates, Biomes
}
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 xz = buffer.readUnsignedByte()
val y = buffer.readShort()
val type = buffer.connection.registries.blockEntityTypeRegistry[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
blockEntities[Vec3i(xz shr 4, y, xz and 0x0F)] = entity
}
this.chunkData.blockEntities = blockEntities
chunkData.blockEntities = blockEntities
val lightPacket = ChunkLightDataS2CP(buffer) { chunkPosition }
chunkData.replace(lightPacket.chunkData)
}
}
}
@ -131,7 +159,6 @@ class ChunkDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
}
val chunk = connection.world.getOrCreateChunk(chunkPosition)
chunk.setData(chunkData)
connection.fireEvent(ChunkDataChangeEvent(connection, this))
}
override fun log() {

View File

@ -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

View File

@ -16,6 +16,7 @@ package de.bixilon.minosoft.protocol.protocol;
@SuppressWarnings("unused")
public class ProtocolVersions {
public static final int
V_21W37A = 795,
V_1_17_1 = 794,
V_1_17_1_RC2 = 793,
V_1_17_1_RC1 = 792,

View File

@ -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