Update 1.0.11

- potentially fix color cache error
- added /imagemap cleanup command
- added /imagemap debuginfo command
This commit is contained in:
SydMontague 2023-05-01 11:05:42 +02:00
parent 67ed74b006
commit b70a163c3c
23 changed files with 2050 additions and 1902 deletions

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>net.craftcitizen</groupId> <groupId>net.craftcitizen</groupId>
<artifactId>imagemaps</artifactId> <artifactId>imagemaps</artifactId>
<version>1.0.10</version> <version>1.0.11</version>
<name>ImageMaps</name> <name>ImageMaps</name>
<description>Render Images onto maps!</description> <description>Render Images onto maps!</description>

View File

@ -78,7 +78,8 @@ public class ImageMap implements ConfigurationSerializable {
if (filename == null) { if (filename == null) {
if (other.filename != null) if (other.filename != null)
return false; return false;
} else if (!filename.equals(other.filename)) }
else if (!filename.equals(other.filename))
return false; return false;
if (Double.doubleToLongBits(scale) != Double.doubleToLongBits(other.scale)) if (Double.doubleToLongBits(scale) != Double.doubleToLongBits(other.scale))
return false; return false;

View File

@ -0,0 +1,37 @@
package net.craftcitizen.imagemaps;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import de.craftlancer.core.util.MessageLevel;
import de.craftlancer.core.util.MessageUtil;
public class ImageMapCleanupCommand extends ImageMapSubCommand {
public ImageMapCleanupCommand(ImageMaps plugin) {
super("imagemaps.admin", plugin, true);
}
@Override
protected String execute(CommandSender sender, Command cmd, String label, String[] args) {
if (!checkSender(sender)) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "You can't run this command.");
return null;
}
int removedMaps = getPlugin().cleanupMaps();
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"Removed " + removedMaps + " invalid images/maps.");
return null;
}
@Override
public void help(CommandSender sender) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"Removes maps with invalid IDs or missing image files.");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING,
"This action is not reverseable. It is recommended to create a backup of your maps.yml first!");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO, "Usage: /imagemap cleanup");
}
}

View File

@ -11,6 +11,8 @@ public class ImageMapCommandHandler extends CommandHandler {
registerSubCommand("info", new ImageMapInfoCommand(plugin)); registerSubCommand("info", new ImageMapInfoCommand(plugin));
registerSubCommand("list", new ImageMapListCommand(plugin)); registerSubCommand("list", new ImageMapListCommand(plugin));
registerSubCommand("reload", new ImageMapReloadCommand(plugin)); registerSubCommand("reload", new ImageMapReloadCommand(plugin));
registerSubCommand("cleanup", new ImageMapCleanupCommand(plugin));
registerSubCommand("debuginfo", new ImageMapDebugInfoCommand(plugin));
registerSubCommand("help", new ImageMapHelpCommand(plugin, getCommands()), "?"); registerSubCommand("help", new ImageMapHelpCommand(plugin, getCommands()), "?");
} }
} }

View File

@ -0,0 +1,39 @@
package net.craftcitizen.imagemaps;
import javax.imageio.ImageIO;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import de.craftlancer.core.util.MessageLevel;
import de.craftlancer.core.util.MessageUtil;
public class ImageMapDebugInfoCommand extends ImageMapSubCommand {
public ImageMapDebugInfoCommand(ImageMaps plugin) {
super("imagemaps.admin", plugin, true);
}
@Override
protected String execute(CommandSender sender, Command cmd, String label, String[] args) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"ImageMaps Version " + getPlugin().getDescription().getVersion());
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "OS: " + System.getProperty("os.name"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "ImageIO Params:");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"Formats: " + String.join(", ", ImageIO.getReaderFormatNames()));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"Suffixes: " + String.join(", ", ImageIO.getReaderFileSuffixes()));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"MIME: " + String.join(", ", ImageIO.getReaderMIMETypes()));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"Uses Cache: " + Boolean.toString(ImageIO.getUseCache()));
return null;
}
@Override
public void help(CommandSender sender) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Prints some debug output.");
}
}

View File

@ -42,7 +42,8 @@ public class ImageMapDeleteCommand extends ImageMapSubCommand {
if (getPlugin().deleteImage(filename)) { if (getPlugin().deleteImage(filename)) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "File deleted."); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "File deleted.");
} else { }
else {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "Failed to delete file."); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "Failed to delete file.");
} }
return null; return null;

View File

