diff --git a/pom.xml b/pom.xml index edf4dcf..0251d97 100644 --- a/pom.xml +++ b/pom.xml @@ -39,8 +39,8 @@ com.nukkitx.protocol - bedrock-v390 - 2.5.5 + bedrock-v407 + 2.6.0-SNAPSHOT compile diff --git a/src/main/java/com/nukkitx/proxypass/ProxyPass.java b/src/main/java/com/nukkitx/proxypass/ProxyPass.java index 3da9c44..ffe7cef 100644 --- a/src/main/java/com/nukkitx/proxypass/ProxyPass.java +++ b/src/main/java/com/nukkitx/proxypass/ProxyPass.java @@ -6,15 +6,15 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; +import com.nukkitx.nbt.NBTInputStream; +import com.nukkitx.nbt.NBTOutputStream; import com.nukkitx.nbt.NbtUtils; -import com.nukkitx.nbt.stream.NBTInputStream; -import com.nukkitx.nbt.stream.NBTOutputStream; -import com.nukkitx.nbt.tag.Tag; import com.nukkitx.protocol.bedrock.BedrockClient; import com.nukkitx.protocol.bedrock.BedrockPacketCodec; import com.nukkitx.protocol.bedrock.BedrockServer; -import com.nukkitx.protocol.bedrock.v390.Bedrock_v390; +import com.nukkitx.protocol.bedrock.v407.Bedrock_v407; import com.nukkitx.proxypass.network.ProxyBedrockEventHandler; +import io.netty.util.ResourceLeakDetector; import lombok.AccessLevel; import lombok.Getter; import lombok.extern.log4j.Log4j2; @@ -37,7 +37,7 @@ public class ProxyPass { public static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); public static final YAMLMapper YAML_MAPPER = (YAMLMapper) new YAMLMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); public static final String MINECRAFT_VERSION; - public static final BedrockPacketCodec CODEC = Bedrock_v390.V390_CODEC; + public static final BedrockPacketCodec CODEC = Bedrock_v407.V407_CODEC; public static final int PROTOCOL_VERSION = CODEC.getProtocolVersion(); private static final DefaultPrettyPrinter PRETTY_PRINTER = new DefaultPrettyPrinter(); @@ -69,6 +69,7 @@ public class ProxyPass { private Path dataDir; public static void main(String[] args) { + ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.PARANOID); ProxyPass proxy = new ProxyPass(); try { proxy.boot(); @@ -145,17 +146,17 @@ public void shutdown() { } } - public void saveNBT(String dataName, Tag dataTag) { + public void saveNBT(String dataName, Object dataTag) { Path path = dataDir.resolve(dataName + ".dat"); try (OutputStream outputStream = Files.newOutputStream(path, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); NBTOutputStream nbtOutputStream = NbtUtils.createNetworkWriter(outputStream)){ - nbtOutputStream.write(dataTag); + nbtOutputStream.writeTag(dataTag); } catch (IOException e) { throw new RuntimeException(e); } } - public Tag loadNBT(String dataName) { + public Object loadNBT(String dataName) { Path path = dataDir.resolve(dataName + ".dat"); try (InputStream inputStream = Files.newInputStream(path); NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(inputStream)){ diff --git a/src/main/java/com/nukkitx/proxypass/network/bedrock/session/DownstreamPacketHandler.java b/src/main/java/com/nukkitx/proxypass/network/bedrock/session/DownstreamPacketHandler.java index 6f8aff1..727024b 100644 --- a/src/main/java/com/nukkitx/proxypass/network/bedrock/session/DownstreamPacketHandler.java +++ b/src/main/java/com/nukkitx/proxypass/network/bedrock/session/DownstreamPacketHandler.java @@ -3,13 +3,14 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.nimbusds.jwt.SignedJWT; -import com.nukkitx.nbt.stream.LittleEndianDataOutputStream; -import com.nukkitx.nbt.stream.NBTOutputStream; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.nbt.tag.ListTag; +import com.nukkitx.nbt.NBTOutputStream; +import com.nukkitx.nbt.NbtList; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtType; +import com.nukkitx.nbt.util.stream.LittleEndianDataOutputStream; import com.nukkitx.protocol.bedrock.BedrockClientSession; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.handler.BedrockPacketHandler; import com.nukkitx.protocol.bedrock.packet.*; import com.nukkitx.protocol.bedrock.util.EncryptionUtils; @@ -56,25 +57,25 @@ public boolean handle(ServerToClientHandshakePacket packet) { } public boolean handle(AvailableEntityIdentifiersPacket packet) { - proxy.saveNBT("entity_identifiers", packet.getTag()); + proxy.saveNBT("entity_identifiers", packet.getIdentifiers()); return false; } public boolean handle(BiomeDefinitionListPacket packet) { - proxy.saveNBT("biome_definitions", packet.getTag()); + proxy.saveNBT("biome_definitions", packet.getDefinitions()); return false; } public boolean handle(StartGamePacket packet) { Map legacyBlocks = new HashMap<>(); - for (CompoundTag entry : packet.getBlockPalette().getValue()) { + for (NbtMap entry : packet.getBlockPalette()) { legacyBlocks.putIfAbsent(entry.getCompound("block").getString("name"), (int) entry.getShort("id")); } proxy.saveJson("legacy_block_ids.json", sortMap(legacyBlocks)); - List palette = new ArrayList<>(packet.getBlockPalette().getValue()); + List palette = new ArrayList<>(packet.getBlockPalette()); palette.sort(Comparator.comparingInt(value -> value.getShort("id"))); - proxy.saveNBT("runtime_block_states", new ListTag<>("", CompoundTag.class, palette)); + proxy.saveNBT("runtime_block_states", new NbtList<>(NbtType.COMPOUND, palette)); BlockPaletteUtils.convertToJson(proxy, palette); List itemData = new ArrayList<>(); @@ -107,31 +108,42 @@ public boolean handle(DisconnectPacket packet) { return false; } - @Override - public boolean handle(InventoryContentPacket packet) { - if (packet.getContainerId() == ContainerId.CREATIVE) { - List entries = new ArrayList<>(); - for (ItemData data : packet.getContents()) { - int id = data.getId(); - Integer damage = data.getDamage() == 0 ? null : (int) data.getDamage(); - - CompoundTag tag = data.getTag(); - String tagData = null; - if (tag != null) { - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - try (NBTOutputStream stream = new NBTOutputStream(new LittleEndianDataOutputStream(byteArrayOutputStream))) { - stream.write(tag); - } catch (IOException e) { - throw new RuntimeException(e); - } - tagData = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()); + private void dumpCreativeItems(ItemData[] contents) { + List entries = new ArrayList<>(); + for (ItemData data : contents) { + int id = data.getId(); + Integer damage = data.getDamage() == 0 ? null : (int) data.getDamage(); + + NbtMap tag = data.getTag(); + String tagData = null; + if (tag != null) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + try (NBTOutputStream stream = new NBTOutputStream(new LittleEndianDataOutputStream(byteArrayOutputStream))) { + stream.writeTag(tag); + } catch (IOException e) { + throw new RuntimeException(e); } - entries.add(new CreativeItemEntry(id, damage, tagData)); + tagData = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()); } + entries.add(new CreativeItemEntry(id, damage, tagData)); + } - CreativeItems items = new CreativeItems(entries); + CreativeItems items = new CreativeItems(entries); - proxy.saveJson("creative_items.json", items); + proxy.saveJson("creative_items.json", items); + } + + @Override + public boolean handle(CreativeContentPacket packet) { + dumpCreativeItems(packet.getEntries().values().toArray(new ItemData[0])); + return false; + } + + // Pre 1.16 method of Creative Items + @Override + public boolean handle(InventoryContentPacket packet) { + if (packet.getContainerId() == ContainerId.CREATIVE) { + dumpCreativeItems(packet.getContents()); } return false; } diff --git a/src/main/java/com/nukkitx/proxypass/network/bedrock/session/ProxyPlayerSession.java b/src/main/java/com/nukkitx/proxypass/network/bedrock/session/ProxyPlayerSession.java index 269663b..a5fd088 100644 --- a/src/main/java/com/nukkitx/proxypass/network/bedrock/session/ProxyPlayerSession.java +++ b/src/main/java/com/nukkitx/proxypass/network/bedrock/session/ProxyPlayerSession.java @@ -5,11 +5,13 @@ import com.nukkitx.protocol.bedrock.BedrockPacket; import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.BedrockSession; +import com.nukkitx.protocol.bedrock.exception.PacketSerializeException; import com.nukkitx.protocol.bedrock.handler.BatchHandler; import com.nukkitx.protocol.bedrock.handler.BedrockPacketHandler; import com.nukkitx.protocol.bedrock.util.EncryptionUtils; import com.nukkitx.proxypass.ProxyPass; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; import lombok.AccessLevel; import lombok.Getter; import lombok.extern.log4j.Log4j2; @@ -131,14 +133,18 @@ public void handle(BedrockSession session, ByteBuf compressed, Collection ProxyPass.PROTOCOL_VERSION) { - status.setStatus(PlayStatusPacket.Status.FAILED_SERVER); + status.setStatus(PlayStatusPacket.Status.LOGIN_FAILED_SERVER_OLD); } else { - status.setStatus(PlayStatusPacket.Status.FAILED_CLIENT); + status.setStatus(PlayStatusPacket.Status.LOGIN_FAILED_CLIENT_OLD); } } session.setPacketCodec(ProxyPass.CODEC); @@ -126,7 +127,9 @@ public boolean handle(LoginPacket packet) { private void initializeProxySession() { log.debug("Initializing proxy session"); - proxy.newClient().connect(proxy.getTargetAddress()).whenComplete((downstream, throwable) -> { + BedrockClient client = proxy.newClient(); + client.setRakNetVersion(10); + client.connect(proxy.getTargetAddress()).whenComplete((downstream, throwable) -> { if (throwable != null) { log.error("Unable to connect to downstream server " + proxy.getTargetAddress(), throwable); return; @@ -153,8 +156,8 @@ private void initializeProxySession() { login.setProtocolVersion(ProxyPass.PROTOCOL_VERSION); downstream.sendPacketImmediately(login); - this.session.setBatchedHandler(proxySession.getUpstreamBatchHandler()); - downstream.setBatchedHandler(proxySession.getDownstreamTailHandler()); + this.session.setBatchHandler(proxySession.getUpstreamBatchHandler()); + downstream.setBatchHandler(proxySession.getDownstreamTailHandler()); downstream.setLogging(true); downstream.setPacketHandler(new DownstreamPacketHandler(downstream, proxySession, this.proxy)); diff --git a/src/main/java/com/nukkitx/proxypass/network/bedrock/util/BlockPaletteUtils.java b/src/main/java/com/nukkitx/proxypass/network/bedrock/util/BlockPaletteUtils.java index 43e9d99..886926c 100644 --- a/src/main/java/com/nukkitx/proxypass/network/bedrock/util/BlockPaletteUtils.java +++ b/src/main/java/com/nukkitx/proxypass/network/bedrock/util/BlockPaletteUtils.java @@ -1,8 +1,8 @@ package com.nukkitx.proxypass.network.bedrock.util; import com.fasterxml.jackson.annotation.JsonInclude; -import com.nukkitx.nbt.TagType; -import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtType; import com.nukkitx.proxypass.ProxyPass; import lombok.Value; @@ -13,23 +13,23 @@ public class BlockPaletteUtils { - public static void convertToJson(ProxyPass proxy, List tags) { + public static void convertToJson(ProxyPass proxy, List tags) { List palette = new ArrayList<>(tags.size()); - for (CompoundTag tag : tags) { + for (NbtMap tag : tags) { int id = tag.getShort("id"); - CompoundTag blockTag = tag.getCompound("block"); + NbtMap blockTag = tag.getCompound("block"); String name = blockTag.getString("name"); Map states = new LinkedHashMap<>(); - blockTag.getCompound("states").getValue().forEach((key, value) -> { - states.put(key, new BlockState(value.getValue(), TagType.byClass(value.getClass()).getId())); + blockTag.getCompound("states").forEach((key, value) -> { + states.put(key, new BlockState(value, NbtType.byClass(value.getClass()).getId())); }); Integer meta = null; - if (tag.contains("meta")) { + if (tag.containsKey("meta")) { meta = (int) tag.getShort("meta"); } palette.add(new Entry(id, meta, name, states)); diff --git a/src/main/java/com/nukkitx/proxypass/network/bedrock/util/RecipeUtils.java b/src/main/java/com/nukkitx/proxypass/network/bedrock/util/RecipeUtils.java index 154c337..e2c51c9 100644 --- a/src/main/java/com/nukkitx/proxypass/network/bedrock/util/RecipeUtils.java +++ b/src/main/java/com/nukkitx/proxypass/network/bedrock/util/RecipeUtils.java @@ -1,10 +1,10 @@ package com.nukkitx.proxypass.network.bedrock.util; import com.fasterxml.jackson.annotation.JsonInclude; +import com.nukkitx.nbt.NBTOutputStream; +import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtUtils; -import com.nukkitx.nbt.stream.NBTOutputStream; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.protocol.bedrock.data.*; +import com.nukkitx.protocol.bedrock.data.inventory.*; import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket; import com.nukkitx.proxypass.ProxyPass; import lombok.AllArgsConstructor; @@ -27,21 +27,21 @@ public static void writeRecipes(CraftingDataPacket packet, ProxyPass proxy) { for (CraftingData craftingData : packet.getCraftingData()) { CraftingDataEntry entry = new CraftingDataEntry(); - CraftingType type = craftingData.getType(); + CraftingDataType type = craftingData.getType(); entry.type = type.ordinal(); - if (type != CraftingType.MULTI) { + if (type != CraftingDataType.MULTI) { entry.block = craftingData.getCraftingTag(); } else { entry.uuid = craftingData.getUuid(); } - if (type == CraftingType.SHAPED || type == CraftingType.SHAPELESS || type == CraftingType.SHAPELESS_CHEMISTRY || type == CraftingType.SHULKER_BOX || type == CraftingType.SHAPED_CHEMISTRY) { + if (type == CraftingDataType.SHAPED || type == CraftingDataType.SHAPELESS || type == CraftingDataType.SHAPELESS_CHEMISTRY || type == CraftingDataType.SHULKER_BOX || type == CraftingDataType.SHAPED_CHEMISTRY) { entry.id = craftingData.getRecipeId(); entry.priority = craftingData.getPriority(); entry.output = writeItemArray(craftingData.getOutputs(), true); } - if (type == CraftingType.SHAPED || type == CraftingType.SHAPED_CHEMISTRY) { + if (type == CraftingDataType.SHAPED || type == CraftingDataType.SHAPED_CHEMISTRY) { int charCounter = 0; ItemData[] inputs = craftingData.getInputs(); @@ -81,11 +81,11 @@ public static void writeRecipes(CraftingDataPacket packet, ProxyPass proxy) { } entry.input = itemMap; } - if (type == CraftingType.SHAPELESS || type == CraftingType.SHAPELESS_CHEMISTRY || type == CraftingType.SHULKER_BOX) { + if (type == CraftingDataType.SHAPELESS || type == CraftingDataType.SHAPELESS_CHEMISTRY || type == CraftingDataType.SHULKER_BOX) { entry.input = writeItemArray(craftingData.getInputs(), false); } - if (type == CraftingType.FURNACE || type == CraftingType.FURNACE_DATA) { + if (type == CraftingDataType.FURNACE || type == CraftingDataType.FURNACE_DATA) { Integer damage = craftingData.getInputDamage(); if (damage == 0x7fff) damage = -1; if (damage == 0) damage = null; @@ -111,11 +111,11 @@ private static Item[] writeItemArray(ItemData[] inputs, boolean output) { return outputs.toArray(new Item[0]); } - private static String nbtToBase64(CompoundTag tag) { + private static String nbtToBase64(NbtMap tag) { if (tag != null) { ByteArrayOutputStream tagStream = new ByteArrayOutputStream(); try (NBTOutputStream writer = NbtUtils.createWriterLE(tagStream)) { - writer.write(tag); + writer.writeTag(tag); } catch (IOException e) { throw new RuntimeException(e); }