diff --git a/build.gradle.kts b/build.gradle.kts index 4da7ee8..6d3dec3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } group = "org.powernukkitx.anyversion" -version = "2.8.3" +version = "2.8.4" java { toolchain { diff --git a/src/main/java/org/powernukkitx/anyversion/handler/handlers/CameraAimAssistPresetsHandler.java b/src/main/java/org/powernukkitx/anyversion/handler/handlers/CameraAimAssistPresetsHandler.java new file mode 100644 index 0000000..95ec362 --- /dev/null +++ b/src/main/java/org/powernukkitx/anyversion/handler/handlers/CameraAimAssistPresetsHandler.java @@ -0,0 +1,19 @@ +package org.powernukkitx.anyversion.handler.handlers; + +import org.cloudburstmc.protocol.bedrock.data.camera.CameraAimAssistPresetDefinition; +import org.cloudburstmc.protocol.bedrock.packet.CameraAimAssistPresetsPacket; +import org.powernukkitx.anyversion.handler.PacketHandler; +import org.powernukkitx.anyversion.manager.ProtocolPlayer; +import org.powernukkitx.anyversion.utils.ProtocolVersion; + +public class CameraAimAssistPresetsHandler extends PacketHandler { + + @Override + public void handle(ProtocolPlayer player, CameraAimAssistPresetsPacket packet) { + for (CameraAimAssistPresetDefinition preset : packet.getPresets()) { + if (preset.getCategories() == null) { + preset.setCategories(""); + } + } + } +} diff --git a/src/main/java/org/powernukkitx/anyversion/handler/handlers/CraftingDataHandler.java b/src/main/java/org/powernukkitx/anyversion/handler/handlers/CraftingDataHandler.java index a003ba0..4399aad 100644 --- a/src/main/java/org/powernukkitx/anyversion/handler/handlers/CraftingDataHandler.java +++ b/src/main/java/org/powernukkitx/anyversion/handler/handlers/CraftingDataHandler.java @@ -4,18 +4,21 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; -import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.CraftingDataEntryType; -import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.*; -import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.DefaultDescriptor; import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptor; -import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount; +import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.NameDescriptor; +import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.RecipeIngredient; +import org.cloudburstmc.protocol.bedrock.data.payload.crafting.FurnaceRecipePayload; +import org.cloudburstmc.protocol.bedrock.data.payload.crafting.ShapedRecipePayload; +import org.cloudburstmc.protocol.bedrock.data.payload.crafting.ShapelessRecipePayload; +import org.cloudburstmc.protocol.bedrock.data.payload.crafting.SmithingTransformRecipePayload; +import org.cloudburstmc.protocol.bedrock.data.payload.crafting.SmithingTrimRecipePayload; import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket; import org.powernukkitx.anyversion.handler.PacketHandler; import org.powernukkitx.anyversion.manager.ProtocolPlayer; import org.powernukkitx.anyversion.registries.Registries; import org.powernukkitx.anyversion.utils.ProtocolVersion; -import java.util.ArrayList; +import java.util.Iterator; import java.util.List; public class CraftingDataHandler extends PacketHandler { @@ -24,83 +27,165 @@ public class CraftingDataHandler extends PacketHandler { @Override public void handle(ProtocolPlayer player, CraftingDataPacket packet) { - List craftingData = new ArrayList<>(packet.getCraftingEntries()); - packet.getCraftingEntries().clear(); - recipe: - for (CraftingDataEntry uncast : craftingData) { - CraftingDataEntry result = uncast; - if (uncast instanceof GridCraftingDataEntry data) { - ObjectArrayList ingredients = new ObjectArrayList<>(); - ObjectArrayList results = new ObjectArrayList<>(); - for (ItemDescriptorWithCount descriptor : data.getIngredientList()) { - ItemDescriptorWithCount itemDescriptor = translateItemDescriptorWithCount(player.getVersion(), descriptor); - if (itemDescriptor == null) continue recipe; - ingredients.add(itemDescriptor); - } - for (ItemData itemData : data.getProductionList()) { - ItemData downgrade = Registries.ITEM.downgrade(player.getVersion(), itemData); - if (downgrade.getDefinition().getIdentifier().equals(Registries.ITEM.getOutdated(downgrade).getDefinition().getIdentifier())) continue recipe; - results.add(downgrade); - } - if (data instanceof ShapedRecipe shaped) { - result = ShapedRecipe.of(shaped.getType(), shaped.getRecipeUniqueId(), shaped.getRecipeWidth(), shaped.getRecipeHeight(), ingredients, results, shaped.getRecipeID(), shaped.getRecipeTag(), shaped.getPriority(), shaped.getNetId(), shaped.isAssumeSymmetry(), shaped.getUnlockingRequirement()); - } else if (data instanceof ShapelessRecipe shapeless) { - if (FURNACE_TAGS.contains(shapeless.getRecipeTag()) && player.getVersion().protocol() < ProtocolVersion.MINECRAFT_PE_1_26_20.protocol()) { - int inputId = org.powernukkitx.registry.Registries.ITEM_RUNTIMEID.getInt(ingredients.getFirst().toItem().getDefinition().getIdentifier()); - ItemData resultItem = data.getProductionList().getFirst(); - Item item = Item.get(org.powernukkitx.registry.Registries.ITEM_RUNTIMEID.getIdentifier(inputId)); - if (item == null) continue recipe; - ItemData itemData = ItemData.builder().definition(new SimpleItemDefinition(item.getId(), item.getRuntimeId(), false)).build(); - ItemData downgrade = Registries.ITEM.downgrade(player.getVersion(), itemData); - if (downgrade.getDefinition().getIdentifier().equals(Registries.ITEM.getOutdated(downgrade).getDefinition().getIdentifier())) continue recipe; - inputId = downgrade.getDefinition().getRuntimeId(); - resultItem = Registries.ITEM.downgrade(player.getVersion(), resultItem); - if (resultItem.getDefinition().getIdentifier().equals(Registries.ITEM.getOutdated(resultItem).getDefinition().getIdentifier())) continue recipe; - result = FurnaceRecipe.of(CraftingDataEntryType.FURNACE_RECIPE, inputId, 0, resultItem, shapeless.getRecipeTag()); - } else { - result = ShapelessRecipe.of(shapeless.getType(), shapeless.getRecipeUniqueId(), ingredients, results, shapeless.getRecipeID(), shapeless.getRecipeTag(), shapeless.getPriority(), shapeless.getNetId(), shapeless.getUnlockingRequirement()); - } + ProtocolVersion version = player.getVersion(); + + // Furnace recipes are downgraded first so that the ones synthesized from + // shapeless recipes below are not processed a second time. + packet.getFurnaceRecipes().removeIf(recipe -> !translateFurnaceRecipe(version, recipe)); + + processShapedRecipes(version, packet.getShapedRecipes()); + processShapedRecipes(version, packet.getShapedChemistryRecipes()); + + processShapelessRecipes(player, packet, packet.getShapelessRecipes()); + processShapelessRecipes(player, packet, packet.getShapelessChemistryRecipes()); + processShapelessRecipes(player, packet, packet.getUserDataShapelessRecipes()); + + packet.getSmithingTrimRecipes().removeIf(recipe -> !translateSmithingTrimRecipe(version, recipe)); + packet.getSmithingTransformRecipes().removeIf(recipe -> !translateSmithingTransformRecipe(version, recipe)); + } + + private void processShapedRecipes(ProtocolVersion version, List recipes) { + recipes.removeIf(recipe -> !translateGrid(version, recipe.getIngredients(), recipe.getResults())); + } + + private void processShapelessRecipes(ProtocolPlayer player, CraftingDataPacket packet, List recipes) { + ProtocolVersion version = player.getVersion(); + Iterator iterator = recipes.iterator(); + while (iterator.hasNext()) { + ShapelessRecipePayload recipe = iterator.next(); + + List ingredients = translateIngredients(version, recipe.getIngredients()); + if (ingredients == null) { + iterator.remove(); + continue; + } + List results = downgradeResults(version, recipe.getResults()); + if (results == null) { + iterator.remove(); + continue; + } + + if (FURNACE_TAGS.contains(recipe.getTag()) && version.protocol() < ProtocolVersion.MINECRAFT_PE_1_26_20.protocol()) { + // Older protocols expect furnace recipes to be sent as furnace entries rather than shapeless ones. + FurnaceRecipePayload furnace = toFurnaceRecipe(version, ingredients.getFirst(), recipe.getResults().getFirst(), recipe.getTag()); + iterator.remove(); + if (furnace != null) { + packet.getFurnaceRecipes().add(furnace); } - } else if (uncast instanceof FurnaceRecipe data) { - int inputId = data.getInputId(); - int damage = data.getInputData(); - ItemData resultItem = data.getResultItem(); - Item item = Item.get(org.powernukkitx.registry.Registries.ITEM_RUNTIMEID.getIdentifier(inputId)); - if (item == null) continue recipe; - ItemData itemData = ItemData.builder().definition(new SimpleItemDefinition(item.getId(), item.getRuntimeId(), false)).build(); - ItemData downgrade = Registries.ITEM.downgrade(player.getVersion(), itemData); - if (downgrade.getDefinition().getIdentifier().equals(Registries.ITEM.getOutdated(downgrade).getDefinition().getIdentifier())) continue recipe; - inputId = downgrade.getDefinition().getRuntimeId(); - damage = downgrade.getDamage(); - resultItem = Registries.ITEM.downgrade(player.getVersion(), resultItem); - if (resultItem.getDefinition().getIdentifier().equals(Registries.ITEM.getOutdated(resultItem).getDefinition().getIdentifier())) continue recipe; - result = FurnaceRecipe.of(data.getType(), inputId, damage, resultItem, data.getRecipeTag()); - } else if (uncast instanceof SmithingTrimRecipe data) { - ItemDescriptorWithCount base = translateItemDescriptorWithCount(player.getVersion(), data.getBaseIngredient()); - ItemDescriptorWithCount addition = translateItemDescriptorWithCount(player.getVersion(), data.getAdditionIngredient()); - ItemDescriptorWithCount template = translateItemDescriptorWithCount(player.getVersion(), data.getTemplateIngredient()); - if (base == null || addition == null || template == null) continue recipe; - result = SmithingTrimRecipe.of(data.getRecipeUniqueId(), base, addition, template, data.getRecipeTag(), data.getNetId()); - } else if (uncast instanceof SmithingTransformRecipe data) { - ItemDescriptorWithCount base = translateItemDescriptorWithCount(player.getVersion(), data.getBaseIngredient()); - ItemDescriptorWithCount addition = translateItemDescriptorWithCount(player.getVersion(), data.getAdditionIngredient()); - ItemDescriptorWithCount template = translateItemDescriptorWithCount(player.getVersion(), data.getTemplateIngredient()); - ItemData downgrade = Registries.ITEM.downgrade(player.getVersion(), data.getResult()); - if (base == null || addition == null || template == null || downgrade.getDefinition().getIdentifier().equals(Registries.ITEM.getOutdated(downgrade).getDefinition().getIdentifier())) continue recipe; - result = SmithingTransformRecipe.of(data.getRecipeUniqueId(), base, addition, template, downgrade, data.getRecipeTag(), data.getNetId()); + } else { + replace(recipe.getIngredients(), ingredients); + replace(recipe.getResults(), results); } - packet.getCraftingEntries().add(result); } } - protected ItemDescriptorWithCount translateItemDescriptorWithCount(ProtocolVersion version, ItemDescriptorWithCount descriptor) { - ItemDescriptor itemDescriptor = descriptor.getDescriptor(); - if (itemDescriptor instanceof DefaultDescriptor defaultDescriptor) { - ItemData itemData = itemDescriptor.toItem().build(); + private FurnaceRecipePayload toFurnaceRecipe(ProtocolVersion version, RecipeIngredient input, ItemData result, String tag) { + int inputId = org.powernukkitx.registry.Registries.ITEM_RUNTIMEID.getInt(input.toItem().getDefinition().getIdentifier()); + Item item = Item.get(org.powernukkitx.registry.Registries.ITEM_RUNTIMEID.getIdentifier(inputId)); + if (item == null) return null; + ItemData itemData = ItemData.builder().definition(new SimpleItemDefinition(item.getId(), item.getRuntimeId(), false)).build(); + ItemData downgrade = Registries.ITEM.downgrade(version, itemData); + if (isDropped(downgrade)) return null; + ItemData resultItem = Registries.ITEM.downgrade(version, result); + if (isDropped(resultItem)) return null; + + FurnaceRecipePayload payload = new FurnaceRecipePayload(); + payload.setInputId(downgrade.getDefinition().getRuntimeId()); + payload.setAuxValue(-1); + payload.setResult(resultItem); + payload.setTag(tag); + return payload; + } + + private boolean translateFurnaceRecipe(ProtocolVersion version, FurnaceRecipePayload recipe) { + Item item = Item.get(org.powernukkitx.registry.Registries.ITEM_RUNTIMEID.getIdentifier(recipe.getInputId())); + if (item == null) return false; + ItemData itemData = ItemData.builder().definition(new SimpleItemDefinition(item.getId(), item.getRuntimeId(), false)).build(); + ItemData downgrade = Registries.ITEM.downgrade(version, itemData); + if (isDropped(downgrade)) return false; + ItemData resultItem = Registries.ITEM.downgrade(version, recipe.getResult()); + if (isDropped(resultItem)) return false; + + recipe.setInputId(downgrade.getDefinition().getRuntimeId()); + // A non-aux furnace recipe keeps its auxValue at -1; only aux recipes carry a damage value. + if (recipe.getAuxValue() != -1) { + recipe.setAuxValue(downgrade.getDamage()); + } + recipe.setResult(resultItem); + return true; + } + + private boolean translateSmithingTrimRecipe(ProtocolVersion version, SmithingTrimRecipePayload recipe) { + RecipeIngredient base = translateIngredient(version, recipe.getBaseIngredient()); + RecipeIngredient addition = translateIngredient(version, recipe.getAdditionIngredient()); + RecipeIngredient template = translateIngredient(version, recipe.getTemplateIngredient()); + if (base == null || addition == null || template == null) return false; + recipe.setBaseIngredient(base); + recipe.setAdditionIngredient(addition); + recipe.setTemplateIngredient(template); + return true; + } + + private boolean translateSmithingTransformRecipe(ProtocolVersion version, SmithingTransformRecipePayload recipe) { + RecipeIngredient base = translateIngredient(version, recipe.getBaseIngredient()); + RecipeIngredient addition = translateIngredient(version, recipe.getAdditionIngredient()); + RecipeIngredient template = translateIngredient(version, recipe.getTemplateIngredient()); + ItemData result = Registries.ITEM.downgrade(version, recipe.getResult()); + if (base == null || addition == null || template == null || isDropped(result)) return false; + recipe.setBaseIngredient(base); + recipe.setAdditionIngredient(addition); + recipe.setTemplateIngredient(template); + recipe.setResult(result); + return true; + } + + private boolean translateGrid(ProtocolVersion version, List ingredients, List results) { + List translatedIngredients = translateIngredients(version, ingredients); + if (translatedIngredients == null) return false; + List downgradedResults = downgradeResults(version, results); + if (downgradedResults == null) return false; + replace(ingredients, translatedIngredients); + replace(results, downgradedResults); + return true; + } + + private List translateIngredients(ProtocolVersion version, List ingredients) { + ObjectArrayList translated = new ObjectArrayList<>(); + for (RecipeIngredient ingredient : ingredients) { + RecipeIngredient result = translateIngredient(version, ingredient); + if (result == null) return null; + translated.add(result); + } + return translated; + } + + private List downgradeResults(ProtocolVersion version, List results) { + ObjectArrayList downgraded = new ObjectArrayList<>(); + for (ItemData itemData : results) { + ItemData downgrade = Registries.ITEM.downgrade(version, itemData); + if (isDropped(downgrade)) return null; + downgraded.add(downgrade); + } + return downgraded; + } + + protected RecipeIngredient translateIngredient(ProtocolVersion version, RecipeIngredient ingredient) { + ItemDescriptor descriptor = ingredient.getDescriptor(); + if (descriptor instanceof NameDescriptor nameDescriptor) { + ItemData itemData = descriptor.toItem().build(); ItemData downgrade = Registries.ITEM.downgrade(version, itemData); - if (downgrade.getDefinition().getIdentifier().equals(Registries.ITEM.getOutdated(downgrade).getDefinition().getIdentifier())) return null; - itemDescriptor = new DefaultDescriptor(downgrade.getDefinition(), defaultDescriptor.getAuxValue()); + if (isDropped(downgrade)) return null; + descriptor = new NameDescriptor(downgrade.getDefinition(), nameDescriptor.getAuxValue()); } - return new ItemDescriptorWithCount(itemDescriptor, descriptor.getCount()); + return new RecipeIngredient(descriptor, ingredient.getStackSize()); + } + + private boolean isDropped(ItemData downgrade) { + return downgrade.getDefinition().getIdentifier().equals(Registries.ITEM.getOutdated(downgrade).getDefinition().getIdentifier()); + } + + private void replace(List target, List replacement) { + target.clear(); + target.addAll(replacement); } } diff --git a/src/main/java/org/powernukkitx/anyversion/handler/handlers/CreativeContentHandler.java b/src/main/java/org/powernukkitx/anyversion/handler/handlers/CreativeContentHandler.java index ab58133..cdab4dc 100644 --- a/src/main/java/org/powernukkitx/anyversion/handler/handlers/CreativeContentHandler.java +++ b/src/main/java/org/powernukkitx/anyversion/handler/handlers/CreativeContentHandler.java @@ -1,7 +1,8 @@ package org.powernukkitx.anyversion.handler.handlers; -import org.cloudburstmc.protocol.bedrock.data.inventory.CreativeItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.cloudburstmc.protocol.bedrock.data.payload.creative.CreativeGroupInfoPayload; +import org.cloudburstmc.protocol.bedrock.data.payload.creative.CreativeItemEntryPayload; import org.cloudburstmc.protocol.bedrock.packet.CreativeContentPacket; import org.powernukkitx.anyversion.handler.PacketHandler; import org.powernukkitx.anyversion.manager.ProtocolPlayer; @@ -14,26 +15,29 @@ public class CreativeContentHandler extends PacketHandler @Override public void handle(ProtocolPlayer player, CreativeContentPacket packet) { - List c = new ArrayList<>(packet.getContents()); - packet.getContents().clear(); - for(CreativeItemData data : c) { + List c = new ArrayList<>(packet.getEntries()); + packet.getEntries().clear(); + for(CreativeItemEntryPayload data : c) { if (data.getItemInstance().getDefinition() == null) { - packet.getContents().add(data); + packet.getEntries().add(data); continue; } ItemData itemData = Registries.ITEM.downgrade(player.getVersion(), data.getItemInstance()); if(itemData.getDefinition() == null || Registries.ITEM.getOutdated(itemData).getDefinition() == null) { - packet.getContents().add(data); + packet.getEntries().add(data); continue; } if(itemData.getDefinition().getIdentifier().equals(Registries.ITEM.getOutdated(itemData).getDefinition().getIdentifier())) continue; - CreativeItemData newData = CreativeItemData.builder() - .itemInstance(itemData) - .creativeNetId(data.getCreativeNetId()) - .groupIndex(data.getGroupIndex()) - .build(); - packet.getContents().add(newData); + CreativeItemEntryPayload newData = new CreativeItemEntryPayload(); + newData.setItemInstance(itemData); + newData.setCreativeNetId(data.getCreativeNetId()); + newData.setGroupIndex(data.getGroupIndex()); + packet.getEntries().add(newData); } - } -} + for(CreativeGroupInfoPayload data : packet.getGroups()) { + ItemData itemData = Registries.ITEM.downgrade(player.getVersion(), data.getGroupIconItem()); + data.setGroupIconItem(itemData); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/powernukkitx/anyversion/handler/handlers/StartGameHandler.java b/src/main/java/org/powernukkitx/anyversion/handler/handlers/StartGameHandler.java index 0ed80fe..3d8ca98 100644 --- a/src/main/java/org/powernukkitx/anyversion/handler/handlers/StartGameHandler.java +++ b/src/main/java/org/powernukkitx/anyversion/handler/handlers/StartGameHandler.java @@ -10,7 +10,7 @@ import org.powernukkitx.registry.ItemRuntimeIdRegistry; import org.powernukkitx.registry.Registries; import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; +import org.cloudburstmc.protocol.bedrock.data.ServerBlockProperty; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -36,10 +36,6 @@ public void handle(ProtocolPlayer player, StartGamePacket packet) { packet.getSettings().setWorldId(""); packet.getSettings().setScenarioId(""); packet.getSettings().setOwnerId(""); - packet.setServerID(""); - packet.setWorldID(""); - packet.setScenarioID(""); - packet.setOwnerID(""); } if(player.protocol() < ProtocolVersion.MINECRAFT_PE_1_21_130.protocol()) { @@ -75,7 +71,7 @@ public void handle(ProtocolPlayer player, StartGamePacket packet) { } } } - packet.getBlockProperties().add(new BlockPropertyData(definition.identifier(), InventoryTransactionHandler.deepcopy(nbt))); + packet.getBlockProperties().add(new ServerBlockProperty(definition.identifier(), InventoryTransactionHandler.deepcopy(nbt))); } } diff --git a/src/main/java/org/powernukkitx/anyversion/manager/ProtocolManager.java b/src/main/java/org/powernukkitx/anyversion/manager/ProtocolManager.java index f03bd0e..32c1c4b 100644 --- a/src/main/java/org/powernukkitx/anyversion/manager/ProtocolManager.java +++ b/src/main/java/org/powernukkitx/anyversion/manager/ProtocolManager.java @@ -22,7 +22,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.extern.slf4j.Slf4j; import org.cloudburstmc.protocol.bedrock.data.auth.PlayerAuthenticationType; -import org.cloudburstmc.protocol.bedrock.data.skin.SerializedSkin; +import org.cloudburstmc.protocol.bedrock.data.skin.Skin; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.cloudburstmc.protocol.bedrock.data.DisconnectFailReason; import org.cloudburstmc.protocol.bedrock.data.PacketCompressionAlgorithm; @@ -235,7 +235,7 @@ private void handleLenient(LoginPacket packet, PlayerSessionHolder holder, Serve try { final ChainValidationResult result = validateChainOrToken(packet, type); - if (xboxAuthRequired && (!result.signed() && !server.getSettings().baseSettings().waterdogpe())) { + if (xboxAuthRequired && !result.signed()) { holder.disconnect(notAuthenticated); return; } @@ -330,7 +330,7 @@ private LenientClientJwt validateClientJwtLenient(LoginPacket packet, PublicKey return null; } - final SerializedSkin skin; + final Skin skin; try { skin = ClientSkinData.readSkin(claims); } catch (RuntimeException e) { @@ -370,7 +370,7 @@ private void enableEncryption(ChainValidationResult.IdentityClaims claims, Playe } } - private record LenientClientJwt(ClientChainData chain, SerializedSkin skin) { } + private record LenientClientJwt(ClientChainData chain, Skin skin) { } private static void padChainClaims(JwtClaims claims) { putIfAbsent(claims, "CompatibleWithClientSideChunkGen", Boolean.FALSE); diff --git a/src/main/java/org/powernukkitx/anyversion/registries/registries/PacketHandlerRegistry.java b/src/main/java/org/powernukkitx/anyversion/registries/registries/PacketHandlerRegistry.java index 866e152..94501fc 100644 --- a/src/main/java/org/powernukkitx/anyversion/registries/registries/PacketHandlerRegistry.java +++ b/src/main/java/org/powernukkitx/anyversion/registries/registries/PacketHandlerRegistry.java @@ -39,6 +39,7 @@ public void init() { HANDLERS.add(new LoginHandler()); HANDLERS.add(new SetEntityDataHandler()); HANDLERS.add(new UpdateSubChunkBlocksHandler()); + HANDLERS.add(new CameraAimAssistPresetsHandler()); HANDLERS.add(new TextHandler()); }