Merge pull request #3 from kirbykirby56/pr/2

Pr/2
This commit is contained in:
kirbykirby56 2018-03-21 21:44:49 -04:00 committed by GitHub
commit 3ed5388552
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 737 additions and 455 deletions

View File

@ -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 <new|list|get|delete|explore|migrate>`
@ -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`.

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>fr.moribus</groupId>
<artifactId>ImageOnMap</artifactId>
<version>3.0</version>
<version>3.1</version>
<packaging>jar</packaging>
<properties>

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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<ImageMap>()
ImageRendererExecutor.render(url, scaling, player.getUniqueId(), width, height, new WorkerCallback<ImageMap>()
{
@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);
}
}

View File

@ -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

View File

@ -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<Short>
@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<Short>
@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<Short>
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<Short>
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<Short>
@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<String>()
{
@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<Short>
@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);
}

View File

@ -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<ImageMap>
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<ImageMap>
.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 <URL> [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 <URL> [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<ImageMap>
@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>
{
ImageMap[] maps = MapManager.getMaps(getPlayer().getUniqueId());
setData(maps);
/// The maps list GUI title
setTitle(I.t(getPlayerLocale(), "{black}Your maps {reset}({0})", maps.length));

View File

@ -30,10 +30,7 @@ import fr.zcraft.zlib.components.worker.WorkerRunnable;
import javax.imageio.ImageIO;
import javax.security.auth.login.Configuration;
import org.bukkit.Bukkit;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
@ -49,7 +46,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<ImageMap> callback)
static public void render(final URL url, final ImageUtils.ScalingType scaling, final UUID playerUUID, final int width, final int height, WorkerCallback<ImageMap> callback)
{
submitQuery(new WorkerRunnable<ImageMap>()
{
@ -72,6 +69,7 @@ public class ImageRendererExecutor extends Worker
if (image == null) throw new IOException(I.t("The given URL is not a valid image"));
//Limits are in place and the player does NOT have rights to avoid them.
if((PluginConfiguration.LIMIT_SIZE_X > 0 || PluginConfiguration.LIMIT_SIZE_Y > 0) && !Bukkit.getPlayer(playerUUID).hasPermission("imageonmap.bypasssize")) {
if(PluginConfiguration.LIMIT_SIZE_X > 0) {
@ -82,17 +80,21 @@ public class ImageRendererExecutor extends Worker
}
}
if (scaling) return RenderSingle(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);
else return RenderPoster(image, 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<Short> futureMapID = submitToMainThread(new Callable<Short>()
final Future<Short> futureMapID = submitToMainThread(new Callable<Short>()
{
@Override
public Short call() throws Exception
@ -100,27 +102,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<Void>()
{
@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();
@ -159,33 +158,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;
}
}

View File

@ -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;
}
}

View File

@ -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 <URL> [resize]"
"{gray}!"
msgstr ""
"{gray}Commencez par en créer une nouvelle avec {white}/tomap <URL> [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 <URL> [resize]"
#~ "{gray}!"
#~ msgstr ""
#~ "{gray}Commencez par en créer une nouvelle avec {white}/tomap <URL> "
#~ "[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"

View File

@ -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
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