/* * This file is part of HoloAPI. * * HoloAPI is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HoloAPI is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HoloAPI. If not, see <http://www.gnu.org/licenses/>. */ package com.dsh105.holoapi.image; import com.dsh105.commodus.GeneralUtil; import com.dsh105.commodus.config.YAMLConfig; import com.dsh105.holoapi.HoloAPI; import com.dsh105.holoapi.HoloAPICore; import com.dsh105.holoapi.config.Lang; import org.bukkit.command.CommandSender; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.scheduler.BukkitRunnable; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URLConnection; import java.util.HashMap; import java.util.logging.Level; public class SimpleAnimationLoader implements ImageLoader<AnimatedImageGenerator> { private final HashMap<String, AnimatedImageGenerator> KEY_TO_IMAGE_MAP = new HashMap<>(); private final HashMap<String, UnloadedImageStorage> URL_UNLOADED = new HashMap<>(); private boolean loaded; public void loadAnimationConfiguration(YAMLConfig config) { KEY_TO_IMAGE_MAP.clear(); URL_UNLOADED.clear(); File imageFolder = new File(HoloAPI.getCore().getDataFolder() + File.separator + "animations"); if (!imageFolder.exists()) { imageFolder.mkdirs(); } ConfigurationSection cs = config.getConfigurationSection("animations"); if (cs != null) { for (String key : cs.getKeys(false)) { String path = "animations." + key + "."; String imagePath = config.getString(path + "path"); if (imagePath == null) { HoloAPI.LOG.info("Failed to load animation: " + key + ". Invalid path"); continue; } int imageHeight = config.getInt(path + "height", 10); int frameRate = config.getInt(path + "frameRate", 10); boolean requiresBorder = config.getBoolean(path + "requiresBorder", true); String imageChar = config.getString(path + "characterType", ImageChar.BLOCK.getHumanName()); String imageType = config.getString(path + "type", "FILE"); if (!GeneralUtil.isEnumType(ImageLoader.ImageLoadType.class, imageType.toUpperCase())) { HoloAPI.LOG.info("Failed to load animation: " + key + ". Invalid image type."); continue; } AnimationLoadType type = AnimationLoadType.valueOf(imageType.toUpperCase()); AnimatedImageGenerator generator = findGenerator(type, key, imagePath, frameRate, imageHeight, imageChar, requiresBorder); if (generator != null) { this.KEY_TO_IMAGE_MAP.put(key, generator); } } } loaded = true; if (!KEY_TO_IMAGE_MAP.isEmpty() || !URL_UNLOADED.isEmpty()) { HoloAPI.LOG.info("Animations loaded."); } } private AnimatedImageGenerator findGenerator(AnimationLoadType type, String key, String imagePath, int frameRate, int imageHeight, String imageCharType, boolean requiresBorder) { try { ImageChar c = ImageChar.fromHumanName(imageCharType); if (c == null) { HoloAPI.LOG.info("Invalid image char type for " + key + ". Using default."); c = ImageChar.BLOCK; } switch (type) { case FILE: File f = new File(HoloAPI.getCore().getDataFolder() + File.separator + "animations" + File.separator + imagePath); if (frameRate == 0) { return new AnimatedImageGenerator(key, f, imageHeight, c, requiresBorder); } else { return new AnimatedImageGenerator(key, f, frameRate, imageHeight, c, requiresBorder); } case URL: this.URL_UNLOADED.put(key, new UnloadedImageStorage(imagePath, imageHeight, frameRate, c, requiresBorder)); return null; } } catch (Exception e) { e.printStackTrace(); return null; } return null; } @Override public AnimatedImageGenerator getGenerator(CommandSender sender, String key) { AnimatedImageGenerator g = this.KEY_TO_IMAGE_MAP.get(key); if (g == null) { if (this.URL_UNLOADED.get(key) != null) { HoloAPI.LOG.info("Loading custom URL animation of key " + key); Lang.LOADING_URL_ANIMATION.send(sender, "key", key); if (sender != null) { this.prepareUrlGenerator(sender, key); } return null; } else { Lang.FAILED_ANIMATION_LOAD.send(sender); } } return g; } @Override public AnimatedImageGenerator getGenerator(String key) { AnimatedImageGenerator g = this.KEY_TO_IMAGE_MAP.get(key); if (g == null) { if (this.URL_UNLOADED.get(key) != null) { HoloAPI.LOG.info("Loading custom URL animation of key " + key); this.prepareUrlGenerator(null, key); return null; } } return g; } private AnimatedImageGenerator prepareUrlGenerator(final CommandSender sender, final String key) { final UnloadedImageStorage data = URL_UNLOADED.get(key); final AnimatedImageGenerator generator = new AnimatedImageGenerator(key); new BukkitRunnable() { @Override public void run() { URI uri = URI.create(data.getImagePath()); URLConnection connection; InputStream input; try { connection = uri.toURL().openConnection(); connection.setRequestProperty("Content-Type", "image/gif"); connection.setUseCaches(false); connection.setDoOutput(true); connection.setConnectTimeout(8000); input = connection.getInputStream(); generator.frames = generator.readGif(input); generator.prepare(data.getImageHeight(), data.getCharType(), data.requiresBorder()); if (data.getFrameRate() != 0) { generator.prepareFrameRate(data.getFrameRate()); } if (sender != null) { Lang.ANIMATION_LOADED.send(sender, "key", key); } HoloAPI.LOG.info("Custom URL animation '" + key + "' loaded."); KEY_TO_IMAGE_MAP.put(key, generator); URL_UNLOADED.remove(key); } catch (IOException e) { e.printStackTrace(); } } }.runTaskAsynchronously(HoloAPI.getCore()); return generator; } @Override public boolean exists(String key) { return this.KEY_TO_IMAGE_MAP.containsKey(key); } @Override public boolean existsAsUnloadedUrl(String key) { return this.URL_UNLOADED.containsKey(key); } @Override public boolean isLoaded() { return loaded; } public enum AnimationLoadType { FILE, URL } }