diff --git a/paper-api/src/main/java/io/papermc/paper/InternalAPIBridge.java b/paper-api/src/main/java/io/papermc/paper/InternalAPIBridge.java index 609b4b1c7d97..7031a6bc9e60 100644 --- a/paper-api/src/main/java/io/papermc/paper/InternalAPIBridge.java +++ b/paper-api/src/main/java/io/papermc/paper/InternalAPIBridge.java @@ -5,6 +5,7 @@ import io.papermc.paper.datacomponent.item.ResolvableProfile; import io.papermc.paper.world.damagesource.CombatEntry; import io.papermc.paper.world.damagesource.FallLocationType; +import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; import net.kyori.adventure.text.Component; @@ -14,6 +15,7 @@ import org.bukkit.damage.DamageEffect; import org.bukkit.damage.DamageSource; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Pose; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jspecify.annotations.NullMarked; @@ -100,4 +102,6 @@ class Holder { Component defaultMannequinDescription(); GameRule legacyGameRuleBridge(GameRule rule, Function fromLegacyToModern, Function toLegacyFromModern, Class legacyClass); + + Set validMannequinPoses(); } diff --git a/paper-api/src/main/java/org/bukkit/entity/Mannequin.java b/paper-api/src/main/java/org/bukkit/entity/Mannequin.java index 02555b387d56..2d19a56096b2 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Mannequin.java +++ b/paper-api/src/main/java/org/bukkit/entity/Mannequin.java @@ -3,6 +3,7 @@ import com.destroystokyo.paper.SkinParts; import io.papermc.paper.InternalAPIBridge; import io.papermc.paper.datacomponent.item.ResolvableProfile; +import java.util.Set; import net.kyori.adventure.text.Component; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.MainHand; @@ -12,6 +13,15 @@ @NullMarked public interface Mannequin extends LivingEntity { + /** + * Returns the valid poses for a mannequin. + * + * @return the valid poses + */ + static Set validPoses() { + return InternalAPIBridge.get().validMannequinPoses(); + } + /** * Returns the default mannequin profile. * diff --git a/paper-server/src/main/java/io/papermc/paper/PaperServerInternalAPIBridge.java b/paper-server/src/main/java/io/papermc/paper/PaperServerInternalAPIBridge.java index f7979f188c3d..7435a9ebb62f 100644 --- a/paper-server/src/main/java/io/papermc/paper/PaperServerInternalAPIBridge.java +++ b/paper-server/src/main/java/io/papermc/paper/PaperServerInternalAPIBridge.java @@ -10,6 +10,7 @@ import io.papermc.paper.world.damagesource.FallLocationType; import io.papermc.paper.world.damagesource.PaperCombatEntryWrapper; import io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper; +import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; import net.kyori.adventure.text.Component; @@ -24,9 +25,11 @@ import org.bukkit.craftbukkit.damage.CraftDamageEffect; import org.bukkit.craftbukkit.damage.CraftDamageSource; import org.bukkit.craftbukkit.entity.CraftLivingEntity; +import org.bukkit.craftbukkit.entity.CraftMannequin; import org.bukkit.damage.DamageEffect; import org.bukkit.damage.DamageSource; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Pose; import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; @@ -116,4 +119,9 @@ public Component defaultMannequinDescription() { public GameRule legacyGameRuleBridge(GameRule rule, Function fromLegacyToModern, Function toLegacyFromModern, Class legacyClass) { return CraftGameRule.wrap(rule, fromLegacyToModern, toLegacyFromModern, legacyClass); } + + @Override + public Set validMannequinPoses() { + return CraftMannequin.VALID_POSES; + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMannequin.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMannequin.java index c22c295114ff..869452f4f356 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMannequin.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMannequin.java @@ -6,6 +6,8 @@ import io.papermc.paper.adventure.PaperAdventure; import io.papermc.paper.datacomponent.item.PaperResolvableProfile; import io.papermc.paper.datacomponent.item.ResolvableProfile; +import java.util.Set; +import java.util.stream.Collectors; import net.kyori.adventure.text.Component; import net.minecraft.Optionull; import net.minecraft.world.entity.Avatar; @@ -19,6 +21,10 @@ @NullMarked public class CraftMannequin extends CraftLivingEntity implements Mannequin { + + public static final Set VALID_POSES = net.minecraft.world.entity.decoration.Mannequin.VALID_POSES.stream() + .map(pose -> Pose.values()[pose.ordinal()]).collect(Collectors.toUnmodifiableSet()); + public CraftMannequin(final CraftServer server, final net.minecraft.world.entity.decoration.Mannequin entity) { super(server, entity); } @@ -31,15 +37,11 @@ public net.minecraft.world.entity.decoration.Mannequin getHandle() { @Override public void setPose(Pose pose, boolean fixed) { Preconditions.checkArgument(pose != null, "pose cannot be null"); - net.minecraft.world.entity.Pose internalPose = net.minecraft.world.entity.Pose.values()[pose.ordinal()]; - if (!net.minecraft.world.entity.decoration.Mannequin.VALID_POSES.contains(internalPose)) { - throw new IllegalArgumentException("Invalid pose '%s', expected one of: %s".formatted( - pose.name(), - net.minecraft.world.entity.decoration.Mannequin.VALID_POSES.stream().map(p -> Pose.values()[p.ordinal()]).toList() // name doesn't match - )); + if (!VALID_POSES.contains(pose)) { + throw new IllegalArgumentException("Invalid pose '%s', expected one of: %s".formatted(pose.name(), VALID_POSES)); } - this.setPose0(internalPose, fixed); + this.setPose0(net.minecraft.world.entity.Pose.values()[pose.ordinal()], fixed); } @Override