Merge branch 'feature/1.20.5' into feature/1.20.5

This commit is contained in:
Hasan 2024-04-21 13:20:45 +03:00 committed by GitHub
commit 3dcb3650ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
58 changed files with 671 additions and 704 deletions

View File

@ -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.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.item.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.cloudburstmc.math.vector.Vector3f; 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.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket;
import org.geysermc.floodgate.util.DeviceOs;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.player.PlayerEntity; 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.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.OptionalInt;
import java.util.UUID; import java.util.UUID;
@ -59,80 +51,16 @@ public class FireworkEntity extends Entity {
if (item == null) { if (item == null) {
return; return;
} }
CompoundTag tag = item.getNbt(); DataComponents components = item.getDataComponents();
if (components == null) {
if (tag == null) {
return; return;
} }
// TODO: Remove once Mojang fixes bugs with fireworks crashing clients on these specific devices. // TODO this looked the same, so I'm going to assume it is and (keep below comment if true)
// https://bugs.mojang.com/browse/MCPE-89115 // Translate using item methods to get firework NBT for Bedrock
if (session.getClientData().getDeviceOs() == DeviceOs.XBOX BedrockItemBuilder builder = new BedrockItemBuilder();
|| session.getClientData().getDeviceOs() == DeviceOs.PS4) { Items.FIREWORK_ROCKET.translateComponentsToBedrock(session, components, builder);
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<NbtMap> 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());
dirtyMetadata.put(EntityDataTypes.DISPLAY_FIREWORK, builder.build()); dirtyMetadata.put(EntityDataTypes.DISPLAY_FIREWORK, builder.build());
} }

View File

@ -299,7 +299,7 @@ public class LivingEntity extends Entity {
case GENERIC_MOVEMENT_SPEED -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.MOVEMENT_SPEED)); case GENERIC_MOVEMENT_SPEED -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.MOVEMENT_SPEED));
case GENERIC_FOLLOW_RANGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FOLLOW_RANGE)); case GENERIC_FOLLOW_RANGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FOLLOW_RANGE));
case GENERIC_KNOCKBACK_RESISTANCE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.KNOCKBACK_RESISTANCE)); 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));
} }
} }
} }

View File

@ -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.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.item.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType;
import com.github.steveice10.opennbt.tag.builtin.Tag; 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.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -58,16 +59,17 @@ public class ThrownPotionEntity extends ThrowableItemEntity {
setFlag(EntityFlag.LINGERING, false); setFlag(EntityFlag.LINGERING, false);
} else { } else {
// As of Java 1.19.3, the server/client doesn't seem to care of the item is actually a potion? // 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) { DataComponents components = itemStack.getDataComponents();
Tag potionTag = itemStack.getNbt().get("Potion"); if (components != null) {
if (potionTag instanceof StringTag) { PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS);
Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); if (potionContents != null) {
Potion potion = Potion.VALUES[potionContents.getPotionId()];
if (potion != null) { if (potion != null) {
dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, (int) potion.getBedrockId()); dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, (int) potion.getBedrockId());
setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion)); setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion));
} else { } else {
dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, 0); dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, 0);
GeyserImpl.getInstance().getLogger().debug("Unknown java potion: " + potionTag.getValue()); GeyserImpl.getInstance().getLogger().debug("Unknown java potion: " + potionContents.getPotionId());
} }
} }

View File

