public void teleport(final Vehicle vehicle) { Location traveller = new Location( this.world, vehicle.getLocation().getX(), vehicle.getLocation().getY(), vehicle.getLocation().getZ()); Location exit = getExit(traveller); double velocity = vehicle.getVelocity().length(); // Stop and teleport vehicle.setVelocity(new Vector()); // Get new velocity final Vector newVelocity = new Vector(); switch ((int) id.getBlock().getData()) { case 2: newVelocity.setZ(-1); break; case 3: newVelocity.setZ(1); break; case 4: newVelocity.setX(-1); break; case 5: newVelocity.setX(1); break; } newVelocity.multiply(velocity); final Entity passenger = vehicle.getPassenger(); if (passenger != null) { final Vehicle v = exit.getWorld().spawn(exit, vehicle.getClass()); vehicle.eject(); vehicle.remove(); passenger.teleport(exit); Stargate.server .getScheduler() .scheduleSyncDelayedTask( Stargate.stargate, new Runnable() { public void run() { v.setPassenger(passenger); v.setVelocity(newVelocity); } }, 1); } else { Vehicle mc = exit.getWorld().spawn(exit, vehicle.getClass()); if (mc instanceof StorageMinecart) { StorageMinecart smc = (StorageMinecart) mc; smc.getInventory().setContents(((StorageMinecart) vehicle).getInventory().getContents()); } mc.setVelocity(newVelocity); vehicle.remove(); } }
/** * Teleports the passed in Entity through the portal. * * <p>Given an Entity object, attempts to teleport them through the portal. This involves many * steps. 1) Verify the portal on the other end still exists. If it doesn't, mark this as such. 2) * If there is no counterpart, figure out where it would be, and get it. This may involve * generating and placing a portal into the world. 3) Assuming we now have a counterpart, figure * out where to teleport the entity to. 3a) Figure out the entity's position relative to the entry * portal. 3b) Translate this to a position relative to the exit portal. 3c) Preserve the entity's * camera's orientation relative to the portal. 4) Teleport the entity. 4a) If the entity is a * Player in a vehicle, we do a dance. - Raise the destination by 1 (vehicles have to 'fall' into * the portal to avoid losing momentum, so they should be one higher). - Make the player leave the * vehicle. - Spawn a new minecart at the destination. - Teleport the player to the destination. - * Make the player a passenger of the minecart. - Give the new minecart the (properly translated) * velocity of the old vehicle. - Remove the old vehicle. * * @param e The entity to teleport. * @return The location the entity was teleported to, or null if the entity was not teleported. */ public Location teleport(Entity e, Location interaction) { if (this.counterpart != null) { if (!this.counterpart.isValid()) { PortalUtil.removePortal(this.counterpart); this.counterpart = null; PortalUtil.getCounterpartPortalFor(this); } else { BlockData bd = this.getWorldBlockType(); if (bd != null && !bd.m.equals(Material.AIR) && !bd.m.equals(Material.OBSIDIAN) && !this.counterpart .getKeyBlock() .getWorld() .equals(PortalUtil.getDestWorldFor(this))) { // Did my keyblock change, and if so, change my destination. this.counterpart = null; PortalUtil.getCounterpartPortalFor(this); } } } else { PortalUtil.getCounterpartPortalFor(this); } if (this.counterpart == null) { // Could not establish a link, for whatever reason. return null; } double destX, destY, destZ; float destPitch, destYaw; int rotateVehicleVelocity = 0; Vector offset = interaction.toVector().subtract(this.keyBlock.getLocation().toVector()); Vector finalOffset; if (this.facingNorth) { if (offset.getX() < .5) { // Player moving south. offset.setX(offset.getX() + OFFSET); } else { // Player moving north. offset.setX(offset.getX() - OFFSET); } if (this.counterpart.isFacingNorth()) { destYaw = e.getLocation().getYaw(); finalOffset = offset; } else { destYaw = e.getLocation().getYaw() - 90; finalOffset = new Vector(offset.getZ(), offset.getY(), -offset.getX() + OFFSET); rotateVehicleVelocity = 1; } } else { if (offset.getZ() < .5) { // Player moving west offset.setZ(offset.getZ() + OFFSET); } else { // Player moving east. offset.setZ(offset.getZ() - OFFSET); } if (this.counterpart.isFacingNorth()) { destYaw = e.getLocation().getYaw() + 90; finalOffset = new Vector(-offset.getZ() + OFFSET, offset.getY(), offset.getX()); rotateVehicleVelocity = 2; } else { destYaw = e.getLocation().getYaw(); finalOffset = offset; } } World destWorld = this.counterpart.getKeyBlock().getWorld(); String permission = "nethrar.block." + destWorld.getName(); if ((Nethrar.getPlugin().shouldUsePermissions()) && ((e instanceof Player)) && (((Player) e).hasPermission(permission)) && !((Player) e).isOp()) { return null; } destX = this.counterpart.getKeyBlock().getX() + finalOffset.getX(); destY = this.counterpart.getKeyBlock().getY() + finalOffset.getY(); destZ = this.counterpart.getKeyBlock().getZ() + finalOffset.getZ(); destPitch = e.getLocation().getPitch(); // Jitter the location just a bit so the resulting minecart doesn't // end up underground, if there is a minecart being teleported. if ((e instanceof Player && ((Player) e).isInsideVehicle()) || (e instanceof Vehicle && !(e instanceof Pig))) { // +.11 is necessary to get a minecart to spawn on top of, instead // of inside, rails on the same level on the other side. However, // if there are *not* rails on the other side, then the minecart // will fall into the block underneath, unless a +1 is added. destY += 1.0; } Location dest; dest = new Location(destWorld, destX, destY, destZ, destYaw, destPitch); // Bug: Player camera orientation not preserved when teleporting // in a vehicle. Probably because vehicle takes over player // camera. Vehicle oldV = null, newV = null; if (e instanceof Player) { if (((Player) e).isInsideVehicle()) { oldV = (Vehicle) ((Player) e).getVehicle(); ((Player) e).leaveVehicle(); } } else if (e instanceof StorageMinecart || e instanceof Minecart || e instanceof Boat) { oldV = ((Vehicle) e); } if (oldV != null) { if (oldV instanceof StorageMinecart) { newV = destWorld.spawn(dest, StorageMinecart.class); ((StorageMinecart) newV) .getInventory() .setContents(((StorageMinecart) oldV).getInventory().getContents()); } else if (oldV instanceof Minecart) { newV = destWorld.spawn(dest, Minecart.class); } else if (oldV instanceof Boat) { newV = destWorld.spawn(dest, Boat.class); } else { log.warning("[NETHRAR] Unsupported vehicle hit a portal."); } Vector oldVelocity = oldV.getVelocity(); Vector newVelocity; switch (rotateVehicleVelocity) { // Left-handed system - clockwise is positive. case 1: // In a north-facing portal, out a west-facing portal. // Rotate 90 degrees counterclockwise. newVelocity = new Vector(oldVelocity.getZ(), oldVelocity.getY(), oldVelocity.getX() * -1); break; case 2: // In a west-facing portal, out a north-facing portal. // Rotate 90 degrees clockwise. newVelocity = new Vector(oldVelocity.getZ() * -1, oldVelocity.getY(), oldVelocity.getX()); break; default: newVelocity = oldVelocity; break; } PortalUtil.markTeleported(e); Bukkit.getServer() .getScheduler() .scheduleSyncDelayedTask( PortalUtil.getPlugin(), new NethrarTeleporter(e, dest, newV, newVelocity, oldV)); } else { PortalUtil.markTeleported(e); // Regular player teleportation doesn't need to be delayed. NethrarTeleporter tp = new NethrarTeleporter(e, dest); tp.run(); } return null; }