Fix empty chunk encoding

This commit is contained in:
Kevin Ludwig 2022-10-16 02:26:02 +02:00 committed by GitHub
parent 8bf8b22d6b
commit bd613987ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 31 additions and 32 deletions

View file

@ -99,6 +99,8 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
if (needsSpawnPacket) { if (needsSpawnPacket) {
// The player has yet to spawn so let's do that using some of the information in this Java packet // The player has yet to spawn so let's do that using some of the information in this Java packet
session.setDimension(newDimension); session.setDimension(newDimension);
session.setDimensionType(dimensions.get(newDimension));
ChunkUtils.loadDimension(session);
session.connect(); session.connect();
// It is now safe to send these packets // It is now safe to send these packets
@ -145,8 +147,5 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
// If the player is spawning into the "fake" nether, send them some fog // If the player is spawning into the "fake" nether, send them some fog
session.sendFog("minecraft:fog_hell"); session.sendFog("minecraft:fog_hell");
} }
session.setDimensionType(dimensions.get(newDimension));
ChunkUtils.loadDimension(session);
} }
} }

View file

@ -36,7 +36,6 @@ import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.DimensionUtils;
@Translator(packet = ClientboundRespawnPacket.class) @Translator(packet = ClientboundRespawnPacket.class)
@ -93,9 +92,6 @@ public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPa
} }
session.setWorldName(packet.getWorldName()); session.setWorldName(packet.getWorldName());
DimensionUtils.switchDimension(session, newDimension); DimensionUtils.switchDimension(session, newDimension);
session.setDimensionType(session.getDimensions().get(newDimension));
ChunkUtils.loadDimension(session);
} }
} }
} }

View file

@ -39,7 +39,6 @@ import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.NBTOutputStream; import com.nukkitx.nbt.NBTOutputStream;
import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtUtils; import com.nukkitx.nbt.NbtUtils;
import com.nukkitx.network.VarInts;
import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufAllocator;
@ -284,6 +283,9 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
} }
sectionCount++; sectionCount++;
// As of 1.18.30, the amount of biomes read is dependent on how high Bedrock thinks the dimension is
int biomeCount = bedrockDimension.height() >> 4;
// Estimate chunk size // Estimate chunk size
int size = 0; int size = 0;
for (int i = 0; i < sectionCount; i++) { for (int i = 0; i < sectionCount; i++) {
@ -294,9 +296,8 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
size += SERIALIZED_CHUNK_DATA.length; size += SERIALIZED_CHUNK_DATA.length;
} }
} }
size += ChunkUtils.EMPTY_CHUNK_DATA.length; // Consists only of biome data size += ChunkUtils.EMPTY_BIOME_DATA.length * biomeCount;
size += 1; // Border blocks size += 1; // Border blocks
size += 1; // Extra data length (always 0)
size += bedrockBlockEntities.size() * 64; // Conservative estimate of 64 bytes per tile entity size += bedrockBlockEntities.size() * 64; // Conservative estimate of 64 bytes per tile entity
// Allocate output buffer // Allocate output buffer
@ -310,8 +311,6 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
} }
} }
// As of 1.18.30, the amount of biomes read is dependent on how high Bedrock thinks the dimension is
int biomeCount = bedrockDimension.height() >> 4;
int dimensionOffset = bedrockDimension.minY() >> 4; int dimensionOffset = bedrockDimension.minY() >> 4;
for (int i = 0; i < biomeCount; i++) { for (int i = 0; i < biomeCount; i++) {
int biomeYOffset = dimensionOffset + i; int biomeYOffset = dimensionOffset + i;
@ -331,7 +330,6 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
} }
byteBuf.writeByte(0); // Border blocks - Edu edition only byteBuf.writeByte(0); // Border blocks - Edu edition only
VarInts.writeUnsignedInt(byteBuf, 0); // extra data length, 0 for now
// Encode tile entities into buffer // Encode tile entities into buffer
NBTOutputStream nbtStream = NbtUtils.createNetworkWriter(new ByteBufOutputStream(byteBuf)); NBTOutputStream nbtStream = NbtUtils.createNetworkWriter(new ByteBufOutputStream(byteBuf));

View file

@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket;
import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket;
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntLists; import it.unimi.dsi.fastutil.ints.IntLists;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
@ -54,10 +55,6 @@ public class ChunkUtils {
* An empty subchunk. * An empty subchunk.
*/ */
public static final byte[] SERIALIZED_CHUNK_DATA; public static final byte[] SERIALIZED_CHUNK_DATA;
/**
* An empty chunk that can be safely passed on to a LevelChunkPacket with subcounts set to 0.
*/
public static final byte[] EMPTY_CHUNK_DATA;
public static final byte[] EMPTY_BIOME_DATA; public static final byte[] EMPTY_BIOME_DATA;
static { static {
@ -81,20 +78,6 @@ public class ChunkUtils {
} finally { } finally {
byteBuf.release(); byteBuf.release();
} }
byteBuf = Unpooled.buffer();
try {
for (int i = 0; i < 32; i++) {
byteBuf.writeBytes(EMPTY_BIOME_DATA);
}
byteBuf.writeByte(0); // Border
EMPTY_CHUNK_DATA = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(EMPTY_CHUNK_DATA);
} finally {
byteBuf.release();
}
} }
public static int indexYZXtoXZY(int yzx) { public static int indexYZXtoXZY(int yzx) {
@ -185,11 +168,32 @@ public class ChunkUtils {
} }
public static void sendEmptyChunk(GeyserSession session, int chunkX, int chunkZ, boolean forceUpdate) { public static void sendEmptyChunk(GeyserSession session, int chunkX, int chunkZ, boolean forceUpdate) {
BedrockDimension bedrockDimension = session.getChunkCache().getBedrockDimension();
int bedrockSubChunkCount = bedrockDimension.height() >> 4;
byte[] payload;
// Allocate output buffer
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(ChunkUtils.EMPTY_BIOME_DATA.length * bedrockSubChunkCount + 1); // Consists only of biome data and border blocks
try {
byteBuf.writeBytes(EMPTY_BIOME_DATA);
for (int i = 1; i < bedrockSubChunkCount; i++) {
byteBuf.writeByte((127 << 1) | 1);
}
byteBuf.writeByte(0); // Border blocks - Edu edition only
payload = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(payload);
} finally {
byteBuf.release();
}
LevelChunkPacket data = new LevelChunkPacket(); LevelChunkPacket data = new LevelChunkPacket();
data.setChunkX(chunkX); data.setChunkX(chunkX);
data.setChunkZ(chunkZ); data.setChunkZ(chunkZ);
data.setSubChunksLength(0); data.setSubChunksLength(0);
data.setData(EMPTY_CHUNK_DATA); data.setData(payload);
data.setCachingEnabled(false); data.setCachingEnabled(false);
session.sendUpstreamPacket(data); session.sendUpstreamPacket(data);

View file

@ -94,6 +94,8 @@ public class DimensionUtils {
changeDimensionPacket.setPosition(pos); changeDimensionPacket.setPosition(pos);
session.sendUpstreamPacket(changeDimensionPacket); session.sendUpstreamPacket(changeDimensionPacket);
session.setDimension(javaDimension); session.setDimension(javaDimension);
session.setDimensionType(session.getDimensions().get(javaDimension));
ChunkUtils.loadDimension(session);
player.setPosition(pos); player.setPosition(pos);
session.setSpawned(false); session.setSpawned(false);
session.setLastChunkPosition(null); session.setLastChunkPosition(null);