Improve RelativeVec api

This commit is contained in:
TheMode 2021-07-09 18:53:13 +02:00
parent f9689bc1f3
commit 2efefe25b3
2 changed files with 63 additions and 62 deletions

View File

@ -15,9 +15,9 @@ import java.util.function.Function;
*/ */
abstract class ArgumentRelativeVec extends Argument<RelativeVec> { abstract class ArgumentRelativeVec extends Argument<RelativeVec> {
public static final char RELATIVE_CHAR = '~'; private static final char RELATIVE_CHAR = '~';
public static final char LOCAL_CHAR = '^'; private static final char LOCAL_CHAR = '^';
public static final Set<Character> MODIFIER_CHARS = Set.of(RELATIVE_CHAR, LOCAL_CHAR); private static final Set<Character> MODIFIER_CHARS = Set.of(RELATIVE_CHAR, LOCAL_CHAR);
public static final int INVALID_NUMBER_COUNT_ERROR = 1; public static final int INVALID_NUMBER_COUNT_ERROR = 1;
public static final int INVALID_NUMBER_ERROR = 2; public static final int INVALID_NUMBER_ERROR = 2;
@ -31,6 +31,7 @@ abstract class ArgumentRelativeVec extends Argument<RelativeVec> {
} }
abstract Function<String, ? extends Number> getRelativeNumberParser(); abstract Function<String, ? extends Number> getRelativeNumberParser();
abstract Function<String, ? extends Number> getAbsoluteNumberParser(); abstract Function<String, ? extends Number> getAbsoluteNumberParser();
@NotNull @NotNull
@ -43,7 +44,7 @@ abstract class ArgumentRelativeVec extends Argument<RelativeVec> {
double[] coordinates = new double[split.length]; double[] coordinates = new double[split.length];
boolean[] isRelative = new boolean[split.length]; boolean[] isRelative = new boolean[split.length];
Type type = Type.UNDEFINED; var type = RelativeVec.CoordinateType.UNDEFINED;
for (int i = 0; i < split.length; i++) { for (int i = 0; i < split.length; i++) {
final String element = split[i]; final String element = split[i];
try { try {
@ -51,9 +52,9 @@ abstract class ArgumentRelativeVec extends Argument<RelativeVec> {
if (MODIFIER_CHARS.contains(modifierChar)) { if (MODIFIER_CHARS.contains(modifierChar)) {
isRelative[i] = true; isRelative[i] = true;
if (type == Type.UNDEFINED) { if (type == RelativeVec.CoordinateType.UNDEFINED) {
type = modifierChar == LOCAL_CHAR ? Type.LOCAL : Type.RELATIVE; type = modifierChar == LOCAL_CHAR ? RelativeVec.CoordinateType.LOCAL : RelativeVec.CoordinateType.RELATIVE;
} else if (type != (modifierChar == LOCAL_CHAR ? Type.LOCAL : Type.RELATIVE)) { } else if (type != (modifierChar == LOCAL_CHAR ? RelativeVec.CoordinateType.LOCAL : RelativeVec.CoordinateType.RELATIVE)) {
throw new ArgumentSyntaxException("Cannot mix world & local coordinates (everything must either use ^ or not)", input, MIXED_TYPE_ERROR); throw new ArgumentSyntaxException("Cannot mix world & local coordinates (everything must either use ^ or not)", input, MIXED_TYPE_ERROR);
} }
@ -69,8 +70,10 @@ abstract class ArgumentRelativeVec extends Argument<RelativeVec> {
} }
} }
return new RelativeVec(split.length == 3 ? new Vec(coordinates[0], coordinates[1], coordinates[2]) : new Vec(coordinates[0], coordinates[1]), return new RelativeVec(split.length == 3 ?
isRelative, type == Type.LOCAL); new Vec(coordinates[0], coordinates[1], coordinates[2]) : new Vec(coordinates[0], coordinates[1]),
type,
isRelative[0], isRelative[1], isRelative[2]);
} }
/** /**
@ -81,10 +84,4 @@ abstract class ArgumentRelativeVec extends Argument<RelativeVec> {
public int getNumberCount() { public int getNumberCount() {
return numberCount; return numberCount;
} }
private enum Type {
RELATIVE,
LOCAL,
UNDEFINED
}
} }

View File

@ -1,7 +1,6 @@
package net.minestom.server.utils.location; package net.minestom.server.utils.location;
import net.minestom.server.command.CommandSender; import net.minestom.server.command.CommandSender;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Pos;
import net.minestom.server.coordinate.Vec; import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Entity; import net.minestom.server.entity.Entity;
@ -18,38 +17,26 @@ import java.util.Objects;
public final class RelativeVec { public final class RelativeVec {
private final Vec vec; private final Vec vec;
private boolean relativeX, relativeY, relativeZ; private final CoordinateType coordinateType;
private boolean[] relative; private final boolean relativeX, relativeY, relativeZ;
private boolean isLocal;
public RelativeVec(@NotNull Vec vec, boolean relativeX, boolean relativeY, boolean relativeZ) { public RelativeVec(@NotNull Vec vec, @NotNull CoordinateType coordinateType, boolean relativeX, boolean relativeY, boolean relativeZ) {
this.vec = vec; this.vec = vec;
this.coordinateType = coordinateType;
this.relativeX = relativeX; this.relativeX = relativeX;
this.relativeY = relativeY; this.relativeY = relativeY;
this.relativeZ = relativeZ; this.relativeZ = relativeZ;
} }
public RelativeVec(Vec vec, boolean[] relative, boolean isLocal) {
this.vec = vec;
this.relative = relative;
this.isLocal = isLocal;
}
/** /**
* Gets the location based on the relative fields and {@code position}. * Gets the location based on the relative fields and {@code position}.
* *
* @param point the relative position * @param origin the origin position, null if none
* @return the location * @return the location
*/ */
public @NotNull Vec from(@Nullable Point point) { public @NotNull Vec from(@Nullable Pos origin) {
if (!relativeX && !relativeY && !relativeZ) { origin = Objects.requireNonNullElse(origin, Pos.ZERO);
return vec; return coordinateType.convert(vec, origin, relativeX, relativeY, relativeZ);
}
final var absolute = Objects.requireNonNullElse(point, Vec.ZERO);
final double x = vec.x() + (relativeX ? absolute.x() : 0);
final double y = vec.y() + (relativeY ? absolute.y() : 0);
final double z = vec.z() + (relativeZ ? absolute.z() : 0);
return new Vec(x, y, z);
} }
@ApiStatus.Experimental @ApiStatus.Experimental
@ -70,9 +57,8 @@ public final class RelativeVec {
* @return the location * @return the location
*/ */
public @NotNull Vec from(@Nullable Entity entity) { public @NotNull Vec from(@Nullable Entity entity) {
return isLocal ? toGlobal(vec, entity.getPosition(), relative) : toGlobal(vec, entity.getPosition().asVec(), relative); final var entityPosition = entity != null ? entity.getPosition() : Pos.ZERO;
// final var entityPosition = entity != null ? entity.getPosition() : Pos.ZERO; return from(entityPosition);
// return from(entityPosition);
} }
public @NotNull Vec fromSender(@Nullable CommandSender sender) { public @NotNull Vec fromSender(@Nullable CommandSender sender) {
@ -113,30 +99,48 @@ public final class RelativeVec {
return relativeZ; return relativeZ;
} }
public static Vec toGlobal(Vec local, Pos origin, boolean[] axis) { public enum CoordinateType {
double double5 = Math.cos(Math.toRadians(origin.yaw() + 90.0f)); RELATIVE((relative, origin, relativeX, relativeY, relativeZ) -> {
double double6 = Math.sin(Math.toRadians(origin.yaw() + 90.0f)); if (!relativeX && !relativeY && !relativeZ) {
double double7 = Math.cos(Math.toRadians(-origin.pitch())); return relative;
double double8 = Math.sin(Math.toRadians(-origin.pitch())); }
double double9 = Math.cos(Math.toRadians(-origin.pitch() + 90.0f)); final var absolute = Objects.requireNonNullElse(origin, Vec.ZERO);
double double10 = Math.sin(Math.toRadians(-origin.pitch() + 90.0f)); final double x = relative.x() + (relativeX ? absolute.x() : 0);
Vec dna11 = new Vec(double5 * double7, double8, double6 * double7); final double y = relative.y() + (relativeY ? absolute.y() : 0);
Vec dna12 = new Vec(double5 * double9, double10, double6 * double9); final double z = relative.z() + (relativeZ ? absolute.z() : 0);
Vec dna13 = dna11.cross(dna12).mul(-1); return new Vec(x, y, z);
double double14 = dna11.x() * local.z() + dna12.x() * local.y() + dna13.x() * local.x(); }),
double double16 = dna11.y() * local.z() + dna12.y() * local.y() + dna13.y() * local.x(); LOCAL((local, origin, relativeX, relativeY, relativeZ) -> {
double double18 = dna11.z() * local.z() + dna12.z() * local.y() + dna13.z() * local.x(); double double5 = Math.cos(Math.toRadians(origin.yaw() + 90.0f));
return new Vec(double14 + (axis[0] ? origin.x() : 0), double16 + (axis[1] ? origin.y() : 0), double18 + (axis[2] ? origin.z() : 0)); double double6 = Math.sin(Math.toRadians(origin.yaw() + 90.0f));
double double7 = Math.cos(Math.toRadians(-origin.pitch()));
double double8 = Math.sin(Math.toRadians(-origin.pitch()));
double double9 = Math.cos(Math.toRadians(-origin.pitch() + 90.0f));
double double10 = Math.sin(Math.toRadians(-origin.pitch() + 90.0f));
Vec dna11 = new Vec(double5 * double7, double8, double6 * double7);
Vec dna12 = new Vec(double5 * double9, double10, double6 * double9);
Vec dna13 = dna11.cross(dna12).mul(-1);
double double14 = dna11.x() * local.z() + dna12.x() * local.y() + dna13.x() * local.x();
double double16 = dna11.y() * local.z() + dna12.y() * local.y() + dna13.y() * local.x();
double double18 = dna11.z() * local.z() + dna12.z() * local.y() + dna13.z() * local.x();
return new Vec(double14 + (relativeX ? origin.x() : 0),
double16 + (relativeY ? origin.y() : 0),
double18 + (relativeZ ? origin.z() : 0));
}),
UNDEFINED((vec, origin, relativeX, relativeY, relativeZ) -> vec);
private final CoordinateConverter converter;
CoordinateType(CoordinateConverter converter) {
this.converter = converter;
}
private @NotNull Vec convert(Vec vec, Pos origin, boolean relativeX, boolean relativeY, boolean relativeZ) {
return converter.convert(vec, origin, relativeX, relativeY, relativeZ);
}
} }
public static Vec toGlobal(Vec relative, Vec origin, boolean[] axis) { private interface CoordinateConverter {
if (!axis[0] && !axis[1] && !axis[2]) { @NotNull Vec convert(Vec vec, Pos origin, boolean relativeX, boolean relativeY, boolean relativeZ);
return relative;
}
final var absolute = Objects.requireNonNullElse(origin, Vec.ZERO);
final double x = relative.x() + (axis[0] ? absolute.x() : 0);
final double y = relative.y() + (axis[1] ? absolute.y() : 0);
final double z = relative.z() + (axis[2] ? absolute.z() : 0);
return new Vec(x, y, z);
} }
} }