forked from GeyserMC/Geyser
Translate CanPlaceOn/CanDestroy NBT (#1253)
* Translate CanPlaceOn/CanDestroy NBT This commit adds support for the translation of the CanPlaceOn/CanDestroy NBT for Bedrock clients. * Remove debug line
This commit is contained in:
parent
9643b208f3
commit
26802e6dab
5 changed files with 79 additions and 25 deletions
|
@ -34,7 +34,6 @@ import com.nukkitx.nbt.NbtMap;
|
|||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
@ -102,13 +101,7 @@ public class ItemFrameEntity extends Entity {
|
|||
ItemEntry itemEntry = ItemRegistry.getItem((ItemStack) entityMetadata.getValue());
|
||||
NbtMapBuilder builder = NbtMap.builder();
|
||||
|
||||
String blockName = "";
|
||||
for (StartGamePacket.ItemEntry startGamePacketItemEntry : ItemRegistry.ITEMS) {
|
||||
if (startGamePacketItemEntry.getId() == (short) itemEntry.getBedrockId()) {
|
||||
blockName = startGamePacketItemEntry.getIdentifier();
|
||||
break;
|
||||
}
|
||||
}
|
||||
String blockName = ItemRegistry.getBedrockIdentifer(itemEntry);
|
||||
|
||||
builder.putByte("Count", (byte) itemData.getCount());
|
||||
if (itemData.getTag() != null) {
|
||||
|
|
|
@ -221,6 +221,23 @@ public class ItemRegistry {
|
|||
.stream().filter(itemEntry -> itemEntry.getJavaIdentifier().equals(key)).findFirst().orElse(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the Bedrock string identifier of an ItemEntry
|
||||
*
|
||||
* @param entry the ItemEntry to search for
|
||||
* @return the Bedrock identifier
|
||||
*/
|
||||
public static String getBedrockIdentifer(ItemEntry entry) {
|
||||
String blockName = "";
|
||||
for (StartGamePacket.ItemEntry startGamePacketItemEntry : ItemRegistry.ITEMS) {
|
||||
if (startGamePacketItemEntry.getId() == (short) entry.getBedrockId()) {
|
||||
blockName = startGamePacketItemEntry.getIdentifier(); // Find the Bedrock string name
|
||||
break;
|
||||
}
|
||||
}
|
||||
return blockName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Bedrock {@link ItemData} from a {@link JsonNode}
|
||||
* @param itemNode the JSON node that contains ProxyPass-compatible Bedrock item data
|
||||
|
|
|
@ -41,6 +41,7 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
|||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.ItemRemapper;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
||||
import org.geysermc.connector.utils.FileUtils;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.connector.utils.MessageUtils;
|
||||
|
@ -154,9 +155,43 @@ public abstract class ItemTranslator {
|
|||
itemData = DEFAULT_TRANSLATOR.translateToBedrock(itemStack, bedrockItem);
|
||||
}
|
||||
|
||||
if (nbt != null) {
|
||||
// Translate the canDestroy and canPlaceOn Java NBT
|
||||
ListTag canDestroy = nbt.get("CanDestroy");
|
||||
String[] canBreak = new String[0];
|
||||
ListTag canPlaceOn = nbt.get("CanPlaceOn");
|
||||
String[] canPlace = new String[0];
|
||||
canBreak = getCanModify(canDestroy, canBreak);
|
||||
canPlace = getCanModify(canPlaceOn, canPlace);
|
||||
itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), itemData.getTag(), canPlace, canBreak);
|
||||
}
|
||||
|
||||
return itemData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the Java NBT of canDestroy and canPlaceOn to its Bedrock counterparts.
|
||||
* In Java, this is treated as normal NBT, but in Bedrock, these arguments are extra parts of the item data itself.
|
||||
* @param canModifyJava the list of items in Java
|
||||
* @param canModifyBedrock the empty list of items in Bedrock
|
||||
* @return the new list of items in Bedrock
|
||||
*/
|
||||
private static String[] getCanModify(ListTag canModifyJava, String[] canModifyBedrock) {
|
||||
if (canModifyJava != null && canModifyJava.size() > 0) {
|
||||
canModifyBedrock = new String[canModifyJava.size()];
|
||||
for (int i = 0; i < canModifyBedrock.length; i++) {
|
||||
// Get the Java identifier of the block that can be placed
|
||||
String block = ((StringTag) canModifyJava.get(i)).getValue();
|
||||
// Sometimes this is done but it's still valid
|
||||
if (!block.startsWith("minecraft:")) block = "minecraft:" + block;
|
||||
// Get the Bedrock identifier of the item and replace it.
|
||||
// This will unfortunately be limited - for example, beds and banners will be translated weirdly
|
||||
canModifyBedrock[i] = BlockTranslator.getBedrockBlockIdentifier(block).replace("minecraft:", "");
|
||||
}
|
||||
}
|
||||
return canModifyBedrock;
|
||||
}
|
||||
|
||||
private static final ItemTranslator DEFAULT_TRANSLATOR = new ItemTranslator() {
|
||||
@Override
|
||||
public List<ItemEntry> getAppliedItems() {
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.connector.network.translators.item.translators.nbt;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.*;
|
||||
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.ItemRemapper;
|
||||
import org.geysermc.connector.network.translators.item.ItemEntry;
|
||||
|
@ -51,13 +50,7 @@ public class ShulkerBoxItemTranslator extends NbtItemStackTranslator {
|
|||
boxItemTag.put(new ByteTag("WasPickedUp", (byte) 0)); // ???
|
||||
|
||||
ItemEntry boxItemEntry = ItemRegistry.getItemEntry(((StringTag) itemData.get("id")).getValue());
|
||||
String blockName = "";
|
||||
for (StartGamePacket.ItemEntry startGamePacketItemEntry : ItemRegistry.ITEMS) {
|
||||
if (startGamePacketItemEntry.getId() == (short) boxItemEntry.getBedrockId()) {
|
||||
blockName = startGamePacketItemEntry.getIdentifier(); // Find the Bedrock string name
|
||||
break;
|
||||
}
|
||||
}
|
||||
String blockName = ItemRegistry.getBedrockIdentifer(boxItemEntry);
|
||||
|
||||
boxItemTag.put(new StringTag("Name", blockName));
|
||||
boxItemTag.put(new ShortTag("Damage", (short) boxItemEntry.getBedrockData()));
|
||||
|
|
|
@ -28,15 +28,12 @@ package org.geysermc.connector.network.translators.world.block;
|
|||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.nukkitx.nbt.NBTInputStream;
|
||||
import com.nukkitx.nbt.NbtList;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import com.nukkitx.nbt.NbtType;
|
||||
import com.nukkitx.nbt.NbtUtils;
|
||||
import com.nukkitx.nbt.*;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.network.translators.world.block.entity.BlockEntity;
|
||||
import org.geysermc.connector.utils.FileUtils;
|
||||
|
@ -52,6 +49,11 @@ public class BlockTranslator {
|
|||
|
||||
private static final Int2IntMap JAVA_TO_BEDROCK_BLOCK_MAP = new Int2IntOpenHashMap();
|
||||
private static final Int2IntMap BEDROCK_TO_JAVA_BLOCK_MAP = new Int2IntOpenHashMap();
|
||||
/**
|
||||
* Stores a list of differences in block identifiers.
|
||||
* Items will not be added to this list if the key and value is the same.
|
||||
*/
|
||||
private static final Object2ObjectMap<String, String> JAVA_TO_BEDROCK_IDENTIFIERS = new Object2ObjectOpenHashMap<>();
|
||||
private static final BiMap<String, Integer> JAVA_ID_BLOCK_MAP = HashBiMap.create();
|
||||
private static final IntSet WATERLOGGED = new IntOpenHashSet();
|
||||
private static final Object2IntMap<NbtMap> ITEM_FRAMES = new Object2IntOpenHashMap<>();
|
||||
|
@ -152,11 +154,11 @@ public class BlockTranslator {
|
|||
|
||||
// Used for adding all "special" Java block states to block state map
|
||||
String identifier;
|
||||
String bedrock_identifer = entry.getValue().get("bedrock_identifier").asText();
|
||||
String bedrockIdentifier = entry.getValue().get("bedrock_identifier").asText();
|
||||
for (Class<?> clazz : ref.getTypesAnnotatedWith(BlockEntity.class)) {
|
||||
identifier = clazz.getAnnotation(BlockEntity.class).regex();
|
||||
// Endswith, or else the block bedrock gets picked up for bed
|
||||
if (bedrock_identifer.endsWith(identifier) && !identifier.equals("")) {
|
||||
if (bedrockIdentifier.endsWith(identifier) && !identifier.equals("")) {
|
||||
JAVA_ID_TO_BLOCK_ENTITY_MAP.put(javaRuntimeId, clazz.getAnnotation(BlockEntity.class).name());
|
||||
break;
|
||||
}
|
||||
|
@ -164,9 +166,15 @@ public class BlockTranslator {
|
|||
|
||||
BlockStateValues.storeBlockStateValues(entry, javaRuntimeId);
|
||||
|
||||
String cleanJavaIdentifier = entry.getKey().split("\\[")[0];
|
||||
|
||||
if (!cleanJavaIdentifier.equals(bedrockIdentifier)) {
|
||||
JAVA_TO_BEDROCK_IDENTIFIERS.put(cleanJavaIdentifier, bedrockIdentifier);
|
||||
}
|
||||
|
||||
// Get the tag needed for non-empty flower pots
|
||||
if (entry.getValue().get("pottable") != null) {
|
||||
BlockStateValues.getFlowerPotBlocks().put(entry.getKey().split("\\[")[0], buildBedrockState(entry.getValue()));
|
||||
BlockStateValues.getFlowerPotBlocks().put(cleanJavaIdentifier, buildBedrockState(entry.getValue()));
|
||||
}
|
||||
|
||||
if ("minecraft:water[level=0]".equals(javaId)) {
|
||||
|
@ -297,6 +305,14 @@ public class BlockTranslator {
|
|||
return BEDROCK_TO_JAVA_BLOCK_MAP.get(bedrockId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param javaIdentifier the Java identifier of the block to search for
|
||||
* @return the Bedrock identifier if different, or else the Java identifier
|
||||
*/
|
||||
public static String getBedrockBlockIdentifier(String javaIdentifier) {
|
||||
return JAVA_TO_BEDROCK_IDENTIFIERS.getOrDefault(javaIdentifier, javaIdentifier);
|
||||
}
|
||||
|
||||
public static int getItemFrame(NbtMap tag) {
|
||||
return ITEM_FRAMES.getOrDefault(tag, -1);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue