From da8bd8a6599bd6d945c903da03bb37c07ef5d053 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Mon, 30 Dec 2019 21:55:17 -0600 Subject: [PATCH] Actually fix signs and start on campfire/container translators Since signs are not sent as block (tile) entities in chunks when it comes to later Minecraft versions, caching and sending the signs after the chunk packet has been sent was the only way to fix this. Sign data sending has intentionally been delayed in JavaUpdateTileEntityTranslator in the event that a chunk takes a long time to send and the block entity data is sent first. --- .../network/translators/TranslatorsInit.java | 6 +- .../block/entity/BlockEntityTranslator.java | 19 ++-- .../ContainerBlockEntityTranslator.java | 92 +++++++++++++++++++ .../entity/EmptyBlockEntityTranslator.java | 8 +- .../entity/SignBlockEntityTranslator.java | 12 ++- .../translators/item/ItemTranslator.java | 8 ++ .../java/world/JavaChunkDataTranslator.java | 18 +++- .../world/JavaUpdateTileEntityTranslator.java | 23 +++-- .../connector/utils/BlockEntityUtils.java | 17 +++- .../geysermc/connector/utils/ChunkUtils.java | 53 ++++++----- .../connector/world/chunk/ChunkPosition.java | 14 +-- 11 files changed, 204 insertions(+), 66 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java 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 072b7aedb..477734d87 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 @@ -46,6 +46,7 @@ import lombok.Getter; import org.geysermc.connector.network.translators.bedrock.*; import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; +import org.geysermc.connector.network.translators.block.entity.ContainerBlockEntityTranslator; import org.geysermc.connector.network.translators.block.entity.EmptyBlockEntityTranslator; import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; import org.geysermc.connector.network.translators.inventory.GenericInventoryTranslator; @@ -174,8 +175,9 @@ public class TranslatorsInit { } private static void registerBlockEntityTranslators() { - blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator()); - blockEntityTranslators.put("Sign", new SignBlockEntityTranslator()); + blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator("empty", "Empty")); + blockEntityTranslators.put("Sign", new SignBlockEntityTranslator("minecraft:sign", "Sign")); + blockEntityTranslators.put("Campfire", new ContainerBlockEntityTranslator("minecraft:campfire", "Campfire")); } private static void registerInventoryTranslators() { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java index 61d3fd08d..e5e3a50d9 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java @@ -30,43 +30,48 @@ import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.Tag; -import org.geysermc.connector.utils.BlockEntityUtils; + +import lombok.AllArgsConstructor; import java.util.List; +@AllArgsConstructor public abstract class BlockEntityTranslator { + protected String javaId; + protected String bedrockId; + public abstract List> translateTag(CompoundTag tag); public abstract CompoundTag getDefaultJavaTag(int x, int y, int z); public abstract com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z); - public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(CompoundTag tag, String id) { + public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(CompoundTag tag) { int x = Integer.parseInt(String.valueOf(tag.getValue().get("x").getValue())); int y = Integer.parseInt(String.valueOf(tag.getValue().get("y").getValue())); int z = Integer.parseInt(String.valueOf(tag.getValue().get("z").getValue())); - CompoundTagBuilder tagBuilder = getConstantBedrockTag(id, x, y, z).toBuilder(); + CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); translateTag(tag).forEach(tagBuilder::tag); return tagBuilder.buildRootTag(); } - protected CompoundTag getConstantJavaTag(String id, int x, int y, int z) { + protected CompoundTag getConstantJavaTag(int x, int y, int z) { CompoundTag tag = new CompoundTag(""); tag.put(new IntTag("x", x)); tag.put(new IntTag("y", y)); tag.put(new IntTag("z", z)); - tag.put(new StringTag("id", id)); + tag.put(new StringTag("id", javaId)); return tag; } - protected com.nukkitx.nbt.tag.CompoundTag getConstantBedrockTag(String id, int x, int y, int z) { + protected com.nukkitx.nbt.tag.CompoundTag getConstantBedrockTag(int x, int y, int z) { CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() .intTag("x", x) .intTag("y", y) .intTag("z", z) - .stringTag("id", id); + .stringTag("id", bedrockId); return tagBuilder.buildRootTag(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java new file mode 100644 index 000000000..181683488 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.IntArrayTag; +import com.nukkitx.nbt.tag.Tag; + +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.item.ItemEntry; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ContainerBlockEntityTranslator extends BlockEntityTranslator { + + public ContainerBlockEntityTranslator(String javaId, String bedrockId) { + super(javaId, bedrockId); + } + + @Override + public List> translateTag(CompoundTag tag) { + List> tags = new ArrayList<>(); + ListTag items = tag.get("Items"); + List tagsList = new ArrayList<>(); + for (com.github.steveice10.opennbt.tag.builtin.Tag itemTag : items.getValue()) { + tagsList.add(getItem((CompoundTag) itemTag)); + } + + int[] fakeCookingTime = new int[4]; + Arrays.fill(fakeCookingTime, 3); + + com.nukkitx.nbt.tag.ListTag bedrockItems = + new com.nukkitx.nbt.tag.ListTag<>("Items", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); + tags.add(bedrockItems); + + tags.add(new IntArrayTag("CookingTimes", fakeCookingTime)); + tags.add(new IntArrayTag("CookingTotalTimes", fakeCookingTime)); + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(int x, int y, int z) { + CompoundTag tag = getConstantJavaTag(x, y, z); + tag.put(new ListTag("Items")); + return tag; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); + tagBuilder.listTag("Items", com.nukkitx.nbt.tag.CompoundTag.class, new ArrayList<>()); + return tagBuilder.buildRootTag(); + } + + protected com.nukkitx.nbt.tag.CompoundTag getItem(CompoundTag tag) { + ItemEntry entry = TranslatorsInit.getItemTranslator().getItemEntry((String) tag.get("id").getValue()); + CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() + .shortTag("id", (short) entry.getBedrockId()) + .byteTag("Count", (byte) tag.get("Count").getValue()) + .shortTag("Damage", (short) entry.getBedrockData()) + .byteTag("Slot", (byte) tag.get("Slot").getValue()) + .tag(CompoundTagBuilder.builder().build("tag")); + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java index 927337bc1..700b50dbc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java @@ -33,6 +33,10 @@ import java.util.List; public class EmptyBlockEntityTranslator extends BlockEntityTranslator { + public EmptyBlockEntityTranslator(String javaId, String bedrockId) { + super(javaId, bedrockId); + } + @Override public List> translateTag(CompoundTag tag) { return new ArrayList<>(); @@ -40,11 +44,11 @@ public class EmptyBlockEntityTranslator extends BlockEntityTranslator { @Override public CompoundTag getDefaultJavaTag(int x, int y, int z) { - return getConstantJavaTag("empty", x, y, z); + return getConstantJavaTag(x, y, z); } @Override public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { - return getConstantBedrockTag("Empty", x, y, z); + return getConstantBedrockTag(x, y, z); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java index 182eedd99..7029143bb 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java @@ -28,9 +28,9 @@ package org.geysermc.connector.network.translators.block.entity; import com.github.steveice10.mc.protocol.data.message.Message; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.ByteTag; import com.nukkitx.nbt.tag.StringTag; import com.nukkitx.nbt.tag.Tag; + import org.geysermc.connector.utils.MessageUtils; import java.util.ArrayList; @@ -38,6 +38,10 @@ import java.util.List; public class SignBlockEntityTranslator extends BlockEntityTranslator { + public SignBlockEntityTranslator(String javaId, String bedrockId) { + super(javaId, bedrockId); + } + @Override public List> translateTag(CompoundTag tag) { List> tags = new ArrayList<>(); @@ -53,13 +57,12 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator { + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line4)) )); - tags.add(new ByteTag("isMovable", (byte) 0)); return tags; } @Override public CompoundTag getDefaultJavaTag(int x, int y, int z) { - CompoundTag tag = getConstantJavaTag("minecraft:sign", x, y, z); + CompoundTag tag = getConstantJavaTag(x, y, z); tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text1", "{\"text\":\"\"}")); tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text2", "{\"text\":\"\"}")); tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text3", "{\"text\":\"\"}")); @@ -69,9 +72,8 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator { @Override public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag("Sign", x, y, z).toBuilder(); + CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); tagBuilder.stringTag("Text", ""); - tagBuilder.byteTag("isMovable", (byte) 0); return tagBuilder.buildRootTag(); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 204210598..22f2c9f15 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -41,6 +41,7 @@ import com.github.steveice10.opennbt.tag.builtin.ShortTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.protocol.bedrock.data.ItemData; + import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.utils.MessageUtils; import org.geysermc.connector.utils.Toolbox; @@ -52,6 +53,8 @@ import java.util.Map; public class ItemTranslator { + private Map javaIdentifierMap = new HashMap<>(); + public ItemStack translateToJava(ItemData data) { ItemEntry javaItem = getItem(data); @@ -89,6 +92,11 @@ public class ItemTranslator { return ItemEntry.AIR; } + public ItemEntry getItemEntry(String javaIdentifier) { + return javaIdentifierMap.computeIfAbsent(javaIdentifier, key -> Toolbox.ITEM_ENTRIES.values() + .stream().filter(itemEntry -> itemEntry.getJavaIdentifier().equals(key)).findFirst().orElse(null)); + } + private CompoundTag translateToJavaNBT(com.nukkitx.nbt.tag.CompoundTag tag) { CompoundTag javaTag = new CompoundTag(tag.getName()); Map javaValue = javaTag.getValue(); 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 index 1c83579a5..c7c9af5b1 100644 --- 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 @@ -1,5 +1,7 @@ package org.geysermc.connector.network.translators.java.world; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket; import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3f; @@ -9,9 +11,13 @@ import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.network.VarInts; import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; + import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; + import org.geysermc.api.Geyser; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -22,7 +28,6 @@ public class JavaChunkDataTranslator extends PacketTranslator { Vector2i chunkPos = session.getLastChunkPosition(); Vector3f position = session.getPlayerEntity().getPosition(); @@ -33,7 +38,6 @@ public class JavaChunkDataTranslator extends PacketTranslator blockEntityEntry : chunkData.signs.int2ObjectEntrySet()) { + int x = blockEntityEntry.getValue().getAsInt("x"); + int y = blockEntityEntry.getValue().getAsInt("y"); + int z = blockEntityEntry.getValue().getAsInt("z"); + + ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntKey()), new Position(x, y, z)); + } + chunkData.signs.clear(); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java index 2b55e27e0..206011040 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java @@ -26,26 +26,29 @@ package org.geysermc.connector.network.translators.java.world; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateTileEntityPacket; -import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; + import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; import org.geysermc.connector.utils.BlockEntityUtils; +import java.util.concurrent.TimeUnit; + public class JavaUpdateTileEntityTranslator extends PacketTranslator { @Override public void translate(ServerUpdateTileEntityPacket packet, GeyserSession session) { - BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket(); - blockEntityPacket.setBlockPosition(Vector3i.from(packet.getPosition().getX(), - packet.getPosition().getY(), - packet.getPosition().getZ()) - ); - String id = BlockEntityUtils.getBedrockBlockEntityId(packet.getType().name()); BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(id); - blockEntityPacket.setData(translator.getBlockEntityTag(packet.getNbt(), id)); - session.getUpstream().sendPacket(blockEntityPacket); + if (id.equalsIgnoreCase("Sign")) { + // Delay so chunks can finish sending + session.getConnector().getGeneralThreadPool().schedule(() -> + BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(packet.getNbt()), packet.getPosition()), + 5, + TimeUnit.SECONDS + ); + } else { + BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(packet.getNbt()), packet.getPosition()); + } } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java index 6fb62b552..f610f2717 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -1,5 +1,10 @@ package org.geysermc.connector.utils; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; + +import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; @@ -10,8 +15,9 @@ public class BlockEntityUtils { if (id.contains("piston_head")) return "PistonArm"; - id = id.replace("minecraft:", ""); - id = id.replace("_", " "); + id = id.toLowerCase() + .replace("minecraft:", "") + .replace("_", " "); String[] words = id.split(" "); for (int i = 0; i < words.length; i++) { words[i] = words[i].substring(0, 1).toUpperCase() + words[i].substring(1).toLowerCase(); @@ -29,4 +35,11 @@ public class BlockEntityUtils { return blockEntityTranslator; } + + public static void updateBlockEntity(GeyserSession session, com.nukkitx.nbt.tag.CompoundTag blockEntity, Position position) { + BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket(); + blockEntityPacket.setBlockPosition(Vector3i.from(position.getX(), position.getY(), position.getZ())); + blockEntityPacket.setData(blockEntity); + session.getUpstream().sendPacket(blockEntityPacket); + } } 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 cf2146259..0059b5233 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -3,35 +3,31 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.chunk.Chunk; import com.github.steveice10.mc.protocol.data.game.chunk.Column; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockChangeRecord; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; -import org.geysermc.connector.console.GeyserLogger; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.BlockEntry; import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; -import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; +import org.geysermc.connector.world.chunk.ChunkPosition; import org.geysermc.connector.world.chunk.ChunkSection; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - public class ChunkUtils { public static ChunkData translateToBedrock(Column column) { ChunkData chunkData = new ChunkData(); - Chunk[] chunks = column.getChunks(); - int chunkSectionCount = chunks.length; - chunkData.sections = new ChunkSection[chunkSectionCount]; + chunkData.sections = new ChunkSection[chunks.length]; - List blockEntities = new ArrayList<>(Arrays.asList(column.getTileEntities())); - for (int chunkY = 0; chunkY < chunkSectionCount; chunkY++) { + CompoundTag[] blockEntities = column.getTileEntities(); + for (int chunkY = 0; chunkY < chunks.length; chunkY++) { chunkData.sections[chunkY] = new ChunkSection(); Chunk chunk = chunks[chunkY]; @@ -39,15 +35,17 @@ public class ChunkUtils { continue; ChunkSection section = chunkData.sections[chunkY]; - for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { BlockState blockState = chunk.get(x, y, z); BlockEntry block = TranslatorsInit.getBlockTranslator().getBlockEntry(blockState); - - section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), - block.getBedrockRuntimeId()); + if (block.getJavaIdentifier().contains("sign[")) { + Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); + chunkData.signs.put(block.getJavaId(), TranslatorsInit.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag(pos.getX(), pos.getY(), pos.getZ())); + } else { + section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), block.getBedrockRuntimeId()); + } if (block.isWaterlogged()) { BlockEntry water = TranslatorsInit.getBlockTranslator().getBlockEntry("minecraft:water[level=0]"); @@ -58,17 +56,20 @@ public class ChunkUtils { } } - List bedrockBlockEntities = new ArrayList<>(); - for (CompoundTag tag : blockEntities) { - Tag idTag = tag.get("id"); - if (idTag == null && !tag.contains("Sign")) { + com.nukkitx.nbt.tag.CompoundTag[] bedrockBlockEntities = new com.nukkitx.nbt.tag.CompoundTag[blockEntities.length]; + for (int i = 0; i < bedrockBlockEntities.length; i++) { + CompoundTag tag = blockEntities[i]; + String tagName; + if (!tag.contains("id")) { GeyserLogger.DEFAULT.debug("Got tag with no id: " + tag.getValue()); - continue; + tagName = "Empty"; + } else { + tagName = (String) tag.get("id").getValue(); } - String id = idTag == null ? "Sign" : BlockEntityUtils.getBedrockBlockEntityId((String) idTag.getValue()); + String id = BlockEntityUtils.getBedrockBlockEntityId(tagName); BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(id); - bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(tag, id)); + bedrockBlockEntities[i] = blockEntityTranslator.getBlockEntityTag(tag); } chunkData.blockEntities = bedrockBlockEntities; @@ -102,6 +103,8 @@ public class ChunkUtils { public ChunkSection[] sections; public byte[] biomes = new byte[256]; - public List blockEntities = new ArrayList<>(); + public com.nukkitx.nbt.tag.CompoundTag[] blockEntities = new com.nukkitx.nbt.tag.CompoundTag[0]; + + public Int2ObjectMap signs = new Int2ObjectOpenHashMap<>(); } } diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java b/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java index 86da2da4f..4af2bcc2f 100644 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java +++ b/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java @@ -18,17 +18,9 @@ public class ChunkPosition { } public Position getChunkBlock(int x, int y, int z) { - int chunkX = x % 16; - int chunkY = y % 16; - int chunkZ = z % 16; - - if (chunkX < 0) - chunkX = -chunkX; - if (chunkY < 0) - chunkY = -chunkY; - if (chunkZ < 0) - chunkZ = -chunkZ; - + int chunkX = x & 15; + int chunkY = y & 15; + int chunkZ = z & 15; return new Position(chunkX, chunkY, chunkZ); } }