@ -61,7 +61,7 @@ public class AxolotlEntity extends AnimalEntity {
@Override @Override
public boolean canEat(Item item) { public boolean canEat(Item item) {
return session.getTagCache().isAxolotlTemptItem(item); return session.getTagCache().isAxolotlFood(item);
} }
@Override @Override

View File

@ -118,7 +118,7 @@ public enum Enchantment {
KNOCKBACK, KNOCKBACK,
FIRE_ASPECT, FIRE_ASPECT,
LOOTING, LOOTING,
SWEEPING, SWEEPING_EDGE,
EFFICIENCY, EFFICIENCY,
SILK_TOUCH, SILK_TOUCH,
UNBREAKING, UNBREAKING,
@ -136,6 +136,9 @@ public enum Enchantment {
MULTISHOT, MULTISHOT,
QUICK_CHARGE, QUICK_CHARGE,
PIERCING, PIERCING,
DENSITY,
BREACH,
WIND_BURST,
MENDING, MENDING,
VANISHING_CURSE; VANISHING_CURSE;

View File

@ -36,6 +36,7 @@ import java.util.Locale;
*/ */
@Getter @Getter
public enum TippedArrowPotion { public enum TippedArrowPotion {
WATER(-1, ArrowParticleColors.NONE), // Guessing this based off of the Potion enum. TODO merge?
MUNDANE(2, ArrowParticleColors.NONE), // 3 is extended? MUNDANE(2, ArrowParticleColors.NONE), // 3 is extended?
THICK(4, ArrowParticleColors.NONE), THICK(4, ArrowParticleColors.NONE),
AWKWARD(5, ArrowParticleColors.NONE), AWKWARD(5, ArrowParticleColors.NONE),
@ -94,6 +95,10 @@ public enum TippedArrowPotion {
this.javaColor = arrowParticleColor.getColor(); this.javaColor = arrowParticleColor.getColor();
} }
public static TippedArrowPotion of(int id) {
return VALUES[id];
}
public static @Nullable TippedArrowPotion getByJavaIdentifier(String javaIdentifier) { public static @Nullable TippedArrowPotion getByJavaIdentifier(String javaIdentifier) {
for (TippedArrowPotion potion : VALUES) { for (TippedArrowPotion potion : VALUES) {
if (potion.javaIdentifier.equals(javaIdentifier)) { if (potion.javaIdentifier.equals(javaIdentifier)) {

View File

@ -350,7 +350,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
if (enchantment == JavaEnchantment.IMPALING) { if (enchantment == JavaEnchantment.IMPALING) {
// Multiplier is halved on Bedrock for some reason // Multiplier is halved on Bedrock for some reason
rarityMultiplier /= 2; rarityMultiplier /= 2;
} else if (enchantment == JavaEnchantment.SWEEPING) { } else if (enchantment == JavaEnchantment.SWEEPING_EDGE) {
// Doesn't exist on Bedrock // Doesn't exist on Bedrock
rarityMultiplier = 0; rarityMultiplier = 0;
} }

View File

@ -31,12 +31,13 @@ import java.util.function.Supplier;
public enum ArmorMaterial { public enum ArmorMaterial {
LEATHER(() -> Items.LEATHER), LEATHER(() -> Items.LEATHER),
CHAIN(() -> Items.IRON_INGOT), CHAINMAIL(() -> Items.IRON_INGOT),
IRON(() -> Items.IRON_INGOT), IRON(() -> Items.IRON_INGOT),
GOLD(() -> Items.GOLD_INGOT), GOLD(() -> Items.GOLD_INGOT),
DIAMOND(() -> Items.DIAMOND), DIAMOND(() -> Items.DIAMOND),
TURTLE(() -> Items.SCUTE), TURTLE(() -> Items.TURTLE_SCUTE),
NETHERITE(() -> Items.NETHERITE_INGOT); NETHERITE(() -> Items.NETHERITE_INGOT),
ARMADILLO(() -> Items.ARMADILLO_SCUTE);
private final Supplier<Item> repairIngredient; private final Supplier<Item> repairIngredient;

View File

@ -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_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_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 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 AMETHYST_BLOCK = register(new BlockItem("amethyst_block", builder()));
public static final Item BUDDING_AMETHYST = register(new BlockItem("budding_amethyst", 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())); 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 STRUCTURE_BLOCK = register(new BlockItem("structure_block", builder()));
public static final Item JIGSAW = register(new BlockItem("jigsaw", 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 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 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 APPLE = register(new Item("apple", builder()));
public static final Item BOW = register(new Item("bow", builder().stackSize(1).maxDamage(384))); 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 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_INGOT = register(new Item("netherite_ingot", builder()));
public static final Item NETHERITE_SCRAP = register(new Item("netherite_scrap", 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_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).attackDamage(2.5).maxDamage(59))); 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).attackDamage(2).maxDamage(59))); 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).attackDamage(7).maxDamage(59))); 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).attackDamage(1).maxDamage(59))); 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).attackDamage(5).maxDamage(131))); 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).attackDamage(3.5).maxDamage(131))); 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).attackDamage(3).maxDamage(131))); 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).attackDamage(9).maxDamage(131))); 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).attackDamage(1).maxDamage(131))); 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).attackDamage(4).maxDamage(32))); 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).attackDamage(2.5).maxDamage(32))); 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).attackDamage(2).maxDamage(32))); 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).attackDamage(7).maxDamage(32))); 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).attackDamage(1).maxDamage(32))); 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).attackDamage(6).maxDamage(250))); 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).attackDamage(4.5).maxDamage(250))); 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).attackDamage(4).maxDamage(250))); 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).attackDamage(9).maxDamage(250))); 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).attackDamage(1).maxDamage(250))); 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).attackDamage(7).maxDamage(1561))); 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).attackDamage(5.5).maxDamage(1561))); 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).attackDamage(5).maxDamage(1561))); 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).attackDamage(9).maxDamage(1561))); 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).attackDamage(1).maxDamage(1561))); 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).attackDamage(8).maxDamage(2031))); 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).attackDamage(6.5).maxDamage(2031))); 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).attackDamage(6).maxDamage(2031))); 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).attackDamage(10).maxDamage(2031))); 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).attackDamage(1).maxDamage(2031))); 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 STICK = register(new Item("stick", builder()));
public static final Item BOWL = register(new Item("bowl", 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))); 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_SEEDS = register(new BlockItem("wheat_seeds", builder()));
public static final Item WHEAT = register(new Item("wheat", 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 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_HELMET = register(new ArmorItem("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_CHESTPLATE = register(new ArmorItem("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_LEGGINGS = register(new ArmorItem("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 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.CHAIN, builder().stackSize(1).maxDamage(165))); 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.CHAIN, builder().stackSize(1).maxDamage(240))); 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.CHAIN, builder().stackSize(1).maxDamage(225))); 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.CHAIN, builder().stackSize(1).maxDamage(195))); 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_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_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))); 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 CAULDRON = register(new BlockItem("cauldron", builder()));
public static final Item ENDER_EYE = register(new Item("ender_eye", 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 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 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 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 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 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 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 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 CAT_SPAWN_EGG = register(new SpawnEggItem("cat_spawn_egg", builder()));
public static final Item CAMEL_SPAWN_EGG = register(new SpawnEggItem("camel_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 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 EXPERIENCE_BOTTLE = register(new Item("experience_bottle", builder()));
public static final Item FIRE_CHARGE = register(new Item("fire_charge", 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 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 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 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 GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder()));
public static final Item FLOWER_POT = register(new BlockItem("flower_pot", 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_FOOT = register(new Item("rabbit_foot", builder()));
public static final Item RABBIT_HIDE = register(new Item("rabbit_hide", 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 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 IRON_HORSE_ARMOR = register(new ArmorItem("iron_horse_armor", ArmorMaterial.IRON, builder().stackSize(1)));
public static final Item GOLDEN_HORSE_ARMOR = register(new Item("golden_horse_armor", 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 Item("diamond_horse_armor", 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 DyeableHorseArmorItem("leather_horse_armor", 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 LEAD = register(new Item("lead", builder()));
public static final Item NAME_TAG = register(new Item("name_tag", 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))); 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_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 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 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 PHANTOM_MEMBRANE = register(new Item("phantom_membrane", builder()));
public static final Item NAUTILUS_SHELL = register(new Item("nautilus_shell", 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())); 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 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 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 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 GOAT_HORN = register(new GoatHornItem("goat_horn", builder().stackSize(1)));
public static final Item COMPOSTER = register(new BlockItem("composter", builder())); public static final Item COMPOSTER = register(new BlockItem("composter", builder()));
public static final Item BARREL = register(new ChestItem("barrel", 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 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 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 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 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 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())); 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 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 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 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 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 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 HEARTBREAK_POTTERY_SHERD = register(new Item("heartbreak_pottery_sherd", builder()));
public static final Item HOWL_POTTERY_SHERD = register(new Item("howl_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 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 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 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 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 SHELTER_POTTERY_SHERD = register(new Item("shelter_pottery_sherd", builder()));
public static final Item SKULL_POTTERY_SHERD = register(new Item("skull_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 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_SPAWNER = register(new BlockItem("trial_spawner", builder()));
public static final Item TRIAL_KEY = register(new Item("trial_key", 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(); public static final int AIR_ID = AIR.javaId();

View File

@ -26,8 +26,6 @@
package org.geysermc.geyser.item.type; 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.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 com.github.steveice10.opennbt.tag.builtin.StringTag;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
@ -48,7 +46,7 @@ public class ArrowItem extends Item {
if (tippedArrowPotion != null) { if (tippedArrowPotion != null) {
itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getDataComponents()); itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getDataComponents());
StringTag potionTag = new StringTag("Potion", tippedArrowPotion.getJavaIdentifier()); 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; return itemStack;
} }

View File

@ -56,14 +56,14 @@ public class BannerItem extends BlockItem {
static { static {
// Construct what an ominous banner is supposed to look like // Construct what an ominous banner is supposed to look like
OMINOUS_BANNER_PATTERN = List.of( OMINOUS_BANNER_PATTERN = List.of(
new BannerPatternLayer("mr", 9), // new BannerPatternLayer("mr", 9),
new BannerPatternLayer("bs", 8), // new BannerPatternLayer("bs", 8),
new BannerPatternLayer("cs", 7), // new BannerPatternLayer("cs", 7),
new BannerPatternLayer("bo", 8), // new BannerPatternLayer("bo", 8),
new BannerPatternLayer("ms", 15), // new BannerPatternLayer("ms", 15),
new BannerPatternLayer("hh", 8), // new BannerPatternLayer("hh", 8),
new BannerPatternLayer("mc", 8), // new BannerPatternLayer("mc", 8),
new BannerPatternLayer("bo", 15) // new BannerPatternLayer("bo", 15)
); );
} }
@ -103,7 +103,8 @@ public class BannerItem extends BlockItem {
* @return The Java edition format pattern nbt * @return The Java edition format pattern nbt
*/ */
public static CompoundTag getJavaBannerPattern(NbtMap pattern) { 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<BannerPatternLayer> patterns = components.get(DataComponentType.BANNER_PATTERNS); List<BannerPatternLayer> patterns = components.get(DataComponentType.BANNER_PATTERNS);
if (patterns != null) { if (patterns != null) {
if (patterns.equals(OMINOUS_BANNER_PATTERN)) { // if (patterns.equals(OMINOUS_BANNER_PATTERN)) {
// Remove the current patterns and set the ominous banner type // // Remove the current patterns and set the ominous banner type
builder.putInt("Type", 1); // builder.putInt("Type", 1);
} else { // } else {
invertBannerColors(patterns); // invertBannerColors(patterns);
tag.put(patterns); // tag.put(patterns);
} // }
} }
} }
@ -146,7 +147,7 @@ public class BannerItem extends BlockItem {
// Ominous banner pattern // Ominous banner pattern
tag.remove("Type"); tag.remove("Type");
CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag"); CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag");
blockEntityTag.put(OMINOUS_BANNER_PATTERN); //blockEntityTag.put(OMINOUS_BANNER_PATTERN);
tag.put(blockEntityTag); tag.put(blockEntityTag);
} else if (tag.get("Patterns") instanceof ListTag patterns) { } else if (tag.get("Patterns") instanceof ListTag patterns) {

View File

@ -43,11 +43,11 @@ public class CompassItem extends Item {
} }
@Override @Override
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
if (isLodestoneCompass(itemStack.getDataComponents())) { if (isLodestoneCompass(components)) {
return super.translateToBedrock(itemStack, mappings.getLodestoneCompass(), mappings); return super.translateToBedrock(count, components, mappings.getLodestoneCompass(), mappings);
} }
return super.translateToBedrock(itemStack, mapping, mappings); return super.translateToBedrock(count, components, mapping, mappings);
} }
@Override @Override

View File

@ -41,7 +41,7 @@ public class DecoratedPotItem extends BlockItem {
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, 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 (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) {
// if (blockEntityTag.remove("sherds") instanceof ListTag sherds) { // if (blockEntityTag.remove("sherds") instanceof ListTag sherds) {
// // bedrock wants it on the root level // // bedrock wants it on the root level

View File

@ -25,16 +25,18 @@
package org.geysermc.geyser.item.type; 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.DataComponents;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.mc.protocol.data.game.item.component.ItemEnchantments;
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.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.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
public class EnchantedBookItem extends Item { public class EnchantedBookItem extends Item {
public EnchantedBookItem(String javaIdentifier, Builder builder) { 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) { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder); super.translateComponentsToBedrock(session, components, builder);
List<Tag> newTags = new ArrayList<>(); List<NbtMap> bedrockEnchants = new ArrayList<>();
Tag enchantmentTag = tag.remove("StoredEnchantments"); ItemEnchantments enchantments = components.get(DataComponentType.STORED_ENCHANTMENTS);
if (enchantmentTag instanceof ListTag listTag) { if (enchantments != null) { // TODO don't duplicate code?
for (Tag subTag : listTag.getValue()) { for (Map.Entry<Integer, Integer> enchantment : enchantments.getEnchantments().entrySet()) {
if (!(subTag instanceof CompoundTag)) continue; NbtMap bedrockTag = remapEnchantment(session, enchantment.getKey(), enchantment.getValue(), builder);
CompoundTag bedrockTag = remapEnchantment(session, (CompoundTag) subTag, tag);
if (bedrockTag != null) { if (bedrockTag != null) {
newTags.add(bedrockTag); bedrockEnchants.add(bedrockTag);
} }
} }
} }
if (!newTags.isEmpty()) { if (!bedrockEnchants.isEmpty()) {
tag.put(new ListTag("ench", newTags)); builder.putList("ench", NbtType.COMPOUND, bedrockEnchants);
} }
} }
} }

View File

@ -25,10 +25,8 @@
package org.geysermc.geyser.item.type; 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.DataComponentType;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; 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.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
@ -39,12 +37,12 @@ public class FilledMapItem extends MapItem {
} }
@Override @Override
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings); ItemData.Builder builder = super.translateToBedrock(count, components, mapping, mappings);
DataComponents components = itemStack.getDataComponents();
if (components == null) { if (components == null) {
// This is a fallback for maps with no nbt (Change added back in June 2020; is it needed in 2023?) // 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 { } else {
Integer mapColor = components.get(DataComponentType.MAP_COLOR); Integer mapColor = components.get(DataComponentType.MAP_COLOR);
if (mapColor != null) { if (mapColor != null) {

View File

@ -32,6 +32,7 @@ import com.github.steveice10.opennbt.tag.builtin.*;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.level.FireworkColor; import org.geysermc.geyser.level.FireworkColor;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -63,9 +64,10 @@ public class FireworkRocketItem extends Item {
} }
List<NbtMap> explosionNbt = new ArrayList<>(); List<NbtMap> explosionNbt = new ArrayList<>();
for (Fireworks.FireworkExplosion explosion : explosions) { 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 @Override
@ -73,17 +75,15 @@ public class FireworkRocketItem extends Item {
super.translateNbtToJava(tag, mapping); super.translateNbtToJava(tag, mapping);
} }
static NbtMap translateExplosionToBedrock(Fireworks.FireworkExplosion explosion, String newName) { static NbtMap translateExplosionToBedrock(Fireworks.FireworkExplosion explosion) {
NbtMapBuilder newExplosionData = NbtMap.builder(); NbtMapBuilder newExplosionData = NbtMap.builder();
if (explosion.get("Type") != null) { // if (explosion.get("Type") != null) {
newExplosionData.put(new ByteTag("FireworkType", MathUtils.getNbtByte(explosion.get("Type").getValue()))); // newExplosionData.put(new ByteTag("FireworkType", MathUtils.getNbtByte(explosion.get("Type").getValue())));
} // }
//newExplosionData.putByte("FireworkType", explosion.get) //TODO??? //newExplosionData.putByte("FireworkType", explosion.get) //TODO???
// TODO do we need length checks int[] oldColors = explosion.getColors();
if (explosion.get("Colors") != null) {
int[] oldColors = (int[]) explosion.get("Colors").getValue();
byte[] colors = new byte[oldColors.length]; byte[] colors = new byte[oldColors.length];
int i = 0; int i = 0;
@ -91,20 +91,17 @@ public class FireworkRocketItem extends Item {
colors[i++] = FireworkColor.fromJavaRGB(color); colors[i++] = FireworkColor.fromJavaRGB(color);
} }
newExplosionData.put(new ByteArrayTag("FireworkColor", colors)); newExplosionData.putByteArray("FireworkColor", colors);
}
if (explosion.get("FadeColors") != null) { oldColors = explosion.getFadeColors();
int[] oldColors = (int[]) explosion.get("FadeColors").getValue(); colors = new byte[oldColors.length];
byte[] colors = new byte[oldColors.length];
int i = 0; i = 0;
for (int color : oldColors) { for (int color : oldColors) {
colors[i++] = FireworkColor.fromJavaRGB(color); colors[i++] = FireworkColor.fromJavaRGB(color);
} }
newExplosionData.put(new ByteArrayTag("FireworkFade", colors)); newExplosionData.putByteArray("FireworkFade", colors);
}
newExplosionData.putBoolean("FireworkTrail", explosion.isHasTrail()); newExplosionData.putBoolean("FireworkTrail", explosion.isHasTrail());
newExplosionData.putBoolean("FireworkFlicker", explosion.isHasTwinkle()); // TODO verify newExplosionData.putBoolean("FireworkFlicker", explosion.isHasTwinkle()); // TODO verify

View File

@ -25,12 +25,13 @@
package org.geysermc.geyser.item.type; 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.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.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 com.github.steveice10.opennbt.tag.builtin.Tag;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMap;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder; 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) { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder); super.translateComponentsToBedrock(session, components, builder);
Tag explosion = tag.remove("Explosion"); Fireworks.FireworkExplosion explosion = components.get(DataComponentType.FIREWORK_EXPLOSION);
if (explosion instanceof CompoundTag) { if (explosion != null) {
CompoundTag newExplosion = FireworkRocketItem.translateExplosionToBedrock((CompoundTag) explosion, "FireworksItem"); NbtMap newExplosion = FireworkRocketItem.translateExplosionToBedrock(explosion);
tag.put(newExplosion); builder.putCompound("FireworksItem", newExplosion);
Tag color = ((CompoundTag) explosion).get("Colors"); int[] colors = explosion.getColors();
if (color instanceof IntArrayTag) { if (colors.length != 0) {
// Determine the custom color, if any. // Determine the custom color, if any.
// Mostly replicates Java's own rendering code, as Java determines the final firework star color client-side // Mostly replicates Java's own rendering code, as Java determines the final firework star color client-side
// while Bedrock determines it server-side. // while Bedrock determines it server-side.
int[] colors = ((IntArrayTag) color).getValue();
if (colors.length == 0) {
return;
}
int finalColor; int finalColor;
if (colors.length == 1) { if (colors.length == 1) {
finalColor = colors[0]; finalColor = colors[0];
@ -77,7 +74,7 @@ public class FireworkStarItem extends Item {
finalColor = r << 16 | g << 8 | b; finalColor = r << 16 | g << 8 | b;
} }
tag.put(new IntTag("customColor", finalColor)); builder.putInt("customColor", finalColor);
} }
} }
} }

View File

@ -26,8 +26,6 @@
package org.geysermc.geyser.item.type; package org.geysermc.geyser.item.type;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; 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.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.BedrockItemBuilder;
@ -42,11 +40,7 @@ public class FishingRodItem extends Item {
super.translateComponentsToBedrock(session, components, builder); super.translateComponentsToBedrock(session, components, builder);
// Fix damage inconsistency // Fix damage inconsistency
Tag damage = tag.get("Damage"); builder.getDamage().ifPresent(damage -> builder.setDamage(getBedrockDamage(damage)));
if (damage instanceof IntTag) {
int originalDurability = ((IntTag) damage).getValue();
tag.put(new IntTag("Damage", getBedrockDamage(originalDurability)));
}
} }
public static int getBedrockDamage(int javaDamage) { public static int getBedrockDamage(int javaDamage) {

View File

@ -26,6 +26,9 @@
package org.geysermc.geyser.item.type; 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.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 com.github.steveice10.opennbt.tag.builtin.StringTag;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
@ -52,21 +55,25 @@ public class GoatHornItem extends Item {
} }
@Override @Override
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings); ItemData.Builder builder = super.translateToBedrock(count, components, mapping, mappings);
if (itemStack.getNbt() != null && itemStack.getNbt().get("instrument") instanceof StringTag instrumentTag) { if (components == null) {
String instrument = instrumentTag.getValue(); return builder;
}
Instrument instrument = components.get(DataComponentType.INSTRUMENT);
// TODO registry
if (instrument != null) {
// Drop the Minecraft namespace if applicable // Drop the Minecraft namespace if applicable
if (instrument.startsWith("minecraft:")) { // if (instrument.startsWith("minecraft:")) {
instrument = instrument.substring("minecraft:".length()); // instrument = instrument.substring("minecraft:".length());
} // }
//
int damage = INSTRUMENTS.indexOf(instrument); // int damage = INSTRUMENTS.indexOf(instrument);
if (damage == -1) { // if (damage == -1) {
damage = 0; // damage = 0;
GeyserImpl.getInstance().getLogger().debug("Unknown goat horn instrument: " + instrumentTag.getValue()); // GeyserImpl.getInstance().getLogger().debug("Unknown goat horn instrument: " + instrumentTag.getValue());
} // }
builder.damage(damage); // builder.damage(damage);
} }
return builder; return builder;
} }
@ -83,7 +90,7 @@ public class GoatHornItem extends Item {
String instrument = INSTRUMENTS.get(damage); String instrument = INSTRUMENTS.get(damage);
StringTag instrumentTag = new StringTag("instrument", "minecraft:" + instrument); StringTag instrumentTag = new StringTag("instrument", "minecraft:" + instrument);
itemStack.getNbt().put(instrumentTag); //itemStack.getNbt().put(instrumentTag);
return itemStack; return itemStack;
} }

View File

@ -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.Identifier;
import com.github.steveice10.mc.protocol.data.game.item.ItemStack; 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.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.mc.protocol.data.game.item.component.ItemEnchantments;
import com.github.steveice10.opennbt.tag.builtin.*; import com.github.steveice10.opennbt.tag.builtin.*;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtMap; 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.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.item.Enchantment; 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.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession; 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.BedrockItemBuilder;
import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.item.ItemTranslator;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.InventoryUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -93,20 +93,16 @@ public class Item {
/* Translation methods to Bedrock and back */ /* Translation methods to Bedrock and back */
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
if (InventoryUtils.isEmpty(itemStack)) { if (this == Items.AIR || count <= 0) {
// Return, essentially, air // Return, essentially, air
return ItemData.builder(); return ItemData.builder();
} }
ItemData.Builder builder = ItemData.builder() ItemData.Builder builder = ItemData.builder()
.definition(mapping.getBedrockDefinition()) .definition(mapping.getBedrockDefinition())
.damage(mapping.getBedrockData()) .damage(mapping.getBedrockData())
.count(itemStack.getAmount()); .count(count);
if (itemStack.getDataComponents() != null) {
builder.tag(ItemTranslator.translateNbtToBedrock(itemStack.getDataComponents()));
}
DataComponents components = itemStack.getDataComponents();
ItemTranslator.translateCustomItem(components, builder, mapping); ItemTranslator.translateCustomItem(components, builder, mapping);
return builder; return builder;
@ -116,7 +112,7 @@ public class Item {
if (itemData.getTag() == null) { if (itemData.getTag() == null) {
return new ItemStack(javaId, itemData.getCount(), 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) { public ItemMapping toBedrockDefinition(DataComponents components, ItemMappings mappings) {
@ -135,23 +131,24 @@ public class Item {
} }
} }
List<Tag> newTags = new ArrayList<>(); Integer damage = components.get(DataComponentType.DAMAGE);
if (damage != null) {
builder.setDamage(damage);
}
List<NbtMap> enchantNbtList = new ArrayList<>();
ItemEnchantments enchantments = components.get(DataComponentType.ENCHANTMENTS); ItemEnchantments enchantments = components.get(DataComponentType.ENCHANTMENTS);
if (enchantments != null) { if (enchantments != null) {
for (Map.Entry<Integer, Integer> enchantment : enchantments.getEnchantments().entrySet()) {
} NbtMap enchantNbt = remapEnchantment(session, enchantment.getKey(), enchantment.getValue(), builder);
if (enchantmentTag instanceof ListTag listTag) { if (enchantNbt != null) {
for (Tag subTag : listTag.getValue()) { enchantNbtList.add(enchantNbt);
if (!(subTag instanceof CompoundTag)) continue;
CompoundTag bedrockTag = remapEnchantment(session, (CompoundTag) subTag, tag);
if (bedrockTag != null) {
newTags.add(bedrockTag);
} }
} }
} }
if (!newTags.isEmpty()) { if (!enchantNbtList.isEmpty()) {
tag.put(new ListTag("ench", newTags)); builder.putList("ench", NbtType.COMPOUND, enchantNbtList);
} }
} }
@ -218,45 +215,30 @@ public class Item {
} }
} }
protected final @Nullable NbtMap remapEnchantment(GeyserSession session, ItemEnchantments, NbtMapBuilder rootBuilder) { protected final @Nullable NbtMap remapEnchantment(GeyserSession session, int enchantId, int level, BedrockItemBuilder builder) {
// TODO verify
Enchantment enchantment = Enchantment.getByJavaIdentifier(((StringTag) javaEnchId).getValue()); // 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 (enchantment == null) {
if (Identifier.formalize((String) javaEnchId.getValue()).equals("minecraft:sweeping")) { GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment while NBT item translating: " + enchantId);
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());
return null; return null;
} }
Tag javaEnchLvl = tag.get("lvl"); return NbtMap.builder()
.putShort("id", (short) Enchantment.valueOf(enchantment.name()).ordinal())
NbtMapBuilder builder = NbtMap.builder(); .putShort("lvl", (short) level)
builder.putShort("id", (short) enchantment.ordinal()); .build();
builder.putShort("lvl", );
return builder.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 sweepingTranslation = MinecraftLocale.getLocaleString("enchantment.minecraft.sweeping", session.locale());
String lvlTranslation = MinecraftLocale.getLocaleString("enchantment.level." + level, 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 */ /* Translation methods end */

View File

@ -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;
}
}

View File

@ -25,6 +25,7 @@
package org.geysermc.geyser.item.type; 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.DataComponents;
import com.github.steveice10.opennbt.tag.builtin.*; import com.github.steveice10.opennbt.tag.builtin.*;
import org.checkerframework.checker.nullness.qual.NonNull; 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) { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder); super.translateComponentsToBedrock(session, components, builder);
Tag mapId = tag.remove("map"); Integer mapValue = components.get(DataComponentType.MAP_ID);
if (mapId == null || !(mapId.getValue() instanceof Number number)) return; if (mapValue == null) {
return;
}
int mapValue = number.intValue(); builder.putLong("map_uuid", mapValue);
builder.putInt("map_name_index", mapValue);
tag.put(new LongTag("map_uuid", mapValue)); builder.putByte("map_display_players", (byte) 1);
tag.put(new IntTag("map_name_index", mapValue));
tag.put(new ByteTag("map_display_players", (byte) 1));
} }
@Override @Override

View File

@ -25,16 +25,14 @@
package org.geysermc.geyser.item.type; 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.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.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.geyser.translator.text.MessageTranslator;
public class PlayerHeadItem extends Item { public class PlayerHeadItem extends Item {
public PlayerHeadItem(String javaIdentifier, Builder builder) { public PlayerHeadItem(String javaIdentifier, Builder builder) {
@ -45,36 +43,25 @@ public class PlayerHeadItem extends Item {
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder); super.translateComponentsToBedrock(session, components, builder);
CompoundTag displayTag; // TODO verify
if (tag.get("display") instanceof CompoundTag existingDisplayTag) { // Also - ChatColor.YELLOW + ChatColor.ITALIC + MessageTranslator.convertMessageLenient(nameTag.getValue(), session.locale())) this code existed if a custom name was already present.
displayTag = existingDisplayTag; // But I think we would always overwrite that because translateDisplayProperties runs after this method.
} else { String customName = builder.getCustomName();
displayTag = new CompoundTag("display"); if (customName == null) {
tag.put(displayTag); GameProfile profile = components.get(DataComponentType.PROFILE);
} if (profile != null) {
String name = profile.getName();
if (displayTag.get("Name") instanceof StringTag nameTag) { if (name != null) {
// Custom names are always yellow and italic // Add correct name of player skull
displayTag.put(new StringTag("Name", ChatColor.YELLOW + ChatColor.ITALIC + MessageTranslator.convertMessageLenient(nameTag.getValue(), session.locale()))); String displayName = ChatColor.RESET + ChatColor.YELLOW +
} else { MinecraftLocale.getLocaleString("block.minecraft.player_head.named", session.locale()).replace("%s", name);
if (tag.contains("SkullOwner")) { builder.setCustomName(displayName);
StringTag name;
Tag skullOwner = tag.get("SkullOwner");
if (skullOwner instanceof StringTag skullName) {
name = skullName;
} else {
if (skullOwner instanceof CompoundTag && ((CompoundTag) skullOwner).get("Name") instanceof StringTag skullName) {
name = skullName;
} else { } else {
// No name found so default to "Player Head" // 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()))); builder.setCustomName(ChatColor.RESET + ChatColor.YELLOW +
return; 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));
}
} }
} }
} }

View File

@ -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.ItemStack;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; 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.mc.protocol.data.game.item.component.PotionContents;
import com.github.steveice10.opennbt.tag.builtin.StringTag; 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.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; 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.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.translator.item.CustomItemTranslator; import org.geysermc.geyser.translator.item.CustomItemTranslator;
import org.geysermc.geyser.translator.item.ItemTranslator;
public class PotionItem extends Item { public class PotionItem extends Item {
public PotionItem(String javaIdentifier, Builder builder) { public PotionItem(String javaIdentifier, Builder builder) {
@ -46,29 +45,27 @@ public class PotionItem extends Item {
} }
@Override @Override
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
if (itemStack.getDataComponents() == null) return super.translateToBedrock(itemStack, mapping, mappings); if (components == null) return super.translateToBedrock(count, components, mapping, mappings);
PotionContents potionContents = itemStack.getDataComponents().get(DataComponentType.POTION_CONTENTS); PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS);
if (potionContents != null) { if (potionContents != null) {
ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(itemStack.getDataComponents(), mapping); ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(components, mapping);
if (customItemDefinition == null) { if (customItemDefinition == null) {
Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); Potion potion = Potion.VALUES[potionContents.getPotionId()];
if (potion != null) { if (potion != null) {
return ItemData.builder() return ItemData.builder()
.definition(mapping.getBedrockDefinition()) .definition(mapping.getBedrockDefinition())
.damage(potion.getBedrockId()) .damage(potion.getBedrockId())
.count(itemStack.getAmount()) .count(count);
.tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt()));
} }
GeyserImpl.getInstance().getLogger().debug("Unknown Java potion: " + potionTag.getValue()); GeyserImpl.getInstance().getLogger().debug("Unknown Java potion: " + potionContents.getPotionId());
} else { } else {
return ItemData.builder() return ItemData.builder()
.definition(customItemDefinition) .definition(customItemDefinition)
.count(itemStack.getAmount()) .count(count);
.tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt()));
} }
} }
return super.translateToBedrock(itemStack, mapping, mappings); return super.translateToBedrock(count, components, mapping, mappings);
} }
@Override @Override
@ -77,7 +74,7 @@ public class PotionItem extends Item {
ItemStack itemStack = super.translateToJava(itemData, mapping, mappings); ItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
if (potion != null) { if (potion != null) {
StringTag potionTag = new StringTag("Potion", potion.getJavaIdentifier()); StringTag potionTag = new StringTag("Potion", potion.getJavaIdentifier());
itemStack.getNbt().put(potionTag); //itemStack.getNbt().put(potionTag);
} }
return itemStack; return itemStack;
} }

View File

@ -26,10 +26,6 @@
package org.geysermc.geyser.item.type; package org.geysermc.geyser.item.type;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; 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.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.item.components.ToolTier; import org.geysermc.geyser.item.components.ToolTier;
import org.geysermc.geyser.session.GeyserSession; 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) { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder); super.translateComponentsToBedrock(session, components, builder);
if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { // TODO figure out patterns first.
if (blockEntityTag.get("Patterns") instanceof ListTag patterns) { // if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) {
for (Tag pattern : patterns) { // if (blockEntityTag.get("Patterns") instanceof ListTag patterns) {
if (((CompoundTag) pattern).get("Color") instanceof IntTag color) { // for (Tag pattern : patterns) {
color.setValue(15 - color.getValue()); // if (((CompoundTag) pattern).get("Color") instanceof IntTag color) {
} // color.setValue(15 - color.getValue());
} // }
// Bedrock looks for patterns at the root // }
tag.put(patterns); // // Bedrock looks for patterns at the root
} // tag.put(patterns);
if (blockEntityTag.get("Base") instanceof IntTag base) { // }
base.setValue(15 - base.getValue()); // if (blockEntityTag.get("Base") instanceof IntTag base) {
tag.put(base); // base.setValue(15 - base.getValue());
} // tag.put(base);
} // }
// }
} }
@Override @Override

View File

@ -83,7 +83,7 @@ public class ShulkerBoxItem extends BlockItem {
itemsList.add(boxItemNbt.build()); itemsList.add(boxItemNbt.build());
} }
builder.getOrCreateNbt().putList("Items", NbtType.COMPOUND, itemsList); builder.putList("Items", NbtType.COMPOUND, itemsList);
} }
@Override @Override

