network, rendering: fix block changes

This commit is contained in:
Bixilon 2021-04-12 19:10:13 +02:00
parent 6afe5d64bd
commit d8790e3de0
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
7 changed files with 68 additions and 59 deletions

View File

@ -115,7 +115,7 @@ object VersionTweaker {
@JvmStatic @JvmStatic
fun transformBlock(originalBlock: BlockState, sections: Map<Int, ChunkSection>, inChunkSectionPositions: Vec3i, sectionHeight: Int): BlockState? { fun transformBlock(originalBlock: BlockState?, sections: Map<Int, ChunkSection>, inChunkSectionPositions: Vec3i, sectionHeight: Int): BlockState? {
// ToDo: Broken // ToDo: Broken
return originalBlock return originalBlock
} }

View File

@ -18,7 +18,6 @@ import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkSectionPosition import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkSectionPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight
import glm_.vec3.Vec3i import glm_.vec3.Vec3i
import java.util.*
/** /**
* Collection of chunks sections (allocated in y) * Collection of chunks sections (allocated in y)
@ -71,7 +70,7 @@ class Chunk(
} }
} }
fun setRawBlocks(blocks: HashMap<Vec3i, BlockState?>) { fun setRawBlocks(blocks: Map<Vec3i, BlockState?>) {
for ((location, blockState) in blocks) { for ((location, blockState) in blocks) {
setBlockState(location, blockState) setBlockState(location, blockState)
} }

View File

@ -278,7 +278,7 @@ class WorldRenderer(
val sections: MutableMap<Int, ChunkSection> = Collections.synchronizedMap(ConcurrentHashMap()) val sections: MutableMap<Int, ChunkSection> = Collections.synchronizedMap(ConcurrentHashMap())
val chunk = world.getChunk(chunkPosition)!! val chunk = world.getChunk(chunkPosition)!!
val lowestSectionHeight = getSectionIndex(sectionHeight) * RenderConstants.CHUNK_SECTIONS_PER_MESH val lowestSectionHeight = getSectionIndex(sectionHeight) * RenderConstants.CHUNK_SECTIONS_PER_MESH
for (i in lowestSectionHeight until lowestSectionHeight + (RenderConstants.CHUNK_SECTIONS_PER_MESH - 1)) { for (i in lowestSectionHeight until lowestSectionHeight + RenderConstants.CHUNK_SECTIONS_PER_MESH) {
sections[i] = chunk.sections?.get(i) ?: continue sections[i] = chunk.sections?.get(i) ?: continue
} }
prepareChunkSections(chunkPosition, sections) prepareChunkSections(chunkPosition, sections)

View File

@ -19,16 +19,16 @@ import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketMultiBlockCha
import glm_.vec2.Vec2i; import glm_.vec2.Vec2i;
import glm_.vec3.Vec3i; import glm_.vec3.Vec3i;
import java.util.HashMap; import java.util.Map;
/** /**
* Fired when at least block is changed * Fired when at least block is changed
*/ */
public class MultiBlockChangeEvent extends PlayConnectionEvent { public class MultiBlockChangeEvent extends PlayConnectionEvent {
private final HashMap<Vec3i, BlockState> blocks; private final Map<Vec3i, BlockState> blocks;
private final Vec2i chunkPosition; private final Vec2i chunkPosition;
public MultiBlockChangeEvent(PlayConnection connection, HashMap<Vec3i, BlockState> blocks, Vec2i position) { public MultiBlockChangeEvent(PlayConnection connection, Map<Vec3i, BlockState> blocks, Vec2i position) {
super(connection); super(connection);
this.blocks = blocks; this.blocks = blocks;
this.chunkPosition = position; this.chunkPosition = position;
@ -40,7 +40,7 @@ public class MultiBlockChangeEvent extends PlayConnectionEvent {
this.chunkPosition = pkg.getChunkPosition(); this.chunkPosition = pkg.getChunkPosition();
} }
public HashMap<Vec3i, BlockState> getBlocks() { public Map<Vec3i, BlockState> getBlocks() {
return this.blocks; return this.blocks;
} }

View File

@ -62,6 +62,6 @@ class PacketBlockChange(buffer: PlayInByteBuffer) : PlayClientboundPacket() {
} }
override fun log() { override fun log() {
Log.protocol(String.format("[IN] Block change received at %s (block=%s)", blockPosition, block)) Log.protocol("[IN] Block change received (position=${blockPosition}, block=$block)")
} }
} }

View File

@ -12,76 +12,74 @@
*/ */
package de.bixilon.minosoft.protocol.packets.clientbound.play package de.bixilon.minosoft.protocol.packets.clientbound.play
import de.bixilon.minosoft.data.mappings.blocks.BlockState import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkSectionPosition import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkSectionPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight
import de.bixilon.minosoft.modding.event.events.MultiBlockChangeEvent import de.bixilon.minosoft.modding.event.events.MultiBlockChangeEvent
import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.packets.clientbound.PlayClientboundPacket import de.bixilon.minosoft.protocol.packets.clientbound.PlayClientboundPacket
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.Log
import glm_.vec2.Vec2i import glm_.vec2.Vec2i
import glm_.vec3.Vec3i import glm_.vec3.Vec3i
import java.util.*
class PacketMultiBlockChange() : PlayClientboundPacket() { class PacketMultiBlockChange(buffer: PlayInByteBuffer) : PlayClientboundPacket() {
val blocks = HashMap<Vec3i, BlockState?>() val blocks: MutableMap<Vec3i, BlockState?> = mutableMapOf()
lateinit var chunkPosition: Vec2i var chunkPosition: Vec2i
private set private set
constructor(buffer: PlayInByteBuffer) : this() { init {
if (buffer.versionId < ProtocolVersions.V_14W26C) { when {
chunkPosition = if (buffer.versionId < ProtocolVersions.V_1_7_5) { buffer.versionId < ProtocolVersions.V_14W26C -> {
Vec2i(buffer.readVarInt(), buffer.readVarInt()) chunkPosition = if (buffer.versionId < ProtocolVersions.V_1_7_5) {
} else { Vec2i(buffer.readVarInt(), buffer.readVarInt())
buffer.readChunkPosition() } else {
buffer.readChunkPosition()
}
val count = buffer.readShort()
val dataSize = buffer.readInt()
check(dataSize == count * 4) { "MultiBlockChangePacket needs 4 bytes per block change!" }
for (i in 0 until count) {
val raw = buffer.readInt()
val meta = (raw and 0xF)
val blockId = (raw and 0xFFF0 ushr 4)
val y = (raw and 0xFF0000 ushr 16)
val z = (raw and 0x0F000000 ushr 24)
val x = (raw and -0x10000000 ushr 28)
blocks[Vec3i(x, y, z)] = buffer.connection.mapping.getBlockState((blockId shl 4) or meta)
}
} }
val count = buffer.readShort() buffer.versionId < ProtocolVersions.V_20W28A -> {
val dataSize = buffer.readInt() chunkPosition = Vec2i(buffer.readInt(), buffer.readInt())
check(dataSize == count * 4) { "MultiBlockChangePacket needs 4 bytes per block change!" } val count = buffer.readVarInt()
for (i in 0 until count) { for (i in 0 until count) {
val raw = buffer.readInt() val position = buffer.readByte().toInt()
val meta = (raw and 0xF) val y = buffer.readByte()
val blockId = (raw and 0xFFF0 ushr 4) val blockId = buffer.readVarInt()
val y = (raw and 0xFF0000 ushr 16) blocks[Vec3i(position and 0xF0 ushr 4 and 0xF, y.toInt(), position and 0xF)] = buffer.connection.mapping.getBlockState(blockId)
val z = (raw and 0x0F000000 ushr 24) }
val x = (raw and -0x10000000 ushr 28)
blocks[Vec3i(x, y, z)] = buffer.connection.mapping.getBlockState((blockId shl 4) or meta)
} }
return else -> {
} val rawPos = buffer.readLong()
if (buffer.versionId < ProtocolVersions.V_20W28A) { chunkPosition = Vec2i((rawPos shr 42).toInt(), (rawPos shl 22 shr 42).toInt())
chunkPosition = Vec2i(buffer.readInt(), buffer.readInt()) val yOffset = (rawPos.toInt() and 0xFFFFF) * ProtocolDefinition.SECTION_HEIGHT_Y
val count = buffer.readVarInt() if (buffer.versionId > ProtocolVersions.V_1_16_2_PRE3) {
for (i in 0 until count) { buffer.readBoolean() // ToDo
val position = buffer.readByte().toInt() }
val y = buffer.readByte() for (data in buffer.readVarLongArray()) {
val blockId = buffer.readVarInt() blocks[Vec3i((data shr 8 and 0x0F).toInt(), yOffset + (data and 0x0F).toInt(), (data shr 4 and 0xF).toInt())] = buffer.connection.mapping.getBlockState((data ushr 12).toInt())
blocks[Vec3i(position and 0xF0 ushr 4 and 0xF, y.toInt(), position and 0xF)] = buffer.connection.mapping.getBlockState(blockId) }
} }
return
} }
val rawPos = buffer.readLong()
chunkPosition = Vec2i((rawPos shr 42).toInt(), (rawPos shl 22 shr 42).toInt())
val yOffset = (rawPos.toInt() and 0xFFFFF) * 16
if (buffer.versionId > ProtocolVersions.V_1_16_2_PRE3) {
buffer.readBoolean() // ToDo
}
val count = buffer.readVarInt()
for (i in 0 until count) {
val data = buffer.readVarLong()
blocks[Vec3i((data shr 8 and 0xF).toInt(), yOffset + (data shr 4 and 0xF).toInt(), (data and 0xF).toInt())] = buffer.connection.mapping.getBlockState((data ushr 12).toInt())
}
return
} }
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
val chunk = connection.world.getChunk(chunkPosition) ?: return // thanks mojang val chunk = connection.world.getChunk(chunkPosition) ?: return // thanks mojang
if (!chunk.isFullyLoaded) { if (chunk.sections == null) {
return return
} }
connection.fireEvent(MultiBlockChangeEvent(connection, this)) connection.fireEvent(MultiBlockChangeEvent(connection, this))
@ -90,14 +88,14 @@ class PacketMultiBlockChange() : PlayClientboundPacket() {
// tweak // tweak
if (!connection.version.isFlattened()) { if (!connection.version.isFlattened()) {
for ((key, value) in blocks) { for ((key, value) in blocks) {
val block = VersionTweaker.transformBlock(value!!, chunk.sections!!, key.inChunkSectionPosition, key.sectionHeight) val block = VersionTweaker.transformBlock(value, chunk.sections!!, key.inChunkSectionPosition, key.sectionHeight)
if (block === value) { if (block === value) {
continue continue
} }
chunk.setBlockState(key, block) chunk.setBlockState(key, block)
} }
} }
val sectionHeights = HashSet<Int>() val sectionHeights: MutableSet<Int> = mutableSetOf()
for ((key) in blocks) { for ((key) in blocks) {
sectionHeights.add(key.sectionHeight) sectionHeights.add(key.sectionHeight)
} }
@ -107,6 +105,6 @@ class PacketMultiBlockChange() : PlayClientboundPacket() {
} }
override fun log() { override fun log() {
Log.protocol(String.format("[IN] Multi block change received at %s (size=%d)", chunkPosition, blocks.size)) Log.protocol("[IN] Multi block change received (chunkPosition=${chunkPosition}, count=${blocks.size})")
} }
} }

View File

@ -418,4 +418,16 @@ public class InByteBuffer {
public Vec2i readChunkPosition() { public Vec2i readChunkPosition() {
return new Vec2i(readInt(), readInt()); return new Vec2i(readInt(), readInt());
} }
public long[] readVarLongArray(int size) {
var ret = new long[size];
for (int i = 0; i < size; i++) {
ret[i] = readVarLong();
}
return ret;
}
public long[] readVarLongArray() {
return readVarLongArray(readVarInt());
}
} }