From 46f4fdaae3661941ac86f2157e625d907fdd8e81 Mon Sep 17 00:00:00 2001 From: David <54660361+NonSwag@users.noreply.github.com> Date: Wed, 12 Feb 2025 23:30:41 +0100 Subject: [PATCH] Add support for rotation argument handling (#12090) --- .../brigadier/argument/ArgumentTypes.java | 10 +++++ .../argument/VanillaArgumentProvider.java | 3 ++ .../argument/resolvers/RotationResolver.java | 16 ++++++++ .../java/io/papermc/paper/math/Rotation.java | 34 +++++++++++++++ .../io/papermc/paper/math/RotationImpl.java | 4 ++ .../src/main/java/org/bukkit/Location.java | 41 +++++++++++++++++++ .../argument/VanillaArgumentProviderImpl.java | 13 ++++++ 7 files changed, 121 insertions(+) create mode 100644 paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/resolvers/RotationResolver.java create mode 100644 paper-api/src/main/java/io/papermc/paper/math/Rotation.java create mode 100644 paper-api/src/main/java/io/papermc/paper/math/RotationImpl.java diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/ArgumentTypes.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/ArgumentTypes.java index 9abb9ff336..440cfcfa58 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/ArgumentTypes.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/ArgumentTypes.java @@ -7,6 +7,7 @@ import io.papermc.paper.command.brigadier.argument.range.IntegerRangeProvider; import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver; import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver; import io.papermc.paper.command.brigadier.argument.resolvers.PlayerProfileListResolver; +import io.papermc.paper.command.brigadier.argument.resolvers.RotationResolver; import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver; import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver; import io.papermc.paper.entity.LookAnchor; @@ -123,6 +124,15 @@ public final class ArgumentTypes { return provider().finePosition(centerIntegers); } + /** + * A rotation argument. + * + * @return rotation argument + */ + public static ArgumentType rotation() { + return provider().rotation(); + } + /** * A blockstate argument which will provide rich parsing for specifying * the specific block variant and then the block entity NBT if applicable. diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProvider.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProvider.java index 4f640bd3e5..7f30fc567d 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProvider.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProvider.java @@ -7,6 +7,7 @@ import io.papermc.paper.command.brigadier.argument.range.IntegerRangeProvider; import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver; import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver; import io.papermc.paper.command.brigadier.argument.resolvers.PlayerProfileListResolver; +import io.papermc.paper.command.brigadier.argument.resolvers.RotationResolver; import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver; import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver; import io.papermc.paper.entity.LookAnchor; @@ -57,6 +58,8 @@ interface VanillaArgumentProvider { ArgumentType finePosition(boolean centerIntegers); + ArgumentType rotation(); + ArgumentType blockState(); ArgumentType itemStack(); diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/resolvers/RotationResolver.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/resolvers/RotationResolver.java new file mode 100644 index 0000000000..fe697d183c --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/resolvers/RotationResolver.java @@ -0,0 +1,16 @@ +package io.papermc.paper.command.brigadier.argument.resolvers; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.math.Rotation; +import org.jetbrains.annotations.ApiStatus; + +/** + * An {@link ArgumentResolver} that's capable of resolving + * a rotation argument value using a {@link CommandSourceStack}. + * + * @see io.papermc.paper.command.brigadier.argument.ArgumentTypes#rotation() + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface RotationResolver extends ArgumentResolver { +} diff --git a/paper-api/src/main/java/io/papermc/paper/math/Rotation.java b/paper-api/src/main/java/io/papermc/paper/math/Rotation.java new file mode 100644 index 0000000000..73add399e4 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/math/Rotation.java @@ -0,0 +1,34 @@ +package io.papermc.paper.math; + +import org.jspecify.annotations.NullMarked; + +/** + * Represents a rotation with specified pitch and yaw values. + */ +@NullMarked +public interface Rotation { + /** + * Creates a new rotation with the specified yaw and pitch values. + * + * @param yaw the yaw component of the rotation, measured in degrees + * @param pitch the pitch component of the rotation, measured in degrees + * @return a new {@code Rotation} instance with the specified yaw and pitch + */ + static Rotation rotation(float yaw, float pitch) { + return new RotationImpl(yaw, pitch); + } + + /** + * Retrieves the pitch component of the rotation, measured in degrees. + * + * @return the pitch value in degrees + */ + float pitch(); + + /** + * Retrieves the yaw component of the rotation, measured in degrees. + * + * @return the yaw value in degrees + */ + float yaw(); +} diff --git a/paper-api/src/main/java/io/papermc/paper/math/RotationImpl.java b/paper-api/src/main/java/io/papermc/paper/math/RotationImpl.java new file mode 100644 index 0000000000..a5cff7debf --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/math/RotationImpl.java @@ -0,0 +1,4 @@ +package io.papermc.paper.math; + +record RotationImpl(float yaw, float pitch) implements Rotation { +} diff --git a/paper-api/src/main/java/org/bukkit/Location.java b/paper-api/src/main/java/org/bukkit/Location.java index 8bc340c9d4..20e30fa5a3 100644 --- a/paper-api/src/main/java/org/bukkit/Location.java +++ b/paper-api/src/main/java/org/bukkit/Location.java @@ -8,6 +8,7 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Predicate; import io.papermc.paper.math.FinePosition; +import io.papermc.paper.math.Rotation; import org.bukkit.block.Block; import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.entity.Entity; @@ -411,6 +412,19 @@ public class Location implements Cloneable, ConfigurationSerializable, io.paperm return this; } + /** + * Adds rotation to this location. Not world-aware. + * + * @param rotation the rotation to add. + * @return the same location + * @see Vector + */ + @NotNull + @Contract(value = "_ -> this", mutates = "this") + public Location addRotation(@NotNull Rotation rotation) { + return addRotation(rotation.yaw(), rotation.pitch()); + } + /** * Subtracts the location by another. * @@ -480,6 +494,19 @@ public class Location implements Cloneable, ConfigurationSerializable, io.paperm return this; } + /** + * Subtracts rotation from this location. + * + * @param rotation the rotation to subtract. + * @return the same location + * @see Vector + */ + @NotNull + @Contract(value = "_ -> this", mutates = "this") + public Location subtractRotation(@NotNull Rotation rotation) { + return subtractRotation(rotation.yaw(), rotation.pitch()); + } + /** * Gets the magnitude of the location, defined as sqrt(x^2+y^2+z^2). The * value of this method is not cached and uses a costly square-root @@ -622,6 +649,20 @@ public class Location implements Cloneable, ConfigurationSerializable, io.paperm return this; } + /** + * Sets the rotation of this location and returns itself. + *

+ * This mutates this object, clone first. + * + * @param rotation the new rotation. + * @return self (not cloned) + */ + @NotNull + @Contract(value = "_ -> this", mutates = "this") + public Location setRotation(@NotNull Rotation rotation) { + return setRotation(rotation.yaw(), rotation.pitch()); + } + /** * Takes the x/y/z from base and adds the specified x/y/z to it and returns self *

diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProviderImpl.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProviderImpl.java index 38fb7d13ab..3cfe319426 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProviderImpl.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProviderImpl.java @@ -19,9 +19,11 @@ import io.papermc.paper.command.brigadier.argument.range.RangeProvider; import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver; import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver; import io.papermc.paper.command.brigadier.argument.resolvers.PlayerProfileListResolver; +import io.papermc.paper.command.brigadier.argument.resolvers.RotationResolver; import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver; import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver; import io.papermc.paper.entity.LookAnchor; +import io.papermc.paper.math.Rotation; import io.papermc.paper.registry.PaperRegistries; import io.papermc.paper.registry.RegistryAccess; import io.papermc.paper.registry.RegistryKey; @@ -61,6 +63,7 @@ import net.minecraft.commands.arguments.TimeArgument; import net.minecraft.commands.arguments.UuidArgument; import net.minecraft.commands.arguments.blocks.BlockStateArgument; import net.minecraft.commands.arguments.coordinates.BlockPosArgument; +import net.minecraft.commands.arguments.coordinates.RotationArgument; import net.minecraft.commands.arguments.coordinates.Vec3Argument; import net.minecraft.commands.arguments.item.ItemArgument; import net.minecraft.commands.arguments.item.ItemPredicateArgument; @@ -71,6 +74,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec3; import org.bukkit.GameMode; import org.bukkit.HeightMap; @@ -156,6 +160,15 @@ public class VanillaArgumentProviderImpl implements VanillaArgumentProvider { }); } + @Override + public ArgumentType rotation() { + return this.wrap(RotationArgument.rotation(), (result) -> sourceStack -> { + final Vec2 vec2 = result.getRotation((CommandSourceStack) sourceStack); + + return Rotation.rotation(vec2.y, vec2.x); + }); + } + @Override public ArgumentType blockState() { return this.wrap(BlockStateArgument.block(PaperCommands.INSTANCE.getBuildContext()), (result) -> {