diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index fcef782d..a2fb6ff2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -100,7 +100,7 @@ import org.geysermc.connector.network.translators.java.entity.spawn.JavaSpawnPla import org.geysermc.connector.network.translators.java.scoreboard.JavaDisplayScoreboardTranslator; import org.geysermc.connector.network.translators.java.scoreboard.JavaScoreboardObjectiveTranslator; import org.geysermc.connector.network.translators.java.scoreboard.JavaUpdateScoreTranslator; -import org.geysermc.connector.network.translators.java.world.JavaChunkDataPacket; +import org.geysermc.connector.network.translators.java.world.JavaChunkDataTranslator; import org.geysermc.connector.network.translators.java.world.JavaNotifyClientTranslator; import org.geysermc.connector.network.translators.java.window.JavaOpenWindowTranslator; import org.geysermc.connector.network.translators.java.window.JavaSetSlotTranslator; @@ -168,7 +168,7 @@ public class TranslatorsInit { Registry.registerJava(ServerPlayerHealthPacket.class, new JavaPlayerHealthTranslator()); Registry.registerJava(ServerNotifyClientPacket.class, new JavaNotifyClientTranslator()); - Registry.registerJava(ServerChunkDataPacket.class, new JavaChunkDataPacket()); + Registry.registerJava(ServerChunkDataPacket.class, new JavaChunkDataTranslator()); Registry.registerJava(ServerEntityDestroyPacket.class, new JavaEntityDestroyTranslator()); Registry.registerJava(ServerWindowItemsPacket.class, new JavaWindowItemsTranslator()); Registry.registerJava(ServerOpenWindowPacket.class, new JavaOpenWindowTranslator()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataPacket.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataPacket.java deleted file mode 100644 index a7656ed8..00000000 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataPacket.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.geysermc.connector.network.translators.java.world; - -import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket; -import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import org.geysermc.connector.console.GeyserLogger; -import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.PacketTranslator; -import org.geysermc.connector.utils.ChunkUtils; -import org.geysermc.connector.world.chunk.ChunkSection; - -public class JavaChunkDataPacket extends PacketTranslator { - - @Override - public void translate(ServerChunkDataPacket packet, GeyserSession session) { - - try { - byte[] buffer = new byte[32]; - ChunkUtils.ChunkData chunkData = ChunkUtils.translateToBedrock(packet.getColumn()); - - int count = 0; - ChunkSection[] sections = chunkData.sections; - for (int i = sections.length - 1; i >= 0; i--) { - if (sections[i].isEmpty()) - continue; - - count = i + 1; - break; - } - - for (int i = 0; i < count; i++) { - ChunkUtils.putBytes(count, buffer, new byte[]{(byte) 0}); - ChunkSection section = chunkData.sections[i]; - - ByteBuf byteBuf = Unpooled.buffer(); - section.writeToNetwork(byteBuf); - byte[] byteData = byteBuf.array(); - ChunkUtils.putBytes(count, buffer, byteData); - } - - LevelChunkPacket levelChunkPacket = new LevelChunkPacket(); - levelChunkPacket.setSubChunksLength(16); - levelChunkPacket.setCachingEnabled(true); - levelChunkPacket.setChunkX(packet.getColumn().getX()); - levelChunkPacket.setChunkZ(packet.getColumn().getZ()); - levelChunkPacket.setData(buffer); - session.getUpstream().sendPacket(levelChunkPacket); - } catch (Exception ex) { - ex.printStackTrace(); - } - - GeyserLogger.DEFAULT.info("Sent chunk packet!"); - } -} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java new file mode 100644 index 00000000..3b77619f --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -0,0 +1,59 @@ +package org.geysermc.connector.network.translators.java.world; + +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket; +import com.nukkitx.network.VarInts; +import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.geysermc.api.Geyser; +import org.geysermc.connector.console.GeyserLogger; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.utils.ChunkUtils; +import org.geysermc.connector.world.chunk.ChunkSection; + +public class JavaChunkDataTranslator extends PacketTranslator { + + @Override + public void translate(ServerChunkDataPacket packet, GeyserSession session) { + // Not sure if this is safe or not, however without this the client usually times out + Geyser.getConnector().getGeneralThreadPool().execute(() -> { + try { + ChunkUtils.ChunkData chunkData = ChunkUtils.translateToBedrock(packet.getColumn()); + ByteBuf byteBuf = Unpooled.buffer(32); + int count = 0; + ChunkSection[] sections = chunkData.sections; + for (int i = sections.length - 1; i >= 0; i--) { + if (sections[i].isEmpty()) + continue; + + count = i + 1; + break; + } + + for (int i = 0; i < count; i++) { + ChunkSection section = chunkData.sections[i]; + section.writeToNetwork(byteBuf); + } + + byteBuf.writeBytes(chunkData.biomes); // Biomes - 256 bytes + byteBuf.writeByte(0); // Border blocks - Edu edition only + VarInts.writeUnsignedInt(byteBuf, 0); // extra data length, 0 for now + + byte[] payload = new byte[byteBuf.writerIndex()]; + byteBuf.readBytes(payload); + + LevelChunkPacket levelChunkPacket = new LevelChunkPacket(); + levelChunkPacket.setSubChunksLength(count); + levelChunkPacket.setCachingEnabled(false); + levelChunkPacket.setChunkX(packet.getColumn().getX()); + levelChunkPacket.setChunkZ(packet.getColumn().getZ()); + levelChunkPacket.setData(payload); + session.getUpstream().sendPacket(levelChunkPacket); + } catch (Exception ex) { + ex.printStackTrace(); + } + GeyserLogger.DEFAULT.info("Sent chunk packet!"); + }); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 196adce8..9e7ad391 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -8,12 +8,8 @@ import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.item.BedrockItem; import org.geysermc.connector.world.chunk.ChunkSection; -import java.util.Arrays; - public class ChunkUtils { - private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; - public static ChunkData translateToBedrock(Column column) { ChunkData chunkData = new ChunkData(); chunkData.sections = new ChunkSection[16]; @@ -21,6 +17,7 @@ public class ChunkUtils { chunkData.sections[i] = new ChunkSection(); } + /* for (int y = 0; y < 256; y++) { int chunkY = y >> 4; @@ -37,55 +34,61 @@ public class ChunkUtils { BlockStorage storage = chunk.getBlocks(); for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { - BlockState block = storage.get(x, y & 0xF, z); + BlockState block = storage.get(x, chunkY, z); + if (block == null) + block = new BlockState(0); + BedrockItem bedrockBlock = TranslatorsInit.getItemTranslator().getBedrockBlock(block); ChunkSection section = chunkData.sections[chunkY]; - org.geysermc.connector.world.chunk.BlockStorage blockStorage = new org.geysermc.connector.world.chunk.BlockStorage(); - blockStorage.setFullBlock(ChunkSection.blockPosition(x, y, z), bedrockBlock.getId()); + //org.geysermc.connector.world.chunk.BlockStorage blockStorage = new org.geysermc.connector.world.chunk.BlockStorage(); + int runtimeId = GlobalBlockPalette.getOrCreateRuntimeId(bedrockBlock.getId(), bedrockBlock.getData()); + section.setFullBlock(x, y >> 4, z, 0, runtimeId << 2 | bedrockBlock.getData()); - section.getBlockStorageArray()[0] = blockStorage; - section.getBlockStorageArray()[1] = blockStorage; + //section.getBlockStorageArray()[0] = blockStorage; + //section.getBlockStorageArray()[1] = blockStorage; } } } + */ + + for (int chunkY = 0; chunkY < 16; chunkY++) { + Chunk chunk = null; + try { + chunk = column.getChunks()[chunkY]; + } catch (Exception ex) { + ex.printStackTrace(); + } + + if (chunk == null || chunk.isEmpty()) + continue; + + BlockStorage storage = chunk.getBlocks(); + ChunkSection section = chunkData.sections[chunkY]; + + section.getBlockStorageArray()[0] = new org.geysermc.connector.world.chunk.BlockStorage(); + section.getBlockStorageArray()[1] = new org.geysermc.connector.world.chunk.BlockStorage(); + + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + BlockState block = storage.get(x, y, z); + BedrockItem bedrockBlock = TranslatorsInit.getItemTranslator().getBedrockBlock(block); + + section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), bedrockBlock.getId() << 4 | bedrockBlock.getData()); + } + } + } + } return chunkData; } public static final class ChunkData { public ChunkSection[] sections; - } - public static void putBytes(int count, byte[] buffer, byte[] bytes) { - if (bytes == null) { - return; - } - - int minCapacity = count + bytes.length; - if ((minCapacity) - buffer.length > 0) { - int oldCapacity = buffer.length; - int newCapacity = oldCapacity << 1; - - if (newCapacity - minCapacity < 0) { - newCapacity = minCapacity; - } - - if (newCapacity - MAX_ARRAY_SIZE > 0) { - newCapacity = hugeCapacity(minCapacity); - } - - buffer = Arrays.copyOf(buffer, newCapacity); - } - - System.arraycopy(bytes, 0, buffer, count, bytes.length); - } - - private static int hugeCapacity(int minCapacity) { - if (minCapacity < 0) { // overflow - throw new OutOfMemoryError(); - } - return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; + public byte[] biomes = new byte[256]; + public byte[] blockEntities = new byte[0]; } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index d94d97f2..1447c572 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -40,7 +40,7 @@ public class Toolbox { ByteBuf b = Unpooled.buffer(); VarInts.writeUnsignedInt(b, entries.size()); for (Map e : entries) { - GlobalBlockPalette.registerMapping((int) e.get("id")); + GlobalBlockPalette.registerMapping((int) e.get("id") << 4 | (int) e.get("data")); BedrockUtils.writeString(b, (String) e.get("name")); b.writeShortLE((int) e.get("data")); b.writeShortLE((int) e.get("id"));