From 2fe58b4b773e4d6d5bfb9988c889255faa5f2c38 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Mar 2026 23:08:03 +0000 Subject: [PATCH 1/6] Initial plan From 6c8542d9b7cf6860a1b038832ce4dc217d86889e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Mar 2026 23:27:06 +0000 Subject: [PATCH 2/6] Add WrappedPositionMoveRotation and getPositionMoveRotation() for 1.21.2+ packet support Agent-Logs-Url: https://github.com/dmulloy2/ProtocolLib/sessions/a2043827-e96e-4714-b875-8ca66b72e91b Co-authored-by: dmulloy2 <3039119+dmulloy2@users.noreply.github.com> --- .../protocol/events/AbstractStructure.java | 15 ++ .../protocol/utility/MinecraftReflection.java | 9 + .../wrappers/WrappedPositionMoveRotation.java | 181 ++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 src/main/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotation.java diff --git a/src/main/java/com/comphenix/protocol/events/AbstractStructure.java b/src/main/java/com/comphenix/protocol/events/AbstractStructure.java index 47c87caf2..6b3703152 100644 --- a/src/main/java/com/comphenix/protocol/events/AbstractStructure.java +++ b/src/main/java/com/comphenix/protocol/events/AbstractStructure.java @@ -55,6 +55,7 @@ import com.comphenix.protocol.wrappers.WrappedMessageSignature; import com.comphenix.protocol.wrappers.WrappedNumberFormat; import com.comphenix.protocol.wrappers.WrappedParticle; +import com.comphenix.protocol.wrappers.WrappedPositionMoveRotation; import com.comphenix.protocol.wrappers.WrappedProfilePublicKey; import com.comphenix.protocol.wrappers.WrappedProfilePublicKey.WrappedProfileKeyData; import com.comphenix.protocol.wrappers.WrappedRegistrable; @@ -1297,6 +1298,20 @@ public StructureModifier> getPacketBundles() { )); } + /** + * Retrieve a read/write structure for {@link WrappedPositionMoveRotation} (available since Minecraft 1.21.2). + *

