I’m looking for a way to teleport a player in a short distance but relatively where he look at.
I mean if he look to the east he’ll be teleported to the east. I don’t know if I’m clear…
I know I can use player.setPosition(extend, x, y, x) btw I don’t exactly understand what extend is used for… is it the world in which the location is? And there is a player.getRotation but I don’t know if it represent the head rotation or just the body, and anyway I don’t know the math to do that, should I use trigonometry or there is a simpliest way?
I hope my english is understandable, and I would to thanks your team to create that api that better and better!
First, get the direction the player is looking at, then normalize it (so it’s length will become 1) and multiply it with the distance you want the player to move. You now have a vector you can add to the players old location.
Vector3d dir = player.getRotation().normalize().mul(3.0);
Location newLoc = player.getLocation().add(dir);
player.setLocation(newLoc);
This will move a player 3 blocks in the exact direction where he’s looking.
EDIT: getRotation() does not work as I assumed, see comment of @ryantheleach below
Yes I guessed you meant getRotation() but it doesn’t work neither, it teleports on 3 blocks but at random location…
I think it’s because it’s a rotation not “direction”. I’m wondering how can I “transform” a rotation into a “direction”
It should teleport in the exact direction someone is facing. If you want to somewhat normalize the behavior (if something is watching east, more or less, port him east), you can use the Direction Enum for that.
Direction dir = Direction.getClosest(player.getRotation());
This gives you a Direction to work with which can be converted back into a Vector3d using the Direction#toVector3d() method.
Oh shoot, I totally overlooked that Thats what happens if you just check the returned type and not the rest of the docs.
Which means my above answer is useless since getRotation does not return a directional vector, it just uses a vector to store Euler angles. With my rusty understanding I just hacked together a helper function that will calculate the closest cardinal direction from the supplied pitch (assuming teleports only occur in North/East/South/West directions)
private void teleportForward(Player player, double distance) {
Vector3d rotation = player.getRotation();
Direction dir = cardinalDirectionFromPitch(rotation.getX());
Vector3d diff = dir.toVector3d().normalize().mul(distance);
Location newLoc = player.getLocation().add(diff);
player.setLocationSafely(newLoc);
}
private Direction cardinalDirectionFromPitch(double pitch) {
Direction[] cardinalDirections = {Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.EAST};
int index = (int) ((pitch+45) / 90);
return cardinalDirections[index % 4];
}
On how to calculate a directional vector form the Euler angles I cannot comment since I’d have to read it all up myself. I hope there is a helper function somewhere in Sponge but so far I have not found it.
I had a quick chat with @DDoS and he suggested having a look at flowpowered / flow.math and using Quaterniond to convert from Eulerangles to Quaternions and then to a vector representing the direction.
BTW, right now SpongeAPI returns the rotations in a Vector3i with the mapping X -> yaw, Y -> pitch, Z -> roll. I’m changing that tomorrow to X -> pitch, Y -> yaw, Z -> roll to match flow-math (and the standard).
Also here’s an example of a Euler angles -> direction conversion using Quaternions.