diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index 960369de746..20028ba9ffa 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -181,6 +181,7 @@ public final class EntityDefinitions { public static final EntityDefinition CHERRY_CHEST_BOAT; public static final EntityDefinition CHEST_MINECART; public static final EntityDefinition CHICKEN; + public static final EntityDefinition CORE_RINGS; public static final EntityDefinition COD; public static final EntityDefinition COMMAND_BLOCK_MINECART; public static final EntityDefinition COW; @@ -651,6 +652,10 @@ public final class EntityDefinitions { .addTranslator(MetadataTypes.ROTATIONS, ArmorStandEntity::setLeftLegRotation) .addTranslator(MetadataTypes.ROTATIONS, ArmorStandEntity::setRightLegRotation) .build(); + CORE_RINGS = EntityDefinition.inherited(ArmorStandEntity::new, ARMOR_STAND) + .identifier("playunlimited:core_rings") + .build(false); + Registries.JAVA_ENTITY_IDENTIFIERS.get().put("playunlimited:core_rings", CORE_RINGS); PLAYER = EntityDefinition.inherited(null, livingEntityBase) .type(EntityType.PLAYER) .height(1.8f).width(0.6f) @@ -973,10 +978,12 @@ public final class EntityDefinitions { .build(); CHICKEN = EntityDefinition.inherited(ChickenEntity::new, ageableEntityBase) .type(EntityType.CHICKEN) + .identifier("playunlimited:playunlimited") .height(0.7f).width(0.4f) .properties(VanillaEntityProperties.CLIMATE_VARIANT) .addTranslator(MetadataTypes.CHICKEN_VARIANT, ChickenEntity::setVariant) .build(); + Registries.JAVA_ENTITY_IDENTIFIERS.get().put("playunlimited:playunlimited", CHICKEN); COW = EntityDefinition.inherited(CowEntity::new, ageableEntityBase) .type(EntityType.COW) .height(1.4f).width(0.9f) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java index afbdcca31f7..df2b9a74fcc 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java @@ -293,6 +293,18 @@ public void setBoots(GeyserItemStack boots) { public void setHand(GeyserItemStack hand) { super.setHand(hand); updateSecondEntityStatus(true); + + if (!hand.isEmpty() && hand.asItem() == Items.GRASS_BLOCK) { + if (this.definition != EntityDefinitions.CORE_RINGS) { + despawnEntity(); + this.definition = EntityDefinitions.CORE_RINGS; + spawnEntity(); + } + } else if (this.definition == EntityDefinitions.CORE_RINGS) { + despawnEntity(); + this.definition = EntityDefinitions.ARMOR_STAND; + spawnEntity(); + } } @Override diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java index d2c0e26b250..e1d601f5849 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -31,6 +31,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.biome.BiomeDefinitions; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.PotionMixData; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; @@ -71,6 +72,7 @@ import java.util.EnumMap; import java.util.HashSet; import java.util.IdentityHashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -206,6 +208,34 @@ public static void load() { // (by using the Items or Blocks class, which loads all the blocks) BEDROCK_ENTITY_IDENTIFIERS.load(); + // Add custom entity identifiers for PlayUnlimited entities + NbtMap identifiers = BEDROCK_ENTITY_IDENTIFIERS.get(); + List idList = new ArrayList<>(identifiers.getList("idlist", NbtType.COMPOUND)); + int nextRid = idList.stream().mapToInt(map -> map.getInt("rid")).max().orElse(-1) + 1; + + for (int i = 0; i < idList.size(); i++) { + NbtMap map = idList.get(i); + if ("minecraft:chicken".equals(map.getString("id"))) { + idList.set(i, NbtMap.builder() + .putString("id", "playunlimited:playunlimited") + .putShort("bid", map.getShort("bid")) + .putInt("rid", map.getInt("rid")) + .putBoolean("summonable", true) + .putBoolean("hasSpawnEgg", map.getBoolean("hasSpawnEgg")) + .build()); + break; + } + } + + idList.add(NbtMap.builder() + .putString("id", "playunlimited:core_rings") + .putShort("bid", (short) 0) + .putInt("rid", nextRid) + .putBoolean("summonable", true) + .putBoolean("hasSpawnEgg", false) + .build()); + + BEDROCK_ENTITY_IDENTIFIERS.set(NbtMap.builder().putList("idlist", NbtType.COMPOUND, idList).build()); BIOMES_NBT.load(); BIOMES.load(); BIOME_IDENTIFIERS.load(); diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java index 71aaa948cee..cedb01b0917 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java @@ -82,7 +82,7 @@ public class ResourcePackLoader implements RegistryLoader load(Path directory) { */ public static GeyserResourcePack.Builder readPack(Path path) throws IllegalArgumentException { if (!PACK_MATCHER.matches(path)) { - throw new IllegalArgumentException("Resource pack " + path.getFileName() + " must be a .zip or .mcpack file!"); + throw new IllegalArgumentException("Resource pack " + path.getFileName() + " must be a .zip, .mcpack or .mcaddon file!"); } ResourcePackManifest manifest = readManifest(path, path.getFileName().toString());