@ -30,7 +30,8 @@ public class ImageMapDownloadCommand extends ImageMapSubCommand {
} }
if (args.length < 3) { if (args.length < 3) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "You must specify a file name and a download link."); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING,
"You must specify a file name and a download link.");
return null; return null;
} }
@ -65,23 +66,24 @@ public class ImageMapDownloadCommand extends ImageMapSubCommand {
connection.setRequestProperty("User-Agent", "ImageMaps/0"); connection.setRequestProperty("User-Agent", "ImageMaps/0");
if (((HttpURLConnection) connection).getResponseCode() != 200) { if (((HttpURLConnection) connection).getResponseCode() != 200) {
MessageUtil.sendMessage(getPlugin(), MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING,
sender, String.format("Download failed, HTTP Error code %d.",
MessageLevel.WARNING, ((HttpURLConnection) connection).getResponseCode()));
String.format("Download failed, HTTP Error code %d.", ((HttpURLConnection) connection).getResponseCode()));
return; return;
} }
String mimeType = connection.getHeaderField("Content-type"); String mimeType = connection.getHeaderField("Content-type");
if (!(mimeType.startsWith("image/"))) { if (!(mimeType.startsWith("image/"))) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, String.format("Download is a %s file, not image.", mimeType)); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING,
String.format("Download is a %s file, not image.", mimeType));
return; return;
} }
try (InputStream str = connection.getInputStream()) { try (InputStream str = connection.getInputStream()) {
BufferedImage image = ImageIO.read(str); BufferedImage image = ImageIO.read(str);
if (image == null) { if (image == null) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "Downloaded file is not an image!"); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING,
"Downloaded file is not an image!");
return; return;
} }
@ -90,18 +92,23 @@ public class ImageMapDownloadCommand extends ImageMapSubCommand {
ImageIO.write(image, "PNG", outFile); ImageIO.write(image, "PNG", outFile);
if (fileExisted) { if (fileExisted) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "File already exists, overwriting!"); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING,
"File already exists, overwriting!");
getPlugin().reloadImage(filename); getPlugin().reloadImage(filename);
} }
} catch (IllegalArgumentException ex) { }
catch (IllegalArgumentException ex) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "Received no data"); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "Received no data");
return; return;
} }
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Download complete."); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Download complete.");
} catch (MalformedURLException ex) { }
catch (MalformedURLException ex) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "Malformatted URL"); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "Malformatted URL");
} catch (IOException ex) { }
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.ERROR, "An IO Exception happened, see server log"); catch (IOException ex) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.ERROR,
"An IO Exception happened, see server log");
ex.printStackTrace(); ex.printStackTrace();
} }
} }
@ -109,6 +116,7 @@ public class ImageMapDownloadCommand extends ImageMapSubCommand {
@Override @Override
public void help(CommandSender sender) { public void help(CommandSender sender) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Downloads an image from an URL."); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Downloads an image from an URL.");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO, "Usage: /imagemap download <filename> <sourceURL>"); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO,
"Usage: /imagemap download <filename> <sourceURL>");
} }
} }

View File

@ -21,25 +21,34 @@ public class ImageMapHelpCommand extends HelpCommand {
@Override @Override
public void help(CommandSender sender) { public void help(CommandSender sender) {
if (((ImageMaps) getPlugin()).isGlowingSupported()) { if (((ImageMaps) getPlugin()).isGlowingSupported()) {
MessageUtil.sendMessage(getPlugin(), MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
sender, buildMessage("/imagemap place <filename> [frameInvisible] [frameFixed] [frameGlowing] [size]",
MessageLevel.NORMAL, " - starts image placement"));
buildMessage("/imagemap place <filename> [frameInvisible] [frameFixed] [frameGlowing] [size]", " - starts image placement")); }
} else if (((ImageMaps) getPlugin()).isInvisibilitySupported()) { else if (((ImageMaps) getPlugin()).isInvisibilitySupported()) {
MessageUtil.sendMessage(getPlugin(), MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
sender, buildMessage("/imagemap place <filename> [frameInvisible] [frameFixed] [size]",
MessageLevel.NORMAL, " - starts image placement"));
buildMessage("/imagemap place <filename> [frameInvisible] [frameFixed] [size]", " - starts image placement")); }
} else { else {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, buildMessage("/imagemap place <filename> [size]", " - starts image placement")); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
buildMessage("/imagemap place <filename> [size]", " - starts image placement"));
} }
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, buildMessage("/imagemap download <filename> <sourceURL>", " - downloads an image")); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, buildMessage("/imagemap delete <filename>", " - deletes an image")); buildMessage("/imagemap download <filename> <sourceURL>", " - downloads an image"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, buildMessage("/imagemap info <filename>", " - displays image info")); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, buildMessage("/imagemap reload <filename>", " - reloads an image from disk")); buildMessage("/imagemap delete <filename>", " - deletes an image"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, buildMessage("/imagemap list [page]", " - lists all files in the images folder")); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, buildMessage("/imagemap help [command]", " - shows help")); buildMessage("/imagemap info <filename>", " - displays image info"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
buildMessage("/imagemap reload <filename>", " - reloads an image from disk"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
buildMessage("/imagemap cleanup", " - removes invalid maps from plugin"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
buildMessage("/imagemap list [page]", " - lists all files in the images folder"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
buildMessage("/imagemap help [command]", " - shows help"));
} }
private static BaseComponent buildMessage(String str1, String str2) { private static BaseComponent buildMessage(String str1, String str2) {

View File

@ -44,13 +44,16 @@ public class ImageMapInfoCommand extends ImageMapSubCommand {
Tuple<Integer, Integer> size = getPlugin().getImageSize(filename, null); Tuple<Integer, Integer> size = getPlugin().getImageSize(filename, null);
BaseComponent reloadAction = new TextComponent("[Reload]"); BaseComponent reloadAction = new TextComponent("[Reload]");
reloadAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/imagemap reload \"%s\"", filename))); reloadAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND,
String.format("/imagemap reload \"%s\"", filename)));
reloadAction.setColor(ChatColor.GOLD); reloadAction.setColor(ChatColor.GOLD);
BaseComponent placeAction = new TextComponent("[Place]"); BaseComponent placeAction = new TextComponent("[Place]");
placeAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/imagemap place \"%s\"", filename))); placeAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND,
String.format("/imagemap place \"%s\"", filename)));
placeAction.setColor(ChatColor.GOLD); placeAction.setColor(ChatColor.GOLD);
BaseComponent deleteAction = new TextComponent("[Delete]"); BaseComponent deleteAction = new TextComponent("[Delete]");
deleteAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/imagemap delete \"%s\"", filename))); deleteAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND,
String.format("/imagemap delete \"%s\"", filename)));
deleteAction.setColor(ChatColor.RED); deleteAction.setColor(ChatColor.RED);
BaseComponent actions = new TextComponent("Action: "); BaseComponent actions = new TextComponent("Action: ");
@ -62,8 +65,10 @@ public class ImageMapInfoCommand extends ImageMapSubCommand {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO, "Image Information: "); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO, "Image Information: ");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, String.format("File Name: %s", filename)); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, String.format("File Name: %s", filename));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, String.format("Resolution: %dx%d", image.getWidth(), image.getHeight())); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, String.format("Ingame Size: %dx%d", size.getKey(), size.getValue())); String.format("Resolution: %dx%d", image.getWidth(), image.getHeight()));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
String.format("Ingame Size: %dx%d", size.getKey(), size.getValue()));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, actions); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, actions);
return null; return null;
} }