+ * This is used in packets such as {@code ENTITY_TELEPORT} and {@code ENTITY_POSITION_SYNC}. + * + * @return A modifier for PositionMoveRotation fields. + */ + public StructureModifier getPositionMoveRotation() { + return structureModifier.withType( + MinecraftReflection.getPositionMoveRotationClass(), + WrappedPositionMoveRotation.getConverter() + ); + } + /** * Represents an equivalent converter for ItemStack arrays. * @author Kristian diff --git a/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java b/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java index 9f474921e..62f3f0116 100644 --- a/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java +++ b/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java @@ -1903,4 +1903,13 @@ public static boolean isMojangMapped() { return isMojangMapped; } + + /** + * Retrieves the PositionMoveRotation class (introduced in 1.21.2). + * + * @return The PositionMoveRotation class. + */ + public static Class getPositionMoveRotationClass() { + return getMinecraftClass("network.protocol.game.PositionMoveRotation"); + } } diff --git a/src/main/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotation.java b/src/main/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotation.java new file mode 100644 index 000000000..124cc3b2e --- /dev/null +++ b/src/main/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotation.java @@ -0,0 +1,181 @@ +package com.comphenix.protocol.wrappers; + +import com.comphenix.protocol.reflect.EquivalentConverter; +import com.comphenix.protocol.reflect.StructureModifier; +import com.comphenix.protocol.reflect.accessors.Accessors; +import com.comphenix.protocol.reflect.accessors.ConstructorAccessor; +import com.comphenix.protocol.utility.MinecraftReflection; + +import org.bukkit.util.Vector; + +/** + * Wrapper around the NMS {@code PositionMoveRotation} record, introduced in Minecraft 1.21.2. + *

+ * This type is used in packets such as {@code ENTITY_TELEPORT} and {@code ENTITY_POSITION_SYNC} + * to represent combined position, movement delta and rotation. + *

+ * Example usage: + *

{@code
+ * WrappedPositionMoveRotation posRot = WrappedPositionMoveRotation.create(
+ *         new Vector(x, y, z),   // position
+ *         new Vector(0, 0, 0),   // deltaMovement
+ *         yaw,                   // yRot
+ *         pitch                  // xRot
+ * );
+ * packet.getPositionMoveRotation().write(0, posRot);
+ * }
+ */ +public class WrappedPositionMoveRotation extends AbstractWrapper { + + private static Class HANDLE_TYPE; + private static ConstructorAccessor CONSTRUCTOR; + private static StructureModifier BASE_MODIFIER; + + private final StructureModifier modifier; + + private WrappedPositionMoveRotation(Object handle) { + super(getHandleType()); + setHandle(handle); + this.modifier = getBaseModifier().withTarget(handle); + } + + private static Class getHandleType() { + if (HANDLE_TYPE == null) { + HANDLE_TYPE = MinecraftReflection.getPositionMoveRotationClass(); + } + return HANDLE_TYPE; + } + + private static StructureModifier getBaseModifier() { + if (BASE_MODIFIER == null) { + BASE_MODIFIER = new StructureModifier<>(getHandleType()); + } + return BASE_MODIFIER; + } + + private static ConstructorAccessor getConstructor() { + if (CONSTRUCTOR == null) { + CONSTRUCTOR = Accessors.getConstructorAccessor( + getHandleType(), + MinecraftReflection.getVec3DClass(), + MinecraftReflection.getVec3DClass(), + float.class, + float.class + ); + } + return CONSTRUCTOR; + } + + /** + * Creates a new {@code WrappedPositionMoveRotation} from the given NMS handle. + * + * @param handle - the NMS {@code PositionMoveRotation} instance. + * @return the wrapper. + */ + public static WrappedPositionMoveRotation fromHandle(Object handle) { + return new WrappedPositionMoveRotation(handle); + } + + /** + * Creates a new {@code WrappedPositionMoveRotation} with the given values. + * + * @param position - the absolute position. + * @param deltaMovement - the movement delta (velocity). + * @param yRot - the yaw rotation. + * @param xRot - the pitch rotation. + * @return a new wrapper instance. + */ + public static WrappedPositionMoveRotation create(Vector position, Vector deltaMovement, float yRot, float xRot) { + EquivalentConverter conv = BukkitConverters.getVectorConverter(); + Object handle = getConstructor().invoke( + conv.getGeneric(position), + conv.getGeneric(deltaMovement), + yRot, + xRot + ); + return new WrappedPositionMoveRotation(handle); + } + + /** + * Retrieves the absolute position component. + * + * @return the position as a Bukkit {@link Vector}. + */ + public Vector getPosition() { + return modifier.withType(MinecraftReflection.getVec3DClass(), BukkitConverters.getVectorConverter()).read(0); + } + + /** + * Sets the absolute position component. + * + * @param position - the new position. + */ + public void setPosition(Vector position) { + modifier.withType(MinecraftReflection.getVec3DClass(), BukkitConverters.getVectorConverter()).write(0, position); + } + + /** + * Retrieves the movement delta (velocity) component. + * + * @return the delta movement as a Bukkit {@link Vector}. + */ + public Vector getDeltaMovement() { + return modifier.withType(MinecraftReflection.getVec3DClass(), BukkitConverters.getVectorConverter()).read(1); + } + + /** + * Sets the movement delta (velocity) component. + * + * @param deltaMovement - the new delta movement. + */ + public void setDeltaMovement(Vector deltaMovement) { + modifier.withType(MinecraftReflection.getVec3DClass(), BukkitConverters.getVectorConverter()).write(1, deltaMovement); + } + + /** + * Retrieves the yaw rotation (y-axis rotation). + * + * @return the yaw as a float. + */ + public float getYRot() { + return modifier.withType(float.class).read(0); + } + + /** + * Sets the yaw rotation (y-axis rotation). + * + * @param yRot - the new yaw value. + */ + public void setYRot(float yRot) { + modifier.withType(float.class).write(0, yRot); + } + + /** + * Retrieves the pitch rotation (x-axis rotation). + * + * @return the pitch as a float. + */ + public float getXRot() { + return modifier.withType(float.class).read(1); + } + + /** + * Sets the pitch rotation (x-axis rotation). + * + * @param xRot - the new pitch value. + */ + public void setXRot(float xRot) { + modifier.withType(float.class).write(1, xRot); + } + + /** + * Returns an {@link EquivalentConverter} that converts between {@code WrappedPositionMoveRotation} + * and the underlying NMS handle. + * + * @return the converter. + */ + public static EquivalentConverter getConverter() { + return Converters.handle(AbstractWrapper::getHandle, + WrappedPositionMoveRotation::fromHandle, WrappedPositionMoveRotation.class); + } +} From bec4eacd731f3469e7040a9ab60da62383f0adf0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 00:44:05 +0000 Subject: [PATCH 3/6] Fix WrappedPositionMoveRotation compilation errors and add unit tests Agent-Logs-Url: https://github.com/dmulloy2/ProtocolLib/sessions/aad8f880-cbb2-49a9-8f74-21794fdd8e60 Co-authored-by: dmulloy2 <3039119+dmulloy2@users.noreply.github.com> --- .../wrappers/WrappedPositionMoveRotation.java | 22 ++-- .../WrappedPositionMoveRotationTest.java | 113 ++++++++++++++++++ 2 files changed, 125 insertions(+), 10 deletions(-) create mode 100644 src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java diff --git a/src/main/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotation.java b/src/main/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotation.java index 124cc3b2e..7bce1b2d5 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotation.java +++ b/src/main/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotation.java @@ -27,28 +27,28 @@ */ public class WrappedPositionMoveRotation extends AbstractWrapper { - private static Class HANDLE_TYPE; + private static Class NMS_CLASS; private static ConstructorAccessor CONSTRUCTOR; private static StructureModifier BASE_MODIFIER; private final StructureModifier modifier; private WrappedPositionMoveRotation(Object handle) { - super(getHandleType()); + super(getNmsClass()); setHandle(handle); this.modifier = getBaseModifier().withTarget(handle); } - private static Class getHandleType() { - if (HANDLE_TYPE == null) { - HANDLE_TYPE = MinecraftReflection.getPositionMoveRotationClass(); + private static Class getNmsClass() { + if (NMS_CLASS == null) { + NMS_CLASS = MinecraftReflection.getPositionMoveRotationClass(); } - return HANDLE_TYPE; + return NMS_CLASS; } private static StructureModifier getBaseModifier() { if (BASE_MODIFIER == null) { - BASE_MODIFIER = new StructureModifier<>(getHandleType()); + BASE_MODIFIER = new StructureModifier<>(getNmsClass()); } return BASE_MODIFIER; } @@ -56,7 +56,7 @@ private static StructureModifier getBaseModifier() { private static ConstructorAccessor getConstructor() { if (CONSTRUCTOR == null) { CONSTRUCTOR = Accessors.getConstructorAccessor( - getHandleType(), + getNmsClass(), MinecraftReflection.getVec3DClass(), MinecraftReflection.getVec3DClass(), float.class, @@ -138,7 +138,8 @@ public void setDeltaMovement(Vector deltaMovement) { * @return the yaw as a float. */ public float getYRot() { - return modifier.withType(float.class).read(0); + StructureModifier floats = modifier.withType(float.class); + return floats.read(0); } /** @@ -156,7 +157,8 @@ public void setYRot(float yRot) { * @return the pitch as a float. */ public float getXRot() { - return modifier.withType(float.class).read(1); + StructureModifier floats = modifier.withType(float.class); + return floats.read(1); } /** diff --git a/src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java b/src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java new file mode 100644 index 000000000..1055832a9 --- /dev/null +++ b/src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java @@ -0,0 +1,113 @@ +package com.comphenix.protocol.wrappers; + +import com.comphenix.protocol.BukkitInitialization; +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; + +import org.bukkit.util.Vector; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class WrappedPositionMoveRotationTest { + + @BeforeAll + public static void beforeClass() { + BukkitInitialization.initializeAll(); + } + + @Test + public void testCreateAndRead() { + Vector position = new Vector(1.5, 64.0, -3.5); + Vector delta = new Vector(0.1, -0.05, 0.2); + float yRot = 45.0f; + float xRot = -10.0f; + + WrappedPositionMoveRotation created = WrappedPositionMoveRotation.create(position, delta, yRot, xRot); + + assertEquals(position.getX(), created.getPosition().getX(), 1e-6); + assertEquals(position.getY(), created.getPosition().getY(), 1e-6); + assertEquals(position.getZ(), created.getPosition().getZ(), 1e-6); + + assertEquals(delta.getX(), created.getDeltaMovement().getX(), 1e-6); + assertEquals(delta.getY(), created.getDeltaMovement().getY(), 1e-6); + assertEquals(delta.getZ(), created.getDeltaMovement().getZ(), 1e-6); + + assertEquals(yRot, created.getYRot(), 1e-6f); + assertEquals(xRot, created.getXRot(), 1e-6f); + } + + @Test + public void testEntityPositionSyncPacket() { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_POSITION_SYNC); + + Vector position = new Vector(10.0, 70.0, -5.0); + Vector delta = new Vector(0.0, 0.0, 0.0); + float yRot = 90.0f; + float xRot = 0.0f; + + packet.getPositionMoveRotation().write(0, + WrappedPositionMoveRotation.create(position, delta, yRot, xRot)); + + WrappedPositionMoveRotation result = packet.getPositionMoveRotation().read(0); + + assertNotNull(result); + + assertEquals(position.getX(), result.getPosition().getX(), 1e-6); + assertEquals(position.getY(), result.getPosition().getY(), 1e-6); + assertEquals(position.getZ(), result.getPosition().getZ(), 1e-6); + + assertEquals(delta.getX(), result.getDeltaMovement().getX(), 1e-6); + assertEquals(delta.getY(), result.getDeltaMovement().getY(), 1e-6); + assertEquals(delta.getZ(), result.getDeltaMovement().getZ(), 1e-6); + + assertEquals(yRot, result.getYRot(), 1e-6f); + assertEquals(xRot, result.getXRot(), 1e-6f); + } + + @Test + public void testEntityTeleportPacket() { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT); + + Vector position = new Vector(-100.5, 200.0, 300.75); + Vector delta = new Vector(0.0, 0.0, 0.0); + float yRot = 180.0f; + float xRot = 30.0f; + + packet.getPositionMoveRotation().write(0, + WrappedPositionMoveRotation.create(position, delta, yRot, xRot)); + + WrappedPositionMoveRotation result = packet.getPositionMoveRotation().read(0); + + assertNotNull(result); + + assertEquals(position.getX(), result.getPosition().getX(), 1e-6); + assertEquals(position.getY(), result.getPosition().getY(), 1e-6); + assertEquals(position.getZ(), result.getPosition().getZ(), 1e-6); + + assertEquals(delta.getX(), result.getDeltaMovement().getX(), 1e-6); + assertEquals(delta.getY(), result.getDeltaMovement().getY(), 1e-6); + assertEquals(delta.getZ(), result.getDeltaMovement().getZ(), 1e-6); + + assertEquals(yRot, result.getYRot(), 1e-6f); + assertEquals(xRot, result.getXRot(), 1e-6f); + } + + @Test + public void testFromHandle() { + Vector position = new Vector(5.0, 65.0, 5.0); + Vector delta = new Vector(0.0, -0.1, 0.0); + float yRot = 270.0f; + float xRot = -45.0f; + + WrappedPositionMoveRotation original = WrappedPositionMoveRotation.create(position, delta, yRot, xRot); + WrappedPositionMoveRotation fromHandle = WrappedPositionMoveRotation.fromHandle(original.getHandle()); + + assertEquals(original.getPosition().getX(), fromHandle.getPosition().getX(), 1e-6); + assertEquals(original.getPosition().getY(), fromHandle.getPosition().getY(), 1e-6); + assertEquals(original.getPosition().getZ(), fromHandle.getPosition().getZ(), 1e-6); + assertEquals(original.getYRot(), fromHandle.getYRot(), 1e-6f); + assertEquals(original.getXRot(), fromHandle.getXRot(), 1e-6f); + } +} From ea013313768c0ab022c0184ad06f6090c5cba9c6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 00:52:38 +0000 Subject: [PATCH 4/6] Fix PositionMoveRotation package: world.entity not network.protocol.game Agent-Logs-Url: https://github.com/dmulloy2/ProtocolLib/sessions/d78c114a-498c-4ea3-84c0-1ea88a84865c Co-authored-by: dmulloy2 <3039119+dmulloy2@users.noreply.github.com> --- .../com/comphenix/protocol/utility/MinecraftReflection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java b/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java index 62f3f0116..3486265fe 100644 --- a/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java +++ b/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java @@ -1910,6 +1910,6 @@ public static boolean isMojangMapped() { * @return The PositionMoveRotation class. */ public static Class getPositionMoveRotationClass() { - return getMinecraftClass("network.protocol.game.PositionMoveRotation"); + return getMinecraftClass("world.entity.PositionMoveRotation"); } } From e8a382ea48f2a0c9160e7739de2e1030ca83edb8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 01:01:54 +0000 Subject: [PATCH 5/6] Simplify testFromHandle: use create() for NMS handle, assert constant values Agent-Logs-Url: https://github.com/dmulloy2/ProtocolLib/sessions/b61d9e0d-18ea-4386-9316-9733b409a4cc Co-authored-by: dmulloy2 <3039119+dmulloy2@users.noreply.github.com> --- .../WrappedPositionMoveRotationTest.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java b/src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java index 1055832a9..56667fb79 100644 --- a/src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java +++ b/src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java @@ -96,18 +96,23 @@ public void testEntityTeleportPacket() { @Test public void testFromHandle() { - Vector position = new Vector(5.0, 65.0, 5.0); - Vector delta = new Vector(0.0, -0.1, 0.0); - float yRot = 270.0f; - float xRot = -45.0f; - - WrappedPositionMoveRotation original = WrappedPositionMoveRotation.create(position, delta, yRot, xRot); - WrappedPositionMoveRotation fromHandle = WrappedPositionMoveRotation.fromHandle(original.getHandle()); - - assertEquals(original.getPosition().getX(), fromHandle.getPosition().getX(), 1e-6); - assertEquals(original.getPosition().getY(), fromHandle.getPosition().getY(), 1e-6); - assertEquals(original.getPosition().getZ(), fromHandle.getPosition().getZ(), 1e-6); - assertEquals(original.getYRot(), fromHandle.getYRot(), 1e-6f); - assertEquals(original.getXRot(), fromHandle.getXRot(), 1e-6f); + // Build a NMS PositionMoveRotation via create() and grab its raw handle + Object nmsHandle = WrappedPositionMoveRotation.create( + new Vector(5.0, 65.0, 5.0), + new Vector(0.0, -0.1, 0.0), + 270.0f, -45.0f).getHandle(); + + WrappedPositionMoveRotation wrapper = WrappedPositionMoveRotation.fromHandle(nmsHandle); + + assertEquals(5.0, wrapper.getPosition().getX(), 1e-6); + assertEquals(65.0, wrapper.getPosition().getY(), 1e-6); + assertEquals(5.0, wrapper.getPosition().getZ(), 1e-6); + + assertEquals(0.0, wrapper.getDeltaMovement().getX(), 1e-6); + assertEquals(-0.1, wrapper.getDeltaMovement().getY(), 1e-6); + assertEquals(0.0, wrapper.getDeltaMovement().getZ(), 1e-6); + + assertEquals(270.0f, wrapper.getYRot(), 1e-6f); + assertEquals(-45.0f, wrapper.getXRot(), 1e-6f); } } From c48a67d6046bc617ff3aea6caa7148bfe6114cba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 01:05:50 +0000 Subject: [PATCH 6/6] Construct NMS PositionMoveRotation directly in testFromHandle Agent-Logs-Url: https://github.com/dmulloy2/ProtocolLib/sessions/c0b73ba6-894f-4182-b21f-6bf6675c214f Co-authored-by: dmulloy2 <3039119+dmulloy2@users.noreply.github.com> --- .../wrappers/WrappedPositionMoveRotationTest.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java b/src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java index 56667fb79..f5962c366 100644 --- a/src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java +++ b/src/test/java/com/comphenix/protocol/wrappers/WrappedPositionMoveRotationTest.java @@ -4,6 +4,8 @@ import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.PacketContainer; +import net.minecraft.world.entity.PositionMoveRotation; +import net.minecraft.world.phys.Vec3; import org.bukkit.util.Vector; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -96,11 +98,11 @@ public void testEntityTeleportPacket() { @Test public void testFromHandle() { - // Build a NMS PositionMoveRotation via create() and grab its raw handle - Object nmsHandle = WrappedPositionMoveRotation.create( - new Vector(5.0, 65.0, 5.0), - new Vector(0.0, -0.1, 0.0), - 270.0f, -45.0f).getHandle(); + PositionMoveRotation nmsHandle = new PositionMoveRotation( + new Vec3(5.0, 65.0, 5.0), + new Vec3(0.0, -0.1, 0.0), + 270.0f, + -45.0f); WrappedPositionMoveRotation wrapper = WrappedPositionMoveRotation.fromHandle(nmsHandle);