diff --git a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts index 09440ac6a..93b4d8c13 100644 --- a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts @@ -70,4 +70,5 @@ repositories { content { includeGroupByRegex("com\\.github\\..*") } } + mavenLocal() } diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index 757c126b9..baf6a9990 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -473,8 +473,9 @@ public final class EntityDefinitions { .heightAndWidth(0.25f) .identifier("minecraft:xp_bottle") .build(); + // TODO 1.21.5 lingering potion POTION = EntityDefinition.inherited(ThrownPotionEntity::new, throwableItemBase) - .type(EntityType.POTION) + .type(EntityType.SPLASH_POTION) .heightAndWidth(0.25f) .identifier("minecraft:splash_potion") .build(); @@ -960,6 +961,7 @@ public final class EntityDefinitions { .type(EntityType.CHICKEN) .height(0.7f).width(0.4f) .properties(VanillaEntityProperties.CLIMATE_VARIANT) + .addTranslator(MetadataTypes.CHICKEN_VARIANT, ChickenEntity::setVariant) .build(); COW = EntityDefinition.inherited(CowEntity::new, ageableEntityBase) .type(EntityType.COW) @@ -1016,8 +1018,8 @@ public final class EntityDefinitions { .type(EntityType.PIG) .heightAndWidth(0.9f) .properties(VanillaEntityProperties.CLIMATE_VARIANT) - .addTranslator(MetadataTypes.BOOLEAN, (pigEntity, entityMetadata) -> pigEntity.setFlag(EntityFlag.SADDLED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue())) .addTranslator(MetadataTypes.INT, PigEntity::setBoost) + .addTranslator(MetadataTypes.PIG_VARIANT, PigEntity::setVariant) .build(); POLAR_BEAR = EntityDefinition.inherited(PolarBearEntity::new, ageableEntityBase) .type(EntityType.POLAR_BEAR) @@ -1045,7 +1047,6 @@ public final class EntityDefinitions { .height(1.7f).width(0.9f) .addTranslator(MetadataTypes.INT, StriderEntity::setBoost) .addTranslator(MetadataTypes.BOOLEAN, StriderEntity::setCold) - .addTranslator(MetadataTypes.BOOLEAN, StriderEntity::setSaddled) .build(); TURTLE = EntityDefinition.inherited(TurtleEntity::new, ageableEntityBase) .type(EntityType.TURTLE) @@ -1144,7 +1145,7 @@ public final class EntityDefinitions { EntityDefinition tameableEntityBase = EntityDefinition.inherited(null, ageableEntityBase) // No factory, is abstract .addTranslator(MetadataTypes.BYTE, TameableEntity::setTameableFlags) - .addTranslator(MetadataTypes.OPTIONAL_UUID, TameableEntity::setOwner) + .addTranslator(MetadataTypes.OPTIONAL_LIVING_ENTITY_REFERENCE, TameableEntity::setOwner) .build(); CAT = EntityDefinition.inherited(CatEntity::new, tameableEntityBase) .type(EntityType.CAT) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java index 165495506..546f66700 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java @@ -35,7 +35,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.MathUtils; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; -import org.geysermc.mcprotocollib.protocol.data.game.level.particle.EntityEffectParticleData; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ColorParticleData; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle; import java.util.UUID; @@ -72,7 +72,7 @@ public class AreaEffectCloudEntity extends Entity { Registries.PARTICLES.map(particle.getType(), p -> p.levelEventType() instanceof ParticleType particleType ? particleType : null).ifPresent(type -> dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_PARTICLE, type)); - if (particle.getData() instanceof EntityEffectParticleData effectParticleData) { + if (particle.getData() instanceof ColorParticleData effectParticleData) { dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, effectParticleData.getColor()); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index 8c1ab80f0..70ef2300e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -62,7 +62,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.Object import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentTypes; -import org.geysermc.mcprotocollib.protocol.data.game.level.particle.EntityEffectParticleData; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ColorParticleData; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType; @@ -80,6 +80,7 @@ public class LivingEntity extends Entity { protected ItemData leggings = ItemData.AIR; protected ItemData boots = ItemData.AIR; protected ItemData body = ItemData.AIR; + protected ItemData saddle = ItemData.AIR; protected ItemData hand = ItemData.AIR; protected ItemData offhand = ItemData.AIR; @@ -118,10 +119,6 @@ public class LivingEntity extends Entity { this.chestplate = ItemTranslator.translateToBedrock(session, stack); } - public void setBody(ItemStack stack) { - this.body = ItemTranslator.translateToBedrock(session, stack); - } - public void setLeggings(ItemStack stack) { this.leggings = ItemTranslator.translateToBedrock(session, stack); } @@ -130,6 +127,15 @@ public class LivingEntity extends Entity { this.boots = ItemTranslator.translateToBedrock(session, stack); } + public void setBody(ItemStack stack) { + this.body = ItemTranslator.translateToBedrock(session, stack); + } + + public void setSaddle(ItemStack stack) { + this.saddle = ItemTranslator.translateToBedrock(session, stack); + updateSaddled(stack.getId() == Items.SADDLE.javaId()); + } + public void setHand(ItemStack stack) { this.hand = ItemTranslator.translateToBedrock(session, stack); } @@ -138,6 +144,18 @@ public class LivingEntity extends Entity { this.offhand = ItemTranslator.translateToBedrock(session, stack); } + protected void updateSaddled(boolean saddled) { + setFlag(EntityFlag.SADDLED, saddled); + updateBedrockMetadata(); + + // Update the interactive tag, if necessary + // TODO 1.21.5 retest + Entity mouseoverEntity = session.getMouseoverEntity(); + if (mouseoverEntity != null && mouseoverEntity.getEntityId() == entityId) { + mouseoverEntity.updateInteractiveTag(); + } + } + public void switchHands() { ItemData offhand = this.offhand; this.offhand = this.hand; @@ -202,7 +220,7 @@ public class LivingEntity extends Entity { continue; } - int color = ((EntityEffectParticleData) particle.getData()).getColor(); + int color = ((ColorParticleData) particle.getData()).getColor(); r += ((color >> 16) & 0xFF) / 255f; g += ((color >> 8) & 0xFF) / 255f; b += ((color) & 0xFF) / 255f; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java index 25bbdbd3c..85abc1c40 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java @@ -120,7 +120,7 @@ public class ThrowableEntity extends Entity implements Tickable { protected float getGravity() { if (getFlag(EntityFlag.HAS_GRAVITY)) { switch (definition.entityType()) { - case POTION: + case LINGERING_POTION, SPLASH_POTION: return 0.05f; case EXPERIENCE_BOTTLE: return 0.07f; @@ -146,7 +146,7 @@ public class ThrowableEntity extends Entity implements Tickable { return 0.8f; } else { switch (definition.entityType()) { - case POTION: + case LINGERING_POTION, SPLASH_POTION: case EXPERIENCE_BOTTLE: case SNOWBALL: case EGG: diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java index d4227cfd9..fb7ef3357 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java @@ -48,6 +48,10 @@ import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.Holder; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.PigVariant; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; @@ -155,4 +159,8 @@ public class PigEntity extends AnimalEntity implements Tickable, ClientVehicle { public boolean isClientControlled() { return getPlayerPassenger() == session.getPlayerEntity() && session.getPlayerInventory().isHolding(Items.CARROT_ON_A_STICK); } + + public void setVariant(EntityMetadata,? extends MetadataType>> holderEntityMetadata) { + // TODO + } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java index 62318e255..236b22c51 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java @@ -69,10 +69,6 @@ public class StriderEntity extends AnimalEntity implements Tickable, ClientVehic isCold = entityMetadata.getPrimitiveValue(); } - public void setSaddled(BooleanEntityMetadata entityMetadata) { - setFlag(EntityFlag.SADDLED, entityMetadata.getPrimitiveValue()); - } - @Override public void updateBedrockMetadata() { // Make sure they are not shaking when riding another entity diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java index 100a29299..80995be1c 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java @@ -79,12 +79,19 @@ public class AbstractHorseEntity extends AnimalEntity { session.sendUpstreamPacket(attributesPacket); } + @Override + public void updateSaddled(boolean saddled) { + // Shows the jump meter + setFlag(EntityFlag.CAN_POWER_JUMP, saddled); + super.updateSaddled(saddled); + } + + // TODO 1.21.5 saddled flag doesnt exist anymore public void setHorseFlags(ByteEntityMetadata entityMetadata) { byte xd = entityMetadata.getPrimitiveValue(); boolean tamed = (xd & 0x02) == 0x02; boolean saddled = (xd & 0x04) == 0x04; setFlag(EntityFlag.TAMED, tamed); - setFlag(EntityFlag.SADDLED, saddled); setFlag(EntityFlag.EATING, (xd & 0x10) == 0x10); setFlag(EntityFlag.STANDING, (xd & 0x20) == 0x20); @@ -114,9 +121,6 @@ public class AbstractHorseEntity extends AnimalEntity { // Set container type if tamed dirtyMetadata.put(EntityDataTypes.CONTAINER_TYPE, tamed ? (byte) ContainerType.HORSE.getId() : (byte) 0); - - // Shows the jump meter - setFlag(EntityFlag.CAN_POWER_JUMP, saddled); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java index 0bfa6d1a7..631b73936 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java @@ -34,11 +34,13 @@ import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import org.geysermc.mcprotocollib.protocol.data.game.inventory.VillagerTrade; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundMerchantOffersPacket; +import java.util.List; + public class MerchantContainer extends Container { @Getter @Setter private Entity villager; @Setter - private VillagerTrade[] villagerTrades; + private List villagerTrades; @Getter @Setter private ClientboundMerchantOffersPacket pendingOffersPacket; @Getter @Setter @@ -49,9 +51,9 @@ public class MerchantContainer extends Container { } public void onTradeSelected(GeyserSession session, int slot) { - if (villagerTrades != null && slot >= 0 && slot < villagerTrades.length) { - VillagerTrade trade = villagerTrades[slot]; - setItem(2, GeyserItemStack.from(trade.getOutput()), session); + if (villagerTrades != null && slot >= 0 && slot < villagerTrades.size()) { + VillagerTrade trade = villagerTrades.get(slot); + setItem(2, GeyserItemStack.from(trade.getResult()), session); tradeExperience += trade.getXp(); villager.getDirtyMetadata().put(EntityDataTypes.TRADE_EXPERIENCE, tradeExperience); diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/GeyserInstrument.java b/core/src/main/java/org/geysermc/geyser/inventory/item/GeyserInstrument.java index 9983a8e90..38d4f2cd5 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/GeyserInstrument.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/GeyserInstrument.java @@ -34,8 +34,7 @@ import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.geyser.util.SoundUtils; -import org.geysermc.mcprotocollib.protocol.data.game.Holder; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.Instrument; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.InstrumentComponent; import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound; import java.util.Locale; @@ -90,34 +89,35 @@ public interface GeyserInstrument { return -1; } - static GeyserInstrument fromHolder(GeyserSession session, Holder holder) { - if (holder.isId()) { - return session.getRegistryCache().instruments().byId(holder.id()); + // TODO 1.21.5 + static GeyserInstrument fromComponent(GeyserSession session, InstrumentComponent component) { + if (component.instrumentHolder().isId()) { + return session.getRegistryCache().instruments().byId(component.instrumentHolder().id()); } - Instrument custom = holder.custom(); + InstrumentComponent.Instrument custom = component.instrumentHolder().custom(); return new Wrapper(custom, session.locale()); } - record Wrapper(Instrument instrument, String locale) implements GeyserInstrument { + record Wrapper(InstrumentComponent.Instrument instrument, String locale) implements GeyserInstrument { @Override public String soundEvent() { - return instrument.getSoundEvent().getName(); + return instrument.soundEvent().getName(); } @Override public float range() { - return instrument.getRange(); + return instrument.range(); } @Override public String description() { - return MessageTranslator.convertMessageForTooltip(instrument.getDescription(), locale); + return MessageTranslator.convertMessageForTooltip(instrument.description(), locale); } @Override public BedrockInstrument bedrockInstrument() { - if (instrument.getSoundEvent() instanceof BuiltinSound) { - return BedrockInstrument.getByJavaIdentifier(MinecraftKey.key(instrument.getSoundEvent().getName())); + if (instrument.soundEvent() instanceof BuiltinSound) { + return BedrockInstrument.getByJavaIdentifier(MinecraftKey.key(instrument.soundEvent().getName())); } // Probably custom return null; diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java index 664c956c3..5fd64c4d4 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -270,9 +270,13 @@ public final class Items { public static final Item COBWEB = register(new BlockItem(builder(), Blocks.COBWEB)); public static final Item SHORT_GRASS = register(new BlockItem(builder(), Blocks.SHORT_GRASS)); public static final Item FERN = register(new BlockItem(builder(), Blocks.FERN)); + public static final Item BUSH = register(new BlockItem(builder(), Blocks.BUSH)); public static final Item AZALEA = register(new BlockItem(builder(), Blocks.AZALEA)); public static final Item FLOWERING_AZALEA = register(new BlockItem(builder(), Blocks.FLOWERING_AZALEA)); public static final Item DEAD_BUSH = register(new BlockItem(builder(), Blocks.DEAD_BUSH)); + public static final Item FIREFLY_BUSH = register(new BlockItem(builder(), Blocks.FIREFLY_BUSH)); + public static final Item SHORT_DRY_GRASS = register(new BlockItem(builder(), Blocks.SHORT_DRY_GRASS)); + public static final Item TALL_DRY_GRASS = register(new BlockItem(builder(), Blocks.TALL_DRY_GRASS)); public static final Item SEAGRASS = register(new BlockItem(builder(), Blocks.SEAGRASS)); public static final Item SEA_PICKLE = register(new BlockItem(builder(), Blocks.SEA_PICKLE)); public static final Item WHITE_WOOL = register(new BlockItem(builder(), Blocks.WHITE_WOOL)); @@ -321,6 +325,8 @@ public final class Items { public static final Item SUGAR_CANE = register(new BlockItem(builder(), Blocks.SUGAR_CANE)); public static final Item KELP = register(new BlockItem(builder(), Blocks.KELP)); public static final Item PINK_PETALS = register(new BlockItem(builder(), Blocks.PINK_PETALS)); + public static final Item WILDFLOWERS = register(new BlockItem(builder(), Blocks.WILDFLOWERS)); + public static final Item LEAF_LITTER = register(new BlockItem(builder(), Blocks.LEAF_LITTER)); public static final Item MOSS_CARPET = register(new BlockItem(builder(), Blocks.MOSS_CARPET)); public static final Item MOSS_BLOCK = register(new BlockItem(builder(), Blocks.MOSS_BLOCK)); public static final Item PALE_MOSS_CARPET = register(new BlockItem(builder(), Blocks.PALE_MOSS_CARPET)); @@ -389,6 +395,7 @@ public final class Items { public static final Item ICE = register(new BlockItem(builder(), Blocks.ICE)); public static final Item SNOW_BLOCK = register(new BlockItem(builder(), Blocks.SNOW_BLOCK)); public static final Item CACTUS = register(new BlockItem(builder(), Blocks.CACTUS)); + public static final Item CACTUS_FLOWER = register(new BlockItem(builder(), Blocks.CACTUS_FLOWER)); public static final Item CLAY = register(new BlockItem(builder(), Blocks.CLAY)); public static final Item JUKEBOX = register(new BlockItem(builder(), Blocks.JUKEBOX)); public static final Item OAK_FENCE = register(new BlockItem(builder(), Blocks.OAK_FENCE)); @@ -891,6 +898,8 @@ public final class Items { public static final Item BAMBOO_CHEST_RAFT = register(new BoatItem("bamboo_chest_raft", builder())); public static final Item STRUCTURE_BLOCK = register(new BlockItem(builder(), Blocks.STRUCTURE_BLOCK)); public static final Item JIGSAW = register(new BlockItem(builder(), Blocks.JIGSAW)); + public static final Item TEST_BLOCK = register(new BlockItem(builder(), Blocks.TEST_BLOCK)); + public static final Item TEST_INSTANCE_BLOCK = register(new BlockItem(builder(), Blocks.TEST_INSTANCE_BLOCK)); public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", builder())); public static final Item TURTLE_SCUTE = register(new Item("turtle_scute", builder())); public static final Item ARMADILLO_SCUTE = register(new Item("armadillo_scute", builder())); @@ -1027,6 +1036,8 @@ public final class Items { public static final Item BOOK = register(new Item("book", builder())); public static final Item SLIME_BALL = register(new Item("slime_ball", builder())); public static final Item EGG = register(new Item("egg", builder())); + public static final Item BLUE_EGG = register(new Item("blue_egg", builder())); + public static final Item BROWN_EGG = register(new Item("brown_egg", builder())); public static final Item COMPASS = register(new CompassItem("compass", builder())); public static final Item RECOVERY_COMPASS = register(new Item("recovery_compass", builder())); public static final Item BUNDLE = register(new Item("bundle", builder())); @@ -1120,7 +1131,7 @@ public final class Items { public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder())); public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder())); public static final Item BREWING_STAND = register(new BlockItem(builder(), Blocks.BREWING_STAND)); - public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.POWDER_SNOW_CAULDRON, Blocks.LAVA_CAULDRON, Blocks.WATER_CAULDRON)); + public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.POWDER_SNOW_CAULDRON, Blocks.WATER_CAULDRON, Blocks.LAVA_CAULDRON)); public static final Item ENDER_EYE = register(new Item("ender_eye", builder())); public static final Item GLISTERING_MELON_SLICE = register(new Item("glistering_melon_slice", builder())); public static final Item ARMADILLO_SPAWN_EGG = register(new SpawnEggItem("armadillo_spawn_egg", builder())); @@ -1210,7 +1221,7 @@ public final class Items { public static final Item WRITABLE_BOOK = register(new WritableBookItem("writable_book", builder())); public static final Item WRITTEN_BOOK = register(new WrittenBookItem("written_book", builder())); public static final Item BREEZE_ROD = register(new Item("breeze_rod", builder())); - public static final Item MACE = register(new Item("mace", builder())); + public static final Item MACE = register(new Item("mace", builder().attackDamage(6.0))); public static final Item ITEM_FRAME = register(new Item("item_frame", builder())); public static final Item GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder())); public static final Item FLOWER_POT = register(new BlockItem(builder(), Blocks.FLOWER_POT)); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 2a5f76c33..f7229e202 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -46,7 +46,6 @@ import org.geysermc.mcprotocollib.protocol.data.game.Holder; import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentTypes; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.Unit; import java.util.ArrayList; import java.util.List; @@ -226,7 +225,7 @@ public class BannerItem extends BlockItem { } components.put(DataComponentTypes.BANNER_PATTERNS, patternLayers); - components.put(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP, Unit.INSTANCE); + // TODO 1.21.5 hide components??? components.put(DataComponentTypes.ITEM_NAME, Component .translatable("block.minecraft.ominous_banner") .style(Style.style(TextColor.color(16755200))) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java index bd1ac0724..e4173d2bb 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java @@ -36,7 +36,7 @@ import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.mcprotocollib.protocol.data.game.Holder; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentTypes; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.Instrument; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.InstrumentComponent; public class GoatHornItem extends Item { public GoatHornItem(String javaIdentifier, Builder builder) { @@ -50,9 +50,9 @@ public class GoatHornItem extends Item { return builder; } - Holder holder = components.get(DataComponentTypes.INSTRUMENT); - if (holder != null) { - GeyserInstrument instrument = GeyserInstrument.fromHolder(session, holder); + InstrumentComponent instrumentComponent = components.get(DataComponentTypes.INSTRUMENT); + if (instrumentComponent != null) { + GeyserInstrument instrument = GeyserInstrument.fromComponent(session, instrumentComponent); int bedrockId = instrument.bedrockId(); if (bedrockId >= 0) { builder.damage(bedrockId); @@ -66,10 +66,10 @@ public class GoatHornItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - Holder holder = components.get(DataComponentTypes.INSTRUMENT); - if (holder != null && components.get(DataComponentTypes.HIDE_TOOLTIP) == null - && components.get(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP) == null) { - GeyserInstrument instrument = GeyserInstrument.fromHolder(session, holder); + InstrumentComponent component = components.get(DataComponentTypes.INSTRUMENT); + // TODO 1.21.5 hiding???? + if (component != null) { + GeyserInstrument instrument = GeyserInstrument.fromComponent(session, component); if (instrument.bedrockInstrument() == null) { builder.getOrCreateLore().add(instrument.description()); } @@ -82,7 +82,7 @@ public class GoatHornItem extends Item { int damage = itemData.getDamage(); // This could cause an issue since -1 is returned for non-vanilla goat horns - itemStack.getOrCreateComponents().put(DataComponentTypes.INSTRUMENT, Holder.ofId(GeyserInstrument.bedrockIdToJava(session, damage))); + itemStack.getOrCreateComponents().put(DataComponentTypes.INSTRUMENT, new InstrumentComponent(Holder.ofId(GeyserInstrument.bedrockIdToJava(session, damage)), null)); return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index f0ae57018..2c3303689 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -46,12 +46,10 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; -import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentTypes; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DyedItemColor; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; import org.jetbrains.annotations.UnmodifiableView; @@ -159,12 +157,13 @@ public class Item { */ public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { List loreComponents = components.get(DataComponentTypes.LORE); - if (loreComponents != null && components.get(DataComponentTypes.HIDE_TOOLTIP) == null) { - List lore = builder.getOrCreateLore(); - for (Component loreComponent : loreComponents) { - lore.add(MessageTranslator.convertMessage(loreComponent, session.locale())); - } - } + // TODO 1.21.5 +// if (loreComponents != null && components.get(DataComponentTypes.HIDE_TOOLTIP) == null) { +// List lore = builder.getOrCreateLore(); +// for (Component loreComponent : loreComponents) { +// lore.add(MessageTranslator.convertMessage(loreComponent, session.locale())); +// } +// } Integer damage = components.get(DataComponentTypes.DAMAGE); if (damage != null) { @@ -266,10 +265,11 @@ public class Item { } protected final void translateDyedColor(DataComponents components, BedrockItemBuilder builder) { - DyedItemColor dyedItemColor = components.get(DataComponentTypes.DYED_COLOR); - if (dyedItemColor != null) { - builder.putInt("customColor", dyedItemColor.getRgb()); - } + // TODO 1.21.5 +// DyedItemColor dyedItemColor = components.get(DataComponentTypes.DYED_COLOR); +// if (dyedItemColor != null) { +// builder.putInt("customColor", dyedItemColor.getRgb()); +// } } /** diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java index 527e49b14..b90bacdd1 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java @@ -325,6 +325,9 @@ public final class Blocks { public static final Block SHORT_GRASS = register(new Block("short_grass", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block FERN = register(new Block("fern", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block DEAD_BUSH = register(new Block("dead_bush", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block BUSH = register(new Block("bush", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block SHORT_DRY_GRASS = register(new Block("short_dry_grass", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block TALL_DRY_GRASS = register(new Block("tall_dry_grass", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block SEAGRASS = register(new Block("seagrass", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block TALL_SEAGRASS = register(new Block("tall_seagrass", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.SEAGRASS) .enumState(DOUBLE_BLOCK_HALF))); @@ -399,8 +402,8 @@ public final class Blocks { public static final Block SOUL_FIRE = register(new Block("soul_fire", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block SPAWNER = register(new SpawnerBlock("spawner", builder().setBlockEntity(BlockEntityType.MOB_SPAWNER).requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block CREAKING_HEART = register(new Block("creaking_heart", builder().setBlockEntity(BlockEntityType.CREAKING_HEART).destroyTime(10.0f) - .booleanState(ACTIVE) .enumState(AXIS, Axis.VALUES) + .enumState(CREAKING_HEART_STATE) .booleanState(NATURAL))); public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) @@ -630,7 +633,7 @@ public final class Blocks { public static final Block REDSTONE_WALL_TORCH = register(new Block("redstone_wall_torch", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); - public static final Block STONE_BUTTON = register(new ButtonBlock("stone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block STONE_BUTTON = register(new Block("stone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); @@ -640,6 +643,7 @@ public final class Blocks { public static final Block SNOW_BLOCK = register(new Block("snow_block", builder().requiresCorrectToolForDrops().destroyTime(0.2f))); public static final Block CACTUS = register(new Block("cactus", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY) .intState(AGE_15))); + public static final Block CACTUS_FLOWER = register(new Block("cactus_flower", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block CLAY = register(new Block("clay", builder().destroyTime(0.6f))); public static final Block SUGAR_CANE = register(new Block("sugar_cane", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_15))); @@ -997,43 +1001,43 @@ public final class Blocks { .intState(AGE_7))); public static final Block POTATOES = register(new Block("potatoes", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_7))); - public static final Block OAK_BUTTON = register(new ButtonBlock("oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block OAK_BUTTON = register(new Block("oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block SPRUCE_BUTTON = register(new ButtonBlock("spruce_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block SPRUCE_BUTTON = register(new Block("spruce_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block BIRCH_BUTTON = register(new ButtonBlock("birch_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block BIRCH_BUTTON = register(new Block("birch_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block JUNGLE_BUTTON = register(new ButtonBlock("jungle_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block JUNGLE_BUTTON = register(new Block("jungle_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block ACACIA_BUTTON = register(new ButtonBlock("acacia_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block ACACIA_BUTTON = register(new Block("acacia_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block CHERRY_BUTTON = register(new ButtonBlock("cherry_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block CHERRY_BUTTON = register(new Block("cherry_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block DARK_OAK_BUTTON = register(new ButtonBlock("dark_oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block DARK_OAK_BUTTON = register(new Block("dark_oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block PALE_OAK_BUTTON = register(new ButtonBlock("pale_oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block PALE_OAK_BUTTON = register(new Block("pale_oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block MANGROVE_BUTTON = register(new ButtonBlock("mangrove_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block MANGROVE_BUTTON = register(new Block("mangrove_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block BAMBOO_BUTTON = register(new ButtonBlock("bamboo_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block BAMBOO_BUTTON = register(new Block("bamboo_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); @@ -2232,11 +2236,11 @@ public final class Blocks { .enumState(HALF) .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); - public static final Block CRIMSON_BUTTON = register(new ButtonBlock("crimson_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block CRIMSON_BUTTON = register(new Block("crimson_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block WARPED_BUTTON = register(new ButtonBlock("warped_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block WARPED_BUTTON = register(new Block("warped_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); @@ -2268,6 +2272,9 @@ public final class Blocks { .enumState(STRUCTUREBLOCK_MODE))); public static final Block JIGSAW = register(new Block("jigsaw", builder().setBlockEntity(BlockEntityType.JIGSAW).requiresCorrectToolForDrops().destroyTime(-1.0f) .enumState(ORIENTATION, FrontAndTop.VALUES))); + public static final Block TEST_BLOCK = register(new Block("test_block", builder().setBlockEntity(BlockEntityType.TEST_BLOCK).destroyTime(-1.0f) + .enumState(TEST_BLOCK_MODE))); + public static final Block TEST_INSTANCE_BLOCK = register(new Block("test_instance_block", builder().setBlockEntity(BlockEntityType.TEST_INSTANCE_BLOCK).destroyTime(-1.0f))); public static final Block COMPOSTER = register(new Block("composter", builder().destroyTime(0.6f) .intState(LEVEL_COMPOSTER))); public static final Block TARGET = register(new Block("target", builder().destroyTime(0.5f) @@ -2336,7 +2343,7 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Block("polished_blackstone_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block POLISHED_BLACKSTONE_BUTTON = register(new ButtonBlock("polished_blackstone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block POLISHED_BLACKSTONE_BUTTON = register(new Block("polished_blackstone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); @@ -2790,6 +2797,12 @@ public final class Blocks { public static final Block PINK_PETALS = register(new Block("pink_petals", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .intState(FLOWER_AMOUNT))); + public static final Block WILDFLOWERS = register(new Block("wildflowers", builder().pushReaction(PistonBehavior.DESTROY) + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .intState(FLOWER_AMOUNT))); + public static final Block LEAF_LITTER = register(new Block("leaf_litter", builder().pushReaction(PistonBehavior.DESTROY) + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .intState(SEGMENT_AMOUNT))); public static final Block MOSS_BLOCK = register(new Block("moss_block", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY))); public static final Block BIG_DRIPLEAF = register(new Block("big_dripleaf", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) @@ -2921,6 +2934,7 @@ public final class Blocks { public static final Block CLOSED_EYEBLOSSOM = register(new Block("closed_eyeblossom", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block POTTED_OPEN_EYEBLOSSOM = register(new FlowerPotBlock("potted_open_eyeblossom", OPEN_EYEBLOSSOM, builder().pushReaction(PistonBehavior.DESTROY))); public static final Block POTTED_CLOSED_EYEBLOSSOM = register(new FlowerPotBlock("potted_closed_eyeblossom", CLOSED_EYEBLOSSOM, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block FIREFLY_BUSH = register(new Block("firefly_bush", builder().pushReaction(PistonBehavior.DESTROY))); private static T register(T block) { block.setJavaId(BlockRegistries.JAVA_BLOCKS.get().size()); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java index f295c4f51..a837bd532 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java @@ -29,7 +29,6 @@ import org.geysermc.geyser.level.physics.Axis; import org.geysermc.geyser.level.physics.Direction; public final class Properties { - public static final BooleanProperty ACTIVE = BooleanProperty.create("active"); public static final BooleanProperty ATTACHED = BooleanProperty.create("attached"); public static final BooleanProperty BERRIES = BooleanProperty.create("berries"); public static final BooleanProperty BLOOM = BooleanProperty.create("bloom"); @@ -77,6 +76,7 @@ public final class Properties { public static final EnumProperty FACING_HOPPER = EnumProperty.create("facing", Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST); public static final EnumProperty HORIZONTAL_FACING = EnumProperty.create("facing", Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST); public static final IntegerProperty FLOWER_AMOUNT = IntegerProperty.create("flower_amount", 1, 4); + public static final IntegerProperty SEGMENT_AMOUNT = IntegerProperty.create("segment_amount", 1, 4); public static final EnumProperty ORIENTATION = EnumProperty.create("orientation", FrontAndTop.VALUES); public static final BasicEnumProperty ATTACH_FACE = BasicEnumProperty.create("face", "floor", "wall", "ceiling"); public static final BasicEnumProperty BELL_ATTACHMENT = BasicEnumProperty.create("attachment", "floor", "ceiling", "single_wall", "double_wall"); @@ -145,5 +145,8 @@ public final class Properties { public static final BooleanProperty CRAFTING = BooleanProperty.create("crafting"); public static final BasicEnumProperty TRIAL_SPAWNER_STATE = BasicEnumProperty.create("trial_spawner_state", "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown"); public static final BasicEnumProperty VAULT_STATE = BasicEnumProperty.create("vault_state", "inactive", "active", "unlocking", "ejecting"); + public static final BasicEnumProperty CREAKING_HEART_STATE = BasicEnumProperty.create("creaking_heart_state", "uprooted", "dormant", "awake"); public static final BooleanProperty OMINOUS = BooleanProperty.create("ominous"); + public static final BasicEnumProperty TEST_BLOCK_MODE = BasicEnumProperty.create("mode", "start", "log", "fail", "accept"); + public static final BooleanProperty MAP = BooleanProperty.create("map"); } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java index 0f6e6b5bc..620a693a2 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java @@ -41,6 +41,7 @@ import org.geysermc.mcprotocollib.network.helper.NettyHelper; import org.geysermc.mcprotocollib.network.netty.MinecraftChannelInitializer; import org.geysermc.mcprotocollib.network.packet.PacketProtocol; import org.geysermc.mcprotocollib.network.session.ClientNetworkSession; +import org.geysermc.mcprotocollib.protocol.MinecraftProtocol; import java.net.InetSocketAddress; import java.net.SocketAddress; @@ -56,7 +57,7 @@ public final class LocalSession extends ClientNetworkSession { private final SocketAddress spoofedRemoteAddress; - public LocalSession(SocketAddress targetAddress, String clientIp, PacketProtocol protocol, Executor packetHandlerExecutor) { + public LocalSession(SocketAddress targetAddress, String clientIp, MinecraftProtocol protocol, Executor packetHandlerExecutor) { super(targetAddress, protocol, packetHandlerExecutor, null, null); this.spoofedRemoteAddress = new InetSocketAddress(clientIp, 0); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java index 81f1fec46..d8e8a68ce 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java @@ -58,6 +58,9 @@ import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.block.type.FlowerPotBlock; import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.populator.conversion.Conversion766_748; +import org.geysermc.geyser.registry.populator.conversion.Conversion776_766; +import org.geysermc.geyser.registry.populator.conversion.Conversion786_776; import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.GeyserBedrockBlock; @@ -119,7 +122,7 @@ public final class BlockRegistryPopulator { var blockMappers = ImmutableMap., Remapper>builder() .put(ObjectIntPair.of("1_21_40", Bedrock_v748.CODEC.getProtocolVersion()), Conversion766_748::remapBlock) .put(ObjectIntPair.of("1_21_50", Bedrock_v766.CODEC.getProtocolVersion()), Conversion776_766::remapBlock) - .put(ObjectIntPair.of("1_21_60", Bedrock_v776.CODEC.getProtocolVersion()), tag -> tag) + .put(ObjectIntPair.of("1_21_60", Bedrock_v776.CODEC.getProtocolVersion()), Conversion786_776::remapBlock) .put(ObjectIntPair.of("1_21_70", Bedrock_v786.CODEC.getProtocolVersion()), tag -> tag) .build(); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/DataComponentRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/DataComponentRegistryPopulator.java index ef3168f41..29d85cdd2 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/DataComponentRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/DataComponentRegistryPopulator.java @@ -75,6 +75,7 @@ public final class DataComponentRegistryPopulator { byte[] bytes = Base64.getDecoder().decode(encodedValue); ByteBuf buf = Unpooled.wrappedBuffer(bytes); int varInt = MinecraftTypes.readVarInt(buf); + System.out.println("int: " + varInt + " " + componentEntry.getKey()); DataComponentType dataComponentType = DataComponentTypes.from(varInt); DataComponent dataComponent = dataComponentType.readDataComponent(buf); @@ -84,6 +85,7 @@ public final class DataComponentRegistryPopulator { defaultComponents.add(new DataComponents(ImmutableMap.copyOf(map))); } } catch (Exception e) { + // TODO 1.21.5 enchantment reading is broken throw new AssertionError("Unable to load or parse components", e); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion766_748.java b/core/src/main/java/org/geysermc/geyser/registry/populator/conversion/Conversion766_748.java similarity index 87% rename from core/src/main/java/org/geysermc/geyser/registry/populator/Conversion766_748.java rename to core/src/main/java/org/geysermc/geyser/registry/populator/conversion/Conversion766_748.java index 6f2bc61e2..b63797d74 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion766_748.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/conversion/Conversion766_748.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 GeyserMC. http://geysermc.org + * Copyright (c) 2024-2025 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 @@ -23,16 +23,18 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.registry.populator; +package org.geysermc.geyser.registry.populator.conversion; import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.Blocks; import java.util.ArrayList; import java.util.List; import java.util.Set; +import static org.geysermc.geyser.registry.populator.conversion.ConversionHelper.withName; +import static org.geysermc.geyser.registry.populator.conversion.ConversionHelper.withoutStates; + public class Conversion766_748 { static List PALE_WOODEN_BLOCKS = new ArrayList<>(); static List OTHER_NEW_BLOCKS = new ArrayList<>(); @@ -84,7 +86,7 @@ public class Conversion766_748 { OTHER_NEW_BLOCKS.add("resin_brick_double_slab"); } - static NbtMap remapBlock(NbtMap tag) { + public static NbtMap remapBlock(NbtMap tag) { // First: Downgrade from 1.21.60 -> 1.21.50 tag = Conversion776_766.remapBlock(tag); @@ -116,17 +118,4 @@ public class Conversion766_748 { return tag; } - - static NbtMap withName(NbtMap tag, String name) { - NbtMapBuilder builder = tag.toBuilder(); - builder.replace("name", "minecraft:" + name); - return builder.build(); - } - - static NbtMap withoutStates(String name) { - NbtMapBuilder tagBuilder = NbtMap.builder(); - tagBuilder.putString("name", "minecraft:" + name); - tagBuilder.putCompound("states", NbtMap.builder().build()); - return tagBuilder.build(); - } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion776_766.java b/core/src/main/java/org/geysermc/geyser/registry/populator/conversion/Conversion776_766.java similarity index 94% rename from core/src/main/java/org/geysermc/geyser/registry/populator/Conversion776_766.java rename to core/src/main/java/org/geysermc/geyser/registry/populator/conversion/Conversion776_766.java index edc2543ae..325ad5ca9 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion776_766.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/conversion/Conversion776_766.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.registry.populator; +package org.geysermc.geyser.registry.populator.conversion; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -31,6 +31,10 @@ import org.cloudburstmc.nbt.NbtMapBuilder; public class Conversion776_766 { public static NbtMap remapBlock(NbtMap tag) { + + // First: Downgrade from 1.21.70 + tag = Conversion786_776.remapBlock(tag); + final String name = tag.getString("name"); if (name.equals("minecraft:creaking_heart")) { diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/conversion/Conversion786_776.java b/core/src/main/java/org/geysermc/geyser/registry/populator/conversion/Conversion786_776.java new file mode 100644 index 000000000..ee4518a95 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/conversion/Conversion786_776.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 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.populator.conversion; + +import org.cloudburstmc.nbt.NbtMap; + +import static org.geysermc.geyser.registry.populator.conversion.ConversionHelper.withName; +import static org.geysermc.geyser.registry.populator.conversion.ConversionHelper.withoutStates; + +public class Conversion786_776 { + + public static NbtMap remapBlock(NbtMap nbtMap) { + + final String name = nbtMap.getString("name"); + if (name.equals("minecraft:bush")) { + return withName(nbtMap, "fern"); + } + + if (name.equals("minecraft:firefly_bush")) { + return withName(nbtMap, "deadbush"); + } + + if (name.equals("minecraft:tall_dry_grass") || name.equals("minecraft:short_dry_grass")) { + return withName(nbtMap, "short_grass"); + } + + if (name.equals("minecraft:cactus_flower")) { + return withName(nbtMap, "unknown"); + } + + if (name.equals("minecraft:leaf_litter") || name.equals("minecraft:wildflowers")) { + return withoutStates("unknown"); + } + + return nbtMap; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/conversion/ConversionHelper.java b/core/src/main/java/org/geysermc/geyser/registry/populator/conversion/ConversionHelper.java new file mode 100644 index 000000000..0bc9708ac --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/conversion/ConversionHelper.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 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.populator.conversion; + +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; + +// A variety of methods to help with re-mapping blocks and items to older versions. +public class ConversionHelper { + + static NbtMap withName(NbtMap tag, String name) { + NbtMapBuilder builder = tag.toBuilder(); + builder.replace("name", "minecraft:" + name); + return builder.build(); + } + + static NbtMap withoutStates(String name) { + NbtMapBuilder tagBuilder = NbtMap.builder(); + tagBuilder.putString("name", "minecraft:" + name); + tagBuilder.putCompound("states", NbtMap.EMPTY); + return tagBuilder.build(); + } + +} diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/tags/BlockTag.java b/core/src/main/java/org/geysermc/geyser/session/cache/tags/BlockTag.java index 59d301a89..924b168a4 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/tags/BlockTag.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/tags/BlockTag.java @@ -141,6 +141,7 @@ public final class BlockTag { public static final Tag FENCE_GATES = create("fence_gates"); public static final Tag UNSTABLE_BOTTOM_CENTER = create("unstable_bottom_center"); public static final Tag MUSHROOM_GROW_BLOCK = create("mushroom_grow_block"); + public static final Tag EDIBLE_FOR_SHEEP = create("edible_for_sheep"); public static final Tag INFINIBURN_OVERWORLD = create("infiniburn_overworld"); public static final Tag INFINIBURN_NETHER = create("infiniburn_nether"); public static final Tag INFINIBURN_END = create("infiniburn_end"); @@ -171,6 +172,7 @@ public final class BlockTag { public static final Tag MINEABLE_PICKAXE = create("mineable/pickaxe"); public static final Tag MINEABLE_SHOVEL = create("mineable/shovel"); public static final Tag SWORD_EFFICIENT = create("sword_efficient"); + public static final Tag SWORD_INSTANTLY_MINES = create("sword_instantly_mines"); public static final Tag NEEDS_DIAMOND_TOOL = create("needs_diamond_tool"); public static final Tag NEEDS_IRON_TOOL = create("needs_iron_tool"); public static final Tag NEEDS_STONE_TOOL = create("needs_stone_tool"); @@ -200,13 +202,15 @@ public final class BlockTag { public static final Tag WOLVES_SPAWNABLE_ON = create("wolves_spawnable_on"); public static final Tag FROGS_SPAWNABLE_ON = create("frogs_spawnable_on"); public static final Tag BATS_SPAWNABLE_ON = create("bats_spawnable_on"); + public static final Tag CAMELS_SPAWNABLE_ON = create("camels_spawnable_on"); public static final Tag AZALEA_GROWS_ON = create("azalea_grows_on"); public static final Tag CONVERTABLE_TO_MUD = create("convertable_to_mud"); public static final Tag MANGROVE_LOGS_CAN_GROW_THROUGH = create("mangrove_logs_can_grow_through"); public static final Tag MANGROVE_ROOTS_CAN_GROW_THROUGH = create("mangrove_roots_can_grow_through"); - public static final Tag DEAD_BUSH_MAY_PLACE_ON = create("dead_bush_may_place_on"); + public static final Tag DRY_VEGETATION_MAY_PLACE_ON = create("dry_vegetation_may_place_on"); public static final Tag SNAPS_GOAT_HORN = create("snaps_goat_horn"); public static final Tag REPLACEABLE_BY_TREES = create("replaceable_by_trees"); + public static final Tag REPLACEABLE_BY_MUSHROOMS = create("replaceable_by_mushrooms"); public static final Tag SNOW_LAYER_CANNOT_SURVIVE_ON = create("snow_layer_cannot_survive_on"); public static final Tag SNOW_LAYER_CAN_SURVIVE_ON = create("snow_layer_can_survive_on"); public static final Tag INVALID_SPAWN_INSIDE = create("invalid_spawn_inside"); @@ -219,6 +223,7 @@ public final class BlockTag { public static final Tag MAINTAINS_FARMLAND = create("maintains_farmland"); public static final Tag BLOCKS_WIND_CHARGE_EXPLOSIONS = create("blocks_wind_charge_explosions"); public static final Tag DOES_NOT_BLOCK_HOPPERS = create("does_not_block_hoppers"); + public static final Tag PLAYS_AMBIENT_DESERT_BLOCK_SOUNDS = create("plays_ambient_desert_block_sounds"); public static final Tag AIR = create("air"); private BlockTag() {} diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java b/core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java index e2f4f2db3..50398a765 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java @@ -76,6 +76,7 @@ public final class ItemTag { public static final Tag LEAVES = create("leaves"); public static final Tag TRAPDOORS = create("trapdoors"); public static final Tag SMALL_FLOWERS = create("small_flowers"); + public static final Tag FLOWERS = create("flowers"); public static final Tag BEDS = create("beds"); public static final Tag FENCES = create("fences"); public static final Tag PIGLIN_REPELLENTS = create("piglin_repellents"); @@ -85,6 +86,7 @@ public final class ItemTag { public static final Tag DUPLICATES_ALLAYS = create("duplicates_allays"); public static final Tag BREWING_FUEL = create("brewing_fuel"); public static final Tag SHULKER_BOXES = create("shulker_boxes"); + public static final Tag EGGS = create("eggs"); public static final Tag MEAT = create("meat"); public static final Tag SNIFFER_FOOD = create("sniffer_food"); public static final Tag PIGLIN_FOOD = create("piglin_food"); @@ -181,6 +183,7 @@ public final class ItemTag { public static final Tag DYEABLE = create("dyeable"); public static final Tag FURNACE_MINECART_FUEL = create("furnace_minecart_fuel"); public static final Tag BUNDLES = create("bundles"); + public static final Tag BOOK_CLONING_TARGET = create("book_cloning_target"); public static final Tag SKELETON_PREFERRED_WEAPONS = create("skeleton_preferred_weapons"); public static final Tag DROWNED_PREFERRED_WEAPONS = create("drowned_preferred_weapons"); public static final Tag PIGLIN_PREFERRED_WEAPONS = create("piglin_preferred_weapons"); diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 0c8c63f00..9d01f0d8c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -168,6 +168,9 @@ public final class ItemTranslator { public static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, @Nullable DataComponents customComponents) { BedrockItemBuilder nbtBuilder = new BedrockItemBuilder(); + // TODO 1.21.5: + // - Hiding components + // Populates default components that aren't sent over the network DataComponents components = javaItem.gatherComponents(customComponents); @@ -180,22 +183,22 @@ public final class ItemTranslator { PotionContents potionContents = components.get(DataComponentTypes.POTION_CONTENTS); // Make custom effect information visible // Ignore when item have "hide_additional_tooltip" component - if (potionContents != null && components.get(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP) == null) { + if (potionContents != null) { // && components.get(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP) == null) { customName += getPotionEffectInfo(potionContents, session.locale()); } nbtBuilder.setCustomName(customName); } - boolean hideTooltips = components.get(DataComponentTypes.HIDE_TOOLTIP) != null; + //boolean hideTooltips = components.get(DataComponentTypes.HIDE_TOOLTIP) != null; ItemAttributeModifiers attributeModifiers = components.get(DataComponentTypes.ATTRIBUTE_MODIFIERS); - if (attributeModifiers != null && attributeModifiers.isShowInTooltip() && !hideTooltips) { + if (attributeModifiers != null) { //&& attributeModifiers.isShowInTooltip() && !hideTooltips) { // only add if attribute modifiers do not indicate to hide them addAttributeLore(session, attributeModifiers, nbtBuilder, session.locale()); } - if (session.isAdvancedTooltips() && !hideTooltips) { + if (session.isAdvancedTooltips()) { //&& !hideTooltips) { addAdvancedTooltips(components, nbtBuilder, javaItem, session.locale()); } @@ -545,7 +548,8 @@ public final class ItemTranslator { if (!customNameOnly) { PotionContents potionContents = components.get(DataComponentTypes.POTION_CONTENTS); if (potionContents != null) { - String potionName = getPotionName(potionContents, mapping, components.get(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP) != null, session.locale()); + // TODO 1.21.5 + String potionName = getPotionName(potionContents, mapping, false /*components.get(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP) != null */, session.locale()); if (potionName != null) { return ChatColor.RESET + ChatColor.ESCAPE + translationColor + potionName; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java index bfc71089a..c44f21213 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java @@ -30,7 +30,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; -import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; @@ -41,8 +40,6 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.InventoryTra import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.LegacySetItemSlotData; import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryTransactionPacket; -import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; -import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Entity; @@ -52,7 +49,6 @@ 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.inventory.item.GeyserInstrument; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.BlockItem; import org.geysermc.geyser.item.type.BoatItem; @@ -78,16 +74,12 @@ import org.geysermc.geyser.util.CooldownUtils; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InventoryUtils; -import org.geysermc.geyser.util.SoundUtils; -import org.geysermc.mcprotocollib.protocol.data.game.Holder; import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.InteractAction; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentTypes; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.Instrument; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket; @@ -388,29 +380,30 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator holder = session.getPlayerInventory() - .getItemInHand() - .getComponent(DataComponentTypes.INSTRUMENT); - if (holder != null) { - GeyserInstrument instrument = GeyserInstrument.fromHolder(session, holder); - if (instrument.bedrockInstrument() != null) { - // BDS uses a LevelSoundEvent2Packet, but that doesn't work here... (as of 1.21.20) - LevelSoundEventPacket soundPacket = new LevelSoundEventPacket(); - soundPacket.setSound(SoundEvent.valueOf("GOAT_CALL_" + instrument.bedrockInstrument().ordinal())); - soundPacket.setPosition(session.getPlayerEntity().getPosition()); - soundPacket.setIdentifier("minecraft:player"); - soundPacket.setExtraData(-1); - session.sendUpstreamPacket(soundPacket); - } else { - PlaySoundPacket playSoundPacket = new PlaySoundPacket(); - playSoundPacket.setPosition(session.getPlayerEntity().position()); - playSoundPacket.setSound(SoundUtils.translatePlaySound(instrument.soundEvent())); - playSoundPacket.setPitch(1.0F); - playSoundPacket.setVolume(instrument.range() / 16.0F); - session.sendUpstreamPacket(playSoundPacket); - } - } +// Holder holder = session.getPlayerInventory() +// .getItemInHand() +// .getComponent(DataComponentTypes.INSTRUMENT); +// if (holder != null) { +// GeyserInstrument instrument = GeyserInstrument.fromComponent(session, holder); +// if (instrument.bedrockInstrument() != null) { +// // BDS uses a LevelSoundEvent2Packet, but that doesn't work here... (as of 1.21.20) +// LevelSoundEventPacket soundPacket = new LevelSoundEventPacket(); +// soundPacket.setSound(SoundEvent.valueOf("GOAT_CALL_" + instrument.bedrockInstrument().ordinal())); +// soundPacket.setPosition(session.getPlayerEntity().getPosition()); +// soundPacket.setIdentifier("minecraft:player"); +// soundPacket.setExtraData(-1); +// session.sendUpstreamPacket(soundPacket); +// } else { +// PlaySoundPacket playSoundPacket = new PlaySoundPacket(); +// playSoundPacket.setPosition(session.getPlayerEntity().position()); +// playSoundPacket.setSound(SoundUtils.translatePlaySound(instrument.soundEvent())); +// playSoundPacket.setPitch(1.0F); +// playSoundPacket.setVolume(instrument.range() / 16.0F); +// session.sendUpstreamPacket(playSoundPacket); +// } +// } } } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAddEntityTranslator.java similarity index 97% rename from core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java rename to core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAddEntityTranslator.java index ed1951243..738d3c07e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAddEntityTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2025 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 @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.translator.protocol.java.entity.spawn; +package org.geysermc.geyser.translator.protocol.java.entity; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.GeyserImpl; @@ -47,7 +47,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.object.FallingBlockD import org.geysermc.mcprotocollib.protocol.data.game.entity.object.ProjectileData; import org.geysermc.mcprotocollib.protocol.data.game.entity.object.WardenData; import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; -import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundAddEntityPacket; @Translator(packet = ClientboundAddEntityPacket.class) public class JavaAddEntityTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddExperienceOrbTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddExperienceOrbTranslator.java deleted file mode 100644 index 8f37eb4d4..000000000 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddExperienceOrbTranslator.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser - */ - -package org.geysermc.geyser.translator.protocol.java.entity.spawn; - -import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddExperienceOrbPacket; -import org.cloudburstmc.math.vector.Vector3f; -import org.geysermc.geyser.entity.type.Entity; -import org.geysermc.geyser.entity.type.ExpOrbEntity; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.protocol.PacketTranslator; -import org.geysermc.geyser.translator.protocol.Translator; - -@Translator(packet = ClientboundAddExperienceOrbPacket.class) -public class JavaAddExperienceOrbTranslator extends PacketTranslator { - - @Override - public void translate(GeyserSession session, ClientboundAddExperienceOrbPacket packet) { - Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ()); - - Entity entity = new ExpOrbEntity( - session, packet.getExp(), packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), position - ); - - session.getEntityCache().spawnEntity(entity); - } -} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java index e4ff0539f..8a06698c0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java @@ -73,11 +73,11 @@ public class JavaMerchantOffersTranslator extends PacketTranslator tags = new ArrayList<>(addExtraTrade ? packet.getTrades().length + 1 : packet.getTrades().length); - for (int i = 0; i < packet.getTrades().length; i++) { - VillagerTrade trade = packet.getTrades()[i]; + boolean addExtraTrade = packet.isShowProgress() && packet.getVillagerLevel() < 5; + List tags = new ArrayList<>(addExtraTrade ? packet.getOffers().size() + 1 : packet.getOffers().size()); + for (int i = 0; i < packet.getOffers().size(); i++) { + VillagerTrade trade = packet.getOffers().get(i); NbtMapBuilder recipe = NbtMap.builder(); recipe.putInt("netId", i + 1); - recipe.putInt("maxUses", trade.isTradeDisabled() ? 0 : trade.getMaxUses()); + recipe.putInt("maxUses", trade.isOutOfStock() ? 0 : trade.getMaxUses()); recipe.putInt("traderExp", trade.getXp()); recipe.putFloat("priceMultiplierA", trade.getPriceMultiplier()); recipe.putFloat("priceMultiplierB", 0.0f); - recipe.put("sell", getItemTag(session, trade.getOutput())); + recipe.put("sell", getItemTag(session, trade.getResult())); // The buy count before demand and special price adjustments // The first input CAN be null as of Java 1.19.0/Bedrock 1.19.10 // Replicable item: https://gist.github.com/Camotoy/3f3f23d1f80981d1b4472bdb23bba698 from https://github.com/GeyserMC/Geyser/issues/3171 - recipe.putInt("buyCountA", trade.getFirstInput() != null ? Math.max(trade.getFirstInput().getAmount(), 0) : 0); - recipe.putInt("buyCountB", trade.getSecondInput() != null ? Math.max(trade.getSecondInput().getAmount(), 0) : 0); + recipe.putInt("buyCountA", trade.getItemCostA() != null ? Math.max(trade.getItemCostA().count(), 0) : 0); + recipe.putInt("buyCountB", trade.getItemCostB() != null ? Math.max(trade.getItemCostB().count(), 0) : 0); recipe.putInt("demand", trade.getDemand()); // Seems to have no effect recipe.putInt("tier", packet.getVillagerLevel() > 0 ? packet.getVillagerLevel() - 1 : 0); // -1 crashes client - recipe.put("buyA", getItemTag(session, trade.getFirstInput(), trade.getSpecialPrice(), trade.getDemand(), trade.getPriceMultiplier())); - recipe.put("buyB", getItemTag(session, trade.getSecondInput())); - recipe.putInt("uses", trade.getNumUses()); + recipe.put("buyA", getItemTag(session, toItemStack(trade.getItemCostA()), trade.getSpecialPriceDiff(), trade.getDemand(), trade.getPriceMultiplier())); + recipe.put("buyB", getItemTag(session, toItemStack(trade.getItemCostB()))); + recipe.putInt("uses", trade.getUses()); recipe.putByte("rewardExp", (byte) 1); tags.add(recipe.build()); } @@ -158,6 +158,11 @@ public class JavaMerchantOffersTranslator extends PacketTranslator { ServerboundClientCommandPacket javaRespawnPacket = new ServerboundClientCommandPacket(ClientCommand.RESPAWN); @@ -114,7 +114,7 @@ public class JavaGameEventTranslator extends PacketTranslator("doimmediaterespawn", packet.getValue() == RespawnScreenValue.IMMEDIATE_RESPAWN)); session.sendUpstreamPacket(gamerulePacket); break; - case INVALID_BED: + case NO_RESPAWN_BLOCK_AVAILABLE: // Not sent as a proper message? Odd. session.sendMessage(MinecraftLocale.getLocaleString("block.minecraft.spawn.not_valid", session.locale())); break; - case ARROW_HIT_PLAYER: + case PLAY_ARROW_HIT_SOUND: PlaySoundPacket arrowSoundPacket = new PlaySoundPacket(); arrowSoundPacket.setSound("random.orb"); arrowSoundPacket.setPitch(0.5f); @@ -143,9 +143,9 @@ public class JavaGameEventTranslator extends PacketTranslator#5075 - */ - @Test - void entityWithoutUuid() { - // experience orbs are the only known entities without an uuid, see Entity#teamIdentifier for more info - mockContextScoreboard(context -> { - var addExperienceOrbTranslator = new JavaAddExperienceOrbTranslator(); - var removeEntitiesTranslator = new JavaRemoveEntitiesTranslator(); - - // Entity#teamIdentifier used to throw because it returned uuid.toString where uuid could be null. - // this would result in both EntityCache#spawnEntity and EntityCache#removeEntity throwing an exception, - // because the entity would be registered and deregistered to the scoreboard. - assertDoesNotThrow(() -> { - context.translate(addExperienceOrbTranslator, new ClientboundAddExperienceOrbPacket(2, 0, 0, 0, 1)); - - String displayName = context.mockOrSpy(EntityCache.class).getEntityByJavaId(2).getDisplayName(); - assertEquals("entity.minecraft.experience_orb", displayName); - - context.translate(removeEntitiesTranslator, new ClientboundRemoveEntitiesPacket(new int[]{2})); - }); - - // we know that spawning and removing the entity should be fine - assertNextPacketType(context, AddEntityPacket.class); - assertNextPacketType(context, RemoveEntityPacket.class); - }); - } + // TODO 1.21.5 +// /** +// * Test for #5075 +// */ +// @Test +// void entityWithoutUuid() { +// // experience orbs are the only known entities without an uuid, see Entity#teamIdentifier for more info +// mockContextScoreboard(context -> { +// var addExperienceOrbTranslator = new JavaAddExperienceOrbTranslator(); +// var removeEntitiesTranslator = new JavaRemoveEntitiesTranslator(); +// +// // Entity#teamIdentifier used to throw because it returned uuid.toString where uuid could be null. +// // this would result in both EntityCache#spawnEntity and EntityCache#removeEntity throwing an exception, +// // because the entity would be registered and deregistered to the scoreboard. +// assertDoesNotThrow(() -> { +// context.translate(addExperienceOrbTranslator, new ClientboundAddExperienceOrbPacket(2, 0, 0, 0, 1)); +// +// String displayName = context.mockOrSpy(EntityCache.class).getEntityByJavaId(2).getDisplayName(); +// assertEquals("entity.minecraft.experience_orb", displayName); +// +// context.translate(removeEntitiesTranslator, new ClientboundRemoveEntitiesPacket(new int[] { 2 })); +// }); +// +// // we know that spawning and removing the entity should be fine +// assertNextPacketType(context, AddEntityPacket.class); +// assertNextPacketType(context, RemoveEntityPacket.class); +// }); +// } /** * Test for #5078 @@ -168,7 +148,7 @@ public class ScoreboardIssueTests { playerInfoUpdateTranslator, new ClientboundPlayerInfoUpdatePacket( EnumSet.of(PlayerListEntryAction.ADD_PLAYER, PlayerListEntryAction.UPDATE_LISTED), - new PlayerListEntry[]{ + new PlayerListEntry[] { new PlayerListEntry(npcUuid, new GameProfile(npcUuid, "1297"), false, 0, GameMode.SURVIVAL, null, false, 0, null, 0, null, null) })); @@ -198,7 +178,7 @@ public class ScoreboardIssueTests { ); context.translate( setPlayerTeamTranslator, - new ClientboundSetPlayerTeamPacket("npc_team_1297", TeamAction.ADD_PLAYER, new String[]{"1297"})); + new ClientboundSetPlayerTeamPacket("npc_team_1297", TeamAction.ADD_PLAYER, new String[]{ "1297" })); context.translate(addEntityTranslator, new ClientboundAddEntityPacket(1297, npcUuid, EntityType.PLAYER, 1, 2, 3, 4, 5, 6)); // then it updates the displayed skin parts, which isn't relevant for us @@ -260,7 +240,7 @@ public class ScoreboardIssueTests { ); context.translate( setPlayerTeamTranslator, - new ClientboundSetPlayerTeamPacket("npc_team_1298", TeamAction.ADD_PLAYER, new String[]{hologramUuid.toString()})); + new ClientboundSetPlayerTeamPacket("npc_team_1298", TeamAction.ADD_PLAYER, new String[]{ hologramUuid.toString() })); assertNextPacket(context, () -> { var packet = new SetEntityDataPacket(); @@ -270,76 +250,4 @@ public class ScoreboardIssueTests { }); }); } - - /** - * Test for #5353. - * It follows a code snippet provided in the PR description. - */ - @Test - void prefixNotShowing() { - mockContextScoreboard(context -> { - var setObjectiveTranslator = new JavaSetObjectiveTranslator(); - var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator(); - var setPlayerTeamTranslator = new JavaSetPlayerTeamTranslator(); - var setScoreTranslator = new JavaSetScoreTranslator(); - - context.translate( - setObjectiveTranslator, - new ClientboundSetObjectivePacket( - "sb-0", - ObjectiveAction.ADD, - Component.text("Test Scoreboard"), - ScoreType.INTEGER, - null - ) - ); - assertNoNextPacket(context); - - context.translate( - setDisplayObjectiveTranslator, - new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "sb-0") - ); - assertNextPacket(context, () -> { - var packet = new SetDisplayObjectivePacket(); - packet.setObjectiveId("0"); - packet.setDisplayName("Test Scoreboard"); - packet.setCriteria("dummy"); - packet.setDisplaySlot("sidebar"); - packet.setSortOrder(1); - return packet; - }); - - context.translate( - setPlayerTeamTranslator, - new ClientboundSetPlayerTeamPacket( - "sbt-1", - Component.text("displaynametest"), - Component.text("§aScore: 10"), - Component.empty(), - false, - false, - NameTagVisibility.NEVER, - CollisionRule.NEVER, - TeamColor.DARK_GREEN, - new String[]{"§0"}) - ); - assertNoNextPacket(context); - - context.translate( - setScoreTranslator, - new ClientboundSetScorePacket( - "§0", - "sb-0", - 10 - ).withDisplay(Component.empty()) - ); - assertNextPacket(context, () -> { - var packet = new SetScorePacket(); - packet.setAction(SetScorePacket.Action.SET); - packet.setInfos(List.of(new ScoreInfo(1, "0", 10, "§2§aScore: 10§r§2§r§2"))); - return packet; - }); - assertNoNextPacket(context); - }); - } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f19ed7678..0f6d1faf5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-common = "3.0.0.Beta6-20250324.162731-5" protocol-codec = "3.0.0.Beta6-20250324.162731-5" raknet = "1.0.0.CR3-20250218.160705-18" minecraftauth = "4.1.1" -mcprotocollib = "1.21.4-20250311.232133-24" +mcprotocollib = "1.21.5-SNAPSHOT" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2"