View File

@ -30,22 +30,26 @@ public class ImageMapListCommand extends ImageMapSubCommand {
long page = args.length >= 2 ? Utils.parseIntegerOrDefault(args[1], 0) - 1 : 0; long page = args.length >= 2 ? Utils.parseIntegerOrDefault(args[1], 0) - 1 : 0;
int numPages = (int) Math.ceil((double) fileList.length / Utils.ELEMENTS_PER_PAGE); int numPages = (int) Math.ceil((double) fileList.length / Utils.ELEMENTS_PER_PAGE);
MessageUtil.sendMessage(plugin, sender, MessageLevel.INFO,
MessageUtil.sendMessage(plugin, sender, MessageLevel.INFO, String.format("## Image List Page %d of %d ##", page + 1, numPages)); String.format("## Image List Page %d of %d ##", page + 1, numPages));
boolean even = false; boolean even = false;
for (String filename : Utils.paginate(fileList, page)) { for (String filename : Utils.paginate(fileList, page)) {
BaseComponent infoAction = new TextComponent("[Info]"); BaseComponent infoAction = new TextComponent("[Info]");
infoAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/imagemap info \"%s\"", filename))); infoAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND,
String.format("/imagemap info \"%s\"", filename)));
infoAction.setColor(ChatColor.GOLD); infoAction.setColor(ChatColor.GOLD);
BaseComponent reloadAction = new TextComponent("[Reload]"); BaseComponent reloadAction = new TextComponent("[Reload]");
reloadAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/imagemap reload \"%s\"", filename))); reloadAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND,
String.format("/imagemap reload \"%s\"", filename)));
reloadAction.setColor(ChatColor.GOLD); reloadAction.setColor(ChatColor.GOLD);
BaseComponent placeAction = new TextComponent("[Place]"); BaseComponent placeAction = new TextComponent("[Place]");
placeAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/imagemap place \"%s\"", filename))); placeAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND,
String.format("/imagemap place \"%s\"", filename)));
placeAction.setColor(ChatColor.GOLD); placeAction.setColor(ChatColor.GOLD);
BaseComponent deleteAction = new TextComponent("[Delete]"); BaseComponent deleteAction = new TextComponent("[Delete]");
deleteAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/imagemap delete \"%s\"", filename))); deleteAction.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND,
String.format("/imagemap delete \"%s\"", filename)));
deleteAction.setColor(ChatColor.RED); deleteAction.setColor(ChatColor.RED);
BaseComponent message = new TextComponent(filename); BaseComponent message = new TextComponent(filename);
@ -65,7 +69,7 @@ public class ImageMapListCommand extends ImageMapSubCommand {
BaseComponent navigation = new TextComponent(); BaseComponent navigation = new TextComponent();
BaseComponent prevPage = new TextComponent(String.format("<< Page %d", Math.max(page, 1))); BaseComponent prevPage = new TextComponent(String.format("<< Page %d", Math.max(page, 1)));
BaseComponent nextPage = new TextComponent(String.format("Page %d >>", Math.min(page + 1, numPages))); BaseComponent nextPage = new TextComponent(String.format("Page %d >>", Math.min(page + 2, numPages)));
prevPage.setClickEvent(new ClickEvent(Action.RUN_COMMAND, "/imagemap list " + Math.max(page, 1))); prevPage.setClickEvent(new ClickEvent(Action.RUN_COMMAND, "/imagemap list " + Math.max(page, 1)));
nextPage.setClickEvent(new ClickEvent(Action.RUN_COMMAND, "/imagemap list " + Math.min(page + 2, numPages))); nextPage.setClickEvent(new ClickEvent(Action.RUN_COMMAND, "/imagemap list " + Math.min(page + 2, numPages)));

View File

@ -44,10 +44,12 @@ public class ImageMapPlaceCommand extends ImageMapSubCommand {
if (getPlugin().isGlowingSupported()) { if (getPlugin().isGlowingSupported()) {
isGlowing = args.length >= 5 && Boolean.parseBoolean(args[4]); isGlowing = args.length >= 5 && Boolean.parseBoolean(args[4]);
scale = args.length >= 6 ? parseScale(args[5]) : new Tuple<>(-1, -1); scale = args.length >= 6 ? parseScale(args[5]) : new Tuple<>(-1, -1);
} else { }
else {
scale = args.length >= 5 ? parseScale(args[4]) : new Tuple<>(-1, -1); scale = args.length >= 5 ? parseScale(args[4]) : new Tuple<>(-1, -1);
} }
} else { }
else {
scale = args.length >= 3 ? parseScale(args[2]) : new Tuple<>(-1, -1); scale = args.length >= 3 ? parseScale(args[2]) : new Tuple<>(-1, -1);
} }
@ -62,14 +64,16 @@ public class ImageMapPlaceCommand extends ImageMapSubCommand {
} }
Player player = (Player) sender; Player player = (Player) sender;
player.setMetadata(ImageMaps.PLACEMENT_METADATA, new FixedMetadataValue(getPlugin(), new PlacementData(filename, isInvisible, isFixed, isGlowing, scale))); player.setMetadata(ImageMaps.PLACEMENT_METADATA,
new FixedMetadataValue(getPlugin(),
new PlacementData(filename, isInvisible, isFixed, isGlowing, scale)));
Tuple<Integer, Integer> size = getPlugin().getImageSize(filename, scale); Tuple<Integer, Integer> size = getPlugin().getImageSize(filename, scale);
MessageUtil.sendMessage(getPlugin(), MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
sender, String.format("Started placing of %s. It needs a %d by %d area.", args[1],
MessageLevel.NORMAL, size.getKey(), size.getValue()));
String.format("Started placing of %s. It needs a %d by %d area.", args[1], size.getKey(), size.getValue())); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Right click on the block, that should be the upper left corner."); "Right click on the block, that should be the upper left corner.");
return null; return null;
} }
@ -78,22 +82,23 @@ public class ImageMapPlaceCommand extends ImageMapSubCommand {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Starts placing an image."); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Starts placing an image.");
if (getPlugin().isGlowingSupported()) { if (getPlugin().isGlowingSupported()) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO, "Usage: /imagemap place <filename> [frameInvisible] [frameFixed] [frameGlowing] [size]"); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO,
} else if (getPlugin().isInvisibilitySupported()) { "Usage: /imagemap place <filename> [frameInvisible] [frameFixed] [frameGlowing] [size]");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO, "Usage: /imagemap place <filename> [frameInvisible] [frameFixed] [size]"); }
} else { else if (getPlugin().isInvisibilitySupported()) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO,
"Usage: /imagemap place <filename> [frameInvisible] [frameFixed] [size]");
}
else {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO, "Usage: /imagemap place <filename> [size]"); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO, "Usage: /imagemap place <filename> [size]");
} }
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Size format: XxY -> 5x2, use -1 for default"); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
MessageUtil.sendMessage(getPlugin(), "Size format: XxY -> 5x2, use -1 for default");
sender, MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
MessageLevel.NORMAL, "The plugin will scale the map to not be larger than the given size while maintaining the aspect ratio.");
"The plugin will scale the map to not be larger than the given size while maintaining the aspect ratio."); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
MessageUtil.sendMessage(getPlugin(), "It's recommended to avoid the size function in favor of using properly sized source images.");
sender,
MessageLevel.NORMAL,
"It's recommended to avoid the size function in favor of using properly sized source images.");
} }
private static Tuple<Integer, Integer> parseScale(String string) { private static Tuple<Integer, Integer> parseScale(String string) {
@ -108,7 +113,7 @@ public class ImageMapPlaceCommand extends ImageMapSubCommand {
@Override @Override
protected List<String> onTabComplete(CommandSender sender, String[] args) { protected List<String> onTabComplete(CommandSender sender, String[] args) {
if (args.length > 2 && !getPlugin().isInvisibilitySupported() if (args.length > 2 && !getPlugin().isInvisibilitySupported()
|| args.length > 4 && !getPlugin().isGlowingSupported()) { || args.length > 4 && !getPlugin().isGlowingSupported()) {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -38,15 +38,18 @@ public class ImageMapReloadCommand extends ImageMapSubCommand {
if (getPlugin().reloadImage(filename)) if (getPlugin().reloadImage(filename))
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Image reloaded."); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Image reloaded.");
else else
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Image couldn't be reloaded (does it exist?)."); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"Image couldn't be reloaded (does it exist?).");
return null; return null;
} }
@Override @Override
public void help(CommandSender sender) { public void help(CommandSender sender) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Reloads an image from disk, to be used when the file changed."); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Avoid resolution changes, since they won't be scaled."); "Reloads an image from disk, to be used when the file changed.");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"Avoid resolution changes, since they won't be scaled.");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO, "Usage: /imagemap reload <filename>"); MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO, "Usage: /imagemap reload <filename>");
} }

