Add Item classes to partially replace ItemMapping. Part 1?

This commit is contained in:
Camotoy 2022-12-29 15:10:40 -05:00
parent 7f38496d61
commit 3f4ed67597
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
103 changed files with 2308 additions and 768 deletions

View file

@ -35,6 +35,9 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntit
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
@ -46,12 +49,10 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket;
import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.AttributeUtils;
@ -98,8 +99,7 @@ public class LivingEntity extends Entity {
boolean isUsingItem = (xd & 0x01) == 0x01;
boolean isUsingOffhand = (xd & 0x02) == 0x02;
ItemMapping shield = session.getItemMappings().getStoredItems().shield();
boolean isUsingShield = hasShield(isUsingOffhand, shield);
boolean isUsingShield = hasShield(isUsingOffhand);
setFlag(EntityFlag.USING_ITEM, isUsingItem && !isUsingShield);
// Override the blocking
@ -142,7 +142,8 @@ public class LivingEntity extends Entity {
}
}
protected boolean hasShield(boolean offhand, ItemMapping shieldMapping) {
protected boolean hasShield(boolean offhand) {
ItemMapping shieldMapping = session.getItemMappings().getStoredItems().shield();
if (offhand) {
return offHand.getDefinition().equals(shieldMapping.getBedrockDefinition());
} else {
@ -190,7 +191,7 @@ public class LivingEntity extends Entity {
@Override
public InteractionResult interact(Hand hand) {
GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(hand);
if (itemStack.getJavaId() == session.getItemMappings().getStoredItems().nameTag().getJavaId()) {
if (itemStack.asItem() == Items.NAME_TAG) {
InteractionResult result = checkInteractWithNameTag(itemStack);
if (result.consumesAction()) {
return result;
@ -220,10 +221,10 @@ public class LivingEntity extends Entity {
// If an entity has a banner on them, it will be in the helmet slot in Java but the chestplate spot in Bedrock
// But don't overwrite the chestplate if it isn't empty
ItemMapping banner = session.getItemMappings().getStoredItems().banner();
if (ItemDefinition.AIR.equals(chestplate.getDefinition()) && helmet.getDefinition().equals(banner.getBedrockDefinition())) {
if (ItemDefinition.AIR.equals(chestplate.getDefinition()) && helmet.getDefinition().equals(banner)) {
chestplate = this.helmet;
helmet = ItemData.AIR;
} else if (chestplate.getDefinition().equals(banner.getBedrockDefinition())) {
} else if (chestplate.getDefinition().equals(banner)) {
// Prevent chestplate banners from showing erroneously
chestplate = ItemData.AIR;
}

View file

@ -35,7 +35,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.session.GeyserSession;
import java.util.EnumSet;
@ -56,8 +57,8 @@ public class ThrownPotionEntity extends ThrowableItemEntity {
setFlag(EntityFlag.ENCHANTED, false);
setFlag(EntityFlag.LINGERING, false);
} else {
ItemMapping mapping = session.getItemMappings().getMapping(itemStack);
if (mapping.getJavaIdentifier().endsWith("potion") && itemStack.getNbt() != null) {
// As of Java 1.19.3, the server/client doesn't seem to care of the item is actually a potion?
if (itemStack.getNbt() != null) {
Tag potionTag = itemStack.getNbt().get("Potion");
if (potionTag instanceof StringTag) {
Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue());
@ -70,7 +71,7 @@ public class ThrownPotionEntity extends ThrowableItemEntity {
}
}
boolean isLingering = mapping.getJavaIdentifier().equals("minecraft:lingering_potion");
boolean isLingering = Registries.JAVA_ITEMS.get().get(itemStack.getId()) == Items.LINGERING_POTION;
setFlag(EntityFlag.LINGERING, isLingering);
}
}

View file

@ -31,6 +31,7 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -87,6 +88,6 @@ public class AllayEntity extends MobEntity {
}
private boolean isDuplicationItem(GeyserItemStack itemStack) {
return itemStack.getJavaId() == session.getItemMappings().getStoredItems().amethystShard().getJavaId();
return itemStack.asItem() == Items.AMETHYST_SHARD;
}
}

View file

@ -39,6 +39,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.LivingEntity;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.MathUtils;
@ -247,7 +248,7 @@ public class ArmorStandEntity extends LivingEntity {
@Override
public InteractionResult interactAt(Hand hand) {
if (!isMarker && session.getPlayerInventory().getItemInHand(hand).getJavaId() != session.getItemMappings().getStoredItems().nameTag().getJavaId()) {
if (!isMarker && session.getPlayerInventory().getItemInHand(hand).asItem() != Items.NAME_TAG) {
// Java Edition returns SUCCESS if in spectator mode, but this is overrided with an earlier check on the client
return InteractionResult.CONSUME;
} else {

View file

@ -31,6 +31,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
@ -52,8 +53,8 @@ public class IronGolemEntity extends GolemEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().ironIngot().getJavaId()) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.IRON_INGOT) {
if (health < maxHealth) {
// Healing the iron golem
return InteractionResult.SUCCESS;

View file

@ -27,15 +27,15 @@ package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import lombok.Getter;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import lombok.Getter;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.LivingEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.item.StoredItemMappings;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.SpawnEggItem;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -79,11 +79,10 @@ public class MobEntity extends LivingEntity {
return InteractiveTag.REMOVE_LEASH;
} else {
GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(hand);
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
if (itemStack.getJavaId() == storedItems.lead().getJavaId() && canBeLeashed()) {
if (itemStack.asItem() == Items.LEAD && canBeLeashed()) {
// We shall leash
return InteractiveTag.LEASH;
} else if (itemStack.getJavaId() == storedItems.nameTag().getJavaId()) {
} else if (itemStack.asItem() == Items.NAME_TAG) {
InteractionResult result = checkInteractWithNameTag(itemStack);
if (result.consumesAction()) {
return InteractiveTag.NAME;
@ -116,18 +115,16 @@ public class MobEntity extends LivingEntity {
}
private InteractionResult checkPriorityInteractions(GeyserItemStack itemInHand) {
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
if (itemInHand.getJavaId() == storedItems.lead().getJavaId() && canBeLeashed()) {
if (itemInHand.asItem() == Items.LEAD && canBeLeashed()) {
// We shall leash
return InteractionResult.SUCCESS;
} else if (itemInHand.getJavaId() == storedItems.nameTag().getJavaId()) {
} else if (itemInHand.asItem() == Items.NAME_TAG) {
InteractionResult result = checkInteractWithNameTag(itemInHand);
if (result.consumesAction()) {
return result;
}
} else {
ItemMapping mapping = itemInHand.getMapping(session);
if (mapping.getJavaIdentifier().endsWith("_spawn_egg")) {
if (itemInHand.asItem() instanceof SpawnEggItem) {
// Using the spawn egg on this entity to create a child
return InteractionResult.CONSUME;
}

View file

@ -31,6 +31,7 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -52,8 +53,8 @@ public class SnowGolemEntity extends GolemEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (session.getItemMappings().getStoredItems().shears().getJavaId() == itemInHand.getJavaId() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (Items.SHEARS == itemInHand.asItem() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
// Shearing the snow golem
return InteractiveTag.SHEAR;
}
@ -62,8 +63,8 @@ public class SnowGolemEntity extends GolemEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (session.getItemMappings().getStoredItems().shears().getJavaId() == itemInHand.getJavaId() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (Items.SHEARS == itemInHand.asItem() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
// Shearing the snow golem
return InteractionResult.SUCCESS;
}

View file

@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -61,6 +62,6 @@ public class TadpoleEntity extends AbstractFishEntity {
}
private boolean isFood(GeyserItemStack itemStack) {
return itemStack.getJavaId() == session.getItemMappings().getStoredItems().slimeBall().getJavaId();
return itemStack.asItem() == Items.SLIME_BALL;
}
}

View file

@ -32,7 +32,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.living.AgeableEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -47,24 +48,20 @@ public class AnimalEntity extends AgeableEntity {
}
public final boolean canEat(GeyserItemStack itemStack) {
ItemMapping mapping = itemStack.getMapping(session);
String handIdentifier = mapping.getJavaIdentifier();
return canEat(handIdentifier.replace("minecraft:", ""), mapping);
return canEat(itemStack.asItem());
}
/**
* @param javaIdentifierStripped the stripped Java identifier of the item that is potential breeding food. For example,
* <code>wheat</code>.
* @return true if this is a valid item to breed with for this animal.
*/
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(Item item) {
// This is what it defaults to. OK.
return javaIdentifierStripped.equals("wheat");
return item == Items.WHEAT;
}
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (canEat(itemInHand)) {
return InteractiveTag.FEED;
}
@ -73,7 +70,7 @@ public class AnimalEntity extends AgeableEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (canEat(itemInHand)) {
// FEED
if (getFlag(EntityFlag.BABY)) {

View file

@ -33,7 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult;
@ -60,8 +60,8 @@ public class AxolotlEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return session.getTagCache().isAxolotlTemptItem(mapping);
public boolean canEat(Item item) {
return session.getTagCache().isAxolotlTemptItem(item);
}
@Override
@ -76,7 +76,7 @@ public class AxolotlEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (EntityUtils.attemptToBucket(session, itemInHand)) {
return InteractionResult.SUCCESS;
} else {

View file

@ -33,7 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
@ -66,7 +66,7 @@ public class BeeEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return session.getTagCache().isFlower(mapping);
public boolean canEat(Item item) {
return session.getTagCache().isFlower(item);
}
}

View file

@ -27,19 +27,22 @@ package org.geysermc.geyser.entity.type.living.animal;
import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import java.util.Set;
import java.util.UUID;
public class ChickenEntity extends AnimalEntity {
private static final Set<Item> VALID_FOOD = Set.of(Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS);
public ChickenEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.contains("seeds");
public boolean canEat(Item item) {
return VALID_FOOD.contains(item);
}
}

View file

@ -31,6 +31,7 @@ import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -45,8 +46,8 @@ public class CowEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (getFlag(EntityFlag.BABY) || !itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (getFlag(EntityFlag.BABY) || itemInHand.asItem() != Items.BUCKET) {
return super.testMobInteraction(hand, itemInHand);
}
@ -55,8 +56,8 @@ public class CowEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (getFlag(EntityFlag.BABY) || !itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (getFlag(EntityFlag.BABY) || itemInHand.asItem() != Items.BUCKET) {
return super.mobInteract(hand, itemInHand);
}

View file

@ -31,7 +31,7 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
@ -55,7 +55,7 @@ public class FoxEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return session.getTagCache().isFoxFood(mapping);
public boolean canEat(Item item) {
return session.getTagCache().isFoxFood(item);
}
}

View file

@ -33,7 +33,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import java.util.OptionalInt;
@ -75,7 +76,7 @@ public class FrogEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return mapping.getJavaId() == session.getItemMappings().getStoredItems().slimeBall().getJavaId();
public boolean canEat(Item item) {
return item == Items.SLIME_BALL;
}
}

View file

@ -34,6 +34,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
@ -67,10 +68,12 @@ public class GoatEntity extends AnimalEntity {
}
}
// TODO testMobInteraction?
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.BABY) && itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.BABY) && itemInHand.asItem() == Items.BUCKET) {
session.playSoundEvent(isScreamer ? SoundEvent.MILK_SCREAMER : SoundEvent.MILK, position);
return InteractionResult.SUCCESS;
} else {

View file

@ -29,7 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
@ -53,8 +54,8 @@ public class HoglinEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("crimson_fungus");
public boolean canEat(Item item) {
return item == Items.CRIMSON_FUNGUS;
}
@Override

View file

@ -31,7 +31,7 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.item.StoredItemMappings;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -53,13 +53,12 @@ public class MooshroomEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!isBaby()) {
if (itemInHand.getJavaId() == storedItems.bowl().getJavaId()) {
if (itemInHand.asItem() == Items.BOWL) {
// Stew
return InteractiveTag.MOOSHROOM_MILK_STEW;
} else if (isAlive() && itemInHand.getJavaId() == storedItems.shears().getJavaId()) {
} else if (isAlive() && itemInHand.asItem() == Items.SHEARS) {
// Shear items
return InteractiveTag.MOOSHROOM_SHEAR;
}
@ -69,13 +68,12 @@ public class MooshroomEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
boolean isBaby = isBaby();
if (!isBaby && itemInHand.getJavaId() == storedItems.bowl().getJavaId()) {
if (!isBaby && itemInHand.asItem() == Items.BOWL) {
// Stew
return InteractionResult.SUCCESS;
} else if (!isBaby && isAlive() && itemInHand.getJavaId() == storedItems.shears().getJavaId()) {
} else if (!isBaby && isAlive() && itemInHand.asItem() == Items.SHEARS) {
// Shear items
return InteractionResult.SUCCESS;
} else if (isBrown && session.getTagCache().isSmallFlower(itemInHand) && itemInHand.getMapping(session).isHasSuspiciousStewEffect()) {

View file

@ -30,7 +30,8 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -45,8 +46,8 @@ public class OcelotEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon");
public boolean canEat(Item item) {
return item == Items.COD || item == Items.SALMON;
}
@Nonnull

View file

@ -35,7 +35,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -88,13 +89,13 @@ public class PandaEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("bamboo");
public boolean canEat(Item item) {
return item == Items.BAMBOO;
}
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (mainGene == Gene.WORRIED && session.isThunder()) {
return InteractiveTag.NONE;
}
@ -103,7 +104,7 @@ public class PandaEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (mainGene == Gene.WORRIED && session.isThunder()) {
// Huh!
return InteractionResult.PASS;

View file

@ -30,7 +30,8 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult;
@ -46,13 +47,13 @@ public class PigEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("potato") || javaIdentifierStripped.equals("beetroot");
public boolean canEat(Item item) {
return item == Items.CARROT || item == Items.POTATO || item == Items.BEETROOT;
}
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount
return InteractiveTag.MOUNT;
@ -61,7 +62,7 @@ public class PigEntity extends AnimalEntity {
if (superTag != InteractiveTag.NONE) {
return superTag;
} else {
return EntityUtils.attemptToSaddle(session, this, itemInHand).consumesAction()
return EntityUtils.attemptToSaddle(this, itemInHand).consumesAction()
? InteractiveTag.SADDLE : InteractiveTag.NONE;
}
}
@ -69,7 +70,7 @@ public class PigEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount
return InteractionResult.SUCCESS;
@ -78,7 +79,7 @@ public class PigEntity extends AnimalEntity {
if (superResult.consumesAction()) {
return superResult;
} else {
return EntityUtils.attemptToSaddle(session, this, itemInHand);
return EntityUtils.attemptToSaddle(this, itemInHand);
}
}
}

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal;
import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
@ -39,7 +39,7 @@ public class PolarBearEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(Item item) {
return false;
}
}

View file

@ -31,7 +31,8 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
@ -72,7 +73,7 @@ public class RabbitEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("dandelion") || javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("golden_carrot");
public boolean canEat(Item item) {
return item == Items.DANDELION || item == Items.CARROT || item == Items.GOLDEN_CARROT;
}
}

View file

@ -32,10 +32,11 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.DyeItem;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.geyser.util.ItemUtils;
import javax.annotation.Nonnull;
import java.util.UUID;
@ -56,16 +57,15 @@ public class SheepEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().shears().getJavaId()) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.SHEARS) {
return InteractiveTag.SHEAR;
} else {
InteractiveTag tag = super.testMobInteraction(hand, itemInHand);
if (tag != InteractiveTag.NONE) {
return tag;
} else {
int color = ItemUtils.dyeColorFor(itemInHand.getJavaId());
if (canDye(color)) {
if (canDye(itemInHand)) {
return InteractiveTag.DYE;
}
return InteractiveTag.NONE;
@ -75,16 +75,15 @@ public class SheepEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().shears().getJavaId()) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.SHEARS) {
return InteractionResult.CONSUME;
} else {
InteractionResult superResult = super.mobInteract(hand, itemInHand);
if (superResult.consumesAction()) {
return superResult;
} else {
int color = ItemUtils.dyeColorFor(itemInHand.getJavaId());
if (canDye(color)) {
if (canDye(itemInHand)) {
// Dyeing the sheep
return InteractionResult.SUCCESS;
}
@ -93,7 +92,7 @@ public class SheepEntity extends AnimalEntity {
}
}
private boolean canDye(int color) {
return color != -1 && color != this.color && !getFlag(EntityFlag.SHEARED);
private boolean canDye(GeyserItemStack item) {
return item.asItem() instanceof DyeItem dyeItem && dyeItem.dyeColor() != this.color && !getFlag(EntityFlag.SHEARED);
}
}

View file

@ -32,7 +32,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult;
@ -93,13 +94,13 @@ public class StriderEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("warped_fungus");
public boolean canEat(Item item) {
return item == Items.WARPED_FUNGUS;
}
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount Strider
return InteractiveTag.RIDE_STRIDER;
@ -108,7 +109,7 @@ public class StriderEntity extends AnimalEntity {
if (tag != InteractiveTag.NONE) {
return tag;
} else {
return EntityUtils.attemptToSaddle(session, this, itemInHand).consumesAction()
return EntityUtils.attemptToSaddle(this, itemInHand).consumesAction()
? InteractiveTag.SADDLE : InteractiveTag.NONE;
}
}
@ -116,7 +117,7 @@ public class StriderEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount Strider
return InteractionResult.SUCCESS;
@ -125,7 +126,7 @@ public class StriderEntity extends AnimalEntity {
if (superResult.consumesAction()) {
return superResult;
} else {
return EntityUtils.attemptToSaddle(session, this, itemInHand);
return EntityUtils.attemptToSaddle(this, itemInHand);
}
}
}

View file

@ -29,7 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
@ -49,8 +50,8 @@ public class TurtleEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("seagrass");
public boolean canEat(Item item) {
return item == Items.SEAGRASS;
}
@Override

View file

@ -27,7 +27,6 @@ package org.geysermc.geyser.entity.type.living.animal.horse;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.google.common.collect.ImmutableSet;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
@ -39,7 +38,8 @@ import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.entity.type.living.animal.AnimalEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -53,8 +53,8 @@ public class AbstractHorseEntity extends AnimalEntity {
* A list of all foods a horse/donkey can eat on Java Edition.
* Used to display interactive tag if needed.
*/
private static final Set<String> DONKEY_AND_HORSE_FOODS = ImmutableSet.of("golden_apple", "enchanted_golden_apple",
"golden_carrot", "sugar", "apple", "wheat", "hay_block");
private static final Set<Item> DONKEY_AND_HORSE_FOODS = Set.of(Items.GOLDEN_APPLE, Items.ENCHANTED_GOLDEN_APPLE,
Items.GOLDEN_CARROT, Items.SUGAR, Items.APPLE, Items.WHEAT, Items.HAY_BLOCK);
public AbstractHorseEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
@ -124,13 +124,13 @@ public class AbstractHorseEntity extends AnimalEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return DONKEY_AND_HORSE_FOODS.contains(javaIdentifierStripped);
public boolean canEat(Item item) {
return DONKEY_AND_HORSE_FOODS.contains(item);
}
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
return testHorseInteraction(hand, itemInHand);
}
@ -165,7 +165,7 @@ public class AbstractHorseEntity extends AnimalEntity {
return InteractiveTag.ATTACH_CHEST;
}
if (additionalTestForInventoryOpen(itemInHand) || !isBaby && !getFlag(EntityFlag.SADDLED) && itemInHand.getJavaId() == session.getItemMappings().getStoredItems().saddle().getJavaId()) {
if (additionalTestForInventoryOpen(itemInHand) || !isBaby && !getFlag(EntityFlag.SADDLED) && itemInHand.asItem() == Items.SADDLE) {
// Will open the inventory to be saddled
return InteractiveTag.OPEN_CONTAINER;
}
@ -221,7 +221,7 @@ public class AbstractHorseEntity extends AnimalEntity {
}
// Note: yes, this code triggers for llamas too. lol (as of Java Edition 1.18.1)
if (additionalTestForInventoryOpen(itemInHand) || (!isBaby && !getFlag(EntityFlag.SADDLED) && itemInHand.getJavaId() == session.getItemMappings().getStoredItems().saddle().getJavaId())) {
if (additionalTestForInventoryOpen(itemInHand) || (!isBaby && !getFlag(EntityFlag.SADDLED) && itemInHand.asItem() == Items.SADDLE)) {
// Will open the inventory to be saddled
return InteractionResult.SUCCESS;
}
@ -245,7 +245,7 @@ public class AbstractHorseEntity extends AnimalEntity {
}
protected boolean additionalTestForInventoryOpen(@Nonnull GeyserItemStack itemInHand) {
return itemInHand.getMapping(session).getJavaIdentifier().endsWith("_horse_armor");
return itemInHand.asItem().javaIdentifier().endsWith("_horse_armor");
}
/* Just a place to stuff common code for the undead variants without having duplicate code */
@ -260,7 +260,7 @@ public class AbstractHorseEntity extends AnimalEntity {
} else if (!passengers.isEmpty()) {
return testHorseInteraction(hand, itemInHand);
} else {
if (session.getItemMappings().getStoredItems().saddle().getJavaId() == itemInHand.getJavaId()) {
if (Items.SADDLE == itemInHand.asItem()) {
return InteractiveTag.OPEN_CONTAINER;
}

View file

@ -30,7 +30,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
@ -50,8 +51,8 @@ public class CamelEntity extends AbstractHorseEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return "cactus".equals(javaIdentifierStripped);
public boolean canEat(Item item) {
return item == Items.CACTUS;
}
@Override

View file

@ -29,6 +29,7 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import javax.annotation.Nonnull;
@ -53,7 +54,7 @@ public class ChestedHorseEntity extends AbstractHorseEntity {
@Override
protected boolean testForChest(@Nonnull GeyserItemStack itemInHand) {
return itemInHand.getJavaId() == session.getItemMappings().getStoredItems().chest().getJavaId() && !getFlag(EntityFlag.CHESTED);
return itemInHand.asItem() == Items.CHEST && !getFlag(EntityFlag.CHESTED);
}
@Override

View file

@ -31,7 +31,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
@ -69,7 +70,7 @@ public class LlamaEntity extends ChestedHorseEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("wheat") || javaIdentifierStripped.equals("hay_block");
public boolean canEat(Item item) {
return item == Items.WHEAT || item == Items.HAY_BLOCK;
}
}

View file

@ -34,7 +34,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -100,13 +101,13 @@ public class CatEntity extends TameableEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon");
public boolean canEat(Item item) {
return item == Items.COD || item == Items.SALMON;
}
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
boolean tamed = getFlag(EntityFlag.TAMED);
if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
// Toggle sitting
@ -118,7 +119,7 @@ public class CatEntity extends TameableEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
boolean tamed = getFlag(EntityFlag.TAMED);
if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
return InteractionResult.SUCCESS;

View file

@ -30,41 +30,44 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import javax.annotation.Nonnull;
import java.util.Set;
import java.util.UUID;
public class ParrotEntity extends TameableEntity {
// Note: is the same as chicken. Reuse?
private static final Set<Item> TAMING_FOOD = Set.of(Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS);
public ParrotEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(Item item) {
return false;
}
private boolean isTameFood(String javaIdentifierStripped) {
return javaIdentifierStripped.contains("seeds");
private boolean isTameFood(Item item) {
return TAMING_FOOD.contains(item);
}
private boolean isPoisonousFood(String javaIdentifierStripped) {
return javaIdentifierStripped.equals("cookie");
private boolean isPoisonousFood(Item item) {
return item == Items.COOKIE;
}
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
String javaIdentifierStripped = itemInHand.getMapping(session).getJavaIdentifier().replace("minecraft:", "");
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
boolean tame = getFlag(EntityFlag.TAMED);
if (!tame && isTameFood(javaIdentifierStripped)) {
if (!tame && isTameFood(itemInHand.asItem())) {
return InteractiveTag.FEED;
} else if (isPoisonousFood(javaIdentifierStripped)) {
} else if (isPoisonousFood(itemInHand.asItem())) {
return InteractiveTag.FEED;
} else if (onGround && tame && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
// Sitting/standing
@ -75,12 +78,11 @@ public class ParrotEntity extends TameableEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
String javaIdentifierStripped = itemInHand.getMapping(session).getJavaIdentifier().replace("minecraft:", "");
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
boolean tame = getFlag(EntityFlag.TAMED);
if (!tame && isTameFood(javaIdentifierStripped)) {
if (!tame && isTameFood(itemInHand.asItem())) {
return InteractionResult.SUCCESS;
} else if (isPoisonousFood(javaIdentifierStripped)) {
} else if (isPoisonousFood(itemInHand.asItem())) {
return InteractionResult.SUCCESS;
} else if (onGround && tame && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
// Sitting/standing

View file

@ -28,17 +28,17 @@ package org.geysermc.geyser.entity.type.living.animal.tameable;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.google.common.collect.ImmutableSet;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.DyeItem;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.geyser.util.ItemUtils;
import javax.annotation.Nonnull;
import java.util.Set;
@ -48,10 +48,11 @@ public class WolfEntity extends TameableEntity {
/**
* A list of all foods a wolf can eat on Java Edition.
* Used to display interactive tag or particles if needed.
* TODO generate
*/
private static final Set<String> WOLF_FOODS = ImmutableSet.of("pufferfish", "tropical_fish", "chicken", "cooked_chicken",
"porkchop", "beef", "rabbit", "cooked_porkchop", "cooked_beef", "rotten_flesh", "mutton", "cooked_mutton",
"cooked_rabbit");
private static final Set<Item> WOLF_FOODS = Set.of(Items.PUFFERFISH, Items.TROPICAL_FISH, Items.CHICKEN, Items.COOKED_CHICKEN,
Items.PORKCHOP, Items.BEEF, Items.RABBIT, Items.COOKED_PORKCHOP, Items.COOKED_BEEF, Items.ROTTEN_FLESH, Items.MUTTON, Items.COOKED_MUTTON,
Items.COOKED_RABBIT);
private byte collarColor;
@ -92,9 +93,9 @@ public class WolfEntity extends TameableEntity {
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(Item item) {
// Cannot be a baby to eat these foods
return WOLF_FOODS.contains(javaIdentifierStripped) && !isBaby();
return WOLF_FOODS.contains(item) && !isBaby();
}
@Override
@ -104,18 +105,17 @@ public class WolfEntity extends TameableEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (getFlag(EntityFlag.ANGRY)) {
return InteractiveTag.NONE;
}
if (itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bone") && !getFlag(EntityFlag.TAMED)) {
if (itemInHand.asItem() == Items.BONE && !getFlag(EntityFlag.TAMED)) {
// Bone and untamed - can tame
return InteractiveTag.TAME;
} else {
int color = ItemUtils.dyeColorFor(itemInHand.getJavaId());
if (color != -1) {
if (itemInHand.asItem() instanceof DyeItem item) {
// If this fails, as of Java Edition 1.18.1, you cannot toggle sit/stand
if (color != this.collarColor) {
if (item.dyeColor() != this.collarColor) {
return InteractiveTag.DYE;
}
} else if (getFlag(EntityFlag.TAMED) && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
@ -128,9 +128,9 @@ public class WolfEntity extends TameableEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (ownerBedrockId == session.getPlayerEntity().getGeyserId() || getFlag(EntityFlag.TAMED)
|| itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bone") && !getFlag(EntityFlag.ANGRY)) {
|| itemInHand.asItem() == Items.BONE && !getFlag(EntityFlag.ANGRY)) {
// Sitting toggle or feeding; not angry
return InteractionResult.CONSUME;
} else {

View file

@ -32,6 +32,7 @@ import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.living.AgeableEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -52,9 +53,8 @@ public class AbstractMerchantEntity extends AgeableEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
String javaIdentifier = itemInHand.getMapping(session).getJavaIdentifier();
if (!javaIdentifier.equals("minecraft:villager_spawn_egg")
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.asItem() != Items.VILLAGER_SPAWN_EGG
&& (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING) && ((VillagerEntity) this).isCanTradeWith())) {
// An additional check we know cannot work
if (!isBaby()) {
@ -66,9 +66,8 @@ public class AbstractMerchantEntity extends AgeableEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
String javaIdentifier = itemInHand.getMapping(session).getJavaIdentifier();
if (!javaIdentifier.equals("minecraft:villager_spawn_egg")
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.asItem() != Items.VILLAGER_SPAWN_EGG
&& (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING))
&& (definition != EntityDefinitions.WANDERING_TRADER || !getFlag(EntityFlag.BABY))) {
// Trading time

View file

@ -33,6 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -64,8 +65,8 @@ public class CreeperEntity extends MonsterEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().flintAndSteel().getJavaId()) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.FLINT_AND_STEEL) { // TODO now uses item tag
return InteractiveTag.IGNITE_CREEPER;
} else {
return super.testMobInteraction(hand, itemInHand);
@ -74,8 +75,8 @@ public class CreeperEntity extends MonsterEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().flintAndSteel().getJavaId()) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.FLINT_AND_STEEL) {
// Ignite creeper
session.playSoundEvent(SoundEvent.IGNITE, position);
return InteractionResult.SUCCESS;

View file

@ -32,6 +32,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -64,7 +65,7 @@ public class PiglinEntity extends BasePiglinEntity {
@Override
public void updateOffHand(GeyserSession session) {
// Check if the Piglin is holding Gold and set the ADMIRING flag accordingly so its pose updates
setFlag(EntityFlag.ADMIRING, session.getTagCache().shouldPiglinAdmire(session.getItemMappings().getMapping(this.offHand)));
setFlag(EntityFlag.ADMIRING, session.getTagCache().shouldPiglinAdmire(session.getItemMappings().getMapping(this.offHand).getJavaItem()));
super.updateBedrockMetadata();
super.updateOffHand(session);
@ -72,7 +73,7 @@ public class PiglinEntity extends BasePiglinEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
InteractiveTag tag = super.testMobInteraction(hand, itemInHand);
if (tag != InteractiveTag.NONE) {
return tag;
@ -83,7 +84,7 @@ public class PiglinEntity extends BasePiglinEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
InteractionResult superResult = super.mobInteract(hand, itemInHand);
if (superResult.consumesAction()) {
return superResult;
@ -93,6 +94,6 @@ public class PiglinEntity extends BasePiglinEntity {
}
private boolean canGiveGoldTo(@Nonnull GeyserItemStack itemInHand) {
return !getFlag(EntityFlag.BABY) && itemInHand.getJavaId() == session.getItemMappings().getStoredItems().goldIngot().getJavaId() && !getFlag(EntityFlag.ADMIRING);
return !getFlag(EntityFlag.BABY) && itemInHand.asItem() == Items.GOLD_INGOT && !getFlag(EntityFlag.ADMIRING);
}
}

View file

@ -35,6 +35,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.living.merchant.VillagerEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -68,8 +69,8 @@ public class ZombieVillagerEntity extends ZombieEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().goldenApple().getJavaId()) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.GOLDEN_APPLE) {
return InteractiveTag.CURE;
} else {
return super.testMobInteraction(hand, itemInHand);
@ -78,8 +79,8 @@ public class ZombieVillagerEntity extends ZombieEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().goldenApple().getJavaId()) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.GOLDEN_APPLE) {
// The client doesn't know if the entity has weakness as that's not usually sent over the network
return InteractionResult.CONSUME;
} else {

View file

@ -38,7 +38,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.DimensionUtils;
@ -189,12 +189,12 @@ public class SessionPlayerEntity extends PlayerEntity {
}
@Override
protected boolean hasShield(boolean offhand, ItemMapping shieldMapping) {
protected boolean hasShield(boolean offhand) {
// Must be overridden to point to the player's inventory cache
if (offhand) {
return session.getPlayerInventory().getOffhand().getJavaId() == shieldMapping.getJavaId();
return session.getPlayerInventory().getOffhand().asItem() == Items.SHIELD;
} else {
return session.getPlayerInventory().getItemInHand().getJavaId() == shieldMapping.getJavaId();
return session.getPlayerInventory().getItemInHand().asItem() == Items.SHIELD;
}
}

View file

@ -29,6 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import lombok.Data;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
@ -105,6 +107,15 @@ public class GeyserItemStack {
return session.getItemMappings().getMapping(this.javaId);
}
private Item item; //TODO
public Item asItem() {
if (item == null) {
return (item = Registries.JAVA_ITEMS.get().get(javaId));
}
return item;
}
public boolean isEmpty() {
return amount <= 0 || javaId == 0;
}

View file

@ -35,6 +35,7 @@ import lombok.Setter;
import lombok.ToString;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import org.jetbrains.annotations.Range;
@ -131,7 +132,7 @@ public abstract class Inventory {
items[slot] = newItem;
// Lodestone caching
if (newItem.getJavaId() == session.getItemMappings().getStoredItems().compass().getJavaId()) {
if (newItem.asItem() == Items.COMPASS) {
CompoundTag nbt = newItem.getNbt();
if (nbt != null) {
Tag lodestoneTag = nbt.get("LodestoneTracked");

View file

@ -27,6 +27,8 @@ package org.geysermc.geyser.inventory.item;
import lombok.Getter;
import lombok.experimental.Accessors;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import javax.annotation.Nonnull;
@ -38,79 +40,45 @@ import java.util.Map;
@Getter
@Accessors(fluent = true)
public class StoredItemMappings {
private final ItemMapping amethystShard;
private final ItemMapping bamboo;
private final ItemMapping banner;
private final ItemMapping barrier;
private final ItemMapping bowl;
private final ItemMapping bucket;
private final ItemMapping chest;
private final ItemMapping compass;
private final ItemMapping crossbow;
private final ItemMapping enchantedBook;
private final ItemMapping fishingRod;
private final ItemMapping flintAndSteel;
private final ItemMapping frogspawn;
private final ItemMapping goatHorn;
private final ItemMapping glassBottle;
private final ItemMapping goldenApple;
private final ItemMapping goldIngot;
private final ItemMapping ironIngot;
private final ItemMapping lead;
private final ItemMapping lilyPad;
private final ItemMapping milkBucket;
private final ItemMapping nameTag;
private final ItemMapping powderSnowBucket;
private final ItemMapping playerHead;
private final ItemMapping egg;
private final ItemMapping saddle;
private final ItemMapping shears;
private final ItemMapping shield;
private final ItemMapping slimeBall;
private final ItemMapping waterBucket;
private final ItemMapping wheat;
private final ItemMapping writableBook;
public StoredItemMappings(Map<String, ItemMapping> itemMappings) {
this.amethystShard = load(itemMappings, "amethyst_shard");
this.bamboo = load(itemMappings, "bamboo");
this.banner = load(itemMappings, "white_banner"); // As of 1.17.10, all banners have the same Bedrock ID
this.barrier = load(itemMappings, "barrier");
this.bowl = load(itemMappings, "bowl");
this.bucket = load(itemMappings, "bucket");
this.chest = load(itemMappings, "chest");
this.compass = load(itemMappings, "compass");
this.crossbow = load(itemMappings, "crossbow");
this.enchantedBook = load(itemMappings, "enchanted_book");
this.fishingRod = load(itemMappings, "fishing_rod");
this.flintAndSteel = load(itemMappings, "flint_and_steel");
this.frogspawn = load(itemMappings, "frogspawn");
this.goatHorn = load(itemMappings, "goat_horn");
this.glassBottle = load(itemMappings, "glass_bottle");
this.goldenApple = load(itemMappings, "golden_apple");
this.goldIngot = load(itemMappings, "gold_ingot");
this.ironIngot = load(itemMappings, "iron_ingot");
this.lead = load(itemMappings, "lead");
this.lilyPad = load(itemMappings, "lily_pad");
this.milkBucket = load(itemMappings, "milk_bucket");
this.nameTag = load(itemMappings, "name_tag");
this.powderSnowBucket = load(itemMappings, "powder_snow_bucket");
this.playerHead = load(itemMappings, "player_head");
this.egg = load(itemMappings, "egg");
this.saddle = load(itemMappings, "saddle");
this.shears = load(itemMappings, "shears");
this.shield = load(itemMappings, "shield");
this.slimeBall = load(itemMappings, "slime_ball");
this.waterBucket = load(itemMappings, "water_bucket");
this.wheat = load(itemMappings, "wheat");
this.writableBook = load(itemMappings, "writable_book");
public StoredItemMappings(Map<Item, ItemMapping> itemMappings) {
this.bamboo = load(itemMappings, Items.BAMBOO);
this.banner = load(itemMappings, Items.WHITE_BANNER); // As of 1.17.10, all banners have the same Bedrock ID
this.barrier = load(itemMappings, Items.BARRIER);
this.bucket = load(itemMappings, Items.BUCKET);
this.compass = load(itemMappings, Items.COMPASS);
this.crossbow = load(itemMappings, Items.CROSSBOW);
this.frogspawn = load(itemMappings, Items.FROGSPAWN);
this.glassBottle = load(itemMappings, Items.GLASS_BOTTLE);
this.lilyPad = load(itemMappings, Items.LILY_PAD);
this.milkBucket = load(itemMappings, Items.MILK_BUCKET);
this.powderSnowBucket = load(itemMappings, Items.POWDER_SNOW_BUCKET);
this.egg = load(itemMappings, Items.EGG);
this.shield = load(itemMappings, Items.SHIELD);
this.waterBucket = load(itemMappings, Items.WATER_BUCKET);
this.wheat = load(itemMappings, Items.WHEAT);
}
@Nonnull
private ItemMapping load(Map<String, ItemMapping> itemMappings, String cleanIdentifier) {
ItemMapping mapping = itemMappings.get("minecraft:" + cleanIdentifier);
private ItemMapping load(Map<Item, ItemMapping> itemMappings, Item item) {
ItemMapping mapping = itemMappings.get(item);
if (mapping == null) {
throw new RuntimeException("Could not find item " + cleanIdentifier);
throw new RuntimeException("Could not find item " + item.javaIdentifier());
}
return mapping;

View file

@ -44,6 +44,7 @@ import org.geysermc.geyser.inventory.AnvilContainer;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.EnchantmentData;
import org.geysermc.geyser.session.GeyserSession;
@ -222,9 +223,9 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
int cost = 0;
if (!material.isEmpty()) {
totalRepairCost += getRepairCost(material);
if (isCombining(session, input, material)) {
if (hasDurability(session, input) && input.getJavaId() == material.getJavaId()) {
cost += calcMergeRepairCost(session, input, material);
if (isCombining(input, material)) {
if (hasDurability(input) && input.getJavaId() == material.getJavaId()) {
cost += calcMergeRepairCost(input, material);
}
int enchantmentLevelCost = calcMergeEnchantmentCost(session, input, material, bedrock);
@ -234,8 +235,8 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
// Can't repair or merge enchantments
return -1;
}
} else if (hasDurability(session, input) && isRepairing(session, input, material)) {
cost = calcRepairLevelCost(session, input, material);
} else if (hasDurability(input) && isRepairing(session, input, material)) {
cost = calcRepairLevelCost(input, material);
if (cost == -1) {
// No damage to repair
return -1;
@ -260,21 +261,20 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
* Calculate the levels needed to repair an item with its repair material
* E.g. iron_sword + iron_ingot
*
* @param session Geyser session
* @param input an item with durability
* @param material the item's respective repair material
* @return the number of levels needed or 0 if it is not possible to repair any further
*/
private int calcRepairLevelCost(GeyserSession session, GeyserItemStack input, GeyserItemStack material) {
private int calcRepairLevelCost(GeyserItemStack input, GeyserItemStack material) {
int newDamage = getDamage(input);
int unitRepair = Math.min(newDamage, input.getMapping(session).getMaxDamage() / 4);
int unitRepair = Math.min(newDamage, input.asItem().maxDamage() / 4);
if (unitRepair <= 0) {
// No damage to repair
return -1;
}
for (int i = 0; i < material.getAmount(); i++) {
newDamage -= unitRepair;
unitRepair = Math.min(newDamage, input.getMapping(session).getMaxDamage() / 4);
unitRepair = Math.min(newDamage, input.asItem().maxDamage() / 4);
if (unitRepair <= 0) {
return i + 1;
}
@ -285,14 +285,13 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
/**
* Calculate the levels cost for repairing items by combining two of the same item
*
* @param session Geyser session
* @param input an item with durability
* @param material a matching item
* @return the number of levels needed or 0 if it is not possible to repair any further
*/
private int calcMergeRepairCost(GeyserSession session, GeyserItemStack input, GeyserItemStack material) {
private int calcMergeRepairCost(GeyserItemStack input, GeyserItemStack material) {
// If the material item is damaged 112% or more, then the input item will not be repaired
if (getDamage(input) > 0 && getDamage(material) < (material.getMapping(session).getMaxDamage() * 112 / 100)) {
if (getDamage(input) > 0 && getDamage(material) < (material.asItem().maxDamage() * 112 / 100)) {
return 2;
}
return 0;
@ -319,7 +318,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
continue;
}
boolean canApply = isEnchantedBook(session, input) || data.validItems().contains(input.getJavaId());
boolean canApply = isEnchantedBook(input) || data.validItems().contains(input.getJavaId());
for (JavaEnchantment incompatible : data.incompatibleEnchantments()) {
if (combinedEnchantments.containsKey(incompatible)) {
canApply = false;
@ -342,7 +341,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
combinedEnchantments.put(enchantment, newLevel);
int rarityMultiplier = data.rarityMultiplier();
if (isEnchantedBook(session, material) && rarityMultiplier > 1) {
if (isEnchantedBook(material) && rarityMultiplier > 1) {
rarityMultiplier /= 2;
}
if (bedrock) {
@ -376,7 +375,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
}
Object2IntMap<JavaEnchantment> enchantments = new Object2IntOpenHashMap<>();
Tag enchantmentTag;
if (isEnchantedBook(session, itemStack)) {
if (isEnchantedBook(itemStack)) {
enchantmentTag = itemStack.getNbt().get("StoredEnchantments");
} else {
enchantmentTag = itemStack.getNbt().get("Enchantments");
@ -408,17 +407,17 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
return enchantments;
}
private boolean isEnchantedBook(GeyserSession session, GeyserItemStack itemStack) {
return itemStack.getJavaId() == session.getItemMappings().getStoredItems().enchantedBook().getJavaId();
private boolean isEnchantedBook(GeyserItemStack itemStack) {
return itemStack.asItem() == Items.ENCHANTED_BOOK;
}
private boolean isCombining(GeyserSession session, GeyserItemStack input, GeyserItemStack material) {
return isEnchantedBook(session, material) || (input.getJavaId() == material.getJavaId() && hasDurability(session, input));
private boolean isCombining(GeyserItemStack input, GeyserItemStack material) {
return isEnchantedBook(material) || (input.getJavaId() == material.getJavaId() && hasDurability(input));
}
private boolean isRepairing(GeyserSession session, GeyserItemStack input, GeyserItemStack material) {
Set<String> repairMaterials = input.getMapping(session).getRepairMaterials();
return repairMaterials != null && repairMaterials.contains(material.getMapping(session).getJavaIdentifier());
return repairMaterials != null && repairMaterials.contains(material.asItem().javaIdentifier());
}
private boolean isRenaming(GeyserSession session, AnvilContainer anvilContainer, boolean bedrock) {
@ -450,8 +449,8 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
return getTagIntValueOr(itemStack, "RepairCost", 0);
}
private boolean hasDurability(GeyserSession session, GeyserItemStack itemStack) {
if (itemStack.getMapping(session).getMaxDamage() > 0) {
private boolean hasDurability(GeyserItemStack itemStack) {
if (itemStack.asItem().maxDamage() > 0) {
return getTagIntValueOr(itemStack, "Unbreakable", 0) == 0;
}
return false;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
/*
* 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.item.type;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.inventory.item.TippedArrowPotion;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
public class ArrowItem extends Item {
public ArrowItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) {
TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage());
ItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
if (tippedArrowPotion != null) {
itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getNbt());
StringTag potionTag = new StringTag("Potion", tippedArrowPotion.getJavaIdentifier());
itemStack.getNbt().put(potionTag);
}
return itemStack;
}
}

View file

@ -0,0 +1,35 @@
/*
* 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.item.type;
/**
* TODO needed?
*/
public class BlockItem extends Item {
public BlockItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
}

View file

@ -23,27 +23,23 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.translator.inventory.item;
package org.geysermc.geyser.item.type;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.ByteTag;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ItemRemapper
public class CompassTranslator extends ItemTranslator {
public class CompassItem extends Item {
public CompassItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
@Override
protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
if (isLodestoneCompass(itemStack.getNbt())) {
// NBT will be translated in nbt/LodestoneCompassTranslator if applicable
return super.translateToBedrock(itemStack, mappings.getLodestoneCompass(), mappings);
@ -52,11 +48,11 @@ public class CompassTranslator extends ItemTranslator {
}
@Override
protected ItemMapping getItemMapping(int javaId, CompoundTag nbt, ItemMappings mappings) {
public ItemMapping toBedrockDefinition(CompoundTag nbt, ItemMappings mappings) {
if (isLodestoneCompass(nbt)) {
return mappings.getLodestoneCompass();
}
return super.getItemMapping(javaId, nbt, mappings);
return super.toBedrockDefinition(nbt, mappings);
}
private boolean isLodestoneCompass(CompoundTag nbt) {
@ -76,11 +72,4 @@ public class CompassTranslator extends ItemTranslator {
return super.translateToJava(itemData, mapping, mappings);
}
@Override
public List<ItemMapping> getAppliedItems() {
return Arrays.stream(Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getItems())
.filter(entry -> entry.getJavaIdentifier().endsWith("compass"))
.collect(Collectors.toList());
}
}

View file

@ -0,0 +1,39 @@
/*
* 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.item.type;
public class DyeItem extends Item {
private final int dyeColor;
public DyeItem(String javaIdentifier, int dyeColor, Builder builder) {
super(javaIdentifier, builder);
this.dyeColor = dyeColor;
}
public int dyeColor() {
return dyeColor;
}
}

View file

@ -23,25 +23,22 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.translator.inventory.item;
package org.geysermc.geyser.item.type;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import java.util.Collections;
import java.util.List;
@ItemRemapper
public class FilledMapTranslator extends ItemTranslator {
public class FilledMapItem extends MapItem {
public FilledMapItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
@Override
protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings);
CompoundTag nbt = itemStack.getNbt();
if (nbt != null && nbt.get("display") instanceof CompoundTag display) {
@ -57,12 +54,4 @@ public class FilledMapTranslator extends ItemTranslator {
}
return builder;
}
@Override
public List<ItemMapping> getAppliedItems() {
return Collections.singletonList(
Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
.getMapping("minecraft:filled_map")
);
}
}

View file

@ -23,23 +23,18 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.translator.inventory.item;
package org.geysermc.geyser.item.type;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import java.util.Collections;
import java.util.List;
@ItemRemapper
public class GoatHornTranslator extends ItemTranslator {
public class GoatHornItem extends Item {
private static final List<String> INSTRUMENTS = List.of(
"ponder_goat_horn",
"sing_goat_horn",
@ -51,8 +46,12 @@ public class GoatHornTranslator extends ItemTranslator {
"dream_goat_horn" // Called "Resist" on Bedrock 1.19.0 due to https://bugs.mojang.com/browse/MCPE-155059
);
public GoatHornItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
@Override
protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings);
if (itemStack.getNbt() != null && itemStack.getNbt().get("instrument") instanceof StringTag instrumentTag) {
String instrument = instrumentTag.getValue();
@ -87,12 +86,4 @@ public class GoatHornTranslator extends ItemTranslator {
return itemStack;
}
@Override
public List<ItemMapping> getAppliedItems() {
return Collections.singletonList(
Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
.getMapping("minecraft:goat_horn")
);
}
}

View file

@ -0,0 +1,170 @@
/*
* 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.item.type;
import com.github.steveice10.mc.protocol.data.game.Identifier;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import javax.annotation.Nullable;
import java.util.Set;
public class Item {
private final String javaIdentifier;
private int javaId = -1;
private final int stackSize;
private final String toolType;
private final String toolTier;
private final int maxDamage;
private final Set<String> repairMaterials;
private final boolean hasSuspiciousStewEffect;
public Item(String javaIdentifier, Builder builder) {
this.javaIdentifier = Identifier.formalize(javaIdentifier).intern();
this.stackSize = builder.stackSize;
this.toolType = builder.toolType;
this.toolTier = builder.toolTier;
this.maxDamage = builder.maxDamage;
this.repairMaterials = builder.repairMaterials;
this.hasSuspiciousStewEffect = builder.hasSuspiciousStewEffect;
}
public String javaIdentifier() {
return javaIdentifier;
}
public int javaId() {
return javaId;
}
public int maxDamage() {
return maxDamage;
}
public int maxStackSize() {
return stackSize;
}
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
if (itemStack == null) {
// Return, essentially, air
return ItemData.builder();
}
ItemData.Builder builder = ItemData.builder()
.definition(mapping.getBedrockDefinition())
.damage(mapping.getBedrockData())
.count(itemStack.getAmount());
if (itemStack.getNbt() != null) {
builder.tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt()));
}
CompoundTag nbt = itemStack.getNbt();
ItemTranslator.translateCustomItem(nbt, builder, mapping);
return builder;
}
public ItemStack translateToJava(@Nullable ItemData itemData, ItemMapping mapping, ItemMappings mappings) {
if (itemData == null) return null;
if (itemData.getTag() == null) {
return new ItemStack(javaId, itemData.getCount(), new CompoundTag(""));
}
return new ItemStack(javaId, itemData.getCount(), ItemTranslator.translateToJavaNBT("", itemData.getTag()));
}
public ItemMapping toBedrockDefinition(CompoundTag nbt, ItemMappings mappings) {
return mappings.getMapping(javaId);
}
public ItemStack newItemStack(int count, CompoundTag tag) {
return new ItemStack(this.javaId, count, tag);
}
public void setJavaId(int javaId) { // TODO like this?
if (this.javaId != -1) { // ID has already been set.
throw new RuntimeException();
}
this.javaId = javaId;
}
@Override
public String toString() {
return "Item{" +
"javaIdentifier='" + javaIdentifier + '\'' +
", javaId=" + javaId +
'}';
}
public static Builder builder() {
return new Builder();
}
public static final class Builder {
private int stackSize = 64;
private String toolType;
private String toolTier;
private int maxDamage;
private Set<String> repairMaterials;
private boolean hasSuspiciousStewEffect;
public Builder stackSize(int stackSize) {
this.stackSize = stackSize;
return this;
}
public Builder setToolType(String toolType) {
this.toolType = toolType;
return this;
}
public Builder setToolTier(String toolTier) {
this.toolTier = toolTier;
return this;
}
public Builder maxDamage(int maxDamage) {
this.maxDamage = maxDamage;
return this;
}
public Builder setRepairMaterials(Set<String> repairMaterials) {
this.repairMaterials = repairMaterials;
return this;
}
public Builder setHasSuspiciousStewEffect(boolean hasSuspiciousStewEffect) {
this.hasSuspiciousStewEffect = hasSuspiciousStewEffect;
return this;
}
private Builder() {
}
}
}

View file

@ -0,0 +1,32 @@
/*
* 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.item.type;
public class MapItem extends Item {
public MapItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
}

View file

@ -23,7 +23,7 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.translator.inventory.item;
package org.geysermc.geyser.item.type;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
@ -31,20 +31,17 @@ import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ItemRemapper
public class PotionTranslator extends ItemTranslator {
public class PotionItem extends Item {
public PotionItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
@Override
protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, mapping, mappings);
Tag potionTag = itemStack.getNbt().get("Potion");
if (potionTag instanceof StringTag) {
@ -54,7 +51,7 @@ public class PotionTranslator extends ItemTranslator {
.definition(mapping.getBedrockDefinition())
.damage(potion.getBedrockId())
.count(itemStack.getAmount())
.tag(translateNbtToBedrock(itemStack.getNbt()));
.tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt()));
}
GeyserImpl.getInstance().getLogger().debug("Unknown Java potion: " + potionTag.getValue());
}
@ -71,11 +68,4 @@ public class PotionTranslator extends ItemTranslator {
}
return itemStack;
}
@Override
public List<ItemMapping> getAppliedItems() {
return Arrays.stream(Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getItems())
.filter(entry -> entry.getJavaIdentifier().endsWith("potion"))
.collect(Collectors.toList());
}
}

View file

@ -0,0 +1,32 @@
/*
* 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.item.type;
public class SpawnEggItem extends Item {
public SpawnEggItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
}

View file

@ -0,0 +1,35 @@
/*
* 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.item.type;
/**
* May not represent all tiered items - just the ones we care about. :)
*/
public class TieredItem extends Item {
public TieredItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
}

View file

@ -23,7 +23,7 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.translator.inventory.item;
package org.geysermc.geyser.item.type;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
@ -31,27 +31,17 @@ import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.item.TippedArrowPotion;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ItemRemapper
public class TippedArrowTranslator extends ItemTranslator {
private static final int TIPPED_ARROW_JAVA_ID = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
.getMapping("minecraft:tipped_arrow")
.getJavaId();
public class TippedArrowItem extends ArrowItem {
public TippedArrowItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
@Override
protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
if (!mapping.getJavaIdentifier().equals("minecraft:tipped_arrow") || itemStack.getNbt() == null) {
// We're only concerned about minecraft:arrow when translating Bedrock -> Java
return super.translateToBedrock(itemStack, mapping, mappings);
}
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
Tag potionTag = itemStack.getNbt().get("Potion");
if (potionTag instanceof StringTag) {
TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByJavaIdentifier(((StringTag) potionTag).getValue());
@ -60,30 +50,10 @@ public class TippedArrowTranslator extends ItemTranslator {
.definition(mapping.getBedrockDefinition())
.damage(tippedArrowPotion.getBedrockId())
.count(itemStack.getAmount())
.tag(translateNbtToBedrock(itemStack.getNbt()));
.tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt()));
}
GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionTag.getValue());
}
return super.translateToBedrock(itemStack, mapping, mappings);
}
@Override
public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) {
TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage());
ItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
if (tippedArrowPotion != null) {
itemStack = new ItemStack(TIPPED_ARROW_JAVA_ID, itemStack.getAmount(), itemStack.getNbt());
StringTag potionTag = new StringTag("Potion", tippedArrowPotion.getJavaIdentifier());
itemStack.getNbt().put(potionTag);
}
return itemStack;
}
@Override
public List<ItemMapping> getAppliedItems() {
return Arrays.stream(Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getItems())
.filter(entry -> entry.getJavaIdentifier().contains("arrow")
&& !entry.getJavaIdentifier().contains("spectral"))
.collect(Collectors.toList());
}
}

View file

@ -44,6 +44,7 @@ import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.loader.*;
import org.geysermc.geyser.registry.populator.ItemRegistryPopulator;
import org.geysermc.geyser.registry.populator.PacketRegistryPopulator;
@ -120,6 +121,10 @@ public final class Registries {
*/
public static final PacketTranslatorRegistry<Packet> JAVA_PACKET_TRANSLATORS = PacketTranslatorRegistry.create();
public static final SimpleRegistry<List<Item>> JAVA_ITEMS = SimpleRegistry.create(RegistryLoaders.empty(ArrayList::new));
public static final SimpleMappedRegistry<String, Item> JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
/**
* A versioned registry which holds {@link ItemMappings} for each version. These item mappings contain
* primarily Bedrock version-specific data.

View file

@ -30,10 +30,9 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.EnchantmentData;
import org.geysermc.geyser.registry.type.ItemMapping;
import java.io.InputStream;
import java.util.EnumMap;
@ -77,9 +76,9 @@ public class EnchantmentRegistryLoader implements RegistryLoader<String, Map<Jav
IntSet validItems = new IntOpenHashSet();
for (JsonNode itemNode : node.get("valid_items")) {
String javaIdentifier = itemNode.textValue();
ItemMapping itemMapping = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getMapping(javaIdentifier);
if (itemMapping != null) {
validItems.add(itemMapping.getJavaId());
Item item = Registries.JAVA_ITEM_IDENTIFIERS.get(javaIdentifier);
if (item != null) {
validItems.add(item.javaId());
} else {
throw new NullPointerException("No item entry exists for java identifier: " + javaIdentifier);
}

View file

@ -27,6 +27,8 @@ package org.geysermc.geyser.registry.loader;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.PotionMixData;
import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
@ -51,37 +53,37 @@ public class PotionMixRegistryLoader implements RegistryLoader<Object, Set<Potio
@Override
public Set<PotionMixData> load(Object input) {
List<ItemMapping> ingredients = new ArrayList<>();
ingredients.add(getNonNull("minecraft:nether_wart"));
ingredients.add(getNonNull("minecraft:redstone"));
ingredients.add(getNonNull("minecraft:glowstone_dust"));
ingredients.add(getNonNull("minecraft:fermented_spider_eye"));
ingredients.add(getNonNull("minecraft:gunpowder"));
ingredients.add(getNonNull("minecraft:dragon_breath"));
ingredients.add(getNonNull("minecraft:sugar"));
ingredients.add(getNonNull("minecraft:rabbit_foot"));
ingredients.add(getNonNull("minecraft:glistering_melon_slice"));
ingredients.add(getNonNull("minecraft:spider_eye"));
ingredients.add(getNonNull("minecraft:pufferfish"));
ingredients.add(getNonNull("minecraft:magma_cream"));
ingredients.add(getNonNull("minecraft:golden_carrot"));
ingredients.add(getNonNull("minecraft:blaze_powder"));
ingredients.add(getNonNull("minecraft:ghast_tear"));
ingredients.add(getNonNull("minecraft:turtle_helmet"));
ingredients.add(getNonNull("minecraft:phantom_membrane"));
ingredients.add(getNonNull(Items.NETHER_WART));
ingredients.add(getNonNull(Items.REDSTONE));
ingredients.add(getNonNull(Items.GLOWSTONE_DUST));
ingredients.add(getNonNull(Items.FERMENTED_SPIDER_EYE));
ingredients.add(getNonNull(Items.GUNPOWDER));
ingredients.add(getNonNull(Items.DRAGON_BREATH));
ingredients.add(getNonNull(Items.SUGAR));
ingredients.add(getNonNull(Items.RABBIT_FOOT));
ingredients.add(getNonNull(Items.GLISTERING_MELON_SLICE));
ingredients.add(getNonNull(Items.SPIDER_EYE));
ingredients.add(getNonNull(Items.PUFFERFISH));
ingredients.add(getNonNull(Items.MAGMA_CREAM));
ingredients.add(getNonNull(Items.GOLDEN_CARROT));
ingredients.add(getNonNull(Items.BLAZE_POWDER));
ingredients.add(getNonNull(Items.GHAST_TEAR));
ingredients.add(getNonNull(Items.TURTLE_HELMET));
ingredients.add(getNonNull(Items.PHANTOM_MEMBRANE));
List<ItemMapping> inputs = new ArrayList<>();
inputs.add(getNonNull("minecraft:potion"));
inputs.add(getNonNull("minecraft:splash_potion"));
inputs.add(getNonNull("minecraft:lingering_potion"));
inputs.add(getNonNull(Items.POTION));
inputs.add(getNonNull(Items.SPLASH_POTION));
inputs.add(getNonNull(Items.LINGERING_POTION));
ItemMapping glassBottle = getNonNull("minecraft:glass_bottle");
ItemMapping glassBottle = getNonNull(Items.GLASS_BOTTLE);
Set<PotionMixData> potionMixes = new HashSet<>();
// Add all types of potions as inputs
ItemMapping fillerIngredient = ingredients.get(0);
for (ItemMapping entryInput : inputs) {
for (Potion potion : Potion.values()) {
for (Potion potion : Potion.VALUES) {
potionMixes.add(new PotionMixData(
entryInput.getBedrockDefinition().getRuntimeId(), potion.getBedrockId(),
fillerIngredient.getBedrockDefinition().getRuntimeId(), fillerIngredient.getBedrockData(),
@ -102,10 +104,10 @@ public class PotionMixRegistryLoader implements RegistryLoader<Object, Set<Potio
return potionMixes;
}
private static ItemMapping getNonNull(String javaIdentifier) {
ItemMapping itemMapping = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getMapping(javaIdentifier);
private static ItemMapping getNonNull(Item javaItem) {
ItemMapping itemMapping = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getMapping(javaItem);
if (itemMapping == null)
throw new NullPointerException("No item entry exists for java identifier: " + javaIdentifier);
throw new NullPointerException("No item entry exists for java identifier: " + javaItem.javaIdentifier());
return itemMapping;
}

View file

@ -54,7 +54,7 @@ public class CreativeItemRegistryPopulator {
(identifier, data) -> identifier.equals("minecraft:bordure_indented_banner_pattern") || identifier.equals("minecraft:field_masoned_banner_pattern")
);
public static void populate(Map.Entry<String, ItemRegistryPopulator.PaletteVersion> version, Map<String, ItemDefinition> definitions, Consumer<ItemData.Builder> itemConsumer) {
static void populate(Map.Entry<String, ItemRegistryPopulator.PaletteVersion> version, Map<String, ItemDefinition> definitions, Consumer<ItemData.Builder> itemConsumer) {
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
// Load creative items
@ -79,7 +79,7 @@ public class CreativeItemRegistryPopulator {
private static ItemData.Builder createItemData(JsonNode itemNode, BlockMappings blockMappings, Map<String, ItemDefinition> definitions) {
int count = 1;
int damage = 0;
int bedrockBlockRuntimeId = 0;
int bedrockBlockRuntimeId = -1;
NbtMap tag = null;
JsonNode damageNode = itemNode.get("damage");
if (damageNode != null) {
@ -125,6 +125,6 @@ public class CreativeItemRegistryPopulator {
.damage(damage)
.count(count)
.tag(tag)
.blockDefinition(blockMappings.getDefinition(bedrockBlockRuntimeId));
.blockDefinition(bedrockBlockRuntimeId == -1 ? null : blockMappings.getDefinition(bedrockBlockRuntimeId));
}
}

View file

@ -26,12 +26,12 @@
package org.geysermc.geyser.registry.populator;
import com.google.common.collect.Multimap;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.item.custom.CustomItemData;
@ -40,9 +40,11 @@ import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
import org.geysermc.geyser.api.util.TriState;
import org.geysermc.geyser.event.type.GeyserDefineCustomItemsEventImpl;
import org.geysermc.geyser.item.GeyserCustomMappingData;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.components.ToolBreakSpeedsUtils;
import org.geysermc.geyser.item.components.WearableSlot;
import org.geysermc.geyser.item.mappings.MappingsConfigReader;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.GeyserMappingItem;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.NonVanillaItemRegistration;
@ -100,7 +102,7 @@ public class CustomItemRegistryPopulator {
}
public static GeyserCustomMappingData registerCustomItem(String customItemName, GeyserMappingItem javaItem, CustomItemData customItemData, int bedrockId) {
ItemDefinition itemDefinition = new ItemDefinition(customItemName, bedrockId, true);
ItemDefinition itemDefinition = new SimpleItemDefinition(customItemName, bedrockId, true);
NbtMapBuilder builder = createComponentNbt(customItemData, javaItem, customItemName, bedrockId);
ComponentItemData componentItemData = new ComponentItemData(customItemName, builder.build());
@ -129,28 +131,30 @@ public class CustomItemRegistryPopulator {
public static NonVanillaItemRegistration registerCustomItem(NonVanillaCustomItemData customItemData, int customItemId) {
String customIdentifier = customItemData.identifier();
Item.Builder itemBuilder = Item.builder()
.stackSize(customItemData.stackSize())
.maxDamage(customItemData.maxDamage());
Item item = new Item(customIdentifier, itemBuilder);
Items.register(item, customItemData.javaId());
ItemMapping customItemMapping = ItemMapping.builder()
.javaIdentifier(customIdentifier)
.bedrockIdentifier(customIdentifier)
.javaId(customItemData.javaId())
.bedrockDefinition(new ItemDefinition(customIdentifier, customItemId, true))
.bedrockDefinition(new SimpleItemDefinition(customIdentifier, customItemId, true))
.bedrockData(0)
.bedrockBlockDefinition(null)
.stackSize(customItemData.stackSize())
.toolType(customItemData.toolType())
.toolTier(customItemData.toolTier())
.translationString(customItemData.translationString())
.maxDamage(customItemData.maxDamage())
.repairMaterials(customItemData.repairMaterials())
.hasSuspiciousStewEffect(false)
.customItemOptions(Collections.emptyList())
.javaItem(item)
.build();
NbtMapBuilder builder = createComponentNbt(customItemData, customItemData.identifier(), customItemId,
customItemData.creativeCategory(), customItemData.creativeGroup(), customItemData.isHat(), customItemData.isTool());
ComponentItemData componentItemData = new ComponentItemData(customIdentifier, builder.build());
return new NonVanillaItemRegistration(componentItemData, customItemMapping);
return new NonVanillaItemRegistration(componentItemData, item, customItemMapping);
}
private static NbtMapBuilder createComponentNbt(CustomItemData customItemData, GeyserMappingItem mapping,

View file

@ -29,23 +29,21 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.objects.*;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.*;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544;
import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.common.SimpleDefinitionRegistry;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.item.custom.CustomItemData;
@ -53,11 +51,11 @@ import org.geysermc.geyser.api.item.custom.CustomItemOptions;
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
import org.geysermc.geyser.inventory.item.StoredItemMappings;
import org.geysermc.geyser.item.GeyserCustomMappingData;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.*;
import org.geysermc.geyser.util.ItemUtils;
import org.geysermc.geyser.util.collection.FixedInt2IntMap;
import java.io.InputStream;
import java.util.*;
@ -68,7 +66,7 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public class ItemRegistryPopulator {
record PaletteVersion(int protocolVersion, Map<String, String> additionalTranslatedItems) {
record PaletteVersion(int protocolVersion, Map<Item, String> additionalTranslatedItems) {
}
public static void populate() {
@ -102,16 +100,11 @@ public class ItemRegistryPopulator {
// We can reduce some operations as Java information is the same across all palette versions
boolean firstMappingsPass = true;
Int2IntMap dyeColors = new FixedInt2IntMap();
/* Load item palette */
for (Map.Entry<String, PaletteVersion> palette : paletteVersions.entrySet()) {
TypeReference<List<PaletteItem>> paletteEntriesType = new TypeReference<>() {};
// Used to get the Bedrock namespaced ID (in instances where there are small differences)
List<String> itemNames = new ArrayList<>();
List<PaletteItem> itemEntries;
try (InputStream stream = bootstrap.getResource(String.format("bedrock/runtime_item_states.%s.json", palette.getKey()))) {
itemEntries = GeyserImpl.JSON_MAPPER.readValue(stream, paletteEntriesType);
@ -123,7 +116,7 @@ public class ItemRegistryPopulator {
int nextFreeBedrockId = 0;
List<ComponentItemData> componentItemData = new ObjectArrayList<>();
SimpleDefinitionRegistry.Builder<ItemDefinition> registry = SimpleDefinitionRegistry.builder();
Int2ObjectMap<ItemDefinition> registry = new Int2ObjectOpenHashMap<>();
Map<String, ItemDefinition> definitions = new Object2ObjectLinkedOpenHashMap<>();
for (PaletteItem entry : itemEntries) {
@ -132,9 +125,9 @@ public class ItemRegistryPopulator {
nextFreeBedrockId = id + 1;
}
ItemDefinition definition = new ItemDefinition(entry.getName(), id, false);
ItemDefinition definition = new SimpleItemDefinition(entry.getName().intern(), id, false);
definitions.put(entry.getName(), definition);
registry.add(definition);
registry.put(definition.getRuntimeId(), definition);
}
Object2ObjectMap<String, BlockDefinition> bedrockBlockIdOverrides = new Object2ObjectOpenHashMap<>();
@ -142,12 +135,11 @@ public class ItemRegistryPopulator {
List<ItemDefinition> boats = new ObjectArrayList<>();
List<ItemDefinition> buckets = new ObjectArrayList<>();
List<ItemDefinition> spawnEggs = new ObjectArrayList<>();
List<ItemData> carpets = new ObjectArrayList<>();
List<ItemMapping> mappings = new ObjectArrayList<>();
// Temporary mapping to create stored items
Map<String, ItemMapping> javaIdentifierToMapping = new Object2ObjectOpenHashMap<>();
Map<Item, ItemMapping> javaItemToMapping = new Object2ObjectOpenHashMap<>();
List<ItemData> creativeItems = new ArrayList<>();
@ -175,14 +167,11 @@ public class ItemRegistryPopulator {
BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(palette.getValue().protocolVersion());
int itemIndex = 0;
int javaFurnaceMinecartId = 0;
Set<String> javaOnlyItems = new ObjectOpenHashSet<>();
Collections.addAll(javaOnlyItems, "minecraft:spectral_arrow", "minecraft:debug_stick",
"minecraft:knowledge_book", "minecraft:tipped_arrow", "minecraft:bundle");
Set<Item> javaOnlyItems = new ObjectOpenHashSet<>();
Collections.addAll(javaOnlyItems, Items.SPECTRAL_ARROW, Items.DEBUG_STICK,
Items.KNOWLEDGE_BOOK, Items.TIPPED_ARROW, Items.BUNDLE);
if (!customItemsAllowed) {
javaOnlyItems.add("minecraft:furnace_minecart");
javaOnlyItems.add(Items.FURNACE_MINECART);
}
// Java-only items for this version
javaOnlyItems.addAll(palette.getValue().additionalTranslatedItems().keySet());
@ -191,9 +180,12 @@ public class ItemRegistryPopulator {
Set<String> registeredItemNames = new ObjectOpenHashSet<>(); // This is used to check for duplicate item names
for (Map.Entry<String, GeyserMappingItem> entry : items.entrySet()) {
String javaIdentifier = entry.getKey().intern();
Item javaItem = Registries.JAVA_ITEM_IDENTIFIERS.get(entry.getKey());
if (javaItem == null) {
throw new RuntimeException("Extra item in mappings? " + entry.getKey());
}
GeyserMappingItem mappingItem;
String replacementItem = palette.getValue().additionalTranslatedItems().get(javaIdentifier);
String replacementItem = palette.getValue().additionalTranslatedItems().get(javaItem);
if (replacementItem != null) {
mappingItem = items.get(replacementItem);
} else {
@ -201,9 +193,7 @@ public class ItemRegistryPopulator {
mappingItem = entry.getValue();
}
if (customItemsAllowed && javaIdentifier.equals("minecraft:furnace_minecart")) {
javaFurnaceMinecartId = itemIndex;
itemIndex++;
if (customItemsAllowed && javaItem == Items.FURNACE_MINECART) {
// Will be added later
mappings.add(null);
continue;
@ -215,8 +205,6 @@ public class ItemRegistryPopulator {
throw new RuntimeException("Missing Bedrock ItemDefinition in mappings: " + bedrockIdentifier);
}
int stackSize = mappingItem.getStackSize();
BlockDefinition bedrockBlock = null;
Integer firstBlockRuntimeId = entry.getValue().getFirstBlockRuntimeId();
if (firstBlockRuntimeId != null) {
@ -336,15 +324,12 @@ public class ItemRegistryPopulator {
}
ItemMapping.ItemMappingBuilder mappingBuilder = ItemMapping.builder()
.javaIdentifier(javaIdentifier)
.javaId(itemIndex)
.bedrockIdentifier(bedrockIdentifier.intern())
.bedrockDefinition(definition)
.bedrockData(mappingItem.getBedrockData())
.bedrockBlockDefinition(bedrockBlock)
.stackSize(stackSize)
.maxDamage(mappingItem.getMaxDamage())
.hasSuspiciousStewEffect(mappingItem.isHasSuspiciousStewEffect());
.hasSuspiciousStewEffect(mappingItem.isHasSuspiciousStewEffect())
.javaItem(javaItem);
if (mappingItem.getRepairMaterials() != null) {
mappingBuilder = mappingBuilder.repairMaterials(new ObjectOpenHashSet<>(mappingItem.getRepairMaterials()));
@ -360,7 +345,7 @@ public class ItemRegistryPopulator {
}
}
if (javaOnlyItems.contains(javaIdentifier)) {
if (javaOnlyItems.contains(javaItem)) {
// These items don't exist on Bedrock, so set up a variable that indicates they should have custom names
mappingBuilder = mappingBuilder.translationString((bedrockBlock != null ? "block." : "item.") + entry.getKey().replace(":", "."));
GeyserImpl.getInstance().getLogger().debug("Adding " + entry.getKey() + " as an item that needs to be translated.");
@ -368,7 +353,7 @@ public class ItemRegistryPopulator {
// Add the custom item properties, if applicable
List<Pair<CustomItemOptions, ItemDefinition>> customItemOptions;
Collection<CustomItemData> customItemsToLoad = customItems.get(javaIdentifier);
Collection<CustomItemData> customItemsToLoad = customItems.get(javaItem.javaIdentifier());
if (customItemsAllowed && !customItemsToLoad.isEmpty()) {
customItemOptions = new ObjectArrayList<>(customItemsToLoad.size());
@ -386,9 +371,6 @@ public class ItemRegistryPopulator {
GeyserCustomMappingData customMapping = CustomItemRegistryPopulator.registerCustomItem(
customItemName, mappingItem, customItem, customProtocolId
);
// StartGamePacket entry - needed for Bedrock to recognize the item through the protocol
definitions.put(customMapping.stringId(), customMapping.itemDefinition());
registry.add(customMapping.itemDefinition());
// ComponentItemData - used to register some custom properties
componentItemData.add(customMapping.componentItemData());
customItemOptions.add(Pair.of(customItem.customItemOptions(), customMapping.itemDefinition()));
@ -405,6 +387,7 @@ public class ItemRegistryPopulator {
ItemMapping mapping = mappingBuilder.build();
/*
if (javaIdentifier.contains("boat")) {
boats.add(definition);
} else if (javaIdentifier.contains("bucket") && !javaIdentifier.contains("milk")) {
@ -419,26 +402,15 @@ public class ItemRegistryPopulator {
.build());
} else if (javaIdentifier.startsWith("minecraft:music_disc_")) {
// The Java record level event uses the item ID as the "key" to play the record
Registries.RECORDS.register(itemIndex, SoundEvent.valueOf("RECORD_" +
Registries.RECORDS.register(javaItem.javaId(), SoundEvent.valueOf("RECORD_" +
javaIdentifier.replace("minecraft:music_disc_", "").toUpperCase(Locale.ENGLISH)));
} else if (javaIdentifier.endsWith("_spawn_egg")) {
spawnEggs.add(definition);
}
*/
mappings.add(mapping);
javaIdentifierToMapping.put(javaIdentifier, mapping);
itemNames.add(javaIdentifier);
if (firstMappingsPass && mappingItem.getDyeColor() != -1) {
dyeColors.put(itemIndex, mappingItem.getDyeColor());
}
itemIndex++;
javaItemToMapping.put(javaItem, mapping);
}
itemNames.add("minecraft:furnace_minecart");
ItemDefinition lodestoneCompass = definitions.get("minecraft:lodestone_compass");
if (lodestoneCompass == null) {
throw new RuntimeException("Lodestone compass not found in item palette!");
@ -446,30 +418,26 @@ public class ItemRegistryPopulator {
// Add the lodestone compass since it doesn't exist on java but we need it for item conversion
ItemMapping lodestoneEntry = ItemMapping.builder()
.javaIdentifier("")
.javaItem(Items.COMPASS)
.bedrockIdentifier("minecraft:lodestone_compass")
.javaId(-1)
.bedrockDefinition(lodestoneCompass)
.bedrockData(0)
.bedrockBlockDefinition(null)
.stackSize(1)
.customItemOptions(Collections.emptyList())
.build();
if (customItemsAllowed) {
// Add furnace minecart
ItemDefinition definition = new ItemDefinition("geysermc:furnace_minecart", nextFreeBedrockId, true);
ItemDefinition definition = new SimpleItemDefinition("geysermc:furnace_minecart", nextFreeBedrockId, true);
definitions.put("geysermc:furnace_minecart", definition);
registry.add(definition);
registry.put(definition.getRuntimeId(), definition);
mappings.set(javaFurnaceMinecartId, ItemMapping.builder()
.javaIdentifier("minecraft:furnace_minecart")
mappings.set(Items.FURNACE_MINECART.javaId(), ItemMapping.builder()
.javaItem(Items.FURNACE_MINECART)
.bedrockIdentifier("geysermc:furnace_minecart")
.javaId(javaFurnaceMinecartId)
.bedrockDefinition(definition)
.bedrockData(0)
.bedrockBlockDefinition(null)
.stackSize(1)
.customItemOptions(Collections.emptyList()) // TODO check for custom items with furnace minecart
.build());
@ -496,11 +464,12 @@ public class ItemRegistryPopulator {
componentItemData.add(registration.componentItemData());
ItemMapping mapping = registration.mapping();
while (mapping.getJavaId() >= mappings.size()) {
Item javaItem = registration.javaItem();
while (javaItem.javaId() >= mappings.size()) {
// Fill with empty to get to the correct size
mappings.add(ItemMapping.AIR);
}
mappings.set(mapping.getJavaId(), mapping);
mappings.set(javaItem.javaId(), mapping);
if (customItem.creativeGroup() != null || customItem.creativeCategory().isPresent()) {
creativeItems.add(ItemData.builder()
@ -515,14 +484,11 @@ public class ItemRegistryPopulator {
ItemMappings itemMappings = ItemMappings.builder()
.items(mappings.toArray(new ItemMapping[0]))
.creativeItems(creativeItems.toArray(new ItemData[0]))
.definitionRegistry(registry.build())
.itemDefinitions(List.copyOf(definitions.values()))
.itemNames(itemNames.toArray(new String[0]))
.storedItems(new StoredItemMappings(javaIdentifierToMapping))
.itemDefinitions(registry)
.storedItems(new StoredItemMappings(javaItemToMapping))
.javaOnlyItems(javaOnlyItems)
.buckets(buckets)
.boats(boats)
.spawnEggs(spawnEggs)
.carpets(carpets)
.componentItemData(componentItemData)
.lodestoneCompass(lodestoneEntry)
@ -533,8 +499,6 @@ public class ItemRegistryPopulator {
firstMappingsPass = false;
}
ItemUtils.setDyeColors(dyeColors);
}
private static void registerFurnaceMinecart(int nextFreeBedrockId, List<ComponentItemData> componentItemData) {

View file

@ -0,0 +1,49 @@
/*
* 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.registry.type;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.geysermc.geyser.item.type.Item;
/**
* Implements ItemDefinition while also providing a reference to our item mappings.
*/
public record GeyserItemDefinition(Item javaItem, String identifier, boolean componentBased, int runtimeId) implements ItemDefinition {
@Override
public String getIdentifier() {
return identifier;
}
@Override
public boolean isComponentBased() {
return componentBased;
}
@Override
public int getRuntimeId() {
return runtimeId;
}
}

View file

@ -26,13 +26,13 @@
package org.geysermc.geyser.registry.type;
import it.unimi.dsi.fastutil.Pair;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Value;
import lombok.*;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import java.util.Collections;
import java.util.List;
@ -44,24 +44,19 @@ import java.util.Set;
public class ItemMapping {
public static final ItemMapping AIR = new ItemMapping(
"minecraft:air",
"minecraft:air",
0,
ItemDefinition.AIR,
0,
null, // Air is never sent in full over the network for this to serialize.
64,
null,
null,
null
, Collections.emptyList(),
0,
null,
false
Collections.emptyList(),
null,
false,
Items.AIR
);
String javaIdentifier;
String bedrockIdentifier;
int javaId;
ItemDefinition bedrockDefinition;
int bedrockData;
@ -70,7 +65,6 @@ public class ItemMapping {
* Required since 1.16.220.
*/
BlockDefinition bedrockBlockDefinition;
int stackSize;
String toolType;
String toolTier;
@ -80,12 +74,13 @@ public class ItemMapping {
@NonNull
List<Pair<CustomItemOptions, ItemDefinition>> customItemOptions;
int maxDamage;
Set<String> repairMaterials;
boolean hasSuspiciousStewEffect;
@NonNull
Item javaItem;
/**
* Gets if this item is a block.
*

View file

@ -35,6 +35,9 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.common.DefinitionRegistry;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.item.StoredItemMappings;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.item.type.PotionItem;
import javax.annotation.Nonnull;
import java.util.List;
@ -44,7 +47,7 @@ import java.util.WeakHashMap;
@Builder
@Value
public class ItemMappings {
public class ItemMappings implements DefinitionRegistry<ItemDefinition> {
Map<String, ItemMapping> cachedJavaMappings = new WeakHashMap<>();
@ -56,16 +59,13 @@ public class ItemMappings {
ItemMapping lodestoneCompass;
ItemData[] creativeItems;
List<ItemDefinition> itemDefinitions;
DefinitionRegistry<ItemDefinition> definitionRegistry;
Int2ObjectMap<ItemDefinition> itemDefinitions;
StoredItemMappings storedItems;
String[] itemNames;
Set<String> javaOnlyItems;
Set<Item> javaOnlyItems;
List<ItemDefinition> buckets;
List<ItemDefinition> boats;
List<ItemDefinition> spawnEggs;
List<ItemData> carpets;
List<ComponentItemData> componentItemData;
@ -94,6 +94,10 @@ public class ItemMappings {
return javaId >= 0 && javaId < this.items.length ? this.items[javaId] : ItemMapping.AIR;
}
public ItemMapping getMapping(Item javaItem) {
return getMapping(javaItem.javaIdentifier());
}
/**
* Gets an {@link ItemMapping} from the given Minecraft: Java Edition
* block state identifier.
@ -104,7 +108,7 @@ public class ItemMappings {
public ItemMapping getMapping(String javaIdentifier) {
return this.cachedJavaMappings.computeIfAbsent(javaIdentifier, key -> {
for (ItemMapping mapping : this.items) {
if (mapping.getJavaIdentifier().equals(key)) {
if (mapping.getJavaItem().javaIdentifier().equals(key)) {
return mapping;
}
}
@ -120,10 +124,9 @@ public class ItemMappings {
*/
public ItemMapping getMapping(ItemData data) {
ItemDefinition definition = data.getDefinition();
int id = data.getDefinition().getRuntimeId();
if (ItemDefinition.AIR.equals(definition)) {
return ItemMapping.AIR;
} else if (definition.equals(lodestoneCompass.getBedrockDefinition())) {
} else if (definition.getRuntimeId() == lodestoneCompass.getBedrockDefinition().getRuntimeId()) {
return lodestoneCompass;
}
@ -131,7 +134,7 @@ public class ItemMappings {
boolean hasDamage = data.getDamage() != 0;
for (ItemMapping mapping : this.items) {
if (mapping.getBedrockDefinition().equals(definition)) {
if (mapping.getBedrockDefinition().getRuntimeId() == definition.getRuntimeId()) {
if (isBlock && !hasDamage) { // Pre-1.16.220 will not use block runtime IDs at all, so we shouldn't check either
if (data.getBlockDefinition() != mapping.getBedrockBlockDefinition()) {
continue;
@ -139,22 +142,29 @@ public class ItemMappings {
} else {
if (!(mapping.getBedrockData() == data.getDamage() ||
// Make exceptions for potions, tipped arrows, firework stars, and goat horns, whose damage values can vary
(mapping.getJavaIdentifier().endsWith("potion") || mapping.getJavaIdentifier().equals("minecraft:arrow")
|| mapping.getJavaIdentifier().equals("minecraft:firework_star") || mapping.getJavaIdentifier().equals("minecraft:goat_horn")))) {
(mapping.getJavaItem() instanceof PotionItem || mapping.getJavaItem() == Items.ARROW
|| mapping.getJavaItem() == Items.FIREWORK_STAR || mapping.getJavaItem() == Items.GOAT_HORN))) {
continue;
}
}
if (!this.javaOnlyItems.contains(mapping.getJavaIdentifier())) {
if (!this.javaOnlyItems.contains(mapping.getJavaItem())) {
// From a Bedrock item data, we aren't getting one of these items
return mapping;
}
}
}
// This will hide the message when the player clicks with an empty hand
if (id != 0 && data.getDamage() != 0) {
GeyserImpl.getInstance().getLogger().debug("Missing mapping for bedrock item " + data.getDefinition() + ":" + data.getDamage());
}
GeyserImpl.getInstance().getLogger().debug("Missing mapping for bedrock item " + data);
return ItemMapping.AIR;
}
@Override
public ItemDefinition getDefinition(int bedrockId) {
return this.itemDefinitions.get(bedrockId);
}
@Override
public boolean isRegistered(ItemDefinition definition) {
return getDefinition(definition.getRuntimeId()) == definition;
}
}

View file

@ -26,9 +26,10 @@
package org.geysermc.geyser.registry.type;
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
import org.geysermc.geyser.item.type.Item;
/**
* The return data of a successful registration of a custom item.
*/
public record NonVanillaItemRegistration(ComponentItemData componentItemData, ItemMapping mapping) {
public record NonVanillaItemRegistration(ComponentItemData componentItemData, Item javaItem, ItemMapping mapping) {
}

View file

@ -116,13 +116,13 @@ import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.level.JavaDimension;
import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.level.physics.CollisionManager;
import org.geysermc.geyser.network.netty.LocalSession;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.BlockMappings;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.auth.AuthData;
import org.geysermc.geyser.session.auth.BedrockClientData;
@ -1278,12 +1278,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
* blocking and sends a packet to the Java server.
*/
private boolean attemptToBlock() {
ItemMapping shield = itemMappings.getStoredItems().shield();
ServerboundUseItemPacket useItemPacket;
if (playerInventory.getItemInHand().getJavaId() == shield.getJavaId()) {
if (playerInventory.getItemInHand().asItem() == Items.SHIELD) {
useItemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, worldCache.nextPredictionSequence());
} else if (playerInventory.getOffhand().getJavaId() == shield.getJavaId()) {
} else if (playerInventory.getOffhand().asItem() == Items.SHIELD) {
useItemPacket = new ServerboundUseItemPacket(Hand.OFF_HAND, worldCache.nextPredictionSequence());
} else {
// No blocking
@ -1410,7 +1408,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
}
private void startGame() {
this.upstream.getCodecHelper().setItemDefinitions(this.itemMappings.getDefinitionRegistry());
this.upstream.getCodecHelper().setItemDefinitions(this.itemMappings);
this.upstream.getCodecHelper().setBlockDefinitions((DefinitionRegistry) this.blockMappings); //FIXME
StartGamePacket startGamePacket = new StartGamePacket();
@ -1467,7 +1465,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
startGamePacket.setEnchantmentSeed(0);
startGamePacket.setMultiplayerCorrelationId("");
startGamePacket.setItemDefinitions(this.itemMappings.getItemDefinitions());
startGamePacket.setItemDefinitions(this.itemMappings.getItemDefinitions().values().stream().toList()); // TODO
// startGamePacket.setBlockPalette(this.blockMappings.getBedrockBlockPalette());
startGamePacket.setVanillaVersion("*");

View file

@ -28,6 +28,7 @@ package org.geysermc.geyser.session.cache;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundEditBookPacket;
import lombok.Setter;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
/**
@ -63,7 +64,7 @@ public class BookEditCache {
}
// Don't send the update if the player isn't not holding a book, shouldn't happen if we catch all interactions
GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand();
if (itemStack == null || itemStack.getJavaId() != this.session.getItemMappings().getStoredItems().writableBook().getJavaId()) {
if (itemStack == null || itemStack.asItem() != Items.WRITABLE_BOOK) {
packet = null;
return;
}

View file

@ -30,8 +30,8 @@ import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntLists;
import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import javax.annotation.ParametersAreNonnullByDefault;
@ -129,24 +129,24 @@ public class TagCache {
this.smallFlowers = IntLists.emptyList();
}
public boolean isAxolotlTemptItem(ItemMapping itemMapping) {
return axolotlTemptItems.contains(itemMapping.getJavaId());
public boolean isAxolotlTemptItem(Item item) {
return axolotlTemptItems.contains(item.javaId());
}
public boolean isFish(GeyserItemStack itemStack) {
return fishes.contains(itemStack.getJavaId());
}
public boolean isFlower(ItemMapping mapping) {
return flowers.contains(mapping.getJavaId());
public boolean isFlower(Item item) {
return flowers.contains(item.javaId());
}
public boolean isFoxFood(ItemMapping mapping) {
return foxFood.contains(mapping.getJavaId());
public boolean isFoxFood(Item item) {
return foxFood.contains(item.javaId());
}
public boolean shouldPiglinAdmire(ItemMapping mapping) {
return piglinLoved.contains(mapping.getJavaId());
public boolean shouldPiglinAdmire(Item item) {
return piglinLoved.contains(item.javaId());
}
public boolean isSmallFlower(GeyserItemStack itemStack) {

View file

@ -30,6 +30,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
public class CartographyInventoryTranslator extends AbstractBlockInventoryTranslator {
@ -43,11 +44,11 @@ public class CartographyInventoryTranslator extends AbstractBlockInventoryTransl
if (javaDestinationSlot == 0) {
// Bedrock Edition can use paper or an empty map in slot 0
GeyserItemStack itemStack = javaSourceSlot == -1 ? session.getPlayerInventory().getCursor() : inventory.getItem(javaSourceSlot);
return itemStack.getMapping(session).getJavaIdentifier().equals("minecraft:paper") || itemStack.getMapping(session).getJavaIdentifier().equals("minecraft:map");
return itemStack.asItem() == Items.PAPER || itemStack.asItem() == Items.MAP;
} else if (javaDestinationSlot == 1) {
// Bedrock Edition can use a compass to create locator maps, or use a filled map, in the ADDITIONAL slot
GeyserItemStack itemStack = javaSourceSlot == -1 ? session.getPlayerInventory().getCursor() : inventory.getItem(javaSourceSlot);
return itemStack.getMapping(session).getJavaIdentifier().equals("minecraft:compass") || itemStack.getMapping(session).getJavaIdentifier().equals("minecraft:filled_map");
return itemStack.asItem() == Items.COMPASS || itemStack.asItem() == Items.FILLED_MAP;
}
return false;
}

View file

@ -854,7 +854,7 @@ public abstract class InventoryTranslator {
int slot = it.nextInt();
BedrockContainerSlot bedrockSlot = javaSlotToBedrockContainer(slot);
List<ItemStackResponseSlot> list = containerMap.computeIfAbsent(bedrockSlot.container(), k -> new ArrayList<>());
list.add(makeItemEntry(session, bedrockSlot.slot(), inventory.getItem(slot)));
list.add(makeItemEntry(bedrockSlot.slot(), inventory.getItem(slot)));
}
List<ItemStackResponseContainer> containerEntries = new ArrayList<>();
@ -862,13 +862,13 @@ public abstract class InventoryTranslator {
containerEntries.add(new ItemStackResponseContainer(entry.getKey(), entry.getValue()));
}
ItemStackResponseSlot cursorEntry = makeItemEntry(session, 0, session.getPlayerInventory().getCursor());
ItemStackResponseSlot cursorEntry = makeItemEntry(0, session.getPlayerInventory().getCursor());
containerEntries.add(new ItemStackResponseContainer(ContainerSlotType.CURSOR, Collections.singletonList(cursorEntry)));
return containerEntries;
}
private static ItemStackResponseSlot makeItemEntry(GeyserSession session, int bedrockSlot, GeyserItemStack itemStack) {
private static ItemStackResponseSlot makeItemEntry(int bedrockSlot, GeyserItemStack itemStack) {
ItemStackResponseSlot itemEntry;
if (!itemStack.isEmpty()) {
// As of 1.16.210: Bedrock needs confirmation on what the current item durability is.
@ -877,7 +877,7 @@ public abstract class InventoryTranslator {
if (itemStack.getNbt() != null) {
Tag damage = itemStack.getNbt().get("Damage");
if (damage instanceof IntTag) {
durability = ItemUtils.getCorrectBedrockDurability(session, itemStack.getJavaId(), ((IntTag) damage).getValue());
durability = ItemUtils.getCorrectBedrockDurability(itemStack.asItem(), ((IntTag) damage).getValue());
}
}

View file

@ -46,6 +46,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.SlotType;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
import org.geysermc.geyser.item.type.DyeItem;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.nbt.BannerTranslator;
@ -113,7 +114,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
}
// Reject the item if Bedrock is attempting to put in a dye that is not a dye in Java Edition
return !itemStack.getMapping(session).getJavaIdentifier().endsWith("_dye");
return !(itemStack.asItem() instanceof DyeItem);
}
@Override

View file

@ -48,6 +48,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemS
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.skin.FakeHeadProvider;
import org.geysermc.geyser.text.GeyserLocale;
@ -134,7 +135,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
if (slot == 5) {
// Check for custom skull
if (javaItem.getJavaId() == session.getItemMappings().getStoredItems().playerHead().getJavaId()
if (javaItem.asItem() == Items.PLAYER_HEAD
&& javaItem.getNbt() != null
&& javaItem.getNbt().get("SkullOwner") instanceof CompoundTag profile) {
FakeHeadProvider.setHead(session, session.getPlayerEntity(), profile);

View file

@ -29,7 +29,6 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.objects.ObjectIntPair;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
@ -55,7 +54,7 @@ final class CustomItemTranslator {
}
int customModelData = nbt.get("CustomModelData") instanceof IntTag customModelDataTag ? customModelDataTag.getValue() : 0;
boolean checkDamage = mapping.getMaxDamage() > 0;
boolean checkDamage = mapping.getJavaItem().maxDamage() > 0;
int damage = !checkDamage ? 0 : nbt.get("Damage") instanceof IntTag damageTag ? damageTag.getValue() : 0;
boolean unbreakable = checkDamage && !isDamaged(nbt, damage);

View file

@ -25,55 +25,41 @@
package org.geysermc.geyser.translator.inventory.item;
import com.github.steveice10.mc.protocol.data.game.Identifier;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag;
import com.github.steveice10.opennbt.tag.builtin.ByteTag;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.DoubleTag;
import com.github.steveice10.opennbt.tag.builtin.FloatTag;
import com.github.steveice10.opennbt.tag.builtin.IntArrayTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.LongArrayTag;
import com.github.steveice10.opennbt.tag.builtin.LongTag;
import com.github.steveice10.opennbt.tag.builtin.ShortTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.github.steveice10.opennbt.tag.builtin.*;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.FileUtils;
import javax.annotation.Nonnull;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
public abstract class ItemTranslator {
private static final Int2ObjectMap<ItemTranslator> ITEM_STACK_TRANSLATORS = new Int2ObjectOpenHashMap<>();
public final class ItemTranslator {
private static final List<NbtItemStackTranslator> NBT_TRANSLATORS;
protected ItemTranslator() {
private ItemTranslator() {
}
public static void init() {
@ -92,19 +78,6 @@ public abstract class ItemTranslator {
if (NbtItemStackTranslator.class.isAssignableFrom(clazz)) {
NbtItemStackTranslator nbtItemTranslator = (NbtItemStackTranslator) clazz.getDeclaredConstructor().newInstance();
loadedNbtItemTranslators.put(nbtItemTranslator, priority);
continue;
}
ItemTranslator itemStackTranslator = (ItemTranslator) clazz.getDeclaredConstructor().newInstance();
List<ItemMapping> appliedItems = itemStackTranslator.getAppliedItems();
for (ItemMapping item : appliedItems) {
ItemTranslator registered = ITEM_STACK_TRANSLATORS.get(item.getJavaId());
if (registered != null) {
GeyserImpl.getInstance().getLogger().error("Could not instantiate annotated item translator " +
clazz.getCanonicalName() + ". Item translator " + registered.getClass().getCanonicalName() +
" is already registered for the item " + item.getJavaIdentifier());
continue;
}
ITEM_STACK_TRANSLATORS.put(item.getJavaId(), itemStackTranslator);
}
} catch (InstantiationException | InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
GeyserImpl.getInstance().getLogger().error("Could not instantiate annotated item translator " + clazz.getCanonicalName());
@ -123,20 +96,15 @@ public abstract class ItemTranslator {
return new ItemStack(0);
}
ItemMapping javaItem = mappings.getMapping(data);
ItemMapping bedrockItem = mappings.getMapping(data);
Item javaItem = bedrockItem.getJavaItem();
ItemStack itemStack;
ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.get(javaItem.getJavaId());
if (itemStackTranslator != null) {
itemStack = itemStackTranslator.translateToJava(data, javaItem, mappings);
} else {
itemStack = DEFAULT_TRANSLATOR.translateToJava(data, javaItem, mappings);
}
ItemStack itemStack = javaItem.translateToJava(data, bedrockItem, mappings);
if (itemStack != null && itemStack.getNbt() != null) {
for (NbtItemStackTranslator translator : NBT_TRANSLATORS) {
if (translator.acceptItem(javaItem)) {
translator.translateToJava(itemStack.getNbt(), javaItem);
translator.translateToJava(itemStack.getNbt(), bedrockItem);
}
}
if (itemStack.getNbt().isEmpty()) {
@ -154,7 +122,7 @@ public abstract class ItemTranslator {
session.getGeyser().getLogger().debug("ItemMapping returned air: " + javaId);
return ItemData.builder();
}
return translateToBedrock(session, bedrockItem, count, tag);
return translateToBedrock(session, Registries.JAVA_ITEMS.get().get(javaId), bedrockItem, count, tag);
}
@Nonnull
@ -168,39 +136,39 @@ public abstract class ItemTranslator {
session.getGeyser().getLogger().debug("ItemMapping returned air: " + stack);
return ItemData.AIR;
}
return translateToBedrock(session, bedrockItem, stack.getAmount(), stack.getNbt())
// Java item needs to be loaded separately. The mapping for tipped arrow would
return translateToBedrock(session, Registries.JAVA_ITEMS.get().get(stack.getId()), bedrockItem, stack.getAmount(), stack.getNbt())
.build();
}
@Nonnull
private static ItemData.Builder translateToBedrock(GeyserSession session, ItemMapping mapping, int count, CompoundTag tag) {
private static ItemData.Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, CompoundTag tag) {
CompoundTag nbt = tag != null ? tag.clone() : null;
// This is a fallback for maps with no nbt
if (nbt == null && mapping.getJavaIdentifier().equals("minecraft:filled_map")) {
if (nbt == null && javaItem == Items.FILLED_MAP) {
nbt = new CompoundTag("");
nbt.put(new IntTag("map", 0));
}
if (nbt != null) {
for (NbtItemStackTranslator translator : NBT_TRANSLATORS) {
if (translator.acceptItem(mapping)) {
translator.translateToBedrock(session, nbt, mapping);
if (translator.acceptItem(javaItem)) {
translator.translateToBedrock(session, nbt, bedrockItem);
}
}
}
nbt = translateDisplayProperties(session, nbt, mapping);
nbt = translateDisplayProperties(session, nbt, bedrockItem);
if (session.isAdvancedTooltips()) {
nbt = addAdvancedTooltips(nbt, mapping, session.locale());
nbt = addAdvancedTooltips(nbt, javaItem, session.locale());
}
ItemStack itemStack = new ItemStack(mapping.getJavaId(), count, nbt);
ItemStack itemStack = new ItemStack(javaItem.javaId(), count, nbt);
ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.getOrDefault(mapping.getJavaId(), DEFAULT_TRANSLATOR);
ItemData.Builder builder = itemStackTranslator.translateToBedrock(itemStack, mapping, session.getItemMappings());
if (mapping.isBlock()) {
builder.blockDefinition(mapping.getBedrockBlockDefinition());
ItemData.Builder builder = javaItem.translateToBedrock(itemStack, bedrockItem, session.getItemMappings());
if (bedrockItem.isBlock()) {
builder.blockDefinition(bedrockItem.getBedrockBlockDefinition());
}
if (nbt != null) {
@ -220,7 +188,7 @@ public abstract class ItemTranslator {
return builder;
}
private static CompoundTag addAdvancedTooltips(CompoundTag nbt, ItemMapping mapping, String language) {
private static CompoundTag addAdvancedTooltips(CompoundTag nbt, Item item, String language) {
CompoundTag newNbt = nbt;
if (newNbt == null) {
newNbt = new CompoundTag("nbt");
@ -237,7 +205,7 @@ public abstract class ItemTranslator {
if (listTag == null) {
listTag = new ListTag("Lore");
}
int maxDurability = mapping.getMaxDamage();
int maxDurability = item.maxDamage();
if (maxDurability != 0) {
Tag durabilityTag = newNbt.get("Damage");
@ -256,7 +224,7 @@ public abstract class ItemTranslator {
}
}
listTag.add(new StringTag("", "§r§8" + mapping.getJavaIdentifier()));
listTag.add(new StringTag("", ChatColor.RESET + ChatColor.DARK_GRAY + item.javaIdentifier()));
if (nbt != null) {
Component component = Component.text()
.resetStyle()
@ -283,9 +251,7 @@ public abstract class ItemTranslator {
String[] canModifyBedrock = new String[canModifyJava.size()];
for (int i = 0; i < canModifyBedrock.length; i++) {
// Get the Java identifier of the block that can be placed
String block = ((StringTag) canModifyJava.get(i)).getValue();
// Sometimes this is done but it's still valid
if (!block.startsWith("minecraft:")) block = "minecraft:" + block;
String block = Identifier.formalize(((StringTag) canModifyJava.get(i)).getValue());
// Get the Bedrock identifier of the item and replace it.
// This will unfortunately be limited - for example, beds and banners will be translated weirdly
canModifyBedrock[i] = BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.getOrDefault(block, block).replace("minecraft:", "");
@ -304,9 +270,7 @@ public abstract class ItemTranslator {
return ItemDefinition.AIR;
}
int javaId = itemStack.getJavaId();
ItemMapping mapping = ITEM_STACK_TRANSLATORS.getOrDefault(javaId, DEFAULT_TRANSLATOR)
.getItemMapping(javaId, itemStack.getNbt(), session.getItemMappings());
ItemMapping mapping = itemStack.asItem().toBedrockDefinition(itemStack.getNbt(), session.getItemMappings());
ItemDefinition definition = CustomItemTranslator.getCustomItem(itemStack.getNbt(), mapping);
if (definition == null) {
@ -317,50 +281,7 @@ public abstract class ItemTranslator {
}
}
private static final ItemTranslator DEFAULT_TRANSLATOR = new ItemTranslator() {
@Override
public List<ItemMapping> getAppliedItems() {
return null;
}
};
protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
if (itemStack == null) {
// Return, essentially, air
return ItemData.builder();
}
ItemData.Builder builder = ItemData.builder()
.definition(mapping.getBedrockDefinition())
.damage(mapping.getBedrockData())
.count(itemStack.getAmount());
if (itemStack.getNbt() != null) {
builder.tag(this.translateNbtToBedrock(itemStack.getNbt()));
}
CompoundTag nbt = itemStack.getNbt();
translateCustomItem(nbt, builder, mapping);
return builder;
}
public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) {
if (itemData == null) return null;
if (itemData.getTag() == null) {
return new ItemStack(mapping.getJavaId(), itemData.getCount(), new CompoundTag(""));
}
return new ItemStack(mapping.getJavaId(), itemData.getCount(), this.translateToJavaNBT("", itemData.getTag()));
}
/**
* Used for initialization only and only called once.
*/
public abstract List<ItemMapping> getAppliedItems();
protected ItemMapping getItemMapping(int javaId, CompoundTag nbt, ItemMappings mappings) {
return mappings.getMapping(javaId);
}
protected NbtMap translateNbtToBedrock(CompoundTag tag) {
public static NbtMap translateNbtToBedrock(CompoundTag tag) {
if (!tag.getValue().isEmpty()) {
NbtMapBuilder builder = NbtMap.builder();
for (Tag javaTag : tag.values()) {
@ -375,7 +296,7 @@ public abstract class ItemTranslator {
return NbtMap.EMPTY;
}
private Object translateToBedrockNBT(Tag tag) {
private static Object translateToBedrockNBT(Tag tag) {
if (tag instanceof CompoundTag compoundTag) {
return translateNbtToBedrock(compoundTag);
}
@ -402,7 +323,7 @@ public abstract class ItemTranslator {
return tag.getValue();
}
private CompoundTag translateToJavaNBT(String name, NbtMap tag) {
public static CompoundTag translateToJavaNBT(String name, NbtMap tag) {
CompoundTag javaTag = new CompoundTag(name);
Map<String, Tag> javaValue = javaTag.getValue();
if (tag != null && !tag.isEmpty()) {
@ -419,7 +340,7 @@ public abstract class ItemTranslator {
return javaTag;
}
private Tag translateToJavaNBT(String name, Object object) {
private static Tag translateToJavaNBT(String name, Object object) {
if (object instanceof int[]) {
return new IntArrayTag(name, (int[]) object);
}
@ -529,7 +450,7 @@ public abstract class ItemTranslator {
String translationKey = mapping.getTranslationString();
// Reset formatting since Bedrock defaults to italics
display.put(new StringTag("Name", "§r§" + translationColor + MinecraftLocale.getLocaleString(translationKey, session.locale())));
display.put(new StringTag("Name", ChatColor.RESET + ChatColor.ESCAPE + translationColor + MinecraftLocale.getLocaleString(translationKey, session.locale())));
}
return tag;
@ -538,7 +459,7 @@ public abstract class ItemTranslator {
/**
* Translates the custom model data of an item
*/
private static void translateCustomItem(CompoundTag nbt, ItemData.Builder builder, ItemMapping mapping) {
public static void translateCustomItem(CompoundTag nbt, ItemData.Builder builder, ItemMapping mapping) {
ItemDefinition definition = CustomItemTranslator.getCustomItem(nbt, mapping);
if (definition != null) {
builder.definition(definition);

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.translator.inventory.item;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
@ -53,11 +54,11 @@ public abstract class NbtItemStackTranslator {
/**
* Gets whether this nbt translator takes in this item.
*
* @param mapping Geyser's item mapping
* @param item Geyser's item mapping
* @return if the item should be processed under this class
*/
public boolean acceptItem(ItemMapping mapping) {
public boolean acceptItem(Item item) {
return true;
}
} // TODO
}

View file

@ -28,6 +28,8 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
import com.github.steveice10.opennbt.tag.builtin.ByteTag;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.MinecraftLocale;
@ -49,7 +51,7 @@ public class AxolotlBucketTranslator extends NbtItemStackTranslator {
}
@Override
public boolean acceptItem(ItemMapping mapping) {
return mapping.getJavaIdentifier().equals("minecraft:axolotl_bucket");
public boolean acceptItem(Item item) {
return item == Items.AXOLOTL_BUCKET;
}
}

View file

@ -29,7 +29,7 @@ import com.github.steveice10.opennbt.tag.builtin.*;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
@ -37,7 +37,10 @@ import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
import org.geysermc.geyser.translator.inventory.item.NbtItemStackTranslator;
import javax.annotation.Nonnull;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ItemRemapper
@ -51,7 +54,7 @@ public class BannerTranslator extends NbtItemStackTranslator {
*/
public static final ListTag OMINOUS_BANNER_PATTERN;
private final List<ItemMapping> appliedItems;
private final List<Item> appliedItems;
static {
OMINOUS_BANNER_PATTERN = new ListTag("Patterns");
@ -76,8 +79,8 @@ public class BannerTranslator extends NbtItemStackTranslator {
}
public BannerTranslator() {
appliedItems = Arrays.stream(Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getItems())
.filter(entry -> entry.getJavaIdentifier().endsWith("banner"))
appliedItems = Registries.JAVA_ITEMS.get().stream()
.filter(entry -> entry.javaIdentifier().endsWith("banner"))
.collect(Collectors.toList());
}
@ -171,7 +174,7 @@ public class BannerTranslator extends NbtItemStackTranslator {
}
@Override
public boolean acceptItem(ItemMapping mapping) {
return appliedItems.contains(mapping);
public boolean acceptItem(Item item) {
return appliedItems.contains(item);
}
}

View file

@ -44,7 +44,7 @@ public class BasicItemTranslator extends NbtItemStackTranslator {
Tag damage = itemTag.get("Damage");
if (damage instanceof IntTag) {
int originalDurability = ((IntTag) damage).getValue();
int durability = ItemUtils.getCorrectBedrockDurability(session, mapping.getJavaId(), originalDurability);
int durability = ItemUtils.getCorrectBedrockDurability(mapping.getJavaItem(), originalDurability);
if (durability != originalDurability) {
// Fix damage tag inconsistencies
itemTag.put(new IntTag("Damage", durability));

View file

@ -28,6 +28,8 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.*;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@ -47,7 +49,7 @@ public class CrossbowTranslator extends NbtItemStackTranslator {
ItemMapping projectileMapping = session.getItemMappings().getMapping((String) projectile.get("id").getValue());
if (projectileMapping == null) return;
CompoundTag tag = projectile.get("tag");
ItemStack itemStack = new ItemStack(mapping.getJavaId(), (byte) projectile.get("Count").getValue(), tag);
ItemStack itemStack = new ItemStack(mapping.getJavaItem().javaId(), (byte) projectile.get("Count").getValue(), tag);
ItemData itemData = ItemTranslator.translateToBedrock(session, itemStack);
CompoundTag newProjectile = new CompoundTag("chargedItem");
@ -78,7 +80,7 @@ public class CrossbowTranslator extends NbtItemStackTranslator {
}
@Override
public boolean acceptItem(ItemMapping mapping) {
return "minecraft:crossbow".equals(mapping.getJavaIdentifier());
public boolean acceptItem(Item item) {
return item == Items.CROSSBOW;
}
}

View file

@ -28,6 +28,8 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
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.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@ -63,7 +65,7 @@ public class EnchantedBookTranslator extends NbtItemStackTranslator {
}
@Override
public boolean acceptItem(ItemMapping mapping) {
return "minecraft:enchanted_book".equals(mapping.getJavaIdentifier());
public boolean acceptItem(Item item) {
return item == Items.ENCHANTED_BOOK;
}
}

View file

@ -29,6 +29,8 @@ import com.github.steveice10.opennbt.tag.builtin.ByteTag;
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.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@ -86,7 +88,7 @@ public class FireworkRocketTranslator extends FireworkBaseTranslator {
}
@Override
public boolean acceptItem(ItemMapping mapping) {
return "minecraft:firework_rocket".equals(mapping.getJavaIdentifier());
public boolean acceptItem(Item item) {
return item == Items.FIREWORK_ROCKET;
}
}

View file

@ -29,6 +29,8 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntArrayTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@ -90,7 +92,7 @@ public class FireworkStarTranslator extends FireworkBaseTranslator {
}
@Override
public boolean acceptItem(ItemMapping mapping) {
return "minecraft:firework_star".equals(mapping.getJavaIdentifier());
public boolean acceptItem(Item item) {
return item == Items.FIREWORK_STAR;
}
}

View file

@ -27,6 +27,8 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@ -37,8 +39,8 @@ import java.util.List;
@ItemRemapper
public class LeatherArmorTranslator extends NbtItemStackTranslator {
private static final List<String> ITEMS = List.of("minecraft:leather_helmet", "minecraft:leather_chestplate",
"minecraft:leather_leggings", "minecraft:leather_boots", "minecraft:leather_horse_armor");
private static final List<Item> ITEMS = List.of(Items.LEATHER_HELMET, Items.LEATHER_CHESTPLATE,
Items.LEATHER_LEGGINGS, Items.LEATHER_BOOTS, Items.LEATHER_HORSE_ARMOR);
@Override
public void translateToBedrock(GeyserSession session, CompoundTag itemTag, ItemMapping mapping) {
@ -67,7 +69,7 @@ public class LeatherArmorTranslator extends NbtItemStackTranslator {
}
@Override
public boolean acceptItem(ItemMapping mapping) {
return ITEMS.contains(mapping.getJavaIdentifier());
public boolean acceptItem(Item item) {
return ITEMS.contains(item);
}
}

View file

@ -29,6 +29,8 @@ import com.github.steveice10.opennbt.tag.builtin.ByteTag;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@ -52,7 +54,7 @@ public class LodestoneCompassTranslator extends NbtItemStackTranslator {
// Lodestone compasses cannot be touched in any of those places.
@Override
public boolean acceptItem(ItemMapping mapping) {
return mapping.getJavaIdentifier().equals("minecraft:compass");
public boolean acceptItem(Item item) {
return item == Items.COMPASS;
}
}

View file

@ -26,6 +26,8 @@
package org.geysermc.geyser.translator.inventory.item.nbt;
import com.github.steveice10.opennbt.tag.builtin.*;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@ -65,7 +67,7 @@ public class MapItemTranslator extends NbtItemStackTranslator {
}
@Override
public boolean acceptItem(ItemMapping mapping) {
return mapping.getJavaIdentifier().equals("minecraft:filled_map");
public boolean acceptItem(Item item) {
return item == Items.FILLED_MAP;
}
}

View file

@ -28,8 +28,11 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
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.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
import org.geysermc.geyser.translator.inventory.item.NbtItemStackTranslator;
@ -56,7 +59,7 @@ public class PlayerHeadTranslator extends NbtItemStackTranslator {
}
// Add correct name of player skull
// TODO: It's always yellow, even with a custom name. Handle?
String displayName = "\u00a7r\u00a7e" + MinecraftLocale.getLocaleString("block.minecraft.player_head.named", session.locale()).replace("%s", name.getValue());
String displayName = ChatColor.RESET + ChatColor.YELLOW + MinecraftLocale.getLocaleString("block.minecraft.player_head.named", session.locale()).replace("%s", name.getValue());
if (!itemTag.contains("display")) {
itemTag.put(new CompoundTag("display"));
}
@ -66,7 +69,7 @@ public class PlayerHeadTranslator extends NbtItemStackTranslator {
}
@Override
public boolean acceptItem(ItemMapping mapping) {
return mapping.getJavaIdentifier().equals("minecraft:player_head");
public boolean acceptItem(Item item) {
return item == Items.PLAYER_HEAD;
}
}

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
import com.github.steveice10.mc.protocol.data.game.Identifier;
import com.github.steveice10.opennbt.tag.builtin.*;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@ -80,7 +81,7 @@ public class ShulkerBoxItemTranslator extends NbtItemStackTranslator {
}
@Override
public boolean acceptItem(ItemMapping mapping) {
return mapping.getJavaIdentifier().contains("shulker_box");
public boolean acceptItem(Item item) {
return item.javaIdentifier().contains("shulker_box");
}
}

View file

@ -31,6 +31,8 @@ import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextDecoration;
import org.geysermc.geyser.entity.type.living.animal.TropicalFishEntity;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.MinecraftLocale;
@ -90,7 +92,7 @@ public class TropicalFishBucketTranslator extends NbtItemStackTranslator {
}
@Override
public boolean acceptItem(ItemMapping mapping) {
return mapping.getJavaIdentifier().equals("minecraft:tropical_fish_bucket");
public boolean acceptItem(Item item) {
return item == Items.TROPICAL_FISH_BUCKET;
}
}

View file

@ -63,6 +63,8 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.click.Click;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.SpawnEggItem;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.ItemMapping;
@ -259,7 +261,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
Block place checks end - client is good to go
*/
if (packet.getItemInHand() != null && session.getItemMappings().getSpawnEggs().contains(packet.getItemInHand().getDefinition())) {
if (packet.getItemInHand() != null && session.getItemMappings().getMapping(packet.getItemInHand()).getJavaItem() instanceof SpawnEggItem) {
int blockState = session.getGeyser().getWorldManager().getBlockAt(session, packet.getBlockPosition());
if (blockState == BlockStateValues.JAVA_WATER_ID) {
// Otherwise causes multiple mobs to spawn - just send a use item packet
@ -321,7 +323,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
ItemMapping handItem = session.getPlayerInventory().getItemInHand().getMapping(session);
if (handItem.isBlock()) {
session.setLastBlockPlacePosition(blockPos);
session.setLastBlockPlacedId(handItem.getJavaIdentifier());
session.setLastBlockPlacedId(handItem.getJavaItem().javaIdentifier());
}
session.setInteracting(true);
}
@ -332,7 +334,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
}
// Handled when sneaking
if (session.getPlayerInventory().getItemInHand().getJavaId() == mappings.getStoredItems().shield().getJavaId()) {
if (session.getPlayerInventory().getItemInHand().asItem() == Items.SHIELD) {
break;
}
@ -342,7 +344,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
packet.getItemInHand().getDefinition() != session.getItemMappings().getStoredItems().milkBucket().getBedrockDefinition()) {
// Handled in case 0 if the item is not milk
break;
} else if (session.getItemMappings().getSpawnEggs().contains(packet.getItemInHand().getDefinition())) {
} else if (session.getItemMappings().getMapping(packet.getItemInHand()).getJavaItem() instanceof SpawnEggItem) {
// Handled in case 0
break;
} else if (packet.getItemInHand().getDefinition() == session.getItemMappings().getStoredItems().glassBottle().getBedrockDefinition()) {

View file

@ -31,6 +31,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.Server
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
@ -61,7 +62,7 @@ public class BedrockMobEquipmentTranslator extends PacketTranslator<MobEquipment
GeyserItemStack newItem = session.getPlayerInventory().getItemInHand();
if (session.isSneaking() && newItem.getJavaId() == session.getItemMappings().getStoredItems().shield().getJavaId()) {
if (session.isSneaking() && newItem.asItem() == Items.SHIELD) {
// Activate shield since we are already sneaking
// (No need to send a release item packet - Java doesn't do this when swapping items)
// Required to do it a tick later or else it doesn't register

View file

@ -37,6 +37,7 @@ import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
import org.cloudburstmc.protocol.bedrock.packet.InteractPacket;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.living.animal.horse.AbstractHorseEntity;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
@ -58,7 +59,7 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
switch (packet.getAction()) {
case INTERACT:
if (session.getPlayerInventory().getItemInHand().getJavaId() == session.getItemMappings().getStoredItems().shield().getJavaId()) {
if (session.getPlayerInventory().getItemInHand().asItem() == Items.SHIELD) {
break;
}
ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(entity.getEntityId(),

View file

@ -241,7 +241,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
case BOOL -> ENUM_BOOLEAN;
case OPERATION -> CommandParam.OPERATOR; // ">=", "==", etc
case BLOCK_STATE -> context.getBlockStates();
case ITEM_STACK -> context.session.getItemMappings().getItemNames();
case ITEM_STACK -> context.getItemNames();
case COLOR -> VALID_COLORS;
case SCOREBOARD_SLOT -> VALID_SCOREBOARD_SLOTS;
case RESOURCE -> handleResource(context, ((ResourceProperties) node.getProperties()).getRegistryKey(), false);
@ -278,6 +278,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
private Object biomesNoTags;
private String[] blockStates;
private String[] entityTypes;
private String[] itemNames;
CommandBuilderContext(GeyserSession session) {
this.session = session;
@ -314,6 +315,13 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
}
return (entityTypes = Registries.JAVA_ENTITY_IDENTIFIERS.get().keySet().toArray(new String[0]));
}
public String[] getItemNames() {
if (itemNames != null) {
return itemNames;
}
return (itemNames = Registries.JAVA_ITEM_IDENTIFIERS.get().keySet().toArray(new String[0]));
}
}
@Getter

View file

@ -168,8 +168,8 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
// Sort the list by each output item's Java identifier - this is how it's sorted on Java, and therefore
// We can get the correct order for button pressing
data.getValue().sort(Comparator.comparing((stoneCuttingRecipeData ->
session.getItemMappings().getMapping(stoneCuttingRecipeData.getResult())
.getJavaIdentifier())));
Registries.JAVA_ITEMS.get().get(stoneCuttingRecipeData.getResult().getId())
.javaIdentifier())));
// Now that it's sorted, let's translate these recipes
int buttonId = 0;

View file

@ -33,6 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.entity.type.Entity;
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.skin.FakeHeadProvider;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
@ -64,7 +65,7 @@ public class JavaSetEquipmentTranslator extends PacketTranslator<ClientboundSetE
ItemStack javaItem = equipment.getItem();
if (livingEntity instanceof PlayerEntity
&& javaItem != null
&& javaItem.getId() == session.getItemMappings().getStoredItems().playerHead().getJavaId()
&& javaItem.getId() == Items.PLAYER_HEAD.javaId()
&& javaItem.getNbt() != null
&& javaItem.getNbt().get("SkullOwner") instanceof CompoundTag profile) {
FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, profile);

View file

@ -38,6 +38,7 @@ import org.cloudburstmc.protocol.bedrock.packet.UpdateTradePacket;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.MerchantContainer;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
@ -163,7 +164,7 @@ public class JavaMerchantOffersTranslator extends PacketTranslator<ClientboundMe
// Bedrock expects all price adjustments to be applied to the item's count
int count = stack.getAmount() + ((int) Math.max(Math.floor(stack.getAmount() * demand * priceMultiplier), 0)) + specialPrice;
count = MathUtils.constrain(count, 1, mapping.getStackSize());
count = MathUtils.constrain(count, 1, Registries.JAVA_ITEMS.get().get(stack.getId()).maxStackSize());
return getItemTag(session, stack, mapping, count);
}

View file

@ -27,7 +27,9 @@ package org.geysermc.geyser.translator.protocol.java.level;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCooldownPacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerStartItemCooldownPacket;
import org.geysermc.geyser.inventory.item.StoredItemMappings;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
@ -37,15 +39,13 @@ public class JavaCooldownTranslator extends PacketTranslator<ClientboundCooldown
@Override
public void translate(GeyserSession session, ClientboundCooldownPacket packet) {
StoredItemMappings itemMappings = session.getItemMappings().getStoredItems();
int itemId = packet.getItemId();
Item item = Registries.JAVA_ITEMS.get().get(packet.getItemId());
// Not every item, as of 1.19, appears to be server-driven. Just these two.
// Use a map here if it gets too big.
String cooldownCategory;
if (itemId == itemMappings.goatHorn().getJavaId()) {
if (item == Items.GOAT_HORN) {
cooldownCategory = "goat_horn";
} else if (itemId == itemMappings.shield().getJavaId()) {
} else if (item == Items.SHIELD) {
cooldownCategory = "shield";
} else {
cooldownCategory = null;

View file

@ -75,7 +75,7 @@ public interface BlockSoundInteractionTranslator extends SoundInteractionTransla
continue;
}
if (handIdentifier == null) {
handIdentifier = itemInHand.getMapping(session).getJavaIdentifier();
handIdentifier = itemInHand.asItem().javaIdentifier();
}
boolean contains = false;
for (String itemIdentifier : interactionEntry.getKey().items()) {

View file

@ -42,7 +42,7 @@ public class BucketSoundInteractionTranslator implements BlockSoundInteractionTr
return; // No bucket was really interacted with
}
GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand();
String handItemIdentifier = itemStack.getMapping(session).getJavaIdentifier();
String handItemIdentifier = itemStack.asItem().javaIdentifier();
if (!BlockSoundInteractionTranslator.canInteract(session, itemStack, identifier)) {
return;
}

View file

@ -37,6 +37,7 @@ import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.living.ArmorStandEntity;
import org.geysermc.geyser.entity.type.living.animal.AnimalEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import java.util.Locale;
@ -217,14 +218,14 @@ public final class EntityUtils {
* Determine if an action would result in a successful bucketing of the given entity.
*/
public static boolean attemptToBucket(GeyserSession session, GeyserItemStack itemInHand) {
return itemInHand.getJavaId() == session.getItemMappings().getStoredItems().waterBucket().getJavaId();
return itemInHand.asItem() == Items.WATER_BUCKET;
}
/**
* Attempt to determine the result of saddling the given entity.
*/
public static InteractionResult attemptToSaddle(GeyserSession session, Entity entityToSaddle, GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().saddle().getJavaId()) {
public static InteractionResult attemptToSaddle(Entity entityToSaddle, GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.SADDLE) {
if (!entityToSaddle.getFlag(EntityFlag.SADDLED) && !entityToSaddle.getFlag(EntityFlag.BABY)) {
// Saddle
return InteractionResult.SUCCESS;

View file

@ -49,6 +49,7 @@ import org.geysermc.geyser.inventory.click.Click;
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe;
import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
@ -178,7 +179,7 @@ public class InventoryUtils {
* Checks to see if an item stack represents air or has no count.
*/
public static boolean isEmpty(@Nullable ItemStack itemStack) {
return itemStack == null || itemStack.getId() == ItemMapping.AIR.getJavaId() || itemStack.getAmount() <= 0;
return itemStack == null || itemStack.getId() == Items.AIR.javaId() || itemStack.getAmount() <= 0;
}
/**
@ -294,7 +295,7 @@ public class InventoryUtils {
continue;
}
// If this isn't the item we're looking for
if (!geyserItem.getMapping(session).getJavaIdentifier().equals(itemName)) {
if (!geyserItem.asItem().javaIdentifier().equals(itemName)) {
continue;
}
@ -310,7 +311,7 @@ public class InventoryUtils {
continue;
}
// If this isn't the item we're looking for
if (!geyserItem.getMapping(session).getJavaIdentifier().equals(itemName)) {
if (!geyserItem.asItem().javaIdentifier().equals(itemName)) {
continue;
}
@ -323,10 +324,10 @@ public class InventoryUtils {
if (session.getGameMode() == GameMode.CREATIVE) {
int slot = findEmptyHotbarSlot(inventory);
ItemMapping mapping = session.getItemMappings().getMapping(itemName);
ItemMapping mapping = session.getItemMappings().getMapping(itemName); // TODO
if (mapping != null) {
ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket(slot,
new ItemStack(mapping.getJavaId()));
new ItemStack(mapping.getJavaItem().javaId()));
if ((slot - 36) != inventory.getHeldItemSlot()) {
setHotbarItem(session, slot);
}

Some files were not shown because too many files have changed in this diff Show more