View File

@ -25,15 +25,14 @@
package org.geysermc.geyser.item.type; 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.opennbt.tag.builtin.StringTag; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.item.TippedArrowPotion; import org.geysermc.geyser.inventory.item.TippedArrowPotion;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.translator.item.ItemTranslator;
public class TippedArrowItem extends ArrowItem { public class TippedArrowItem extends ArrowItem {
public TippedArrowItem(String javaIdentifier, Builder builder) { public TippedArrowItem(String javaIdentifier, Builder builder) {
@ -41,19 +40,18 @@ public class TippedArrowItem extends ArrowItem {
} }
@Override @Override
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
Tag potionTag = itemStack.getNbt().get("Potion"); PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS);
if (potionTag instanceof StringTag) { if (potionContents != null) {
TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByJavaIdentifier(((StringTag) potionTag).getValue()); TippedArrowPotion tippedArrowPotion = TippedArrowPotion.of(potionContents.getPotionId());
if (tippedArrowPotion != null) { if (tippedArrowPotion != null) {
return ItemData.builder() return ItemData.builder()
.definition(mapping.getBedrockDefinition()) .definition(mapping.getBedrockDefinition())
.damage(tippedArrowPotion.getBedrockId()) .damage(tippedArrowPotion.getBedrockId())
.count(itemStack.getAmount()) .count(count);
.tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt()));
} }
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);
} }
} }

