diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java index 171849ce5..04317e6d6 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java @@ -27,24 +27,16 @@ package org.geysermc.geyser.entity.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.nbt.NbtMapBuilder; -import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket; -import org.geysermc.floodgate.util.DeviceOs; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.player.PlayerEntity; -import org.geysermc.geyser.level.FireworkColor; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.util.MathUtils; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; -import java.util.ArrayList; -import java.util.List; import java.util.OptionalInt; import java.util.UUID; @@ -59,80 +51,16 @@ public class FireworkEntity extends Entity { if (item == null) { return; } - CompoundTag tag = item.getNbt(); - - if (tag == null) { + DataComponents components = item.getDataComponents(); + if (components == null) { return; } - // TODO: Remove once Mojang fixes bugs with fireworks crashing clients on these specific devices. - // https://bugs.mojang.com/browse/MCPE-89115 - if (session.getClientData().getDeviceOs() == DeviceOs.XBOX - || session.getClientData().getDeviceOs() == DeviceOs.PS4) { - return; - } - - CompoundTag fireworks = tag.get("Fireworks"); - if (fireworks == null) { - // Thank you Mineplex very cool - return; - } - - NbtMapBuilder fireworksBuilder = NbtMap.builder(); - if (fireworks.get("Flight") != null) { - fireworksBuilder.putByte("Flight", MathUtils.getNbtByte(fireworks.get("Flight").getValue())); - } - - List explosions = new ArrayList<>(); - if (fireworks.get("Explosions") != null) { - for (Tag effect : ((ListTag) fireworks.get("Explosions")).getValue()) { - CompoundTag effectData = (CompoundTag) effect; - NbtMapBuilder effectBuilder = NbtMap.builder(); - - if (effectData.get("Type") != null) { - effectBuilder.putByte("FireworkType", MathUtils.getNbtByte(effectData.get("Type").getValue())); - } - - if (effectData.get("Colors") != null) { - int[] oldColors = (int[]) effectData.get("Colors").getValue(); - byte[] colors = new byte[oldColors.length]; - - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaRGB(color); - } - - effectBuilder.putByteArray("FireworkColor", colors); - } - - if (effectData.get("FadeColors") != null) { - int[] oldColors = (int[]) effectData.get("FadeColors").getValue(); - byte[] colors = new byte[oldColors.length]; - - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaRGB(color); - } - - effectBuilder.putByteArray("FireworkFade", colors); - } - - if (effectData.get("Trail") != null) { - effectBuilder.putByte("FireworkTrail", MathUtils.getNbtByte(effectData.get("Trail").getValue())); - } - - if (effectData.get("Flicker") != null) { - effectBuilder.putByte("FireworkFlicker", MathUtils.getNbtByte(effectData.get("Flicker").getValue())); - } - - explosions.add(effectBuilder.build()); - } - } - - fireworksBuilder.putList("Explosions", NbtType.COMPOUND, explosions); - - NbtMapBuilder builder = NbtMap.builder(); - builder.put("Fireworks", fireworksBuilder.build()); + // TODO this looked the same, so I'm going to assume it is and (keep below comment if true) + // Translate using item methods to get firework NBT for Bedrock + BedrockItemBuilder builder = new BedrockItemBuilder(); + Items.FIREWORK_ROCKET.translateComponentsToBedrock(session, components, builder); + dirtyMetadata.put(EntityDataTypes.DISPLAY_FIREWORK, builder.build()); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index 245b99cef..b070bdfff 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -299,7 +299,7 @@ public class LivingEntity extends Entity { case GENERIC_MOVEMENT_SPEED -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.MOVEMENT_SPEED)); case GENERIC_FOLLOW_RANGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FOLLOW_RANGE)); case GENERIC_KNOCKBACK_RESISTANCE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.KNOCKBACK_RESISTANCE)); - case HORSE_JUMP_STRENGTH -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.HORSE_JUMP_STRENGTH)); + case GENERIC_JUMP_STRENGTH -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.HORSE_JUMP_STRENGTH)); } } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java index cea371963..31428477a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java @@ -27,8 +27,9 @@ package org.geysermc.geyser.entity.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -58,16 +59,17 @@ public class ThrownPotionEntity extends ThrowableItemEntity { setFlag(EntityFlag.LINGERING, false); } else { // As of Java 1.19.3, the server/client doesn't seem to care of the item is actually a potion? - if (itemStack.getNbt() != null) { - Tag potionTag = itemStack.getNbt().get("Potion"); - if (potionTag instanceof StringTag) { - Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); + DataComponents components = itemStack.getDataComponents(); + if (components != null) { + PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS); + if (potionContents != null) { + Potion potion = Potion.VALUES[potionContents.getPotionId()]; if (potion != null) { dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, (int) potion.getBedrockId()); setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion)); } else { dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, 0); - GeyserImpl.getInstance().getLogger().debug("Unknown java potion: " + potionTag.getValue()); + GeyserImpl.getInstance().getLogger().debug("Unknown java potion: " + potionContents.getPotionId()); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java index 85b2afc14..97753f63f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java @@ -61,7 +61,7 @@ public class AxolotlEntity extends AnimalEntity { @Override public boolean canEat(Item item) { - return session.getTagCache().isAxolotlTemptItem(item); + return session.getTagCache().isAxolotlFood(item); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java b/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java index 5fa2a5784..773de29b1 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java @@ -118,7 +118,7 @@ public enum Enchantment { KNOCKBACK, FIRE_ASPECT, LOOTING, - SWEEPING, + SWEEPING_EDGE, EFFICIENCY, SILK_TOUCH, UNBREAKING, @@ -136,6 +136,9 @@ public enum Enchantment { MULTISHOT, QUICK_CHARGE, PIERCING, + DENSITY, + BREACH, + WIND_BURST, MENDING, VANISHING_CURSE; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java index 3ba0ad56f..5c33fec67 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java @@ -36,6 +36,7 @@ import java.util.Locale; */ @Getter public enum TippedArrowPotion { + WATER(-1, ArrowParticleColors.NONE), // Guessing this based off of the Potion enum. TODO merge? MUNDANE(2, ArrowParticleColors.NONE), // 3 is extended? THICK(4, ArrowParticleColors.NONE), AWKWARD(5, ArrowParticleColors.NONE), @@ -94,6 +95,10 @@ public enum TippedArrowPotion { this.javaColor = arrowParticleColor.getColor(); } + public static TippedArrowPotion of(int id) { + return VALUES[id]; + } + public static @Nullable TippedArrowPotion getByJavaIdentifier(String javaIdentifier) { for (TippedArrowPotion potion : VALUES) { if (potion.javaIdentifier.equals(javaIdentifier)) { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index 5adee0c20..96ef12861 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -350,7 +350,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { if (enchantment == JavaEnchantment.IMPALING) { // Multiplier is halved on Bedrock for some reason rarityMultiplier /= 2; - } else if (enchantment == JavaEnchantment.SWEEPING) { + } else if (enchantment == JavaEnchantment.SWEEPING_EDGE) { // Doesn't exist on Bedrock rarityMultiplier = 0; } diff --git a/core/src/main/java/org/geysermc/geyser/item/ArmorMaterial.java b/core/src/main/java/org/geysermc/geyser/item/ArmorMaterial.java index 315a8cd4d..348c0af8c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/ArmorMaterial.java +++ b/core/src/main/java/org/geysermc/geyser/item/ArmorMaterial.java @@ -31,12 +31,13 @@ import java.util.function.Supplier; public enum ArmorMaterial { LEATHER(() -> Items.LEATHER), - CHAIN(() -> Items.IRON_INGOT), + CHAINMAIL(() -> Items.IRON_INGOT), IRON(() -> Items.IRON_INGOT), GOLD(() -> Items.GOLD_INGOT), DIAMOND(() -> Items.DIAMOND), - TURTLE(() -> Items.SCUTE), - NETHERITE(() -> Items.NETHERITE_INGOT); + TURTLE(() -> Items.TURTLE_SCUTE), + NETHERITE(() -> Items.NETHERITE_INGOT), + ARMADILLO(() -> Items.ARMADILLO_SCUTE); private final Supplier repairIngredient; diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java index 2147ebb2c..42a087acf 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -123,6 +123,7 @@ public final class Items { public static final Item RAW_IRON_BLOCK = register(new BlockItem("raw_iron_block", builder())); public static final Item RAW_COPPER_BLOCK = register(new BlockItem("raw_copper_block", builder())); public static final Item RAW_GOLD_BLOCK = register(new BlockItem("raw_gold_block", builder())); + public static final Item HEAVY_CORE = register(new BlockItem("heavy_core", builder())); public static final Item AMETHYST_BLOCK = register(new BlockItem("amethyst_block", builder())); public static final Item BUDDING_AMETHYST = register(new BlockItem("budding_amethyst", builder())); public static final Item IRON_BLOCK = register(new BlockItem("iron_block", builder())); @@ -832,7 +833,9 @@ public final class Items { public static final Item STRUCTURE_BLOCK = register(new BlockItem("structure_block", builder())); public static final Item JIGSAW = register(new BlockItem("jigsaw", builder())); public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", ArmorMaterial.TURTLE, builder().stackSize(1).maxDamage(275))); - public static final Item SCUTE = register(new Item("scute", builder())); + public static final Item TURTLE_SCUTE = register(new Item("turtle_scute", builder())); + public static final Item ARMADILLO_SCUTE = register(new Item("armadillo_scute", builder())); + public static final Item WOLF_ARMOR = register(new ArmorItem("wolf_armor", ArmorMaterial.ARMADILLO, builder().stackSize(1).maxDamage(64))); public static final Item FLINT_AND_STEEL = register(new Item("flint_and_steel", builder().stackSize(1).maxDamage(64))); public static final Item APPLE = register(new Item("apple", builder())); public static final Item BOW = register(new Item("bow", builder().stackSize(1).maxDamage(384))); @@ -852,36 +855,36 @@ public final class Items { public static final Item GOLD_INGOT = register(new Item("gold_ingot", builder())); public static final Item NETHERITE_INGOT = register(new Item("netherite_ingot", builder())); public static final Item NETHERITE_SCRAP = register(new Item("netherite_scrap", builder())); - public static final Item WOODEN_SWORD = register(new TieredItem("wooden_sword", ToolTier.WOODEN, builder().stackSize(1).attackDamage(4).maxDamage(59))); - public static final Item WOODEN_SHOVEL = register(new TieredItem("wooden_shovel", ToolTier.WOODEN, builder().stackSize(1).attackDamage(2.5).maxDamage(59))); - public static final Item WOODEN_PICKAXE = register(new TieredItem("wooden_pickaxe", ToolTier.WOODEN, builder().stackSize(1).attackDamage(2).maxDamage(59))); - public static final Item WOODEN_AXE = register(new TieredItem("wooden_axe", ToolTier.WOODEN, builder().stackSize(1).attackDamage(7).maxDamage(59))); - public static final Item WOODEN_HOE = register(new TieredItem("wooden_hoe", ToolTier.WOODEN, builder().stackSize(1).attackDamage(1).maxDamage(59))); - public static final Item STONE_SWORD = register(new TieredItem("stone_sword", ToolTier.STONE, builder().stackSize(1).attackDamage(5).maxDamage(131))); - public static final Item STONE_SHOVEL = register(new TieredItem("stone_shovel", ToolTier.STONE, builder().stackSize(1).attackDamage(3.5).maxDamage(131))); - public static final Item STONE_PICKAXE = register(new TieredItem("stone_pickaxe", ToolTier.STONE, builder().stackSize(1).attackDamage(3).maxDamage(131))); - public static final Item STONE_AXE = register(new TieredItem("stone_axe", ToolTier.STONE, builder().stackSize(1).attackDamage(9).maxDamage(131))); - public static final Item STONE_HOE = register(new TieredItem("stone_hoe", ToolTier.STONE, builder().stackSize(1).attackDamage(1).maxDamage(131))); - public static final Item GOLDEN_SWORD = register(new TieredItem("golden_sword", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(4).maxDamage(32))); - public static final Item GOLDEN_SHOVEL = register(new TieredItem("golden_shovel", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(2.5).maxDamage(32))); - public static final Item GOLDEN_PICKAXE = register(new TieredItem("golden_pickaxe", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(2).maxDamage(32))); - public static final Item GOLDEN_AXE = register(new TieredItem("golden_axe", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(7).maxDamage(32))); - public static final Item GOLDEN_HOE = register(new TieredItem("golden_hoe", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(1).maxDamage(32))); - public static final Item IRON_SWORD = register(new TieredItem("iron_sword", ToolTier.IRON, builder().stackSize(1).attackDamage(6).maxDamage(250))); - public static final Item IRON_SHOVEL = register(new TieredItem("iron_shovel", ToolTier.IRON, builder().stackSize(1).attackDamage(4.5).maxDamage(250))); - public static final Item IRON_PICKAXE = register(new TieredItem("iron_pickaxe", ToolTier.IRON, builder().stackSize(1).attackDamage(4).maxDamage(250))); - public static final Item IRON_AXE = register(new TieredItem("iron_axe", ToolTier.IRON, builder().stackSize(1).attackDamage(9).maxDamage(250))); - public static final Item IRON_HOE = register(new TieredItem("iron_hoe", ToolTier.IRON, builder().stackSize(1).attackDamage(1).maxDamage(250))); - public static final Item DIAMOND_SWORD = register(new TieredItem("diamond_sword", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(7).maxDamage(1561))); - public static final Item DIAMOND_SHOVEL = register(new TieredItem("diamond_shovel", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(5.5).maxDamage(1561))); - public static final Item DIAMOND_PICKAXE = register(new TieredItem("diamond_pickaxe", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(5).maxDamage(1561))); - public static final Item DIAMOND_AXE = register(new TieredItem("diamond_axe", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(9).maxDamage(1561))); - public static final Item DIAMOND_HOE = register(new TieredItem("diamond_hoe", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(1).maxDamage(1561))); - public static final Item NETHERITE_SWORD = register(new TieredItem("netherite_sword", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(8).maxDamage(2031))); - public static final Item NETHERITE_SHOVEL = register(new TieredItem("netherite_shovel", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(6.5).maxDamage(2031))); - public static final Item NETHERITE_PICKAXE = register(new TieredItem("netherite_pickaxe", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(6).maxDamage(2031))); - public static final Item NETHERITE_AXE = register(new TieredItem("netherite_axe", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(10).maxDamage(2031))); - public static final Item NETHERITE_HOE = register(new TieredItem("netherite_hoe", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(1).maxDamage(2031))); + public static final Item WOODEN_SWORD = register(new TieredItem("wooden_sword", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(4.0))); + public static final Item WOODEN_SHOVEL = register(new TieredItem("wooden_shovel", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(2.5))); + public static final Item WOODEN_PICKAXE = register(new TieredItem("wooden_pickaxe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(2.0))); + public static final Item WOODEN_AXE = register(new TieredItem("wooden_axe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(7.0))); + public static final Item WOODEN_HOE = register(new TieredItem("wooden_hoe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(1.0))); + public static final Item STONE_SWORD = register(new TieredItem("stone_sword", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(5.0))); + public static final Item STONE_SHOVEL = register(new TieredItem("stone_shovel", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(3.5))); + public static final Item STONE_PICKAXE = register(new TieredItem("stone_pickaxe", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(3.0))); + public static final Item STONE_AXE = register(new TieredItem("stone_axe", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(9.0))); + public static final Item STONE_HOE = register(new TieredItem("stone_hoe", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(1.0))); + public static final Item GOLDEN_SWORD = register(new TieredItem("golden_sword", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(4.0))); + public static final Item GOLDEN_SHOVEL = register(new TieredItem("golden_shovel", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(2.5))); + public static final Item GOLDEN_PICKAXE = register(new TieredItem("golden_pickaxe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(2.0))); + public static final Item GOLDEN_AXE = register(new TieredItem("golden_axe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(7.0))); + public static final Item GOLDEN_HOE = register(new TieredItem("golden_hoe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(1.0))); + public static final Item IRON_SWORD = register(new TieredItem("iron_sword", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(6.0))); + public static final Item IRON_SHOVEL = register(new TieredItem("iron_shovel", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(4.5))); + public static final Item IRON_PICKAXE = register(new TieredItem("iron_pickaxe", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(4.0))); + public static final Item IRON_AXE = register(new TieredItem("iron_axe", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(9.0))); + public static final Item IRON_HOE = register(new TieredItem("iron_hoe", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(1.0))); + public static final Item DIAMOND_SWORD = register(new TieredItem("diamond_sword", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(7.0))); + public static final Item DIAMOND_SHOVEL = register(new TieredItem("diamond_shovel", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(5.5))); + public static final Item DIAMOND_PICKAXE = register(new TieredItem("diamond_pickaxe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(5.0))); + public static final Item DIAMOND_AXE = register(new TieredItem("diamond_axe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(9.0))); + public static final Item DIAMOND_HOE = register(new TieredItem("diamond_hoe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(1.0))); + public static final Item NETHERITE_SWORD = register(new TieredItem("netherite_sword", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(8.0))); + public static final Item NETHERITE_SHOVEL = register(new TieredItem("netherite_shovel", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(6.5))); + public static final Item NETHERITE_PICKAXE = register(new TieredItem("netherite_pickaxe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(6.0))); + public static final Item NETHERITE_AXE = register(new TieredItem("netherite_axe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(10.0))); + public static final Item NETHERITE_HOE = register(new TieredItem("netherite_hoe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(1.0))); public static final Item STICK = register(new Item("stick", builder())); public static final Item BOWL = register(new Item("bowl", builder())); public static final Item MUSHROOM_STEW = register(new Item("mushroom_stew", builder().stackSize(1))); @@ -891,14 +894,14 @@ public final class Items { public static final Item WHEAT_SEEDS = register(new BlockItem("wheat_seeds", builder())); public static final Item WHEAT = register(new Item("wheat", builder())); public static final Item BREAD = register(new Item("bread", builder())); - public static final Item LEATHER_HELMET = register(new DyeableArmorItem("leather_helmet", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(55))); - public static final Item LEATHER_CHESTPLATE = register(new DyeableArmorItem("leather_chestplate", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(80))); - public static final Item LEATHER_LEGGINGS = register(new DyeableArmorItem("leather_leggings", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(75))); - public static final Item LEATHER_BOOTS = register(new DyeableArmorItem("leather_boots", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(65))); - public static final Item CHAINMAIL_HELMET = register(new ArmorItem("chainmail_helmet", ArmorMaterial.CHAIN, builder().stackSize(1).maxDamage(165))); - public static final Item CHAINMAIL_CHESTPLATE = register(new ArmorItem("chainmail_chestplate", ArmorMaterial.CHAIN, builder().stackSize(1).maxDamage(240))); - public static final Item CHAINMAIL_LEGGINGS = register(new ArmorItem("chainmail_leggings", ArmorMaterial.CHAIN, builder().stackSize(1).maxDamage(225))); - public static final Item CHAINMAIL_BOOTS = register(new ArmorItem("chainmail_boots", ArmorMaterial.CHAIN, builder().stackSize(1).maxDamage(195))); + public static final Item LEATHER_HELMET = register(new ArmorItem("leather_helmet", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(55))); + public static final Item LEATHER_CHESTPLATE = register(new ArmorItem("leather_chestplate", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(80))); + public static final Item LEATHER_LEGGINGS = register(new ArmorItem("leather_leggings", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(75))); + public static final Item LEATHER_BOOTS = register(new ArmorItem("leather_boots", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(65))); + public static final Item CHAINMAIL_HELMET = register(new ArmorItem("chainmail_helmet", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(165))); + public static final Item CHAINMAIL_CHESTPLATE = register(new ArmorItem("chainmail_chestplate", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(240))); + public static final Item CHAINMAIL_LEGGINGS = register(new ArmorItem("chainmail_leggings", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(225))); + public static final Item CHAINMAIL_BOOTS = register(new ArmorItem("chainmail_boots", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(195))); public static final Item IRON_HELMET = register(new ArmorItem("iron_helmet", ArmorMaterial.IRON, builder().stackSize(1).maxDamage(165))); public static final Item IRON_CHESTPLATE = register(new ArmorItem("iron_chestplate", ArmorMaterial.IRON, builder().stackSize(1).maxDamage(240))); public static final Item IRON_LEGGINGS = register(new ArmorItem("iron_leggings", ArmorMaterial.IRON, builder().stackSize(1).maxDamage(225))); @@ -1043,11 +1046,13 @@ public final class Items { public static final Item CAULDRON = register(new BlockItem("cauldron", builder())); public static final Item ENDER_EYE = register(new Item("ender_eye", builder())); public static final Item GLISTERING_MELON_SLICE = register(new Item("glistering_melon_slice", builder())); + public static final Item ARMADILLO_SPAWN_EGG = register(new SpawnEggItem("armadillo_spawn_egg", builder())); public static final Item ALLAY_SPAWN_EGG = register(new SpawnEggItem("allay_spawn_egg", builder())); public static final Item AXOLOTL_SPAWN_EGG = register(new SpawnEggItem("axolotl_spawn_egg", builder())); public static final Item BAT_SPAWN_EGG = register(new SpawnEggItem("bat_spawn_egg", builder())); public static final Item BEE_SPAWN_EGG = register(new SpawnEggItem("bee_spawn_egg", builder())); public static final Item BLAZE_SPAWN_EGG = register(new SpawnEggItem("blaze_spawn_egg", builder())); + public static final Item BOGGED_SPAWN_EGG = register(new SpawnEggItem("bogged_spawn_egg", builder())); public static final Item BREEZE_SPAWN_EGG = register(new SpawnEggItem("breeze_spawn_egg", builder())); public static final Item CAT_SPAWN_EGG = register(new SpawnEggItem("cat_spawn_egg", builder())); public static final Item CAMEL_SPAWN_EGG = register(new SpawnEggItem("camel_spawn_egg", builder())); @@ -1123,8 +1128,10 @@ public final class Items { public static final Item ZOMBIFIED_PIGLIN_SPAWN_EGG = register(new SpawnEggItem("zombified_piglin_spawn_egg", builder())); public static final Item EXPERIENCE_BOTTLE = register(new Item("experience_bottle", builder())); public static final Item FIRE_CHARGE = register(new Item("fire_charge", builder())); + public static final Item WIND_CHARGE = register(new Item("wind_charge", builder())); public static final Item WRITABLE_BOOK = register(new WritableBookItem("writable_book", builder().stackSize(1))); public static final Item WRITTEN_BOOK = register(new WrittenBookItem("written_book", builder().stackSize(16))); + public static final Item MACE = register(new MaceItem("mace", builder().stackSize(1).maxDamage(250))); public static final Item ITEM_FRAME = register(new Item("item_frame", builder())); public static final Item GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder())); public static final Item FLOWER_POT = register(new BlockItem("flower_pot", builder())); @@ -1155,10 +1162,10 @@ public final class Items { public static final Item RABBIT_FOOT = register(new Item("rabbit_foot", builder())); public static final Item RABBIT_HIDE = register(new Item("rabbit_hide", builder())); public static final Item ARMOR_STAND = register(new Item("armor_stand", builder().stackSize(16))); - public static final Item IRON_HORSE_ARMOR = register(new Item("iron_horse_armor", builder().stackSize(1))); - public static final Item GOLDEN_HORSE_ARMOR = register(new Item("golden_horse_armor", builder().stackSize(1))); - public static final Item DIAMOND_HORSE_ARMOR = register(new Item("diamond_horse_armor", builder().stackSize(1))); - public static final Item LEATHER_HORSE_ARMOR = register(new DyeableHorseArmorItem("leather_horse_armor", builder().stackSize(1))); + public static final Item IRON_HORSE_ARMOR = register(new ArmorItem("iron_horse_armor", ArmorMaterial.IRON, builder().stackSize(1))); + public static final Item GOLDEN_HORSE_ARMOR = register(new ArmorItem("golden_horse_armor", ArmorMaterial.GOLD, builder().stackSize(1))); + public static final Item DIAMOND_HORSE_ARMOR = register(new ArmorItem("diamond_horse_armor", ArmorMaterial.DIAMOND, builder().stackSize(1))); + public static final Item LEATHER_HORSE_ARMOR = register(new ArmorItem("leather_horse_armor", ArmorMaterial.LEATHER, builder().stackSize(1))); public static final Item LEAD = register(new Item("lead", builder())); public static final Item NAME_TAG = register(new Item("name_tag", builder())); public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder().stackSize(1))); @@ -1216,7 +1223,7 @@ public final class Items { public static final Item MUSIC_DISC_5 = register(new Item("music_disc_5", builder().stackSize(1))); public static final Item MUSIC_DISC_PIGSTEP = register(new Item("music_disc_pigstep", builder().stackSize(1))); public static final Item DISC_FRAGMENT_5 = register(new Item("disc_fragment_5", builder())); - public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).attackDamage(9).maxDamage(250))); + public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).maxDamage(250).attackDamage(9.0))); public static final Item PHANTOM_MEMBRANE = register(new Item("phantom_membrane", builder())); public static final Item NAUTILUS_SHELL = register(new Item("nautilus_shell", builder())); public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder())); @@ -1229,6 +1236,8 @@ public final class Items { public static final Item MOJANG_BANNER_PATTERN = register(new Item("mojang_banner_pattern", builder().stackSize(1))); public static final Item GLOBE_BANNER_PATTERN = register(new Item("globe_banner_pattern", builder().stackSize(1))); public static final Item PIGLIN_BANNER_PATTERN = register(new Item("piglin_banner_pattern", builder().stackSize(1))); + public static final Item FLOW_BANNER_PATTERN = register(new Item("flow_banner_pattern", builder().stackSize(1))); + public static final Item GUSTER_BANNER_PATTERN = register(new Item("guster_banner_pattern", builder().stackSize(1))); public static final Item GOAT_HORN = register(new GoatHornItem("goat_horn", builder().stackSize(1))); public static final Item COMPOSTER = register(new BlockItem("composter", builder())); public static final Item BARREL = register(new ChestItem("barrel", builder())); @@ -1312,6 +1321,8 @@ public final class Items { public static final Item SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("silence_armor_trim_smithing_template", builder())); public static final Item RAISER_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("raiser_armor_trim_smithing_template", builder())); public static final Item HOST_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("host_armor_trim_smithing_template", builder())); + public static final Item FLOW_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("flow_armor_trim_smithing_template", builder())); + public static final Item BOLT_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("bolt_armor_trim_smithing_template", builder())); public static final Item ANGLER_POTTERY_SHERD = register(new Item("angler_pottery_sherd", builder())); public static final Item ARCHER_POTTERY_SHERD = register(new Item("archer_pottery_sherd", builder())); public static final Item ARMS_UP_POTTERY_SHERD = register(new Item("arms_up_pottery_sherd", builder())); @@ -1320,7 +1331,9 @@ public final class Items { public static final Item BURN_POTTERY_SHERD = register(new Item("burn_pottery_sherd", builder())); public static final Item DANGER_POTTERY_SHERD = register(new Item("danger_pottery_sherd", builder())); public static final Item EXPLORER_POTTERY_SHERD = register(new Item("explorer_pottery_sherd", builder())); + public static final Item FLOW_POTTERY_SHERD = register(new Item("flow_pottery_sherd", builder())); public static final Item FRIEND_POTTERY_SHERD = register(new Item("friend_pottery_sherd", builder())); + public static final Item GUSTER_POTTERY_SHERD = register(new Item("guster_pottery_sherd", builder())); public static final Item HEART_POTTERY_SHERD = register(new Item("heart_pottery_sherd", builder())); public static final Item HEARTBREAK_POTTERY_SHERD = register(new Item("heartbreak_pottery_sherd", builder())); public static final Item HOWL_POTTERY_SHERD = register(new Item("howl_pottery_sherd", builder())); @@ -1328,6 +1341,7 @@ public final class Items { public static final Item MOURNER_POTTERY_SHERD = register(new Item("mourner_pottery_sherd", builder())); public static final Item PLENTY_POTTERY_SHERD = register(new Item("plenty_pottery_sherd", builder())); public static final Item PRIZE_POTTERY_SHERD = register(new Item("prize_pottery_sherd", builder())); + public static final Item SCRAPE_POTTERY_SHERD = register(new Item("scrape_pottery_sherd", builder())); public static final Item SHEAF_POTTERY_SHERD = register(new Item("sheaf_pottery_sherd", builder())); public static final Item SHELTER_POTTERY_SHERD = register(new Item("shelter_pottery_sherd", builder())); public static final Item SKULL_POTTERY_SHERD = register(new Item("skull_pottery_sherd", builder())); @@ -1350,6 +1364,10 @@ public final class Items { public static final Item WAXED_OXIDIZED_COPPER_BULB = register(new BlockItem("waxed_oxidized_copper_bulb", builder())); public static final Item TRIAL_SPAWNER = register(new BlockItem("trial_spawner", builder())); public static final Item TRIAL_KEY = register(new Item("trial_key", builder())); + public static final Item OMINOUS_TRIAL_KEY = register(new Item("ominous_trial_key", builder())); + public static final Item VAULT = register(new BlockItem("vault", builder())); + public static final Item OMINOUS_BOTTLE = register(new Item("ominous_bottle", builder())); + public static final Item BREEZE_ROD = register(new Item("breeze_rod", builder())); public static final int AIR_ID = AIR.javaId(); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java index cf66b036b..16d5fd482 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java @@ -26,8 +26,6 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -48,7 +46,7 @@ public class ArrowItem extends Item { if (tippedArrowPotion != null) { itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getDataComponents()); StringTag potionTag = new StringTag("Potion", tippedArrowPotion.getJavaIdentifier()); - itemStack.getDataComponents().put(DataComponentType.POTION_CONTENTS, new PotionContents()); + //itemStack.getDataComponents().put(DataComponentType.POTION_CONTENTS, new PotionContents()); } return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 549809391..32806c3c2 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -56,14 +56,14 @@ public class BannerItem extends BlockItem { static { // Construct what an ominous banner is supposed to look like OMINOUS_BANNER_PATTERN = List.of( - new BannerPatternLayer("mr", 9), - new BannerPatternLayer("bs", 8), - new BannerPatternLayer("cs", 7), - new BannerPatternLayer("bo", 8), - new BannerPatternLayer("ms", 15), - new BannerPatternLayer("hh", 8), - new BannerPatternLayer("mc", 8), - new BannerPatternLayer("bo", 15) +// new BannerPatternLayer("mr", 9), +// new BannerPatternLayer("bs", 8), +// new BannerPatternLayer("cs", 7), +// new BannerPatternLayer("bo", 8), +// new BannerPatternLayer("ms", 15), +// new BannerPatternLayer("hh", 8), +// new BannerPatternLayer("mc", 8), +// new BannerPatternLayer("bo", 15) ); } @@ -103,7 +103,8 @@ public class BannerItem extends BlockItem { * @return The Java edition format pattern nbt */ public static CompoundTag getJavaBannerPattern(NbtMap pattern) { - return new BannerPatternLayer(pattern.getString("Pattern"), 15 - pattern.getInt("Color")); + //return new BannerPatternLayer(0/*pattern.getString("Pattern")*/, 15 - pattern.getInt("Color")); + return null; } /** @@ -128,13 +129,13 @@ public class BannerItem extends BlockItem { List patterns = components.get(DataComponentType.BANNER_PATTERNS); if (patterns != null) { - if (patterns.equals(OMINOUS_BANNER_PATTERN)) { - // Remove the current patterns and set the ominous banner type - builder.putInt("Type", 1); - } else { - invertBannerColors(patterns); - tag.put(patterns); - } +// if (patterns.equals(OMINOUS_BANNER_PATTERN)) { +// // Remove the current patterns and set the ominous banner type +// builder.putInt("Type", 1); +// } else { +// invertBannerColors(patterns); +// tag.put(patterns); +// } } } @@ -146,7 +147,7 @@ public class BannerItem extends BlockItem { // Ominous banner pattern tag.remove("Type"); CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag"); - blockEntityTag.put(OMINOUS_BANNER_PATTERN); + //blockEntityTag.put(OMINOUS_BANNER_PATTERN); tag.put(blockEntityTag); } else if (tag.get("Patterns") instanceof ListTag patterns) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java index 8d48d1307..10c574d5d 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java @@ -43,11 +43,11 @@ public class CompassItem extends Item { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - if (isLodestoneCompass(itemStack.getDataComponents())) { - return super.translateToBedrock(itemStack, mappings.getLodestoneCompass(), mappings); + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + if (isLodestoneCompass(components)) { + return super.translateToBedrock(count, components, mappings.getLodestoneCompass(), mappings); } - return super.translateToBedrock(itemStack, mapping, mappings); + return super.translateToBedrock(count, components, mapping, mappings); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java index 792ec0f0b..8d9be4db2 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java @@ -41,7 +41,7 @@ public class DecoratedPotItem extends BlockItem { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - components.get(DataComponentType.POT_DECORATIONS); // TODO + components.get(DataComponentType.POT_DECORATIONS); // TODO what does this look like on Bedrock? // if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { // if (blockEntityTag.remove("sherds") instanceof ListTag sherds) { // // bedrock wants it on the root level diff --git a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java index 3851813ae..095537a09 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java @@ -25,16 +25,18 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.ItemEnchantments; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import java.util.ArrayList; import java.util.List; +import java.util.Map; public class EnchantedBookItem extends Item { public EnchantedBookItem(String javaIdentifier, Builder builder) { @@ -45,20 +47,19 @@ public class EnchantedBookItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - List newTags = new ArrayList<>(); - Tag enchantmentTag = tag.remove("StoredEnchantments"); - if (enchantmentTag instanceof ListTag listTag) { - for (Tag subTag : listTag.getValue()) { - if (!(subTag instanceof CompoundTag)) continue; - CompoundTag bedrockTag = remapEnchantment(session, (CompoundTag) subTag, tag); + List bedrockEnchants = new ArrayList<>(); + ItemEnchantments enchantments = components.get(DataComponentType.STORED_ENCHANTMENTS); + if (enchantments != null) { // TODO don't duplicate code? + for (Map.Entry enchantment : enchantments.getEnchantments().entrySet()) { + NbtMap bedrockTag = remapEnchantment(session, enchantment.getKey(), enchantment.getValue(), builder); if (bedrockTag != null) { - newTags.add(bedrockTag); + bedrockEnchants.add(bedrockTag); } } } - if (!newTags.isEmpty()) { - tag.put(new ListTag("ench", newTags)); + if (!bedrockEnchants.isEmpty()) { + builder.putList("ench", NbtType.COMPOUND, bedrockEnchants); } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java index 78a175f8d..af0b84308 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java @@ -25,10 +25,8 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; @@ -39,12 +37,12 @@ public class FilledMapItem extends MapItem { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings); - DataComponents components = itemStack.getDataComponents(); + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + ItemData.Builder builder = super.translateToBedrock(count, components, mapping, mappings); if (components == null) { // This is a fallback for maps with no nbt (Change added back in June 2020; is it needed in 2023?) - return builder.tag(NbtMap.builder().putInt("map", 0).build()); + //return builder.tag(NbtMap.builder().putInt("map", 0).build()); TODO if this is *still* broken, let's move it to translateComponentsToBedrock + return builder; } else { Integer mapColor = components.get(DataComponentType.MAP_COLOR); if (mapColor != null) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java index d688e59f6..afb848e2d 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java @@ -32,6 +32,7 @@ import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.level.FireworkColor; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -63,9 +64,10 @@ public class FireworkRocketItem extends Item { } List explosionNbt = new ArrayList<>(); for (Fireworks.FireworkExplosion explosion : explosions) { - explosionNbt.add(translateExplosionToBedrock(explosion, "")); + explosionNbt.add(translateExplosionToBedrock(explosion)); } - + fireworksNbt.putList("Explosions", NbtType.COMPOUND, explosionNbt); + builder.putCompound("Fireworks", fireworksNbt.build()); } @Override @@ -73,39 +75,34 @@ public class FireworkRocketItem extends Item { super.translateNbtToJava(tag, mapping); } - static NbtMap translateExplosionToBedrock(Fireworks.FireworkExplosion explosion, String newName) { + static NbtMap translateExplosionToBedrock(Fireworks.FireworkExplosion explosion) { NbtMapBuilder newExplosionData = NbtMap.builder(); - if (explosion.get("Type") != null) { - newExplosionData.put(new ByteTag("FireworkType", MathUtils.getNbtByte(explosion.get("Type").getValue()))); - } +// if (explosion.get("Type") != null) { +// newExplosionData.put(new ByteTag("FireworkType", MathUtils.getNbtByte(explosion.get("Type").getValue()))); +// } //newExplosionData.putByte("FireworkType", explosion.get) //TODO??? - // TODO do we need length checks - if (explosion.get("Colors") != null) { - int[] oldColors = (int[]) explosion.get("Colors").getValue(); - byte[] colors = new byte[oldColors.length]; + int[] oldColors = explosion.getColors(); + byte[] colors = new byte[oldColors.length]; - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaRGB(color); - } - - newExplosionData.put(new ByteArrayTag("FireworkColor", colors)); + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaRGB(color); } - if (explosion.get("FadeColors") != null) { - int[] oldColors = (int[]) explosion.get("FadeColors").getValue(); - byte[] colors = new byte[oldColors.length]; + newExplosionData.putByteArray("FireworkColor", colors); - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaRGB(color); - } + oldColors = explosion.getFadeColors(); + colors = new byte[oldColors.length]; - newExplosionData.put(new ByteArrayTag("FireworkFade", colors)); + i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaRGB(color); } + newExplosionData.putByteArray("FireworkFade", colors); + newExplosionData.putBoolean("FireworkTrail", explosion.isHasTrail()); newExplosionData.putBoolean("FireworkFlicker", explosion.isHasTwinkle()); // TODO verify diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java index 4ae9c8b13..505296418 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java @@ -25,12 +25,13 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.Fireworks; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -44,19 +45,15 @@ public class FireworkStarItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - Tag explosion = tag.remove("Explosion"); - if (explosion instanceof CompoundTag) { - CompoundTag newExplosion = FireworkRocketItem.translateExplosionToBedrock((CompoundTag) explosion, "FireworksItem"); - tag.put(newExplosion); - Tag color = ((CompoundTag) explosion).get("Colors"); - if (color instanceof IntArrayTag) { + Fireworks.FireworkExplosion explosion = components.get(DataComponentType.FIREWORK_EXPLOSION); + if (explosion != null) { + NbtMap newExplosion = FireworkRocketItem.translateExplosionToBedrock(explosion); + builder.putCompound("FireworksItem", newExplosion); + int[] colors = explosion.getColors(); + if (colors.length != 0) { // Determine the custom color, if any. // Mostly replicates Java's own rendering code, as Java determines the final firework star color client-side // while Bedrock determines it server-side. - int[] colors = ((IntArrayTag) color).getValue(); - if (colors.length == 0) { - return; - } int finalColor; if (colors.length == 1) { finalColor = colors[0]; @@ -77,7 +74,7 @@ public class FireworkStarItem extends Item { finalColor = r << 16 | g << 8 | b; } - tag.put(new IntTag("customColor", finalColor)); + builder.putInt("customColor", finalColor); } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java index 4538689da..743928482 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java @@ -26,8 +26,6 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -42,11 +40,7 @@ public class FishingRodItem extends Item { super.translateComponentsToBedrock(session, components, builder); // Fix damage inconsistency - Tag damage = tag.get("Damage"); - if (damage instanceof IntTag) { - int originalDurability = ((IntTag) damage).getValue(); - tag.put(new IntTag("Damage", getBedrockDamage(originalDurability))); - } + builder.getDamage().ifPresent(damage -> builder.setDamage(getBedrockDamage(damage))); } public static int getBedrockDamage(int javaDamage) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java index 60b201961..48e75dc79 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java @@ -26,6 +26,9 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.Instrument; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -52,21 +55,25 @@ public class GoatHornItem extends Item { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings); - if (itemStack.getNbt() != null && itemStack.getNbt().get("instrument") instanceof StringTag instrumentTag) { - String instrument = instrumentTag.getValue(); + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + ItemData.Builder builder = super.translateToBedrock(count, components, mapping, mappings); + if (components == null) { + return builder; + } + Instrument instrument = components.get(DataComponentType.INSTRUMENT); + // TODO registry + if (instrument != null) { // Drop the Minecraft namespace if applicable - if (instrument.startsWith("minecraft:")) { - instrument = instrument.substring("minecraft:".length()); - } - - int damage = INSTRUMENTS.indexOf(instrument); - if (damage == -1) { - damage = 0; - GeyserImpl.getInstance().getLogger().debug("Unknown goat horn instrument: " + instrumentTag.getValue()); - } - builder.damage(damage); +// if (instrument.startsWith("minecraft:")) { +// instrument = instrument.substring("minecraft:".length()); +// } +// +// int damage = INSTRUMENTS.indexOf(instrument); +// if (damage == -1) { +// damage = 0; +// GeyserImpl.getInstance().getLogger().debug("Unknown goat horn instrument: " + instrumentTag.getValue()); +// } +// builder.damage(damage); } return builder; } @@ -83,7 +90,7 @@ public class GoatHornItem extends Item { String instrument = INSTRUMENTS.get(damage); StringTag instrumentTag = new StringTag("instrument", "minecraft:" + instrument); - itemStack.getNbt().put(instrumentTag); + //itemStack.getNbt().put(instrumentTag); return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index decc60da8..2779768db 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -27,18 +27,19 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.ItemEnchantments; import com.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.Enchantment; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; @@ -47,7 +48,6 @@ import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; -import org.geysermc.geyser.util.InventoryUtils; import java.util.ArrayList; import java.util.List; @@ -93,20 +93,16 @@ public class Item { /* Translation methods to Bedrock and back */ - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - if (InventoryUtils.isEmpty(itemStack)) { + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + if (this == Items.AIR || count <= 0) { // Return, essentially, air return ItemData.builder(); } ItemData.Builder builder = ItemData.builder() .definition(mapping.getBedrockDefinition()) .damage(mapping.getBedrockData()) - .count(itemStack.getAmount()); - if (itemStack.getDataComponents() != null) { - builder.tag(ItemTranslator.translateNbtToBedrock(itemStack.getDataComponents())); - } + .count(count); - DataComponents components = itemStack.getDataComponents(); ItemTranslator.translateCustomItem(components, builder, mapping); return builder; @@ -116,7 +112,7 @@ public class Item { if (itemData.getTag() == null) { return new ItemStack(javaId, itemData.getCount(), null); } - return new ItemStack(javaId, itemData.getCount(), ItemTranslator.translateToJavaNBT("", itemData.getTag())); + return new ItemStack(javaId, itemData.getCount(), null/*ItemTranslator.translateToJavaNBT("", itemData.getTag())*/); } public ItemMapping toBedrockDefinition(DataComponents components, ItemMappings mappings) { @@ -135,23 +131,24 @@ public class Item { } } - List newTags = new ArrayList<>(); + Integer damage = components.get(DataComponentType.DAMAGE); + if (damage != null) { + builder.setDamage(damage); + } + + List enchantNbtList = new ArrayList<>(); ItemEnchantments enchantments = components.get(DataComponentType.ENCHANTMENTS); if (enchantments != null) { - - } - if (enchantmentTag instanceof ListTag listTag) { - for (Tag subTag : listTag.getValue()) { - if (!(subTag instanceof CompoundTag)) continue; - CompoundTag bedrockTag = remapEnchantment(session, (CompoundTag) subTag, tag); - if (bedrockTag != null) { - newTags.add(bedrockTag); + for (Map.Entry enchantment : enchantments.getEnchantments().entrySet()) { + NbtMap enchantNbt = remapEnchantment(session, enchantment.getKey(), enchantment.getValue(), builder); + if (enchantNbt != null) { + enchantNbtList.add(enchantNbt); } } } - if (!newTags.isEmpty()) { - tag.put(new ListTag("ench", newTags)); + if (!enchantNbtList.isEmpty()) { + builder.putList("ench", NbtType.COMPOUND, enchantNbtList); } } @@ -218,45 +215,30 @@ public class Item { } } - protected final @Nullable NbtMap remapEnchantment(GeyserSession session, ItemEnchantments, NbtMapBuilder rootBuilder) { - - Enchantment enchantment = Enchantment.getByJavaIdentifier(((StringTag) javaEnchId).getValue()); + protected final @Nullable NbtMap remapEnchantment(GeyserSession session, int enchantId, int level, BedrockItemBuilder builder) { + // TODO verify + // TODO streamline Enchantment process + Enchantment.JavaEnchantment enchantment = Enchantment.JavaEnchantment.of(enchantId); + if (enchantment == Enchantment.JavaEnchantment.SWEEPING_EDGE) { + addSweeping(session, builder, level); + return null; + } if (enchantment == null) { - if (Identifier.formalize((String) javaEnchId.getValue()).equals("minecraft:sweeping")) { - Tag javaEnchLvl = tag.get("lvl"); - int sweepingLvl = javaEnchLvl != null && javaEnchLvl.getValue() instanceof Number lvl ? lvl.intValue() : 0; - - addSweeping(session, rootTag, sweepingLvl); - return null; - } - GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment while NBT item translating: " + javaEnchId.getValue()); + GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment while NBT item translating: " + enchantId); return null; } - Tag javaEnchLvl = tag.get("lvl"); - - NbtMapBuilder builder = NbtMap.builder(); - builder.putShort("id", (short) enchantment.ordinal()); - builder.putShort("lvl", ); - return builder.build(); + return NbtMap.builder() + .putShort("id", (short) Enchantment.valueOf(enchantment.name()).ordinal()) + .putShort("lvl", (short) level) + .build(); } - private void addSweeping(GeyserSession session, CompoundTag itemTag, int level) { - CompoundTag displayTag = itemTag.get("display"); - if (displayTag == null) { - displayTag = new CompoundTag("display"); - itemTag.put(displayTag); - } - ListTag loreTag = displayTag.get("Lore"); - if (loreTag == null) { - loreTag = new ListTag("Lore"); - displayTag.put(loreTag); - } - + private void addSweeping(GeyserSession session, BedrockItemBuilder builder, int level) { String sweepingTranslation = MinecraftLocale.getLocaleString("enchantment.minecraft.sweeping", session.locale()); String lvlTranslation = MinecraftLocale.getLocaleString("enchantment.level." + level, session.locale()); - loreTag.add(new StringTag("", ChatColor.RESET + ChatColor.GRAY + sweepingTranslation + " " + lvlTranslation)); + builder.getOrCreateLore().add(ChatColor.RESET + ChatColor.GRAY + sweepingTranslation + " " + lvlTranslation); } /* Translation methods end */ diff --git a/core/src/main/java/org/geysermc/geyser/item/type/MaceItem.java b/core/src/main/java/org/geysermc/geyser/item/type/MaceItem.java new file mode 100644 index 000000000..e7b9a8684 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/item/type/MaceItem.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019-2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.item.type; + +import org.geysermc.geyser.item.Items; + +public class MaceItem extends Item { + public MaceItem(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + public boolean isValidRepairItem(Item other) { + return other == Items.BREEZE_ROD; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java index b015862c5..72014e15e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; @@ -41,14 +42,14 @@ public class MapItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - Tag mapId = tag.remove("map"); - if (mapId == null || !(mapId.getValue() instanceof Number number)) return; + Integer mapValue = components.get(DataComponentType.MAP_ID); + if (mapValue == null) { + return; + } - int mapValue = number.intValue(); - - tag.put(new LongTag("map_uuid", mapValue)); - tag.put(new IntTag("map_name_index", mapValue)); - tag.put(new ByteTag("map_display_players", (byte) 1)); + builder.putLong("map_uuid", mapValue); + builder.putInt("map_name_index", mapValue); + builder.putByte("map_display_players", (byte) 1); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java index dae444775..82219d7d9 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java @@ -25,16 +25,14 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.auth.data.GameProfile; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; -import org.geysermc.geyser.translator.text.MessageTranslator; public class PlayerHeadItem extends Item { public PlayerHeadItem(String javaIdentifier, Builder builder) { @@ -45,35 +43,24 @@ public class PlayerHeadItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - CompoundTag displayTag; - if (tag.get("display") instanceof CompoundTag existingDisplayTag) { - displayTag = existingDisplayTag; - } else { - displayTag = new CompoundTag("display"); - tag.put(displayTag); - } - - if (displayTag.get("Name") instanceof StringTag nameTag) { - // Custom names are always yellow and italic - displayTag.put(new StringTag("Name", ChatColor.YELLOW + ChatColor.ITALIC + MessageTranslator.convertMessageLenient(nameTag.getValue(), session.locale()))); - } else { - if (tag.contains("SkullOwner")) { - StringTag name; - Tag skullOwner = tag.get("SkullOwner"); - if (skullOwner instanceof StringTag skullName) { - name = skullName; + // TODO verify + // Also - ChatColor.YELLOW + ChatColor.ITALIC + MessageTranslator.convertMessageLenient(nameTag.getValue(), session.locale())) this code existed if a custom name was already present. + // But I think we would always overwrite that because translateDisplayProperties runs after this method. + String customName = builder.getCustomName(); + if (customName == null) { + GameProfile profile = components.get(DataComponentType.PROFILE); + if (profile != null) { + String name = profile.getName(); + if (name != null) { + // Add correct name of player skull + String displayName = ChatColor.RESET + ChatColor.YELLOW + + MinecraftLocale.getLocaleString("block.minecraft.player_head.named", session.locale()).replace("%s", name); + builder.setCustomName(displayName); } else { - if (skullOwner instanceof CompoundTag && ((CompoundTag) skullOwner).get("Name") instanceof StringTag skullName) { - name = skullName; - } else { - // No name found so default to "Player Head" - displayTag.put(new StringTag("Name", ChatColor.RESET + ChatColor.YELLOW + MinecraftLocale.getLocaleString("block.minecraft.player_head", session.locale()))); - return; - } + // No name found so default to "Player Head" + builder.setCustomName(ChatColor.RESET + ChatColor.YELLOW + + MinecraftLocale.getLocaleString("block.minecraft.player_head", session.locale())); } - // Add correct name of player skull - String displayName = ChatColor.RESET + ChatColor.YELLOW + MinecraftLocale.getLocaleString("block.minecraft.player_head.named", session.locale()).replace("%s", name.getValue()); - displayTag.put(new StringTag("Name", displayName)); } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java index bed2945ba..63b9240c0 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java @@ -27,9 +27,9 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -38,7 +38,6 @@ import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.translator.item.CustomItemTranslator; -import org.geysermc.geyser.translator.item.ItemTranslator; public class PotionItem extends Item { public PotionItem(String javaIdentifier, Builder builder) { @@ -46,29 +45,27 @@ public class PotionItem extends Item { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - if (itemStack.getDataComponents() == null) return super.translateToBedrock(itemStack, mapping, mappings); - PotionContents potionContents = itemStack.getDataComponents().get(DataComponentType.POTION_CONTENTS); + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + if (components == null) return super.translateToBedrock(count, components, mapping, mappings); + PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS); if (potionContents != null) { - ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(itemStack.getDataComponents(), mapping); + ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(components, mapping); if (customItemDefinition == null) { - Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); + Potion potion = Potion.VALUES[potionContents.getPotionId()]; if (potion != null) { return ItemData.builder() .definition(mapping.getBedrockDefinition()) .damage(potion.getBedrockId()) - .count(itemStack.getAmount()) - .tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt())); + .count(count); } - GeyserImpl.getInstance().getLogger().debug("Unknown Java potion: " + potionTag.getValue()); + GeyserImpl.getInstance().getLogger().debug("Unknown Java potion: " + potionContents.getPotionId()); } else { return ItemData.builder() .definition(customItemDefinition) - .count(itemStack.getAmount()) - .tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt())); + .count(count); } } - return super.translateToBedrock(itemStack, mapping, mappings); + return super.translateToBedrock(count, components, mapping, mappings); } @Override @@ -77,7 +74,7 @@ public class PotionItem extends Item { ItemStack itemStack = super.translateToJava(itemData, mapping, mappings); if (potion != null) { StringTag potionTag = new StringTag("Potion", potion.getJavaIdentifier()); - itemStack.getNbt().put(potionTag); + //itemStack.getNbt().put(potionTag); } return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java index 30b50b436..f495222f3 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java @@ -26,10 +26,6 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.components.ToolTier; import org.geysermc.geyser.session.GeyserSession; @@ -44,21 +40,22 @@ public class ShieldItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { - if (blockEntityTag.get("Patterns") instanceof ListTag patterns) { - for (Tag pattern : patterns) { - if (((CompoundTag) pattern).get("Color") instanceof IntTag color) { - color.setValue(15 - color.getValue()); - } - } - // Bedrock looks for patterns at the root - tag.put(patterns); - } - if (blockEntityTag.get("Base") instanceof IntTag base) { - base.setValue(15 - base.getValue()); - tag.put(base); - } - } + // TODO figure out patterns first. +// if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { +// if (blockEntityTag.get("Patterns") instanceof ListTag patterns) { +// for (Tag pattern : patterns) { +// if (((CompoundTag) pattern).get("Color") instanceof IntTag color) { +// color.setValue(15 - color.getValue()); +// } +// } +// // Bedrock looks for patterns at the root +// tag.put(patterns); +// } +// if (blockEntityTag.get("Base") instanceof IntTag base) { +// base.setValue(15 - base.getValue()); +// tag.put(base); +// } +// } } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java index 395563fe3..267946442 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java @@ -83,7 +83,7 @@ public class ShulkerBoxItem extends BlockItem { itemsList.add(boxItemNbt.build()); } - builder.getOrCreateNbt().putList("Items", NbtType.COMPOUND, itemsList); + builder.putList("Items", NbtType.COMPOUND, itemsList); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java index fcf562ba5..9074c2ec8 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java @@ -25,15 +25,14 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.TippedArrowPotion; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; -import org.geysermc.geyser.translator.item.ItemTranslator; public class TippedArrowItem extends ArrowItem { public TippedArrowItem(String javaIdentifier, Builder builder) { @@ -41,19 +40,18 @@ public class TippedArrowItem extends ArrowItem { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - Tag potionTag = itemStack.getNbt().get("Potion"); - if (potionTag instanceof StringTag) { - TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByJavaIdentifier(((StringTag) potionTag).getValue()); + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS); + if (potionContents != null) { + TippedArrowPotion tippedArrowPotion = TippedArrowPotion.of(potionContents.getPotionId()); if (tippedArrowPotion != null) { return ItemData.builder() .definition(mapping.getBedrockDefinition()) .damage(tippedArrowPotion.getBedrockId()) - .count(itemStack.getAmount()) - .tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt())); + .count(count); } - GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionTag.getValue()); + GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionContents.getPotionId()); } - return super.translateToBedrock(itemStack, mapping, mappings); + return super.translateToBedrock(count, components, mapping, mappings); } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java index 3ece87745..f70e6b295 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java @@ -25,8 +25,10 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.*; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; @@ -38,7 +40,6 @@ import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; -import java.util.ArrayList; import java.util.List; public class TropicalFishBucketItem extends Item { @@ -53,27 +54,27 @@ public class TropicalFishBucketItem extends Item { super.translateComponentsToBedrock(session, components, builder); // Prevent name from appearing as "Bucket of" - tag.put(new ByteTag("AppendCustomName", (byte) 1)); - tag.put(new StringTag("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.tropical_fish", session.locale()))); + builder.putByte("AppendCustomName", (byte) 1); + builder.putString("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.tropical_fish", session.locale())); // Add Java's client side lore tag - Tag bucketVariantTag = tag.get("BucketVariantTag"); - if (bucketVariantTag instanceof IntTag) { - CompoundTag displayTag = tag.get("display"); - if (displayTag == null) { - displayTag = new CompoundTag("display"); - tag.put(displayTag); + // Do you know how frequently Java NBT used to be before 1.20.5? It was a lot. And now it's just this lowly check. + CompoundTag entityTag = components.get(DataComponentType.BUCKET_ENTITY_DATA); + if (entityTag != null && !entityTag.isEmpty()) { + //TODO test + Tag bucketVariant = entityTag.get("BucketVariantTag"); + if (bucketVariant == null || !(bucketVariant.getValue() instanceof Number)) { + return; } + List lore = builder.getOrCreateLore(); - List lore = new ArrayList<>(); - - int varNumber = ((IntTag) bucketVariantTag).getValue(); + int varNumber = ((Number) bucketVariant.getValue()).intValue(); int predefinedVariantId = TropicalFishEntity.getPredefinedId(varNumber); if (predefinedVariantId != -1) { Component tooltip = Component.translatable("entity.minecraft.tropical_fish.predefined." + predefinedVariantId, LORE_STYLE); - lore.add(0, new StringTag("", MessageTranslator.convertMessage(tooltip, session.locale()))); + lore.add(0, MessageTranslator.convertMessage(tooltip, session.locale())); } else { Component typeTooltip = Component.translatable("entity.minecraft.tropical_fish.type." + TropicalFishEntity.getVariantName(varNumber), LORE_STYLE); - lore.add(0, new StringTag("", MessageTranslator.convertMessage(typeTooltip, session.locale()))); + lore.add(0, MessageTranslator.convertMessage(typeTooltip, session.locale())); byte baseColor = TropicalFishEntity.getBaseColor(varNumber); byte patternColor = TropicalFishEntity.getPatternColor(varNumber); @@ -82,14 +83,8 @@ public class TropicalFishBucketItem extends Item { colorTooltip = colorTooltip.append(Component.text(", ", LORE_STYLE)) .append(Component.translatable("color.minecraft." + TropicalFishEntity.getColorName(patternColor), LORE_STYLE)); } - lore.add(1, new StringTag("", MessageTranslator.convertMessage(colorTooltip, session.locale()))); + lore.add(1, MessageTranslator.convertMessage(colorTooltip, session.locale())); } - - ListTag loreTag = displayTag.get("Lore"); - if (loreTag != null) { - lore.addAll(loreTag.getValue()); - } - displayTag.put(new ListTag("Lore", lore)); } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java index 68cdf99d4..d925d2b8a 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java @@ -25,12 +25,18 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.Filterable; +import com.github.steveice10.mc.protocol.data.game.item.component.WritableBookContent; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -48,22 +54,20 @@ public class WritableBookItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - ListTag pagesTag = tag.remove("pages"); - if (pagesTag == null) { + WritableBookContent bookContent = components.get(DataComponentType.WRITABLE_BOOK_CONTENT); + if (bookContent == null) { return; } - List pages = new ArrayList<>(); - for (Tag subTag : pagesTag.getValue()) { - if (!(subTag instanceof StringTag textTag)) - continue; - CompoundTag pageTag = new CompoundTag(""); - pageTag.put(new StringTag("photoname", "")); - pageTag.put(new StringTag("text", MessageTranslator.convertMessageLenient(textTag.getValue()))); - pages.add(pageTag); + List bedrockPages = new ArrayList<>(); + for (Filterable page : bookContent.getPages()) { + NbtMapBuilder pageBuilder = NbtMap.builder(); + pageBuilder.putString("photoname", ""); + pageBuilder.putString("text", MessageTranslator.convertMessageLenient(page.getRaw())); + bedrockPages.add(pageBuilder.build()); } - tag.put(new ListTag("pages", pages)); + builder.putList("pages", NbtType.COMPOUND, bedrockPages); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java index ae6b81f6e..6ca52aca4 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java @@ -25,21 +25,27 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.Filterable; +import com.github.steveice10.mc.protocol.data.game.item.component.WrittenBookContent; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; +import java.util.ArrayList; import java.util.List; -public class WrittenBookItem extends WritableBookItem { +public class WrittenBookItem extends Item { public static final int MAXIMUM_PAGE_EDIT_LENGTH = 1024; public static final int MAXIMUM_PAGE_LENGTH = 32768; public static final int MAXIMUM_PAGE_COUNT = 100; // Java edition limit. Bedrock edition has a limit of 50 pages. @@ -51,25 +57,24 @@ public class WrittenBookItem extends WritableBookItem { @Override public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { - boolean isValid = isValidWrittenBook(tag); - if (!isValid) { - tag.remove("pages"); - } - super.translateComponentsToBedrock(session, components, builder); - if (!isValid) { - CompoundTag invalidTagPage = new CompoundTag(""); - invalidTagPage.put(new StringTag("photoname", "")); - invalidTagPage.put(new StringTag( - "text", - MessageTranslator.convertMessage( - Component.translatable("book.invalid.tag", NamedTextColor.DARK_RED), - session.locale() - ) - )); - tag.put(new ListTag("pages", List.of(invalidTagPage))); + WrittenBookContent bookContent = components.get(DataComponentType.WRITTEN_BOOK_CONTENT); + if (bookContent == null) { + return; } + List bedrockPages = new ArrayList<>(); + for (Filterable page : bookContent.getPages()) { + NbtMapBuilder pageBuilder = NbtMap.builder(); + pageBuilder.putString("photoname", ""); + pageBuilder.putString("text", MessageTranslator.convertMessage(page.getRaw())); + bedrockPages.add(pageBuilder.build()); + } + builder.putList("pages", NbtType.COMPOUND, bedrockPages); + + builder.putString("title", bookContent.getTitle().getRaw()) + .putString("author", bookContent.getAuthor()); + // TODO isResolved } private boolean isValidWrittenBook(CompoundTag tag) { diff --git a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java index a3f6b55e4..6e7223da0 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java @@ -25,11 +25,12 @@ package org.geysermc.geyser.level; +import com.github.steveice10.mc.protocol.data.game.RegistryEntry; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; -import org.geysermc.geyser.util.JavaCodecUtil; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import java.util.Map; +import java.util.List; /** * Represents the information we store from the current Java dimension @@ -38,19 +39,20 @@ import java.util.Map; */ public record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale) { - public static void load(CompoundTag tag, Map map) { - for (CompoundTag dimension : JavaCodecUtil.iterateAsTag(tag.get("minecraft:dimension_type"))) { - CompoundTag elements = dimension.get("element"); - int minY = ((IntTag) elements.get("min_y")).getValue(); - int maxY = ((IntTag) elements.get("height")).getValue(); + public static void load(List entries, Int2ObjectMap map) { + for (int i = 0; i < entries.size(); i++) { + RegistryEntry entry = entries.get(i); + CompoundTag dimension = entry.getData(); + int minY = ((IntTag) dimension.get("min_y")).getValue(); + int maxY = ((IntTag) dimension.get("height")).getValue(); // Logical height can be ignored probably - seems to be for artificial limits like the Nether. // Set if piglins/hoglins should shake - boolean piglinSafe = ((Number) elements.get("piglin_safe").getValue()).byteValue() != (byte) 0; + boolean piglinSafe = ((Number) dimension.get("piglin_safe").getValue()).byteValue() != (byte) 0; // Load world coordinate scale for the world border - double coordinateScale = ((Number) elements.get("coordinate_scale").getValue()).doubleValue(); + double coordinateScale = ((Number) dimension.get("coordinate_scale").getValue()).doubleValue(); - map.put((String) dimension.get("name").getValue(), new JavaDimension(minY, maxY, piglinSafe, coordinateScale)); + map.put(i, new JavaDimension(minY, maxY, piglinSafe, coordinateScale)); } } } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java index a2951116f..121c70f90 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java @@ -79,7 +79,7 @@ public final class LocalSession extends TcpSession { public void initChannel(@NonNull LocalChannelWithRemoteAddress channel) { channel.spoofedRemoteAddress(new InetSocketAddress(clientIp, 0)); PacketProtocol protocol = getPacketProtocol(); - protocol.newClientSession(LocalSession.this); + protocol.newClientSession(LocalSession.this, false); refreshReadTimeoutHandler(channel); refreshWriteTimeoutHandler(channel); diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java index 185eca694..8a0fb1f40 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java @@ -56,13 +56,7 @@ public class EnchantmentRegistryLoader implements RegistryLoader entry = it.next(); JavaEnchantment key = JavaEnchantment.getByJavaIdentifier(entry.getKey()); JsonNode node = entry.getValue(); - int rarityMultiplier = switch (node.get("rarity").textValue()) { - case "common" -> 1; - case "uncommon" -> 2; - case "rare" -> 4; - case "very_rare" -> 8; - default -> throw new IllegalStateException("Unexpected value: " + node.get("rarity").textValue()); - }; + int rarityMultiplier = node.get("anvil_cost").asInt(); int maxLevel = node.get("max_level").asInt(); EnumSet incompatibleEnchantments = EnumSet.noneOf(JavaEnchantment.class); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java index 56de1081e..70a5e1ad9 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java @@ -37,9 +37,11 @@ public class Conversion649_630 { String identifer = mapping.getBedrockIdentifier(); switch (identifer) { - case "minecraft:turtle_scute" -> { return mapping.withBedrockIdentifier("minecraft:scute"); } + case "minecraft:armadillo_scute", "minecraft:turtle_scute" -> { return mapping.withBedrockIdentifier("minecraft:scute"); } + case "minecraft:armadillo_spawn_egg" -> { return mapping.withBedrockIdentifier("minecraft:rabbit_spawn_egg"); } case "minecraft:trial_spawner" -> { return mapping.withBedrockIdentifier("minecraft:mob_spawner"); } case "minecraft:trial_key" -> { return mapping.withBedrockIdentifier("minecraft:echo_shard"); } + case "minecraft:wolf_armor" -> { return mapping.withBedrockIdentifier("minecraft:leather_horse_armor"); } default -> { return mapping; } } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java index 0fe1610f2..041afdbc8 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java @@ -35,7 +35,7 @@ import java.util.stream.Stream; public class Conversion662_649 { - private static final List NEW_MISC = List.of("minecraft:grass_block", "minecraft:trial_spawner"); + private static final List NEW_MISC = List.of("minecraft:grass_block", "minecraft:vault"); private static final List NEW_WOODS = List.of("minecraft:oak_wood", "minecraft:spruce_wood", "minecraft:birch_wood", "minecraft:jungle_wood", "minecraft:acacia_wood", "minecraft:dark_oak_wood", "minecraft:stripped_oak_wood", "minecraft:stripped_spruce_wood", "minecraft:stripped_birch_wood", "minecraft:stripped_jungle_wood", "minecraft:stripped_acacia_wood", "minecraft:stripped_dark_oak_wood"); private static final List NEW_LEAVES = List.of("minecraft:oak_leaves", "minecraft:spruce_leaves", "minecraft:birch_leaves", "minecraft:jungle_leaves"); private static final List NEW_LEAVES2 = List.of("minecraft:acacia_leaves", "minecraft:dark_oak_leaves"); @@ -48,9 +48,12 @@ public class Conversion662_649 { String identifer = mapping.getBedrockIdentifier(); - if (identifer.equals("minecraft:grass_block")) { - return mapping.withBedrockIdentifier("minecraft:grass"); - } + switch (identifer) { + case "minecraft:bogged_spawn_egg" -> { return mapping.withBedrockIdentifier("minecraft:creeper_spawn_egg"); } + case "minecraft:grass_block" -> { return mapping.withBedrockIdentifier("minecraft:grass"); } + case "minecraft:vault" -> { return mapping.withBedrockIdentifier("minecraft:trial_spawner"); } + case "minecraft:wind_charge" -> { return mapping.withBedrockIdentifier("minecraft:snowball"); } + }; if (NEW_WOODS.contains(identifer)) { switch (identifer) { @@ -114,6 +117,19 @@ public class Conversion662_649 { return builder.build(); } + if (name.equals("minecraft:vault")) { + replacement = "minecraft:trial_spawner"; + + NbtMapBuilder statesBuilder = NbtMap.builder() + .putInt("trial_spawner_state", 0); + + NbtMapBuilder builder = tag.toBuilder(); + builder.putString("name", replacement); + builder.putCompound("states", statesBuilder.build()); + + return builder.build(); + } + if (NEW_WOODS.contains(name)) { replacement = "minecraft:wood"; diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java index 2c6db7567..29ab3f2e5 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.registry.populator; import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.type.GeyserMappingItem; @@ -33,11 +34,12 @@ import java.util.List; import java.util.stream.Stream; public class Conversion671_662 { + private static final List NEW_MISC = List.of("minecraft:heavy_core", "minecraft:mace", "minecraft:flow_banner_pattern", "minecraft:guster_banner_pattern", "minecraft:flow_armor_trim_smithing_template", "minecraft:bolt_armor_trim_smithing_template", "minecraft:flow_pottery_sherd", "minecraft:guster_pottery_sherd", "minecraft:scrape_pottery_sherd", "minecraft:breeze_rod"); private static final List NEW_CORAL_FANS = List.of("minecraft:tube_coral_fan", "minecraft:brain_coral_fan", "minecraft:bubble_coral_fan", "minecraft:fire_coral_fan", "minecraft:horn_coral_fan"); private static final List NEW_DEAD_CORAL_FANS = List.of("minecraft:dead_tube_coral_fan", "minecraft:dead_brain_coral_fan", "minecraft:dead_bubble_coral_fan", "minecraft:dead_fire_coral_fan", "minecraft:dead_horn_coral_fan"); private static final List NEW_FLOWERS = List.of("minecraft:poppy", "minecraft:blue_orchid", "minecraft:allium", "minecraft:azure_bluet", "minecraft:red_tulip", "minecraft:orange_tulip", "minecraft:white_tulip", "minecraft:pink_tulip", "minecraft:oxeye_daisy", "minecraft:cornflower", "minecraft:lily_of_the_valley"); private static final List NEW_SAPLINGS = List.of("minecraft:oak_sapling", "minecraft:spruce_sapling", "minecraft:birch_sapling", "minecraft:jungle_sapling", "minecraft:acacia_sapling", "minecraft:dark_oak_sapling", "minecraft:bamboo_sapling"); - private static final List NEW_BLOCKS = Stream.of(NEW_CORAL_FANS, NEW_DEAD_CORAL_FANS, NEW_FLOWERS, NEW_SAPLINGS).flatMap(List::stream).toList(); + private static final List NEW_BLOCKS = Stream.of(NEW_MISC, NEW_CORAL_FANS, NEW_DEAD_CORAL_FANS, NEW_FLOWERS, NEW_SAPLINGS).flatMap(List::stream).toList(); static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { String identifer = mapping.getBedrockIdentifier(); @@ -46,6 +48,18 @@ public class Conversion671_662 { return mapping; } + switch (identifer) { + case "minecraft:bolt_armor_trim_smithing_template" -> { return mapping.withBedrockIdentifier("minecraft:wayfinder_armor_trim_smithing_template"); } + case "minecraft:breeze_rod" -> { return mapping.withBedrockIdentifier("minecraft:blaze_rod"); } + case "minecraft:flow_armor_trim_smithing_template" -> { return mapping.withBedrockIdentifier("minecraft:spire_armor_trim_smithing_template"); } + case "minecraft:flow_banner_pattern", "minecraft:guster_banner_pattern" -> { return mapping.withBedrockIdentifier("minecraft:globe_banner_pattern"); } + case "minecraft:flow_pottery_sherd" -> { return mapping.withBedrockIdentifier("minecraft:skull_pottery_sherd"); } + case "minecraft:guster_pottery_sherd" -> { return mapping.withBedrockIdentifier("minecraft:shelter_pottery_sherd"); } + case "minecraft:scrape_pottery_sherd" -> { return mapping.withBedrockIdentifier("minecraft:heartbreak_pottery_sherd"); } + case "minecraft:heavy_core" -> { return mapping.withBedrockIdentifier("minecraft:conduit"); } + case "minecraft:mace" -> { return mapping.withBedrockIdentifier("minecraft:netherite_axe"); } + } + if (NEW_FLOWERS.contains(identifer)) { switch (identifer) { case "minecraft:poppy" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(0); } @@ -114,6 +128,15 @@ public class Conversion671_662 { String replacement; + if (name.equals("minecraft:heavy_core")) { + replacement = "minecraft:conduit"; + + NbtMapBuilder builder = tag.toBuilder(); + builder.putString("name", replacement); + + return builder.build(); + } + if (NEW_SAPLINGS.contains(name)) { replacement = "minecraft:sapling"; String saplingType = name.replaceAll("minecraft:|_sapling", "");; diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index aff21182e..756bb1bde 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -45,6 +45,7 @@ import com.github.steveice10.mc.protocol.data.game.statistic.Statistic; import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundClientInformationPacket; import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandSignedPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; @@ -360,14 +361,14 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * As all entities are in the same world, this can be safely applied to all other entities. */ @Setter - private String dimension = DimensionUtils.OVERWORLD; + private int dimension = DimensionUtils.OVERWORLD; @MonotonicNonNull @Setter private JavaDimension dimensionType = null; /** * All dimensions that the client could possibly connect to. */ - private final Map dimensions = new Object2ObjectOpenHashMap<>(3); + private final Int2ObjectMap dimensions = new Int2ObjectOpenHashMap<>(4); private final Int2ObjectMap chatTypes = new Int2ObjectOpenHashMap<>(7); @@ -1460,7 +1461,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * Sends a command to the Java server. */ public void sendCommand(String command) { - sendDownstreamGamePacket(new ServerboundChatCommandPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyList(), 0, new BitSet())); + sendDownstreamGamePacket(new ServerboundChatCommandSignedPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyList(), 0, new BitSet())); } public void setServerRenderDistance(int renderDistance) { diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java index 4bd2244ab..eced0e50b 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java @@ -25,13 +25,14 @@ package org.geysermc.geyser.session.cache; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.LodestoneTracker; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.GeyserItemStack; import java.util.Map; @@ -54,22 +55,27 @@ public final class LodestoneCache { private int id = 1; public void cacheInventoryItem(GeyserItemStack itemStack) { - CompoundTag tag = itemStack.getNbt(); - if (tag == null) { + DataComponents components = itemStack.getComponents(); + if (components == null) { // invalid return; } - CompoundTag lodestonePos = tag.get("LodestonePos"); - if (lodestonePos == null) { - // invalid + LodestoneTracker tracker = components.get(DataComponentType.LODESTONE_TRACKER); + if (tracker == null) { return; } - // Get all info needed for tracking - int x = ((IntTag) lodestonePos.get("X")).getValue(); - int y = ((IntTag) lodestonePos.get("Y")).getValue(); - int z = ((IntTag) lodestonePos.get("Z")).getValue(); - String dim = ((StringTag) tag.get("LodestoneDimension")).getValue(); + GlobalPos position = tracker.getPos(); + + if (position == null) { + GeyserImpl.getInstance().getLogger().error("Position is null. Find out why."); + Thread.dumpStack(); + return; + } + int x = position.getX(); + int y = position.getY(); + int z = position.getZ(); + String dim = position.getDimension(); for (LodestonePos pos : this.activeLodestones.values()) { if (pos.equals(x, y, z, dim)) { @@ -90,17 +96,17 @@ public final class LodestoneCache { } public int store(LodestoneTracker tracker) { - CompoundTag lodestonePos = tag.get("LodestonePos"); - if (lodestonePos == null) { - // invalid - return 0; - } + GlobalPos position = tracker.getPos(); - // Get all info needed for tracking - int x = ((IntTag) lodestonePos.get("X")).getValue(); - int y = ((IntTag) lodestonePos.get("Y")).getValue(); - int z = ((IntTag) lodestonePos.get("Z")).getValue(); - String dim = ((StringTag) tag.get("LodestoneDimension")).getValue(); + if (position == null) { + GeyserImpl.getInstance().getLogger().error("Position is null. Find out why."); + Thread.dumpStack(); + return -1; + } + int x = position.getX(); + int y = position.getY(); + int z = position.getZ(); + String dim = position.getDimension(); for (LodestonePos pos : this.activeLodestones.values()) { if (pos.equals(x, y, z, dim)) { diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java index 5acfc1f09..57000bf8b 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java @@ -58,7 +58,7 @@ public class TagCache { private IntList requiresDiamondTool; /* Items */ - private IntList axolotlTemptItems; + private IntList axolotlFood; private IntList creeperIgniters; private IntList fishes; private IntList flowers; @@ -96,7 +96,7 @@ public class TagCache { } Map itemTags = packet.getTags().get("minecraft:item"); - this.axolotlTemptItems = IntList.of(itemTags.get("minecraft:axolotl_tempt_items")); + this.axolotlFood = IntList.of(itemTags.get("minecraft:axolotl_food")); this.creeperIgniters = load(itemTags.get("minecraft:creeper_igniters")); this.fishes = IntList.of(itemTags.get("minecraft:fishes")); this.flowers = IntList.of(itemTags.get("minecraft:flowers")); @@ -133,7 +133,7 @@ public class TagCache { this.requiresIronTool = IntLists.emptyList(); this.requiresDiamondTool = IntLists.emptyList(); - this.axolotlTemptItems = IntLists.emptyList(); + this.axolotlFood = IntLists.emptyList(); this.creeperIgniters = IntLists.emptyList(); this.fishes = IntLists.emptyList(); this.flowers = IntLists.emptyList(); @@ -143,8 +143,8 @@ public class TagCache { this.snifferFood = IntLists.emptyList(); } - public boolean isAxolotlTemptItem(Item item) { - return axolotlTemptItems.contains(item.javaId()); + public boolean isAxolotlFood(Item item) { + return axolotlFood.contains(item.javaId()); } public boolean isCreeperIgniter(Item item) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java index 0e43ba660..6c7a11ff2 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.translator.inventory; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; @@ -51,6 +52,7 @@ import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.session.GeyserSession; import java.util.Collections; +import java.util.HashMap; import java.util.List; public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { @@ -154,9 +156,10 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { GeyserItemStack inputCopy = inventory.getItem(0).copy(1); inputCopy.setNetId(session.getNextItemNetId()); // Add the pattern manually, for better item synchronization - if (inputCopy.getNbt() == null) { - inputCopy.setNbt(new CompoundTag("")); + if (inputCopy.getComponents() == null) { + inputCopy.setComponents(new DataComponents(new HashMap<>())); } + //TODO CompoundTag blockEntityTag = inputCopy.getNbt().get("BlockEntityTag"); CompoundTag javaBannerPattern = BannerItem.getJavaBannerPattern(pattern); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java index 429b577ce..b461c7afc 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java @@ -360,7 +360,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { return rejectRequest(request); } - ServerboundSetCreativeModeSlotPacket creativeDropPacket = new ServerboundSetCreativeModeSlotPacket(-1, sourceItem.getItemStack(dropAction.getCount())); + ServerboundSetCreativeModeSlotPacket creativeDropPacket = new ServerboundSetCreativeModeSlotPacket((short)-1, sourceItem.getItemStack(dropAction.getCount())); session.sendDownstreamGamePacket(creativeDropPacket); sourceItem.sub(dropAction.getCount()); @@ -493,9 +493,9 @@ public class PlayerInventoryTranslator extends InventoryTranslator { dropStack = javaCreativeItem; } else { // Specify custom count - dropStack = new ItemStack(javaCreativeItem.getId(), dropAction.getCount(), javaCreativeItem.getNbt()); + dropStack = new ItemStack(javaCreativeItem.getId(), dropAction.getCount(), javaCreativeItem.getDataComponents()); } - ServerboundSetCreativeModeSlotPacket creativeDropPacket = new ServerboundSetCreativeModeSlotPacket(-1, dropStack); + ServerboundSetCreativeModeSlotPacket creativeDropPacket = new ServerboundSetCreativeModeSlotPacket((short)-1, dropStack); session.sendDownstreamGamePacket(creativeDropPacket); break; } @@ -516,7 +516,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { GeyserItemStack item = inventory.getItem(slot); ItemStack itemStack = item.isEmpty() ? new ItemStack(-1, 0, null) : item.getItemStack(); - ServerboundSetCreativeModeSlotPacket creativePacket = new ServerboundSetCreativeModeSlotPacket(slot, itemStack); + ServerboundSetCreativeModeSlotPacket creativePacket = new ServerboundSetCreativeModeSlotPacket((short)slot, itemStack); session.sendDownstreamGamePacket(creativePacket); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java index 83293d4ee..52d5b7e31 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java @@ -34,6 +34,7 @@ import org.geysermc.geyser.registry.type.ItemMapping; import java.util.ArrayList; import java.util.List; +import java.util.OptionalInt; /** * An intermediary class made to allow easy access to work-in-progress NBT, such as lore and display. @@ -44,12 +45,18 @@ public final class BedrockItemBuilder { private String customName; @Nullable private List lore; + private OptionalInt damage = OptionalInt.empty(); /** * Miscellaneous NBT that will be put into the final item. */ @Nullable private NbtMapBuilder builder; + @Nullable + public String getCustomName() { + return customName; + } + public BedrockItemBuilder setCustomName(String customName) { this.customName = customName; return this; @@ -63,6 +70,15 @@ public final class BedrockItemBuilder { return lore; } + public OptionalInt getDamage() { + return damage; + } + + public BedrockItemBuilder setDamage(int damage) { + this.damage = OptionalInt.of(damage); + return this; + } + @NonNull public NbtMapBuilder getOrCreateNbt() { if (builder == null) { @@ -85,6 +101,14 @@ public final class BedrockItemBuilder { return getOrCreateNbt().putInt(name, value); } + public NbtMapBuilder putList(String name, NbtType type, List value) { + return getOrCreateNbt().putList(name, type, value); + } + + public NbtMapBuilder putLong(String name, long value) { + return getOrCreateNbt().putLong(name, value); + } + public NbtMapBuilder putString(String name, String value) { return getOrCreateNbt().putString(name, value); } @@ -108,6 +132,9 @@ public final class BedrockItemBuilder { } getOrCreateNbt().put("display", display.build()); } + if (damage.isPresent()) { + getOrCreateNbt().putInt("Damage", damage.getAsInt()); + } if (builder == null) { return null; } @@ -115,13 +142,12 @@ public final class BedrockItemBuilder { } /** - * Creates item NBT with count, name, and damage set. + * Creates item NBT to nest within NBT with name, count, and damage set. */ public static NbtMapBuilder createItemNbt(ItemMapping mapping, int count, int damage) { NbtMapBuilder builder = NbtMap.builder(); - builder.putByte("Count", (byte) count); builder.putString("Name", mapping.getBedrockIdentifier()); - + builder.putByte("Count", (byte) count); builder.putShort("Damage", (short) damage); return builder; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 6459aa9ec..c96542fc1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -30,52 +30,42 @@ import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.entity.attribute.ModifierOperation; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.item.component.AdventureModePredicate; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.ItemAttributeModifiers; -import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag; -import com.github.steveice10.opennbt.tag.builtin.ByteTag; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.DoubleTag; -import com.github.steveice10.opennbt.tag.builtin.FloatTag; -import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.LongArrayTag; -import com.github.steveice10.opennbt.tag.builtin.LongTag; -import com.github.steveice10.opennbt.tag.builtin.ShortTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; -import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.CustomSkull; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.skin.SkinManager; -import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.InventoryUtils; import java.text.DecimalFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public final class ItemTranslator { @@ -161,9 +151,9 @@ public final class ItemTranslator { addAdvancedTooltips(components, nbtBuilder, javaItem, session.locale()); } - ItemStack itemStack = new ItemStack(javaItem.javaId(), count, components); - - ItemData.Builder builder = javaItem.translateToBedrock(itemStack, bedrockItem, session.getItemMappings()); + ItemData.Builder builder = javaItem.translateToBedrock(count, components, bedrockItem, session.getItemMappings()); + // Finalize the Bedrock NBT + builder.tag(nbtBuilder.build()); if (bedrockItem.isBlock()) { CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault( bedrockItem.getJavaItem().javaIdentifier(), null); @@ -357,7 +347,7 @@ public final class ItemTranslator { return ItemDefinition.AIR; } - ItemMapping mapping = itemStack.asItem().toBedrockDefinition(itemStack.getNbt(), session.getItemMappings()); + ItemMapping mapping = itemStack.asItem().toBedrockDefinition(itemStack.getComponents(), session.getItemMappings()); ItemDefinition itemDefinition = mapping.getBedrockDefinition(); CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault( @@ -563,20 +553,21 @@ public final class ItemTranslator { if (components == null) { return null; } + //TODO GameProfile profile = components.get(DataComponentType.PROFILE); if (profile != null) { - if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) { - // It's a username give up d: - return null; - } - SkinManager.GameProfileData data = SkinManager.GameProfileData.from(skullOwner); - if (data == null) { - session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt); - return null; - } - - String skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1); - return BlockRegistries.CUSTOM_SKULLS.get(skinHash); +// if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) { +// // It's a username give up d: +// return null; +// } +// SkinManager.GameProfileData data = SkinManager.GameProfileData.from(skullOwner); +// if (data == null) { +// session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt); +// return null; +// } +// +// String skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1); +// return BlockRegistries.CUSTOM_SKULLS.get(skinHash); } return null; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/BiomeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/BiomeTranslator.java index 90ac1cc5e..d4288c5a7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/BiomeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/BiomeTranslator.java @@ -25,15 +25,13 @@ package org.geysermc.geyser.translator.level; +import com.github.steveice10.mc.protocol.data.game.RegistryEntry; import com.github.steveice10.mc.protocol.data.game.chunk.BitStorage; import com.github.steveice10.mc.protocol.data.game.chunk.DataPalette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.GlobalPalette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.SingletonPalette; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import it.unimi.dsi.fastutil.ints.*; import org.geysermc.geyser.level.chunk.BlockStorage; import org.geysermc.geyser.level.chunk.bitarray.BitArray; @@ -41,24 +39,24 @@ import org.geysermc.geyser.level.chunk.bitarray.BitArrayVersion; import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.util.JavaCodecUtil; import org.geysermc.geyser.util.MathUtils; +import java.util.List; + // Array index formula by https://wiki.vg/Chunk_Format public class BiomeTranslator { - public static void loadServerBiomes(GeyserSession session, CompoundTag codec) { + public static void loadServerBiomes(GeyserSession session, List entries) { Int2IntMap biomeTranslations = new Int2IntOpenHashMap(); - CompoundTag worldGen = codec.get("minecraft:worldgen/biome"); - ListTag serverBiomes = worldGen.get("value"); - session.setBiomeGlobalPalette(MathUtils.getGlobalPaletteForSize(serverBiomes.size())); + session.setBiomeGlobalPalette(MathUtils.getGlobalPaletteForSize(entries.size())); int greatestBiomeId = 0; - for (CompoundTag biomeTag : JavaCodecUtil.iterateAsTag(worldGen)) { - String javaIdentifier = ((StringTag) biomeTag.get("name")).getValue(); + for (int i = 0; i < entries.size(); i++) { + RegistryEntry entry = entries.get(i); + String javaIdentifier = entry.getId(); int bedrockId = Registries.BIOME_IDENTIFIERS.get().getOrDefault(javaIdentifier, 0); - int javaId = ((IntTag) biomeTag.get("id")).getValue(); + int javaId = i; if (javaId > greatestBiomeId) { greatestBiomeId = javaId; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java index 59317fd7c..3781ef3c0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java @@ -69,7 +69,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator session.ensureInEventLoop(() -> { if (tag == null) { @@ -94,7 +94,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator { @@ -56,9 +53,16 @@ public class BedrockBookEditTranslator extends PacketTranslator GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(); if (itemStack != null) { - CompoundTag tag = itemStack.getNbt() != null ? itemStack.getNbt() : new CompoundTag(""); - ItemStack bookItem = new ItemStack(itemStack.getJavaId(), itemStack.getAmount(), tag); - List pages = tag.contains("pages") ? new LinkedList<>(((ListTag) tag.get("pages")).getValue()) : new LinkedList<>(); + DataComponents components = itemStack.getComponents() != null ? itemStack.getComponents() : new DataComponents(new HashMap<>()); + ItemStack bookItem = new ItemStack(itemStack.getJavaId(), itemStack.getAmount(), components); + List pages = new LinkedList<>(); + + WritableBookContent writableBookContent = components.get(DataComponentType.WRITABLE_BOOK_CONTENT); + if (writableBookContent != null) { + for (Filterable page : writableBookContent.getPages()) { + pages.add(page.getRaw()); + } + } int page = packet.getPageNumber(); if (page < 0 || WrittenBookItem.MAXIMUM_PAGE_COUNT <= page) { @@ -69,21 +73,21 @@ public class BedrockBookEditTranslator extends PacketTranslator case ADD_PAGE: { // Add empty pages in between for (int i = pages.size(); i < page; i++) { - pages.add(i, new StringTag("", "")); + pages.add(i, ""); } - pages.add(page, new StringTag("", MessageTranslator.convertToPlainText(packet.getText()))); + pages.add(page, MessageTranslator.convertToPlainText(packet.getText())); break; } // Called whenever a page is modified case REPLACE_PAGE: { if (page < pages.size()) { - pages.set(page, new StringTag("", MessageTranslator.convertToPlainText(packet.getText()))); + pages.set(page, MessageTranslator.convertToPlainText(packet.getText())); } else { // Add empty pages in between for (int i = pages.size(); i < page; i++) { - pages.add(i, new StringTag("", "")); + pages.add(i, ""); } - pages.add(page, new StringTag("", MessageTranslator.convertToPlainText(packet.getText()))); + pages.add(page, MessageTranslator.convertToPlainText(packet.getText())); } break; } @@ -100,33 +104,29 @@ public class BedrockBookEditTranslator extends PacketTranslator } break; } - case SIGN_BOOK: { - tag.put(new StringTag("author", MessageTranslator.convertToPlainText(packet.getAuthor()))); - tag.put(new StringTag("title", MessageTranslator.convertToPlainText(packet.getTitle()))); - break; - } default: return; } // Remove empty pages at the end - while (pages.size() > 0) { - StringTag currentPage = (StringTag) pages.get(pages.size() - 1); - if (currentPage.getValue() == null || currentPage.getValue().isEmpty()) { + while (!pages.isEmpty()) { + String currentPage = pages.get(pages.size() - 1); + if (currentPage.isEmpty()) { pages.remove(pages.size() - 1); } else { break; } } - tag.put(new ListTag("pages", pages)); + + List> filterablePages = new ArrayList<>(pages.size()); + for (String raw : pages) { + filterablePages.add(new Filterable<>(raw, null)); + } + components.put(DataComponentType.WRITABLE_BOOK_CONTENT, new WritableBookContent(filterablePages)); + // Update local copy session.getPlayerInventory().setItem(36 + session.getPlayerInventory().getHeldItemSlot(), GeyserItemStack.from(bookItem), session); session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory()); - List networkPages = new ArrayList<>(); - for (Tag pageTag : pages) { - networkPages.add(((StringTag) pageTag).getValue()); - } - String title; if (packet.getAction() == BookEditPacket.Action.SIGN_BOOK) { // Add title to packet so the server knows we're signing @@ -139,7 +139,7 @@ public class BedrockBookEditTranslator extends PacketTranslator title = null; } - session.getBookEditCache().setPacket(new ServerboundEditBookPacket(session.getPlayerInventory().getHeldItemSlot(), networkPages, title)); + session.getBookEditCache().setPacket(new ServerboundEditBookPacket(session.getPlayerInventory().getHeldItemSlot(), pages, title)); // There won't be any more book updates after this, so we can try sending the edit packet immediately if (packet.getAction() == BookEditPacket.Action.SIGN_BOOK) { session.getBookEditCache().checkForSend(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java index f5122b256..2fd9ce405 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java @@ -168,7 +168,7 @@ public class BedrockActionTranslator extends PacketTranslator { private static final String[] ALL_EFFECT_IDENTIFIERS = EntityUtils.getAllEffectIdentifiers(); - private static final String[] ATTRIBUTES = AttributeType.Builtin.BUILTIN.keySet().toArray(new String[0]); + private static final String[] ATTRIBUTES = AttributeType.Builtin.BUILTIN.values().stream().map(AttributeType::getIdentifier).toList().toArray(new String[0]); private static final String[] ENUM_BOOLEAN = {"true", "false"}; private static final String[] VALID_COLORS; private static final String[] VALID_SCOREBOARD_SLOTS; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index 4a15157f9..ebf99fb65 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -63,7 +63,7 @@ public class JavaLoginTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, ClientboundRegistryDataPacket packet) { - Map dimensions = session.getDimensions(); - dimensions.clear(); - JavaDimension.load(packet.getRegistry(), dimensions); - - Int2ObjectMap chatTypes = session.getChatTypes(); - chatTypes.clear(); - for (CompoundTag tag : JavaCodecUtil.iterateAsTag(packet.getRegistry().get("minecraft:chat_type"))) { - // The ID is NOT ALWAYS THE SAME! ViaVersion as of 1.19 adds two registry entries that do NOT match vanilla. - int id = ((IntTag) tag.get("id")).getValue(); - CompoundTag element = tag.get("element"); - CompoundTag chat = element.get("chat"); - TextDecoration textDecoration = null; - if (chat != null) { - textDecoration = new TextDecoration(chat); - } - chatTypes.put(id, textDecoration); + if (packet.getRegistry().equals("minecraft:dimension_type")) { + Int2ObjectMap dimensions = session.getDimensions(); + dimensions.clear(); + JavaDimension.load(packet.getEntries(), dimensions); } - BiomeTranslator.loadServerBiomes(session, packet.getRegistry()); + if (packet.getRegistry().equals("minecraft:chat_type")) { + Int2ObjectMap chatTypes = session.getChatTypes(); + chatTypes.clear(); + List entries = packet.getEntries(); + for (int i = 0; i < entries.size(); i++) { + // The ID is NOT ALWAYS THE SAME! ViaVersion as of 1.19 adds two registry entries that do NOT match vanilla. + RegistryEntry entry = entries.get(i); + CompoundTag tag = entry.getData(); + CompoundTag chat = tag.get("chat"); + TextDecoration textDecoration = null; + if (chat != null) { + textDecoration = new TextDecoration(chat); + } + chatTypes.put(i, textDecoration); + } + } + + if (packet.getRegistry().equals("minecraft:worldgen/biome")) { + BiomeTranslator.loadServerBiomes(session, packet.getEntries()); + } } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java index d69077dcb..bfb590247 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java @@ -92,11 +92,11 @@ public class JavaRespawnTranslator extends PacketTranslator { ItemStack javaItem = equipment.getItem(); - if (livingEntity instanceof PlayerEntity - && javaItem != null - && javaItem.getId() == Items.PLAYER_HEAD.javaId() - && javaItem.getNbt() != null) { - FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, javaItem.getNbt().get("SkullOwner")); - } else { - FakeHeadProvider.restoreOriginalSkin(session, livingEntity); - } + // TODO +// if (livingEntity instanceof PlayerEntity +// && javaItem != null +// && javaItem.getId() == Items.PLAYER_HEAD.javaId() +// && javaItem.getNbt() != null) { +// FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, javaItem.getNbt().get("SkullOwner")); +// } else { +// FakeHeadProvider.restoreOriginalSkin(session, livingEntity); +// } livingEntity.setHelmet(item); armorUpdated = true; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java index 78290f6bd..7d9b81d29 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java @@ -28,7 +28,6 @@ package org.geysermc.geyser.translator.protocol.java.level; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.level.particle.BlockParticleData; import com.github.steveice10.mc.protocol.data.game.level.particle.DustParticleData; -import com.github.steveice10.mc.protocol.data.game.level.particle.FallingDustParticleData; import com.github.steveice10.mc.protocol.data.game.level.particle.ItemParticleData; import com.github.steveice10.mc.protocol.data.game.level.particle.Particle; import com.github.steveice10.mc.protocol.data.game.level.particle.VibrationParticleData; @@ -106,7 +105,7 @@ public class JavaLevelParticlesTranslator extends PacketTranslator { - int blockState = session.getBlockMappings().getBedrockBlockId(((FallingDustParticleData) particle.getData()).getBlockState()); + int blockState = session.getBlockMappings().getBedrockBlockId(((BlockParticleData) particle.getData()).getBlockState()); return (position) -> { LevelEventPacket packet = new LevelEventPacket(); // In fact, FallingDustParticle should have data like DustParticle, diff --git a/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java b/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java index e1fe6e6f2..d79d606b4 100644 --- a/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java @@ -45,12 +45,12 @@ public class AttributeUtils { } double value = base; for (AttributeModifier modifier : attribute.getModifiers()) { - if (modifier.getOperation() == ModifierOperation.ADD_MULTIPLIED) { + if (modifier.getOperation() == ModifierOperation.ADD_MULTIPLIED_BASE) { value += base * modifier.getAmount(); } } for (AttributeModifier modifier : attribute.getModifiers()) { - if (modifier.getOperation() == ModifierOperation.MULTIPLY) { + if (modifier.getOperation() == ModifierOperation.ADD_MULTIPLIED_TOTAL) { value *= 1.0D + modifier.getAmount(); } } diff --git a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java index eaa7b5084..469accd40 100644 --- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java @@ -50,19 +50,19 @@ public class DimensionUtils { /** * String reference to vanilla Java overworld dimension identifier */ - public static final String OVERWORLD = "minecraft:overworld"; + public static final int OVERWORLD = 0; /** * String reference to vanilla Java nether dimension identifier */ - public static final String NETHER = "minecraft:the_nether"; + public static final int NETHER = 3; /** * String reference to vanilla Java end dimension identifier */ - public static final String THE_END = "minecraft:the_end"; + public static final int THE_END = 2; - public static void switchDimension(GeyserSession session, String javaDimension) { + public static void switchDimension(GeyserSession session, int javaDimension) { int bedrockDimension = javaToBedrock(javaDimension); // new bedrock dimension - String previousDimension = session.getDimension(); // previous java dimension + int previousDimension = session.getDimension(); // previous java dimension Entity player = session.getPlayerEntity(); @@ -142,15 +142,15 @@ public class DimensionUtils { // we check if the player is entering the nether and apply the nether fog to fake the fact that the client // thinks they are in the end dimension. if (isCustomBedrockNetherId()) { - if (NETHER.equals(javaDimension)) { + if (NETHER == javaDimension) { session.camera().sendFog(BEDROCK_FOG_HELL); - } else if (NETHER.equals(previousDimension)) { + } else if (NETHER == previousDimension) { session.camera().removeFog(BEDROCK_FOG_HELL); } } } - public static void setBedrockDimension(GeyserSession session, String javaDimension) { + public static void setBedrockDimension(GeyserSession session, int javaDimension) { session.getChunkCache().setBedrockDimension(switch (javaDimension) { case DimensionUtils.THE_END -> BedrockDimension.THE_END; case DimensionUtils.NETHER -> DimensionUtils.isCustomBedrockNetherId() ? BedrockDimension.THE_END : BedrockDimension.THE_NETHER; @@ -174,7 +174,7 @@ public class DimensionUtils { * @param javaDimension Dimension ID to convert * @return Converted Bedrock edition dimension ID */ - public static int javaToBedrock(String javaDimension) { + public static int javaToBedrock(int javaDimension) { return switch (javaDimension) { case NETHER -> BEDROCK_NETHER_ID; case THE_END -> 2; @@ -182,6 +182,20 @@ public class DimensionUtils { }; } + /** + * Map the Java edition dimension IDs to Bedrock edition + * + * @param javaDimension Dimension ID to convert + * @return Converted Bedrock edition dimension ID + */ + public static int javaToBedrock(String javaDimension) { + return switch (javaDimension) { + case "minecraft:the_nether" -> BEDROCK_NETHER_ID; + case "minecraft:the_end" -> 2; + default -> 0; + }; + } + /** * The Nether dimension in Bedrock does not permit building above Y128 - the Bedrock above the dimension. * This workaround sets the Nether as the End dimension to ignore this limit. @@ -201,7 +215,7 @@ public class DimensionUtils { * @param newDimension the new dimension that the player will be transferred to * @return the fake dimension to transfer to */ - public static String getTemporaryDimension(String currentDimension, String newDimension) { + public static int getTemporaryDimension(int currentDimension, int newDimension) { if (isCustomBedrockNetherId()) { // Prevents rare instances of Bedrock locking up return javaToBedrock(newDimension) == 2 ? OVERWORLD : NETHER; diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index e56aea8c9..08c2b6cdb 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; @@ -42,11 +42,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerHotbarPacket; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.inventory.Container; -import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.inventory.Inventory; -import org.geysermc.geyser.inventory.LecternContainer; -import org.geysermc.geyser.inventory.PlayerInventory; +import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.click.Click; import org.geysermc.geyser.inventory.recipe.GeyserRecipe; import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe; @@ -66,6 +62,7 @@ import org.jetbrains.annotations.Contract; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.function.IntFunction; @@ -77,7 +74,7 @@ public class InventoryUtils { */ public static int LAST_RECIPE_NET_ID; - public static final ItemStack REFRESH_ITEM = new ItemStack(1, 127, new CompoundTag("")); + public static final ItemStack REFRESH_ITEM = new ItemStack(1, 127, new DataComponents(new HashMap<>())); public static void openInventory(GeyserSession session, Inventory inventory) { session.setOpenInventory(inventory); @@ -254,7 +251,7 @@ public class InventoryUtils { continue; } // If this is the item we're looking for - if (geyserItem.getJavaId() == itemStack.getId() && Objects.equals(geyserItem.getNbt(), itemStack.getNbt())) { + if (geyserItem.getJavaId() == itemStack.getId() && Objects.equals(geyserItem.getComponents(), itemStack.getDataComponents())) { //TODO verify setHotbarItem(session, i); // Don't check inventory if item was in hotbar return; @@ -268,7 +265,7 @@ public class InventoryUtils { continue; } // If this is the item we're looking for - if (geyserItem.getJavaId() == itemStack.getId() && Objects.equals(geyserItem.getNbt(), itemStack.getNbt())) { + if (geyserItem.getJavaId() == itemStack.getId() && Objects.equals(geyserItem.getComponents(), itemStack.getDataComponents())) { //TODO verify ServerboundPickItemPacket packetToSend = new ServerboundPickItemPacket(i); // https://wiki.vg/Protocol#Pick_Item session.sendDownstreamGamePacket(packetToSend); return; @@ -279,7 +276,7 @@ public class InventoryUtils { if (session.getGameMode() == GameMode.CREATIVE) { int slot = findEmptyHotbarSlot(inventory); - ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket(slot, + ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket((short) slot, itemStack); if ((slot - 36) != inventory.getHeldItemSlot()) { setHotbarItem(session, slot); @@ -345,7 +342,7 @@ public class InventoryUtils { ItemMapping mapping = session.getItemMappings().getMapping(itemName); // TODO if (mapping != null) { - ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket(slot, + ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket((short)slot, new ItemStack(mapping.getJavaItem().javaId())); if ((slot - 36) != inventory.getHeldItemSlot()) { setHotbarItem(session, slot); diff --git a/core/src/main/java/org/geysermc/geyser/util/JavaCodecUtil.java b/core/src/main/java/org/geysermc/geyser/util/JavaCodecUtil.java deleted file mode 100644 index 795d45490..000000000 --- a/core/src/main/java/org/geysermc/geyser/util/JavaCodecUtil.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser - */ - -package org.geysermc.geyser.util; - -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Iterator; - -public final class JavaCodecUtil { - - /** - * Iterate over a Java Edition codec and return each entry as a CompoundTag - */ - public static Iterable iterateAsTag(CompoundTag tag) { - ListTag value = tag.get("value"); - Iterator originalIterator = value.iterator(); - return new Iterable<>() { - @NonNull - @Override - public Iterator iterator() { - return new Iterator<>() { - @Override - public boolean hasNext() { - return originalIterator.hasNext(); - } - - @Override - public CompoundTag next() { - return (CompoundTag) originalIterator.next(); - } - }; - } - }; - } - - private JavaCodecUtil() { - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2115992ff..ae8170c4f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "1.20.4-2-20240116.220521-7" +mcprotocollib = "897eb241b6" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" @@ -107,7 +107,7 @@ guava = { group = "com.google.guava", name = "guava", version.ref = "guava" } gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" } junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" } mcauthlib = { group = "com.github.GeyserMC", name = "MCAuthLib", version.ref = "mcauthlib" } -mcprotocollib = { group = "com.github.steveice10", name = "mcprotocollib", version.ref = "mcprotocollib" } +mcprotocollib = { group = "com.github.geysermc", name = "mcprotocollib", version.ref = "mcprotocollib" } raknet = { group = "org.cloudburstmc.netty", name = "netty-transport-raknet", version.ref = "raknet" } terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" } velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }