package com.dsh105.holoapi.api; import com.dsh105.commodus.IdentUtil; import com.dsh105.holoapi.HoloAPI; import com.dsh105.holoapi.config.Settings; import com.dsh105.holoapi.image.AnimatedImageGenerator; import com.dsh105.holoapi.image.AnimatedTextGenerator; import com.dsh105.holoapi.image.Frame; import com.dsh105.holoapi.util.TagIdGenerator; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; import org.bukkit.util.Vector; import java.util.ArrayList; import java.util.Map; import static com.google.common.base.Preconditions.*; public class AnimatedHologramImpl extends HologramImpl implements AnimatedHologram { private BukkitTask displayTask; private boolean imageGenerated; private String animationKey; private ArrayList<Frame> frames = new ArrayList<>(); private int index = 0; private Frame currentFrame; protected AnimatedHologramImpl(String saveId, String worldName, double x, double y, double z, AnimatedImageGenerator animatedImage) { super(TagIdGenerator.next(animatedImage.getLargestFrame().getImageGenerator().getLines().length * animatedImage.getFrames().size()), saveId, worldName, x, y, z, animatedImage.getLargestFrame().getImageGenerator().getLines()); this.frames.addAll(animatedImage.getFrames()); this.currentFrame = this.getCurrent(); this.animate(); this.imageGenerated = true; this.animationKey = animatedImage.getKey(); } protected AnimatedHologramImpl(String saveId, String worldName, double x, double y, double z, AnimatedTextGenerator textGenerator) { super(TagIdGenerator.next(textGenerator.getLargestFrame().getLines().length * textGenerator.getFrames().size()), saveId, worldName, x, y, z, textGenerator.getLargestFrame().getLines()); this.frames.addAll(textGenerator.getFrames()); this.currentFrame = this.getCurrent(); this.animate(); } @Override public boolean isImageGenerated() { return this.imageGenerated; } @Override public String getAnimationKey() { return this.animationKey; } @Override public Frame getCurrent() { return this.getFrame(this.index); } @Override public Frame getNext() { return this.getFrame((this.index + 1) >= this.frames.size() ? 0 : this.index + 1); } private Frame next() { if (++this.index >= this.frames.size()) { this.index = 0; } return this.getFrame(this.index); } @Override public Frame getFrame(int index) { if (index >= this.frames.size()) { throw new IndexOutOfBoundsException("Frame " + index + "doesn't exist."); } else if(index < 0) { throw new IndexOutOfBoundsException("Index cannot be less than 0"); } return this.frames.get(index); } @Override public ArrayList<Frame> getFrames() { ArrayList<Frame> list = new ArrayList<>(); list.addAll(this.frames); return list; } @Override public void updateLine(int index, String content) { // Nothing can happen here. Lines are always changing } @Override public void animate() { if (this.isAnimating()) { this.cancelAnimation(); } this.displayTask = new BukkitRunnable() { @Override public void run() { runAnimation(); } }.runTaskTimer(HoloAPI.getCore(), 0L, currentFrame.getDelay()); } private void runAnimation() { for (Map.Entry<String, Vector> entry : getPlayerViews().entrySet()) { final Player p = IdentUtil.getPlayerOf(entry.getKey()); if (p != null) { currentFrame = next(); updateAnimation(p, currentFrame.getLines()); } } } @Override public boolean isAnimating() { return this.displayTask != null; } @Override public void cancelAnimation() { if (this.displayTask != null) { this.displayTask.cancel(); this.displayTask = null; } } @Override public void refreshDisplay() { this.cancelAnimation(); this.animate(); } @Override public void updateAnimation(Player observer, String... lines) { checkNotNull(observer, "The Player object is null in AnimatedHologramImpl#updateAnimation(...)"); for (int index = 0; index < lines.length; index++) { this.updateNametag(observer, lines[index], index); } } @Override public void show(Player observer) { checkNotNull(observer, "The Player object is null in AnimatedHologramImpl#show(Player)"); this.showAnimation(observer, currentFrame.getLines()); } @Override public void show(Player observer, Location location) { checkNotNull(observer, "The Player object is null in AnimatedHologramImpl#show(Player, Observer)"); checkNotNull(location, "The Location object is null in AnimatedHologramImpl#show(Player, Observer)"); this.showAnimation(observer, location.toVector(), currentFrame.getLines()); } @Override public void show(Player observer, double x, double y, double z) { checkNotNull(observer, "The Player object is null in AnimatedHologramImpl#show(Player, double, double, double)"); this.showAnimation(observer, x, y, z, currentFrame.getLines()); } @Override public void showAnimation(Player observer, String... lines) { checkNotNull(observer, "The Player object is null in AnimatedHologramImpl#showAnimation(Player, String...)"); this.showAnimation(observer, this.getDefaultX(), this.getDefaultY(), this.getDefaultZ(), lines); } @Override public void showAnimation(Player observer, Vector v, String... lines) { checkNotNull(observer, "The Player object is null in AnimatedHologramImpl#showAnimation(Player, Vector, String...)"); checkNotNull(v, "The Vector object is null in AnimatedHologramImpl#showAnimation(Player, Vector, String...)"); this.showAnimation(observer, v.getBlockX(), v.getBlockY(), v.getBlockZ(), lines); } private void showAnimation(Player observer, double x, double y, double z, String[] lines) { checkNotNull(observer, "The Player object is null in AnimatedHologramImpl#showAnimation(Player, double, double, double, String[])"); checkNotNull(lines, "The String[] object is null in AnimatedHologramImpl#showAnimation(Player, double, double, double, String[])"); for (int index = 0; index < lines.length; index++) { this.generate(observer, lines[index], index, -index * Settings.VERTICAL_LINE_SPACING.getValue(), x, y, z); } this.playerToLocationMap.put(IdentUtil.getIdentificationForAsString(observer), new Vector(x, y, z)); } @Override public void move(Player observer, Vector to) { checkNotNull(observer, "The Player object is null in AnimatedHologramImpl#move(Player, Vector)"); checkNotNull(to, "The Vector object is null in AnimatedHologramImpl#move(Player, Vector)"); this.cancelAnimation(); super.move(observer, to); this.animate(); } }