View File

@ -25,8 +25,10 @@
package org.geysermc.geyser.item.type; 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.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.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style; 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.item.BedrockItemBuilder;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class TropicalFishBucketItem extends Item { public class TropicalFishBucketItem extends Item {
@ -53,27 +54,27 @@ public class TropicalFishBucketItem extends Item {
super.translateComponentsToBedrock(session, components, builder); super.translateComponentsToBedrock(session, components, builder);
// Prevent name from appearing as "Bucket of" // Prevent name from appearing as "Bucket of"
tag.put(new ByteTag("AppendCustomName", (byte) 1)); builder.putByte("AppendCustomName", (byte) 1);
tag.put(new StringTag("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.tropical_fish", session.locale()))); builder.putString("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.tropical_fish", session.locale()));
// Add Java's client side lore tag // Add Java's client side lore tag
Tag bucketVariantTag = tag.get("BucketVariantTag"); // 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.
if (bucketVariantTag instanceof IntTag) { CompoundTag entityTag = components.get(DataComponentType.BUCKET_ENTITY_DATA);
CompoundTag displayTag = tag.get("display"); if (entityTag != null && !entityTag.isEmpty()) {
if (displayTag == null) { //TODO test
displayTag = new CompoundTag("display"); Tag bucketVariant = entityTag.get("BucketVariantTag");
tag.put(displayTag); if (bucketVariant == null || !(bucketVariant.getValue() instanceof Number)) {
return;
} }
List<String> lore = builder.getOrCreateLore();
List<Tag> lore = new ArrayList<>(); int varNumber = ((Number) bucketVariant.getValue()).intValue();
int varNumber = ((IntTag) bucketVariantTag).getValue();
int predefinedVariantId = TropicalFishEntity.getPredefinedId(varNumber); int predefinedVariantId = TropicalFishEntity.getPredefinedId(varNumber);
if (predefinedVariantId != -1) { if (predefinedVariantId != -1) {
Component tooltip = Component.translatable("entity.minecraft.tropical_fish.predefined." + predefinedVariantId, LORE_STYLE); 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 { } else {
Component typeTooltip = Component.translatable("entity.minecraft.tropical_fish.type." + TropicalFishEntity.getVariantName(varNumber), LORE_STYLE); 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 baseColor = TropicalFishEntity.getBaseColor(varNumber);
byte patternColor = TropicalFishEntity.getPatternColor(varNumber); byte patternColor = TropicalFishEntity.getPatternColor(varNumber);
@ -82,14 +83,8 @@ public class TropicalFishBucketItem extends Item {
colorTooltip = colorTooltip.append(Component.text(", ", LORE_STYLE)) colorTooltip = colorTooltip.append(Component.text(", ", LORE_STYLE))
.append(Component.translatable("color.minecraft." + TropicalFishEntity.getColorName(patternColor), 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));
} }
} }
} }

View File

@ -25,12 +25,18 @@
package org.geysermc.geyser.item.type; 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.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.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.checkerframework.checker.nullness.qual.NonNull; 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.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder; 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) { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder); super.translateComponentsToBedrock(session, components, builder);
ListTag pagesTag = tag.remove("pages"); WritableBookContent bookContent = components.get(DataComponentType.WRITABLE_BOOK_CONTENT);
if (pagesTag == null) { if (bookContent == null) {
return; return;
} }
List<Tag> pages = new ArrayList<>();
for (Tag subTag : pagesTag.getValue()) {
if (!(subTag instanceof StringTag textTag))
continue;
CompoundTag pageTag = new CompoundTag(""); List<NbtMap> bedrockPages = new ArrayList<>();
pageTag.put(new StringTag("photoname", "")); for (Filterable<String> page : bookContent.getPages()) {
pageTag.put(new StringTag("text", MessageTranslator.convertMessageLenient(textTag.getValue()))); NbtMapBuilder pageBuilder = NbtMap.builder();
pages.add(pageTag); 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 @Override

View File

@ -25,21 +25,27 @@
package org.geysermc.geyser.item.type; 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.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.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.checkerframework.checker.nullness.qual.NonNull; 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.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import java.util.ArrayList;
import java.util.List; 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_EDIT_LENGTH = 1024;
public static final int MAXIMUM_PAGE_LENGTH = 32768; 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. 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 @Override
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { 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); super.translateComponentsToBedrock(session, components, builder);
if (!isValid) { WrittenBookContent bookContent = components.get(DataComponentType.WRITTEN_BOOK_CONTENT);
CompoundTag invalidTagPage = new CompoundTag(""); if (bookContent == null) {
invalidTagPage.put(new StringTag("photoname", "")); return;
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)));
} }
List<NbtMap> bedrockPages = new ArrayList<>();
for (Filterable<Component> 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) { private boolean isValidWrittenBook(CompoundTag tag) {

View File

@ -25,11 +25,12 @@
package org.geysermc.geyser.level; 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.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag; 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 * 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 record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale) {
public static void load(CompoundTag tag, Map<String, JavaDimension> map) { public static void load(List<RegistryEntry> entries, Int2ObjectMap<JavaDimension> map) {
for (CompoundTag dimension : JavaCodecUtil.iterateAsTag(tag.get("minecraft:dimension_type"))) { for (int i = 0; i < entries.size(); i++) {
CompoundTag elements = dimension.get("element"); RegistryEntry entry = entries.get(i);
int minY = ((IntTag) elements.get("min_y")).getValue(); CompoundTag dimension = entry.getData();
int maxY = ((IntTag) elements.get("height")).getValue(); 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. // Logical height can be ignored probably - seems to be for artificial limits like the Nether.
// Set if piglins/hoglins should shake // 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 // 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));
} }
} }
} }

