Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExprYawPitch: support for entities, better description #5298

Merged
merged 14 commits into from
Jul 1, 2024
Merged
201 changes: 137 additions & 64 deletions src/main/java/ch/njol/skript/expressions/ExprYawPitch.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@
*/
package ch.njol.skript.expressions;

import ch.njol.skript.ServerPlatform;
import ch.njol.skript.Skript;
import ch.njol.skript.doc.RequiredPlugins;
import ch.njol.util.VectorMath;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;

import ch.njol.skript.classes.Changer.ChangeMode;
Expand All @@ -33,125 +38,193 @@
import ch.njol.util.Kleenean;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.Nullable;

@Name("Yaw / Pitch")
@Description("The yaw or pitch of a location or vector.")
@Examples({"log \"%player%: %location of player%, %player's yaw%, %player's pitch%\" to \"playerlocs.log\"",
"set {_yaw} to yaw of player",
"set {_p} to pitch of target entity"})
@Since("2.0, 2.2-dev28 (vector yaw/pitch)")
public class ExprYawPitch extends SimplePropertyExpression<Object, Number> {
@Description({
"The yaw or pitch of a location or vector.",
"A yaw of 0 or 360 represents the positive z direction. Adding a positive number to the yaw of a player will rotate it clockwise.",
"A pitch of 90 represents the negative y direction, or downward facing. A pitch of -90 represents upward facing. Adding a positive number to the pitch will rotate the direction downwards.",
"Only Paper 1.19+ users may directly change the yaw/pitch of players."
})
@Examples({
"log \"%player%: %location of player%, %player's yaw%, %player's pitch%\" to \"playerlocs.log\"",
"set {_yaw} to yaw of player",
"set {_p} to pitch of target entity",
"set pitch of player to -90 # Makes the player look upwards, Paper 1.19+ only",
"add 180 to yaw of target of player # Makes the target look behind themselves"
})
@Since("2.0, 2.2-dev28 (vector yaw/pitch), INSERT VERSION (entity changers)")
@RequiredPlugins("Paper 1.19+ (player changers)")
public class ExprYawPitch extends SimplePropertyExpression<Object, Float> {

static {
register(ExprYawPitch.class, Number.class, "(yaw|pitch)", "locations/vectors");
register(ExprYawPitch.class, Float.class, "(:yaw|pitch)", "entities/locations/vectors");
}

// For non-Paper versions lower than 1.19, changing the rotation of an entity is not supported for players.
private static final boolean SUPPORTS_PLAYERS = Skript.isRunningMinecraft(1, 19) && Skript.getServerPlatform() == ServerPlatform.BUKKIT_PAPER;
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved

private boolean usesYaw;

@Override
public boolean init(final Expression<?>[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parseResult) {
usesYaw = parseResult.mark == 0;
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
usesYaw = parseResult.hasTag("yaw");
return super.init(exprs, matchedPattern, isDelayed, parseResult);
}

@Override
public Number convert(final Object object) {
if (object instanceof Location) {
Location l = ((Location) object);
return usesYaw ? convertToPositive(l.getYaw()) : l.getPitch();
public Float convert(Object object) {
if (object instanceof Entity) {
Location location = ((Entity) object).getLocation();
return usesYaw
? normalizeYaw(location.getYaw())
: location.getPitch();
} else if (object instanceof Location) {
Location location = (Location) object;
return usesYaw
? normalizeYaw(location.getYaw())
: location.getPitch();
} else if (object instanceof Vector) {
Vector vector = ((Vector) object);
if (usesYaw)
return VectorMath.skriptYaw(VectorMath.getYaw(vector));
return VectorMath.skriptPitch(VectorMath.getPitch(vector));
Vector vector = (Vector) object;
return usesYaw
? VectorMath.skriptYaw((VectorMath.getYaw(vector)))
: VectorMath.skriptPitch(VectorMath.getPitch(vector));
}
return null;
}

@SuppressWarnings({"null"})
@Override
public Class<?>[] acceptChange(final ChangeMode mode) {
if (mode == ChangeMode.SET || mode == ChangeMode.ADD || mode == ChangeMode.REMOVE)
return CollectionUtils.array(Number.class);
return null;
public Class<?>[] acceptChange(ChangeMode mode) {
if (Player.class.isAssignableFrom(getExpr().getReturnType()) && !SUPPORTS_PLAYERS)
return null;

switch (mode) {
case SET:
case ADD:
case REMOVE:
return CollectionUtils.array(Number.class);
case RESET:
return new Class[0];
default:
return null;
}
}

@SuppressWarnings("null")
@Override
public void change(Event e, Object[] delta, ChangeMode mode) {
if (delta == null)
Mwexim marked this conversation as resolved.
Show resolved Hide resolved
public void change(Event event, @Nullable Object[] delta, ChangeMode mode) {
if (delta == null && mode != ChangeMode.RESET)
return;
float value = ((Number) delta[0]).floatValue();
for (Object single : getExpr().getArray(e)) {
if (single instanceof Location) {
changeLocation(((Location) single), value, mode);
} else if (single instanceof Vector) {
changeVector(((Vector) single), value, mode);
for (Object object : getExpr().getArray(event)) {
if (object instanceof Player && !SUPPORTS_PLAYERS)
continue;
Mwexim marked this conversation as resolved.
Show resolved Hide resolved

if (object instanceof Entity) {
changeForEntity((Entity) object, value, mode);
} else if (object instanceof Location) {
changeForLocation(((Location) object), value, mode);
} else if (object instanceof Vector) {
changeForVector(((Vector) object), value, mode);
}
}
}

private void changeLocation(Location l, float value, ChangeMode mode) {
private void changeForEntity(Entity entity, float value, ChangeMode mode) {
Location location = entity.getLocation();
switch (mode) {
case SET:
if (usesYaw)
l.setYaw(convertToPositive(value));
else
l.setPitch(value);
if (usesYaw) {
entity.setRotation(value, location.getPitch());
} else {
entity.setRotation(location.getYaw(), value);
}
break;
case REMOVE:
value = -value;
case ADD:
if (usesYaw)
l.setYaw(convertToPositive(l.getYaw()) + value);
else
l.setPitch(l.getPitch() + value);
if (usesYaw) {
entity.setRotation(location.getYaw() + value, location.getPitch());
Mwexim marked this conversation as resolved.
Show resolved Hide resolved
} else {
// Subtracting because of Minecraft's upside-down pitch.
entity.setRotation(location.getYaw(), location.getPitch() - value);
}
break;
case RESET:
if (usesYaw) {
entity.setRotation(0, location.getPitch());
} else {
entity.setRotation(location.getYaw(), 0);
}
break;
default:
break;
}
}

private void changeForLocation(Location location, float value, ChangeMode mode) {
switch (mode) {
case SET:
if (usesYaw) {
location.setYaw(value);
} else {
location.setPitch(value);
}
break;
case REMOVE:
if (usesYaw)
l.setYaw(convertToPositive(l.getYaw()) - value);
else
l.setPitch(l.getPitch() - value);
value = -value;
case ADD:
if (usesYaw) {
location.setYaw(location.getYaw() + value);
} else {
// Subtracting because of Minecraft's upside-down pitch.
location.setPitch(location.getPitch() - value);
}
break;
case RESET:
if (usesYaw) {
location.setYaw(0);
} else {
location.setPitch(0);
}
default:
break;
}
}

private void changeVector(Vector vector, float n, ChangeMode mode) {
private void changeForVector(Vector vector, float value, ChangeMode mode) {
float yaw = VectorMath.getYaw(vector);
float pitch = VectorMath.getPitch(vector);
switch (mode) {
case REMOVE:
n = -n;
//$FALL-THROUGH$
value = -value;
// $FALL-THROUGH$
case ADD:
if (usesYaw)
yaw += n;
else
pitch -= n; // Negative because of Minecraft's / Skript's upside down pitch
Vector newVector = VectorMath.fromYawAndPitch(yaw, pitch).multiply(vector.length());
VectorMath.copyVector(vector, newVector);
if (usesYaw) {
yaw += value;
} else {
// Subtracting because of Minecraft's upside-down pitch.
pitch -= value;
}
break;
case SET:
if (usesYaw)
yaw = VectorMath.fromSkriptYaw(n);
yaw = VectorMath.fromSkriptYaw(value);
else
pitch = VectorMath.fromSkriptPitch(n);
newVector = VectorMath.fromYawAndPitch(yaw, pitch).multiply(vector.length());
VectorMath.copyVector(vector, newVector);
pitch = VectorMath.fromSkriptPitch(value);
}
Vector newVector = VectorMath.fromYawAndPitch(yaw, pitch).multiply(vector.length());
VectorMath.copyVector(vector, newVector);
}


//Some random method decided to use for converting to positive values.
public float convertToPositive(float f) {
if (f != 0 && f * -1 == Math.abs(f))
return 360 + f;
return f;
private static float normalizeYaw(float yaw) {
yaw = Location.normalizeYaw(yaw);
return yaw < 0 ? yaw + 360 : yaw;
}

@Override
public Class<? extends Number> getReturnType() {
return Number.class;
public Class<? extends Float> getReturnType() {
return Float.class;
}

@Override
Expand Down