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>
<groupId>net.craftcitizen</groupId>
<artifactId>imagemaps</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<name>ImageMaps</name>
<description>Render Images onto maps!</description>

View File

@ -78,7 +78,8 @@ public class ImageMap implements ConfigurationSerializable {
if (filename == null) {
if (other.filename != null)
return false;
} else if (!filename.equals(other.filename))
}
else if (!filename.equals(other.filename))
return false;
if (Double.doubleToLongBits(scale) != Double.doubleToLongBits(other.scale))
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("list", new ImageMapListCommand(plugin));
registerSubCommand("reload", new ImageMapReloadCommand(plugin));
registerSubCommand("cleanup", new ImageMapCleanupCommand(plugin));
registerSubCommand("debuginfo", new ImageMapDebugInfoCommand(plugin));
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)) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "File deleted.");
} else {
}
else {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "Failed to delete file.");
}
return null;

View File

@ -30,7 +30,8 @@ public class ImageMapDownloadCommand extends ImageMapSubCommand {
}
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;
}
@ -65,23 +66,24 @@ public class ImageMapDownloadCommand extends ImageMapSubCommand {
connection.setRequestProperty("User-Agent", "ImageMaps/0");
if (((HttpURLConnection) connection).getResponseCode() != 200) {
MessageUtil.sendMessage(getPlugin(),
sender,
MessageLevel.WARNING,
String.format("Download failed, HTTP Error code %d.", ((HttpURLConnection) connection).getResponseCode()));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING,
String.format("Download failed, HTTP Error code %d.",
((HttpURLConnection) connection).getResponseCode()));
return;
}
String mimeType = connection.getHeaderField("Content-type");
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;
}
try (InputStream str = connection.getInputStream()) {
BufferedImage image = ImageIO.read(str);
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;
}
@ -90,18 +92,23 @@ public class ImageMapDownloadCommand extends ImageMapSubCommand {
ImageIO.write(image, "PNG", outFile);
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);
}
} catch (IllegalArgumentException ex) {
}
catch (IllegalArgumentException ex) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.WARNING, "Received no data");
return;
}
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Download complete.");
} catch (MalformedURLException ex) {
}
catch (MalformedURLException ex) {
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();
}
}
@ -109,6 +116,7 @@ public class ImageMapDownloadCommand extends ImageMapSubCommand {
@Override
public void help(CommandSender sender) {
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
public void help(CommandSender sender) {
if (((ImageMaps) getPlugin()).isGlowingSupported()) {
MessageUtil.sendMessage(getPlugin(),
sender,
MessageLevel.NORMAL,
buildMessage("/imagemap place <filename> [frameInvisible] [frameFixed] [frameGlowing] [size]", " - starts image placement"));
} else if (((ImageMaps) getPlugin()).isInvisibilitySupported()) {
MessageUtil.sendMessage(getPlugin(),
sender,
MessageLevel.NORMAL,
buildMessage("/imagemap place <filename> [frameInvisible] [frameFixed] [size]", " - starts image placement"));
} 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> [frameInvisible] [frameFixed] [frameGlowing] [size]",
" - starts image placement"));
}
else if (((ImageMaps) getPlugin()).isInvisibilitySupported()) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
buildMessage("/imagemap place <filename> [frameInvisible] [frameFixed] [size]",
" - starts image placement"));
}
else {
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, buildMessage("/imagemap delete <filename>", " - deletes an image"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, 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 list [page]", " - lists all files in the images folder"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, buildMessage("/imagemap help [command]", " - shows help"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
buildMessage("/imagemap download <filename> <sourceURL>", " - downloads an image"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
buildMessage("/imagemap delete <filename>", " - deletes an image"));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
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) {

View File

@ -44,13 +44,16 @@ public class ImageMapInfoCommand extends ImageMapSubCommand {
Tuple<Integer, Integer> size = getPlugin().getImageSize(filename, null);
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);
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);
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);
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.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, String.format("Ingame Size: %dx%d", size.getKey(), size.getValue()));
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
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);
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;
int numPages = (int) Math.ceil((double) fileList.length / Utils.ELEMENTS_PER_PAGE);
MessageUtil.sendMessage(plugin, sender, MessageLevel.INFO, String.format("## Image List Page %d of %d ##", page + 1, numPages));
MessageUtil.sendMessage(plugin, sender, MessageLevel.INFO,
String.format("## Image List Page %d of %d ##", page + 1, numPages));
boolean even = false;
for (String filename : Utils.paginate(fileList, page)) {
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);
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);
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);
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);
BaseComponent message = new TextComponent(filename);
@ -65,7 +69,7 @@ public class ImageMapListCommand extends ImageMapSubCommand {
BaseComponent navigation = new TextComponent();
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)));
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()) {
isGlowing = args.length >= 5 && Boolean.parseBoolean(args[4]);
scale = args.length >= 6 ? parseScale(args[5]) : new Tuple<>(-1, -1);
} else {
}
else {
scale = args.length >= 5 ? parseScale(args[4]) : new Tuple<>(-1, -1);
}
} else {
}
else {
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.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);
MessageUtil.sendMessage(getPlugin(),
sender,
MessageLevel.NORMAL,
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, "Right click on the block, that should be the upper left corner.");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
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,
"Right click on the block, that should be the upper left corner.");
return null;
}
@ -78,22 +82,23 @@ public class ImageMapPlaceCommand extends ImageMapSubCommand {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Starts placing an image.");
if (getPlugin().isGlowingSupported()) {
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.INFO, "Usage: /imagemap place <filename> [frameInvisible] [frameFixed] [frameGlowing] [size]");
} 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> [frameInvisible] [frameFixed] [frameGlowing] [size]");
}
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.NORMAL, "Size format: XxY -> 5x2, use -1 for default");
MessageUtil.sendMessage(getPlugin(),
sender,
MessageLevel.NORMAL,
"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,
"It's recommended to avoid the size function in favor of using properly sized source images.");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"Size format: XxY -> 5x2, use -1 for default");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"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,
"It's recommended to avoid the size function in favor of using properly sized source images.");
}
private static Tuple<Integer, Integer> parseScale(String string) {
@ -108,7 +113,7 @@ public class ImageMapPlaceCommand extends ImageMapSubCommand {
@Override
protected List<String> onTabComplete(CommandSender sender, String[] args) {
if (args.length > 2 && !getPlugin().isInvisibilitySupported()
|| args.length > 4 && !getPlugin().isGlowingSupported()) {
|| args.length > 4 && !getPlugin().isGlowingSupported()) {
return Collections.emptyList();
}

View File

@ -38,15 +38,18 @@ public class ImageMapReloadCommand extends ImageMapSubCommand {
if (getPlugin().reloadImage(filename))
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL, "Image reloaded.");
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;
}
@Override
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, "Avoid resolution changes, since they won't be scaled.");
MessageUtil.sendMessage(getPlugin(), sender, MessageLevel.NORMAL,
"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>");
}