View File

@ -30,7 +30,8 @@ public class ImageMapRenderer extends MapRenderer {
} }
public void recalculateInput(BufferedImage input) { public void recalculateInput(BufferedImage input) {
if (x * ImageMaps.MAP_WIDTH > Math.round(input.getWidth() * scale) || y * ImageMaps.MAP_HEIGHT > Math.round(input.getHeight() * scale)) if (x * ImageMaps.MAP_WIDTH > Math.round(input.getWidth() * scale)
|| y * ImageMaps.MAP_HEIGHT > Math.round(input.getHeight() * scale))
return; return;
int x1 = (int) Math.floor(x * ImageMaps.MAP_WIDTH / scale); int x1 = (int) Math.floor(x * ImageMaps.MAP_WIDTH / scale);
@ -45,7 +46,8 @@ public class ImageMapRenderer extends MapRenderer {
this.image = input.getSubimage(x1, y1, x2 - x1, y2 - y1); this.image = input.getSubimage(x1, y1, x2 - x1, y2 - y1);
if (scale != 1D) { if (scale != 1D) {
BufferedImage resized = new BufferedImage(ImageMaps.MAP_WIDTH, ImageMaps.MAP_HEIGHT, input.getType() == 0 ? image.getType() : input.getType()); BufferedImage resized = new BufferedImage(ImageMaps.MAP_WIDTH, ImageMaps.MAP_HEIGHT,
input.getType() == 0 ? image.getType() : input.getType());
AffineTransform at = new AffineTransform(); AffineTransform at = new AffineTransform();
at.scale(scale, scale); at.scale(scale, scale);
AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
@ -58,20 +60,8 @@ public class ImageMapRenderer extends MapRenderer {
@Override @Override
public void render(MapView view, MapCanvas canvas, Player player) { public void render(MapView view, MapCanvas canvas, Player player) {
if (image != null && first) { if (image != null && first) {
new LambdaRunnable(() -> { new LambdaRunnable(() -> canvas.drawImage(0, 0, image)).runTaskLater(plugin, System.nanoTime() % 60);
@SuppressWarnings("deprecation") // spread out pseudo randomly in a very naive way
byte[] imageData = MapPalette.imageToBytes(image);
new LambdaRunnable(() -> {
for (int x2 = 0; x2 < image.getWidth(null); ++x2) {
for (int y2 = 0; y2 < image.getHeight(null); ++y2) {
canvas.setPixel(x2, y2, imageData[y2 * image.getWidth(null) + x2]);
}
}
}).runTaskLater(plugin, System.nanoTime() % 20);
// spread out pseudo randomly in a very naive way
}).runTaskAsynchronously(plugin);
first = false; first = false;
} }
} }

View File

@ -69,9 +69,11 @@ public class ImageMaps extends JavaPlugin implements Listener {
@Override @Override
public void onEnable() { public void onEnable() {
BaseComponent prefix = new TextComponent( BaseComponent prefix = new TextComponent(new ComponentBuilder("[").color(ChatColor.GRAY).append("ImageMaps")
new ComponentBuilder("[").color(ChatColor.GRAY).append("ImageMaps").color(ChatColor.AQUA).append("]").color(ChatColor.GRAY).create()); .color(ChatColor.AQUA).append("]")
MessageUtil.registerPlugin(this, prefix, ChatColor.GRAY, ChatColor.YELLOW, ChatColor.RED, ChatColor.DARK_RED, ChatColor.DARK_AQUA); .color(ChatColor.GRAY).create());
MessageUtil.registerPlugin(this, prefix, ChatColor.GRAY, ChatColor.YELLOW, ChatColor.RED, ChatColor.DARK_RED,
ChatColor.DARK_AQUA);
if (!new File(getDataFolder(), IMAGES_DIR).exists()) if (!new File(getDataFolder(), IMAGES_DIR).exists())
new File(getDataFolder(), IMAGES_DIR).mkdirs(); new File(getDataFolder(), IMAGES_DIR).mkdirs();
@ -102,8 +104,8 @@ public class ImageMaps extends JavaPlugin implements Listener {
if (!isInvisibilitySupported()) if (!isInvisibilitySupported())
return; return;
if (event.getRightClicked().getType() != EntityType.ITEM_FRAME && if (event.getRightClicked().getType() != EntityType.ITEM_FRAME
(!isGlowingSupported() || event.getRightClicked().getType() != EntityType.GLOW_ITEM_FRAME)) && (!isGlowingSupported() || event.getRightClicked().getType() != EntityType.GLOW_ITEM_FRAME))
return; return;
ItemFrame frame = (ItemFrame) event.getRightClicked(); ItemFrame frame = (ItemFrame) event.getRightClicked();
@ -116,12 +118,15 @@ public class ImageMaps extends JavaPlugin implements Listener {
if (p.hasPermission("imagemaps.toggleFixed")) { if (p.hasPermission("imagemaps.toggleFixed")) {
event.setCancelled(true); event.setCancelled(true);
frame.setFixed(!frame.isFixed()); frame.setFixed(!frame.isFixed());
MessageUtil.sendMessage(this, p, MessageLevel.INFO, String.format("Frame set to %s.", frame.isFixed() ? "fixed" : "unfixed")); MessageUtil.sendMessage(this, p, MessageLevel.INFO,
String.format("Frame set to %s.", frame.isFixed() ? "fixed" : "unfixed"));
} }
} else if (p.hasPermission("imagemaps.toggleVisible")) { }
else if (p.hasPermission("imagemaps.toggleVisible")) {
event.setCancelled(true); event.setCancelled(true);
frame.setVisible(!frame.isVisible()); frame.setVisible(!frame.isVisible());
MessageUtil.sendMessage(this, p, MessageLevel.INFO, String.format("Frame set to %s.", frame.isVisible() ? "visible" : "invisible")); MessageUtil.sendMessage(this, p, MessageLevel.INFO,
String.format("Frame set to %s.", frame.isVisible() ? "visible" : "invisible"));
} }
} }
@ -159,7 +164,8 @@ public class ImageMaps extends JavaPlugin implements Listener {
BukkitRunnable saveTask = new LambdaRunnable(() -> { BukkitRunnable saveTask = new LambdaRunnable(() -> {
try { try {
config.save(new File(getDataFolder(), MAPS_YML)); config.save(new File(getDataFolder(), MAPS_YML));
} catch (IOException e) { }
catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
}); });
@ -190,30 +196,46 @@ public class ImageMaps extends JavaPlugin implements Listener {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
MapView map = Bukkit.getMap(id); MapView map = Bukkit.getMap(id);
BufferedImage image = getImage(imageMap.getFilename()); BufferedImage image = getImage(imageMap.getFilename());
maps.put(imageMap, id);
if (image == null) { if (image == null) {
getLogger().warning(() -> "Image file " + imageMap.getFilename() + " not found. Removing map!"); getLogger().warning(() -> "Image file " + imageMap.getFilename() + " not found!");
return; return;
} }
if (map == null) { if (map == null) {
getLogger().warning(() -> "Map " + id + " referenced but does not exist. Removing map!"); getLogger().warning(() -> "Map " + id + " referenced but does not exist!");
return; return;
} }
if (isSetTrackingSupported()) if (isSetTrackingSupported())
map.setTrackingPosition(false); map.setTrackingPosition(false);
map.getRenderers().forEach(map::removeRenderer); map.getRenderers().forEach(map::removeRenderer);
map.addRenderer(new ImageMapRenderer(this, image, imageMap.getX(), imageMap.getY(), imageMap.getScale())); map.addRenderer(new ImageMapRenderer(this, image, imageMap.getX(), imageMap.getY(),
maps.put(imageMap, id); imageMap.getScale()));
}); });
} }
public int cleanupMaps() {
int start = maps.size();
maps.entrySet().removeIf(a -> {
@SuppressWarnings("deprecation")
MapView map = Bukkit.getMap(a.getValue().intValue());
BufferedImage image = getImage(a.getKey().getFilename());
return map == null || image == null;
});
return start - maps.size();
}
private Configuration convertLegacyMaps(Configuration config) { private Configuration convertLegacyMaps(Configuration config) {
getLogger().info("Converting maps from Version <1.0"); getLogger().info("Converting maps from Version <1.0");
try { try {
Files.copy(new File(getDataFolder(), MAPS_YML), new File(getDataFolder(), MAPS_YML + ".backup")); Files.copy(new File(getDataFolder(), MAPS_YML), new File(getDataFolder(), MAPS_YML + ".backup"));
} catch (IOException e) { }
catch (IOException e) {
getLogger().severe("Failed to backup maps.yml!"); getLogger().severe("Failed to backup maps.yml!");
e.printStackTrace(); e.printStackTrace();
} }
@ -244,6 +266,7 @@ public class ImageMaps extends JavaPlugin implements Listener {
return file.exists() && getImage(filename) != null; return file.exists() && getImage(filename) != null;
} }
// TODO stop returning null, begin throwing exception
public BufferedImage getImage(String filename) { public BufferedImage getImage(String filename) {
if (filename.contains("/") || filename.contains("\\") || filename.contains(":")) { if (filename.contains("/") || filename.contains("\\") || filename.contains(":")) {
getLogger().warning("Someone tried to get image with illegal characters in file name."); getLogger().warning("Someone tried to get image with illegal characters in file name.");
@ -262,10 +285,14 @@ public class ImageMaps extends JavaPlugin implements Listener {
try { try {
image = ImageIO.read(file); image = ImageIO.read(file);
imageCache.put(filename.toLowerCase(), image); imageCache.put(filename.toLowerCase(), image);
} catch (IOException e) { }
catch (IOException e) {
getLogger().log(Level.SEVERE, String.format("Error while trying to read image %s.", file.getName()), e); getLogger().log(Level.SEVERE, String.format("Error while trying to read image %s.", file.getName()), e);
} }
if (image == null)
getLogger().log(Level.WARNING, () -> String.format("Failed to read file as image %s.", file.getName()));
return image; return image;
} }
@ -290,22 +317,27 @@ public class ImageMaps extends JavaPlugin implements Listener {
switch (result) { switch (result) {
case INVALID_FACING: case INVALID_FACING:
MessageUtil.sendMessage(this, player, MessageLevel.WARNING, "You can't place an image on this block face."); MessageUtil.sendMessage(this, player, MessageLevel.WARNING,
"You can't place an image on this block face.");
break; break;
case INVALID_DIRECTION: case INVALID_DIRECTION:
MessageUtil.sendMessage(this, player, MessageLevel.WARNING, "Couldn't calculate how to place the map."); MessageUtil.sendMessage(this, player, MessageLevel.WARNING, "Couldn't calculate how to place the map.");
break; break;
case EVENT_CANCELLED: case EVENT_CANCELLED:
MessageUtil.sendMessage(this, player, MessageLevel.NORMAL, "Image placement cancelled by another plugin."); MessageUtil.sendMessage(this, player, MessageLevel.NORMAL,
"Image placement cancelled by another plugin.");
break; break;
case INSUFFICIENT_SPACE: case INSUFFICIENT_SPACE:
MessageUtil.sendMessage(this, player, MessageLevel.NORMAL, "Map couldn't be placed, the space is blocked."); MessageUtil.sendMessage(this, player, MessageLevel.NORMAL,
"Map couldn't be placed, the space is blocked.");
break; break;
case INSUFFICIENT_WALL: case INSUFFICIENT_WALL:
MessageUtil.sendMessage(this, player, MessageLevel.NORMAL, "Map couldn't be placed, the supporting wall is too small."); MessageUtil.sendMessage(this, player, MessageLevel.NORMAL,
"Map couldn't be placed, the supporting wall is too small.");
break; break;
case OVERLAPPING_ENTITY: case OVERLAPPING_ENTITY:
MessageUtil.sendMessage(this, player, MessageLevel.NORMAL, "Map couldn't be placed, there is another entity in the way."); MessageUtil.sendMessage(this, player, MessageLevel.NORMAL,
"Map couldn't be placed, there is another entity in the way.");
break; break;
case SUCCESS: case SUCCESS:
break; break;
@ -342,11 +374,14 @@ public class ImageMaps extends JavaPlugin implements Listener {
return PlacementResult.INSUFFICIENT_WALL; return PlacementResult.INSUFFICIENT_WALL;
if (frameBlock.getType().isSolid()) if (frameBlock.getType().isSolid())
return PlacementResult.INSUFFICIENT_SPACE; return PlacementResult.INSUFFICIENT_SPACE;
if (!b.getWorld().getNearbyEntities(frameBlock.getLocation().add(0.5, 0.5, 0.5), 0.5, 0.5, 0.5, Hanging.class::isInstance).isEmpty()) if (!b.getWorld().getNearbyEntities(frameBlock.getLocation().add(0.5, 0.5, 0.5), 0.5, 0.5, 0.5,
Hanging.class::isInstance)
.isEmpty())
return PlacementResult.OVERLAPPING_ENTITY; return PlacementResult.OVERLAPPING_ENTITY;
} }
ImagePlaceEvent event = new ImagePlaceEvent(player, block, widthDirection, heightDirection, size.getKey(), size.getValue(), data); ImagePlaceEvent event = new ImagePlaceEvent(player, block, widthDirection, heightDirection, size.getKey(),
size.getValue(), data);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) if (event.isCancelled())
return PlacementResult.EVENT_CANCELLED; return PlacementResult.EVENT_CANCELLED;
@ -355,7 +390,10 @@ public class ImageMaps extends JavaPlugin implements Listener {
for (int x = 0; x < size.getKey(); x++) for (int x = 0; x < size.getKey(); x++)
for (int y = 0; y < size.getValue(); y++) { for (int y = 0; y < size.getValue(); y++) {
Class<? extends ItemFrame> itemFrameClass = data.isGlowing() ? GlowItemFrame.class : ItemFrame.class; Class<? extends ItemFrame> itemFrameClass = data.isGlowing() ? GlowItemFrame.class : ItemFrame.class;
ItemFrame frame = block.getWorld().spawn(b.getRelative(widthDirection, x).getRelative(heightDirection, y).getLocation(), itemFrameClass); ItemFrame frame = block.getWorld().spawn(
b.getRelative(widthDirection, x)
.getRelative(heightDirection, y).getLocation(),
itemFrameClass);
frame.setFacingDirection(face); frame.setFacingDirection(face);
frame.setItem(getMapItem(image, x, y, data)); frame.setItem(getMapItem(image, x, y, data));
frame.setRotation(facingToRotation(heightDirection, widthDirection)); frame.setRotation(facingToRotation(heightDirection, widthDirection));
@ -414,8 +452,9 @@ public class ImageMaps extends JavaPlugin implements Listener {
return false; return false;
} }
maps.entrySet().stream().filter(a -> a.getKey().getFilename().equalsIgnoreCase(filename)).map(a -> Bukkit.getMap(a.getValue())) maps.entrySet().stream().filter(a -> a.getKey().getFilename().equalsIgnoreCase(filename))
.flatMap(a -> a.getRenderers().stream()).filter(ImageMapRenderer.class::isInstance).forEach(a -> ((ImageMapRenderer) a).recalculateInput(image)); .map(a -> Bukkit.getMap(a.getValue())).flatMap(a -> a.getRenderers().stream())
.filter(ImageMapRenderer.class::isInstance).forEach(a -> ((ImageMapRenderer) a).recalculateInput(image));
return true; return true;
} }

View File

@ -23,7 +23,8 @@ public class ImagePlaceEvent extends Event implements Cancellable {
private boolean cancelled; private boolean cancelled;
public ImagePlaceEvent(Player player, Block block, BlockFace widthDirection, BlockFace heightDirection, int width, int height, PlacementData cache) { public ImagePlaceEvent(Player player, Block block, BlockFace widthDirection, BlockFace heightDirection, int width,
int height, PlacementData cache) {
this.player = player; this.player = player;
this.block = block; this.block = block;
this.widthDirection = widthDirection; this.widthDirection = widthDirection;

View File

@ -13,7 +13,8 @@ public class PlacementData {
private final boolean isGlowing; private final boolean isGlowing;
private final Tuple<Integer, Integer> scale; private final Tuple<Integer, Integer> scale;
public PlacementData(String filename, boolean isInvisible, boolean isFixed, boolean isGlowing, Tuple<Integer, Integer> scale) { public PlacementData(String filename, boolean isInvisible, boolean isFixed, boolean isGlowing,
Tuple<Integer, Integer> scale) {
this.filename = filename; this.filename = filename;
this.isInvisible = isInvisible; this.isInvisible = isInvisible;
this.isFixed = isFixed; this.isFixed = isFixed;
@ -31,8 +32,8 @@ public class PlacementData {
} }
/** /**
* Whether the placed item frame will have the "fixed" property set. * Whether the placed item frame will have the "fixed" property set. A fixed frame can't be destroyed or modified by
* A fixed frame can't be destroyed or modified by survival players. * survival players.
* <p> * <p>
* Only supported in 1.16 or higher! * Only supported in 1.16 or higher!
* *
@ -43,8 +44,8 @@ public class PlacementData {
} }
/** /**
* Whether the placed item frame will have the "invisible" property set. * Whether the placed item frame will have the "invisible" property set. An invisible frame won't be rendered,
* An invisible frame won't be rendered, leaving only the item/map visible. * leaving only the item/map visible.
* <p> * <p>
* Only supported in 1.16 or higher! * Only supported in 1.16 or higher!
* *
@ -54,7 +55,6 @@ public class PlacementData {
return isInvisible; return isInvisible;
} }
/** /**
* Whether the placed item frame will be a glowing one. * Whether the placed item frame will be a glowing one.
* <p> * <p>
@ -67,8 +67,8 @@ public class PlacementData {
} }
/** /**
* The <b>requested</b> size of the image. The actual size might be smaller * The <b>requested</b> size of the image. The actual size might be smaller since the plugin won't modify aspect
* since the plugin won't modify aspect ratios. * ratios.
* <p> * <p>
* Values of -1 stand for the default value of an unscaled map. * Values of -1 stand for the default value of an unscaled map.
* *

View File

@ -46,3 +46,7 @@ permissions:
default: op default: op
imagemaps.toggleVisible: imagemaps.toggleVisible:
default: op default: op
imagemaps.admin:
default: op
children:
imagemaps.*: true