Fix anvils for 1.18.30 Bedrock

This commit is contained in:
Camotoy 2022-04-20 21:39:35 -04:00
parent e923325246
commit 575fe98c0f
No known key found for this signature in database
GPG Key ID: 7EEFB66FE798081F
4 changed files with 69 additions and 29 deletions

View File

@ -26,8 +26,14 @@
package org.geysermc.geyser.inventory;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ItemUtils;
import javax.annotation.Nullable;
/**
* Used to determine if rename packets should be sent and stores
@ -48,6 +54,7 @@ public class AnvilContainer extends Container {
/**
* The new name of the item as received from Bedrock
*/
@Nullable
private String newName = null;
private GeyserItemStack lastInput = GeyserItemStack.EMPTY;
@ -59,6 +66,36 @@ public class AnvilContainer extends Container {
super(title, id, size, containerType, playerInventory);
}
/**
* @return the name to use instead for renaming.
*/
public String checkForRename(GeyserSession session, String rename) {
String correctRename;
newName = rename;
String originalName = ItemUtils.getCustomName(getInput().getNbt());
String plainOriginalName = MessageTranslator.convertToPlainText(originalName, session.getLocale());
String plainNewName = MessageTranslator.convertToPlainText(rename, session.getLocale());
if (!plainOriginalName.equals(plainNewName)) {
// Strip out formatting since Java Edition does not allow it
correctRename = plainNewName;
// Java Edition sends a packet every time an item is renamed even slightly in GUI. Fortunately, this works out for us now
ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(plainNewName);
session.sendDownstreamPacket(renameItemPacket);
} else {
// Restore formatting for item since we're not renaming
correctRename = MessageTranslator.convertMessageLenient(originalName);
// Java Edition sends the original custom name when not renaming,
// if there isn't a custom name an empty string is sent
ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(plainOriginalName);
session.sendDownstreamPacket(renameItemPacket);
}
useJavaLevelCost = false;
return correctRename;
}
public GeyserItemStack getInput() {
return getItem(0);
}

View File

@ -384,19 +384,19 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
if (enchantTag.get("id") instanceof StringTag javaEnchId) {
JavaEnchantment enchantment = JavaEnchantment.getByJavaIdentifier(javaEnchId.getValue());
if (enchantment == null) {
GeyserImpl.getInstance().getLogger().debug("Unknown java enchantment: " + javaEnchId.getValue());
GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment in anvil: " + javaEnchId.getValue());
continue;
}
Tag javaEnchLvl = enchantTag.get("lvl");
if (!(javaEnchLvl instanceof ShortTag || javaEnchLvl instanceof IntTag))
if (javaEnchLvl == null || !(javaEnchLvl.getValue() instanceof Number number))
continue;
// Handle duplicate enchantments
if (bedrock) {
enchantments.putIfAbsent(enchantment, ((Number) javaEnchLvl.getValue()).intValue());
enchantments.putIfAbsent(enchantment, number.intValue());
} else {
enchantments.mergeInt(enchantment, ((Number) javaEnchLvl.getValue()).intValue(), Math::max);
enchantments.mergeInt(enchantment, number.intValue(), Math::max);
}
}
}

View File

@ -27,7 +27,12 @@ package org.geysermc.geyser.translator.inventory;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
import com.nukkitx.protocol.bedrock.data.inventory.ItemStackRequest;
import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData;
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.CraftRecipeOptionalStackRequestActionData;
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionData;
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionType;
import com.nukkitx.protocol.bedrock.packet.ItemStackResponsePacket;
import org.geysermc.geyser.inventory.AnvilContainer;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
@ -35,12 +40,34 @@ import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.updater.AnvilInventoryUpdater;
import java.util.Objects;
public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator {
public AnvilInventoryTranslator() {
super(3, "minecraft:anvil[facing=north]", com.nukkitx.protocol.bedrock.data.inventory.ContainerType.ANVIL, AnvilInventoryUpdater.INSTANCE,
"minecraft:chipped_anvil", "minecraft:damaged_anvil");
}
@Override
protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) {
return action.getType() == StackRequestActionType.CRAFT_RECIPE_OPTIONAL;
}
@Override
protected ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
// Guarded by shouldHandleRequestFirst check
CraftRecipeOptionalStackRequestActionData data = (CraftRecipeOptionalStackRequestActionData) request.getActions()[0];
AnvilContainer container = (AnvilContainer) inventory;
// Required as of 1.18.30 - FilterTextPackets no longer appear to be sent
String name = request.getFilterStrings()[data.getFilteredStringIndex()];
if (!Objects.equals(name, container.getNewName())) {
container.checkForRename(session, name);
}
return super.translateRequest(session, inventory, request);
}
@Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) {
return switch (slotInfoData.getContainer()) {

View File

@ -25,15 +25,12 @@
package org.geysermc.geyser.translator.protocol.bedrock;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
import com.nukkitx.protocol.bedrock.packet.FilterTextPacket;
import org.geysermc.geyser.inventory.AnvilContainer;
import org.geysermc.geyser.inventory.CartographyContainer;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ItemUtils;
/**
* Used to send strings to the server and filter out unwanted words.
@ -50,28 +47,7 @@ public class BedrockFilterTextTranslator extends PacketTranslator<FilterTextPack
}
packet.setFromServer(true);
if (session.getOpenInventory() instanceof AnvilContainer anvilContainer) {
anvilContainer.setNewName(packet.getText());
String originalName = ItemUtils.getCustomName(anvilContainer.getInput().getNbt());
String plainOriginalName = MessageTranslator.convertToPlainText(originalName, session.getLocale());
String plainNewName = MessageTranslator.convertToPlainText(packet.getText(), session.getLocale());
if (!plainOriginalName.equals(plainNewName)) {
// Strip out formatting since Java Edition does not allow it
packet.setText(plainNewName);
// Java Edition sends a packet every time an item is renamed even slightly in GUI. Fortunately, this works out for us now
ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(plainNewName);
session.sendDownstreamPacket(renameItemPacket);
} else {
// Restore formatting for item since we're not renaming
packet.setText(MessageTranslator.convertMessageLenient(originalName));
// Java Edition sends the original custom name when not renaming,
// if there isn't a custom name an empty string is sent
ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(plainOriginalName);
session.sendDownstreamPacket(renameItemPacket);
}
anvilContainer.setUseJavaLevelCost(false);
packet.setText(anvilContainer.checkForRename(session, packet.getText()));
session.getInventoryTranslator().updateSlot(session, anvilContainer, 1);
}
session.sendUpstreamPacket(packet);