View File

@ -30,7 +30,8 @@ public class ImageMapRenderer extends MapRenderer {
}
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;
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);
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();
at.scale(scale, scale);
AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
@ -58,20 +60,8 @@ public class ImageMapRenderer extends MapRenderer {
@Override
public void render(MapView view, MapCanvas canvas, Player player) {
if (image != null && first) {
new LambdaRunnable(() -> {
@SuppressWarnings("deprecation")
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);
new LambdaRunnable(() -> canvas.drawImage(0, 0, image)).runTaskLater(plugin, System.nanoTime() % 60);
// spread out pseudo randomly in a very naive way
first = false;
}
}

View File

@ -69,9 +69,11 @@ public class ImageMaps extends JavaPlugin implements Listener {
@Override
public void onEnable() {
BaseComponent prefix = new TextComponent(
new ComponentBuilder("[").color(ChatColor.GRAY).append("ImageMaps").color(ChatColor.AQUA).append("]").color(ChatColor.GRAY).create());
MessageUtil.registerPlugin(this, prefix, ChatColor.GRAY, ChatColor.YELLOW, ChatColor.RED, ChatColor.DARK_RED, ChatColor.DARK_AQUA);
BaseComponent prefix = new TextComponent(new ComponentBuilder("[").color(ChatColor.GRAY).append("ImageMaps")
.color(ChatColor.AQUA).append("]")
.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())
new File(getDataFolder(), IMAGES_DIR).mkdirs();
@ -102,8 +104,8 @@ public class ImageMaps extends JavaPlugin implements Listener {
if (!isInvisibilitySupported())
return;
if (event.getRightClicked().getType() != EntityType.ITEM_FRAME &&
(!isGlowingSupported() || event.getRightClicked().getType() != EntityType.GLOW_ITEM_FRAME))
if (event.getRightClicked().getType() != EntityType.ITEM_FRAME
&& (!isGlowingSupported() || event.getRightClicked().getType() != EntityType.GLOW_ITEM_FRAME))
return;
ItemFrame frame = (ItemFrame) event.getRightClicked();
@ -116,12 +118,15 @@ public class ImageMaps extends JavaPlugin implements Listener {
if (p.hasPermission("imagemaps.toggleFixed")) {
event.setCancelled(true);
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);
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(() -> {
try {
config.save(new File(getDataFolder(), MAPS_YML));
} catch (IOException e) {
}
catch (IOException e) {
e.printStackTrace();
}
});
@ -190,30 +196,46 @@ public class ImageMaps extends JavaPlugin implements Listener {
@SuppressWarnings("deprecation")
MapView map = Bukkit.getMap(id);
BufferedImage image = getImage(imageMap.getFilename());
maps.put(imageMap, id);
if (image == null) {
getLogger().warning(() -> "Image file " + imageMap.getFilename() + " not found. Removing map!");
getLogger().warning(() -> "Image file " + imageMap.getFilename() + " not found!");
return;
}
if (map == null) {
getLogger().warning(() -> "Map " + id + " referenced but does not exist. Removing map!");
getLogger().warning(() -> "Map " + id + " referenced but does not exist!");
return;
}
if (isSetTrackingSupported())
map.setTrackingPosition(false);
map.getRenderers().forEach(map::removeRenderer);
map.addRenderer(new ImageMapRenderer(this, image, imageMap.getX(), imageMap.getY(), imageMap.getScale()));
maps.put(imageMap, id);
map.addRenderer(new ImageMapRenderer(this, image, imageMap.getX(), imageMap.getY(),
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) {
getLogger().info("Converting maps from Version <1.0");
try {
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!");
e.printStackTrace();
}
@ -244,6 +266,7 @@ public class ImageMaps extends JavaPlugin implements Listener {
return file.exists() && getImage(filename) != null;
}
// TODO stop returning null, begin throwing exception
public BufferedImage getImage(String filename) {
if (filename.contains("/") || filename.contains("\\") || filename.contains(":")) {
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 {
image = ImageIO.read(file);
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);
}
if (image == null)
getLogger().log(Level.WARNING, () -> String.format("Failed to read file as image %s.", file.getName()));
return image;
}
@ -290,22 +317,27 @@ public class ImageMaps extends JavaPlugin implements Listener {
switch (result) {
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;
case INVALID_DIRECTION:
MessageUtil.sendMessage(this, player, MessageLevel.WARNING, "Couldn't calculate how to place the map.");
break;
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;
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;
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;
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;
case SUCCESS:
break;
@ -342,11 +374,14 @@ public class ImageMaps extends JavaPlugin implements Listener {
return PlacementResult.INSUFFICIENT_WALL;
if (frameBlock.getType().isSolid())
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;
}
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);
if (event.isCancelled())
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 y = 0; y < size.getValue(); y++) {
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.setItem(getMapItem(image, x, y, data));
frame.setRotation(facingToRotation(heightDirection, widthDirection));
@ -414,8 +452,9 @@ public class ImageMaps extends JavaPlugin implements Listener {
return false;
}
maps.entrySet().stream().filter(a -> a.getKey().getFilename().equalsIgnoreCase(filename)).map(a -> Bukkit.getMap(a.getValue()))
.flatMap(a -> a.getRenderers().stream()).filter(ImageMapRenderer.class::isInstance).forEach(a -> ((ImageMapRenderer) a).recalculateInput(image));
maps.entrySet().stream().filter(a -> a.getKey().getFilename().equalsIgnoreCase(filename))
.map(a -> Bukkit.getMap(a.getValue())).flatMap(a -> a.getRenderers().stream())
.filter(ImageMapRenderer.class::isInstance).forEach(a -> ((ImageMapRenderer) a).recalculateInput(image));
return true;
}

View File

@ -23,7 +23,8 @@ public class ImagePlaceEvent extends Event implements Cancellable {
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.block = block;
this.widthDirection = widthDirection;

View File

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

View File

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