Skip to content

ExprMidpointLocations #7888

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

Open
wants to merge 13 commits into
base: dev/feature
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package ch.njol.skript.expressions;

import ch.njol.skript.Skript;
import ch.njol.skript.config.Node;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Example;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.SyntaxStringBuilder;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.util.Kleenean;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.event.Event;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.Nullable;
import org.skriptlang.skript.log.runtime.SyntaxRuntimeErrorProducer;

@Name("Midpoint of Locations")
@Description("Get the midpoint from two locations in the same world.")
@Example("""
set {_center} to the midpoint between location(0, 0, 0) and location(10, 10, 10)
set {_centerBlock} to the block at {_center}
""")
@Since("INSERT VERSION")
public class ExprMidpointLocations extends SimpleExpression<Location> implements SyntaxRuntimeErrorProducer {

static {
Skript.registerExpression(ExprMidpointLocations.class, Location.class, ExpressionType.COMBINED,
"[the] mid[-]point (of|between) %location% and %location%");
}

private Expression<Location> location1;
private Expression<Location> location2;
private Node node;

@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
//noinspection unchecked
location1 = (Expression<Location>) exprs[0];
//noinspection unchecked
location2 = (Expression<Location>) exprs[1];
node = getParser().getNode();
return true;
}

@Override
protected Location @Nullable [] get(Event event) {
Location loc1 = location1.getSingle(event);
Location loc2 = location2.getSingle(event);
if (loc1 == null || loc2 == null) {
return null;
} else if (loc1.getWorld() != loc2.getWorld()) {
error("Cannot get the midpoint of two locations in different worlds.");
return null;
}
World world = loc1.getWorld();
Vector vector = loc1.toVector().getMidpoint(loc2.toVector());
return new Location[] {vector.toLocation(world)};
}

@Override
public boolean isSingle() {
return true;
}

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

@Override
public Node getNode() {
return node;
}

@Override
public String toString(@Nullable Event event, boolean debug) {
return new SyntaxStringBuilder(event, debug)
.append("the midpoint between")
.append(location1)
.append("and")
.append(location2)
.toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

test "midpoint locations - simple":
set {_loc1} to location(0, 0, 0)
set {_loc2} to {_loc1} ~ vector(10, 10, 10)
set {_center} to the midpoint between {_loc1} and {_loc2}
assert {_center} is location(5, 5, 5) with "Simple midpoint loc1 -> loc2 is incorrect"
set {_center2} to the midpoint between {_loc2} and {_loc1}
assert {_center2} is location(5, 5, 5) with "Simple midpoint loc2 -> loc1 is incorrect"

test "midpoint locations - complex":
set {_loc1} to location(10.3, 38.6, 72.9)
set {_loc2} to location(-24.2, 63.8, 598.1)
set {_center} to the midpoint between {_loc1} and {_loc2}
assert {_center} is location(-6.95, 51.2, 335.5) with "Complex midpoint loc1 -> loc2 is incorrect"
set {_center2} to the midpoint between {_loc2} and {_loc1}
assert {_center2} is location(-6.95, 51.2, 335.5) with "Complex midpoint loc2 -> loc1 is incorrect"

test "midpoint locations - negative":
set {_loc1} to location(-48.2, -33.6, -97.8)
set {_loc2} to location(-257.3, -59.3, -327.4)
set {_center} to the midpoint between {_loc1} and {_loc2}
assert {_center} is location(-152.75, -46.45, -212.6) with "Negative midpoint loc1 -> loc2 is incorrect"
set {_center2} to the midpoint between {_loc2} and {_loc1}
assert {_center2} is location(-152.75, -46.45, -212.6) with "Negative midpoint loc2 -> loc1 is incorrect"

test "midpoint location - world error":
set {_loc1} to location(0, 0, 0)
set {_loc2} to location(0, 0, 0, "world_the_end")
# TODO: Change to catch runtime errors
set {_center} to the midpoint between {_loc1} and {_loc2}
assert {_center} is not set with "Should not be able to get a center location from locations in different worlds"