package net.aufdemrand.denizen.utilities.maps; import net.aufdemrand.denizen.utilities.DenizenAPI; import net.aufdemrand.denizen.utilities.debugging.dB; import net.aufdemrand.denizencore.utilities.CoreUtilities; import net.aufdemrand.denizencore.utilities.NaturalOrderComparator; import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.map.MapRenderer; import org.bukkit.map.MapView; import javax.imageio.stream.FileImageOutputStream; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.*; public class DenizenMapManager { private final static Map<Short, DenizenMapRenderer> mapRenderers = new HashMap<Short, DenizenMapRenderer>(); private final static Map<String, String> downloadedByUrl = new HashMap<String, String>(); private final static File imagesFolder = new File(DenizenAPI.getCurrentInstance().getDataFolder(), "images"); private final static File imageDownloads = new File(imagesFolder, "downloaded"); private final static File mapsFile = new File(DenizenAPI.getCurrentInstance().getDataFolder(), "maps.yml"); private static int downloadCount = (imageDownloads.exists() ? imageDownloads.listFiles().length : 0) + 1; private static YamlConfiguration mapsConfig; public static void reloadMaps() { Map<Short, List<MapRenderer>> oldMapRenderers = new HashMap<Short, List<MapRenderer>>(); for (Map.Entry<Short, DenizenMapRenderer> entry : mapRenderers.entrySet()) { DenizenMapRenderer renderer = entry.getValue(); oldMapRenderers.put(entry.getKey(), renderer.getOldRenderers()); renderer.deactivate(); } mapRenderers.clear(); downloadedByUrl.clear(); mapsConfig = YamlConfiguration.loadConfiguration(mapsFile); ConfigurationSection mapsSection = mapsConfig.getConfigurationSection("MAPS"); if (mapsSection == null) { return; } for (String key : mapsSection.getKeys(false)) { short mapId = Short.valueOf(key); MapView mapView = Bukkit.getServer().getMap(mapId); if (mapView == null) { dB.echoError("Map #" + key + " does not exist. Has it been removed? Deleting from maps.yml..."); mapsSection.set(key, null); continue; } ConfigurationSection objectsData = mapsSection.getConfigurationSection(key + ".objects"); List<MapRenderer> oldRenderers; if (oldMapRenderers.containsKey(mapId)) { oldRenderers = oldMapRenderers.get(mapId); } else { oldRenderers = mapView.getRenderers(); for (MapRenderer oldRenderer : oldRenderers) { mapView.removeRenderer(oldRenderer); } } DenizenMapRenderer renderer = new DenizenMapRenderer(oldRenderers, mapsSection.getBoolean(key + ".auto update", false)); List<String> objects = new ArrayList<String>(objectsData.getKeys(false)); Collections.sort(objects, new NaturalOrderComparator()); for (String objectKey : objects) { String type = objectsData.getString(objectKey + ".type").toUpperCase(); String xTag = objectsData.getString(objectKey + ".x"); String yTag = objectsData.getString(objectKey + ".y"); String visibilityTag = objectsData.getString(objectKey + ".visibility"); boolean debug = objectsData.getBoolean(objectKey + ".debug"); MapObject object = null; if (type.equals("CURSOR")) { object = new MapCursor(xTag, yTag, visibilityTag, debug, objectsData.getString(objectKey + ".direction"), objectsData.getString(objectKey + ".cursor")); } else if (type.equals("IMAGE")) { String file = objectsData.getString(objectKey + ".image"); int width = objectsData.getInt(objectKey + ".width", 0); int height = objectsData.getInt(objectKey + ".height", 0); if (CoreUtilities.toLowerCase(file).endsWith(".gif")) { object = new MapAnimatedImage(xTag, yTag, visibilityTag, debug, file, width, height); } else { object = new MapImage(xTag, yTag, visibilityTag, debug, file, width, height); } } else if (type.equals("TEXT")) { object = new MapText(xTag, yTag, visibilityTag, debug, objectsData.getString(objectKey + ".text")); } if (object != null) { renderer.addObject(object); } } mapView.addRenderer(renderer); mapRenderers.put(mapId, renderer); } for (Map.Entry<Short, List<MapRenderer>> entry : oldMapRenderers.entrySet()) { short id = entry.getKey(); if (!mapRenderers.containsKey(id)) { MapView mapView = Bukkit.getServer().getMap(id); if (mapView != null) { for (MapRenderer renderer : entry.getValue()) { mapView.addRenderer(renderer); } } // If it's null, the server no longer has the map - don't do anything about it } } ConfigurationSection downloadedImages = mapsConfig.getConfigurationSection("DOWNLOADED"); if (downloadedImages == null) { return; } for (String image : downloadedImages.getKeys(false)) { downloadedByUrl.put(CoreUtilities.toLowerCase(downloadedImages.getString(image)), image.replace("DOT", ".")); } } public static void saveMaps() { for (Map.Entry<Short, DenizenMapRenderer> entry : mapRenderers.entrySet()) { if (entry.getValue().isActive()) { mapsConfig.set("MAPS." + entry.getKey(), entry.getValue().getSaveData()); } } for (Map.Entry<String, String> entry : downloadedByUrl.entrySet()) { mapsConfig.set("DOWNLOADED." + entry.getValue().replace(".", "DOT"), entry.getKey()); } try { mapsConfig.save(mapsFile); } catch (Exception e) { dB.echoError(e); } } public static void setMap(MapView map, DenizenMapRenderer denizenMapRenderer) { List<MapRenderer> oldRenderers = map.getRenderers(); for (MapRenderer renderer : oldRenderers) { map.removeRenderer(renderer); } map.addRenderer(denizenMapRenderer); mapRenderers.put(map.getId(), denizenMapRenderer); } public static DenizenMapRenderer getDenizenRenderer(MapView map) { short mapId = map.getId(); DenizenMapRenderer dmr; if (!mapRenderers.containsKey(mapId)) { dmr = new DenizenMapRenderer(map.getRenderers(), false); setMap(map, dmr); } else { dmr = mapRenderers.get(mapId); } return dmr; } public static List<MapRenderer> removeDenizenRenderers(MapView map) { List<MapRenderer> oldRenderers = new ArrayList<MapRenderer>(); for (MapRenderer renderer : map.getRenderers()) { if (renderer instanceof DenizenMapRenderer) { map.removeRenderer(renderer); oldRenderers.addAll(((DenizenMapRenderer) renderer).getOldRenderers()); ((DenizenMapRenderer) renderer).deactivate(); mapRenderers.remove(map.getId()); } } return oldRenderers; } public static String getActualFile(String file) { String fileLower = CoreUtilities.toLowerCase(file); if (!fileLower.startsWith("http://") && !fileLower.startsWith("https://")) { return new File(imagesFolder, file).getPath(); } else { try { return downloadImage(new URL(file)); } catch (MalformedURLException e) { dB.echoError("URL is malformed: " + file); return null; } } } private static String downloadImage(URL url) { try { if (!imageDownloads.exists()) { imageDownloads.mkdirs(); } String urlString = CoreUtilities.toLowerCase(url.toString()); if (downloadedByUrl.containsKey(urlString)) { File image = new File(imageDownloads, downloadedByUrl.get(urlString)); if (image.exists()) { return image.getPath(); } } URLConnection connection = url.openConnection(); BufferedInputStream in = new BufferedInputStream(connection.getInputStream()); int lastDot = urlString.lastIndexOf('.'); String fileName = String.format("%0" + (6 - String.valueOf(downloadCount).length()) + "d", downloadCount) + (lastDot > 0 ? urlString.substring(lastDot) : ""); File output = new File(imageDownloads, fileName); FileImageOutputStream out = new FileImageOutputStream(output); int i; while ((i = in.read()) != -1) { out.write(i); } out.flush(); out.close(); in.close(); downloadedByUrl.put(urlString, fileName); downloadCount++; return output.getPath(); } catch (IOException e) { dB.echoError(e); } return null; } }