diff --git a/README.md b/README.md index 73101a3..314b19a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ImageOnMap ========== -Repo for ImageOnMap, a bukkit plugin +Repo for ImageOnMap, a bukkit plugin. ## Features @@ -14,7 +14,7 @@ ImageOnMap allows you to load a picture from the Internet to a Minecraft map. - Your image will be centered. - You can put your map in an item frame. -This plugin is a free software lisensed under the GNU General Public License (version 3 or above). The source code is published on GitHub. You can also get unstable development builds here. +This plugin is a free software licenced under the GNU General Public License (version 3 or above). You can also get unstable development builds here. ## Quick guide @@ -34,7 +34,7 @@ Renders an image and gives a map to the player with it. - The link must be complete, do not forget that the chat limit is 240 characters. - You can use an URL shortener like tinyURL or bitly. - If you want a picture in one map, type resize after the link. -- Permission: `imageonmap.userender` +- Permission: `imageonmap.new` (or `imageonmap.userender`—legacy, but will be kept in the plugin). ### `/maps` @@ -46,6 +46,7 @@ Opens a GUI to see, retrieve and manage the user's maps. - A book is displayed too to see some usage statistics (maps created, quotas). - An user can retrieve a map by left-clicking it, or manage it by right-clicking. - Maps can be renamed (for organization), deleted (but they won't render in game anymore!), or partially retrieved (for posters maps containing more than one map). +- Permission: `imageonmap.list`, plus `imageonmap.get`, `imageonmap.rename` and `imageonmap.delete` for actions into the GUI. ### `/maptool ` @@ -56,7 +57,19 @@ Main command to manage the maps. The less used in everyday usage, too. - `/maptool new` is an alias of `/tomap`. - `/maptool explore` is an alias of `/maps`. - `/maptool migrate` migrates the old maps when you upgrade from IoM <= 2.7 to IoM 3.0. You HAVE TO execute this command to retrieve all maps when you do such a migration. +- Permissions: + - `imageonmap.new` for `/maptool new`; + - `imageonmap.list` for both `/maptool list` and `/maptool explore`; + - `imageonmap.get` for `/maptool get`; + - `imageonmap.delete` for `/maptool delete`; + - `imageonmap.administrative` for `/maptool migrate`. +### About the permissions + +All permissions are by default granted to everyone, with the exception of `imageonmap.administrative`. We believe that in most cases, servers administrators want to give the availability to create images on maps to every player. +Negate a permission using a plugin manager to remove it, if you want to restrict this possibility to a set of users. + +You can grant `imageonmap.*` to users, as this permission is a shortcut for all _user_ permissions (excluding `imageonmap.administrative`). ## Configuration @@ -77,7 +90,9 @@ map-global-limit: 0 map-player-limit: 0 ``` -## New features in the 3.0 version +## Changelog + +### 3.0 The 3.0 release is a complete rewrite of the original ImageOnMap plugin, now based on zLib, which adds many feature and fixes many bugs. @@ -94,8 +109,12 @@ You will find amongst the new features: - Asynchronous maps rendering (your server won't freeze anymore when rendering big maps, and you can queue multiple map renderings !) - UUID management (which requires to run `/maptool migrate`) +### 3.1 + +- Fixed permissions support by adding a full set of permissions for every action of the plugin. + ## Data collection -We use metrics to collect basic informations about the usage of this plugin. This can be disabled by setting "collect-data" to false in config.yml. +We use metrics to collect basic information about the usage of this plugin. This can be disabled by setting `collect-data` to false in `config.yml`. diff --git a/pom.xml b/pom.xml index f013a4c..df341f9 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 fr.moribus ImageOnMap - 3.0 + 3.1 jar diff --git a/src/main/java/fr/moribus/imageonmap/Permissions.java b/src/main/java/fr/moribus/imageonmap/Permissions.java new file mode 100644 index 0000000..abaa110 --- /dev/null +++ b/src/main/java/fr/moribus/imageonmap/Permissions.java @@ -0,0 +1,75 @@ +/* + * Copyright or © or Copr. AmauryCarrade (2015) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package fr.moribus.imageonmap; + + +import org.bukkit.permissions.Permissible; + +public enum Permissions +{ + NEW("imageonmap.new", "imageonmap.userender"), + LIST("imageonmap.list"), + GET("imageonmap.get"), + RENAME("imageonmap.rename"), + DELETE("imageonmap.delete"), + ADMINISTRATIVE("imageonmap.administrative") + + ; + + + private final String permission; + private final String[] aliases; + + Permissions(String permission, String... aliases) + { + this.permission = permission; + this.aliases = aliases; + } + + /** + * Checks if this permission is granted to the given permissible. + * + * @param permissible The permissible to check. + * @return {@code true} if this permission is granted to the permissible. + */ + public boolean grantedTo(Permissible permissible) + { + if (permissible.hasPermission(permission)) + return true; + + for (String alias : aliases) + if (permissible.hasPermission(alias)) + return true; + + return false; + } +} diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java index 9b3e1b0..12ac5c9 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java @@ -18,6 +18,7 @@ package fr.moribus.imageonmap.commands.maptool; +import fr.moribus.imageonmap.Permissions; import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.MapManager; @@ -29,6 +30,7 @@ import fr.zcraft.zlib.components.i18n.I; import fr.zcraft.zlib.components.rawtext.RawText; import fr.zcraft.zlib.tools.PluginLogger; import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.util.List; @@ -83,4 +85,10 @@ public class DeleteCommand extends IoMCommand return null; } + + @Override + public boolean canExecute(CommandSender sender) + { + return Permissions.DELETE.grantedTo(sender); + } } diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java index 8a72e15..34f0ad2 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java @@ -19,11 +19,13 @@ package fr.moribus.imageonmap.commands.maptool; +import fr.moribus.imageonmap.Permissions; import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.gui.MapListGui; import fr.zcraft.zlib.components.commands.CommandException; import fr.zcraft.zlib.components.commands.CommandInfo; import fr.zcraft.zlib.components.gui.Gui; +import org.bukkit.command.CommandSender; @CommandInfo (name = "explore") @@ -32,6 +34,12 @@ public class ExploreCommand extends IoMCommand @Override protected void run() throws CommandException { - Gui.open(playerSender(), new MapListGui()); + Gui.open(playerSender(), new MapListGui()); + } + + @Override + public boolean canExecute(CommandSender sender) + { + return Permissions.LIST.grantedTo(sender); } } diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java index 51c47ff..6480fac 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java @@ -18,10 +18,12 @@ package fr.moribus.imageonmap.commands.maptool; +import fr.moribus.imageonmap.Permissions; import fr.moribus.imageonmap.commands.IoMCommand; import fr.zcraft.zlib.components.commands.CommandException; import fr.zcraft.zlib.components.commands.CommandInfo; import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.util.List; @@ -47,4 +49,10 @@ public class GetCommand extends IoMCommand return getMatchingMapNames(playerSender(), args[0]); return null; } + + @Override + public boolean canExecute(CommandSender sender) + { + return Permissions.GET.grantedTo(sender); + } } diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java index 7bd1b72..00adb00 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java @@ -18,11 +18,13 @@ package fr.moribus.imageonmap.commands.maptool; +import fr.moribus.imageonmap.Permissions; import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.ui.MapItemManager; import fr.zcraft.zlib.components.commands.CommandException; import fr.zcraft.zlib.components.commands.CommandInfo; import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @CommandInfo (name = "getremaining", aliases = {"getrest"}) @@ -50,4 +52,10 @@ public class GetRemainingCommand extends IoMCommand info(I.tn("There is {0} map remaining.", "There are {0} maps remaining.", MapItemManager.getCacheSize(player))); } } + + @Override + public boolean canExecute(CommandSender sender) + { + return Permissions.NEW.grantedTo(sender) || Permissions.GET.grantedTo(sender); + } } diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java index c19b895..1019c7b 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java @@ -18,6 +18,7 @@ package fr.moribus.imageonmap.commands.maptool; +import fr.moribus.imageonmap.Permissions; import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.MapManager; @@ -31,6 +32,7 @@ import fr.zcraft.zlib.tools.items.ItemStackBuilder; import fr.zcraft.zlib.tools.text.RawMessage; import org.bukkit.ChatColor; import org.bukkit.Material; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.util.List; @@ -81,4 +83,10 @@ public class ListCommand extends IoMCommand .item() ); } + + @Override + public boolean canExecute(CommandSender sender) + { + return Permissions.LIST.grantedTo(sender); + } } diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java index 9f4fdcc..e1b7b98 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java @@ -18,6 +18,7 @@ package fr.moribus.imageonmap.commands.maptool; +import fr.moribus.imageonmap.Permissions; import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.migration.MigratorExecutor; import fr.zcraft.zlib.components.commands.CommandException; @@ -45,6 +46,6 @@ public class MigrateCommand extends IoMCommand @Override public boolean canExecute(CommandSender sender) { - return sender.isOp(); + return sender.isOp() || Permissions.ADMINISTRATIVE.grantedTo(sender); } } diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java index c478f8d..56cf819 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java @@ -18,14 +18,17 @@ package fr.moribus.imageonmap.commands.maptool; +import fr.moribus.imageonmap.Permissions; import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.image.ImageRendererExecutor; +import fr.moribus.imageonmap.image.ImageUtils; import fr.moribus.imageonmap.map.ImageMap; import fr.zcraft.zlib.components.commands.CommandException; import fr.zcraft.zlib.components.commands.CommandInfo; import fr.zcraft.zlib.components.i18n.I; import fr.zcraft.zlib.components.worker.WorkerCallback; import fr.zcraft.zlib.tools.PluginLogger; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.net.MalformedURLException; @@ -38,8 +41,9 @@ public class NewCommand extends IoMCommand protected void run() throws CommandException { final Player player = playerSender(); - boolean scaling = false; + ImageUtils.ScalingType scaling = ImageUtils.ScalingType.NONE; URL url; + int width = 0, height = 0; if(args.length < 1) throwInvalidArgument(I.t("You must give an URL to take the image from.")); @@ -55,11 +59,21 @@ public class NewCommand extends IoMCommand if(args.length >= 2) { - if(args[1].equals("resize")) scaling = true; + if(args.length >= 4) { + width = Integer.parseInt(args[2]); + height = Integer.parseInt(args[3]); + } + + switch(args[1]) { + case "resize": scaling = ImageUtils.ScalingType.CONTAINED; break; + case "resize-stretched": scaling = ImageUtils.ScalingType.STRETCHED; break; + case "resize-covered": scaling = ImageUtils.ScalingType.COVERED; break; + default: throwInvalidArgument(I.t("Invalid Stretching mode.")); break; + } } info(I.t("Rendering...")); - ImageRendererExecutor.Render(url, scaling, player.getUniqueId(), new WorkerCallback() + ImageRendererExecutor.render(url, scaling, player.getUniqueId(), width, height, new WorkerCallback() { @Override public void finished(ImageMap result) @@ -84,4 +98,10 @@ public class NewCommand extends IoMCommand } }); } + + @Override + public boolean canExecute(CommandSender sender) + { + return Permissions.NEW.grantedTo(sender); + } } diff --git a/src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java b/src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java index 83c5890..706b627 100644 --- a/src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java +++ b/src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java @@ -18,6 +18,7 @@ package fr.moribus.imageonmap.gui; +import fr.moribus.imageonmap.Permissions; import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.MapManager; import fr.moribus.imageonmap.map.MapManagerException; @@ -170,6 +171,14 @@ public class ConfirmDeleteMapGui extends ActionGui @GuiAction ("delete") protected void delete() { + // Does the player still have the permission to delete a map? + if (!Permissions.DELETE.grantedTo(getPlayer())) + { + I.sendT(getPlayer(), "{ce}You are no longer allowed to do that."); + close(); + return; + } + MapManager.clear(getPlayer().getInventory(), mapToDelete); try diff --git a/src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java b/src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java index 57b9e1d..f7e48ce 100644 --- a/src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java +++ b/src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java @@ -18,6 +18,7 @@ package fr.moribus.imageonmap.gui; +import fr.moribus.imageonmap.Permissions; import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.PosterMap; import fr.moribus.imageonmap.map.SingleMap; @@ -46,43 +47,46 @@ public class MapDetailGui extends ExplorerGui @Override protected ItemStack getViewItem(int x, int y) { - Material partMaterial = Material.PAPER; - if((y % 2 == 0 && x % 2 == 0) || (y % 2 == 1 && x % 2 == 1)) - partMaterial = Material.EMPTY_MAP; + final Material partMaterial = y % 2 == x % 2 ? Material.EMPTY_MAP : Material.PAPER; - return new ItemStackBuilder(partMaterial) + final ItemStackBuilder builder = new ItemStackBuilder(partMaterial) .title(I.t(getPlayerLocale(), "{green}Map part")) .lore(I.t(getPlayerLocale(), "{gray}Row: {white}{0}", y + 1)) - .lore(I.t(getPlayerLocale(), "{gray}Column: {white}{0}", x + 1)) - .loreLine() - .lore(I.t(getPlayerLocale(), "{gray}» {white}Click{gray} to get only this part")) - .item(); + .lore(I.t(getPlayerLocale(), "{gray}Column: {white}{0}", x + 1)); + + if (Permissions.GET.grantedTo(getPlayer())) + builder.loreLine().lore(I.t(getPlayerLocale(), "{gray}» {white}Click{gray} to get only this part")); + + return builder.item(); } @Override protected ItemStack getViewItem(Short mapId) { - int index = ((PosterMap) map).getIndex(mapId); - Material partMaterial = Material.PAPER; - if(index % 2 == 0) - partMaterial = Material.EMPTY_MAP; + final int index = ((PosterMap) map).getIndex(mapId); + final Material partMaterial = index % 2 == 0 ? Material.EMPTY_MAP : Material.PAPER; - return new ItemStackBuilder(partMaterial) + final ItemStackBuilder builder = new ItemStackBuilder(partMaterial) .title(I.t(getPlayerLocale(), "{green}Map part")) - .lore(I.t(getPlayerLocale(), "{gray}Part: {white}{0}", index + 1)) - .loreLine() - .lore(I.t(getPlayerLocale(), "{gray}» {white}Click{gray} to get only this part")) - .item(); + .lore(I.t(getPlayerLocale(), "{gray}Part: {white}{0}", index + 1)); + + if (Permissions.GET.grantedTo(getPlayer())) + builder.loreLine().lore(I.t(getPlayerLocale(), "{gray}» {white}Click{gray} to get only this part")); + + return builder.item(); } @Override protected ItemStack getPickedUpItem(int x, int y) { - if(map instanceof SingleMap) + if (!Permissions.GET.grantedTo(getPlayer())) + return null; + + if (map instanceof SingleMap) { return MapItemManager.createMapItem((SingleMap)map); } - else if(map instanceof PosterMap) + else if (map instanceof PosterMap) { return MapItemManager.createMapItem((PosterMap)map, x, y); } @@ -93,14 +97,17 @@ public class MapDetailGui extends ExplorerGui @Override protected ItemStack getPickedUpItem(Short mapId) { - PosterMap poster = (PosterMap) map; + if (!Permissions.GET.grantedTo(getPlayer())) + return null; + + final PosterMap poster = (PosterMap) map; return MapItemManager.createMapItem(poster, poster.getIndex(mapId)); } @Override protected ItemStack getEmptyViewItem() { - if(map instanceof SingleMap) + if (map instanceof SingleMap) { return getViewItem(0, 0); } @@ -114,7 +121,7 @@ public class MapDetailGui extends ExplorerGui setTitle(I.t(getPlayerLocale(), "Your maps » {black}{0}", map.getName())); setKeepHorizontalScrollingSpace(true); - if(map instanceof PosterMap) + if (map instanceof PosterMap) { PosterMap poster = (PosterMap) map; if(poster.hasColumnData()) @@ -131,25 +138,41 @@ public class MapDetailGui extends ExplorerGui setDataShape(1,1); } + final boolean canRename = Permissions.RENAME.grantedTo(getPlayer()); + final boolean canDelete = Permissions.DELETE.grantedTo(getPlayer()); - action("rename", getSize() - 7, new ItemStackBuilder(Material.BOOK_AND_QUILL) - .title(I.t(getPlayerLocale(), "{blue}Rename this image")) - .longLore(I.t(getPlayerLocale(), "{gray}Click here to rename this image; this is used for your own organization.")) - ); + int renameSlot = getSize() - 7; + int deleteSlot = getSize() - 6; - action("delete", getSize() - 6, new ItemStackBuilder(Material.BARRIER) - .title(I.t(getPlayerLocale(), "{red}Delete this image")) - .longLore(I.t(getPlayerLocale(), "{gray}Deletes this map {white}forever{gray}. This action cannot be undone!")) - .loreLine() - .longLore(I.t(getPlayerLocale(), "{gray}You will be asked to confirm your choice if you click here.")) - ); + if (!canRename) + deleteSlot--; + + if (canRename) + { + action("rename", renameSlot, new ItemStackBuilder(Material.BOOK_AND_QUILL) + .title(I.t(getPlayerLocale(), "{blue}Rename this image")) + .longLore(I.t(getPlayerLocale(), "{gray}Click here to rename this image; this is used for your own organization.")) + ); + } + + if (canDelete) + { + action("delete", deleteSlot, new ItemStackBuilder(Material.BARRIER) + .title(I.t(getPlayerLocale(), "{red}Delete this image")) + .longLore(I.t(getPlayerLocale(), "{gray}Deletes this map {white}forever{gray}. This action cannot be undone!")) + .loreLine() + .longLore(I.t(getPlayerLocale(), "{gray}You will be asked to confirm your choice if you click here.")) + ); + } // To keep the controls centered, the back button is shifted to the right when the // arrow isn't displayed, so when the map fit on the grid without sliders. int backSlot = getSize() - 4; - if(map instanceof PosterMap && ((PosterMap) map).getColumnCount() <= INVENTORY_ROW_SIZE) + if (!canRename && !canDelete) + backSlot = getSize() - 5; + else if (map instanceof PosterMap && ((PosterMap) map).getColumnCount() <= INVENTORY_ROW_SIZE) backSlot++; action("back", backSlot, new ItemStackBuilder(Material.EMERALD) @@ -162,11 +185,24 @@ public class MapDetailGui extends ExplorerGui @GuiAction ("rename") public void rename() { + if (!Permissions.RENAME.grantedTo(getPlayer())) + { + I.sendT(getPlayer(), "{ce}You are no longer allowed to do that."); + update(); + return; + } + PromptGui.prompt(getPlayer(), new Callback() { @Override public void call(String newName) { + if (!Permissions.RENAME.grantedTo(getPlayer())) + { + I.sendT(getPlayer(), "{ce}You are no longer allowed to do that."); + return; + } + if (newName == null || newName.isEmpty()) { I.sendT(getPlayer(), "{ce}Map names can't be empty."); @@ -182,6 +218,13 @@ public class MapDetailGui extends ExplorerGui @GuiAction ("delete") public void delete() { + if (!Permissions.DELETE.grantedTo(getPlayer())) + { + I.sendT(getPlayer(), "{ce}You are no longer allowed to do that."); + update(); + return; + } + Gui.open(getPlayer(), new ConfirmDeleteMapGui(map), this); } diff --git a/src/main/java/fr/moribus/imageonmap/gui/MapListGui.java b/src/main/java/fr/moribus/imageonmap/gui/MapListGui.java index c8e50ea..51dc27d 100644 --- a/src/main/java/fr/moribus/imageonmap/gui/MapListGui.java +++ b/src/main/java/fr/moribus/imageonmap/gui/MapListGui.java @@ -17,6 +17,7 @@ */ package fr.moribus.imageonmap.gui; +import fr.moribus.imageonmap.Permissions; import fr.moribus.imageonmap.PluginConfiguration; import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.MapManager; @@ -57,7 +58,7 @@ public class MapListGui extends ExplorerGui mapDescription = I.t(getPlayerLocale(), "{white}Poster map ({0} parts)", poster.getMapCount()); } } - return new ItemStackBuilder(Material.MAP) + ItemStackBuilder builder = new ItemStackBuilder(Material.MAP) /// Displayed title of a map on the list GUI .title(I.t(getPlayerLocale(), "{green}{bold}{0}", map.getName())) @@ -65,20 +66,28 @@ public class MapListGui extends ExplorerGui .loreLine() /// Map ID displayed in the tooltip of a map on the list GUI .lore(I.t(getPlayerLocale(), "{gray}Map ID: {0}", map.getId())) - .loreLine() - .lore(I.t(getPlayerLocale(), "{gray}» {white}Left-click{gray} to get this map")) - .lore(I.t(getPlayerLocale(), "{gray}» {white}Right-click{gray} for details and options")) + .loreLine(); - .item(); + if (Permissions.GET.grantedTo(getPlayer())) + builder.lore(I.t(getPlayerLocale(), "{gray}» {white}Left-click{gray} to get this map")); + + builder.lore(I.t(getPlayerLocale(), "{gray}» {white}Right-click{gray} for details and options")); + + return builder.item(); } @Override protected ItemStack getEmptyViewItem() { - return new ItemStackBuilder(Material.BARRIER) - .title(I.t(getPlayerLocale(), "{red}You don't have any map.")) - .longLore(I.t(getPlayerLocale(), "{gray}Get started by creating a new one using {white}/tomap [resize]{gray}!")) - .item(); + ItemStackBuilder builder = new ItemStackBuilder(Material.BARRIER) + .title(I.t(getPlayerLocale(), "{red}You don't have any map.")); + + if (Permissions.NEW.grantedTo(getPlayer())) + builder.longLore(I.t(getPlayerLocale(), "{gray}Get started by creating a new one using {white}/tomap [resize]{gray}!")); + else + builder.longLore(I.t(getPlayerLocale(), "{gray}Unfortunately, you are not allowed to create one.")); + + return builder.item(); } @Override @@ -90,6 +99,9 @@ public class MapListGui extends ExplorerGui @Override protected ItemStack getPickedUpItem(ImageMap map) { + if (!Permissions.GET.grantedTo(getPlayer())) + return null; + if (map instanceof SingleMap) { return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName()); @@ -114,6 +126,7 @@ public class MapListGui extends ExplorerGui { ImageMap[] maps = MapManager.getMaps(getPlayer().getUniqueId()); setData(maps); + /// The maps list GUI title setTitle(I.t(getPlayerLocale(), "{black}Your maps {reset}({0})", maps.length)); diff --git a/src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java b/src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java index 390ccdd..2b47a8c 100644 --- a/src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java +++ b/src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java @@ -27,7 +27,6 @@ import fr.zcraft.zlib.components.worker.WorkerCallback; import fr.zcraft.zlib.components.worker.WorkerRunnable; import javax.imageio.ImageIO; -import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; @@ -42,7 +41,7 @@ import java.util.concurrent.Future; @WorkerAttributes (name = "Image Renderer", queriesMainThread = true) public class ImageRendererExecutor extends Worker { - static public void Render(final URL url, final boolean scaling, final UUID playerUUID, WorkerCallback callback) + static public void render(final URL url, final ImageUtils.ScalingType scaling, final UUID playerUUID, final int width, final int height, WorkerCallback callback) { submitQuery(new WorkerRunnable() { @@ -65,16 +64,20 @@ public class ImageRendererExecutor extends Worker if (image == null) throw new IOException(I.t("The given URL is not a valid image")); - if (scaling) return RenderSingle(image, playerUUID); - else return RenderPoster(image, playerUUID); + if(scaling != ImageUtils.ScalingType.NONE && height <= 1 && width <= 1) { + return renderSingle(scaling.resize(image, ImageMap.WIDTH, ImageMap.HEIGHT), playerUUID); + } + + final BufferedImage resizedImage = scaling.resize(image, ImageMap.WIDTH * width, ImageMap.HEIGHT * height); + return renderPoster(resizedImage, playerUUID); } }, callback); } - - static private ImageMap RenderSingle(final BufferedImage image, final UUID playerUUID) throws Throwable + + static private ImageMap renderSingle(final BufferedImage image, final UUID playerUUID) throws Throwable { MapManager.checkMapLimit(1, playerUUID); - Future futureMapID = submitToMainThread(new Callable() + final Future futureMapID = submitToMainThread(new Callable() { @Override public Short call() throws Exception @@ -82,27 +85,24 @@ public class ImageRendererExecutor extends Worker return MapManager.getNewMapsIds(1)[0]; } }); - - final BufferedImage finalImage = ResizeImage(image, ImageMap.WIDTH, ImageMap.HEIGHT); - + final short mapID = futureMapID.get(); - ImageIOExecutor.saveImage(mapID, finalImage); + ImageIOExecutor.saveImage(mapID, image); submitToMainThread(new Callable() { @Override public Void call() throws Exception { - Renderer.installRenderer(finalImage, mapID); + Renderer.installRenderer(image, mapID); return null; } - }); return MapManager.createMap(playerUUID, mapID); } - static private ImageMap RenderPoster(final BufferedImage image, final UUID playerUUID) throws Throwable + static private ImageMap renderPoster(final BufferedImage image, final UUID playerUUID) throws Throwable { final PosterImage poster = new PosterImage(image); final int mapCount = poster.getImagesCount(); @@ -136,33 +136,4 @@ public class ImageRendererExecutor extends Worker return MapManager.createMap(poster, playerUUID, mapsIDs); } - - static private BufferedImage ResizeImage(BufferedImage source, int destinationW, int destinationH) - { - float ratioW = (float)destinationW / (float)source.getWidth(); - float ratioH = (float)destinationH / (float)source.getHeight(); - int finalW, finalH; - - if(ratioW < ratioH) - { - finalW = destinationW; - finalH = (int)(source.getHeight() * ratioW); - } - else - { - finalW = (int)(source.getWidth() * ratioH); - finalH = destinationH; - } - - int x, y; - x = (destinationW - finalW) / 2; - y = (destinationH - finalH) / 2; - - BufferedImage newImage = new BufferedImage(destinationW, destinationH, BufferedImage.TYPE_INT_ARGB); - - Graphics graphics = newImage.getGraphics(); - graphics.drawImage(source, x, y, finalW, finalH, null); - graphics.dispose(); - return newImage; - } } diff --git a/src/main/java/fr/moribus/imageonmap/image/ImageUtils.java b/src/main/java/fr/moribus/imageonmap/image/ImageUtils.java new file mode 100644 index 0000000..0dac647 --- /dev/null +++ b/src/main/java/fr/moribus/imageonmap/image/ImageUtils.java @@ -0,0 +1,97 @@ +package fr.moribus.imageonmap.image; + +import java.awt.*; +import java.awt.image.BufferedImage; + +/** + * Various image-related utilities + */ +public class ImageUtils { + + public enum ScalingType { + NONE, + CONTAINED, + COVERED, + STRETCHED, + ; + + public BufferedImage resize(BufferedImage source, int destinationW, int destinationH) { + switch(this) { + case CONTAINED: return ImageUtils.resize(source, destinationW, destinationH, false); + case COVERED: return ImageUtils.resize(source, destinationW, destinationH, true); + case STRETCHED: return resizeStretched(source, destinationW, destinationH); + default: return source; + } + } + } + + /** + * Generates a resized buffer of the given source + * @param source + * @param destinationW + * @param destinationH + * @return + */ + static private BufferedImage resize(BufferedImage source, int destinationW, int destinationH, boolean covered) + { + float ratioW = (float)destinationW / (float)source.getWidth(); + float ratioH = (float)destinationH / (float)source.getHeight(); + int finalW, finalH; + int x, y; + + if(covered ? ratioW > ratioH : ratioW < ratioH) + { + finalW = destinationW; + finalH = (int)(source.getHeight() * ratioW); + } + else + { + finalW = (int)(source.getWidth() * ratioH); + finalH = destinationH; + } + + x = (destinationW - finalW) / 2; + y = (destinationH - finalH) / 2; + + return drawImage(source, + destinationW, destinationH, + x, y, finalW, finalH); + } + + /** + * + * @param source + * @param destinationW + * @param destinationH + * @return + */ + static private BufferedImage resizeStretched(BufferedImage source, int destinationW, int destinationH) { + return drawImage(source, + destinationW, destinationH, + 0, 0, destinationW, destinationH); + } + + /** + * Draws the source image on a new buffer, and returns it. + * The source buffer can be drawn at any size and position in the new buffer. + * @param source The source buffer to draw + * @param bufferW The width of the new buffer + * @param bufferH The height of the new buffer + * @param posX The X position of the source buffer + * @param posY The Y position of the source buffer + * @param sourceW The width of the source buffer + * @param sourceH The height of the source buffer + * @return The new buffer, with the source buffer drawn on it + */ + static private BufferedImage drawImage(BufferedImage source, + int bufferW, int bufferH, + int posX, int posY, + int sourceW, int sourceH) { + BufferedImage newImage = new BufferedImage(bufferW, bufferH, BufferedImage.TYPE_INT_ARGB); + + Graphics graphics = newImage.getGraphics(); + graphics.drawImage(source, posX, posY, sourceW, sourceH, null); + graphics.dispose(); + return newImage; + } +} diff --git a/src/main/resources/i18n/fr_FR.po b/src/main/resources/i18n/fr_FR.po index b4ab74b..2bd5bcd 100644 --- a/src/main/resources/i18n/fr_FR.po +++ b/src/main/resources/i18n/fr_FR.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-07-10 00:59+0200\n" -"PO-Revision-Date: 2016-07-19 16:15+0200\n" +"POT-Creation-Date: 2018-01-24 01:08+0100\n" +"PO-Revision-Date: 2018-01-24 01:45+0100\n" "Last-Translator: Amaury Carrade\n" "Language-Team: \n" "Language: fr_FR\n" @@ -16,329 +16,74 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 1.8.8\n" +"X-Generator: Poedit 2.0.6\n" -#: src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java:40 -msgid "You need to give a map name." -msgstr "Vous devez donner le nom d'une carte." +#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:177 +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:190 +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:202 +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:223 +msgid "{ce}You are no longer allowed to do that." +msgstr "{ce}Vous n'avez plus le droit de faire cela." -#: src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java:57 -#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteNoConfirmCommand.java:51 -msgid "This map does not exist." -msgstr "Cette carte n'existe pas." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteConfirmCommand.java:39 -msgid "You are going to delete" -msgstr "Vous êtes sur le point de supprimer" - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteConfirmCommand.java:42 -msgid "Are you sure ? " -msgstr "Êtes-vous sûr(e) ?" - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteConfirmCommand.java:44 -msgid "[Confirm]" -msgstr "[Confirmer]" - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteConfirmCommand.java:46 -msgid "{red}This map will be deleted {bold}forever{red}!" -msgstr "{red}Cette carte sera supprimée {bold}définitivement{red} !" - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteNoConfirmCommand.java:46 -msgid "Map successfully deleted." -msgstr "Carte supprimée avec succès." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java:38 -msgid "The requested map was too big to fit in your inventory." -msgstr "" -"La carte demandée est trop grande et ne rentre pas dans votre inventaire." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java:39 -#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:71 -msgid "Use '/maptool getremaining' to get the remaining maps." -msgstr "Utilisez “/maptool getremaining” pour récupérer les cartes restantes." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java:38 -msgid "You have no remaining map." -msgstr "Vous n'avez aucune carte restante." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java:46 -msgid "" -"Your inventory is full! Make some space before requesting the remaining maps." -msgstr "" -"Votre inventaire est plein ! Faites de la place avant de demander les cartes " -"supplémentaires." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java:50 -#, java-format -msgid "There is {0} map remaining." -msgid_plural "There are {0} maps remaining." -msgstr[0] "Il y a {0} carte restante." -msgstr[1] "Il y a {0} cartes restantes." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:49 -msgid "No map found." -msgstr "Aucune carte trouvée." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:53 -msgid "{white}{bold}{0} map found." -msgid_plural "{white}{bold}{0} maps found." -msgstr[0] "{white}{bold}{0} carte trouvée." -msgstr[1] "{white}{bold}{0} cartes trouvées." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:79 -msgid "{white}Click{gray} to get this map" -msgstr "{white}Cliquez{gray} pour obtenir cette carte" - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java:36 -msgid "A migration process is already running. Check console for details." -msgstr "" -"Un processus de migration est déjà en cours. Consultez la console pour plus " -"de détails." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java:40 -msgid "Migration started. See console for details." -msgstr "Migration démarrée. Consultez la console pour plus de détails." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:44 -msgid "You must give an URL to take the image from." -msgstr "Vous devez fournir l'URL de l'image." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:52 -msgid "Invalid URL." -msgstr "URL invalide." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:61 -msgid "Rendering..." -msgstr "Rendu en cours..." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:67 -msgid "{cst}Rendering finished!" -msgstr "{cst}Rendu achevé !" - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:70 -msgid "The rendered map was too big to fit in your inventory." -msgstr "" -"La carte rendue est trop grosse et ne rentre pas dans votre inventaire." - -#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:78 -msgid "{ce}Map rendering failed: {0}" -msgstr "{ce}Impossible de faire le rendu de la carte : {0}" - -#. The title of the map deletion GUI. {0}: map name. -#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:102 -msgid "{0} » {black}Confirm deletion" -msgstr "{0} » {black}Confirmez la suppression" - -#. The title of the map deletion item -#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:110 -msgid "{red}You're about to destroy this map..." -msgstr "{red}Vous êtes sur le point de supprimer cette carte..." - -#. The end, in the lore, of a title starting with “You're about to destroy this map...”. -#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:112 -msgid "{red}...{italic}forever{red}." -msgstr "{red}...{italic}pour toujours{red}." - -#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:114 -msgid "{gray}Name: {white}{0}" -msgstr "{gray}Nom : {white}{0}" - -#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:115 -msgid "{gray}Map ID: {white}{0}" -msgstr "{gray}Identifiant : {white}{0}" - -#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:116 -msgid "{gray}Maps inside: {white}{0}" -msgstr "{gray}Cartes : {white}{0}" - -#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:178 +#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:187 msgid "{gray}Map successfully deleted." msgstr "{gray}Carte supprimée avec succès." -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:54 -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:71 -msgid "{green}Map part" -msgstr "{green}Extrait de carte" +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:208 +msgid "{ce}Map names can't be empty." +msgstr "{ce}Les noms de cartes ne peuvent être vide." -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:55 -msgid "{gray}Column: {white}{0}" -msgstr "{gray}Colonne : {white}{0}" +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:213 +msgid "{cs}Map successfully renamed." +msgstr "{cs}Carte renommée avec succès." -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:56 -msgid "{gray}Row: {white}{0}" -msgstr "{gray}Ligne : {white}{0}" +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:45 +msgid "Splatter Map" +msgstr "Poster auto-dépliant" -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:58 -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:74 -msgid "{gray}» {white}Click{gray} to get only this part" -msgstr "{gray}» {white}Cliquez{gray} pour récupérer cette partie" +#. Title in a splatter map tooltip +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:49 +msgid "Item frames needed" +msgstr "Cadres requis" -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:72 -msgid "{gray}Part: {white}{0}" -msgstr "{gray}Partie : {white}{0}" - -#. Title of the map details GUI -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:114 -msgid "Your maps » {black}{0}" -msgstr "Vos cartes » {black}{0}" - -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:136 -msgid "{blue}Rename this image" -msgstr "{blue}Renommer cette image" - -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:137 -msgid "" -"{gray}Click here to rename this image; this is used for your own " -"organization." -msgstr "" -"{gray}Cliquez ici pour renommer cette image ; ceci ne sert qu'à votre " -"organisation personnelle." - -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:105 -msgid "{red}Delete this image" -msgstr "{red}Supprimer cette image" - -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:106 -msgid "" -"{gray}Deletes this map {white}forever{gray}. This action cannot be undone!" -msgstr "" -"{gray}Supprime cette carte {white}pour toujours{gray}. Cette action ne peut " -"être annulée !" - -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:144 -msgid "{gray}You will be asked to confirm your choice if you click here." -msgstr "{gray}Une confirmation vous sera demandée si vous cliquez ici." - -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:156 -msgid "{green}« Back" -msgstr "{green}« Retour" - -#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:157 -msgid "{gray}Go back to the list." -msgstr "{gray}Retourner à la liste." - -#. Displayed subtitle description of a single map on the list GUI -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:44 -msgid "{white}Single map" -msgstr "{white}Carte unique" - -#. Displayed subtitle description of a poster map on the list GUI (columns × rows in english) -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:52 -msgid "{white}Poster map ({0} × {1})" -msgstr "{white}Poster ({0} × {1})" - -#. Displayed subtitle description of a poster map without column data on the list GUI -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:57 -msgid "{white}Poster map ({0} parts)" -msgstr "{white}Poster ({0} parties)" - -#. Displayed title of a map on the list GUI -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:62 -msgid "{green}{bold}{0}" -msgstr "{green}{bold}{0}" - -#. Map ID displayed in the tooltip of a map on the list GUI -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:67 -msgid "{gray}Map ID: {0}" -msgstr "{gray}Identifiant : {white}{0}" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:69 -msgid "{gray}» {white}Left-click{gray} to get this map" -msgstr "{gray}» {white}Cliquez gauche{gray} pour récupérer cette carte" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:70 -msgid "{gray}» {white}Right-click{gray} for details and options" -msgstr "{gray}» {white}Cliquez droit{gray} pour des détails et options" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:79 -msgid "{red}You don't have any map." -msgstr "{red}Vous n'avez aucune carte." - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:80 -msgid "" -"{gray}Get started by creating a new one using {white}/tomap [resize]" -"{gray}!" -msgstr "" -"{gray}Commencez par en créer une nouvelle avec {white}/tomap [resize]" -"{gray} !" - -#. The maps list GUI title -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:119 -msgid "{black}Your maps {reset}({0})" -msgstr "{black}Vos cartes {reset}({0})" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:148 -msgid "{blue}Usage statistics" -msgstr "{blue}Statistiques d'utilisation" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:150 -msgid "{white}{0}{gray} image rendered" -msgid_plural "{white}{0}{gray} images rendered" -msgstr[0] "{white}{0}{gray} image rendue" -msgstr[1] "{white}{0}{gray} images rendues" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:151 -msgid "{white}{0}{gray} Minecraft map used" -msgid_plural "{white}{0}{gray} Minecraft maps used" -msgstr[0] "{white}{0}{gray} carte Minecraft utilisée" -msgstr[1] "{white}{0}{gray} cartes Minecraft utilisées" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:156 -msgid "{blue}Minecraft maps limits" -msgstr "{blue}Limites de cartes Minecraft" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:158 -msgid "{gray}Server-wide limit: {white}unlimited" -msgstr "{gray}Limite du serveur : {white}illimité" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:159 -msgid "{gray}Server-wide limit: {white}{0}" -msgstr "{gray}Limite du serveur : {white}{0}" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:161 -msgid "{gray}Per-player limit: {white}unlimited" -msgstr "{gray}Limite individuelle : {white}illimité" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:162 -msgid "{gray}Per-player limit: {white}{0}" -msgstr "{gray}Limite individuelle : {white}{0}" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:164 -msgid "{white}{0} %{gray} of your quota used" -msgstr "{white}{0} %{gray} de votre quota utilisé" - -#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:165 -msgid "{white}{0}{gray} map left" -msgid_plural "{white}{0}{gray} maps left" -msgstr[0] "{white}{0}{gray} carte restante" -msgstr[1] "{white}{0}{gray} cartes restantes" - -#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:73 +#. Size of a map stored in a splatter map +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:51 #, java-format -msgid "HTTP error: {0} {1}" -msgstr "Erreur HTTP : {0} {1}" +msgid "{0} × {1}" +msgstr "{0} × {1}" -#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:79 -msgid "The given URL is not a valid image" -msgstr "L'URL donnée n'est pas une image valide." +#. Title in a splatter map tooltip +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:54 +msgid "How to use this?" +msgstr "Comment l'utiliser ?" -#. The default display name of a map -#: src/main/java/fr/moribus/imageonmap/map/ImageMap.java:44 -msgid "Map" -msgstr "Carte" +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:55 +msgid "" +"Place empty item frames on a wall, enough to host the whole map. Then, right-" +"click on the bottom-left frame with this map." +msgstr "" +"Placez des cadres vides sur un mur, en quantité suffisante pour accueillir " +"la carte entière. Ensuite, cliquez-droit sur le cadre en bas à gauche avec " +"cette carte." -#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:29 +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:57 +msgid "" +"Shift-click one of the placed maps to remove the whole poster in one shot." +msgstr "Cliquez accroupi l'une des cartes du poster pour le retirer d'un coup." + +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:102 +msgid "{ce}There is not enough space to place this map ({0} × {1})." +msgstr "{ce}Il n'y a pas assez d'espace pour accueillir ce poster ({0} × {1})." + +#: src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java:150 #, java-format -msgid "You have too many maps (maximum : {0})." -msgstr "Vous avez trop de cartes (maximum : {0})." +msgid "{0} (row {1}, column {2})" +msgstr "{0} (ligne {1}, colonne {2})" -#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:30 -msgid "The server ImageOnMap limit has been reached." -msgstr "La limite serveur de cartes a été atteinte." - -#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:31 -msgid "The given map does not exist." -msgstr "La carte donnée n'existe pas." +#: src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java:155 +#, java-format +msgid "{0} (part {1})" +msgstr "{0} (partie {1})" #: src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java:34 msgid "Migration is already running." @@ -551,60 +296,269 @@ msgstr "" "Les données qui n'ont pas été migrées seront conservées dans les vieux " "fichiers de données." -#. The name of a map item given to a player, if splatter maps are not used. 0 = map name; 1 = index. -#: src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java:139 -#: src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java:215 +#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:60 #, java-format -msgid "{0} (part {1})" -msgstr "{0} (partie {1})" +msgid "HTTP error: {0} {1}" +msgstr "Erreur HTTP : {0} {1}" -#. The name of a map item given to a player, if splatter maps are not used. 0 = map name; 1 = row; 2 = column. -#: src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java:145 -#: src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java:213 -#, java-format -msgid "{0} (row {1}, column {2})" -msgstr "{0} (ligne {1}, colonne {2})" +#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:66 +msgid "The given URL is not a valid image" +msgstr "L'URL donnée n'est pas une image valide." -#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:44 -msgid "Splatter Map" -msgstr "Poster auto-dépliant" +#: src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java:40 +msgid "You need to give a map name." +msgstr "Vous devez donner le nom d'une carte." -#. Title in a splatter map tooltip -#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:48 -msgid "Item frames needed" -msgstr "Cadres requis" +#: src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java:57 +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:75 +msgid "This map does not exist." +msgstr "Cette carte n'existe pas." -#. Size of a map stored in a splatter map -#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:50 -#, java-format -msgid "{0} × {1}" -msgstr "{0} × {1}" +#: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:51 +msgid "No map found." +msgstr "Aucune carte trouvée." -#. Title in a splatter map tooltip -#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:53 -msgid "How to use this?" -msgstr "Comment l'utiliser ?" +#: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:55 +msgid "{white}{bold}{0} map found." +msgid_plural "{white}{bold}{0} maps found." +msgstr[0] "{white}{bold}{0} carte trouvée." +msgstr[1] "{white}{bold}{0} cartes trouvées." -#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:54 -msgid "" -"Place empty item frames on a wall, enough to host the whole map. Then, right-" -"click on the bottom-left frame with this map." +#: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:81 +msgid "{white}Click{gray} to get this map" +msgstr "{white}Cliquez{gray} pour obtenir cette carte" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java:40 +msgid "The requested map was too big to fit in your inventory." msgstr "" -"Placez des cadres vides sur un mur, en quantité suffisante pour accueillir " -"la carte entière. Ensuite, cliquez-droit sur le cadre en bas à gauche avec " -"cette carte." +"La carte demandée est trop grande et ne rentre pas dans votre inventaire." -#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:56 +#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java:41 +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:73 +msgid "Use '/maptool getremaining' to get the remaining maps." +msgstr "Utilisez “/maptool getremaining” pour récupérer les cartes restantes." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:49 +msgid "You are going to delete" +msgstr "Vous êtes sur le point de supprimer" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:52 +msgid "Are you sure ? " +msgstr "Êtes-vous sûr(e) ?" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:54 +msgid "[Confirm]" +msgstr "[Confirmer]" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:56 +msgid "{red}This map will be deleted {bold}forever{red}!" +msgstr "{red}Cette carte sera supprimée {bold}définitivement{red} !" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:70 +msgid "Map successfully deleted." +msgstr "Carte supprimée avec succès." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:46 +msgid "You must give an URL to take the image from." +msgstr "Vous devez fournir l'URL de l'image." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:54 +msgid "Invalid URL." +msgstr "URL invalide." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:63 +msgid "Rendering..." +msgstr "Rendu en cours..." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:69 +msgid "{cst}Rendering finished!" +msgstr "{cst}Rendu achevé !" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:72 +msgid "The rendered map was too big to fit in your inventory." +msgstr "" +"La carte rendue est trop grosse et ne rentre pas dans votre inventaire." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:80 +msgid "{ce}Map rendering failed: {0}" +msgstr "{ce}Impossible de faire le rendu de la carte : {0}" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java:40 +msgid "You have no remaining map." +msgstr "Vous n'avez aucune carte restante." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java:48 msgid "" -"Shift-click one of the placed maps to remove the whole poster in one shot." -msgstr "Cliquez accroupi l'une des cartes du poster pour le retirer d'un coup." +"Your inventory is full! Make some space before requesting the remaining maps." +msgstr "" +"Votre inventaire est plein ! Faites de la place avant de demander les cartes " +"supplémentaires." -#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:101 -msgid "{ce}There is not enough space to place this map ({0} × {1})." -msgstr "{ce}Il n'y a pas assez d'espace pour accueillir ce poster ({0} × {1})." +#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java:52 +#, java-format +msgid "There is {0} map remaining." +msgid_plural "There are {0} maps remaining." +msgstr[0] "Il y a {0} carte restante." +msgstr[1] "Il y a {0} cartes restantes." -#~ msgid "{ce}Map names can't be empty." -#~ msgstr "{ce}Les noms de cartes ne peuvent être vide." +#: src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java:37 +msgid "A migration process is already running. Check console for details." +msgstr "" +"Un processus de migration est déjà en cours. Consultez la console pour plus " +"de détails." -#~ msgid "{cs}Map successfully renamed." -#~ msgstr "{cs}Carte renommée avec succès." +#: src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java:41 +msgid "Migration started. See console for details." +msgstr "Migration démarrée. Consultez la console pour plus de détails." + +#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:29 +#, java-format +msgid "You have too many maps (maximum : {0})." +msgstr "Vous avez trop de cartes (maximum : {0})." + +#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:30 +msgid "The server ImageOnMap limit has been reached." +msgstr "La limite serveur de cartes a été atteinte." + +#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:31 +msgid "The given map does not exist." +msgstr "La carte donnée n'existe pas." + +#. The default display name of a map +#: src/main/java/fr/moribus/imageonmap/map/ImageMap.java:44 +msgid "Map" +msgstr "Carte" + +#~ msgid "{0} » {black}Confirm deletion" +#~ msgstr "{0} » {black}Confirmez la suppression" + +#~ msgid "{red}You're about to destroy this map..." +#~ msgstr "{red}Vous êtes sur le point de supprimer cette carte..." + +#~ msgid "{red}...{italic}forever{red}." +#~ msgstr "{red}...{italic}pour toujours{red}." + +#~ msgid "{gray}Name: {white}{0}" +#~ msgstr "{gray}Nom : {white}{0}" + +#~ msgid "{gray}Map ID: {white}{0}" +#~ msgstr "{gray}Identifiant : {white}{0}" + +#~ msgid "{gray}Maps inside: {white}{0}" +#~ msgstr "{gray}Cartes : {white}{0}" + +#~ msgid "{green}Map part" +#~ msgstr "{green}Extrait de carte" + +#~ msgid "{gray}Column: {white}{0}" +#~ msgstr "{gray}Colonne : {white}{0}" + +#~ msgid "{gray}Row: {white}{0}" +#~ msgstr "{gray}Ligne : {white}{0}" + +#~ msgid "{gray}» {white}Click{gray} to get only this part" +#~ msgstr "{gray}» {white}Cliquez{gray} pour récupérer cette partie" + +#~ msgid "{gray}Part: {white}{0}" +#~ msgstr "{gray}Partie : {white}{0}" + +#~ msgid "Your maps » {black}{0}" +#~ msgstr "Vos cartes » {black}{0}" + +#~ msgid "{blue}Rename this image" +#~ msgstr "{blue}Renommer cette image" + +#~ msgid "" +#~ "{gray}Click here to rename this image; this is used for your own " +#~ "organization." +#~ msgstr "" +#~ "{gray}Cliquez ici pour renommer cette image ; ceci ne sert qu'à votre " +#~ "organisation personnelle." + +#~ msgid "{red}Delete this image" +#~ msgstr "{red}Supprimer cette image" + +#~ msgid "" +#~ "{gray}Deletes this map {white}forever{gray}. This action cannot be undone!" +#~ msgstr "" +#~ "{gray}Supprime cette carte {white}pour toujours{gray}. Cette action ne " +#~ "peut être annulée !" + +#~ msgid "{gray}You will be asked to confirm your choice if you click here." +#~ msgstr "{gray}Une confirmation vous sera demandée si vous cliquez ici." + +#~ msgid "{green}« Back" +#~ msgstr "{green}« Retour" + +#~ msgid "{gray}Go back to the list." +#~ msgstr "{gray}Retourner à la liste." + +#~ msgid "{white}Single map" +#~ msgstr "{white}Carte unique" + +#~ msgid "{white}Poster map ({0} × {1})" +#~ msgstr "{white}Poster ({0} × {1})" + +#~ msgid "{white}Poster map ({0} parts)" +#~ msgstr "{white}Poster ({0} parties)" + +#~ msgid "{green}{bold}{0}" +#~ msgstr "{green}{bold}{0}" + +#~ msgid "{gray}Map ID: {0}" +#~ msgstr "{gray}Identifiant : {white}{0}" + +#~ msgid "{gray}» {white}Left-click{gray} to get this map" +#~ msgstr "{gray}» {white}Cliquez gauche{gray} pour récupérer cette carte" + +#~ msgid "{gray}» {white}Right-click{gray} for details and options" +#~ msgstr "{gray}» {white}Cliquez droit{gray} pour des détails et options" + +#~ msgid "{red}You don't have any map." +#~ msgstr "{red}Vous n'avez aucune carte." + +#~ msgid "" +#~ "{gray}Get started by creating a new one using {white}/tomap [resize]" +#~ "{gray}!" +#~ msgstr "" +#~ "{gray}Commencez par en créer une nouvelle avec {white}/tomap " +#~ "[resize]{gray} !" + +#~ msgid "{black}Your maps {reset}({0})" +#~ msgstr "{black}Vos cartes {reset}({0})" + +#~ msgid "{blue}Usage statistics" +#~ msgstr "{blue}Statistiques d'utilisation" + +#~ msgid "{white}{0}{gray} image rendered" +#~ msgid_plural "{white}{0}{gray} images rendered" +#~ msgstr[0] "{white}{0}{gray} image rendue" +#~ msgstr[1] "{white}{0}{gray} images rendues" + +#~ msgid "{white}{0}{gray} Minecraft map used" +#~ msgid_plural "{white}{0}{gray} Minecraft maps used" +#~ msgstr[0] "{white}{0}{gray} carte Minecraft utilisée" +#~ msgstr[1] "{white}{0}{gray} cartes Minecraft utilisées" + +#~ msgid "{blue}Minecraft maps limits" +#~ msgstr "{blue}Limites de cartes Minecraft" + +#~ msgid "{gray}Server-wide limit: {white}unlimited" +#~ msgstr "{gray}Limite du serveur : {white}illimité" + +#~ msgid "{gray}Server-wide limit: {white}{0}" +#~ msgstr "{gray}Limite du serveur : {white}{0}" + +#~ msgid "{gray}Per-player limit: {white}unlimited" +#~ msgstr "{gray}Limite individuelle : {white}illimité" + +#~ msgid "{gray}Per-player limit: {white}{0}" +#~ msgstr "{gray}Limite individuelle : {white}{0}" + +#~ msgid "{white}{0} %{gray} of your quota used" +#~ msgstr "{white}{0} %{gray} de votre quota utilisé" + +#~ msgid "{white}{0}{gray} map left" +#~ msgid_plural "{white}{0}{gray} maps left" +#~ msgstr[0] "{white}{0}{gray} carte restante" +#~ msgstr[1] "{white}{0}{gray} cartes restantes" diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index a1acf4b..17bd4fe 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ImageOnMap main: fr.moribus.imageonmap.ImageOnMap -version: 3.0 +version: 3.1 commands: tomap: @@ -12,6 +12,47 @@ commands: description: manage maps through a GUI permissions: + imageonmap.*: + description: "Grants all the user permissions (excluding administrative ones)." + default: true + children: + imageonmap.userender: true + imageonmap.new: true + imageonmap.list: true + imageonmap.get: true + imageonmap.explore: true + imageonmap.rename: true + imageonmap.delete: true + imageonmap.administrative: false + imageonmap.userender: - description: Allows you to use /tomap - default: op \ No newline at end of file + description: "Allows you to use /tomap and related commands (/maptool getremaing). Alias of imageonmap.new." + default: true + + imageonmap.new: + description: "Allows you to use /tomap and related commands (/maptool getremaing)." + default: true + + imageonmap.list: + description: "Allows you to list the images you rendered." + default: true + + imageonmap.get: + description: "Allows you to get a new map among the ones you already rendered, and related commands (/maptool getremaing)." + default: true + + imageonmap.explore: + description: "Allows you to open a GUI with all your maps." + default: true + + imageonmap.rename: + description: "Allows you to rename a map you rendered in the past." + default: true + + imageonmap.delete: + description: "Allows you to delete a map you rendered in the past." + default: true + + imageonmap.administrative: + description: "Allows you to perform administrative tasks (like /maptool migrate)." + default: op