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 05024f274..af3aecd18 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -967,6 +967,7 @@ public final class EntityDefinitions { .type(EntityType.COW) .height(1.4f).width(0.9f) .properties(VanillaEntityProperties.CLIMATE_VARIANT) + .addTranslator(MetadataTypes.COW_VARIANT, CowEntity::setVariant) .build(); FOX = EntityDefinition.inherited(FoxEntity::new, ageableEntityBase) .type(EntityType.FOX) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/farm/TemperatureVariantAnimal.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/farm/TemperatureVariantAnimal.java index 7b675ef98..e6dc63e72 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/farm/TemperatureVariantAnimal.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/farm/TemperatureVariantAnimal.java @@ -62,9 +62,12 @@ public abstract class TemperatureVariantAnimal extends AnimalEntity { } else { animalVariant = BuiltInVariant.TEMPERATE; } + // TODO does this work? dirtyMetadata.put(EntityDataTypes.VARIANT, animalVariant.ordinal()); } + // Ordered by bedrock id + // TODO: are these ordered correctly? Does the order differ for mobs? public enum BuiltInVariant { COLD, TEMPERATE, diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java index fb53c18ed..b5f7ffb19 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.entity.type.living.animal.tameable; +import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; @@ -34,16 +35,21 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.registry.JavaRegistries; +import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import java.util.Locale; import java.util.UUID; +import java.util.function.Function; public class CatEntity extends TameableEntity { @@ -81,17 +87,17 @@ public class CatEntity extends TameableEntity { updateCollarColor(); } + // TODO this is a holder when MCPL updates + // TODO also checks if this works public void setCatVariant(IntEntityMetadata entityMetadata) { // Different colors in Java and Bedrock for some reason int metadataValue = entityMetadata.getPrimitiveValue(); - int variantColor = switch (metadataValue) { - case 0 -> 8; - case 8 -> 0; - case 9 -> 10; - case 10 -> 9; - default -> metadataValue; - }; - dirtyMetadata.put(EntityDataTypes.VARIANT, variantColor); + + BuiltInVariant variant = JavaRegistries.CAT_VARIANT.fromNetworkId(session, metadataValue); + if (variant == null) { + variant = BuiltInVariant.BLACK; // Default variant on Java + } + dirtyMetadata.put(EntityDataTypes.VARIANT, variant.ordinal()); } public void setResting(BooleanEntityMetadata entityMetadata) { @@ -138,4 +144,38 @@ public class CatEntity extends TameableEntity { return !canEat(itemInHand) || health >= maxHealth && tamed ? InteractionResult.PASS : InteractionResult.SUCCESS; } } + + // Ordered by bedrock id + // TODO: are these ordered correctly? + // TODO lessen code duplication with other variant mobs + public enum BuiltInVariant { + WHITE, + BLACK, + RED, + SIAMESE, + BRITISH_SHORTHAIR, + CALICO, + PERSIAN, + RAGDOLL, + TABBY, + ALL_BLACK, + JELLIE; + + public static final Function READER = context -> getByJavaIdentifier(context.id()); + + private final Key javaIdentifier; + + BuiltInVariant() { + javaIdentifier = MinecraftKey.key(name().toLowerCase(Locale.ROOT)); + } + + public static @Nullable BuiltInVariant getByJavaIdentifier(Key identifier) { + for (BuiltInVariant variant : values()) { + if (variant.javaIdentifier.equals(identifier)) { + return variant; + } + } + return null; + } + } } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java index 979da99fb..49e0d5566 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java @@ -39,6 +39,7 @@ import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; import org.cloudburstmc.protocol.bedrock.data.TrimPattern; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.entity.type.living.animal.farm.TemperatureVariantAnimal; +import org.geysermc.geyser.entity.type.living.animal.tameable.CatEntity; import org.geysermc.geyser.entity.type.living.animal.tameable.WolfEntity; import org.geysermc.geyser.inventory.item.BannerPattern; import org.geysermc.geyser.inventory.item.GeyserInstrument; @@ -95,6 +96,8 @@ public final class RegistryCache { register("banner_pattern", cache -> cache.bannerPatterns, context -> BannerPattern.getByJavaIdentifier(context.id())); register("wolf_variant", cache -> cache.wolfVariants, context -> WolfEntity.BuiltInWolfVariant.getByJavaIdentifier(context.id().asString())); + register(JavaRegistries.CAT_VARIANT, cache -> cache.catVariants, CatEntity.BuiltInVariant.READER); + register(JavaRegistries.PIG_VARIANT, cache -> cache.pigVariants, TemperatureVariantAnimal.BuiltInVariant.READER); register(JavaRegistries.COW_VARIANT, cache -> cache.cowVariants, TemperatureVariantAnimal.BuiltInVariant.READER); register(JavaRegistries.CHICKEN_VARIANT, cache -> cache.chickenVariants, TemperatureVariantAnimal.BuiltInVariant.READER); @@ -136,9 +139,11 @@ public final class RegistryCache { private final JavaRegistry trimPatterns = new SimpleJavaRegistry<>(); private final JavaRegistry bannerPatterns = new SimpleJavaRegistry<>(); - private final JavaRegistry wolfVariants = new SimpleJavaRegistry<>(); private final JavaRegistry instruments = new SimpleJavaRegistry<>(); + private final JavaRegistry wolfVariants = new SimpleJavaRegistry<>(); + private final JavaRegistry catVariants = new SimpleJavaRegistry<>(); + private final JavaRegistry pigVariants = new SimpleJavaRegistry<>(); private final JavaRegistry cowVariants = new SimpleJavaRegistry<>(); private final JavaRegistry chickenVariants = new SimpleJavaRegistry<>(); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistries.java b/core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistries.java index 224c60348..fd195b38a 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistries.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistries.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.session.cache.registry; import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.entity.type.living.animal.farm.TemperatureVariantAnimal; +import org.geysermc.geyser.entity.type.living.animal.tameable.CatEntity; import org.geysermc.geyser.inventory.item.BannerPattern; import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.item.type.Item; @@ -51,6 +52,7 @@ public class JavaRegistries { public static final JavaRegistryKey ITEM = create("item", Registries.JAVA_ITEMS, Item::javaId); public static final JavaRegistryKey ENCHANTMENT = create("enchantment", RegistryCache::enchantments); public static final JavaRegistryKey BANNER_PATTERN = create("banner_pattern", RegistryCache::bannerPatterns); + public static final JavaRegistryKey CAT_VARIANT = create("cat_variant", RegistryCache::catVariants); public static final JavaRegistryKey PIG_VARIANT = create("pig_variant", RegistryCache::pigVariants); public static final JavaRegistryKey COW_VARIANT = create("cow_variant", RegistryCache::cowVariants); public static final JavaRegistryKey CHICKEN_VARIANT = create("chicken_variant", RegistryCache::chickenVariants);