Initial support for 1.19.30 Bedrock

This commit is contained in:
Camotoy 2022-09-14 21:17:08 -04:00
parent 77827d5cf5
commit e64e12ff98
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
10 changed files with 66 additions and 41 deletions

View file

@ -31,7 +31,7 @@ object Versions {
const val gsonVersion = "2.3.1" // Provided by Spigot 1.8.8 const val gsonVersion = "2.3.1" // Provided by Spigot 1.8.8
const val nbtVersion = "2.1.0" const val nbtVersion = "2.1.0"
const val websocketVersion = "1.5.1" const val websocketVersion = "1.5.1"
const val protocolVersion = "0bd459f" const val protocolVersion = "f0feacd"
const val raknetVersion = "1.6.28-20220125.214016-6" const val raknetVersion = "1.6.28-20220125.214016-6"
const val mcauthlibVersion = "d9d773e" const val mcauthlibVersion = "d9d773e"
const val mcprotocollibversion = "9f78bd5" const val mcprotocollibversion = "9f78bd5"

View file

@ -30,7 +30,7 @@ dependencies {
// Network libraries // Network libraries
implementation("org.java-websocket", "Java-WebSocket", Versions.websocketVersion) implementation("org.java-websocket", "Java-WebSocket", Versions.websocketVersion)
api("com.github.CloudburstMC.Protocol", "bedrock-v544", Versions.protocolVersion) { api("com.github.CloudburstMC.Protocol", "bedrock-v553", Versions.protocolVersion) {
exclude("com.nukkitx.network", "raknet") exclude("com.nukkitx.network", "raknet")
exclude("com.nukkitx", "nbt") exclude("com.nukkitx", "nbt")
} }

View file

@ -28,6 +28,7 @@ package org.geysermc.geyser.network;
import com.nukkitx.protocol.bedrock.BedrockPong; import com.nukkitx.protocol.bedrock.BedrockPong;
import com.nukkitx.protocol.bedrock.BedrockServerEventHandler; import com.nukkitx.protocol.bedrock.BedrockServerEventHandler;
import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.BedrockServerSession;
import com.nukkitx.protocol.bedrock.v553.Bedrock_v553;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.DefaultEventLoopGroup; import io.netty.channel.DefaultEventLoopGroup;
@ -171,7 +172,7 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
@Override @Override
public void onSessionCreation(@Nonnull BedrockServerSession bedrockServerSession) { public void onSessionCreation(@Nonnull BedrockServerSession bedrockServerSession) {
try { try {
bedrockServerSession.setPacketCodec(GameProtocol.DEFAULT_BEDROCK_CODEC); bedrockServerSession.setPacketCodec(Bedrock_v553.V553_CODEC); // Has the RequestNetworkSettingsPacket
bedrockServerSession.setLogging(true); bedrockServerSession.setLogging(true);
bedrockServerSession.setCompressionLevel(geyser.getConfig().getBedrock().getCompressionLevel()); bedrockServerSession.setCompressionLevel(geyser.getConfig().getBedrock().getCompressionLevel());
bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(geyser, new GeyserSession(geyser, bedrockServerSession, eventLoopGroup.next()))); bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(geyser, new GeyserSession(geyser, bedrockServerSession, eventLoopGroup.next())));

View file

@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
import com.nukkitx.protocol.bedrock.v527.Bedrock_v527; import com.nukkitx.protocol.bedrock.v527.Bedrock_v527;
import com.nukkitx.protocol.bedrock.v534.Bedrock_v534; import com.nukkitx.protocol.bedrock.v534.Bedrock_v534;
import com.nukkitx.protocol.bedrock.v544.Bedrock_v544; import com.nukkitx.protocol.bedrock.v544.Bedrock_v544;
import com.nukkitx.protocol.bedrock.v553.Bedrock_v553;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import java.util.ArrayList; import java.util.ArrayList;
@ -71,6 +72,7 @@ public final class GameProtocol {
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder()
.minecraftVersion("1.19.21/1.19.22") .minecraftVersion("1.19.21/1.19.22")
.build()); .build());
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v553.V553_CODEC);
} }
/** /**

View file

@ -856,4 +856,11 @@ public class LoggingPacketHandler implements BedrockPacketHandler {
public boolean handle(FilterTextPacket packet) { public boolean handle(FilterTextPacket packet) {
return defaultHandler(packet); return defaultHandler(packet);
} }
// 1.19.30 new packet
@Override
public boolean handle(RequestNetworkSettingsPacket packet) {
return defaultHandler(packet);
}
} }

View file

@ -28,6 +28,7 @@ package org.geysermc.geyser.network;
import com.nukkitx.protocol.bedrock.BedrockPacket; import com.nukkitx.protocol.bedrock.BedrockPacket;
import com.nukkitx.protocol.bedrock.BedrockPacketCodec; import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
import com.nukkitx.protocol.bedrock.data.ExperimentData; import com.nukkitx.protocol.bedrock.data.ExperimentData;
import com.nukkitx.protocol.bedrock.data.PacketCompressionAlgorithm;
import com.nukkitx.protocol.bedrock.data.ResourcePackType; import com.nukkitx.protocol.bedrock.data.ResourcePackType;
import com.nukkitx.protocol.bedrock.packet.*; import com.nukkitx.protocol.bedrock.packet.*;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
@ -61,6 +62,20 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
return translateAndDefault(packet); return translateAndDefault(packet);
} }
@Override
public boolean handle(RequestNetworkSettingsPacket packet) {
// New since 1.19.30 - sent before login packet
PacketCompressionAlgorithm algorithm = PacketCompressionAlgorithm.ZLIB;
NetworkSettingsPacket responsePacket = new NetworkSettingsPacket();
responsePacket.setCompressionAlgorithm(algorithm);
responsePacket.setCompressionThreshold(512);
session.sendUpstreamPacketImmediately(responsePacket);
session.getUpstream().getSession().setCompression(algorithm);
return true;
}
@Override @Override
public boolean handle(LoginPacket loginPacket) { public boolean handle(LoginPacket loginPacket) {
if (geyser.isShuttingDown()) { if (geyser.isShuttingDown()) {

View file

@ -33,6 +33,7 @@ import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtUtils; import com.nukkitx.nbt.NbtUtils;
import com.nukkitx.protocol.bedrock.data.inventory.CraftingData; import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectArrayList;
@ -171,7 +172,7 @@ public class RecipeRegistryPopulator {
/* Convert end */ /* Convert end */
return CraftingData.fromShaped(uuid.toString(), shape.get(0).length(), shape.size(), return CraftingData.fromShaped(uuid.toString(), shape.get(0).length(), shape.size(),
inputs, Collections.singletonList(output), uuid, "crafting_table", 0, netId); inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId);
} }
List<ItemData> inputs = new ObjectArrayList<>(); List<ItemData> inputs = new ObjectArrayList<>();
for (JsonNode entry : node.get("inputs")) { for (JsonNode entry : node.get("inputs")) {
@ -191,10 +192,10 @@ public class RecipeRegistryPopulator {
if (type == 5) { if (type == 5) {
// Shulker box // Shulker box
return CraftingData.fromShulkerBox(uuid.toString(), return CraftingData.fromShulkerBox(uuid.toString(),
inputs, Collections.singletonList(output), uuid, "crafting_table", 0, netId); inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId);
} }
return CraftingData.fromShapeless(uuid.toString(), return CraftingData.fromShapeless(uuid.toString(),
inputs, Collections.singletonList(output), uuid, "crafting_table", 0, netId); inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId);
} }
private static ItemData getBedrockItemFromIdentifierJson(ItemMapping mapping, JsonNode itemNode) { private static ItemData getBedrockItemFromIdentifierJson(ItemMapping mapping, JsonNode itemNode) {

View file

@ -62,7 +62,8 @@ public final class SessionManager {
} }
public void removeSession(GeyserSession session) { public void removeSession(GeyserSession session) {
if (sessions.remove(session.getPlayerEntity().getUuid()) == null) { UUID uuid = session.getPlayerEntity().getUuid();
if (uuid == null || sessions.remove(uuid) == null) {
// Connection was likely pending // Connection was likely pending
pendingSessions.remove(session); pendingSessions.remove(session);
} }

View file

@ -34,9 +34,10 @@ import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeDa
import com.github.steveice10.mc.protocol.data.game.recipe.data.SmithingRecipeData; import com.github.steveice10.mc.protocol.data.game.recipe.data.SmithingRecipeData;
import com.github.steveice10.mc.protocol.data.game.recipe.data.StoneCuttingRecipeData; import com.github.steveice10.mc.protocol.data.game.recipe.data.StoneCuttingRecipeData;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateRecipesPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateRecipesPacket;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.protocol.bedrock.data.inventory.CraftingData; import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.data.inventory.descriptor.DefaultDescriptor;
import com.nukkitx.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount;
import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket; import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@ -99,8 +100,8 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
} }
// Strip NBT - tools won't appear in the recipe book otherwise // Strip NBT - tools won't appear in the recipe book otherwise
output = output.toBuilder().tag(null).build(); output = output.toBuilder().tag(null).build();
ItemData[][] inputCombinations = combinations(session, shapelessRecipeData.getIngredients()); ItemDescriptorWithCount[][] inputCombinations = combinations(session, shapelessRecipeData.getIngredients());
for (ItemData[] inputs : inputCombinations) { for (ItemDescriptorWithCount[] inputs : inputCombinations) {
UUID uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(), craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
Arrays.asList(inputs), Collections.singletonList(output), uuid, "crafting_table", 0, netId)); Arrays.asList(inputs), Collections.singletonList(output), uuid, "crafting_table", 0, netId));
@ -116,8 +117,8 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
} }
// See above // See above
output = output.toBuilder().tag(null).build(); output = output.toBuilder().tag(null).build();
ItemData[][] inputCombinations = combinations(session, shapedRecipeData.getIngredients()); ItemDescriptorWithCount[][] inputCombinations = combinations(session, shapedRecipeData.getIngredients());
for (ItemData[] inputs : inputCombinations) { for (ItemDescriptorWithCount[] inputs : inputCombinations) {
UUID uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(), craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(),
shapedRecipeData.getWidth(), shapedRecipeData.getHeight(), Arrays.asList(inputs), shapedRecipeData.getWidth(), shapedRecipeData.getHeight(), Arrays.asList(inputs),
@ -141,14 +142,14 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
SmithingRecipeData recipeData = (SmithingRecipeData) recipe.getData(); SmithingRecipeData recipeData = (SmithingRecipeData) recipe.getData();
ItemData output = ItemTranslator.translateToBedrock(session, recipeData.getResult()); ItemData output = ItemTranslator.translateToBedrock(session, recipeData.getResult());
for (ItemStack base : recipeData.getBase().getOptions()) { for (ItemStack base : recipeData.getBase().getOptions()) {
ItemData bedrockBase = ItemTranslator.translateToBedrock(session, base); ItemDescriptorWithCount bedrockBase = ItemDescriptorWithCount.fromItem(ItemTranslator.translateToBedrock(session, base));
for (ItemStack addition : recipeData.getAddition().getOptions()) { for (ItemStack addition : recipeData.getAddition().getOptions()) {
ItemData bedrockAddition = ItemTranslator.translateToBedrock(session, addition); ItemDescriptorWithCount bedrockAddition = ItemDescriptorWithCount.fromItem(ItemTranslator.translateToBedrock(session, addition));
UUID uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(), craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
Arrays.asList(bedrockBase, bedrockAddition), List.of(bedrockBase, bedrockAddition),
Collections.singletonList(output), uuid, "smithing_table", 2, netId++)); Collections.singletonList(output), uuid, "smithing_table", 2, netId++));
} }
} }
@ -178,6 +179,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
// As of 1.16.4, all stonecutter recipes have one ingredient option // As of 1.16.4, all stonecutter recipes have one ingredient option
ItemStack ingredient = stoneCuttingData.getIngredient().getOptions()[0]; ItemStack ingredient = stoneCuttingData.getIngredient().getOptions()[0];
ItemData input = ItemTranslator.translateToBedrock(session, ingredient); ItemData input = ItemTranslator.translateToBedrock(session, ingredient);
ItemDescriptorWithCount descriptor = ItemDescriptorWithCount.fromItem(input);
ItemStack javaOutput = stoneCuttingData.getResult(); ItemStack javaOutput = stoneCuttingData.getResult();
ItemData output = ItemTranslator.translateToBedrock(session, javaOutput); ItemData output = ItemTranslator.translateToBedrock(session, javaOutput);
if (input.equals(ItemData.AIR) || output.equals(ItemData.AIR)) { if (input.equals(ItemData.AIR) || output.equals(ItemData.AIR)) {
@ -188,7 +190,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
// We need to register stonecutting recipes so they show up on Bedrock // We need to register stonecutting recipes so they show up on Bedrock
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(), craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
Collections.singletonList(input), Collections.singletonList(output), uuid, "stonecutter", 0, netId)); Collections.singletonList(descriptor), Collections.singletonList(output), uuid, "stonecutter", 0, netId));
// Save the recipe list for reference when crafting // Save the recipe list for reference when crafting
// Add the net ID as the key and the button required + output for the value // Add the net ID as the key and the button required + output for the value
@ -209,19 +211,19 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
* *
* @return the Java ingredient list as an array that Bedrock can understand * @return the Java ingredient list as an array that Bedrock can understand
*/ */
private ItemData[][] combinations(GeyserSession session, Ingredient[] ingredients) { private ItemDescriptorWithCount[][] combinations(GeyserSession session, Ingredient[] ingredients) {
Map<Set<ItemData>, IntSet> squashedOptions = new HashMap<>(); Map<Set<ItemDescriptorWithCount>, IntSet> squashedOptions = new HashMap<>();
for (int i = 0; i < ingredients.length; i++) { for (int i = 0; i < ingredients.length; i++) {
if (ingredients[i].getOptions().length == 0) { if (ingredients[i].getOptions().length == 0) {
squashedOptions.computeIfAbsent(Collections.singleton(ItemData.AIR), k -> new IntOpenHashSet()).add(i); squashedOptions.computeIfAbsent(Collections.singleton(ItemDescriptorWithCount.EMPTY), k -> new IntOpenHashSet()).add(i);
continue; continue;
} }
Ingredient ingredient = ingredients[i]; Ingredient ingredient = ingredients[i];
Map<GroupedItem, List<ItemData>> groupedByIds = Arrays.stream(ingredient.getOptions()) Map<GroupedItem, List<ItemDescriptorWithCount>> groupedByIds = Arrays.stream(ingredient.getOptions())
.map(item -> ItemTranslator.translateToBedrock(session, item)) .map(item -> ItemDescriptorWithCount.fromItem(ItemTranslator.translateToBedrock(session, item)))
.collect(Collectors.groupingBy(item -> new GroupedItem(item.getId(), item.getCount(), item.getTag()))); .collect(Collectors.groupingBy(item -> new GroupedItem(((DefaultDescriptor) item.getDescriptor()).getItemId(), item.getCount())));
Set<ItemData> optionSet = new HashSet<>(groupedByIds.size()); Set<ItemDescriptorWithCount> optionSet = new HashSet<>(groupedByIds.size());
for (Map.Entry<GroupedItem, List<ItemData>> entry : groupedByIds.entrySet()) { for (Map.Entry<GroupedItem, List<ItemDescriptorWithCount>> entry : groupedByIds.entrySet()) {
if (entry.getValue().size() > 1) { if (entry.getValue().size() > 1) {
GroupedItem groupedItem = entry.getKey(); GroupedItem groupedItem = entry.getKey();
int idCount = 0; int idCount = 0;
@ -234,42 +236,38 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
if (entry.getValue().size() < idCount) { if (entry.getValue().size() < idCount) {
optionSet.addAll(entry.getValue()); optionSet.addAll(entry.getValue());
} else { } else {
optionSet.add(ItemData.builder() optionSet.add(new ItemDescriptorWithCount(new DefaultDescriptor(groupedItem.id, Short.MAX_VALUE), groupedItem.count));
.id(groupedItem.id)
.damage(Short.MAX_VALUE)
.count(groupedItem.count)
.tag(groupedItem.tag).build());
} }
} else { } else {
ItemData item = entry.getValue().get(0); ItemDescriptorWithCount item = entry.getValue().get(0);
optionSet.add(item); optionSet.add(item);
} }
} }
squashedOptions.computeIfAbsent(optionSet, k -> new IntOpenHashSet()).add(i); squashedOptions.computeIfAbsent(optionSet, k -> new IntOpenHashSet()).add(i);
} }
int totalCombinations = 1; int totalCombinations = 1;
for (Set<ItemData> optionSet : squashedOptions.keySet()) { for (Set<ItemDescriptorWithCount> optionSet : squashedOptions.keySet()) {
totalCombinations *= optionSet.size(); totalCombinations *= optionSet.size();
} }
if (totalCombinations > 500) { if (totalCombinations > 500) {
ItemData[] translatedItems = new ItemData[ingredients.length]; ItemDescriptorWithCount[] translatedItems = new ItemDescriptorWithCount[ingredients.length];
for (int i = 0; i < ingredients.length; i++) { for (int i = 0; i < ingredients.length; i++) {
if (ingredients[i].getOptions().length > 0) { if (ingredients[i].getOptions().length > 0) {
translatedItems[i] = ItemTranslator.translateToBedrock(session, ingredients[i].getOptions()[0]); translatedItems[i] = ItemDescriptorWithCount.fromItem(ItemTranslator.translateToBedrock(session, ingredients[i].getOptions()[0]));
} else { } else {
translatedItems[i] = ItemData.AIR; translatedItems[i] = ItemDescriptorWithCount.EMPTY;
} }
} }
return new ItemData[][]{translatedItems}; return new ItemDescriptorWithCount[][]{translatedItems};
} }
List<Set<ItemData>> sortedSets = new ArrayList<>(squashedOptions.keySet()); List<Set<ItemDescriptorWithCount>> sortedSets = new ArrayList<>(squashedOptions.keySet());
sortedSets.sort(Comparator.comparing(Set::size, Comparator.reverseOrder())); sortedSets.sort(Comparator.comparing(Set::size, Comparator.reverseOrder()));
ItemData[][] combinations = new ItemData[totalCombinations][ingredients.length]; ItemDescriptorWithCount[][] combinations = new ItemDescriptorWithCount[totalCombinations][ingredients.length];
int x = 1; int x = 1;
for (Set<ItemData> set : sortedSets) { for (Set<ItemDescriptorWithCount> set : sortedSets) {
IntSet slotSet = squashedOptions.get(set); IntSet slotSet = squashedOptions.get(set);
int i = 0; int i = 0;
for (ItemData item : set) { for (ItemDescriptorWithCount item : set) {
for (int j = 0; j < totalCombinations / set.size(); j++) { for (int j = 0; j < totalCombinations / set.size(); j++) {
final int comboIndex = (i * x) + (j % x) + ((j / x) * set.size() * x); final int comboIndex = (i * x) + (j % x) + ((j / x) * set.size() * x);
for (int slot : slotSet) { for (int slot : slotSet) {
@ -288,6 +286,5 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
private static class GroupedItem { private static class GroupedItem {
int id; int id;
int count; int count;
NbtMap tag;
} }
} }

View file

@ -31,6 +31,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.Cli
import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
import com.nukkitx.protocol.bedrock.data.inventory.CraftingData; import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount;
import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket; import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket;
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
@ -186,7 +187,7 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
uuid.toString(), uuid.toString(),
width, width,
height, height,
Arrays.asList(ingredients), Arrays.stream(ingredients).map(ItemDescriptorWithCount::fromItem).toList(),
Collections.singletonList(ItemTranslator.translateToBedrock(session, item)), Collections.singletonList(ItemTranslator.translateToBedrock(session, item)),
uuid, uuid,
"crafting_table", "crafting_table",