private final BlendCameraAnimation animation; private Location startLocation; public BlendCutscene(BlendCameraAnimation animation, Location startLocation) { this.animation = animation.clone(); this.startLocation = startLocation; this.animation.getFrames().forEach(f -> f.setLocation(f.getLocation().add(startLocation.toVector()))); } public BlendCameraAnimation getAnimation() { return animation; } public Location getStartLocation() { return startLocation; } public void setStartLocation(Location startLocation) { this.startLocation = startLocation; } /** * Rotates all frames by positions around the axis (startLocation) and yaw rotation. * @param yaw */ public void rotateAllFrames(double yaw) { animation.getFrames().forEach(f -> f.getRot().setX(Vector3f.transformFloat(f.getRot().x + ((float) Math.toDegrees(yaw)), 180))); animation.getFrames().forEach(f -> f.setLocation(MathUtils.rotateLocXZ(f.getLocation(), startLocation.toVector().clone().setY(f.getLocation().getY()), yaw))); } public void play(Plugin plugin, Player player) throws ClassNotFoundException { play(plugin, player, null, null, null); } public void play(Plugin plugin, Player player, Runnable startCallback, Runnable endCallback, Consumer markerCallback) throws ClassNotFoundException { new BukkitRunnable() { int frameIndex = 0; @Override public void run() { Frame frame = animation.getFrames().get(this.frameIndex++); player.teleport(new Location(startLocation.getWorld(), frame.getLocation().getX(), frame.getLocation().getY(), frame.getLocation().getZ(), frame.getRot().getX(), frame.getRot().getZ())); if (frameIndex <= 1) startCallback.run(); try { getEntityPlayer(player).x().getPlayerChunkMap().movePlayer(((CraftPlayer) player).getHandle()); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } frame.getMarkers().forEach(markerCallback::accept); if (this.frameIndex >= animation.getFrames().size()) cancel(); } @Override public synchronized void cancel() throws IllegalStateException { if (endCallback != null) endCallback.run(); super.cancel(); } }.runTaskTimer(plugin, 0, 1); } public static Object getEntityPlayer(Player player) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, InvocationTargetException { Class craftPlayer = getCraftBukkitClass("entity.CraftPlayer"); Method getHandle = craftPlayer.getMethod("getHandle"); return getHandle.invoke(player); } public static Class getCraftBukkitClass(String name) throws ClassNotFoundException { return Class.forName("org.bukkit.craftbukkit." + Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3] + "." + name); }