rename DimensionType to DimensionProperties

This commit is contained in:
Bixilon 2021-10-18 13:37:12 +02:00
parent 85fe06d1f0
commit 13a91a0812
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
11 changed files with 45 additions and 41 deletions

View File

@ -19,7 +19,7 @@ import de.bixilon.minosoft.data.registries.registries.registry.ResourceLocationD
data class Dimension( data class Dimension(
override val resourceLocation: ResourceLocation, override val resourceLocation: ResourceLocation,
val type: DimensionType, val type: DimensionProperties,
) : RegistryItem() { ) : RegistryItem() {
override fun toString(): String { override fun toString(): String {
@ -30,7 +30,7 @@ data class Dimension(
override fun deserialize(registries: Registries?, resourceLocation: ResourceLocation, data: Map<String, Any>): Dimension { override fun deserialize(registries: Registries?, resourceLocation: ResourceLocation, data: Map<String, Any>): Dimension {
return Dimension( return Dimension(
resourceLocation = resourceLocation, resourceLocation = resourceLocation,
type = DimensionType.deserialize(data) type = DimensionProperties.deserialize(data)
) )
} }
} }

View File

@ -9,7 +9,7 @@ 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.nbt.tag.NBTUtil.get import de.bixilon.minosoft.util.nbt.tag.NBTUtil.get
data class DimensionType( data class DimensionProperties(
val piglinSafe: Boolean = false, val piglinSafe: Boolean = false,
val natural: Boolean = true, val natural: Boolean = true,
val ambientLight: Float = 0.0f, val ambientLight: Float = 0.0f,
@ -51,8 +51,8 @@ data class DimensionType(
companion object { companion object {
fun deserialize(data: Map<String, Any>): DimensionType { fun deserialize(data: Map<String, Any>): DimensionProperties {
return DimensionType( return DimensionProperties(
piglinSafe = data["piglin_safe"]?.toBoolean() ?: false, piglinSafe = data["piglin_safe"]?.toBoolean() ?: false,
natural = data["natural"]?.toBoolean() ?: false, natural = data["natural"]?.toBoolean() ?: false,
ambientLight = data["ambient_light"]?.unsafeCast<Float>() ?: 0.0f, ambientLight = data["ambient_light"]?.unsafeCast<Float>() ?: 0.0f,

View File

@ -19,7 +19,7 @@ import de.bixilon.minosoft.data.registries.ResourceLocation
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.blocks.types.FluidBlock import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock
import de.bixilon.minosoft.data.registries.dimension.DimensionType import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
import de.bixilon.minosoft.data.registries.sounds.SoundEvent import de.bixilon.minosoft.data.registries.sounds.SoundEvent
import de.bixilon.minosoft.data.registries.tweaker.VersionTweaker import de.bixilon.minosoft.data.registries.tweaker.VersionTweaker
import de.bixilon.minosoft.data.world.biome.accessor.BiomeAccessor import de.bixilon.minosoft.data.world.biome.accessor.BiomeAccessor
@ -61,7 +61,7 @@ class World(
val chunks: MutableMap<Vec2i, Chunk> = synchronizedMapOf() val chunks: MutableMap<Vec2i, Chunk> = synchronizedMapOf()
val entities = WorldEntities() val entities = WorldEntities()
var hardcore = false var hardcore = false
var dimension: DimensionType? = null var dimension: DimensionProperties? = null
var difficulty: Difficulties? = null var difficulty: Difficulties? = null
var difficultyLocked = false var difficultyLocked = false
val worldLightAccessor = WorldLightAccessor(this) val worldLightAccessor = WorldLightAccessor(this)

View File

@ -15,7 +15,7 @@ package de.bixilon.minosoft.modding.event.events;
import de.bixilon.minosoft.data.Difficulties; import de.bixilon.minosoft.data.Difficulties;
import de.bixilon.minosoft.data.abilities.Gamemodes; import de.bixilon.minosoft.data.abilities.Gamemodes;
import de.bixilon.minosoft.data.registries.dimension.DimensionType; import de.bixilon.minosoft.data.registries.dimension.DimensionProperties;
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent; import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent;
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.play.RespawnS2CP; import de.bixilon.minosoft.protocol.packets.s2c.play.RespawnS2CP;
@ -23,20 +23,20 @@ import de.bixilon.minosoft.protocol.packets.s2c.play.RespawnS2CP;
@Deprecated @Deprecated
public class RespawnEvent extends PlayConnectionEvent { public class RespawnEvent extends PlayConnectionEvent {
private final Gamemodes gamemode; private final Gamemodes gamemode;
private final DimensionType dimensionType; private final DimensionProperties dimensionProperties;
private final Difficulties difficulty; private final Difficulties difficulty;
public RespawnEvent(PlayConnection connection, Gamemodes gamemode, DimensionType dimensionType, Difficulties difficulty) { public RespawnEvent(PlayConnection connection, Gamemodes gamemode, DimensionProperties dimensionProperties, Difficulties difficulty) {
super(connection); super(connection);
this.gamemode = gamemode; this.gamemode = gamemode;
this.dimensionType = dimensionType; this.dimensionProperties = dimensionProperties;
this.difficulty = difficulty; this.difficulty = difficulty;
} }
public RespawnEvent(PlayConnection connection, RespawnS2CP pkg) { public RespawnEvent(PlayConnection connection, RespawnS2CP pkg) {
super(connection); super(connection);
this.gamemode = pkg.getGamemode(); this.gamemode = pkg.getGamemode();
this.dimensionType = pkg.getDimension(); this.dimensionProperties = pkg.getDimension();
this.difficulty = pkg.getDifficulty(); this.difficulty = pkg.getDifficulty();
} }
@ -44,8 +44,8 @@ public class RespawnEvent extends PlayConnectionEvent {
return this.gamemode; return this.gamemode;
} }
public DimensionType getDimensionType() { public DimensionProperties getDimensionType() {
return this.dimensionType; return this.dimensionProperties;
} }
public Difficulties getDifficulty() { public Difficulties getDifficulty() {

View File

@ -18,18 +18,14 @@ 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.ProtocolStates import de.bixilon.minosoft.protocol.protocol.ProtocolStates
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
import de.bixilon.minosoft.util.Util import de.bixilon.minosoft.util.KUtil.decide
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
import java.util.* import java.util.*
class LoginSuccessS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { class LoginSuccessS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
val uuid: UUID = if (buffer.versionId < ProtocolVersions.V_20W12A) { val uuid: UUID = (buffer.versionId < ProtocolVersions.V_20W12A).decide({ buffer.readUUIDString() }, { buffer.readUUID() })
Util.getUUIDFromString(buffer.readString())
} else {
buffer.readUUID()
}
val name: String = buffer.readString() val name: String = buffer.readString()
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {

View File

@ -18,7 +18,7 @@ import de.bixilon.minosoft.data.abilities.Gamemodes
import de.bixilon.minosoft.data.registries.DefaultRegistries import de.bixilon.minosoft.data.registries.DefaultRegistries
import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.dimension.Dimension import de.bixilon.minosoft.data.registries.dimension.Dimension
import de.bixilon.minosoft.data.registries.dimension.DimensionType import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
import de.bixilon.minosoft.data.registries.other.game.event.handlers.gamemode.GamemodeChangeEvent import de.bixilon.minosoft.data.registries.other.game.event.handlers.gamemode.GamemodeChangeEvent
import de.bixilon.minosoft.data.world.biome.accessor.BlockBiomeAccessor import de.bixilon.minosoft.data.world.biome.accessor.BlockBiomeAccessor
import de.bixilon.minosoft.data.world.biome.accessor.NoiseBiomeAccessor import de.bixilon.minosoft.data.world.biome.accessor.NoiseBiomeAccessor
@ -50,7 +50,7 @@ class JoinGameS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
val entityId: Int val entityId: Int
val isHardcore: Boolean val isHardcore: Boolean
val gamemode: Gamemodes val gamemode: Gamemodes
var dimensionType: DimensionType var dimensionProperties: DimensionProperties
private set private set
var difficulty: Difficulties = Difficulties.NORMAL var difficulty: Difficulties = Difficulties.NORMAL
private set private set
@ -87,7 +87,7 @@ class JoinGameS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
} }
if (buffer.versionId < ProtocolVersions.V_1_9_1) { if (buffer.versionId < ProtocolVersions.V_1_9_1) {
dimensionType = buffer.connection.registries.dimensionRegistry[buffer.readByte().toInt()].type dimensionProperties = buffer.connection.registries.dimensionRegistry[buffer.readByte().toInt()].type
difficulty = Difficulties[buffer.readUnsignedByte()] difficulty = Difficulties[buffer.readUnsignedByte()]
maxPlayers = buffer.readByte().toInt() maxPlayers = buffer.readByte().toInt()
if (buffer.versionId >= ProtocolVersions.V_13W42B) { if (buffer.versionId >= ProtocolVersions.V_13W42B) {
@ -104,14 +104,14 @@ class JoinGameS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
worlds = buffer.readArray { buffer.readResourceLocation() } worlds = buffer.readArray { buffer.readResourceLocation() }
} }
if (buffer.versionId < ProtocolVersions.V_20W21A) { if (buffer.versionId < ProtocolVersions.V_20W21A) {
dimensionType = buffer.connection.registries.dimensionRegistry[buffer.readInt()].type dimensionProperties = buffer.connection.registries.dimensionRegistry[buffer.readInt()].type
} else { } else {
val dimensionCodec = buffer.readNBT().asCompound() val dimensionCodec = buffer.readNBT().asCompound()
dimensions = parseDimensionCodec(dimensionCodec, buffer.versionId) dimensions = parseDimensionCodec(dimensionCodec, buffer.versionId)
dimensionType = if (buffer.versionId < ProtocolVersions.V_1_16_2_PRE3) { dimensionProperties = if (buffer.versionId < ProtocolVersions.V_1_16_2_PRE3) {
dimensions[buffer.readResourceLocation()]!!.type dimensions[buffer.readResourceLocation()]!!.type
} else { } else {
DimensionType.deserialize(buffer.readNBT().asCompound()) DimensionProperties.deserialize(buffer.readNBT().asCompound())
} }
world = buffer.readResourceLocation() world = buffer.readResourceLocation()
} }
@ -158,7 +158,7 @@ class JoinGameS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
connection.world.hardcore = isHardcore connection.world.hardcore = isHardcore
connection.registries.dimensionRegistry.setData(dimensions) connection.registries.dimensionRegistry.setData(dimensions)
connection.world.dimension = dimensionType connection.world.dimension = dimensionProperties
connection.world.entities.add(entityId, null, playerEntity) connection.world.entities.add(entityId, null, playerEntity)
connection.world.hashedSeed = hashedSeed connection.world.hashedSeed = hashedSeed
@ -202,7 +202,7 @@ class JoinGameS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
} }
override fun log() { override fun log() {
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Join game (entityId=$entityId, gamemode=$gamemode, dimensionType=$dimensionType, difficulty=$difficulty, hardcore=$isHardcore, viewDistance=$viewDistance)" } Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Join game (entityId=$entityId, gamemode=$gamemode, dimensionType=$dimensionProperties, difficulty=$difficulty, hardcore=$isHardcore, viewDistance=$viewDistance)" }
} }
companion object : ErrorHandler { companion object : ErrorHandler {

View File

@ -23,7 +23,6 @@ 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.terminal.RunConfiguration import de.bixilon.minosoft.terminal.RunConfiguration
import de.bixilon.minosoft.util.Util
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
@ -42,7 +41,7 @@ class PlayerEntitySpawnS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
val properties: MutableMap<String, PlayerProperty> = mutableMapOf() val properties: MutableMap<String, PlayerProperty> = mutableMapOf()
if (buffer.versionId < ProtocolVersions.V_14W21A) { if (buffer.versionId < ProtocolVersions.V_14W21A) {
name = buffer.readString() name = buffer.readString()
entityUUID = Util.getUUIDFromString(buffer.readString()) entityUUID = buffer.readUUIDString()
val length = buffer.readVarInt() val length = buffer.readVarInt()
for (i in 0 until length) { for (i in 0 until length) {
val property = PlayerProperty(buffer.readString(), buffer.readString(), buffer.readString()) val property = PlayerProperty(buffer.readString(), buffer.readString(), buffer.readString())

View File

@ -15,7 +15,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play
import de.bixilon.minosoft.data.Difficulties import de.bixilon.minosoft.data.Difficulties
import de.bixilon.minosoft.data.abilities.Gamemodes import de.bixilon.minosoft.data.abilities.Gamemodes
import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.dimension.DimensionType import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.modding.event.events.RespawnEvent import de.bixilon.minosoft.modding.event.events.RespawnEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
@ -29,7 +29,7 @@ import de.bixilon.minosoft.util.nbt.tag.NBTUtil.asCompound
import glm_.vec3.Vec3d import glm_.vec3.Vec3d
class RespawnS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { class RespawnS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
var dimension: DimensionType var dimension: DimensionProperties
private set private set
var difficulty: Difficulties = Difficulties.NORMAL var difficulty: Difficulties = Difficulties.NORMAL
private set private set
@ -60,7 +60,7 @@ class RespawnS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
buffer.connection.registries.dimensionRegistry[buffer.readResourceLocation()]!!.type buffer.connection.registries.dimensionRegistry[buffer.readResourceLocation()]!!.type
} }
else -> { else -> {
DimensionType.deserialize(buffer.readNBT().asCompound()) // current dimension data DimensionProperties.deserialize(buffer.readNBT().asCompound()) // current dimension data
} }
} }
if (buffer.versionId < ProtocolVersions.V_19W11A) { if (buffer.versionId < ProtocolVersions.V_19W11A) {

View File

@ -246,6 +246,15 @@ open class InByteBuffer {
return readArray(length) { readUUID() } return readArray(length) { readUUID() }
} }
fun readUUIDString(): UUID {
return Util.getUUIDFromString(readString())
}
fun readUUIDStringArray(length: Int = readVarInt()): Array<UUID> {
return readArray(length) { readUUIDString() }
}
fun readJson(): Map<String, Any> { fun readJson(): Map<String, Any> {
return JSONSerializer.MUTABLE_MAP_ADAPTER.fromJson(readString())!! return JSONSerializer.MUTABLE_MAP_ADAPTER.fromJson(readString())!!
} }

View File

@ -15,7 +15,7 @@ package de.bixilon.minosoft.util.chunk
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.dimension.DimensionType import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
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.XZBiomeArray import de.bixilon.minosoft.data.world.biome.source.XZBiomeArray
@ -30,14 +30,14 @@ import java.util.*
object ChunkUtil { object ChunkUtil {
fun readChunkPacket(buffer: PlayInByteBuffer, dimension: DimensionType, sectionBitMask: BitSet, addBitMask: BitSet? = null, isFullChunk: Boolean, containsSkyLight: Boolean): ChunkData? { fun readChunkPacket(buffer: PlayInByteBuffer, dimension: DimensionProperties, sectionBitMask: BitSet, addBitMask: BitSet? = null, isFullChunk: Boolean, containsSkyLight: Boolean): ChunkData? {
if (buffer.versionId < V_15W35A) { // ToDo: was this really changed in 62? if (buffer.versionId < V_15W35A) { // ToDo: was this really changed in 62?
return readLegacyChunk(buffer, dimension, sectionBitMask, addBitMask, isFullChunk, containsSkyLight) return readLegacyChunk(buffer, dimension, sectionBitMask, addBitMask, isFullChunk, containsSkyLight)
} }
return readPaletteChunk(buffer, dimension, sectionBitMask, isFullChunk, containsSkyLight) return readPaletteChunk(buffer, dimension, sectionBitMask, isFullChunk, containsSkyLight)
} }
private fun readLegacyChunkWithAddBitSet(buffer: PlayInByteBuffer, dimension: DimensionType, sectionBitMask: BitSet, addBitMask: BitSet, isFullChunk: Boolean, containsSkyLight: Boolean): ChunkData { private fun readLegacyChunkWithAddBitSet(buffer: PlayInByteBuffer, dimension: DimensionProperties, sectionBitMask: BitSet, addBitMask: BitSet, isFullChunk: Boolean, containsSkyLight: Boolean): ChunkData {
val chunkData = ChunkData() val chunkData = ChunkData()
chunkData.lightAccessor = DummyLightAccessor // ToDo chunkData.lightAccessor = DummyLightAccessor // ToDo
@ -97,7 +97,7 @@ object ChunkUtil {
return chunkData return chunkData
} }
fun readLegacyChunk(buffer: PlayInByteBuffer, dimension: DimensionType, sectionBitMask: BitSet, addBitMask: BitSet? = null, isFullChunk: Boolean, containsSkyLight: Boolean = false): ChunkData? { fun readLegacyChunk(buffer: PlayInByteBuffer, dimension: DimensionProperties, sectionBitMask: BitSet, addBitMask: BitSet? = null, isFullChunk: Boolean, containsSkyLight: Boolean = false): ChunkData? {
if (sectionBitMask.length() == 0 && isFullChunk) { if (sectionBitMask.length() == 0 && isFullChunk) {
// unload chunk // unload chunk
return null return null
@ -142,7 +142,7 @@ object ChunkUtil {
return chunkData return chunkData
} }
fun readPaletteChunk(buffer: PlayInByteBuffer, dimension: DimensionType, 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 sectionMap: MutableMap<Int, ChunkSection> = synchronizedMapOf() val sectionMap: MutableMap<Int, ChunkSection> = synchronizedMapOf()

View File

@ -13,7 +13,7 @@
package de.bixilon.minosoft.util.chunk package de.bixilon.minosoft.util.chunk
import de.bixilon.minosoft.data.registries.dimension.DimensionType import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
import de.bixilon.minosoft.data.world.light.ChunkLightAccessor import de.bixilon.minosoft.data.world.light.ChunkLightAccessor
import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
@ -23,7 +23,7 @@ import java.util.*
object LightUtil { object LightUtil {
fun readLightPacket(buffer: PlayInByteBuffer, skyLightMask: BitSet, blockLightMask: BitSet, dimension: DimensionType): LightAccessor { fun readLightPacket(buffer: PlayInByteBuffer, skyLightMask: BitSet, blockLightMask: BitSet, dimension: DimensionProperties): LightAccessor {
// ToDo // 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)
@ -34,7 +34,7 @@ object LightUtil {
return ChunkLightAccessor(blockLight, skyLight) return ChunkLightAccessor(blockLight, skyLight)
} }
private fun readLightArray(buffer: PlayInByteBuffer, lightMask: BitSet, dimension: DimensionType): MutableMap<Int, ByteArray> { private fun readLightArray(buffer: PlayInByteBuffer, lightMask: BitSet, dimension: DimensionProperties): MutableMap<Int, ByteArray> {
var highestSectionIndex = dimension.highestSection + 1 var highestSectionIndex = dimension.highestSection + 1
val lowesSectionIndex = dimension.lowestSection - 1 val lowesSectionIndex = dimension.lowestSection - 1
if (buffer.versionId >= ProtocolVersions.V_20W49A) { if (buffer.versionId >= ProtocolVersions.V_20W49A) {