View File

@ -79,7 +79,7 @@ public final class LocalSession extends TcpSession {
public void initChannel(@NonNull LocalChannelWithRemoteAddress channel) { public void initChannel(@NonNull LocalChannelWithRemoteAddress channel) {
channel.spoofedRemoteAddress(new InetSocketAddress(clientIp, 0)); channel.spoofedRemoteAddress(new InetSocketAddress(clientIp, 0));
PacketProtocol protocol = getPacketProtocol(); PacketProtocol protocol = getPacketProtocol();
protocol.newClientSession(LocalSession.this); protocol.newClientSession(LocalSession.this, false);
refreshReadTimeoutHandler(channel); refreshReadTimeoutHandler(channel);
refreshWriteTimeoutHandler(channel); refreshWriteTimeoutHandler(channel);

View File

@ -56,13 +56,7 @@ public class EnchantmentRegistryLoader implements RegistryLoader<String, Map<Jav
Map.Entry<String, JsonNode> entry = it.next(); Map.Entry<String, JsonNode> entry = it.next();
JavaEnchantment key = JavaEnchantment.getByJavaIdentifier(entry.getKey()); JavaEnchantment key = JavaEnchantment.getByJavaIdentifier(entry.getKey());
JsonNode node = entry.getValue(); JsonNode node = entry.getValue();
int rarityMultiplier = switch (node.get("rarity").textValue()) { int rarityMultiplier = node.get("anvil_cost").asInt();
case "common" -> 1;
case "uncommon" -> 2;
case "rare" -> 4;
case "very_rare" -> 8;
default -> throw new IllegalStateException("Unexpected value: " + node.get("rarity").textValue());
};
int maxLevel = node.get("max_level").asInt(); int maxLevel = node.get("max_level").asInt();
EnumSet<JavaEnchantment> incompatibleEnchantments = EnumSet.noneOf(JavaEnchantment.class); EnumSet<JavaEnchantment> incompatibleEnchantments = EnumSet.noneOf(JavaEnchantment.class);

View File

@ -37,9 +37,11 @@ public class Conversion649_630 {
String identifer = mapping.getBedrockIdentifier(); String identifer = mapping.getBedrockIdentifier();
switch (identifer) { 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_spawner" -> { return mapping.withBedrockIdentifier("minecraft:mob_spawner"); }
case "minecraft:trial_key" -> { return mapping.withBedrockIdentifier("minecraft:echo_shard"); } case "minecraft:trial_key" -> { return mapping.withBedrockIdentifier("minecraft:echo_shard"); }
case "minecraft:wolf_armor" -> { return mapping.withBedrockIdentifier("minecraft:leather_horse_armor"); }
default -> { return mapping; } default -> { return mapping; }
} }
} }

View File

@ -35,7 +35,7 @@ import java.util.stream.Stream;
public class Conversion662_649 { public class Conversion662_649 {
private static final List<String> NEW_MISC = List.of("minecraft:grass_block", "minecraft:trial_spawner"); private static final List<String> NEW_MISC = List.of("minecraft:grass_block", "minecraft:vault");
private static final List<String> 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<String> 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<String> NEW_LEAVES = List.of("minecraft:oak_leaves", "minecraft:spruce_leaves", "minecraft:birch_leaves", "minecraft:jungle_leaves"); private static final List<String> NEW_LEAVES = List.of("minecraft:oak_leaves", "minecraft:spruce_leaves", "minecraft:birch_leaves", "minecraft:jungle_leaves");
private static final List<String> NEW_LEAVES2 = List.of("minecraft:acacia_leaves", "minecraft:dark_oak_leaves"); private static final List<String> NEW_LEAVES2 = List.of("minecraft:acacia_leaves", "minecraft:dark_oak_leaves");
@ -48,9 +48,12 @@ public class Conversion662_649 {
String identifer = mapping.getBedrockIdentifier(); String identifer = mapping.getBedrockIdentifier();
if (identifer.equals("minecraft:grass_block")) { switch (identifer) {
return mapping.withBedrockIdentifier("minecraft:grass"); 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)) { if (NEW_WOODS.contains(identifer)) {
switch (identifer) { switch (identifer) {
@ -114,6 +117,19 @@ public class Conversion662_649 {
return builder.build(); 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)) { if (NEW_WOODS.contains(name)) {
replacement = "minecraft:wood"; replacement = "minecraft:wood";

View File

@ -26,6 +26,7 @@
package org.geysermc.geyser.registry.populator; package org.geysermc.geyser.registry.populator;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.GeyserMappingItem; import org.geysermc.geyser.registry.type.GeyserMappingItem;
@ -33,11 +34,12 @@ import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
public class Conversion671_662 { public class Conversion671_662 {
private static final List<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> NEW_BLOCKS = Stream.of(NEW_CORAL_FANS, NEW_DEAD_CORAL_FANS, NEW_FLOWERS, NEW_SAPLINGS).flatMap(List::stream).toList(); private static final List<String> 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) { static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) {
String identifer = mapping.getBedrockIdentifier(); String identifer = mapping.getBedrockIdentifier();
@ -46,6 +48,18 @@ public class Conversion671_662 {
return mapping; 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)) { if (NEW_FLOWERS.contains(identifer)) {
switch (identifer) { switch (identifer) {
case "minecraft:poppy" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(0); } case "minecraft:poppy" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(0); }
@ -114,6 +128,15 @@ public class Conversion671_662 {
String replacement; 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)) { if (NEW_SAPLINGS.contains(name)) {
replacement = "minecraft:sapling"; replacement = "minecraft:sapling";
String saplingType = name.replaceAll("minecraft:|_sapling", "");; String saplingType = name.replaceAll("minecraft:|_sapling", "");;

View File

@ -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.common.serverbound.ServerboundClientInformationPacket;
import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; 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.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.ServerboundChatPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; 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. * As all entities are in the same world, this can be safely applied to all other entities.
*/ */
@Setter @Setter
private String dimension = DimensionUtils.OVERWORLD; private int dimension = DimensionUtils.OVERWORLD;
@MonotonicNonNull @MonotonicNonNull
@Setter @Setter
private JavaDimension dimensionType = null; private JavaDimension dimensionType = null;
/** /**
* All dimensions that the client could possibly connect to. * All dimensions that the client could possibly connect to.
*/ */
private final Map<String, JavaDimension> dimensions = new Object2ObjectOpenHashMap<>(3); private final Int2ObjectMap<JavaDimension> dimensions = new Int2ObjectOpenHashMap<>(4);
private final Int2ObjectMap<TextDecoration> chatTypes = new Int2ObjectOpenHashMap<>(7); private final Int2ObjectMap<TextDecoration> chatTypes = new Int2ObjectOpenHashMap<>(7);
@ -1460,7 +1461,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
* Sends a command to the Java server. * Sends a command to the Java server.
*/ */
public void sendCommand(String command) { 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) { public void setServerRenderDistance(int renderDistance) {

View File

@ -25,13 +25,14 @@
package org.geysermc.geyser.session.cache; 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.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.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import java.util.Map; import java.util.Map;
@ -54,22 +55,27 @@ public final class LodestoneCache {
private int id = 1; private int id = 1;
public void cacheInventoryItem(GeyserItemStack itemStack) { public void cacheInventoryItem(GeyserItemStack itemStack) {
CompoundTag tag = itemStack.getNbt(); DataComponents components = itemStack.getComponents();
if (tag == null) { if (components == null) {
// invalid // invalid
return; return;
} }
CompoundTag lodestonePos = tag.get("LodestonePos"); LodestoneTracker tracker = components.get(DataComponentType.LODESTONE_TRACKER);
if (lodestonePos == null) { if (tracker == null) {
// invalid
return; return;
} }
// Get all info needed for tracking GlobalPos position = tracker.getPos();
int x = ((IntTag) lodestonePos.get("X")).getValue();
int y = ((IntTag) lodestonePos.get("Y")).getValue(); if (position == null) {
int z = ((IntTag) lodestonePos.get("Z")).getValue(); GeyserImpl.getInstance().getLogger().error("Position is null. Find out why.");
String dim = ((StringTag) tag.get("LodestoneDimension")).getValue(); 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()) { for (LodestonePos pos : this.activeLodestones.values()) {
if (pos.equals(x, y, z, dim)) { if (pos.equals(x, y, z, dim)) {
@ -90,17 +96,17 @@ public final class LodestoneCache {
} }
public int store(LodestoneTracker tracker) { public int store(LodestoneTracker tracker) {
CompoundTag lodestonePos = tag.get("LodestonePos"); GlobalPos position = tracker.getPos();
if (lodestonePos == null) {
// invalid
return 0;
}
// Get all info needed for tracking if (position == null) {
int x = ((IntTag) lodestonePos.get("X")).getValue(); GeyserImpl.getInstance().getLogger().error("Position is null. Find out why.");
int y = ((IntTag) lodestonePos.get("Y")).getValue(); Thread.dumpStack();
int z = ((IntTag) lodestonePos.get("Z")).getValue(); return -1;
String dim = ((StringTag) tag.get("LodestoneDimension")).getValue(); }
int x = position.getX();
int y = position.getY();
int z = position.getZ();
String dim = position.getDimension();
for (LodestonePos pos : this.activeLodestones.values()) { for (LodestonePos pos : this.activeLodestones.values()) {
if (pos.equals(x, y, z, dim)) { if (pos.equals(x, y, z, dim)) {

View File

@ -58,7 +58,7 @@ public class TagCache {
private IntList requiresDiamondTool; private IntList requiresDiamondTool;
/* Items */ /* Items */
private IntList axolotlTemptItems; private IntList axolotlFood;
private IntList creeperIgniters; private IntList creeperIgniters;
private IntList fishes; private IntList fishes;
private IntList flowers; private IntList flowers;
@ -96,7 +96,7 @@ public class TagCache {
} }
Map<String, int[]> itemTags = packet.getTags().get("minecraft:item"); Map<String, int[]> 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.creeperIgniters = load(itemTags.get("minecraft:creeper_igniters"));
this.fishes = IntList.of(itemTags.get("minecraft:fishes")); this.fishes = IntList.of(itemTags.get("minecraft:fishes"));
this.flowers = IntList.of(itemTags.get("minecraft:flowers")); this.flowers = IntList.of(itemTags.get("minecraft:flowers"));
@ -133,7 +133,7 @@ public class TagCache {
this.requiresIronTool = IntLists.emptyList(); this.requiresIronTool = IntLists.emptyList();
this.requiresDiamondTool = IntLists.emptyList(); this.requiresDiamondTool = IntLists.emptyList();
this.axolotlTemptItems = IntLists.emptyList(); this.axolotlFood = IntLists.emptyList();
this.creeperIgniters = IntLists.emptyList(); this.creeperIgniters = IntLists.emptyList();
this.fishes = IntLists.emptyList(); this.fishes = IntLists.emptyList();
this.flowers = IntLists.emptyList(); this.flowers = IntLists.emptyList();
@ -143,8 +143,8 @@ public class TagCache {
this.snifferFood = IntLists.emptyList(); this.snifferFood = IntLists.emptyList();
} }
public boolean isAxolotlTemptItem(Item item) { public boolean isAxolotlFood(Item item) {
return axolotlTemptItems.contains(item.javaId()); return axolotlFood.contains(item.javaId());
} }
public boolean isCreeperIgniter(Item item) { public boolean isCreeperIgniter(Item item) {

View File

@ -25,6 +25,7 @@
package org.geysermc.geyser.translator.inventory; 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.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; 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 org.geysermc.geyser.session.GeyserSession;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
@ -154,9 +156,10 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
GeyserItemStack inputCopy = inventory.getItem(0).copy(1); GeyserItemStack inputCopy = inventory.getItem(0).copy(1);
inputCopy.setNetId(session.getNextItemNetId()); inputCopy.setNetId(session.getNextItemNetId());
// Add the pattern manually, for better item synchronization // Add the pattern manually, for better item synchronization
if (inputCopy.getNbt() == null) { if (inputCopy.getComponents() == null) {
inputCopy.setNbt(new CompoundTag("")); inputCopy.setComponents(new DataComponents(new HashMap<>()));
} }
//TODO
CompoundTag blockEntityTag = inputCopy.getNbt().get("BlockEntityTag"); CompoundTag blockEntityTag = inputCopy.getNbt().get("BlockEntityTag");
CompoundTag javaBannerPattern = BannerItem.getJavaBannerPattern(pattern); CompoundTag javaBannerPattern = BannerItem.getJavaBannerPattern(pattern);

View File

@ -360,7 +360,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
return rejectRequest(request); 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); session.sendDownstreamGamePacket(creativeDropPacket);
sourceItem.sub(dropAction.getCount()); sourceItem.sub(dropAction.getCount());
@ -493,9 +493,9 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
dropStack = javaCreativeItem; dropStack = javaCreativeItem;
} else { } else {
// Specify custom count // 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); session.sendDownstreamGamePacket(creativeDropPacket);
break; break;
} }
@ -516,7 +516,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
GeyserItemStack item = inventory.getItem(slot); GeyserItemStack item = inventory.getItem(slot);
ItemStack itemStack = item.isEmpty() ? new ItemStack(-1, 0, null) : item.getItemStack(); 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); session.sendDownstreamGamePacket(creativePacket);
} }

View File

@ -34,6 +34,7 @@ import org.geysermc.geyser.registry.type.ItemMapping;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; 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. * 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; private String customName;
@Nullable @Nullable
private List<String> lore; private List<String> lore;
private OptionalInt damage = OptionalInt.empty();
/** /**
* Miscellaneous NBT that will be put into the final item. * Miscellaneous NBT that will be put into the final item.
*/ */
@Nullable @Nullable
private NbtMapBuilder builder; private NbtMapBuilder builder;
@Nullable
public String getCustomName() {
return customName;
}
public BedrockItemBuilder setCustomName(String customName) { public BedrockItemBuilder setCustomName(String customName) {
this.customName = customName; this.customName = customName;
return this; return this;
@ -63,6 +70,15 @@ public final class BedrockItemBuilder {
return lore; return lore;
} }
public OptionalInt getDamage() {
return damage;
}
public BedrockItemBuilder setDamage(int damage) {
this.damage = OptionalInt.of(damage);
return this;
}
@NonNull @NonNull
public NbtMapBuilder getOrCreateNbt() { public NbtMapBuilder getOrCreateNbt() {
if (builder == null) { if (builder == null) {
@ -85,6 +101,14 @@ public final class BedrockItemBuilder {
return getOrCreateNbt().putInt(name, value); return getOrCreateNbt().putInt(name, value);
} }
public <T> NbtMapBuilder putList(String name, NbtType<T> type, List<T> 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) { public NbtMapBuilder putString(String name, String value) {
return getOrCreateNbt().putString(name, value); return getOrCreateNbt().putString(name, value);
} }
@ -108,6 +132,9 @@ public final class BedrockItemBuilder {
} }
getOrCreateNbt().put("display", display.build()); getOrCreateNbt().put("display", display.build());
} }
if (damage.isPresent()) {
getOrCreateNbt().putInt("Damage", damage.getAsInt());
}
if (builder == null) { if (builder == null) {
return 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) { public static NbtMapBuilder createItemNbt(ItemMapping mapping, int count, int damage) {
NbtMapBuilder builder = NbtMap.builder(); NbtMapBuilder builder = NbtMap.builder();
builder.putByte("Count", (byte) count);
builder.putString("Name", mapping.getBedrockIdentifier()); builder.putString("Name", mapping.getBedrockIdentifier());
builder.putByte("Count", (byte) count);
builder.putShort("Damage", (short) damage); builder.putShort("Damage", (short) damage);
return builder; return builder;
} }

View File

@ -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.entity.attribute.ModifierOperation;
import com.github.steveice10.mc.protocol.data.game.item.ItemStack; 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.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.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.mc.protocol.data.game.item.component.ItemAttributeModifiers;
import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag; import com.github.steveice10.opennbt.tag.builtin.*;
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 net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; 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.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType; 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.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.BlockRegistries; 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.CustomSkull;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession; 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.ChatColor;
import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.InventoryUtils; import org.geysermc.geyser.util.InventoryUtils;
import java.text.DecimalFormat; 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 { public final class ItemTranslator {
@ -161,9 +151,9 @@ public final class ItemTranslator {
addAdvancedTooltips(components, nbtBuilder, javaItem, session.locale()); addAdvancedTooltips(components, nbtBuilder, javaItem, session.locale());
} }
ItemStack itemStack = new ItemStack(javaItem.javaId(), count, components); ItemData.Builder builder = javaItem.translateToBedrock(count, components, bedrockItem, session.getItemMappings());
// Finalize the Bedrock NBT
ItemData.Builder builder = javaItem.translateToBedrock(itemStack, bedrockItem, session.getItemMappings()); builder.tag(nbtBuilder.build());
if (bedrockItem.isBlock()) { if (bedrockItem.isBlock()) {
CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault( CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault(
bedrockItem.getJavaItem().javaIdentifier(), null); bedrockItem.getJavaItem().javaIdentifier(), null);
@ -357,7 +347,7 @@ public final class ItemTranslator {
return ItemDefinition.AIR; 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(); ItemDefinition itemDefinition = mapping.getBedrockDefinition();
CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault( CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault(
@ -563,20 +553,21 @@ public final class ItemTranslator {
if (components == null) { if (components == null) {
return null; return null;
} }
//TODO
GameProfile profile = components.get(DataComponentType.PROFILE); GameProfile profile = components.get(DataComponentType.PROFILE);
if (profile != null) { if (profile != null) {
if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) { // if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) {
// It's a username give up d: // // It's a username give up d:
return null; // return null;
} // }
SkinManager.GameProfileData data = SkinManager.GameProfileData.from(skullOwner); // SkinManager.GameProfileData data = SkinManager.GameProfileData.from(skullOwner);
if (data == null) { // if (data == null) {
session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt); // session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt);
return null; // return null;
} // }
//
String skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1); // String skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1);
return BlockRegistries.CUSTOM_SKULLS.get(skinHash); // return BlockRegistries.CUSTOM_SKULLS.get(skinHash);
} }
return null; return null;
} }

View File

@ -25,15 +25,13 @@
package org.geysermc.geyser.translator.level; 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.BitStorage;
import com.github.steveice10.mc.protocol.data.game.chunk.DataPalette; 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.GlobalPalette;
import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette; 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.mc.protocol.data.game.chunk.palette.SingletonPalette;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; 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 it.unimi.dsi.fastutil.ints.*;
import org.geysermc.geyser.level.chunk.BlockStorage; import org.geysermc.geyser.level.chunk.BlockStorage;
import org.geysermc.geyser.level.chunk.bitarray.BitArray; 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.level.chunk.bitarray.SingletonBitArray;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.JavaCodecUtil;
import org.geysermc.geyser.util.MathUtils; import org.geysermc.geyser.util.MathUtils;
import java.util.List;
// Array index formula by https://wiki.vg/Chunk_Format // Array index formula by https://wiki.vg/Chunk_Format
public class BiomeTranslator { public class BiomeTranslator {
public static void loadServerBiomes(GeyserSession session, CompoundTag codec) { public static void loadServerBiomes(GeyserSession session, List<RegistryEntry> entries) {
Int2IntMap biomeTranslations = new Int2IntOpenHashMap(); Int2IntMap biomeTranslations = new Int2IntOpenHashMap();
CompoundTag worldGen = codec.get("minecraft:worldgen/biome"); session.setBiomeGlobalPalette(MathUtils.getGlobalPaletteForSize(entries.size()));
ListTag serverBiomes = worldGen.get("value");
session.setBiomeGlobalPalette(MathUtils.getGlobalPaletteForSize(serverBiomes.size()));
int greatestBiomeId = 0; int greatestBiomeId = 0;
for (CompoundTag biomeTag : JavaCodecUtil.iterateAsTag(worldGen)) { for (int i = 0; i < entries.size(); i++) {
String javaIdentifier = ((StringTag) biomeTag.get("name")).getValue(); RegistryEntry entry = entries.get(i);
String javaIdentifier = entry.getId();
int bedrockId = Registries.BIOME_IDENTIFIERS.get().getOrDefault(javaIdentifier, 0); int bedrockId = Registries.BIOME_IDENTIFIERS.get().getOrDefault(javaIdentifier, 0);
int javaId = ((IntTag) biomeTag.get("id")).getValue(); int javaId = i;
if (javaId > greatestBiomeId) { if (javaId > greatestBiomeId) {
greatestBiomeId = javaId; greatestBiomeId = javaId;
} }

View File

@ -69,7 +69,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator<BlockPic
BlockMapping blockMapping = BlockRegistries.JAVA_BLOCKS.getOrDefault(blockToPick, BlockMapping.DEFAULT); BlockMapping blockMapping = BlockRegistries.JAVA_BLOCKS.getOrDefault(blockToPick, BlockMapping.DEFAULT);
boolean addNbtData = packet.isAddUserData() && blockMapping.isBlockEntity(); // Holding down CTRL boolean addNbtData = packet.isAddUserData() && blockMapping.isBlockEntity(); // Holding down CTRL
if (BlockStateValues.getBannerColor(blockToPick) != -1 || addNbtData) { /*if (BlockStateValues.getBannerColor(blockToPick) != -1 || addNbtData) { //TODO
session.getGeyser().getWorldManager().getPickItemNbt(session, vector.getX(), vector.getY(), vector.getZ(), addNbtData) session.getGeyser().getWorldManager().getPickItemNbt(session, vector.getX(), vector.getY(), vector.getZ(), addNbtData)
.whenComplete((tag, ex) -> session.ensureInEventLoop(() -> { .whenComplete((tag, ex) -> session.ensureInEventLoop(() -> {
if (tag == null) { if (tag == null) {
@ -94,7 +94,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator<BlockPic
InventoryUtils.findOrCreateItem(session, itemStack); InventoryUtils.findOrCreateItem(session, itemStack);
})); }));
return; return;
} }*/
pickItem(session, blockMapping); pickItem(session, blockMapping);
} }

View File

@ -26,11 +26,11 @@
package org.geysermc.geyser.translator.protocol.bedrock; package org.geysermc.geyser.translator.protocol.bedrock;
import com.github.steveice10.mc.protocol.data.game.item.ItemStack; 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.Filterable;
import com.github.steveice10.mc.protocol.data.game.item.component.WritableBookContent;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundEditBookPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundEditBookPacket;
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.cloudburstmc.protocol.bedrock.packet.BookEditPacket; import org.cloudburstmc.protocol.bedrock.packet.BookEditPacket;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.WrittenBookItem; import org.geysermc.geyser.item.type.WrittenBookItem;
@ -39,10 +39,7 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@Translator(packet = BookEditPacket.class) @Translator(packet = BookEditPacket.class)
public class BedrockBookEditTranslator extends PacketTranslator<BookEditPacket> { public class BedrockBookEditTranslator extends PacketTranslator<BookEditPacket> {
@ -56,9 +53,16 @@ public class BedrockBookEditTranslator extends PacketTranslator<BookEditPacket>
GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(); GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand();
if (itemStack != null) { if (itemStack != null) {
CompoundTag tag = itemStack.getNbt() != null ? itemStack.getNbt() : new CompoundTag(""); DataComponents components = itemStack.getComponents() != null ? itemStack.getComponents() : new DataComponents(new HashMap<>());
ItemStack bookItem = new ItemStack(itemStack.getJavaId(), itemStack.getAmount(), tag); ItemStack bookItem = new ItemStack(itemStack.getJavaId(), itemStack.getAmount(), components);
List<Tag> pages = tag.contains("pages") ? new LinkedList<>(((ListTag) tag.get("pages")).getValue()) : new LinkedList<>(); List<String> pages = new LinkedList<>();
WritableBookContent writableBookContent = components.get(DataComponentType.WRITABLE_BOOK_CONTENT);
if (writableBookContent != null) {
for (Filterable<String> page : writableBookContent.getPages()) {
pages.add(page.getRaw());
}
}
int page = packet.getPageNumber(); int page = packet.getPageNumber();
if (page < 0 || WrittenBookItem.MAXIMUM_PAGE_COUNT <= page) { if (page < 0 || WrittenBookItem.MAXIMUM_PAGE_COUNT <= page) {
@ -69,21 +73,21 @@ public class BedrockBookEditTranslator extends PacketTranslator<BookEditPacket>
case ADD_PAGE: { case ADD_PAGE: {
// Add empty pages in between // Add empty pages in between
for (int i = pages.size(); i < page; i++) { 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; break;
} }
// Called whenever a page is modified // Called whenever a page is modified
case REPLACE_PAGE: { case REPLACE_PAGE: {
if (page < pages.size()) { if (page < pages.size()) {
pages.set(page, new StringTag("", MessageTranslator.convertToPlainText(packet.getText()))); pages.set(page, MessageTranslator.convertToPlainText(packet.getText()));
} else { } else {
// Add empty pages in between // Add empty pages in between
for (int i = pages.size(); i < page; i++) { 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; break;
} }
@ -100,33 +104,29 @@ public class BedrockBookEditTranslator extends PacketTranslator<BookEditPacket>
} }
break; break;
} }
case SIGN_BOOK: {
tag.put(new StringTag("author", MessageTranslator.convertToPlainText(packet.getAuthor())));
tag.put(new StringTag("title", MessageTranslator.convertToPlainText(packet.getTitle())));
break;
}
default: default:
return; return;
} }
// Remove empty pages at the end // Remove empty pages at the end
while (pages.size() > 0) { while (!pages.isEmpty()) {
StringTag currentPage = (StringTag) pages.get(pages.size() - 1); String currentPage = pages.get(pages.size() - 1);
if (currentPage.getValue() == null || currentPage.getValue().isEmpty()) { if (currentPage.isEmpty()) {
pages.remove(pages.size() - 1); pages.remove(pages.size() - 1);
} else { } else {
break; break;
} }
} }
tag.put(new ListTag("pages", pages));
List<Filterable<String>> 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 // Update local copy
session.getPlayerInventory().setItem(36 + session.getPlayerInventory().getHeldItemSlot(), GeyserItemStack.from(bookItem), session); session.getPlayerInventory().setItem(36 + session.getPlayerInventory().getHeldItemSlot(), GeyserItemStack.from(bookItem), session);
session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory()); session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory());
List<String> networkPages = new ArrayList<>();
for (Tag pageTag : pages) {
networkPages.add(((StringTag) pageTag).getValue());
}
String title; String title;
if (packet.getAction() == BookEditPacket.Action.SIGN_BOOK) { if (packet.getAction() == BookEditPacket.Action.SIGN_BOOK) {
// Add title to packet so the server knows we're signing // Add title to packet so the server knows we're signing
@ -139,7 +139,7 @@ public class BedrockBookEditTranslator extends PacketTranslator<BookEditPacket>
title = null; 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 // 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) { if (packet.getAction() == BookEditPacket.Action.SIGN_BOOK) {
session.getBookEditCache().checkForSend(); session.getBookEditCache().checkForSend();

View File

@ -168,7 +168,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
// If the block is custom or the breaking item is custom, we must keep track of break time ourselves // If the block is custom or the breaking item is custom, we must keep track of break time ourselves
GeyserItemStack item = session.getPlayerInventory().getItemInHand(); GeyserItemStack item = session.getPlayerInventory().getItemInHand();
ItemMapping mapping = item.getMapping(session); ItemMapping mapping = item.getMapping(session);
ItemDefinition customItem = mapping.isTool() ? CustomItemTranslator.getCustomItem(item.getNbt(), mapping) : null; ItemDefinition customItem = mapping.isTool() ? CustomItemTranslator.getCustomItem(item.getComponents(), mapping) : null;
CustomBlockState blockStateOverride = BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get(blockState); CustomBlockState blockStateOverride = BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get(blockState);
SkullCache.Skull skull = session.getSkullCache().getSkulls().get(vector); SkullCache.Skull skull = session.getSkullCache().getSkulls().get(vector);

View File

@ -60,7 +60,7 @@ import java.util.*;
public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommandsPacket> { public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommandsPacket> {
private static final String[] ALL_EFFECT_IDENTIFIERS = EntityUtils.getAllEffectIdentifiers(); 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[] ENUM_BOOLEAN = {"true", "false"};
private static final String[] VALID_COLORS; private static final String[] VALID_COLORS;
private static final String[] VALID_SCOREBOARD_SLOTS; private static final String[] VALID_SCOREBOARD_SLOTS;

View File

@ -63,7 +63,7 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
// If the player is already initialized and a join game packet is sent, they // If the player is already initialized and a join game packet is sent, they
// are swapping servers // are swapping servers
if (session.isSpawned()) { if (session.isSpawned()) {
String fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), spawnInfo.getDimension()); int fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), spawnInfo.getDimension());
DimensionUtils.switchDimension(session, fakeDim); DimensionUtils.switchDimension(session, fakeDim);
session.getWorldCache().removeScoreboard(); session.getWorldCache().removeScoreboard();
@ -97,7 +97,7 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
session.setWorldName(spawnInfo.getWorldName()); session.setWorldName(spawnInfo.getWorldName());
session.setLevels(packet.getWorldNames()); session.setLevels(packet.getWorldNames());
session.setGameMode(spawnInfo.getGameMode()); session.setGameMode(spawnInfo.getGameMode());
String newDimension = spawnInfo.getDimension(); int newDimension = spawnInfo.getDimension();
boolean needsSpawnPacket = !session.isSentSpawnPacket(); boolean needsSpawnPacket = !session.isSentSpawnPacket();
if (needsSpawnPacket) { if (needsSpawnPacket) {
@ -135,9 +135,9 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
session.sendDownstreamPacket(new ServerboundCustomPayloadPacket("minecraft:register", PluginMessageChannels.getFloodgateRegisterData())); session.sendDownstreamPacket(new ServerboundCustomPayloadPacket("minecraft:register", PluginMessageChannels.getFloodgateRegisterData()));
} }
if (!newDimension.equals(session.getDimension())) { if (newDimension != session.getDimension()) {
DimensionUtils.switchDimension(session, newDimension); DimensionUtils.switchDimension(session, newDimension);
} else if (DimensionUtils.isCustomBedrockNetherId() && newDimension.equalsIgnoreCase(DimensionUtils.NETHER)) { } else if (DimensionUtils.isCustomBedrockNetherId() && newDimension == DimensionUtils.NETHER) {
// If the player is spawning into the "fake" nether, send them some fog // If the player is spawning into the "fake" nether, send them some fog
session.camera().sendFog(DimensionUtils.BEDROCK_FOG_HELL); session.camera().sendFog(DimensionUtils.BEDROCK_FOG_HELL);
} }

View File

@ -25,9 +25,9 @@
package org.geysermc.geyser.translator.protocol.java; package org.geysermc.geyser.translator.protocol.java;
import com.github.steveice10.mc.protocol.data.game.RegistryEntry;
import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.JavaDimension;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -35,33 +35,39 @@ import org.geysermc.geyser.text.TextDecoration;
import org.geysermc.geyser.translator.level.BiomeTranslator; import org.geysermc.geyser.translator.level.BiomeTranslator;
import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.JavaCodecUtil;
import java.util.Map; import java.util.List;
@Translator(packet = ClientboundRegistryDataPacket.class) @Translator(packet = ClientboundRegistryDataPacket.class)
public class JavaRegistryDataTranslator extends PacketTranslator<ClientboundRegistryDataPacket> { public class JavaRegistryDataTranslator extends PacketTranslator<ClientboundRegistryDataPacket> {
@Override @Override
public void translate(GeyserSession session, ClientboundRegistryDataPacket packet) { public void translate(GeyserSession session, ClientboundRegistryDataPacket packet) {
Map<String, JavaDimension> dimensions = session.getDimensions(); if (packet.getRegistry().equals("minecraft:dimension_type")) {
Int2ObjectMap<JavaDimension> dimensions = session.getDimensions();
dimensions.clear(); dimensions.clear();
JavaDimension.load(packet.getRegistry(), dimensions); JavaDimension.load(packet.getEntries(), dimensions);
}
if (packet.getRegistry().equals("minecraft:chat_type")) {
Int2ObjectMap<TextDecoration> chatTypes = session.getChatTypes(); Int2ObjectMap<TextDecoration> chatTypes = session.getChatTypes();
chatTypes.clear(); chatTypes.clear();
for (CompoundTag tag : JavaCodecUtil.iterateAsTag(packet.getRegistry().get("minecraft:chat_type"))) { List<RegistryEntry> 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. // 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(); RegistryEntry entry = entries.get(i);
CompoundTag element = tag.get("element"); CompoundTag tag = entry.getData();
CompoundTag chat = element.get("chat"); CompoundTag chat = tag.get("chat");
TextDecoration textDecoration = null; TextDecoration textDecoration = null;
if (chat != null) { if (chat != null) {
textDecoration = new TextDecoration(chat); textDecoration = new TextDecoration(chat);
} }
chatTypes.put(id, textDecoration); chatTypes.put(i, textDecoration);
}
} }
BiomeTranslator.loadServerBiomes(session, packet.getRegistry()); if (packet.getRegistry().equals("minecraft:worldgen/biome")) {
BiomeTranslator.loadServerBiomes(session, packet.getEntries());
}
} }
} }

View File

@ -92,11 +92,11 @@ public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPa
session.setThunder(false); session.setThunder(false);
} }
String newDimension = spawnInfo.getDimension(); int newDimension = spawnInfo.getDimension();
if (!session.getDimension().equals(newDimension) || !spawnInfo.getWorldName().equals(session.getWorldName())) { if (session.getDimension() != newDimension || !spawnInfo.getWorldName().equals(session.getWorldName())) {
// Switching to a new world (based off the world name change or new dimension); send a fake dimension change // Switching to a new world (based off the world name change or new dimension); send a fake dimension change
if (DimensionUtils.javaToBedrock(session.getDimension()) == DimensionUtils.javaToBedrock(newDimension)) { if (DimensionUtils.javaToBedrock(session.getDimension()) == DimensionUtils.javaToBedrock(newDimension)) {
String fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), newDimension); int fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), newDimension);
DimensionUtils.switchDimension(session, fakeDim); DimensionUtils.switchDimension(session, fakeDim);
} }
session.setWorldName(spawnInfo.getWorldName()); session.setWorldName(spawnInfo.getWorldName());

View File

@ -31,10 +31,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.Client
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.entity.type.LivingEntity;
import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.skin.FakeHeadProvider;
import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.item.ItemTranslator;
import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
@ -62,14 +59,15 @@ public class JavaSetEquipmentTranslator extends PacketTranslator<ClientboundSetE
switch (equipment.getSlot()) { switch (equipment.getSlot()) {
case HELMET -> { case HELMET -> {
ItemStack javaItem = equipment.getItem(); ItemStack javaItem = equipment.getItem();
if (livingEntity instanceof PlayerEntity // TODO
&& javaItem != null // if (livingEntity instanceof PlayerEntity
&& javaItem.getId() == Items.PLAYER_HEAD.javaId() // && javaItem != null
&& javaItem.getNbt() != null) { // && javaItem.getId() == Items.PLAYER_HEAD.javaId()
FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, javaItem.getNbt().get("SkullOwner")); // && javaItem.getNbt() != null) {
} else { // FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, javaItem.getNbt().get("SkullOwner"));
FakeHeadProvider.restoreOriginalSkin(session, livingEntity); // } else {
} // FakeHeadProvider.restoreOriginalSkin(session, livingEntity);
// }
livingEntity.setHelmet(item); livingEntity.setHelmet(item);
armorUpdated = true; armorUpdated = true;

View File

@ -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.item.ItemStack;
import com.github.steveice10.mc.protocol.data.game.level.particle.BlockParticleData; 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.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.ItemParticleData;
import com.github.steveice10.mc.protocol.data.game.level.particle.Particle; import com.github.steveice10.mc.protocol.data.game.level.particle.Particle;
import com.github.steveice10.mc.protocol.data.game.level.particle.VibrationParticleData; import com.github.steveice10.mc.protocol.data.game.level.particle.VibrationParticleData;
@ -106,7 +105,7 @@ public class JavaLevelParticlesTranslator extends PacketTranslator<ClientboundLe
}; };
} }
case FALLING_DUST -> { case FALLING_DUST -> {
int blockState = session.getBlockMappings().getBedrockBlockId(((FallingDustParticleData) particle.getData()).getBlockState()); int blockState = session.getBlockMappings().getBedrockBlockId(((BlockParticleData) particle.getData()).getBlockState());
return (position) -> { return (position) -> {
LevelEventPacket packet = new LevelEventPacket(); LevelEventPacket packet = new LevelEventPacket();
// In fact, FallingDustParticle should have data like DustParticle, // In fact, FallingDustParticle should have data like DustParticle,

View File

@ -45,12 +45,12 @@ public class AttributeUtils {
} }
double value = base; double value = base;
for (AttributeModifier modifier : attribute.getModifiers()) { for (AttributeModifier modifier : attribute.getModifiers()) {
if (modifier.getOperation() == ModifierOperation.ADD_MULTIPLIED) { if (modifier.getOperation() == ModifierOperation.ADD_MULTIPLIED_BASE) {
value += base * modifier.getAmount(); value += base * modifier.getAmount();
} }
} }
for (AttributeModifier modifier : attribute.getModifiers()) { for (AttributeModifier modifier : attribute.getModifiers()) {
if (modifier.getOperation() == ModifierOperation.MULTIPLY) { if (modifier.getOperation() == ModifierOperation.ADD_MULTIPLIED_TOTAL) {
value *= 1.0D + modifier.getAmount(); value *= 1.0D + modifier.getAmount();
} }
} }

View File

@ -50,19 +50,19 @@ public class DimensionUtils {
/** /**
* String reference to vanilla Java overworld dimension identifier * 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 * 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 * 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 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(); 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 // 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. // thinks they are in the end dimension.
if (isCustomBedrockNetherId()) { if (isCustomBedrockNetherId()) {
if (NETHER.equals(javaDimension)) { if (NETHER == javaDimension) {
session.camera().sendFog(BEDROCK_FOG_HELL); session.camera().sendFog(BEDROCK_FOG_HELL);
} else if (NETHER.equals(previousDimension)) { } else if (NETHER == previousDimension) {
session.camera().removeFog(BEDROCK_FOG_HELL); 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) { session.getChunkCache().setBedrockDimension(switch (javaDimension) {
case DimensionUtils.THE_END -> BedrockDimension.THE_END; case DimensionUtils.THE_END -> BedrockDimension.THE_END;
case DimensionUtils.NETHER -> DimensionUtils.isCustomBedrockNetherId() ? BedrockDimension.THE_END : BedrockDimension.THE_NETHER; case DimensionUtils.NETHER -> DimensionUtils.isCustomBedrockNetherId() ? BedrockDimension.THE_END : BedrockDimension.THE_NETHER;
@ -174,7 +174,7 @@ public class DimensionUtils {
* @param javaDimension Dimension ID to convert * @param javaDimension Dimension ID to convert
* @return Converted Bedrock edition dimension ID * @return Converted Bedrock edition dimension ID
*/ */
public static int javaToBedrock(String javaDimension) { public static int javaToBedrock(int javaDimension) {
return switch (javaDimension) { return switch (javaDimension) {
case NETHER -> BEDROCK_NETHER_ID; case NETHER -> BEDROCK_NETHER_ID;
case THE_END -> 2; 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. * 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. * 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 * @param newDimension the new dimension that the player will be transferred to
* @return the fake dimension to transfer 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()) { if (isCustomBedrockNetherId()) {
// Prevents rare instances of Bedrock locking up // Prevents rare instances of Bedrock locking up
return javaToBedrock(newDimension) == 2 ? OVERWORLD : NETHER; return javaToBedrock(newDimension) == 2 ? OVERWORLD : NETHER;

View File

@ -25,12 +25,12 @@
package org.geysermc.geyser.util; 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.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.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.ServerboundPickItemPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket; 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.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap; 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.InventorySlotPacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerHotbarPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerHotbarPacket;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.*;
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.click.Click; import org.geysermc.geyser.inventory.click.Click;
import org.geysermc.geyser.inventory.recipe.GeyserRecipe; import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe; import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe;
@ -66,6 +62,7 @@ import org.jetbrains.annotations.Contract;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.IntFunction; import java.util.function.IntFunction;
@ -77,7 +74,7 @@ public class InventoryUtils {
*/ */
public static int LAST_RECIPE_NET_ID; 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) { public static void openInventory(GeyserSession session, Inventory inventory) {
session.setOpenInventory(inventory); session.setOpenInventory(inventory);
@ -254,7 +251,7 @@ public class InventoryUtils {
continue; continue;
} }
// If this is the item we're looking for // 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); setHotbarItem(session, i);
// Don't check inventory if item was in hotbar // Don't check inventory if item was in hotbar
return; return;
@ -268,7 +265,7 @@ public class InventoryUtils {
continue; continue;
} }
// If this is the item we're looking for // 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 ServerboundPickItemPacket packetToSend = new ServerboundPickItemPacket(i); // https://wiki.vg/Protocol#Pick_Item
session.sendDownstreamGamePacket(packetToSend); session.sendDownstreamGamePacket(packetToSend);
return; return;
@ -279,7 +276,7 @@ public class InventoryUtils {
if (session.getGameMode() == GameMode.CREATIVE) { if (session.getGameMode() == GameMode.CREATIVE) {
int slot = findEmptyHotbarSlot(inventory); int slot = findEmptyHotbarSlot(inventory);
ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket(slot, ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket((short) slot,
itemStack); itemStack);
if ((slot - 36) != inventory.getHeldItemSlot()) { if ((slot - 36) != inventory.getHeldItemSlot()) {
setHotbarItem(session, slot); setHotbarItem(session, slot);
@ -345,7 +342,7 @@ public class InventoryUtils {
ItemMapping mapping = session.getItemMappings().getMapping(itemName); // TODO ItemMapping mapping = session.getItemMappings().getMapping(itemName); // TODO
if (mapping != null) { if (mapping != null) {
ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket(slot, ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket((short)slot,
new ItemStack(mapping.getJavaItem().javaId())); new ItemStack(mapping.getJavaItem().javaId()));
if ((slot - 36) != inventory.getHeldItemSlot()) { if ((slot - 36) != inventory.getHeldItemSlot()) {
setHotbarItem(session, slot); setHotbarItem(session, slot);

View File

@ -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<CompoundTag> iterateAsTag(CompoundTag tag) {
ListTag value = tag.get("value");
Iterator<Tag> originalIterator = value.iterator();
return new Iterable<>() {
@NonNull
@Override
public Iterator<CompoundTag> iterator() {
return new Iterator<>() {
@Override
public boolean hasNext() {
return originalIterator.hasNext();
}
@Override
public CompoundTag next() {
return (CompoundTag) originalIterator.next();
}
};
}
};
}
private JavaCodecUtil() {
}
}

View File

@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128"
raknet = "1.0.0.CR3-20240416.144209-1" raknet = "1.0.0.CR3-20240416.144209-1"
blockstateupdater="1.20.80-20240411.142413-1" blockstateupdater="1.20.80-20240411.142413-1"
mcauthlib = "d9d773e" mcauthlib = "d9d773e"
mcprotocollib = "1.20.4-2-20240116.220521-7" mcprotocollib = "897eb241b6" # Revert from jitpack after release
adventure = "4.14.0" adventure = "4.14.0"
adventure-platform = "4.3.0" adventure-platform = "4.3.0"
junit = "5.9.2" 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" } gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" } junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" }
mcauthlib = { group = "com.github.GeyserMC", name = "MCAuthLib", version.ref = "mcauthlib" } 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" } raknet = { group = "org.cloudburstmc.netty", name = "netty-transport-raknet", version.ref = "raknet" }
terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" } terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" }
velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" } velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }