From e78b24830de8a72ce6e66867050d073e66503bd1 Mon Sep 17 00:00:00 2001 From: Eclipse Date: Tue, 22 Oct 2024 22:31:37 +0000 Subject: [PATCH] Improve tag loading and load non-vanilla tags as well (#4849) * Work on new tag system, still largely unfinished * Continue work on new tag system, closer to testing now * Add holderset class for geyser * My IDE did some stuff it shouldn't have done * Add is method for HolderSets to TagCache * Add some documentation * Fix build and slightly adjust documentation * Fix some issues, still broken * Fix more issues with registering vanilla tags, works better now * Fix all issues with vanilla and non-vanilla tags, fix documentation a bit. * Small cleanup * Use IllegalArgumentException instead of asserting and make TagRegistry#getVanillaTags return original map * Generics - still untested * Remove different lookups for vanilla- and non-vanilla tags * Add toNetworkId and fromNetworkId methods to JavaRegistryKey, simplify TagCache * More cleanup, add documentation * Fix registry loading * Rename HolderSet to GeyserHolderSet and address reviews by camotoy * Make holder set reader method not throw an exception, clean up * Make holder set reader warn when failing to read * Add comment to make clearer why a cast is make --------- Co-authored-by: chris --- .../type/living/animal/AnimalEntity.java | 7 +- .../type/living/animal/ArmadilloEntity.java | 4 +- .../type/living/animal/AxolotlEntity.java | 4 +- .../entity/type/living/animal/BeeEntity.java | 4 +- .../type/living/animal/ChickenEntity.java | 4 +- .../entity/type/living/animal/CowEntity.java | 4 +- .../entity/type/living/animal/FoxEntity.java | 4 +- .../entity/type/living/animal/FrogEntity.java | 4 +- .../entity/type/living/animal/GoatEntity.java | 4 +- .../type/living/animal/HoglinEntity.java | 4 +- .../type/living/animal/OcelotEntity.java | 4 +- .../type/living/animal/PandaEntity.java | 4 +- .../entity/type/living/animal/PigEntity.java | 4 +- .../type/living/animal/PolarBearEntity.java | 5 +- .../type/living/animal/RabbitEntity.java | 4 +- .../type/living/animal/SheepEntity.java | 6 +- .../type/living/animal/SnifferEntity.java | 4 +- .../type/living/animal/StriderEntity.java | 4 +- .../type/living/animal/TurtleEntity.java | 4 +- .../animal/horse/AbstractHorseEntity.java | 4 +- .../type/living/animal/horse/CamelEntity.java | 4 +- .../type/living/animal/horse/LlamaEntity.java | 4 +- .../living/animal/tameable/CatEntity.java | 4 +- .../living/animal/tameable/ParrotEntity.java | 3 +- .../living/animal/tameable/WolfEntity.java | 4 +- .../updater/AnvilInventoryUpdater.java | 14 +- .../geyser/item/enchantment/Enchantment.java | 37 +- .../geyser/session/GeyserSession.java | 2 +- .../geyser/session/cache/RegistryCache.java | 48 +-- .../geyser/session/cache/TagCache.java | 140 +++--- .../cache/registry/JavaRegistries.java | 112 +++++ .../cache/registry/JavaRegistryKey.java | 86 ++++ .../geyser/session/cache/tags/BlockTag.java | 399 +++++++++--------- .../session/cache/tags/EnchantmentTag.java | 102 ++--- .../session/cache/tags/GeyserHolderSet.java | 118 ++++++ .../geyser/session/cache/tags/ItemTag.java | 324 +++++++------- .../geyser/session/cache/tags/Tag.java | 35 ++ 37 files changed, 927 insertions(+), 595 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistries.java create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistryKey.java create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/tags/GeyserHolderSet.java create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/tags/Tag.java diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java index 2e627b461..57cbdc783 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java @@ -33,8 +33,9 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.living.AgeableEntity; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; -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.mcprotocollib.protocol.data.game.entity.player.Hand; @@ -48,7 +49,7 @@ public abstract class AnimalEntity extends AgeableEntity { } protected final boolean canEat(GeyserItemStack itemStack) { - ItemTag tag = getFoodTag(); + Tag tag = getFoodTag(); if (tag == null) { return false; } @@ -58,7 +59,7 @@ public abstract class AnimalEntity extends AgeableEntity { /** * @return the tag associated with this animal for eating food. Null for nothing or different behavior. */ - protected abstract @Nullable ItemTag getFoodTag(); + protected abstract @Nullable Tag getFoodTag(); @NonNull @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java index 968520bb6..2b443f5e4 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java @@ -28,8 +28,10 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ArmadilloState; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; @@ -75,7 +77,7 @@ public class ArmadilloEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.ARMADILLO_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java index a0ab56ead..0a87f59bc 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java @@ -32,8 +32,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; @@ -62,7 +64,7 @@ public class AxolotlEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.AXOLOTL_FOOD; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java index 4fcf0e178..5f8956b6a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java @@ -32,8 +32,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; @@ -69,7 +71,7 @@ public class BeeEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.BEE_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java index 075a49923..0c8e437c8 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java @@ -28,8 +28,10 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import java.util.UUID; @@ -41,7 +43,7 @@ public class ChickenEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.CHICKEN_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java index 64e7de193..66210068b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java @@ -33,8 +33,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; 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.mcprotocollib.protocol.data.game.entity.player.Hand; @@ -69,7 +71,7 @@ public class CowEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.COW_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java index e20031baa..b140b7956 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java @@ -30,8 +30,10 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; @@ -57,7 +59,7 @@ public class FoxEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.FOX_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java index 120bfcdd4..a0b909b75 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java @@ -31,8 +31,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Entity; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; @@ -77,7 +79,7 @@ public class FrogEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.FROG_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java index 4e919b81c..b5e4ad117 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java @@ -34,8 +34,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; 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.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; @@ -99,7 +101,7 @@ public class GoatEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.GOAT_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java index cc23fc607..b506f1425 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java @@ -30,8 +30,10 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; @@ -58,7 +60,7 @@ public class HoglinEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.HOGLIN_FOOD; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java index 9d6d33227..c45092b02 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java @@ -31,8 +31,10 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; 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.mcprotocollib.protocol.data.game.entity.player.Hand; @@ -47,7 +49,7 @@ public class OcelotEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.OCELOT_FOOD; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java index aaa7c2d7e..022e58bc0 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java @@ -34,8 +34,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; 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.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; @@ -90,7 +92,7 @@ public class PandaEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.PANDA_FOOD; } 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 2ec23d673..b8ba2c94f 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 @@ -38,9 +38,11 @@ import org.geysermc.geyser.entity.vehicle.BoostableVehicleComponent; import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.entity.vehicle.VehicleComponent; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +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; @@ -58,7 +60,7 @@ public class PigEntity extends AnimalEntity implements Tickable, ClientVehicle { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.PIG_FOOD; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java index 0e83615f7..900878dbd 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java @@ -28,8 +28,9 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import java.util.UUID; @@ -41,7 +42,7 @@ public class PolarBearEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return null; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java index fbfc5d40a..dca6fe5ff 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java @@ -31,8 +31,10 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; @@ -79,7 +81,7 @@ public class RabbitEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.RABBIT_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java index 155ddf00c..e26b0be61 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java @@ -34,8 +34,10 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.DyeItem; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; 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.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; @@ -59,7 +61,7 @@ public class SheepEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.SHEEP_FOOD; } @@ -103,4 +105,4 @@ public class SheepEntity extends AnimalEntity { private boolean canDye(GeyserItemStack item) { return item.asItem() instanceof DyeItem dyeItem && dyeItem.dyeColor() != this.color && !getFlag(EntityFlag.SHEARED); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java index 11fee5bbf..203a48f19 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java @@ -35,8 +35,10 @@ import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Tickable; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.SnifferState; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; @@ -73,7 +75,7 @@ public class SnifferEntity extends AnimalEntity implements Tickable { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.SNIFFER_FOOD; } 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 e06af2786..62318e255 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 @@ -39,9 +39,11 @@ import org.geysermc.geyser.entity.vehicle.BoostableVehicleComponent; import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.entity.vehicle.VehicleComponent; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +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; @@ -105,7 +107,7 @@ public class StriderEntity extends AnimalEntity implements Tickable, ClientVehic @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.STRIDER_FOOD; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java index ae7f2d2bd..1f700f12b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java @@ -29,8 +29,10 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; @@ -51,7 +53,7 @@ public class TurtleEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.TURTLE_FOOD; } 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 ddc212053..100a29299 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 @@ -39,8 +39,10 @@ import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.type.living.animal.AnimalEntity; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; 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.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; @@ -119,7 +121,7 @@ public class AbstractHorseEntity extends AnimalEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.HORSE_FOOD; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java index b83a85bfb..ca39bd1e6 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java @@ -35,12 +35,14 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.vehicle.CamelVehicleComponent; import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.entity.vehicle.VehicleComponent; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.Attribute; import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; @@ -100,7 +102,7 @@ public class CamelEntity extends AbstractHorseEntity implements ClientVehicle { } @Override - protected @Nullable ItemTag getFoodTag() { + protected @Nullable Tag getFoodTag() { return ItemTag.CAMEL_FOOD; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java index 76939ceb9..d27a1fff3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java @@ -30,8 +30,10 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.geyser.util.MathUtils; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; @@ -56,7 +58,7 @@ public class LlamaEntity extends ChestedHorseEntity { } @Override - protected @Nullable ItemTag getFoodTag() { + protected @Nullable Tag getFoodTag() { return ItemTag.LLAMA_FOOD; } } 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 bf1555e9d..fb53c18ed 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 @@ -32,8 +32,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; 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.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; @@ -109,7 +111,7 @@ public class CatEntity extends TameableEntity { } @Override - protected @Nullable ItemTag getFoodTag() { + protected @Nullable Tag getFoodTag() { return ItemTag.CAT_FOOD; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java index 69b19b1b9..95e9c901b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java @@ -34,6 +34,7 @@ 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.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.mcprotocollib.protocol.data.game.entity.player.Hand; @@ -47,7 +48,7 @@ public class ParrotEntity extends TameableEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return null; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java index e7fde2be8..f0b554ef9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java @@ -36,8 +36,10 @@ import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.enchantment.EnchantmentComponent; import org.geysermc.geyser.item.type.DyeItem; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; 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.ItemUtils; @@ -116,7 +118,7 @@ public class WolfEntity extends TameableEntity { @Override @Nullable - protected ItemTag getFoodTag() { + protected Tag getFoodTag() { return ItemTag.WOLF_FOOD; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index dc532cc62..0ffb74082 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -41,17 +41,15 @@ import org.geysermc.geyser.inventory.item.BedrockEnchantment; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.session.cache.tags.EnchantmentTag; -import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.ItemUtils; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.IntStream; @@ -314,14 +312,10 @@ public class AnvilInventoryUpdater extends InventoryUpdater { for (Object2IntMap.Entry entry : getEnchantments(session, material).object2IntEntrySet()) { Enchantment enchantment = entry.getKey(); - HolderSet supportedItems = enchantment.supportedItems(); - int[] supportedItemIds = supportedItems.resolve(tagId -> session.getTagCache().get(ItemTag.ALL_ITEM_TAGS.get(tagId))); - boolean canApply = isEnchantedBook(input) || IntStream.of(supportedItemIds).anyMatch(id -> id == input.getJavaId()); + boolean canApply = isEnchantedBook(input) || session.getTagCache().is(enchantment.supportedItems(), input.asItem()); - HolderSet exclusiveSet = enchantment.exclusiveSet(); - int[] incompatibleEnchantments = exclusiveSet.resolve(tagId -> session.getTagCache().get(EnchantmentTag.ALL_ENCHANTMENT_TAGS.get(tagId))); - for (int i : incompatibleEnchantments) { - Enchantment incompatible = session.getRegistryCache().enchantments().byId(i); + List incompatibleEnchantments = enchantment.exclusiveSet().resolve(session); + for (Enchantment incompatible : incompatibleEnchantments) { if (combinedEnchantments.containsKey(incompatible)) { canApply = false; if (!bedrock) { diff --git a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java index 301f69a5f..9088d9626 100644 --- a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java +++ b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java @@ -25,23 +25,20 @@ package org.geysermc.geyser.item.enchantment; -import it.unimi.dsi.fastutil.ints.IntArrays; -import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.inventory.item.BedrockEnchantment; import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.session.cache.registry.JavaRegistries; import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; +import org.geysermc.geyser.session.cache.tags.GeyserHolderSet; import org.geysermc.geyser.translator.text.MessageTranslator; -import org.geysermc.geyser.util.MinecraftKey; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; -import java.util.function.ToIntFunction; /** * @param description only populated if {@link #bedrockEnchantment()} is not null. @@ -49,23 +46,23 @@ import java.util.function.ToIntFunction; */ public record Enchantment(String identifier, Set effects, - HolderSet supportedItems, + GeyserHolderSet supportedItems, int maxLevel, String description, int anvilCost, - HolderSet exclusiveSet, + GeyserHolderSet exclusiveSet, @Nullable BedrockEnchantment bedrockEnchantment) { public static Enchantment read(RegistryEntryContext context) { NbtMap data = context.data(); Set effects = readEnchantmentComponents(data.getCompound("effects")); - HolderSet supportedItems = readHolderSet(data.get("supported_items"), itemId -> Registries.JAVA_ITEM_IDENTIFIERS.getOrDefault(itemId.asString(), Items.AIR).javaId()); + GeyserHolderSet supportedItems = GeyserHolderSet.readHolderSet(context.session(), JavaRegistries.ITEM, data.get("supported_items"), itemId -> Registries.JAVA_ITEM_IDENTIFIERS.getOrDefault(itemId.asString(), Items.AIR).javaId()); int maxLevel = data.getInt("max_level"); int anvilCost = data.getInt("anvil_cost"); - HolderSet exclusiveSet = readHolderSet(data.getOrDefault("exclusive_set", null), context::getNetworkId); + GeyserHolderSet exclusiveSet = GeyserHolderSet.readHolderSet(context.session(), JavaRegistries.ENCHANTMENT, data.get("exclusive_set"), context::getNetworkId); BedrockEnchantment bedrockEnchantment = BedrockEnchantment.getByJavaIdentifier(context.id().asString()); @@ -86,24 +83,4 @@ public record Enchantment(String identifier, } return Set.copyOf(components); // Also ensures any empty sets are consolidated } - - // TODO holder set util? - private static HolderSet readHolderSet(@Nullable Object holderSet, ToIntFunction keyIdMapping) { - if (holderSet == null) { - return new HolderSet(IntArrays.EMPTY_ARRAY); - } - - if (holderSet instanceof String stringTag) { - // Tag - if (stringTag.startsWith("#")) { - return new HolderSet(MinecraftKey.key(stringTag.substring(1))); // Remove '#' at beginning that indicates tag - } else { - return new HolderSet(new int[]{keyIdMapping.applyAsInt(MinecraftKey.key(stringTag))}); - } - } else if (holderSet instanceof List list) { - // Assume the list is a list of strings - return new HolderSet(list.stream().map(o -> (String) o).map(Key::key).mapToInt(keyIdMapping).toArray()); - } - throw new IllegalArgumentException("Holder set must either be a tag, a string ID or a list of string IDs"); - } } diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index bf396a3c3..fb64cfc41 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -679,7 +679,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { this.registryCache = new RegistryCache(this); this.skullCache = new SkullCache(this); this.structureBlockCache = new StructureBlockCache(); - this.tagCache = new TagCache(); + this.tagCache = new TagCache(this); this.worldCache = new WorldCache(this); this.cameraData = new GeyserCameraData(this); this.entityData = new GeyserEntityData(this); 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 4a4167f15..fcbc7c64c 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 @@ -46,7 +46,9 @@ import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.JukeboxSong; import org.geysermc.geyser.level.PaintingType; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.registry.JavaRegistries; import org.geysermc.geyser.session.cache.registry.JavaRegistry; +import org.geysermc.geyser.session.cache.registry.JavaRegistryKey; import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; import org.geysermc.geyser.session.cache.registry.SimpleJavaRegistry; import org.geysermc.geyser.text.ChatDecoration; @@ -74,35 +76,34 @@ import java.util.function.ToIntFunction; @Accessors(fluent = true) @Getter public final class RegistryCache { - private static final Map> DEFAULTS; - private static final Map>> REGISTRIES = new HashMap<>(); + private static final Map, Map> DEFAULTS; + private static final Map, BiConsumer>> REGISTRIES = new HashMap<>(); static { - register("chat_type", cache -> cache.chatTypes, ChatDecoration::readChatType); - register("dimension_type", cache -> cache.dimensions, JavaDimension::read); - register("enchantment", cache -> cache.enchantments, Enchantment::read); - register("jukebox_song", cache -> cache.jukeboxSongs, JukeboxSong::read); - register("painting_variant", cache -> cache.paintings, context -> PaintingType.getByName(context.id())); - register("trim_material", cache -> cache.trimMaterials, TrimRecipe::readTrimMaterial); - register("trim_pattern", cache -> cache.trimPatterns, TrimRecipe::readTrimPattern); - register("worldgen/biome", (cache, array) -> cache.biomeTranslations = array, BiomeTranslator::loadServerBiome); - 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.CHAT_TYPE, cache -> cache.chatTypes, ChatDecoration::readChatType); + register(JavaRegistries.DIMENSION_TYPE, cache -> cache.dimensions, JavaDimension::read); + register(JavaRegistries.ENCHANTMENT, cache -> cache.enchantments, Enchantment::read); + register(JavaRegistries.JUKEBOX_SONG, cache -> cache.jukeboxSongs, JukeboxSong::read); + register(JavaRegistries.PAINTING_VARIANT, cache -> cache.paintings, context -> PaintingType.getByName(context.id())); + register(JavaRegistries.TRIM_MATERIAL, cache -> cache.trimMaterials, TrimRecipe::readTrimMaterial); + register(JavaRegistries.TRIM_PATTERN, cache -> cache.trimPatterns, TrimRecipe::readTrimPattern); + register(JavaRegistries.BIOME, (cache, array) -> cache.biomeTranslations = array, BiomeTranslator::loadServerBiome); + register(JavaRegistries.BANNER_PATTERN, cache -> cache.bannerPatterns, context -> BannerPattern.getByJavaIdentifier(context.id())); + register(JavaRegistries.WOLF_VARIANT, cache -> cache.wolfVariants, context -> WolfEntity.BuiltInWolfVariant.getByJavaIdentifier(context.id().asString())); // Load from MCProtocolLib's classloader NbtMap tag = MinecraftProtocol.loadNetworkCodec(); - Map> defaults = new HashMap<>(); + Map, Map> defaults = new HashMap<>(); // Don't create a keySet - no need to create the cached object in HashMap if we don't use it again - REGISTRIES.forEach((key, $) -> { - List rawValues = tag.getCompound(key.asString()) - .getList("value", NbtType.COMPOUND); + REGISTRIES.forEach((registry, $) -> { + List rawValues = tag.getCompound(registry.registryKey().asString()).getList("value", NbtType.COMPOUND); Map values = new HashMap<>(); for (NbtMap value : rawValues) { Key name = MinecraftKey.key(value.getString("name")); values.put(name, value.getCompound("element")); } // Can make these maps immutable and as efficient as possible after initialization - defaults.put(key, Map.copyOf(values)); + defaults.put(registry, Map.copyOf(values)); }); DEFAULTS = Map.copyOf(defaults); @@ -137,7 +138,7 @@ public final class RegistryCache { * Loads a registry in, if we are tracking it. */ public void load(ClientboundRegistryDataPacket packet) { - var reader = REGISTRIES.get(packet.getRegistry()); + var reader = REGISTRIES.get(JavaRegistries.fromKey(packet.getRegistry())); if (reader != null) { reader.accept(this, packet.getEntries()); } else { @@ -151,9 +152,8 @@ public final class RegistryCache { * @param reader converts the RegistryEntry NBT into a class file * @param the class that represents these entries. */ - private static void register(String registry, Function> localCacheFunction, Function reader) { - Key registryKey = MinecraftKey.key(registry); - REGISTRIES.put(registryKey, (registryCache, entries) -> { + private static void register(JavaRegistryKey registry, Function> localCacheFunction, Function reader) { + REGISTRIES.put(registry, (registryCache, entries) -> { Map localRegistry = null; JavaRegistry localCache = localCacheFunction.apply(registryCache); // Clear each local cache every time a new registry entry is given to us @@ -172,7 +172,7 @@ public final class RegistryCache { // If the data is null, that's the server telling us we need to use our default values. if (entry.getData() == null) { if (localRegistry == null) { // Lazy initialize - localRegistry = DEFAULTS.get(registryKey); + localRegistry = DEFAULTS.get(registry); } entry = new RegistryEntry(entry.getId(), localRegistry.get(entry.getId())); } @@ -189,8 +189,8 @@ public final class RegistryCache { /** * @param localCacheFunction the int array to set the final values to. */ - private static void register(String registry, BiConsumer localCacheFunction, ToIntFunction reader) { - REGISTRIES.put(MinecraftKey.key(registry), (registryCache, entries) -> { + private static void register(JavaRegistryKey registry, BiConsumer localCacheFunction, ToIntFunction reader) { + REGISTRIES.put(registry, (registryCache, entries) -> { Int2IntMap temp = new Int2IntOpenHashMap(); int greatestId = 0; for (int i = 0; i < entries.size(); i++) { diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java index f4d69dcdb..f01ef64c5 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java @@ -26,116 +26,114 @@ package org.geysermc.geyser.session.cache; import it.unimi.dsi.fastutil.ints.IntArrays; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.kyori.adventure.key.Key; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.type.Item; -import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.session.cache.tags.BlockTag; -import org.geysermc.geyser.session.cache.tags.EnchantmentTag; -import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.session.cache.registry.JavaRegistries; +import org.geysermc.geyser.session.cache.registry.JavaRegistryKey; +import org.geysermc.geyser.session.cache.tags.GeyserHolderSet; +import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.geyser.util.MinecraftKey; -import org.geysermc.geyser.util.Ordered; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; import javax.annotation.ParametersAreNonnullByDefault; import java.util.Arrays; +import java.util.List; import java.util.Map; -import static org.geysermc.geyser.session.cache.tags.BlockTag.ALL_BLOCK_TAGS; -import static org.geysermc.geyser.session.cache.tags.EnchantmentTag.ALL_ENCHANTMENT_TAGS; -import static org.geysermc.geyser.session.cache.tags.ItemTag.ALL_ITEM_TAGS; - /** * Manages information sent from the {@link ClientboundUpdateTagsPacket}. If that packet is not sent, all lists here - * will remain empty, matching Java Edition behavior. + * will remain empty, matching Java Edition behavior. Looking up a tag that wasn't listed in that packet will return an empty array. + * Only tags from suitable registries in {@link JavaRegistries} are stored. Read {@link JavaRegistryKey} for more information. */ @ParametersAreNonnullByDefault public final class TagCache { - private final int[][] blocks = new int[ALL_BLOCK_TAGS.size()][]; - private final int[][] items = new int[ALL_ITEM_TAGS.size()][]; - private final int[][] enchantments = new int[ALL_ENCHANTMENT_TAGS.size()][]; + private final GeyserSession session; + private final Map, int[]> tags = new Object2ObjectOpenHashMap<>(); + + public TagCache(GeyserSession session) { + this.session = session; + } public void loadPacket(GeyserSession session, ClientboundUpdateTagsPacket packet) { - Map blockTags = packet.getTags().get(MinecraftKey.key("block")); - loadTags("Block", blockTags, ALL_BLOCK_TAGS, this.blocks); - - // Hack btw + Map> allTags = packet.getTags(); GeyserLogger logger = session.getGeyser().getLogger(); - int[] convertableToMud = blockTags.get(MinecraftKey.key("convertable_to_mud")); - boolean emulatePost1_18Logic = convertableToMud != null && convertableToMud.length != 0; - session.setEmulatePost1_18Logic(emulatePost1_18Logic); - if (logger.isDebug()) { - logger.debug("Emulating post 1.18 block predication logic for " + session.bedrockUsername() + "? " + emulatePost1_18Logic); - } - Map itemTags = packet.getTags().get(MinecraftKey.key("item")); - loadTags("Item", itemTags, ALL_ITEM_TAGS, this.items); + this.tags.clear(); - // Hack btw - boolean emulatePost1_13Logic = itemTags.get(MinecraftKey.key("signs")).length > 1; - session.setEmulatePost1_13Logic(emulatePost1_13Logic); - if (logger.isDebug()) { - logger.debug("Emulating post 1.13 villager logic for " + session.bedrockUsername() + "? " + emulatePost1_13Logic); - } - - Map enchantmentTags = packet.getTags().get(MinecraftKey.key("enchantment")); - loadTags("Enchantment", enchantmentTags, ALL_ENCHANTMENT_TAGS, this.enchantments); - } - - private void loadTags(String type, @Nullable Map packetTags, Map allTags, int[][] localValues) { - if (packetTags == null) { - Arrays.fill(localValues, IntArrays.EMPTY_ARRAY); - GeyserImpl.getInstance().getLogger().debug("Not loading " + type + " tags; they do not exist here."); - return; - } - allTags.forEach((location, tag) -> { - int[] values = packetTags.get(location); - if (values != null) { - if (values.length != 0) { - localValues[tag.ordinal()] = values; - } else { - localValues[tag.ordinal()] = IntArrays.EMPTY_ARRAY; - } - } else { - localValues[tag.ordinal()] = IntArrays.EMPTY_ARRAY; - GeyserImpl.getInstance().getLogger().debug(type + " tag not found from server: " + location); + for (Key registryKey : allTags.keySet()) { + JavaRegistryKey registry = JavaRegistries.fromKey(registryKey); + if (registry == null || !registry.shouldStoreTags()) { + logger.debug("Not loading tags for registry " + registryKey + " (registry not listed in JavaRegistries, or was not suitable to load tags)"); + continue; } - }); + + Map registryTags = allTags.get(registryKey); + + if (registry == JavaRegistries.BLOCK) { + // Hack btw + int[] convertableToMud = registryTags.get(MinecraftKey.key("convertable_to_mud")); + boolean emulatePost1_18Logic = convertableToMud != null && convertableToMud.length != 0; + session.setEmulatePost1_18Logic(emulatePost1_18Logic); + if (logger.isDebug()) { + logger.debug("Emulating post 1.18 block predication logic for " + session.bedrockUsername() + "? " + emulatePost1_18Logic); + } + } else if (registry == JavaRegistries.ITEM) { + // Hack btw + boolean emulatePost1_13Logic = registryTags.get(MinecraftKey.key("signs")).length > 1; + session.setEmulatePost1_13Logic(emulatePost1_13Logic); + if (logger.isDebug()) { + logger.debug("Emulating post 1.13 villager logic for " + session.bedrockUsername() + "? " + emulatePost1_13Logic); + } + } + + loadTags(registryTags, registry); + } } - /** - * @return true if the block tag is present and contains this block mapping's Java ID. - */ - public boolean is(BlockTag tag, Block block) { - int[] values = this.blocks[tag.ordinal()]; - return contains(values, block.javaId()); + private void loadTags(Map packetTags, JavaRegistryKey registry) { + for (Map.Entry tag : packetTags.entrySet()) { + this.tags.put(new Tag<>(registry, tag.getKey()), tag.getValue()); + } + } + + public boolean is(Tag tag, T object) { + return contains(getRaw(tag), tag.registry().toNetworkId(session, object)); } /** * @return true if the item tag is present and contains this item stack's Java ID. */ - public boolean is(ItemTag tag, GeyserItemStack itemStack) { + public boolean is(Tag tag, GeyserItemStack itemStack) { return is(tag, itemStack.asItem()); } /** - * @return true if the item tag is present and contains this item's Java ID. + * @return true if the specified network ID is in the given holder set. */ - public boolean is(ItemTag tag, Item item) { - int[] values = this.items[tag.ordinal()]; - return contains(values, item.javaId()); + public boolean is(GeyserHolderSet holderSet, T object) { + return contains(holderSet.resolveRaw(this), holderSet.getRegistry().toNetworkId(session, object)); } - public int[] get(ItemTag itemTag) { - return this.items[itemTag.ordinal()]; + public List get(Tag tag) { + return mapRawArray(session, getRaw(tag), tag.registry()); } - public int[] get(EnchantmentTag enchantmentTag) { - return this.enchantments[enchantmentTag.ordinal()]; + /** + * @return the network IDs in the given tag. This can be an empty list. + */ + public int[] getRaw(Tag tag) { + return this.tags.getOrDefault(tag, IntArrays.EMPTY_ARRAY); + } + + /** + * Maps a raw array of network IDs to their respective objects. + */ + public static List mapRawArray(GeyserSession session, int[] array, JavaRegistryKey registry) { + return Arrays.stream(array).mapToObj(i -> registry.fromNetworkId(session, i)).toList(); } private static boolean contains(int[] array, int i) { 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 new file mode 100644 index 000000000..cb51f488e --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistries.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.session.cache.registry; + +import net.kyori.adventure.key.Key; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; +import org.cloudburstmc.protocol.bedrock.data.TrimPattern; +import org.geysermc.geyser.entity.type.living.animal.tameable.WolfEntity; +import org.geysermc.geyser.inventory.item.BannerPattern; +import org.geysermc.geyser.item.enchantment.Enchantment; +import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.level.JavaDimension; +import org.geysermc.geyser.level.JukeboxSong; +import org.geysermc.geyser.level.PaintingType; +import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.ListRegistry; +import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.session.cache.RegistryCache; +import org.geysermc.geyser.util.MinecraftKey; +import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatType; + +import java.util.ArrayList; +import java.util.List; + +/** + * Stores {@link JavaRegistryKey} for Java registries that are used for loading of data-driven objects, tags, or both. Read {@link JavaRegistryKey} for more information on how to use one. + */ +public class JavaRegistries { + private static final List> VALUES = new ArrayList<>(); + + public static final JavaRegistryKey BLOCK = create("block", BlockRegistries.JAVA_BLOCKS, Block::javaId); + public static final JavaRegistryKey ITEM = create("item", Registries.JAVA_ITEMS, Item::javaId); + public static final JavaRegistryKey CHAT_TYPE = create("chat_type", RegistryCache::chatTypes); + public static final JavaRegistryKey DIMENSION_TYPE = create("dimension_type", RegistryCache::dimensions); + public static final JavaRegistryKey ENCHANTMENT = create("enchantment", RegistryCache::enchantments); + public static final JavaRegistryKey JUKEBOX_SONG = create("jukebox_song", RegistryCache::jukeboxSongs); + public static final JavaRegistryKey PAINTING_VARIANT = create("painting_variant", RegistryCache::paintings); + public static final JavaRegistryKey TRIM_MATERIAL = create("trim_material", RegistryCache::trimMaterials); + public static final JavaRegistryKey TRIM_PATTERN = create("trim_pattern", RegistryCache::trimPatterns); + /** + * This registry should not be used in holder sets, tags, etc. It's simply used as a mapping from Java biomes to Bedrock ones. + */ + public static final JavaRegistryKey BIOME = create("worldgen/biome"); + public static final JavaRegistryKey BANNER_PATTERN = create("banner_pattern", RegistryCache::bannerPatterns); + public static final JavaRegistryKey WOLF_VARIANT = create("wolf_variant", RegistryCache::wolfVariants); + + private static JavaRegistryKey create(String key, JavaRegistryKey.NetworkSerializer networkSerializer, JavaRegistryKey.NetworkDeserializer networkDeserializer) { + JavaRegistryKey registry = new JavaRegistryKey<>(MinecraftKey.key(key), networkSerializer, networkDeserializer); + VALUES.add(registry); + return registry; + } + + private static JavaRegistryKey create(String key, ListRegistry registry, RegistryNetworkMapper networkSerializer) { + return create(key, (session, object) -> networkSerializer.get(object), (session, id) -> registry.get(id)); + } + + private static JavaRegistryKey create(String key, RegistryGetter getter) { + return create(key, (session, object) -> getter.get(session.getRegistryCache()).byValue(object), (session, id) -> getter.get(session.getRegistryCache()).byId(id)); + } + + private static JavaRegistryKey create(String key) { + // Cast for ambiguous call + return create(key, (JavaRegistryKey.NetworkSerializer) null, null); + } + + @Nullable + public static JavaRegistryKey fromKey(Key registryKey) { + for (JavaRegistryKey registry : VALUES) { + if (registry.registryKey().equals(registryKey)) { + return registry; + } + } + return null; + } + + @FunctionalInterface + interface RegistryGetter { + + JavaRegistry get(RegistryCache cache); + } + + @FunctionalInterface + interface RegistryNetworkMapper { + + int get(T object); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistryKey.java b/core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistryKey.java new file mode 100644 index 000000000..369bea7a4 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistryKey.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.session.cache.registry; + +import net.kyori.adventure.key.Key; +import org.geysermc.geyser.session.GeyserSession; + +import javax.annotation.Nullable; + +/** + * Defines a Java registry, which can be hardcoded or data-driven. This class doesn't store registry contents itself, that is handled by {@link org.geysermc.geyser.session.cache.RegistryCache} in the case of + * data-driven registries and other classes in the case of hardcoded registries. + * + *

This class is used when, for a Java registry, data-driven objects or tags need to be loaded. Only one instance of this class should be created for each Java registry. Instances of this + * class are kept in {@link JavaRegistries}, which also has useful methods for creating instances of this class. When only using a registry to load data-driven objects, the network (de)serializer parameters + * can be null. For tag loading however, these are required, as {@link org.geysermc.geyser.session.cache.TagCache} relies on their functionality.

+ * + * @param registryKey the registry key, as it appears on Java. + * @param networkSerializer a method that converts an object in this registry to its network ID. + * @param networkDeserializer a method that converts a network ID to an object in this registry. + * @param the object type this registry holds. + */ +public record JavaRegistryKey(Key registryKey, @Nullable NetworkSerializer networkSerializer, @Nullable NetworkDeserializer networkDeserializer) { + + /** + * Converts an object in this registry to its network ID. This will fail if this registry doesn't have a network serializer. + */ + public int toNetworkId(GeyserSession session, T object) { + if (networkSerializer == null) { + throw new UnsupportedOperationException("Registry does not hava a network serializer"); + } + return networkSerializer.toNetworkId(session, object); + } + + /** + * Converts a network ID to an object in this registry. This will fail if this registry doesn't have a network deserializer. + */ + public T fromNetworkId(GeyserSession session, int networkId) { + if (networkDeserializer == null) { + throw new UnsupportedOperationException("Registry does not hava a network deserializer"); + } + return networkDeserializer.fromNetworkId(session, networkId); + } + + /** + * @return true if this registry has a network serializer and deserializer. + */ + public boolean shouldStoreTags() { + return networkSerializer != null && networkDeserializer != null; + } + + @FunctionalInterface + public interface NetworkSerializer { + + int toNetworkId(GeyserSession session, T object); + } + + @FunctionalInterface + public interface NetworkDeserializer { + + T fromNetworkId(GeyserSession session, int networkId); + } +} 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 1dca7843a..6ad666780 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 @@ -25,214 +25,203 @@ package org.geysermc.geyser.session.cache.tags; -import net.kyori.adventure.key.Key; -import org.geysermc.geyser.util.Ordered; - -import java.util.HashMap; -import java.util.Map; +import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.session.cache.registry.JavaRegistries; +import org.geysermc.geyser.util.MinecraftKey; +/** + * Lists vanilla block tags. + */ @SuppressWarnings("unused") -public final class BlockTag implements Ordered { - public static final Map ALL_BLOCK_TAGS = new HashMap<>(); +public final class BlockTag { + public static final Tag WOOL = create("wool"); + public static final Tag PLANKS = create("planks"); + public static final Tag STONE_BRICKS = create("stone_bricks"); + public static final Tag WOODEN_BUTTONS = create("wooden_buttons"); + public static final Tag STONE_BUTTONS = create("stone_buttons"); + public static final Tag BUTTONS = create("buttons"); + public static final Tag WOOL_CARPETS = create("wool_carpets"); + public static final Tag WOODEN_DOORS = create("wooden_doors"); + public static final Tag MOB_INTERACTABLE_DOORS = create("mob_interactable_doors"); + public static final Tag WOODEN_STAIRS = create("wooden_stairs"); + public static final Tag WOODEN_SLABS = create("wooden_slabs"); + public static final Tag WOODEN_FENCES = create("wooden_fences"); + public static final Tag PRESSURE_PLATES = create("pressure_plates"); + public static final Tag WOODEN_PRESSURE_PLATES = create("wooden_pressure_plates"); + public static final Tag STONE_PRESSURE_PLATES = create("stone_pressure_plates"); + public static final Tag WOODEN_TRAPDOORS = create("wooden_trapdoors"); + public static final Tag DOORS = create("doors"); + public static final Tag SAPLINGS = create("saplings"); + public static final Tag LOGS_THAT_BURN = create("logs_that_burn"); + public static final Tag OVERWORLD_NATURAL_LOGS = create("overworld_natural_logs"); + public static final Tag LOGS = create("logs"); + public static final Tag DARK_OAK_LOGS = create("dark_oak_logs"); + public static final Tag OAK_LOGS = create("oak_logs"); + public static final Tag BIRCH_LOGS = create("birch_logs"); + public static final Tag ACACIA_LOGS = create("acacia_logs"); + public static final Tag CHERRY_LOGS = create("cherry_logs"); + public static final Tag JUNGLE_LOGS = create("jungle_logs"); + public static final Tag SPRUCE_LOGS = create("spruce_logs"); + public static final Tag MANGROVE_LOGS = create("mangrove_logs"); + public static final Tag CRIMSON_STEMS = create("crimson_stems"); + public static final Tag WARPED_STEMS = create("warped_stems"); + public static final Tag BAMBOO_BLOCKS = create("bamboo_blocks"); + public static final Tag WART_BLOCKS = create("wart_blocks"); + public static final Tag BANNERS = create("banners"); + public static final Tag SAND = create("sand"); + public static final Tag SMELTS_TO_GLASS = create("smelts_to_glass"); + public static final Tag STAIRS = create("stairs"); + public static final Tag SLABS = create("slabs"); + public static final Tag WALLS = create("walls"); + public static final Tag ANVIL = create("anvil"); + public static final Tag RAILS = create("rails"); + 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 BEDS = create("beds"); + public static final Tag FENCES = create("fences"); + public static final Tag TALL_FLOWERS = create("tall_flowers"); + public static final Tag FLOWERS = create("flowers"); + public static final Tag PIGLIN_REPELLENTS = create("piglin_repellents"); + public static final Tag GOLD_ORES = create("gold_ores"); + public static final Tag IRON_ORES = create("iron_ores"); + public static final Tag DIAMOND_ORES = create("diamond_ores"); + public static final Tag REDSTONE_ORES = create("redstone_ores"); + public static final Tag LAPIS_ORES = create("lapis_ores"); + public static final Tag COAL_ORES = create("coal_ores"); + public static final Tag EMERALD_ORES = create("emerald_ores"); + public static final Tag COPPER_ORES = create("copper_ores"); + public static final Tag CANDLES = create("candles"); + public static final Tag DIRT = create("dirt"); + public static final Tag TERRACOTTA = create("terracotta"); + public static final Tag BADLANDS_TERRACOTTA = create("badlands_terracotta"); + public static final Tag CONCRETE_POWDER = create("concrete_powder"); + public static final Tag COMPLETES_FIND_TREE_TUTORIAL = create("completes_find_tree_tutorial"); + public static final Tag FLOWER_POTS = create("flower_pots"); + public static final Tag ENDERMAN_HOLDABLE = create("enderman_holdable"); + public static final Tag ICE = create("ice"); + public static final Tag VALID_SPAWN = create("valid_spawn"); + public static final Tag IMPERMEABLE = create("impermeable"); + public static final Tag UNDERWATER_BONEMEALS = create("underwater_bonemeals"); + public static final Tag CORAL_BLOCKS = create("coral_blocks"); + public static final Tag WALL_CORALS = create("wall_corals"); + public static final Tag CORAL_PLANTS = create("coral_plants"); + public static final Tag CORALS = create("corals"); + public static final Tag BAMBOO_PLANTABLE_ON = create("bamboo_plantable_on"); + public static final Tag STANDING_SIGNS = create("standing_signs"); + public static final Tag WALL_SIGNS = create("wall_signs"); + public static final Tag SIGNS = create("signs"); + public static final Tag CEILING_HANGING_SIGNS = create("ceiling_hanging_signs"); + public static final Tag WALL_HANGING_SIGNS = create("wall_hanging_signs"); + public static final Tag ALL_HANGING_SIGNS = create("all_hanging_signs"); + public static final Tag ALL_SIGNS = create("all_signs"); + public static final Tag DRAGON_IMMUNE = create("dragon_immune"); + public static final Tag DRAGON_TRANSPARENT = create("dragon_transparent"); + public static final Tag WITHER_IMMUNE = create("wither_immune"); + public static final Tag WITHER_SUMMON_BASE_BLOCKS = create("wither_summon_base_blocks"); + public static final Tag BEEHIVES = create("beehives"); + public static final Tag CROPS = create("crops"); + public static final Tag BEE_GROWABLES = create("bee_growables"); + public static final Tag PORTALS = create("portals"); + public static final Tag FIRE = create("fire"); + public static final Tag NYLIUM = create("nylium"); + public static final Tag BEACON_BASE_BLOCKS = create("beacon_base_blocks"); + public static final Tag SOUL_SPEED_BLOCKS = create("soul_speed_blocks"); + public static final Tag WALL_POST_OVERRIDE = create("wall_post_override"); + public static final Tag CLIMBABLE = create("climbable"); + public static final Tag FALL_DAMAGE_RESETTING = create("fall_damage_resetting"); + public static final Tag SHULKER_BOXES = create("shulker_boxes"); + public static final Tag HOGLIN_REPELLENTS = create("hoglin_repellents"); + public static final Tag SOUL_FIRE_BASE_BLOCKS = create("soul_fire_base_blocks"); + public static final Tag STRIDER_WARM_BLOCKS = create("strider_warm_blocks"); + public static final Tag CAMPFIRES = create("campfires"); + public static final Tag GUARDED_BY_PIGLINS = create("guarded_by_piglins"); + public static final Tag PREVENT_MOB_SPAWNING_INSIDE = create("prevent_mob_spawning_inside"); + 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 INFINIBURN_OVERWORLD = create("infiniburn_overworld"); + public static final Tag INFINIBURN_NETHER = create("infiniburn_nether"); + public static final Tag INFINIBURN_END = create("infiniburn_end"); + public static final Tag BASE_STONE_OVERWORLD = create("base_stone_overworld"); + public static final Tag STONE_ORE_REPLACEABLES = create("stone_ore_replaceables"); + public static final Tag DEEPSLATE_ORE_REPLACEABLES = create("deepslate_ore_replaceables"); + public static final Tag BASE_STONE_NETHER = create("base_stone_nether"); + public static final Tag OVERWORLD_CARVER_REPLACEABLES = create("overworld_carver_replaceables"); + public static final Tag NETHER_CARVER_REPLACEABLES = create("nether_carver_replaceables"); + public static final Tag CANDLE_CAKES = create("candle_cakes"); + public static final Tag CAULDRONS = create("cauldrons"); + public static final Tag CRYSTAL_SOUND_BLOCKS = create("crystal_sound_blocks"); + public static final Tag INSIDE_STEP_SOUND_BLOCKS = create("inside_step_sound_blocks"); + public static final Tag COMBINATION_STEP_SOUND_BLOCKS = create("combination_step_sound_blocks"); + public static final Tag CAMEL_SAND_STEP_SOUND_BLOCKS = create("camel_sand_step_sound_blocks"); + public static final Tag OCCLUDES_VIBRATION_SIGNALS = create("occludes_vibration_signals"); + public static final Tag DAMPENS_VIBRATIONS = create("dampens_vibrations"); + public static final Tag DRIPSTONE_REPLACEABLE_BLOCKS = create("dripstone_replaceable_blocks"); + public static final Tag CAVE_VINES = create("cave_vines"); + public static final Tag MOSS_REPLACEABLE = create("moss_replaceable"); + public static final Tag LUSH_GROUND_REPLACEABLE = create("lush_ground_replaceable"); + public static final Tag AZALEA_ROOT_REPLACEABLE = create("azalea_root_replaceable"); + public static final Tag SMALL_DRIPLEAF_PLACEABLE = create("small_dripleaf_placeable"); + public static final Tag BIG_DRIPLEAF_PLACEABLE = create("big_dripleaf_placeable"); + public static final Tag SNOW = create("snow"); + public static final Tag MINEABLE_AXE = create("mineable/axe"); + public static final Tag MINEABLE_HOE = create("mineable/hoe"); + 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 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"); + public static final Tag INCORRECT_FOR_NETHERITE_TOOL = create("incorrect_for_netherite_tool"); + public static final Tag INCORRECT_FOR_DIAMOND_TOOL = create("incorrect_for_diamond_tool"); + public static final Tag INCORRECT_FOR_IRON_TOOL = create("incorrect_for_iron_tool"); + public static final Tag INCORRECT_FOR_STONE_TOOL = create("incorrect_for_stone_tool"); + public static final Tag INCORRECT_FOR_GOLD_TOOL = create("incorrect_for_gold_tool"); + public static final Tag INCORRECT_FOR_WOODEN_TOOL = create("incorrect_for_wooden_tool"); + public static final Tag FEATURES_CANNOT_REPLACE = create("features_cannot_replace"); + public static final Tag LAVA_POOL_STONE_CANNOT_REPLACE = create("lava_pool_stone_cannot_replace"); + public static final Tag GEODE_INVALID_BLOCKS = create("geode_invalid_blocks"); + public static final Tag FROG_PREFER_JUMP_TO = create("frog_prefer_jump_to"); + public static final Tag SCULK_REPLACEABLE = create("sculk_replaceable"); + public static final Tag SCULK_REPLACEABLE_WORLD_GEN = create("sculk_replaceable_world_gen"); + public static final Tag ANCIENT_CITY_REPLACEABLE = create("ancient_city_replaceable"); + public static final Tag VIBRATION_RESONATORS = create("vibration_resonators"); + public static final Tag ANIMALS_SPAWNABLE_ON = create("animals_spawnable_on"); + public static final Tag ARMADILLO_SPAWNABLE_ON = create("armadillo_spawnable_on"); + public static final Tag AXOLOTLS_SPAWNABLE_ON = create("axolotls_spawnable_on"); + public static final Tag GOATS_SPAWNABLE_ON = create("goats_spawnable_on"); + public static final Tag MOOSHROOMS_SPAWNABLE_ON = create("mooshrooms_spawnable_on"); + public static final Tag PARROTS_SPAWNABLE_ON = create("parrots_spawnable_on"); + public static final Tag POLAR_BEARS_SPAWNABLE_ON_ALTERNATE = create("polar_bears_spawnable_on_alternate"); + public static final Tag RABBITS_SPAWNABLE_ON = create("rabbits_spawnable_on"); + public static final Tag FOXES_SPAWNABLE_ON = create("foxes_spawnable_on"); + 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 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 SNAPS_GOAT_HORN = create("snaps_goat_horn"); + public static final Tag REPLACEABLE_BY_TREES = create("replaceable_by_trees"); + 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"); + public static final Tag SNIFFER_DIGGABLE_BLOCK = create("sniffer_diggable_block"); + public static final Tag SNIFFER_EGG_HATCH_BOOST = create("sniffer_egg_hatch_boost"); + public static final Tag TRAIL_RUINS_REPLACEABLE = create("trail_ruins_replaceable"); + public static final Tag REPLACEABLE = create("replaceable"); + public static final Tag ENCHANTMENT_POWER_PROVIDER = create("enchantment_power_provider"); + public static final Tag ENCHANTMENT_POWER_TRANSMITTER = create("enchantment_power_transmitter"); + 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 AIR = create("air"); - public static final BlockTag WOOL = new BlockTag("wool"); - public static final BlockTag PLANKS = new BlockTag("planks"); - public static final BlockTag STONE_BRICKS = new BlockTag("stone_bricks"); - public static final BlockTag WOODEN_BUTTONS = new BlockTag("wooden_buttons"); - public static final BlockTag STONE_BUTTONS = new BlockTag("stone_buttons"); - public static final BlockTag BUTTONS = new BlockTag("buttons"); - public static final BlockTag WOOL_CARPETS = new BlockTag("wool_carpets"); - public static final BlockTag WOODEN_DOORS = new BlockTag("wooden_doors"); - public static final BlockTag MOB_INTERACTABLE_DOORS = new BlockTag("mob_interactable_doors"); - public static final BlockTag WOODEN_STAIRS = new BlockTag("wooden_stairs"); - public static final BlockTag WOODEN_SLABS = new BlockTag("wooden_slabs"); - public static final BlockTag WOODEN_FENCES = new BlockTag("wooden_fences"); - public static final BlockTag PRESSURE_PLATES = new BlockTag("pressure_plates"); - public static final BlockTag WOODEN_PRESSURE_PLATES = new BlockTag("wooden_pressure_plates"); - public static final BlockTag STONE_PRESSURE_PLATES = new BlockTag("stone_pressure_plates"); - public static final BlockTag WOODEN_TRAPDOORS = new BlockTag("wooden_trapdoors"); - public static final BlockTag DOORS = new BlockTag("doors"); - public static final BlockTag SAPLINGS = new BlockTag("saplings"); - public static final BlockTag LOGS_THAT_BURN = new BlockTag("logs_that_burn"); - public static final BlockTag OVERWORLD_NATURAL_LOGS = new BlockTag("overworld_natural_logs"); - public static final BlockTag LOGS = new BlockTag("logs"); - public static final BlockTag DARK_OAK_LOGS = new BlockTag("dark_oak_logs"); - public static final BlockTag OAK_LOGS = new BlockTag("oak_logs"); - public static final BlockTag BIRCH_LOGS = new BlockTag("birch_logs"); - public static final BlockTag ACACIA_LOGS = new BlockTag("acacia_logs"); - public static final BlockTag CHERRY_LOGS = new BlockTag("cherry_logs"); - public static final BlockTag JUNGLE_LOGS = new BlockTag("jungle_logs"); - public static final BlockTag SPRUCE_LOGS = new BlockTag("spruce_logs"); - public static final BlockTag MANGROVE_LOGS = new BlockTag("mangrove_logs"); - public static final BlockTag CRIMSON_STEMS = new BlockTag("crimson_stems"); - public static final BlockTag WARPED_STEMS = new BlockTag("warped_stems"); - public static final BlockTag BAMBOO_BLOCKS = new BlockTag("bamboo_blocks"); - public static final BlockTag WART_BLOCKS = new BlockTag("wart_blocks"); - public static final BlockTag BANNERS = new BlockTag("banners"); - public static final BlockTag SAND = new BlockTag("sand"); - public static final BlockTag SMELTS_TO_GLASS = new BlockTag("smelts_to_glass"); - public static final BlockTag STAIRS = new BlockTag("stairs"); - public static final BlockTag SLABS = new BlockTag("slabs"); - public static final BlockTag WALLS = new BlockTag("walls"); - public static final BlockTag ANVIL = new BlockTag("anvil"); - public static final BlockTag RAILS = new BlockTag("rails"); - public static final BlockTag LEAVES = new BlockTag("leaves"); - public static final BlockTag TRAPDOORS = new BlockTag("trapdoors"); - public static final BlockTag SMALL_FLOWERS = new BlockTag("small_flowers"); - public static final BlockTag BEDS = new BlockTag("beds"); - public static final BlockTag FENCES = new BlockTag("fences"); - public static final BlockTag TALL_FLOWERS = new BlockTag("tall_flowers"); - public static final BlockTag FLOWERS = new BlockTag("flowers"); - public static final BlockTag PIGLIN_REPELLENTS = new BlockTag("piglin_repellents"); - public static final BlockTag GOLD_ORES = new BlockTag("gold_ores"); - public static final BlockTag IRON_ORES = new BlockTag("iron_ores"); - public static final BlockTag DIAMOND_ORES = new BlockTag("diamond_ores"); - public static final BlockTag REDSTONE_ORES = new BlockTag("redstone_ores"); - public static final BlockTag LAPIS_ORES = new BlockTag("lapis_ores"); - public static final BlockTag COAL_ORES = new BlockTag("coal_ores"); - public static final BlockTag EMERALD_ORES = new BlockTag("emerald_ores"); - public static final BlockTag COPPER_ORES = new BlockTag("copper_ores"); - public static final BlockTag CANDLES = new BlockTag("candles"); - public static final BlockTag DIRT = new BlockTag("dirt"); - public static final BlockTag TERRACOTTA = new BlockTag("terracotta"); - public static final BlockTag BADLANDS_TERRACOTTA = new BlockTag("badlands_terracotta"); - public static final BlockTag CONCRETE_POWDER = new BlockTag("concrete_powder"); - public static final BlockTag COMPLETES_FIND_TREE_TUTORIAL = new BlockTag("completes_find_tree_tutorial"); - public static final BlockTag FLOWER_POTS = new BlockTag("flower_pots"); - public static final BlockTag ENDERMAN_HOLDABLE = new BlockTag("enderman_holdable"); - public static final BlockTag ICE = new BlockTag("ice"); - public static final BlockTag VALID_SPAWN = new BlockTag("valid_spawn"); - public static final BlockTag IMPERMEABLE = new BlockTag("impermeable"); - public static final BlockTag UNDERWATER_BONEMEALS = new BlockTag("underwater_bonemeals"); - public static final BlockTag CORAL_BLOCKS = new BlockTag("coral_blocks"); - public static final BlockTag WALL_CORALS = new BlockTag("wall_corals"); - public static final BlockTag CORAL_PLANTS = new BlockTag("coral_plants"); - public static final BlockTag CORALS = new BlockTag("corals"); - public static final BlockTag BAMBOO_PLANTABLE_ON = new BlockTag("bamboo_plantable_on"); - public static final BlockTag STANDING_SIGNS = new BlockTag("standing_signs"); - public static final BlockTag WALL_SIGNS = new BlockTag("wall_signs"); - public static final BlockTag SIGNS = new BlockTag("signs"); - public static final BlockTag CEILING_HANGING_SIGNS = new BlockTag("ceiling_hanging_signs"); - public static final BlockTag WALL_HANGING_SIGNS = new BlockTag("wall_hanging_signs"); - public static final BlockTag ALL_HANGING_SIGNS = new BlockTag("all_hanging_signs"); - public static final BlockTag ALL_SIGNS = new BlockTag("all_signs"); - public static final BlockTag DRAGON_IMMUNE = new BlockTag("dragon_immune"); - public static final BlockTag DRAGON_TRANSPARENT = new BlockTag("dragon_transparent"); - public static final BlockTag WITHER_IMMUNE = new BlockTag("wither_immune"); - public static final BlockTag WITHER_SUMMON_BASE_BLOCKS = new BlockTag("wither_summon_base_blocks"); - public static final BlockTag BEEHIVES = new BlockTag("beehives"); - public static final BlockTag CROPS = new BlockTag("crops"); - public static final BlockTag BEE_GROWABLES = new BlockTag("bee_growables"); - public static final BlockTag PORTALS = new BlockTag("portals"); - public static final BlockTag FIRE = new BlockTag("fire"); - public static final BlockTag NYLIUM = new BlockTag("nylium"); - public static final BlockTag BEACON_BASE_BLOCKS = new BlockTag("beacon_base_blocks"); - public static final BlockTag SOUL_SPEED_BLOCKS = new BlockTag("soul_speed_blocks"); - public static final BlockTag WALL_POST_OVERRIDE = new BlockTag("wall_post_override"); - public static final BlockTag CLIMBABLE = new BlockTag("climbable"); - public static final BlockTag FALL_DAMAGE_RESETTING = new BlockTag("fall_damage_resetting"); - public static final BlockTag SHULKER_BOXES = new BlockTag("shulker_boxes"); - public static final BlockTag HOGLIN_REPELLENTS = new BlockTag("hoglin_repellents"); - public static final BlockTag SOUL_FIRE_BASE_BLOCKS = new BlockTag("soul_fire_base_blocks"); - public static final BlockTag STRIDER_WARM_BLOCKS = new BlockTag("strider_warm_blocks"); - public static final BlockTag CAMPFIRES = new BlockTag("campfires"); - public static final BlockTag GUARDED_BY_PIGLINS = new BlockTag("guarded_by_piglins"); - public static final BlockTag PREVENT_MOB_SPAWNING_INSIDE = new BlockTag("prevent_mob_spawning_inside"); - public static final BlockTag FENCE_GATES = new BlockTag("fence_gates"); - public static final BlockTag UNSTABLE_BOTTOM_CENTER = new BlockTag("unstable_bottom_center"); - public static final BlockTag MUSHROOM_GROW_BLOCK = new BlockTag("mushroom_grow_block"); - public static final BlockTag INFINIBURN_OVERWORLD = new BlockTag("infiniburn_overworld"); - public static final BlockTag INFINIBURN_NETHER = new BlockTag("infiniburn_nether"); - public static final BlockTag INFINIBURN_END = new BlockTag("infiniburn_end"); - public static final BlockTag BASE_STONE_OVERWORLD = new BlockTag("base_stone_overworld"); - public static final BlockTag STONE_ORE_REPLACEABLES = new BlockTag("stone_ore_replaceables"); - public static final BlockTag DEEPSLATE_ORE_REPLACEABLES = new BlockTag("deepslate_ore_replaceables"); - public static final BlockTag BASE_STONE_NETHER = new BlockTag("base_stone_nether"); - public static final BlockTag OVERWORLD_CARVER_REPLACEABLES = new BlockTag("overworld_carver_replaceables"); - public static final BlockTag NETHER_CARVER_REPLACEABLES = new BlockTag("nether_carver_replaceables"); - public static final BlockTag CANDLE_CAKES = new BlockTag("candle_cakes"); - public static final BlockTag CAULDRONS = new BlockTag("cauldrons"); - public static final BlockTag CRYSTAL_SOUND_BLOCKS = new BlockTag("crystal_sound_blocks"); - public static final BlockTag INSIDE_STEP_SOUND_BLOCKS = new BlockTag("inside_step_sound_blocks"); - public static final BlockTag COMBINATION_STEP_SOUND_BLOCKS = new BlockTag("combination_step_sound_blocks"); - public static final BlockTag CAMEL_SAND_STEP_SOUND_BLOCKS = new BlockTag("camel_sand_step_sound_blocks"); - public static final BlockTag OCCLUDES_VIBRATION_SIGNALS = new BlockTag("occludes_vibration_signals"); - public static final BlockTag DAMPENS_VIBRATIONS = new BlockTag("dampens_vibrations"); - public static final BlockTag DRIPSTONE_REPLACEABLE_BLOCKS = new BlockTag("dripstone_replaceable_blocks"); - public static final BlockTag CAVE_VINES = new BlockTag("cave_vines"); - public static final BlockTag MOSS_REPLACEABLE = new BlockTag("moss_replaceable"); - public static final BlockTag LUSH_GROUND_REPLACEABLE = new BlockTag("lush_ground_replaceable"); - public static final BlockTag AZALEA_ROOT_REPLACEABLE = new BlockTag("azalea_root_replaceable"); - public static final BlockTag SMALL_DRIPLEAF_PLACEABLE = new BlockTag("small_dripleaf_placeable"); - public static final BlockTag BIG_DRIPLEAF_PLACEABLE = new BlockTag("big_dripleaf_placeable"); - public static final BlockTag SNOW = new BlockTag("snow"); - public static final BlockTag MINEABLE_AXE = new BlockTag("mineable/axe"); - public static final BlockTag MINEABLE_HOE = new BlockTag("mineable/hoe"); - public static final BlockTag MINEABLE_PICKAXE = new BlockTag("mineable/pickaxe"); - public static final BlockTag MINEABLE_SHOVEL = new BlockTag("mineable/shovel"); - public static final BlockTag SWORD_EFFICIENT = new BlockTag("sword_efficient"); - public static final BlockTag NEEDS_DIAMOND_TOOL = new BlockTag("needs_diamond_tool"); - public static final BlockTag NEEDS_IRON_TOOL = new BlockTag("needs_iron_tool"); - public static final BlockTag NEEDS_STONE_TOOL = new BlockTag("needs_stone_tool"); - public static final BlockTag INCORRECT_FOR_NETHERITE_TOOL = new BlockTag("incorrect_for_netherite_tool"); - public static final BlockTag INCORRECT_FOR_DIAMOND_TOOL = new BlockTag("incorrect_for_diamond_tool"); - public static final BlockTag INCORRECT_FOR_IRON_TOOL = new BlockTag("incorrect_for_iron_tool"); - public static final BlockTag INCORRECT_FOR_STONE_TOOL = new BlockTag("incorrect_for_stone_tool"); - public static final BlockTag INCORRECT_FOR_GOLD_TOOL = new BlockTag("incorrect_for_gold_tool"); - public static final BlockTag INCORRECT_FOR_WOODEN_TOOL = new BlockTag("incorrect_for_wooden_tool"); - public static final BlockTag FEATURES_CANNOT_REPLACE = new BlockTag("features_cannot_replace"); - public static final BlockTag LAVA_POOL_STONE_CANNOT_REPLACE = new BlockTag("lava_pool_stone_cannot_replace"); - public static final BlockTag GEODE_INVALID_BLOCKS = new BlockTag("geode_invalid_blocks"); - public static final BlockTag FROG_PREFER_JUMP_TO = new BlockTag("frog_prefer_jump_to"); - public static final BlockTag SCULK_REPLACEABLE = new BlockTag("sculk_replaceable"); - public static final BlockTag SCULK_REPLACEABLE_WORLD_GEN = new BlockTag("sculk_replaceable_world_gen"); - public static final BlockTag ANCIENT_CITY_REPLACEABLE = new BlockTag("ancient_city_replaceable"); - public static final BlockTag VIBRATION_RESONATORS = new BlockTag("vibration_resonators"); - public static final BlockTag ANIMALS_SPAWNABLE_ON = new BlockTag("animals_spawnable_on"); - public static final BlockTag ARMADILLO_SPAWNABLE_ON = new BlockTag("armadillo_spawnable_on"); - public static final BlockTag AXOLOTLS_SPAWNABLE_ON = new BlockTag("axolotls_spawnable_on"); - public static final BlockTag GOATS_SPAWNABLE_ON = new BlockTag("goats_spawnable_on"); - public static final BlockTag MOOSHROOMS_SPAWNABLE_ON = new BlockTag("mooshrooms_spawnable_on"); - public static final BlockTag PARROTS_SPAWNABLE_ON = new BlockTag("parrots_spawnable_on"); - public static final BlockTag POLAR_BEARS_SPAWNABLE_ON_ALTERNATE = new BlockTag("polar_bears_spawnable_on_alternate"); - public static final BlockTag RABBITS_SPAWNABLE_ON = new BlockTag("rabbits_spawnable_on"); - public static final BlockTag FOXES_SPAWNABLE_ON = new BlockTag("foxes_spawnable_on"); - public static final BlockTag WOLVES_SPAWNABLE_ON = new BlockTag("wolves_spawnable_on"); - public static final BlockTag FROGS_SPAWNABLE_ON = new BlockTag("frogs_spawnable_on"); - public static final BlockTag AZALEA_GROWS_ON = new BlockTag("azalea_grows_on"); - public static final BlockTag CONVERTABLE_TO_MUD = new BlockTag("convertable_to_mud"); - public static final BlockTag MANGROVE_LOGS_CAN_GROW_THROUGH = new BlockTag("mangrove_logs_can_grow_through"); - public static final BlockTag MANGROVE_ROOTS_CAN_GROW_THROUGH = new BlockTag("mangrove_roots_can_grow_through"); - public static final BlockTag DEAD_BUSH_MAY_PLACE_ON = new BlockTag("dead_bush_may_place_on"); - public static final BlockTag SNAPS_GOAT_HORN = new BlockTag("snaps_goat_horn"); - public static final BlockTag REPLACEABLE_BY_TREES = new BlockTag("replaceable_by_trees"); - public static final BlockTag SNOW_LAYER_CANNOT_SURVIVE_ON = new BlockTag("snow_layer_cannot_survive_on"); - public static final BlockTag SNOW_LAYER_CAN_SURVIVE_ON = new BlockTag("snow_layer_can_survive_on"); - public static final BlockTag INVALID_SPAWN_INSIDE = new BlockTag("invalid_spawn_inside"); - public static final BlockTag SNIFFER_DIGGABLE_BLOCK = new BlockTag("sniffer_diggable_block"); - public static final BlockTag SNIFFER_EGG_HATCH_BOOST = new BlockTag("sniffer_egg_hatch_boost"); - public static final BlockTag TRAIL_RUINS_REPLACEABLE = new BlockTag("trail_ruins_replaceable"); - public static final BlockTag REPLACEABLE = new BlockTag("replaceable"); - public static final BlockTag ENCHANTMENT_POWER_PROVIDER = new BlockTag("enchantment_power_provider"); - public static final BlockTag ENCHANTMENT_POWER_TRANSMITTER = new BlockTag("enchantment_power_transmitter"); - public static final BlockTag MAINTAINS_FARMLAND = new BlockTag("maintains_farmland"); - public static final BlockTag BLOCKS_WIND_CHARGE_EXPLOSIONS = new BlockTag("blocks_wind_charge_explosions"); - public static final BlockTag DOES_NOT_BLOCK_HOPPERS = new BlockTag("does_not_block_hoppers"); - public static final BlockTag AIR = new BlockTag("air"); + private BlockTag() {} - private final int id; - - private BlockTag(String identifier) { - this.id = ALL_BLOCK_TAGS.size(); - register(identifier, this); - } - - @Override - public int ordinal() { - return id; - } - - private static void register(String name, BlockTag tag) { - ALL_BLOCK_TAGS.put(Key.key(name), tag); + private static Tag create(String name) { + return new Tag<>(JavaRegistries.BLOCK, MinecraftKey.key(name)); } } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java b/core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java index 0af690abd..1ef875642 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java @@ -25,67 +25,55 @@ package org.geysermc.geyser.session.cache.tags; -import net.kyori.adventure.key.Key; +import org.geysermc.geyser.item.enchantment.Enchantment; +import org.geysermc.geyser.session.cache.registry.JavaRegistries; import org.geysermc.geyser.util.MinecraftKey; -import org.geysermc.geyser.util.Ordered; - -import java.util.HashMap; -import java.util.Map; +/** + * Lists vanilla enchantment tags. + */ @SuppressWarnings("unused") -public final class EnchantmentTag implements Ordered { - public static final Map ALL_ENCHANTMENT_TAGS = new HashMap<>(); +public final class EnchantmentTag { + public static final Tag TOOLTIP_ORDER = create("tooltip_order"); + public static final Tag EXCLUSIVE_SET_ARMOR = create("exclusive_set/armor"); + public static final Tag EXCLUSIVE_SET_BOOTS = create("exclusive_set/boots"); + public static final Tag EXCLUSIVE_SET_BOW = create("exclusive_set/bow"); + public static final Tag EXCLUSIVE_SET_CROSSBOW = create("exclusive_set/crossbow"); + public static final Tag EXCLUSIVE_SET_DAMAGE = create("exclusive_set/damage"); + public static final Tag EXCLUSIVE_SET_MINING = create("exclusive_set/mining"); + public static final Tag EXCLUSIVE_SET_RIPTIDE = create("exclusive_set/riptide"); + public static final Tag TRADEABLE = create("tradeable"); + public static final Tag DOUBLE_TRADE_PRICE = create("double_trade_price"); + public static final Tag IN_ENCHANTING_TABLE = create("in_enchanting_table"); + public static final Tag ON_MOB_SPAWN_EQUIPMENT = create("on_mob_spawn_equipment"); + public static final Tag ON_TRADED_EQUIPMENT = create("on_traded_equipment"); + public static final Tag ON_RANDOM_LOOT = create("on_random_loot"); + public static final Tag CURSE = create("curse"); + public static final Tag SMELTS_LOOT = create("smelts_loot"); + public static final Tag PREVENTS_BEE_SPAWNS_WHEN_MINING = create("prevents_bee_spawns_when_mining"); + public static final Tag PREVENTS_DECORATED_POT_SHATTERING = create("prevents_decorated_pot_shattering"); + public static final Tag PREVENTS_ICE_MELTING = create("prevents_ice_melting"); + public static final Tag PREVENTS_INFESTED_SPAWNS = create("prevents_infested_spawns"); + public static final Tag TREASURE = create("treasure"); + public static final Tag NON_TREASURE = create("non_treasure"); + public static final Tag TRADES_DESERT_COMMON = create("trades/desert_common"); + public static final Tag TRADES_JUNGLE_COMMON = create("trades/jungle_common"); + public static final Tag TRADES_PLAINS_COMMON = create("trades/plains_common"); + public static final Tag TRADES_SAVANNA_COMMON = create("trades/savanna_common"); + public static final Tag TRADES_SNOW_COMMON = create("trades/snow_common"); + public static final Tag TRADES_SWAMP_COMMON = create("trades/swamp_common"); + public static final Tag TRADES_TAIGA_COMMON = create("trades/taiga_common"); + public static final Tag TRADES_DESERT_SPECIAL = create("trades/desert_special"); + public static final Tag TRADES_JUNGLE_SPECIAL = create("trades/jungle_special"); + public static final Tag TRADES_PLAINS_SPECIAL = create("trades/plains_special"); + public static final Tag TRADES_SAVANNA_SPECIAL = create("trades/savanna_special"); + public static final Tag TRADES_SNOW_SPECIAL = create("trades/snow_special"); + public static final Tag TRADES_SWAMP_SPECIAL = create("trades/swamp_special"); + public static final Tag TRADES_TAIGA_SPECIAL = create("trades/taiga_special"); - public static final EnchantmentTag TOOLTIP_ORDER = new EnchantmentTag("tooltip_order"); - public static final EnchantmentTag EXCLUSIVE_SET_ARMOR = new EnchantmentTag("exclusive_set/armor"); - public static final EnchantmentTag EXCLUSIVE_SET_BOOTS = new EnchantmentTag("exclusive_set/boots"); - public static final EnchantmentTag EXCLUSIVE_SET_BOW = new EnchantmentTag("exclusive_set/bow"); - public static final EnchantmentTag EXCLUSIVE_SET_CROSSBOW = new EnchantmentTag("exclusive_set/crossbow"); - public static final EnchantmentTag EXCLUSIVE_SET_DAMAGE = new EnchantmentTag("exclusive_set/damage"); - public static final EnchantmentTag EXCLUSIVE_SET_MINING = new EnchantmentTag("exclusive_set/mining"); - public static final EnchantmentTag EXCLUSIVE_SET_RIPTIDE = new EnchantmentTag("exclusive_set/riptide"); - public static final EnchantmentTag TRADEABLE = new EnchantmentTag("tradeable"); - public static final EnchantmentTag DOUBLE_TRADE_PRICE = new EnchantmentTag("double_trade_price"); - public static final EnchantmentTag IN_ENCHANTING_TABLE = new EnchantmentTag("in_enchanting_table"); - public static final EnchantmentTag ON_MOB_SPAWN_EQUIPMENT = new EnchantmentTag("on_mob_spawn_equipment"); - public static final EnchantmentTag ON_TRADED_EQUIPMENT = new EnchantmentTag("on_traded_equipment"); - public static final EnchantmentTag ON_RANDOM_LOOT = new EnchantmentTag("on_random_loot"); - public static final EnchantmentTag CURSE = new EnchantmentTag("curse"); - public static final EnchantmentTag SMELTS_LOOT = new EnchantmentTag("smelts_loot"); - public static final EnchantmentTag PREVENTS_BEE_SPAWNS_WHEN_MINING = new EnchantmentTag("prevents_bee_spawns_when_mining"); - public static final EnchantmentTag PREVENTS_DECORATED_POT_SHATTERING = new EnchantmentTag("prevents_decorated_pot_shattering"); - public static final EnchantmentTag PREVENTS_ICE_MELTING = new EnchantmentTag("prevents_ice_melting"); - public static final EnchantmentTag PREVENTS_INFESTED_SPAWNS = new EnchantmentTag("prevents_infested_spawns"); - public static final EnchantmentTag TREASURE = new EnchantmentTag("treasure"); - public static final EnchantmentTag NON_TREASURE = new EnchantmentTag("non_treasure"); - public static final EnchantmentTag TRADES_DESERT_COMMON = new EnchantmentTag("trades/desert_common"); - public static final EnchantmentTag TRADES_JUNGLE_COMMON = new EnchantmentTag("trades/jungle_common"); - public static final EnchantmentTag TRADES_PLAINS_COMMON = new EnchantmentTag("trades/plains_common"); - public static final EnchantmentTag TRADES_SAVANNA_COMMON = new EnchantmentTag("trades/savanna_common"); - public static final EnchantmentTag TRADES_SNOW_COMMON = new EnchantmentTag("trades/snow_common"); - public static final EnchantmentTag TRADES_SWAMP_COMMON = new EnchantmentTag("trades/swamp_common"); - public static final EnchantmentTag TRADES_TAIGA_COMMON = new EnchantmentTag("trades/taiga_common"); - public static final EnchantmentTag TRADES_DESERT_SPECIAL = new EnchantmentTag("trades/desert_special"); - public static final EnchantmentTag TRADES_JUNGLE_SPECIAL = new EnchantmentTag("trades/jungle_special"); - public static final EnchantmentTag TRADES_PLAINS_SPECIAL = new EnchantmentTag("trades/plains_special"); - public static final EnchantmentTag TRADES_SAVANNA_SPECIAL = new EnchantmentTag("trades/savanna_special"); - public static final EnchantmentTag TRADES_SNOW_SPECIAL = new EnchantmentTag("trades/snow_special"); - public static final EnchantmentTag TRADES_SWAMP_SPECIAL = new EnchantmentTag("trades/swamp_special"); - public static final EnchantmentTag TRADES_TAIGA_SPECIAL = new EnchantmentTag("trades/taiga_special"); + private EnchantmentTag() {} - private final int id; - - private EnchantmentTag(String identifier) { - this.id = ALL_ENCHANTMENT_TAGS.size(); - register(identifier, this); - } - - @Override - public int ordinal() { - return id; - } - - private static void register(String name, EnchantmentTag tag) { - ALL_ENCHANTMENT_TAGS.put(MinecraftKey.key(name), tag); + private static Tag create(String name) { + return new Tag<>(JavaRegistries.ENCHANTMENT, MinecraftKey.key(name)); } } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/tags/GeyserHolderSet.java b/core/src/main/java/org/geysermc/geyser/session/cache/tags/GeyserHolderSet.java new file mode 100644 index 000000000..3c6e02e53 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/tags/GeyserHolderSet.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.session.cache.tags; + +import java.util.List; +import java.util.Objects; +import java.util.function.ToIntFunction; + +import it.unimi.dsi.fastutil.ints.IntArrays; +import lombok.Data; +import net.kyori.adventure.key.Key; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.TagCache; +import org.geysermc.geyser.session.cache.registry.JavaRegistryKey; + +/** + * Similar to vanilla Minecraft's HolderSets, stores either a tag or a list of IDs (this list can also be represented as a single ID in vanilla HolderSets). + * + *

Because HolderSets utilise tags, when loading a HolderSet, Geyser must store tags for the registry the HolderSet is for (see {@link JavaRegistryKey}).

+ * + *

Use the {@link GeyserHolderSet#readHolderSet} method to easily read a HolderSet from NBT sent by a server. To turn the HolderSet into a list of network IDs, use the {@link GeyserHolderSet#resolveRaw} method. + * To turn the HolderSet into a list of objects, use the {@link GeyserHolderSet#resolve} method.

+ */ +@Data +public final class GeyserHolderSet { + + private final JavaRegistryKey registry; + private final @Nullable Tag tag; + private final int @Nullable [] holders; + + public GeyserHolderSet(JavaRegistryKey registry, int @NonNull [] holders) { + this.registry = registry; + this.tag = null; + this.holders = holders; + } + + public GeyserHolderSet(JavaRegistryKey registry, @NonNull Tag tagId) { + this.registry = registry; + this.tag = tagId; + this.holders = null; + } + + /** + * Resolves the HolderSet, and automatically maps the network IDs to their respective object types. If the HolderSet is a list of IDs, this will be returned. If it is a tag, the tag will be resolved from the tag cache. + * + * @return the HolderSet turned into a list of objects. + */ + public List resolve(GeyserSession session) { + return TagCache.mapRawArray(session, resolveRaw(session.getTagCache()), registry); + } + + /** + * Resolves the HolderSet. If the HolderSet is a list of IDs, this will be returned. If it is a tag, the tag will be resolved from the tag cache. + * + * @return the HolderSet turned into a list of objects. + */ + public int[] resolveRaw(TagCache tagCache) { + if (holders != null) { + return holders; + } + + return tagCache.getRaw(Objects.requireNonNull(tag, "HolderSet must have a tag if it doesn't have a list of IDs")); + } + + /** + * Reads a HolderSet from an object from NBT. + * + * @param session session, only used for logging purposes. + * @param registry the registry the HolderSet contains IDs from. + * @param holderSet the HolderSet as an object from NBT. + * @param keyIdMapping a function that maps resource location IDs in the HolderSet's registry to their network IDs. + */ + public static GeyserHolderSet readHolderSet(GeyserSession session, JavaRegistryKey registry, @Nullable Object holderSet, ToIntFunction keyIdMapping) { + if (holderSet == null) { + return new GeyserHolderSet<>(registry, IntArrays.EMPTY_ARRAY); + } + + if (holderSet instanceof String stringTag) { + if (stringTag.startsWith("#")) { + // Tag + return new GeyserHolderSet<>(registry, new Tag<>(registry, Key.key(stringTag.substring(1)))); // Remove '#' at beginning that indicates tag + } else if (stringTag.isEmpty()) { + return new GeyserHolderSet<>(registry, IntArrays.EMPTY_ARRAY); + } + return new GeyserHolderSet<>(registry, new int[]{keyIdMapping.applyAsInt(Key.key(stringTag))}); + } else if (holderSet instanceof List list) { + // Assume the list is a list of strings + return new GeyserHolderSet<>(registry, list.stream().map(o -> (String) o).map(Key::key).mapToInt(keyIdMapping).toArray()); + } + session.getGeyser().getLogger().warning("Failed parsing HolderSet for registry + " + registry + "! Expected either a tag, a string ID or a list of string IDs, found " + holderSet); + return new GeyserHolderSet<>(registry, IntArrays.EMPTY_ARRAY); + } +} 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 a2e861dd6..4f42f146a 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 @@ -25,178 +25,166 @@ package org.geysermc.geyser.session.cache.tags; -import net.kyori.adventure.key.Key; +import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.session.cache.registry.JavaRegistries; import org.geysermc.geyser.util.MinecraftKey; -import org.geysermc.geyser.util.Ordered; - -import java.util.HashMap; -import java.util.Map; +/** + * Lists vanilla item tags. + */ @SuppressWarnings("unused") -public final class ItemTag implements Ordered { - public static final Map ALL_ITEM_TAGS = new HashMap<>(); +public final class ItemTag { + public static final Tag WOOL = create("wool"); + public static final Tag PLANKS = create("planks"); + public static final Tag STONE_BRICKS = create("stone_bricks"); + public static final Tag WOODEN_BUTTONS = create("wooden_buttons"); + public static final Tag STONE_BUTTONS = create("stone_buttons"); + public static final Tag BUTTONS = create("buttons"); + public static final Tag WOOL_CARPETS = create("wool_carpets"); + public static final Tag WOODEN_DOORS = create("wooden_doors"); + public static final Tag WOODEN_STAIRS = create("wooden_stairs"); + public static final Tag WOODEN_SLABS = create("wooden_slabs"); + public static final Tag WOODEN_FENCES = create("wooden_fences"); + public static final Tag FENCE_GATES = create("fence_gates"); + public static final Tag WOODEN_PRESSURE_PLATES = create("wooden_pressure_plates"); + public static final Tag WOODEN_TRAPDOORS = create("wooden_trapdoors"); + public static final Tag DOORS = create("doors"); + public static final Tag SAPLINGS = create("saplings"); + public static final Tag LOGS_THAT_BURN = create("logs_that_burn"); + public static final Tag LOGS = create("logs"); + public static final Tag DARK_OAK_LOGS = create("dark_oak_logs"); + public static final Tag OAK_LOGS = create("oak_logs"); + public static final Tag BIRCH_LOGS = create("birch_logs"); + public static final Tag ACACIA_LOGS = create("acacia_logs"); + public static final Tag CHERRY_LOGS = create("cherry_logs"); + public static final Tag JUNGLE_LOGS = create("jungle_logs"); + public static final Tag SPRUCE_LOGS = create("spruce_logs"); + public static final Tag MANGROVE_LOGS = create("mangrove_logs"); + public static final Tag CRIMSON_STEMS = create("crimson_stems"); + public static final Tag WARPED_STEMS = create("warped_stems"); + public static final Tag BAMBOO_BLOCKS = create("bamboo_blocks"); + public static final Tag WART_BLOCKS = create("wart_blocks"); + public static final Tag BANNERS = create("banners"); + public static final Tag SAND = create("sand"); + public static final Tag SMELTS_TO_GLASS = create("smelts_to_glass"); + public static final Tag STAIRS = create("stairs"); + public static final Tag SLABS = create("slabs"); + public static final Tag WALLS = create("walls"); + public static final Tag ANVIL = create("anvil"); + public static final Tag RAILS = create("rails"); + 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 BEDS = create("beds"); + public static final Tag FENCES = create("fences"); + public static final Tag TALL_FLOWERS = create("tall_flowers"); + public static final Tag FLOWERS = create("flowers"); + public static final Tag PIGLIN_REPELLENTS = create("piglin_repellents"); + public static final Tag PIGLIN_LOVED = create("piglin_loved"); + public static final Tag IGNORED_BY_PIGLIN_BABIES = create("ignored_by_piglin_babies"); + 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"); + public static final Tag FOX_FOOD = create("fox_food"); + public static final Tag COW_FOOD = create("cow_food"); + public static final Tag GOAT_FOOD = create("goat_food"); + public static final Tag SHEEP_FOOD = create("sheep_food"); + public static final Tag WOLF_FOOD = create("wolf_food"); + public static final Tag CAT_FOOD = create("cat_food"); + public static final Tag HORSE_FOOD = create("horse_food"); + public static final Tag HORSE_TEMPT_ITEMS = create("horse_tempt_items"); + public static final Tag CAMEL_FOOD = create("camel_food"); + public static final Tag ARMADILLO_FOOD = create("armadillo_food"); + public static final Tag BEE_FOOD = create("bee_food"); + public static final Tag CHICKEN_FOOD = create("chicken_food"); + public static final Tag FROG_FOOD = create("frog_food"); + public static final Tag HOGLIN_FOOD = create("hoglin_food"); + public static final Tag LLAMA_FOOD = create("llama_food"); + public static final Tag LLAMA_TEMPT_ITEMS = create("llama_tempt_items"); + public static final Tag OCELOT_FOOD = create("ocelot_food"); + public static final Tag PANDA_FOOD = create("panda_food"); + public static final Tag PIG_FOOD = create("pig_food"); + public static final Tag RABBIT_FOOD = create("rabbit_food"); + public static final Tag STRIDER_FOOD = create("strider_food"); + public static final Tag STRIDER_TEMPT_ITEMS = create("strider_tempt_items"); + public static final Tag TURTLE_FOOD = create("turtle_food"); + public static final Tag PARROT_FOOD = create("parrot_food"); + public static final Tag PARROT_POISONOUS_FOOD = create("parrot_poisonous_food"); + public static final Tag AXOLOTL_FOOD = create("axolotl_food"); + public static final Tag GOLD_ORES = create("gold_ores"); + public static final Tag IRON_ORES = create("iron_ores"); + public static final Tag DIAMOND_ORES = create("diamond_ores"); + public static final Tag REDSTONE_ORES = create("redstone_ores"); + public static final Tag LAPIS_ORES = create("lapis_ores"); + public static final Tag COAL_ORES = create("coal_ores"); + public static final Tag EMERALD_ORES = create("emerald_ores"); + public static final Tag COPPER_ORES = create("copper_ores"); + public static final Tag NON_FLAMMABLE_WOOD = create("non_flammable_wood"); + public static final Tag SOUL_FIRE_BASE_BLOCKS = create("soul_fire_base_blocks"); + public static final Tag CANDLES = create("candles"); + public static final Tag DIRT = create("dirt"); + public static final Tag TERRACOTTA = create("terracotta"); + public static final Tag COMPLETES_FIND_TREE_TUTORIAL = create("completes_find_tree_tutorial"); + public static final Tag BOATS = create("boats"); + public static final Tag CHEST_BOATS = create("chest_boats"); + public static final Tag FISHES = create("fishes"); + public static final Tag SIGNS = create("signs"); + public static final Tag CREEPER_DROP_MUSIC_DISCS = create("creeper_drop_music_discs"); + public static final Tag COALS = create("coals"); + public static final Tag ARROWS = create("arrows"); + public static final Tag LECTERN_BOOKS = create("lectern_books"); + public static final Tag BOOKSHELF_BOOKS = create("bookshelf_books"); + public static final Tag BEACON_PAYMENT_ITEMS = create("beacon_payment_items"); + public static final Tag STONE_TOOL_MATERIALS = create("stone_tool_materials"); + public static final Tag STONE_CRAFTING_MATERIALS = create("stone_crafting_materials"); + public static final Tag FREEZE_IMMUNE_WEARABLES = create("freeze_immune_wearables"); + public static final Tag DAMPENS_VIBRATIONS = create("dampens_vibrations"); + public static final Tag CLUSTER_MAX_HARVESTABLES = create("cluster_max_harvestables"); + public static final Tag COMPASSES = create("compasses"); + public static final Tag HANGING_SIGNS = create("hanging_signs"); + public static final Tag CREEPER_IGNITERS = create("creeper_igniters"); + public static final Tag NOTEBLOCK_TOP_INSTRUMENTS = create("noteblock_top_instruments"); + public static final Tag FOOT_ARMOR = create("foot_armor"); + public static final Tag LEG_ARMOR = create("leg_armor"); + public static final Tag CHEST_ARMOR = create("chest_armor"); + public static final Tag HEAD_ARMOR = create("head_armor"); + public static final Tag SKULLS = create("skulls"); + public static final Tag TRIMMABLE_ARMOR = create("trimmable_armor"); + public static final Tag TRIM_MATERIALS = create("trim_materials"); + public static final Tag TRIM_TEMPLATES = create("trim_templates"); + public static final Tag DECORATED_POT_SHERDS = create("decorated_pot_sherds"); + public static final Tag DECORATED_POT_INGREDIENTS = create("decorated_pot_ingredients"); + public static final Tag SWORDS = create("swords"); + public static final Tag AXES = create("axes"); + public static final Tag HOES = create("hoes"); + public static final Tag PICKAXES = create("pickaxes"); + public static final Tag SHOVELS = create("shovels"); + public static final Tag BREAKS_DECORATED_POTS = create("breaks_decorated_pots"); + public static final Tag VILLAGER_PLANTABLE_SEEDS = create("villager_plantable_seeds"); + public static final Tag DYEABLE = create("dyeable"); + public static final Tag ENCHANTABLE_FOOT_ARMOR = create("enchantable/foot_armor"); + public static final Tag ENCHANTABLE_LEG_ARMOR = create("enchantable/leg_armor"); + public static final Tag ENCHANTABLE_CHEST_ARMOR = create("enchantable/chest_armor"); + public static final Tag ENCHANTABLE_HEAD_ARMOR = create("enchantable/head_armor"); + public static final Tag ENCHANTABLE_ARMOR = create("enchantable/armor"); + public static final Tag ENCHANTABLE_SWORD = create("enchantable/sword"); + public static final Tag ENCHANTABLE_FIRE_ASPECT = create("enchantable/fire_aspect"); + public static final Tag ENCHANTABLE_SHARP_WEAPON = create("enchantable/sharp_weapon"); + public static final Tag ENCHANTABLE_WEAPON = create("enchantable/weapon"); + public static final Tag ENCHANTABLE_MINING = create("enchantable/mining"); + public static final Tag ENCHANTABLE_MINING_LOOT = create("enchantable/mining_loot"); + public static final Tag ENCHANTABLE_FISHING = create("enchantable/fishing"); + public static final Tag ENCHANTABLE_TRIDENT = create("enchantable/trident"); + public static final Tag ENCHANTABLE_DURABILITY = create("enchantable/durability"); + public static final Tag ENCHANTABLE_BOW = create("enchantable/bow"); + public static final Tag ENCHANTABLE_EQUIPPABLE = create("enchantable/equippable"); + public static final Tag ENCHANTABLE_CROSSBOW = create("enchantable/crossbow"); + public static final Tag ENCHANTABLE_VANISHING = create("enchantable/vanishing"); + public static final Tag ENCHANTABLE_MACE = create("enchantable/mace"); - public static final ItemTag WOOL = new ItemTag("wool"); - public static final ItemTag PLANKS = new ItemTag("planks"); - public static final ItemTag STONE_BRICKS = new ItemTag("stone_bricks"); - public static final ItemTag WOODEN_BUTTONS = new ItemTag("wooden_buttons"); - public static final ItemTag STONE_BUTTONS = new ItemTag("stone_buttons"); - public static final ItemTag BUTTONS = new ItemTag("buttons"); - public static final ItemTag WOOL_CARPETS = new ItemTag("wool_carpets"); - public static final ItemTag WOODEN_DOORS = new ItemTag("wooden_doors"); - public static final ItemTag WOODEN_STAIRS = new ItemTag("wooden_stairs"); - public static final ItemTag WOODEN_SLABS = new ItemTag("wooden_slabs"); - public static final ItemTag WOODEN_FENCES = new ItemTag("wooden_fences"); - public static final ItemTag FENCE_GATES = new ItemTag("fence_gates"); - public static final ItemTag WOODEN_PRESSURE_PLATES = new ItemTag("wooden_pressure_plates"); - public static final ItemTag WOODEN_TRAPDOORS = new ItemTag("wooden_trapdoors"); - public static final ItemTag DOORS = new ItemTag("doors"); - public static final ItemTag SAPLINGS = new ItemTag("saplings"); - public static final ItemTag LOGS_THAT_BURN = new ItemTag("logs_that_burn"); - public static final ItemTag LOGS = new ItemTag("logs"); - public static final ItemTag DARK_OAK_LOGS = new ItemTag("dark_oak_logs"); - public static final ItemTag OAK_LOGS = new ItemTag("oak_logs"); - public static final ItemTag BIRCH_LOGS = new ItemTag("birch_logs"); - public static final ItemTag ACACIA_LOGS = new ItemTag("acacia_logs"); - public static final ItemTag CHERRY_LOGS = new ItemTag("cherry_logs"); - public static final ItemTag JUNGLE_LOGS = new ItemTag("jungle_logs"); - public static final ItemTag SPRUCE_LOGS = new ItemTag("spruce_logs"); - public static final ItemTag MANGROVE_LOGS = new ItemTag("mangrove_logs"); - public static final ItemTag CRIMSON_STEMS = new ItemTag("crimson_stems"); - public static final ItemTag WARPED_STEMS = new ItemTag("warped_stems"); - public static final ItemTag BAMBOO_BLOCKS = new ItemTag("bamboo_blocks"); - public static final ItemTag WART_BLOCKS = new ItemTag("wart_blocks"); - public static final ItemTag BANNERS = new ItemTag("banners"); - public static final ItemTag SAND = new ItemTag("sand"); - public static final ItemTag SMELTS_TO_GLASS = new ItemTag("smelts_to_glass"); - public static final ItemTag STAIRS = new ItemTag("stairs"); - public static final ItemTag SLABS = new ItemTag("slabs"); - public static final ItemTag WALLS = new ItemTag("walls"); - public static final ItemTag ANVIL = new ItemTag("anvil"); - public static final ItemTag RAILS = new ItemTag("rails"); - public static final ItemTag LEAVES = new ItemTag("leaves"); - public static final ItemTag TRAPDOORS = new ItemTag("trapdoors"); - public static final ItemTag SMALL_FLOWERS = new ItemTag("small_flowers"); - public static final ItemTag BEDS = new ItemTag("beds"); - public static final ItemTag FENCES = new ItemTag("fences"); - public static final ItemTag TALL_FLOWERS = new ItemTag("tall_flowers"); - public static final ItemTag FLOWERS = new ItemTag("flowers"); - public static final ItemTag PIGLIN_REPELLENTS = new ItemTag("piglin_repellents"); - public static final ItemTag PIGLIN_LOVED = new ItemTag("piglin_loved"); - public static final ItemTag IGNORED_BY_PIGLIN_BABIES = new ItemTag("ignored_by_piglin_babies"); - public static final ItemTag MEAT = new ItemTag("meat"); - public static final ItemTag SNIFFER_FOOD = new ItemTag("sniffer_food"); - public static final ItemTag PIGLIN_FOOD = new ItemTag("piglin_food"); - public static final ItemTag FOX_FOOD = new ItemTag("fox_food"); - public static final ItemTag COW_FOOD = new ItemTag("cow_food"); - public static final ItemTag GOAT_FOOD = new ItemTag("goat_food"); - public static final ItemTag SHEEP_FOOD = new ItemTag("sheep_food"); - public static final ItemTag WOLF_FOOD = new ItemTag("wolf_food"); - public static final ItemTag CAT_FOOD = new ItemTag("cat_food"); - public static final ItemTag HORSE_FOOD = new ItemTag("horse_food"); - public static final ItemTag HORSE_TEMPT_ITEMS = new ItemTag("horse_tempt_items"); - public static final ItemTag CAMEL_FOOD = new ItemTag("camel_food"); - public static final ItemTag ARMADILLO_FOOD = new ItemTag("armadillo_food"); - public static final ItemTag BEE_FOOD = new ItemTag("bee_food"); - public static final ItemTag CHICKEN_FOOD = new ItemTag("chicken_food"); - public static final ItemTag FROG_FOOD = new ItemTag("frog_food"); - public static final ItemTag HOGLIN_FOOD = new ItemTag("hoglin_food"); - public static final ItemTag LLAMA_FOOD = new ItemTag("llama_food"); - public static final ItemTag LLAMA_TEMPT_ITEMS = new ItemTag("llama_tempt_items"); - public static final ItemTag OCELOT_FOOD = new ItemTag("ocelot_food"); - public static final ItemTag PANDA_FOOD = new ItemTag("panda_food"); - public static final ItemTag PIG_FOOD = new ItemTag("pig_food"); - public static final ItemTag RABBIT_FOOD = new ItemTag("rabbit_food"); - public static final ItemTag STRIDER_FOOD = new ItemTag("strider_food"); - public static final ItemTag STRIDER_TEMPT_ITEMS = new ItemTag("strider_tempt_items"); - public static final ItemTag TURTLE_FOOD = new ItemTag("turtle_food"); - public static final ItemTag PARROT_FOOD = new ItemTag("parrot_food"); - public static final ItemTag PARROT_POISONOUS_FOOD = new ItemTag("parrot_poisonous_food"); - public static final ItemTag AXOLOTL_FOOD = new ItemTag("axolotl_food"); - public static final ItemTag GOLD_ORES = new ItemTag("gold_ores"); - public static final ItemTag IRON_ORES = new ItemTag("iron_ores"); - public static final ItemTag DIAMOND_ORES = new ItemTag("diamond_ores"); - public static final ItemTag REDSTONE_ORES = new ItemTag("redstone_ores"); - public static final ItemTag LAPIS_ORES = new ItemTag("lapis_ores"); - public static final ItemTag COAL_ORES = new ItemTag("coal_ores"); - public static final ItemTag EMERALD_ORES = new ItemTag("emerald_ores"); - public static final ItemTag COPPER_ORES = new ItemTag("copper_ores"); - public static final ItemTag NON_FLAMMABLE_WOOD = new ItemTag("non_flammable_wood"); - public static final ItemTag SOUL_FIRE_BASE_BLOCKS = new ItemTag("soul_fire_base_blocks"); - public static final ItemTag CANDLES = new ItemTag("candles"); - public static final ItemTag DIRT = new ItemTag("dirt"); - public static final ItemTag TERRACOTTA = new ItemTag("terracotta"); - public static final ItemTag COMPLETES_FIND_TREE_TUTORIAL = new ItemTag("completes_find_tree_tutorial"); - public static final ItemTag BOATS = new ItemTag("boats"); - public static final ItemTag CHEST_BOATS = new ItemTag("chest_boats"); - public static final ItemTag FISHES = new ItemTag("fishes"); - public static final ItemTag SIGNS = new ItemTag("signs"); - public static final ItemTag CREEPER_DROP_MUSIC_DISCS = new ItemTag("creeper_drop_music_discs"); - public static final ItemTag COALS = new ItemTag("coals"); - public static final ItemTag ARROWS = new ItemTag("arrows"); - public static final ItemTag LECTERN_BOOKS = new ItemTag("lectern_books"); - public static final ItemTag BOOKSHELF_BOOKS = new ItemTag("bookshelf_books"); - public static final ItemTag BEACON_PAYMENT_ITEMS = new ItemTag("beacon_payment_items"); - public static final ItemTag STONE_TOOL_MATERIALS = new ItemTag("stone_tool_materials"); - public static final ItemTag STONE_CRAFTING_MATERIALS = new ItemTag("stone_crafting_materials"); - public static final ItemTag FREEZE_IMMUNE_WEARABLES = new ItemTag("freeze_immune_wearables"); - public static final ItemTag DAMPENS_VIBRATIONS = new ItemTag("dampens_vibrations"); - public static final ItemTag CLUSTER_MAX_HARVESTABLES = new ItemTag("cluster_max_harvestables"); - public static final ItemTag COMPASSES = new ItemTag("compasses"); - public static final ItemTag HANGING_SIGNS = new ItemTag("hanging_signs"); - public static final ItemTag CREEPER_IGNITERS = new ItemTag("creeper_igniters"); - public static final ItemTag NOTEBLOCK_TOP_INSTRUMENTS = new ItemTag("noteblock_top_instruments"); - public static final ItemTag FOOT_ARMOR = new ItemTag("foot_armor"); - public static final ItemTag LEG_ARMOR = new ItemTag("leg_armor"); - public static final ItemTag CHEST_ARMOR = new ItemTag("chest_armor"); - public static final ItemTag HEAD_ARMOR = new ItemTag("head_armor"); - public static final ItemTag SKULLS = new ItemTag("skulls"); - public static final ItemTag TRIMMABLE_ARMOR = new ItemTag("trimmable_armor"); - public static final ItemTag TRIM_MATERIALS = new ItemTag("trim_materials"); - public static final ItemTag TRIM_TEMPLATES = new ItemTag("trim_templates"); - public static final ItemTag DECORATED_POT_SHERDS = new ItemTag("decorated_pot_sherds"); - public static final ItemTag DECORATED_POT_INGREDIENTS = new ItemTag("decorated_pot_ingredients"); - public static final ItemTag SWORDS = new ItemTag("swords"); - public static final ItemTag AXES = new ItemTag("axes"); - public static final ItemTag HOES = new ItemTag("hoes"); - public static final ItemTag PICKAXES = new ItemTag("pickaxes"); - public static final ItemTag SHOVELS = new ItemTag("shovels"); - public static final ItemTag BREAKS_DECORATED_POTS = new ItemTag("breaks_decorated_pots"); - public static final ItemTag VILLAGER_PLANTABLE_SEEDS = new ItemTag("villager_plantable_seeds"); - public static final ItemTag DYEABLE = new ItemTag("dyeable"); - public static final ItemTag ENCHANTABLE_FOOT_ARMOR = new ItemTag("enchantable/foot_armor"); - public static final ItemTag ENCHANTABLE_LEG_ARMOR = new ItemTag("enchantable/leg_armor"); - public static final ItemTag ENCHANTABLE_CHEST_ARMOR = new ItemTag("enchantable/chest_armor"); - public static final ItemTag ENCHANTABLE_HEAD_ARMOR = new ItemTag("enchantable/head_armor"); - public static final ItemTag ENCHANTABLE_ARMOR = new ItemTag("enchantable/armor"); - public static final ItemTag ENCHANTABLE_SWORD = new ItemTag("enchantable/sword"); - public static final ItemTag ENCHANTABLE_FIRE_ASPECT = new ItemTag("enchantable/fire_aspect"); - public static final ItemTag ENCHANTABLE_SHARP_WEAPON = new ItemTag("enchantable/sharp_weapon"); - public static final ItemTag ENCHANTABLE_WEAPON = new ItemTag("enchantable/weapon"); - public static final ItemTag ENCHANTABLE_MINING = new ItemTag("enchantable/mining"); - public static final ItemTag ENCHANTABLE_MINING_LOOT = new ItemTag("enchantable/mining_loot"); - public static final ItemTag ENCHANTABLE_FISHING = new ItemTag("enchantable/fishing"); - public static final ItemTag ENCHANTABLE_TRIDENT = new ItemTag("enchantable/trident"); - public static final ItemTag ENCHANTABLE_DURABILITY = new ItemTag("enchantable/durability"); - public static final ItemTag ENCHANTABLE_BOW = new ItemTag("enchantable/bow"); - public static final ItemTag ENCHANTABLE_EQUIPPABLE = new ItemTag("enchantable/equippable"); - public static final ItemTag ENCHANTABLE_CROSSBOW = new ItemTag("enchantable/crossbow"); - public static final ItemTag ENCHANTABLE_VANISHING = new ItemTag("enchantable/vanishing"); - public static final ItemTag ENCHANTABLE_MACE = new ItemTag("enchantable/mace"); + private ItemTag() {} - private final int id; - - private ItemTag(String identifier) { - this.id = ALL_ITEM_TAGS.size(); - register(identifier, this); - } - - @Override - public int ordinal() { - return id; - } - - private static void register(String name, ItemTag tag) { - ALL_ITEM_TAGS.put(MinecraftKey.key(name), tag); + private static Tag create(String name) { + return new Tag<>(JavaRegistries.ITEM, MinecraftKey.key(name)); } } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/tags/Tag.java b/core/src/main/java/org/geysermc/geyser/session/cache/tags/Tag.java new file mode 100644 index 000000000..276e30b9f --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/tags/Tag.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.session.cache.tags; + +import net.kyori.adventure.key.Key; +import org.geysermc.geyser.session.cache.registry.JavaRegistryKey; + +/** + * A tag in any of the registries that tags are loaded for by Geyser. + */ +public record Tag(JavaRegistryKey registry, Key tag) { +}