Merge pull request #1 from zDevelopers/indev

update to zdev off indev
This commit is contained in:
kirbykirby56 2018-03-18 19:35:15 -04:00 committed by GitHub
commit 3d7d2fd27e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 736 additions and 453 deletions

View File

@ -1,7 +1,7 @@
ImageOnMap ImageOnMap
========== ==========
Repo for ImageOnMap, a bukkit plugin Repo for ImageOnMap, a bukkit plugin.
## Features ## Features
@ -14,7 +14,7 @@ ImageOnMap allows you to load a picture from the Internet to a Minecraft map.
- Your image will be centered. - Your image will be centered.
- You can put your map in an item frame. - 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 ## 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. - 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. - You can use an URL shortener like tinyURL or bitly.
- If you want a picture in one map, type resize after the link. - 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` ### `/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). - 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. - 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). - 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>` ### `/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 new` is an alias of `/tomap`.
- `/maptool explore` is an alias of `/maps`. - `/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. - `/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 ## Configuration
@ -77,7 +90,9 @@ map-global-limit: 0
map-player-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. 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 !) - 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`) - 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 ## 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> <modelVersion>4.0.0</modelVersion>
<groupId>fr.moribus</groupId> <groupId>fr.moribus</groupId>
<artifactId>ImageOnMap</artifactId> <artifactId>ImageOnMap</artifactId>
<version>3.0</version> <version>3.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<properties> <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; package fr.moribus.imageonmap.commands.maptool;
import fr.moribus.imageonmap.Permissions;
import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.commands.IoMCommand;
import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.ImageMap;
import fr.moribus.imageonmap.map.MapManager; 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.components.rawtext.RawText;
import fr.zcraft.zlib.tools.PluginLogger; import fr.zcraft.zlib.tools.PluginLogger;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
@ -83,4 +85,10 @@ public class DeleteCommand extends IoMCommand
return null; 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; package fr.moribus.imageonmap.commands.maptool;
import fr.moribus.imageonmap.Permissions;
import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.commands.IoMCommand;
import fr.moribus.imageonmap.gui.MapListGui; import fr.moribus.imageonmap.gui.MapListGui;
import fr.zcraft.zlib.components.commands.CommandException; import fr.zcraft.zlib.components.commands.CommandException;
import fr.zcraft.zlib.components.commands.CommandInfo; import fr.zcraft.zlib.components.commands.CommandInfo;
import fr.zcraft.zlib.components.gui.Gui; import fr.zcraft.zlib.components.gui.Gui;
import org.bukkit.command.CommandSender;
@CommandInfo (name = "explore") @CommandInfo (name = "explore")
@ -34,4 +36,10 @@ public class ExploreCommand extends IoMCommand
{ {
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; package fr.moribus.imageonmap.commands.maptool;
import fr.moribus.imageonmap.Permissions;
import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.commands.IoMCommand;
import fr.zcraft.zlib.components.commands.CommandException; import fr.zcraft.zlib.components.commands.CommandException;
import fr.zcraft.zlib.components.commands.CommandInfo; import fr.zcraft.zlib.components.commands.CommandInfo;
import fr.zcraft.zlib.components.i18n.I; import fr.zcraft.zlib.components.i18n.I;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
@ -47,4 +49,10 @@ public class GetCommand extends IoMCommand
return getMatchingMapNames(playerSender(), args[0]); return getMatchingMapNames(playerSender(), args[0]);
return null; 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; package fr.moribus.imageonmap.commands.maptool;
import fr.moribus.imageonmap.Permissions;
import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.commands.IoMCommand;
import fr.moribus.imageonmap.ui.MapItemManager; import fr.moribus.imageonmap.ui.MapItemManager;
import fr.zcraft.zlib.components.commands.CommandException; import fr.zcraft.zlib.components.commands.CommandException;
import fr.zcraft.zlib.components.commands.CommandInfo; import fr.zcraft.zlib.components.commands.CommandInfo;
import fr.zcraft.zlib.components.i18n.I; import fr.zcraft.zlib.components.i18n.I;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@CommandInfo (name = "getremaining", aliases = {"getrest"}) @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))); 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; package fr.moribus.imageonmap.commands.maptool;
import fr.moribus.imageonmap.Permissions;
import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.commands.IoMCommand;
import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.ImageMap;
import fr.moribus.imageonmap.map.MapManager; 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 fr.zcraft.zlib.tools.text.RawMessage;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
@ -81,4 +83,10 @@ public class ListCommand extends IoMCommand
.item() .item()
); );
} }
@Override
public boolean canExecute(CommandSender sender)
{
return Permissions.LIST.grantedTo(sender);
}
} }

