diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java index e4296c2d4..c787f87a1 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java @@ -52,7 +52,6 @@ public class StoredItemMappings { private final int goldIngot; private final int ironIngot; private final int lead; - private final ItemMapping lodestoneCompass; private final ItemMapping milkBucket; private final int nameTag; private final ItemMapping powderSnowBucket; @@ -80,7 +79,6 @@ public class StoredItemMappings { this.goldIngot = load(itemMappings, "gold_ingot").getJavaId(); this.ironIngot = load(itemMappings, "iron_ingot").getJavaId(); this.lead = load(itemMappings, "lead").getJavaId(); - this.lodestoneCompass = load(itemMappings, "lodestone_compass"); this.milkBucket = load(itemMappings, "milk_bucket"); this.nameTag = load(itemMappings, "name_tag").getJavaId(); this.powderSnowBucket = load(itemMappings, "powder_snow_bucket"); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java index 534c68776..0e12669e3 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java @@ -128,7 +128,7 @@ public class ItemRegistryPopulator { IntList spawnEggs = new IntArrayList(); List carpets = new ObjectArrayList<>(); - Int2ObjectMap mappings = new Int2ObjectOpenHashMap<>(); + List mappings = new ObjectArrayList<>(); // Temporary mapping to create stored items Map identifierToMapping = new Object2ObjectOpenHashMap<>(); @@ -243,6 +243,8 @@ public class ItemRegistryPopulator { if (usingFurnaceMinecart && javaIdentifier.equals("minecraft:furnace_minecart")) { javaFurnaceMinecartId = itemIndex; itemIndex++; + // Will be added later + mappings.add(null); continue; } @@ -419,7 +421,7 @@ public class ItemRegistryPopulator { spawnEggs.add(mapping.getBedrockId()); } - mappings.put(itemIndex, mapping); + mappings.add(mapping); identifierToMapping.put(javaIdentifier, mapping); itemNames.add(javaIdentifier); @@ -440,16 +442,14 @@ public class ItemRegistryPopulator { // Add the lodestone compass since it doesn't exist on java but we need it for item conversion ItemMapping lodestoneEntry = ItemMapping.builder() - .javaIdentifier("minecraft:lodestone_compass") + .javaIdentifier("") .bedrockIdentifier("minecraft:lodestone_compass") - .javaId(itemIndex) + .javaId(-1) .bedrockId(lodestoneCompassId) .bedrockData(0) .bedrockBlockId(-1) .stackSize(1) .build(); - mappings.put(itemIndex, lodestoneEntry); - identifierToMapping.put(lodestoneEntry.getJavaIdentifier(), lodestoneEntry); ComponentItemData furnaceMinecartData = null; if (usingFurnaceMinecart) { @@ -458,7 +458,7 @@ public class ItemRegistryPopulator { entries.put("geysermc:furnace_minecart", new StartGamePacket.ItemEntry("geysermc:furnace_minecart", (short) furnaceMinecartId, true)); - mappings.put(javaFurnaceMinecartId, ItemMapping.builder() + mappings.set(javaFurnaceMinecartId, ItemMapping.builder() .javaIdentifier("minecraft:furnace_minecart") .bedrockIdentifier("geysermc:furnace_minecart") .javaId(javaFurnaceMinecartId) @@ -509,9 +509,9 @@ public class ItemRegistryPopulator { } ItemMappings itemMappings = ItemMappings.builder() - .items(mappings) + .items(mappings.toArray(new ItemMapping[0])) .creativeItems(creativeItems.toArray(new ItemData[0])) - .itemEntries(new ArrayList<>(entries.values())) + .itemEntries(List.copyOf(entries.values())) .itemNames(itemNames.toArray(new String[0])) .storedItems(new StoredItemMappings(identifierToMapping)) .javaOnlyItems(javaOnlyItems) @@ -520,6 +520,7 @@ public class ItemRegistryPopulator { .spawnEggIds(spawnEggs) .carpets(carpets) .furnaceMinecartData(furnaceMinecartData) + .lodestoneCompass(lodestoneEntry) .build(); Registries.ITEMS.register(palette.getValue().protocolVersion(), itemMappings); diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java index a4953b05b..3072568f3 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java @@ -29,13 +29,13 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.nukkitx.protocol.bedrock.data.inventory.ComponentItemData; import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.StartGamePacket; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.IntList; import lombok.Builder; import lombok.Value; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.StoredItemMappings; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; import java.util.Map; @@ -48,7 +48,12 @@ public class ItemMappings { Map cachedJavaMappings = new WeakHashMap<>(); - Int2ObjectMap items; + ItemMapping[] items; + + /** + * A unique exception as this is an item in Bedrock, but not in Java. + */ + ItemMapping lodestoneCompass; ItemData[] creativeItems; List itemEntries; @@ -70,6 +75,7 @@ public class ItemMappings { * @param itemStack the itemstack * @return an item entry from the given java edition identifier */ + @Nonnull public ItemMapping getMapping(ItemStack itemStack) { return this.getMapping(itemStack.getId()); } @@ -81,8 +87,9 @@ public class ItemMappings { * @param javaId the id * @return an item entry from the given java edition identifier */ + @Nonnull public ItemMapping getMapping(int javaId) { - return this.items.get(javaId); + return javaId >= 0 && javaId < this.items.length ? this.items[javaId] : ItemMapping.AIR; } /** @@ -94,7 +101,7 @@ public class ItemMappings { */ public ItemMapping getMapping(String javaIdentifier) { return this.cachedJavaMappings.computeIfAbsent(javaIdentifier, key -> { - for (ItemMapping mapping : this.items.values()) { + for (ItemMapping mapping : this.items) { if (mapping.getJavaIdentifier().equals(key)) { return mapping; } @@ -110,11 +117,18 @@ public class ItemMappings { * @return an item entry from the given item data */ public ItemMapping getMapping(ItemData data) { + int id = data.getId(); + if (id == 0) { + return ItemMapping.AIR; + } else if (id == lodestoneCompass.getBedrockId()) { + return lodestoneCompass; + } + boolean isBlock = data.getBlockRuntimeId() != 0; boolean hasDamage = data.getDamage() != 0; - for (ItemMapping mapping : this.items.values()) { - if (mapping.getBedrockId() == data.getId()) { + for (ItemMapping mapping : this.items) { + if (mapping.getBedrockId() == id) { if (isBlock && !hasDamage) { // Pre-1.16.220 will not use block runtime IDs at all, so we shouldn't check either if (data.getBlockRuntimeId() != mapping.getBedrockBlockId()) { continue; @@ -135,7 +149,7 @@ public class ItemMappings { } // This will hide the message when the player clicks with an empty hand - if (data.getId() != 0 && data.getDamage() != 0) { + if (id != 0 && data.getDamage() != 0) { GeyserImpl.getInstance().getLogger().debug("Missing mapping for bedrock item " + data.getId() + ":" + data.getDamage()); } return ItemMapping.AIR; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CompassTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CompassTranslator.java index b8ef85f81..4c2978082 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CompassTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CompassTranslator.java @@ -35,6 +35,7 @@ import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; +import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -45,7 +46,7 @@ public class CompassTranslator extends ItemTranslator { protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { if (isLodestoneCompass(itemStack.getNbt())) { // NBT will be translated in nbt/LodestoneCompassTranslator if applicable - return super.translateToBedrock(itemStack, mappings.getStoredItems().lodestoneCompass(), mappings); + return super.translateToBedrock(itemStack, mappings.getLodestoneCompass(), mappings); } return super.translateToBedrock(itemStack, mapping, mappings); } @@ -53,7 +54,7 @@ public class CompassTranslator extends ItemTranslator { @Override protected ItemMapping getItemMapping(int javaId, CompoundTag nbt, ItemMappings mappings) { if (isLodestoneCompass(nbt)) { - return mappings.getStoredItems().lodestoneCompass(); + return mappings.getLodestoneCompass(); } return super.getItemMapping(javaId, nbt, mappings); } @@ -78,10 +79,8 @@ public class CompassTranslator extends ItemTranslator { @Override public List getAppliedItems() { - return Registries.ITEMS.forVersion(MinecraftProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) - .getItems() - .values() - .stream() + return Arrays.stream(Registries.ITEMS.forVersion(MinecraftProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) + .getItems()) .filter(entry -> entry.getJavaIdentifier().endsWith("compass")) .collect(Collectors.toList()); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/PotionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/PotionTranslator.java index 04183e095..bf16af38f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/PotionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/PotionTranslator.java @@ -36,6 +36,7 @@ import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; +import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -73,10 +74,8 @@ public class PotionTranslator extends ItemTranslator { @Override public List getAppliedItems() { - return Registries.ITEMS.forVersion(MinecraftProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) - .getItems() - .values() - .stream() + return Arrays.stream(Registries.ITEMS.forVersion(MinecraftProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) + .getItems()) .filter(entry -> entry.getJavaIdentifier().endsWith("potion")) .collect(Collectors.toList()); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/TippedArrowTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/TippedArrowTranslator.java index b3aecb668..d831ce586 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/TippedArrowTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/TippedArrowTranslator.java @@ -36,6 +36,7 @@ import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; +import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -80,10 +81,8 @@ public class TippedArrowTranslator extends ItemTranslator { @Override public List getAppliedItems() { - return Registries.ITEMS.forVersion(MinecraftProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) - .getItems() - .values() - .stream() + return Arrays.stream(Registries.ITEMS.forVersion(MinecraftProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) + .getItems()) .filter(entry -> entry.getJavaIdentifier().contains("arrow") && !entry.getJavaIdentifier().contains("spectral")) .collect(Collectors.toList()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BannerTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BannerTranslator.java index 3da157cfc..ed4865411 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BannerTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BannerTranslator.java @@ -37,10 +37,7 @@ import org.geysermc.geyser.translator.inventory.item.ItemRemapper; import org.geysermc.geyser.translator.inventory.item.NbtItemStackTranslator; import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; @ItemRemapper @@ -79,10 +76,8 @@ public class BannerTranslator extends NbtItemStackTranslator { } public BannerTranslator() { - appliedItems = Registries.ITEMS.forVersion(MinecraftProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) - .getItems() - .values() - .stream() + appliedItems = Arrays.stream(Registries.ITEMS.forVersion(MinecraftProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) + .getItems()) .filter(entry -> entry.getJavaIdentifier().endsWith("banner")) .collect(Collectors.toList()); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java index f120e4a19..073917293 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java @@ -284,7 +284,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator - session.getItemMappings().getItems() - .getOrDefault(stoneCuttingRecipeData.getResult().getId(), ItemMapping.AIR) + session.getItemMappings().getMapping(stoneCuttingRecipeData.getResult()) .getJavaIdentifier()))); // Now that it's sorted, let's translate these recipes @@ -229,7 +228,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator