diff --git a/src/de/steamwar/lobby/command/PortalCommand.java b/src/de/steamwar/lobby/command/PortalCommand.java index 78f7749..989a516 100644 --- a/src/de/steamwar/lobby/command/PortalCommand.java +++ b/src/de/steamwar/lobby/command/PortalCommand.java @@ -4,6 +4,7 @@ import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.RegionSelector; import de.steamwar.command.SWCommand; import de.steamwar.command.TypeMapper; @@ -126,15 +127,14 @@ public class PortalCommand extends SWCommand { .getRegionSelector(BukkitAdapter.adapt(player.getWorld())); try { - BlockVector3 min = regionSelector.getRegion().getMinimumPoint(); - BlockVector3 max = regionSelector.getRegion().getMaximumPoint(); - return new Tuple<>(adapt(player.getWorld(), min), adapt(player.getWorld(), max)); + CuboidRegion region = (CuboidRegion)regionSelector.getRegion(); + return new Tuple<>(adapt(player.getWorld(), region.getPos1()), adapt(player.getWorld(), region.getPos2())); } catch (IncompleteRegionException e) { return null; } } private Location adapt(World world, BlockVector3 blockVector3) { - return new Location(world, blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ()); + return new Location(world, blockVector3.getBlockX() + 0.5, blockVector3.getBlockY(), blockVector3.getBlockZ() + 0.5); } } diff --git a/src/de/steamwar/lobby/display/Hologram.java b/src/de/steamwar/lobby/display/Hologram.java index 410bc2a..537eafb 100644 --- a/src/de/steamwar/lobby/display/Hologram.java +++ b/src/de/steamwar/lobby/display/Hologram.java @@ -157,11 +157,11 @@ public class Hologram implements ConfigurationSerializable { public void delete() { display.delete(); if(id != null) - holograms.remove(this); + holograms.remove(id); } @Override public String toString() { - return id + " " + location + " " + text; + return id + " " + text; } } diff --git a/src/de/steamwar/lobby/listener/Portals.java b/src/de/steamwar/lobby/listener/Portals.java index a462458..7416c7e 100644 --- a/src/de/steamwar/lobby/listener/Portals.java +++ b/src/de/steamwar/lobby/listener/Portals.java @@ -47,10 +47,11 @@ public class Portals extends BasicListener { @EventHandler public void onMove(PlayerMoveEvent e) { + Location from = e.getFrom(); Location to = e.getTo(); assert to != null; - Portal portal = Portal.getPortal(to); + Portal portal = Portal.getPortal(e.getPlayer(), from, to); if (portal == null) return; @@ -59,7 +60,7 @@ public class Portals extends BasicListener { if(!lastPortals.isEmpty() && lastPortals.peek() == portal) return; - portal.handle(player, to); + portal.handle(player, from, to); } @EventHandler diff --git a/src/de/steamwar/lobby/portal/CommandPortal.java b/src/de/steamwar/lobby/portal/CommandPortal.java index ac560a4..6eba0b4 100644 --- a/src/de/steamwar/lobby/portal/CommandPortal.java +++ b/src/de/steamwar/lobby/portal/CommandPortal.java @@ -19,6 +19,7 @@ package de.steamwar.lobby.portal; +import de.steamwar.comms.packets.ExecuteCommandPacket; import de.steamwar.lobby.listener.Portals; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -75,7 +76,7 @@ public class CommandPortal implements PortalHandler { cmd.append(pieces[i]).append(parts[i+1].substring(1)); } - player.sendMessage("Folgender Command wäre jetzt ausgeführt worden, könnte der Bungee das schon: " + cmd); + new ExecuteCommandPacket(player, cmd.toString()).send(player); } @Override diff --git a/src/de/steamwar/lobby/portal/Portal.java b/src/de/steamwar/lobby/portal/Portal.java index 4b772ff..91479c6 100644 --- a/src/de/steamwar/lobby/portal/Portal.java +++ b/src/de/steamwar/lobby/portal/Portal.java @@ -32,8 +32,6 @@ import java.util.function.Function; public class Portal implements PortalHandler, ConfigurationSerializable { private static final Map portals = new HashMap<>(); - private static final Map posMap = new HashMap<>(); - public static final Vector NORMAL = new Vector(0, 0, 1); public static List getPortals() { return new ArrayList<>(portals.values()); @@ -43,35 +41,46 @@ public class Portal implements PortalHandler, ConfigurationSerializable { return portals.keySet(); } - public static Portal getPortal(Location loc) { - return posMap.get(new Vector(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); + public static Portal getPortal(Player player, Location from, Location to) { + Vector movement = to.toVector().subtract(from.toVector()); + + for(Portal portal : portals.values()) { + double d = portal.orientation.getX() * movement.getZ() - portal.orientation.getZ() * movement.getX(); + if(d == 0 || !insidePortal(to.getY(), portal.pos1.getY(), portal.pos2.getY())) + continue; + + double t = ((portal.pos2.getX() - to.getX()) * movement.getZ() - (portal.pos2.getZ() - to.getZ()) * movement.getX()) / d; + double u = ((portal.pos2.getX() - to.getX()) * portal.orientation.getZ() - (portal.pos2.getZ() - to.getZ()) * portal.orientation.getX()) / d; + if(0 <= t && t <= 1 && 0 <= u && u <= 1) + return portal; + } + return null; } public static Portal getPortal(String id) { return portals.get(id); } + private static boolean insidePortal(double x, double p1, double p2) { + return x < p1 ^ x < p2; + } + private final Location pos1; private final Location pos2; + private final Vector orientation; + private final String id; private final PortalType type; private final PortalHandler handler; - final Vector v1; - final Vector v2; - final Vector dv; - final double degree; public Portal(Map map) { this.id = (String) map.get("id"); this.pos1 = (Location) map.get("pos1"); this.pos2 = (Location) map.get("pos2"); + this.orientation = pos2.toVector().subtract(pos1.toVector()); this.type = PortalType.valueOf((String) map.get("type")); this.handler = type.deserialize(map, this); - v1 = getPos1().toVector(); - v2 = getPos2().toVector(); - dv = v2.clone().subtract(v1); - degree = NORMAL.angle(dv); init(); } @@ -80,12 +89,9 @@ public class Portal implements PortalHandler, ConfigurationSerializable { this.id = id; this.pos1 = pos1; this.pos2 = pos2; + this.orientation = pos2.toVector().subtract(pos1.toVector()); this.handler = handlerConstructor.apply(this); this.type = handler.type(); - v1 = pos1.toVector(); - v2 = pos2.toVector(); - dv = v2.clone().subtract(v1); - degree = NORMAL.angle(dv); init(); LobbySystem.config().save(); @@ -93,18 +99,11 @@ public class Portal implements PortalHandler, ConfigurationSerializable { private void init() { portals.put(id, this); - for(int x = pos1.getBlockX(); x <= pos2.getBlockX(); x++) { - for(int y = pos1.getBlockY(); y <= pos2.getBlockY(); y++) { - for(int z = pos1.getBlockZ(); z <= pos2.getBlockZ(); z++) { - posMap.put(new Vector(x, y, z), this); - } - } - } } @Override - public void handle(Player player, Location from) { - handler.handle(player, from); + public void handle(Player player, Location from, Location to) { + handler.handle(player, from, to); Portals.getStack(player).push(this); } @@ -126,7 +125,6 @@ public class Portal implements PortalHandler, ConfigurationSerializable { public void delete() { handler.delete(); portals.remove(id); - posMap.values().removeIf(this::equals); LobbySystem.config().save(); } @@ -145,6 +143,10 @@ public class Portal implements PortalHandler, ConfigurationSerializable { return pos2; } + public Vector getOrientation() { + return orientation; + } + public String getId() { return id; } diff --git a/src/de/steamwar/lobby/portal/PortalHandler.java b/src/de/steamwar/lobby/portal/PortalHandler.java index 4e5e023..135fdd1 100644 --- a/src/de/steamwar/lobby/portal/PortalHandler.java +++ b/src/de/steamwar/lobby/portal/PortalHandler.java @@ -25,7 +25,13 @@ import org.bukkit.entity.Player; import java.util.Map; public interface PortalHandler { - void handle(Player player, Location from); + default void handle(Player player, Location to) { + throw new UnsupportedOperationException(); + } + + default void handle(Player player, Location from, Location to) { + handle(player, to); + } void serialize(Map map); diff --git a/src/de/steamwar/lobby/portal/TeleportPortal.java b/src/de/steamwar/lobby/portal/TeleportPortal.java index a9bb762..5355b2a 100644 --- a/src/de/steamwar/lobby/portal/TeleportPortal.java +++ b/src/de/steamwar/lobby/portal/TeleportPortal.java @@ -55,50 +55,36 @@ public class TeleportPortal implements PortalHandler { } @Override - public void handle(Player player, Location loc) { + public void handle(Player player, Location from, Location to) { Deque stack = Portals.getStack(player); if(!stack.isEmpty() && sources.contains(stack.peek().getHandler())) { - teleport(player, loc, stack.pop()); + teleport(player, from, to, stack.pop()); } else { - teleport(player, loc, Portal.getPortal(target)); + teleport(player, from, to, Portal.getPortal(target)); } } - protected void teleport(Player player, Location from, Portal target) { + private void teleport(Player player, Location from, Location to, Portal target) { player.sendMessage("teleport " + portal.getId() + " -> " + target.getId()); - Vector vector = from.toVector(); - double yaw = from.getYaw(); - Vector lookVector = Portal.NORMAL.clone().rotateAroundY(Math.toRadians(yaw)).normalize(); - double portalDegreeDelta = portal.degree - Portal.NORMAL.angle(lookVector); - // System.out.println(Math.toDegrees(degree) + " " + Math.toDegrees(portalDegreeDelta) + " " + Math.toDegrees(destination.degree)); + Vector ownOrientation = portal.getOrientation().clone(); + Vector targetOrientation = target.getOrientation().clone(); + double rotation = Math.atan2(targetOrientation.getZ(), targetOrientation.getX()) - Math.atan2(ownOrientation.getZ(), ownOrientation.getX()); + rotation = Math.atan2(Math.sin(rotation), Math.cos(rotation)); - double relativeSectionX = vector.clone().subtract(portal.v1).getX() / portal.dv.getX(); - double relativeSectionZ = vector.clone().subtract(portal.v1).getZ() / portal.dv.getZ(); - double relativeHeight = (vector.getY() - portal.v1.getY()) / portal.dv.getY(); + Vector pos = to.toVector() + .subtract(portal.getPos1().toVector()).divide(absPlusOne(ownOrientation)) + .rotateAroundY(-rotation) + .multiply(absPlusOne(targetOrientation)).add(target.getPos1().toVector()); + player.teleport(pos.toLocation(from.getWorld(), (float) (to.getYaw() + Math.toDegrees(rotation)), to.getPitch()), PlayerTeleportEvent.TeleportCause.PLUGIN); + } - Vector destinationSection = target.v1.clone(); - Vector now = target.dv.clone(); - if (Double.isFinite(relativeSectionX)) { - now.setX(now.getX() * relativeSectionX); - } - if (Double.isFinite(relativeSectionZ)) { - now.setZ(now.getZ() * relativeSectionZ); - } - destinationSection.add(now); - Vector v = destinationSection.clone(); - v.setX(v.getBlockX()); - v.setY(target.v1.getY()); - v.setZ(v.getBlockZ()); - - double destinationHeight = portal.dv.getY() * relativeHeight; - - Location location = destinationSection.toLocation(from.getWorld()); - location.setPitch(from.getPitch()); - location.setYaw((float) Math.toDegrees(target.degree + portalDegreeDelta)); - location.add(0, destinationHeight, 0); - player.teleport(location, PlayerTeleportEvent.TeleportCause.PLUGIN); + private Vector absPlusOne(Vector v) { + v.setX(Math.abs(v.getX()) + 1); + v.setY(Math.abs(v.getY()) + 1); + v.setZ(Math.abs(v.getZ()) + 1); + return v; } @Override