From 1316321c7fc5ce438527b7bb5881f26bf980fe19 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Tue, 22 Aug 2023 06:05:47 +0300
Subject: [PATCH] Expand Pose API (#8781)

---
 patches/api/Expand-Pose-API.patch             | 53 +++++++++++++++++++
 patches/server/Expand-Pose-API.patch          | 51 ++++++++++++++++++
 .../server/Fix-NPE-on-Boat-getStatus.patch    |  2 +-
 3 files changed, 105 insertions(+), 1 deletion(-)
 create mode 100644 patches/api/Expand-Pose-API.patch
 create mode 100644 patches/server/Expand-Pose-API.patch

diff --git a/patches/api/Expand-Pose-API.patch b/patches/api/Expand-Pose-API.patch
new file mode 100644
index 0000000000..1863058f69
--- /dev/null
+++ b/patches/api/Expand-Pose-API.patch
@@ -0,0 +1,53 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: SoSeDiK <mrsosedik@gmail.com>
+Date: Wed, 11 Jan 2023 20:59:02 +0200
+Subject: [PATCH] Expand Pose API
+
+
+diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/entity/Entity.java
++++ b/src/main/java/org/bukkit/entity/Entity.java
+@@ -0,0 +0,0 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
+      * @param sneak true if the entity should be sneaking
+      */
+     void setSneaking(boolean sneak);
++
++    /**
++     * Sets the entity's current {@link Pose}.
++     *
++     * <p>Note: While poses affect some things like hitboxes, they do not change the entity's state
++     * (e.g. having {@link Pose#SNEAKING} does not guarantee {@link #isSneaking()} being {@code true}).
++     *
++     * <p>If applied to the {@link Player}, they might see a different pose client-side.
++     *
++     * @param pose a new {@link Pose}
++     * @see #setPose(Pose, boolean)
++     */
++    default void setPose(@NotNull Pose pose) {
++        setPose(pose, false);
++    }
++
++    /**
++     * Sets the entity's current {@link Pose}.
++     *
++     * <p>Note: While poses affect some things like hitboxes, they do not change the entity's state
++     * (e.g. having {@link Pose#SNEAKING} does not guarantee {@link #isSneaking()} being {@code true}).
++     *
++     * <p>If applied to the {@link Player}, they might see a different pose client-side.
++     *
++     * @param pose a new {@link Pose}
++     * @param fixed whether the new {@link Pose} should stay until manually changed
++     */
++    void setPose(@NotNull Pose pose, boolean fixed);
++
++    /**
++     * Checks whether the entity has a fixed {@link Pose}
++     *
++     * @see #setPose(Pose, boolean)
++     * @return whether the entity has a fixed {@link Pose}
++     */
++    boolean hasFixedPose();
+     // Paper end
+ 
+     /**
diff --git a/patches/server/Expand-Pose-API.patch b/patches/server/Expand-Pose-API.patch
new file mode 100644
index 0000000000..4b0741d583
--- /dev/null
+++ b/patches/server/Expand-Pose-API.patch
@@ -0,0 +1,51 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: SoSeDiK <mrsosedik@gmail.com>
+Date: Wed, 11 Jan 2023 20:59:01 +0200
+Subject: [PATCH] Expand Pose API
+
+
+diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/world/entity/Entity.java
++++ b/src/main/java/net/minecraft/world/entity/Entity.java
+@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+     private UUID originWorld;
+     public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
+     public boolean collidingWithWorldBorder; // Paper
++    public boolean fixedPose = false; // Paper
+ 
+     public void setOrigin(@javax.annotation.Nonnull Location location) {
+         this.origin = location.toVector();
+@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+     public void onClientRemoval() {}
+ 
+     public void setPose(net.minecraft.world.entity.Pose pose) {
++        if (this.fixedPose) return; // Paper
+         // CraftBukkit start
+         if (pose == this.getPose()) {
+             return;
+diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
+     public boolean isSneaking() {
+         return this.getHandle().isShiftKeyDown();
+     }
++
++    @Override
++    public void setPose(Pose pose, boolean fixed) {
++        Preconditions.checkNotNull(pose, "Pose cannot be null");
++        final Entity handle = this.getHandle();
++        handle.fixedPose = false;
++        handle.setPose(net.minecraft.world.entity.Pose.values()[pose.ordinal()]);
++        handle.fixedPose = fixed;
++    }
++
++    @Override
++    public boolean hasFixedPose() {
++        return this.getHandle().fixedPose;
++    }
+     // Paper end
+ 
+     @Override
diff --git a/patches/server/Fix-NPE-on-Boat-getStatus.patch b/patches/server/Fix-NPE-on-Boat-getStatus.patch
index 7255b77668..03913bcaf5 100644
--- a/patches/server/Fix-NPE-on-Boat-getStatus.patch
+++ b/patches/server/Fix-NPE-on-Boat-getStatus.patch
@@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        if (handle.status == null) {
 +            if (handle.valid && !handle.updatingSectionStatus) {
 +                // Don't actually set the status because it would skew the old status check in the next tick
-+                return CraftBoat.boatStatusFromNms(this.getHandle().getStatus());
++                return CraftBoat.boatStatusFromNms(handle.getStatus());
 +            } else {
 +                return Status.NOT_IN_WORLD;
 +            }