View File

@ -18,6 +18,7 @@
package fr.moribus.imageonmap.commands.maptool; package fr.moribus.imageonmap.commands.maptool;
import fr.moribus.imageonmap.Permissions;
import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.commands.IoMCommand;
import fr.moribus.imageonmap.migration.MigratorExecutor; import fr.moribus.imageonmap.migration.MigratorExecutor;
import fr.zcraft.zlib.components.commands.CommandException; import fr.zcraft.zlib.components.commands.CommandException;
@ -45,6 +46,6 @@ public class MigrateCommand extends IoMCommand
@Override @Override
public boolean canExecute(CommandSender sender) 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; package fr.moribus.imageonmap.commands.maptool;
import fr.moribus.imageonmap.Permissions;
import fr.moribus.imageonmap.commands.IoMCommand; import fr.moribus.imageonmap.commands.IoMCommand;
import fr.moribus.imageonmap.image.ImageRendererExecutor; import fr.moribus.imageonmap.image.ImageRendererExecutor;
import fr.moribus.imageonmap.image.ImageUtils;
import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.ImageMap;
import fr.zcraft.zlib.components.commands.CommandException; import fr.zcraft.zlib.components.commands.CommandException;
import fr.zcraft.zlib.components.commands.CommandInfo; import fr.zcraft.zlib.components.commands.CommandInfo;
import fr.zcraft.zlib.components.i18n.I; import fr.zcraft.zlib.components.i18n.I;
import fr.zcraft.zlib.components.worker.WorkerCallback; import fr.zcraft.zlib.components.worker.WorkerCallback;
import fr.zcraft.zlib.tools.PluginLogger; import fr.zcraft.zlib.tools.PluginLogger;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.net.MalformedURLException; import java.net.MalformedURLException;
@ -38,8 +41,9 @@ public class NewCommand extends IoMCommand
protected void run() throws CommandException protected void run() throws CommandException
{ {
final Player player = playerSender(); final Player player = playerSender();
boolean scaling = false; ImageUtils.ScalingType scaling = ImageUtils.ScalingType.NONE;
URL url; URL url;
int width = 0, height = 0;
if(args.length < 1) throwInvalidArgument(I.t("You must give an URL to take the image from.")); 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.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...")); 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 @Override
public void finished(ImageMap result) 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; package fr.moribus.imageonmap.gui;
import fr.moribus.imageonmap.Permissions;
import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.ImageMap;
import fr.moribus.imageonmap.map.MapManager; import fr.moribus.imageonmap.map.MapManager;
import fr.moribus.imageonmap.map.MapManagerException; import fr.moribus.imageonmap.map.MapManagerException;
@ -170,6 +171,14 @@ public class ConfirmDeleteMapGui extends ActionGui
@GuiAction ("delete") @GuiAction ("delete")
protected void 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); MapManager.clear(getPlayer().getInventory(), mapToDelete);
try try

View File

@ -18,6 +18,7 @@
package fr.moribus.imageonmap.gui; package fr.moribus.imageonmap.gui;
import fr.moribus.imageonmap.Permissions;
import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.ImageMap;
import fr.moribus.imageonmap.map.PosterMap; import fr.moribus.imageonmap.map.PosterMap;
import fr.moribus.imageonmap.map.SingleMap; import fr.moribus.imageonmap.map.SingleMap;
@ -46,43 +47,46 @@ public class MapDetailGui extends ExplorerGui<Short>
@Override @Override
protected ItemStack getViewItem(int x, int y) protected ItemStack getViewItem(int x, int y)
{ {
Material partMaterial = Material.PAPER; final Material partMaterial = y % 2 == x % 2 ? Material.EMPTY_MAP : Material.PAPER;
if((y % 2 == 0 && x % 2 == 0) || (y % 2 == 1 && x % 2 == 1))
partMaterial = Material.EMPTY_MAP;
return new ItemStackBuilder(partMaterial) final ItemStackBuilder builder = new ItemStackBuilder(partMaterial)
.title(I.t(getPlayerLocale(), "{green}Map part")) .title(I.t(getPlayerLocale(), "{green}Map part"))
.lore(I.t(getPlayerLocale(), "{gray}Row: {white}{0}", y + 1)) .lore(I.t(getPlayerLocale(), "{gray}Row: {white}{0}", y + 1))
.lore(I.t(getPlayerLocale(), "{gray}Column: {white}{0}", x + 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")) if (Permissions.GET.grantedTo(getPlayer()))
.item(); builder.loreLine().lore(I.t(getPlayerLocale(), "{gray}» {white}Click{gray} to get only this part"));
return builder.item();
} }
@Override @Override
protected ItemStack getViewItem(Short mapId) protected ItemStack getViewItem(Short mapId)
{ {
int index = ((PosterMap) map).getIndex(mapId); final int index = ((PosterMap) map).getIndex(mapId);
Material partMaterial = Material.PAPER; final Material partMaterial = index % 2 == 0 ? Material.EMPTY_MAP : Material.PAPER;
if(index % 2 == 0)
partMaterial = Material.EMPTY_MAP;
return new ItemStackBuilder(partMaterial) final ItemStackBuilder builder = new ItemStackBuilder(partMaterial)
.title(I.t(getPlayerLocale(), "{green}Map part")) .title(I.t(getPlayerLocale(), "{green}Map part"))
.lore(I.t(getPlayerLocale(), "{gray}Part: {white}{0}", index + 1)) .lore(I.t(getPlayerLocale(), "{gray}Part: {white}{0}", index + 1));
.loreLine()
.lore(I.t(getPlayerLocale(), "{gray}» {white}Click{gray} to get only this part")) if (Permissions.GET.grantedTo(getPlayer()))
.item(); builder.loreLine().lore(I.t(getPlayerLocale(), "{gray}» {white}Click{gray} to get only this part"));
return builder.item();
} }
@Override @Override
protected ItemStack getPickedUpItem(int x, int y) 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); return MapItemManager.createMapItem((SingleMap)map);
} }
else if(map instanceof PosterMap) else if (map instanceof PosterMap)
{ {
return MapItemManager.createMapItem((PosterMap)map, x, y); return MapItemManager.createMapItem((PosterMap)map, x, y);
} }
@ -93,14 +97,17 @@ public class MapDetailGui extends ExplorerGui<Short>
@Override @Override
protected ItemStack getPickedUpItem(Short mapId) 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)); return MapItemManager.createMapItem(poster, poster.getIndex(mapId));
} }
@Override @Override
protected ItemStack getEmptyViewItem() protected ItemStack getEmptyViewItem()
{ {
if(map instanceof SingleMap) if (map instanceof SingleMap)
{ {
return getViewItem(0, 0); return getViewItem(0, 0);
} }
@ -114,7 +121,7 @@ public class MapDetailGui extends ExplorerGui<Short>
setTitle(I.t(getPlayerLocale(), "Your maps » {black}{0}", map.getName())); setTitle(I.t(getPlayerLocale(), "Your maps » {black}{0}", map.getName()));
setKeepHorizontalScrollingSpace(true); setKeepHorizontalScrollingSpace(true);
if(map instanceof PosterMap) if (map instanceof PosterMap)
{ {
PosterMap poster = (PosterMap) map; PosterMap poster = (PosterMap) map;
if(poster.hasColumnData()) if(poster.hasColumnData())
@ -131,25 +138,41 @@ public class MapDetailGui extends ExplorerGui<Short>
setDataShape(1,1); 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) int renameSlot = getSize() - 7;
int deleteSlot = getSize() - 6;
if (!canRename)
deleteSlot--;
if (canRename)
{
action("rename", renameSlot, new ItemStackBuilder(Material.BOOK_AND_QUILL)
.title(I.t(getPlayerLocale(), "{blue}Rename this image")) .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.")) .longLore(I.t(getPlayerLocale(), "{gray}Click here to rename this image; this is used for your own organization."))
); );
}
action("delete", getSize() - 6, new ItemStackBuilder(Material.BARRIER) if (canDelete)
{
action("delete", deleteSlot, new ItemStackBuilder(Material.BARRIER)
.title(I.t(getPlayerLocale(), "{red}Delete this image")) .title(I.t(getPlayerLocale(), "{red}Delete this image"))
.longLore(I.t(getPlayerLocale(), "{gray}Deletes this map {white}forever{gray}. This action cannot be undone!")) .longLore(I.t(getPlayerLocale(), "{gray}Deletes this map {white}forever{gray}. This action cannot be undone!"))
.loreLine() .loreLine()
.longLore(I.t(getPlayerLocale(), "{gray}You will be asked to confirm your choice if you click here.")) .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 // 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. // arrow isn't displayed, so when the map fit on the grid without sliders.
int backSlot = getSize() - 4; 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++; backSlot++;
action("back", backSlot, new ItemStackBuilder(Material.EMERALD) action("back", backSlot, new ItemStackBuilder(Material.EMERALD)
@ -162,11 +185,24 @@ public class MapDetailGui extends ExplorerGui<Short>
@GuiAction ("rename") @GuiAction ("rename")
public void 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>() PromptGui.prompt(getPlayer(), new Callback<String>()
{ {
@Override @Override
public void call(String newName) 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()) if (newName == null || newName.isEmpty())
{ {
I.sendT(getPlayer(), "{ce}Map names can't be empty."); I.sendT(getPlayer(), "{ce}Map names can't be empty.");
@ -182,6 +218,13 @@ public class MapDetailGui extends ExplorerGui<Short>
@GuiAction ("delete") @GuiAction ("delete")
public void 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); Gui.open(getPlayer(), new ConfirmDeleteMapGui(map), this);
} }

View File

@ -17,6 +17,7 @@
*/ */
package fr.moribus.imageonmap.gui; package fr.moribus.imageonmap.gui;
import fr.moribus.imageonmap.Permissions;
import fr.moribus.imageonmap.PluginConfiguration; import fr.moribus.imageonmap.PluginConfiguration;
import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.ImageMap;
import fr.moribus.imageonmap.map.MapManager; 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()); 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 /// Displayed title of a map on the list GUI
.title(I.t(getPlayerLocale(), "{green}{bold}{0}", map.getName())) .title(I.t(getPlayerLocale(), "{green}{bold}{0}", map.getName()))
@ -65,20 +66,28 @@ public class MapListGui extends ExplorerGui<ImageMap>
.loreLine() .loreLine()
/// Map ID displayed in the tooltip of a map on the list GUI /// Map ID displayed in the tooltip of a map on the list GUI
.lore(I.t(getPlayerLocale(), "{gray}Map ID: {0}", map.getId())) .lore(I.t(getPlayerLocale(), "{gray}Map ID: {0}", map.getId()))
.loreLine() .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"))
.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 @Override
protected ItemStack getEmptyViewItem() protected ItemStack getEmptyViewItem()
{ {
return new ItemStackBuilder(Material.BARRIER) ItemStackBuilder builder = new ItemStackBuilder(Material.BARRIER)
.title(I.t(getPlayerLocale(), "{red}You don't have any map.")) .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(); 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 @Override
@ -90,6 +99,9 @@ public class MapListGui extends ExplorerGui<ImageMap>
@Override @Override
protected ItemStack getPickedUpItem(ImageMap map) protected ItemStack getPickedUpItem(ImageMap map)
{ {
if (!Permissions.GET.grantedTo(getPlayer()))
return null;
if (map instanceof SingleMap) if (map instanceof SingleMap)
{ {
return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName()); return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName());
@ -114,6 +126,7 @@ public class MapListGui extends ExplorerGui<ImageMap>
{ {
ImageMap[] maps = MapManager.getMaps(getPlayer().getUniqueId()); ImageMap[] maps = MapManager.getMaps(getPlayer().getUniqueId());
setData(maps); setData(maps);
/// The maps list GUI title /// The maps list GUI title
setTitle(I.t(getPlayerLocale(), "{black}Your maps {reset}({0})", maps.length)); setTitle(I.t(getPlayerLocale(), "{black}Your maps {reset}({0})", maps.length));

View File

@ -27,7 +27,6 @@ import fr.zcraft.zlib.components.worker.WorkerCallback;
import fr.zcraft.zlib.components.worker.WorkerRunnable; import fr.zcraft.zlib.components.worker.WorkerRunnable;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -42,7 +41,7 @@ import java.util.concurrent.Future;
@WorkerAttributes (name = "Image Renderer", queriesMainThread = true) @WorkerAttributes (name = "Image Renderer", queriesMainThread = true)
public class ImageRendererExecutor extends Worker 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>() submitQuery(new WorkerRunnable<ImageMap>()
{ {
@ -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 (image == null) throw new IOException(I.t("The given URL is not a valid image"));
if (scaling) return RenderSingle(image, playerUUID); if(scaling != ImageUtils.ScalingType.NONE && height <= 1 && width <= 1) {
else return RenderPoster(image, playerUUID); 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); }, 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); MapManager.checkMapLimit(1, playerUUID);
Future<Short> futureMapID = submitToMainThread(new Callable<Short>() final Future<Short> futureMapID = submitToMainThread(new Callable<Short>()
{ {
@Override @Override
public Short call() throws Exception public Short call() throws Exception
@ -83,26 +86,23 @@ public class ImageRendererExecutor extends Worker
} }
}); });
final BufferedImage finalImage = ResizeImage(image, ImageMap.WIDTH, ImageMap.HEIGHT);
final short mapID = futureMapID.get(); final short mapID = futureMapID.get();
ImageIOExecutor.saveImage(mapID, finalImage); ImageIOExecutor.saveImage(mapID, image);
submitToMainThread(new Callable<Void>() submitToMainThread(new Callable<Void>()
{ {
@Override @Override
public Void call() throws Exception public Void call() throws Exception
{ {
Renderer.installRenderer(finalImage, mapID); Renderer.installRenderer(image, mapID);
return null; return null;
} }
}); });
return MapManager.createMap(playerUUID, mapID); 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 PosterImage poster = new PosterImage(image);
final int mapCount = poster.getImagesCount(); final int mapCount = poster.getImagesCount();
@ -136,33 +136,4 @@ public class ImageRendererExecutor extends Worker
return MapManager.createMap(poster, playerUUID, mapsIDs); 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 "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-07-10 00:59+0200\n" "POT-Creation-Date: 2018-01-24 01:08+0100\n"
"PO-Revision-Date: 2016-07-19 16:15+0200\n" "PO-Revision-Date: 2018-01-24 01:45+0100\n"
"Last-Translator: Amaury Carrade\n" "Last-Translator: Amaury Carrade\n"
"Language-Team: \n" "Language-Team: \n"
"Language: fr_FR\n" "Language: fr_FR\n"
@ -16,329 +16,74 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\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 #: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:177
msgid "You need to give a map name." #: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:190
msgstr "Vous devez donner le nom d'une carte." #: 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/gui/ConfirmDeleteMapGui.java:187
#: 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
msgid "{gray}Map successfully deleted." msgid "{gray}Map successfully deleted."
msgstr "{gray}Carte supprimée avec succès." 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:208
#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:71 msgid "{ce}Map names can't be empty."
msgid "{green}Map part" msgstr "{ce}Les noms de cartes ne peuvent être vide."
msgstr "{green}Extrait de carte"
#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:55 #: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:213
msgid "{gray}Column: {white}{0}" msgid "{cs}Map successfully renamed."
msgstr "{gray}Colonne : {white}{0}" msgstr "{cs}Carte renommée avec succès."
#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:56 #: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:45
msgid "{gray}Row: {white}{0}" msgid "Splatter Map"
msgstr "{gray}Ligne : {white}{0}" msgstr "Poster auto-dépliant"
#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:58 #. Title in a splatter map tooltip
#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:74 #: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:49
msgid "{gray}» {white}Click{gray} to get only this part" msgid "Item frames needed"
msgstr "{gray}» {white}Cliquez{gray} pour récupérer cette partie" msgstr "Cadres requis"
#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:72 #. Size of a map stored in a splatter map
msgid "{gray}Part: {white}{0}" #: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:51
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
#, java-format #, java-format
msgid "HTTP error: {0} {1}" msgid "{0} × {1}"
msgstr "Erreur HTTP : {0} {1}" msgstr "{0} × {1}"
#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:79 #. Title in a splatter map tooltip
msgid "The given URL is not a valid image" #: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:54
msgstr "L'URL donnée n'est pas une image valide." msgid "How to use this?"
msgstr "Comment l'utiliser ?"
#. The default display name of a map #: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:55
#: src/main/java/fr/moribus/imageonmap/map/ImageMap.java:44 msgid ""
msgid "Map" "Place empty item frames on a wall, enough to host the whole map. Then, right-"
msgstr "Carte" "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 #, java-format
msgid "You have too many maps (maximum : {0})." msgid "{0} (row {1}, column {2})"
msgstr "Vous avez trop de cartes (maximum : {0})." msgstr "{0} (ligne {1}, colonne {2})"
#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:30 #: src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java:155
msgid "The server ImageOnMap limit has been reached." #, java-format
msgstr "La limite serveur de cartes a été atteinte." msgid "{0} (part {1})"
msgstr "{0} (partie {1})"
#: 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/migration/MigratorExecutor.java:34 #: src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java:34
msgid "Migration is already running." 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 " "Les données qui n'ont pas été migrées seront conservées dans les vieux "
"fichiers de données." "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/image/ImageRendererExecutor.java:60
#: src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java:139
#: src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java:215
#, java-format #, java-format
msgid "{0} (part {1})" msgid "HTTP error: {0} {1}"
msgstr "{0} (partie {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/image/ImageRendererExecutor.java:66
#: src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java:145 msgid "The given URL is not a valid image"
#: src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java:213 msgstr "L'URL donnée n'est pas une image valide."
#, java-format
msgid "{0} (row {1}, column {2})"
msgstr "{0} (ligne {1}, colonne {2})"
#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:44 #: src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java:40
msgid "Splatter Map" msgid "You need to give a map name."
msgstr "Poster auto-dépliant" msgstr "Vous devez donner le nom d'une carte."
#. Title in a splatter map tooltip #: src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java:57
#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:48 #: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:75
msgid "Item frames needed" msgid "This map does not exist."
msgstr "Cadres requis" msgstr "Cette carte n'existe pas."
#. Size of a map stored in a splatter map #: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:51
#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:50 msgid "No map found."
#, java-format msgstr "Aucune carte trouvée."
msgid "{0} × {1}"
msgstr "{0} × {1}"
#. Title in a splatter map tooltip #: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:55
#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:53 msgid "{white}{bold}{0} map found."
msgid "How to use this?" msgid_plural "{white}{bold}{0} maps found."
msgstr "Comment l'utiliser ?" 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 #: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:81
msgid "" msgid "{white}Click{gray} to get this map"
"Place empty item frames on a wall, enough to host the whole map. Then, right-" msgstr "{white}Cliquez{gray} pour obtenir cette carte"
"click on the bottom-left frame with this map."
#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java:40
msgid "The requested map was too big to fit in your inventory."
msgstr "" msgstr ""
"Placez des cadres vides sur un mur, en quantité suffisante pour accueillir " "La carte demandée est trop grande et ne rentre pas dans votre inventaire."
"la carte entière. Ensuite, cliquez-droit sur le cadre en bas à gauche avec "
"cette carte."
#: 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 "" msgid ""
"Shift-click one of the placed maps to remove the whole poster in one shot." "Your inventory is full! Make some space before requesting the remaining maps."
msgstr "Cliquez accroupi l'une des cartes du poster pour le retirer d'un coup." 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 #: src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java:52
msgid "{ce}There is not enough space to place this map ({0} × {1})." #, java-format
msgstr "{ce}Il n'y a pas assez d'espace pour accueillir ce poster ({0} × {1})." 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." #: src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java:37
#~ msgstr "{ce}Les noms de cartes ne peuvent être vide." 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." #: src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java:41
#~ msgstr "{cs}Carte renommée avec succès." 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 name: ImageOnMap
main: fr.moribus.imageonmap.ImageOnMap main: fr.moribus.imageonmap.ImageOnMap
version: 3.0 version: 3.1
commands: commands:
tomap: tomap:
@ -12,6 +12,47 @@ commands:
description: manage maps through a GUI description: manage maps through a GUI
permissions: 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: imageonmap.userender:
description: Allows you to use /tomap 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 default: op