diff --git a/README.md b/README.md index 314b19a..d853a2b 100644 --- a/README.md +++ b/README.md @@ -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 licenced under the GNU General Public License (version 3 or above). You can also get unstable development builds here. +This plugin is a free software licenced under the [CeCILL-B licence](https://cecill.info/licences/Licence_CeCILL-B_V1-en.html) (BSD-style in French law). ## Quick guide @@ -113,8 +113,19 @@ You will find amongst the new features: - Fixed permissions support by adding a full set of permissions for every action of the plugin. +### 4.0 (Upcoming) +The 4.0 is a bit light in content but we have unified part of the plugin (splatter map) and we have make various change to zLib, next update should be bigger and will add more stuff (thumbnail, optimization, possibility to deploy and place item frame in creative, creating interactive map that can run a command if you click on a specific frame...). +Despite the changes to zLib we have a lot of things to refactor in order to keep version older than 1.15 working. +Backcompatibility is dropped for now but in the future we will try to bring it back, (use 4.0 pre1 for now :( ). +The new features added to ImageOnMap for the 4.0 are: +- You can now place a map on the ground or on a ceilling. +- Fixed a bug where UTf8 char got bugged +- Fixed bug with splattermap that throw an exception +- Fixed renderer issues when putting a map other player don't see the bottom left corner +- Added Russian and German (thx to Danechek and to ...) +- Compatible with 1.15 (pre2) ## Data collection We use metrics to collect basic information about the usage of this plugin. This can be disabled by setting `collect-data` to false in `config.yml`. diff --git a/licenseheader.txt b/licenseheader.txt index 4f75de8..e5d7d76 100644 --- a/licenseheader.txt +++ b/licenseheader.txt @@ -1,21 +1,39 @@ <#if licenseFirst??> ${licenseFirst} -${licensePrefix}Copyright (C) 2013 Moribus -${licensePrefix}Copyright (C) 2015 ProkopyL +${licensePrefix}Copyright or © or Copr. Moribus (2013) +${licensePrefix}Copyright or © or Copr. ProkopyL (2015) +${licensePrefix}Copyright or © or Copr. Amaury Carrade (2016 – 2020) +${licensePrefix}Copyright or © or Copr. Vlammar (2019 – 2020) ${licensePrefix?replace(" +$", "", "r")} -${licensePrefix}This program is free software: you can redistribute it and/or modify -${licensePrefix}it under the terms of the GNU General Public License as published by -${licensePrefix}the Free Software Foundation, either version 3 of the License, or -${licensePrefix}(at your option) any later version. +${licensePrefix}This software is a computer program whose purpose is to allow insertion of +${licensePrefix}custom images in a Minecraft word. ${licensePrefix?replace(" +$", "", "r")} -${licensePrefix}This program is distributed in the hope that it will be useful, -${licensePrefix}but WITHOUT ANY WARRANTY; without even the implied warranty of -${licensePrefix}MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -${licensePrefix}GNU General Public License for more details. +${licensePrefix}This software is governed by the CeCILL-B license under French law and +${licensePrefix}abiding by the rules of distribution of free software. You can use, +${licensePrefix}modify and/ or redistribute the software under the terms of the CeCILL-B +${licensePrefix}license as circulated by CEA, CNRS and INRIA at the following URL +${licensePrefix}"http://www.cecill.info". ${licensePrefix?replace(" +$", "", "r")} -${licensePrefix}You should have received a copy of the GNU General Public License -${licensePrefix}along with this program. If not, see . +${licensePrefix}As a counterpart to the access to the source code and rights to copy, +${licensePrefix}modify and redistribute granted by the license, users are provided only +${licensePrefix}with a limited warranty and the software's author, the holder of the +${licensePrefix}economic rights, and the successive licensors have only limited +${licensePrefix}liability. +${licensePrefix?replace(" +$", "", "r")} +${licensePrefix}In this respect, the user's attention is drawn to the risks associated +${licensePrefix}with loading, using, modifying and/or developing or reproducing the +${licensePrefix}software by the user in light of its specific status of free software, +${licensePrefix}that may mean that it is complicated to manipulate, and that also +${licensePrefix}therefore means that it is reserved for developers and experienced +${licensePrefix}professionals having in-depth computer knowledge. Users are therefore +${licensePrefix}encouraged to load and test the software's suitability as regards their +${licensePrefix}requirements in conditions enabling the security of their systems and/or +${licensePrefix}data to be ensured and, more generally, to use and operate it in the +${licensePrefix}same conditions as regards security. +${licensePrefix?replace(" +$", "", "r")} +${licensePrefix}The fact that you are presently reading this means that you have had +${licensePrefix}knowledge of the CeCILL-B license and that you accept its terms. <#if licenseLast??> ${licenseLast} - + diff --git a/pom.xml b/pom.xml index df341f9..90e8790 100644 --- a/pom.xml +++ b/pom.xml @@ -3,13 +3,13 @@ 4.0.0 fr.moribus ImageOnMap - 3.1 + 4.0 jar UTF-8 - 1.7 - 1.7 + 1.8 + 1.8 @@ -17,11 +17,12 @@ org.apache.maven.plugins maven-shade-plugin - 2.3 + 2.4 fr.zcraft:zlib + org.bstats:bstats-bukkit @@ -29,7 +30,12 @@ fr.zcraft.zlib fr.moribus.imageonmap + + org.bstats + fr.moribus.imageonmap + + true @@ -46,24 +52,37 @@ spigot-repo - https://hub.spigotmc.org/nexus/content/groups/public/ + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ zDevelopers http://maven.carrade.eu/artifactory/snapshots + + + + CodeMC + https://repo.codemc.org/repository/maven-public + org.bukkit bukkit - 1.8.3-R0.1-SNAPSHOT + 1.13.2-R0.1-SNAPSHOT fr.zcraft zlib - 0.99-SNAPSHOT + 1.0-SNAPSHOT + compile + + + org.bstats + bstats-bukkit + 1.5 + compile diff --git a/src/main/java/fr/moribus/imageonmap/ImageOnMap.java b/src/main/java/fr/moribus/imageonmap/ImageOnMap.java index f16aa90..2c1361d 100644 --- a/src/main/java/fr/moribus/imageonmap/ImageOnMap.java +++ b/src/main/java/fr/moribus/imageonmap/ImageOnMap.java @@ -1,30 +1,42 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 fr.moribus.imageonmap.commands.maptool.DeleteCommand; -import fr.moribus.imageonmap.commands.maptool.ExploreCommand; -import fr.moribus.imageonmap.commands.maptool.GetCommand; -import fr.moribus.imageonmap.commands.maptool.GetRemainingCommand; -import fr.moribus.imageonmap.commands.maptool.ListCommand; -import fr.moribus.imageonmap.commands.maptool.MigrateCommand; -import fr.moribus.imageonmap.commands.maptool.NewCommand; +import fr.moribus.imageonmap.commands.maptool.*; import fr.moribus.imageonmap.image.ImageIOExecutor; import fr.moribus.imageonmap.image.ImageRendererExecutor; import fr.moribus.imageonmap.image.MapInitEvent; @@ -37,6 +49,8 @@ import fr.zcraft.zlib.components.gui.Gui; import fr.zcraft.zlib.components.i18n.I18n; import fr.zcraft.zlib.core.ZPlugin; import fr.zcraft.zlib.tools.PluginLogger; +import fr.zcraft.zlib.tools.UpdateChecker; +import org.bstats.bukkit.Metrics; import java.io.File; import java.io.IOException; @@ -46,7 +60,7 @@ public final class ImageOnMap extends ZPlugin static private final String IMAGES_DIRECTORY_NAME = "images"; static private final String MAPS_DIRECTORY_NAME = "maps"; static private ImageOnMap plugin; - + private File imagesDirectory; private final File mapsDirectory; @@ -64,7 +78,7 @@ public final class ImageOnMap extends ZPlugin public File getImagesDirectory() {return imagesDirectory;} public File getMapsDirectory() {return mapsDirectory;} - public File getImageFile(short mapID) + public File getImageFile(int mapID) { return new File(imagesDirectory, "map"+mapID+".png"); } @@ -79,7 +93,7 @@ public final class ImageOnMap extends ZPlugin imagesDirectory = checkPluginDirectory(imagesDirectory, V3Migrator.getOldImagesDirectory(this)); checkPluginDirectory(mapsDirectory); } - catch(IOException ex) + catch(final IOException ex) { PluginLogger.error("FATAL: " + ex.getMessage()); this.setEnabled(false); @@ -91,7 +105,6 @@ public final class ImageOnMap extends ZPlugin loadComponents(I18n.class, Gui.class, Commands.class, PluginConfiguration.class, ImageIOExecutor.class, ImageRendererExecutor.class); //Init all the things ! - MetricsLite.startMetrics(); I18n.setPrimaryLocale(PluginConfiguration.LANG.get()); MapManager.init(); @@ -111,6 +124,19 @@ public final class ImageOnMap extends ZPlugin Commands.registerShortcut("maptool", NewCommand.class, "tomap"); Commands.registerShortcut("maptool", ExploreCommand.class, "maps"); + + if (PluginConfiguration.CHECK_FOR_UPDATES.get()) + { + UpdateChecker.boot("imageonmap.26585"); + } + + if (PluginConfiguration.COLLECT_DATA.get()) + { + final Metrics metrics = new Metrics(this); + + metrics.addCustomChart(new Metrics.SingleLineChart("rendered-images", MapManager::getImagesCount)); + metrics.addCustomChart(new Metrics.SingleLineChart("used-minecraft-maps", MapManager::getMapCount)); + } } @Override diff --git a/src/main/java/fr/moribus/imageonmap/MetricsLite.java b/src/main/java/fr/moribus/imageonmap/MetricsLite.java deleted file mode 100644 index c742518..0000000 --- a/src/main/java/fr/moribus/imageonmap/MetricsLite.java +++ /dev/null @@ -1,528 +0,0 @@ -package fr.moribus.imageonmap; - -/* -* Copyright 2011-2013 Tyler Blair. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and contributors and should not be interpreted as representing official policies, -* either expressed or implied, of anybody else. -*/ - -import fr.zcraft.zlib.tools.PluginLogger; -import org.bukkit.Bukkit; -import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.scheduler.BukkitTask; - -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.net.Proxy; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLEncoder; -import java.util.UUID; -import java.util.zip.GZIPOutputStream; - -public class MetricsLite -{ - /** - * Starts MetricsLite, unless disabled in config - */ - static public void startMetrics() - { - if(!PluginConfiguration.COLLECT_DATA.get()) return; - - try - { - MetricsLite metrics = new MetricsLite(ImageOnMap.getPlugin()); - metrics.start(); - } - catch (IOException e) - { - PluginLogger.error("Failed to start MetricsLite", e); - } - } - - /** -* The current revision number -*/ - private final static int REVISION = 7; - - /** -* The base url of the metrics domain -*/ - private static final String BASE_URL = "http://report.mcstats.org"; - - /** -* The url used to report a server's status -*/ - private static final String REPORT_URL = "/plugin/%s"; - - /** -* Interval of time to ping (in minutes) -*/ - private final static int PING_INTERVAL = 15; - - /** -* The plugin this metrics submits for -*/ - private final Plugin plugin; - - /** -* The plugin configuration file -*/ - private final YamlConfiguration configuration; - - /** -* The plugin configuration file -*/ - private final File configurationFile; - - /** -* Unique server id -*/ - private final String guid; - - /** -* Debug mode -*/ - private final boolean debug; - - /** -* Lock for synchronization -*/ - private final Object optOutLock = new Object(); - - /** -* Id of the scheduled task -*/ - private volatile BukkitTask task = null; - - public MetricsLite(Plugin plugin) throws IOException { - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null"); - } - - this.plugin = plugin; - - // load the config - configurationFile = getConfigFile(); - configuration = YamlConfiguration.loadConfiguration(configurationFile); - - // add some defaults - configuration.addDefault("opt-out", false); - configuration.addDefault("guid", UUID.randomUUID().toString()); - configuration.addDefault("debug", false); - - // Do we need to create the file? - if (configuration.get("guid", null) == null) { - configuration.options().header("http://mcstats.org").copyDefaults(true); - configuration.save(configurationFile); - } - - // Load the guid then - guid = configuration.getString("guid"); - debug = configuration.getBoolean("debug", false); - } - - /** -* Start measuring statistics. This will immediately create an async repeating task as the plugin and send -* the initial data to the metrics backend, and then after that it will post in increments of -* PING_INTERVAL * 1200 ticks. -* -* @return True if statistics measuring is running, otherwise false. -*/ - public boolean start() { - synchronized (optOutLock) { - // Did we opt out? - if (isOptOut()) { - return false; - } - - // Is metrics already running? - if (task != null) { - return true; - } - - // Begin hitting the server with glorious data - task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { - - private boolean firstPost = true; - - @Override - public void run() { - try { - // This has to be synchronized or it can collide with the disable method. - synchronized (optOutLock) { - // Disable Task, if it is running and the server owner decided to opt-out - if (isOptOut() && task != null) { - task.cancel(); - task = null; - } - } - - // We use the inverse of firstPost because if it is the first time we are posting, - // it is not a interval ping, so it evaluates to FALSE - // Each time thereafter it will evaluate to TRUE, i.e PING! - postPlugin(!firstPost); - - // After the first post we set firstPost to false - // Each post thereafter will be a ping - firstPost = false; - } catch (IOException e) { - if (debug) { - PluginLogger.warning("[Metrics] ", e); - } - } - } - }, 0, PING_INTERVAL * 1200); - - return true; - } - } - - /** -* Has the server owner denied plugin metrics? -* -* @return true if metrics should be opted out of it -*/ - public boolean isOptOut() { - synchronized (optOutLock) { - try { - // Reload the metrics file - configuration.load(getConfigFile()); - } catch (IOException | InvalidConfigurationException ex) { - if (debug) { - PluginLogger.info("[Metrics] " + ex.getMessage()); - } - return true; - } - return configuration.getBoolean("opt-out", false); - } - } - - /** -* Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. -* -* @throws java.io.IOException -*/ - public void enable() throws IOException { - // This has to be synchronized or it can collide with the check in the task. - synchronized (optOutLock) { - // Check if the server owner has already set opt-out, if not, set it. - if (isOptOut()) { - configuration.set("opt-out", false); - configuration.save(configurationFile); - } - - // Enable Task, if it is not running - if (task == null) { - start(); - } - } - } - - /** -* Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. -* -* @throws java.io.IOException -*/ - public void disable() throws IOException { - // This has to be synchronized or it can collide with the check in the task. - synchronized (optOutLock) { - // Check if the server owner has already set opt-out, if not, set it. - if (!isOptOut()) { - configuration.set("opt-out", true); - configuration.save(configurationFile); - } - - // Disable Task, if it is running - if (task != null) { - task.cancel(); - task = null; - } - } - } - - /** -* Gets the File object of the config file that should be used to store data such as the GUID and opt-out status -* -* @return the File object for the config file -*/ - public final File getConfigFile() { - // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use - // is to abuse the plugin object we already have - // plugin.getDataFolder() => base/plugins/PluginA/ - // pluginsFolder => base/plugins/ - // The base is not necessarily relative to the startup directory. - File pluginsFolder = plugin.getDataFolder().getParentFile(); - - // return => base/plugins/PluginMetrics/config.yml - return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml"); - } - - /** -* Generic method that posts a plugin to the metrics website -*/ - private void postPlugin(boolean isPing) throws IOException { - // Server software specific section - PluginDescriptionFile description = plugin.getDescription(); - String pluginName = description.getName(); - boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled - String pluginVersion = description.getVersion(); - String serverVersion = Bukkit.getVersion(); - int playersOnline = Bukkit.getServer().getOnlinePlayers().size(); - - // END server software specific section -- all code below does not use any code outside of this class / Java - - // Construct the post data - StringBuilder json = new StringBuilder(1024); - json.append('{'); - - // The plugin's description file containg all of the plugin data such as name, version, author, etc - appendJSONPair(json, "guid", guid); - appendJSONPair(json, "plugin_version", pluginVersion); - appendJSONPair(json, "server_version", serverVersion); - appendJSONPair(json, "players_online", Integer.toString(playersOnline)); - - // New data as of R6 - String osname = System.getProperty("os.name"); - String osarch = System.getProperty("os.arch"); - String osversion = System.getProperty("os.version"); - String java_version = System.getProperty("java.version"); - int coreCount = Runtime.getRuntime().availableProcessors(); - - // normalize os arch .. amd64 -> x86_64 - if (osarch.equals("amd64")) { - osarch = "x86_64"; - } - - appendJSONPair(json, "osname", osname); - appendJSONPair(json, "osarch", osarch); - appendJSONPair(json, "osversion", osversion); - appendJSONPair(json, "cores", Integer.toString(coreCount)); - appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0"); - appendJSONPair(json, "java_version", java_version); - - // If we're pinging, append it - if (isPing) { - appendJSONPair(json, "ping", "1"); - } - - // close json - json.append('}'); - - // Create the url - URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); - - // Connect to the website - URLConnection connection; - - // Mineshafter creates a socks proxy, so we can safely bypass it - // It does not reroute POST requests so we need to go around it - if (isMineshafterPresent()) { - connection = url.openConnection(Proxy.NO_PROXY); - } else { - connection = url.openConnection(); - } - - - byte[] uncompressed = json.toString().getBytes(); - byte[] compressed = gzip(json.toString()); - - // Headers - connection.addRequestProperty("User-Agent", "MCStats/" + REVISION); - connection.addRequestProperty("Content-Type", "application/json"); - connection.addRequestProperty("Content-Encoding", "gzip"); - connection.addRequestProperty("Content-Length", Integer.toString(compressed.length)); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - - connection.setDoOutput(true); - - if (debug) { - System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length); - } - - // Write the data - OutputStream os = connection.getOutputStream(); - os.write(compressed); - os.flush(); - - // Now read the response - final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); - String response = reader.readLine(); - - // close resources - os.close(); - reader.close(); - - if (response == null || response.startsWith("ERR") || response.startsWith("7")) { - if (response == null) { - response = "null"; - } else if (response.startsWith("7")) { - response = response.substring(response.startsWith("7,") ? 2 : 1); - } - - throw new IOException(response); - } - } - - /** -* GZip compress a string of bytes -* -* @param input -* @return -*/ - public static byte[] gzip(String input) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - GZIPOutputStream gzos = null; - - try { - gzos = new GZIPOutputStream(baos); - gzos.write(input.getBytes("UTF-8")); - } catch (IOException e) { - PluginLogger.error("MetricsLite GZIP error : ", e); - } finally { - if (gzos != null) try { - gzos.close(); - } catch (IOException ignore) { - } - } - - return baos.toByteArray(); - } - - /** -* Check if mineshafter is present. If it is, we need to bypass it to send POST requests -* -* @return true if mineshafter is installed on the server -*/ - private boolean isMineshafterPresent() { - try { - Class.forName("mineshafter.MineServer"); - return true; - } catch (Exception e) { - return false; - } - } - - /** -* Appends a json encoded key/value pair to the given string builder. -* -* @param json -* @param key -* @param value -* @throws UnsupportedEncodingException -*/ - private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException { - boolean isValueNumeric = false; - - try { - if (value.equals("0") || !value.endsWith("0")) { - Double.parseDouble(value); - isValueNumeric = true; - } - } catch (NumberFormatException e) { - isValueNumeric = false; - } - - if (json.charAt(json.length() - 1) != '{') { - json.append(','); - } - - json.append(escapeJSON(key)); - json.append(':'); - - if (isValueNumeric) { - json.append(value); - } else { - json.append(escapeJSON(value)); - } - } - - /** -* Escape a string to create a valid JSON string -* -* @param text -* @return -*/ - private static String escapeJSON(String text) { - StringBuilder builder = new StringBuilder(); - - builder.append('"'); - for (int index = 0; index < text.length(); index++) { - char chr = text.charAt(index); - - switch (chr) { - case '"': - case '\\': - builder.append('\\'); - builder.append(chr); - break; - case '\b': - builder.append("\\b"); - break; - case '\t': - builder.append("\\t"); - break; - case '\n': - builder.append("\\n"); - break; - case '\r': - builder.append("\\r"); - break; - default: - if (chr < ' ') { - String t = "000" + Integer.toHexString(chr); - builder.append("\\u"); - builder.append(t.substring(t.length() - 4)); - } else { - builder.append(chr); - } - break; - } - } - builder.append('"'); - - return builder.toString(); - } - - /** -* Encode text as UTF-8 -* -* @param text the text to encode -* @return the encoded text, as UTF-8 -*/ - private static String urlEncode(final String text) throws UnsupportedEncodingException { - return URLEncoder.encode(text, "UTF-8"); - } - -} \ No newline at end of file diff --git a/src/main/java/fr/moribus/imageonmap/Permissions.java b/src/main/java/fr/moribus/imageonmap/Permissions.java index abaa110..69c6858 100644 --- a/src/main/java/fr/moribus/imageonmap/Permissions.java +++ b/src/main/java/fr/moribus/imageonmap/Permissions.java @@ -1,7 +1,11 @@ /* - * Copyright or © or Copr. AmauryCarrade (2015) + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * http://amaury.carrade.eu + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * * 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, diff --git a/src/main/java/fr/moribus/imageonmap/PluginConfiguration.java b/src/main/java/fr/moribus/imageonmap/PluginConfiguration.java index 3dff18e..bf74ba9 100644 --- a/src/main/java/fr/moribus/imageonmap/PluginConfiguration.java +++ b/src/main/java/fr/moribus/imageonmap/PluginConfiguration.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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; @@ -32,6 +50,15 @@ public final class PluginConfiguration extends Configuration static public ConfigurationItem COLLECT_DATA = item("collect-data", true); + static public ConfigurationItem CHECK_FOR_UPDATES = item("check-for-updates", true); + static public ConfigurationItem MAP_GLOBAL_LIMIT = item("map-global-limit", 0, "Limit-map-by-server"); static public ConfigurationItem MAP_PLAYER_LIMIT = item("map-player-limit", 0, "Limit-map-by-player"); + + static public ConfigurationItem SAVE_FULL_IMAGE = item("save-full-image", true); + + + static public ConfigurationItem LIMIT_SIZE_X = item("limit-map-size-x", 0); + static public ConfigurationItem LIMIT_SIZE_Y = item("limit-map-size-y", 0); + } diff --git a/src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java b/src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java index 4497d8e..b3203b4 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.commands; diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java index 12ac5c9..a2516f1 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.commands.maptool; diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java index 34f0ad2..d4bac06 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.commands.maptool; diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java index 6480fac..4da3c9a 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java @@ -1,32 +1,51 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.commands.maptool; +import java.util.List; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + 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; @CommandInfo (name = "get") public class GetCommand extends IoMCommand diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java index 00adb00..0da8207 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.commands.maptool; diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java index 1019c7b..8ff19d1 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.commands.maptool; @@ -74,7 +92,7 @@ public class ListCommand extends IoMCommand .then(map.getId()) .color(ChatColor.WHITE) .command(GetCommand.class, map.getId()) - .hover(new ItemStackBuilder(Material.MAP) + .hover(new ItemStackBuilder(Material.FILLED_MAP) .title(ChatColor.GREEN + "" + ChatColor.BOLD + map.getName()) .lore(ChatColor.GRAY + map.getId() + ", " + size) .lore("") diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java index e1b7b98..ac0be3e 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.commands.maptool; diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java index facae31..daebc02 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.commands.maptool; @@ -21,12 +39,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.moribus.imageonmap.map.PosterMap; 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 fr.zcraft.zlib.tools.text.ActionBar; +import fr.zcraft.zlib.tools.text.MessageSender; +import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -40,8 +63,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.")); @@ -57,34 +81,49 @@ 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() - { - @Override - public void finished(ImageMap result) - { - player.sendMessage(I.t("{cst}Rendering finished!")); - if(result.give(player)) - { - info(I.t("The rendered map was too big to fit in your inventory.")); - info(I.t("Use '/maptool getremaining' to get the remaining maps.")); + try { + + + ActionBar.sendPermanentMessage(player, ChatColor.DARK_GREEN + I.t("Rendering...")); + ImageRendererExecutor.render(url, scaling, player.getUniqueId(), width, height, new WorkerCallback() { + @Override + public void finished(ImageMap result) { + ActionBar.removeMessage(player); + MessageSender.sendActionBarMessage(player, ChatColor.DARK_GREEN + I.t("Rendering finished!")); + + if (result.give(player) && (result instanceof PosterMap && !((PosterMap) result).hasColumnData())) { + info(I.t("The rendered map was too big to fit in your inventory.")); + info(I.t("Use '/maptool getremaining' to get the remaining maps.")); + } } - } - @Override - public void errored(Throwable exception) - { - player.sendMessage(I.t("{ce}Map rendering failed: {0}", exception.getMessage())); + @Override + public void errored(Throwable exception) { + player.sendMessage(I.t("{ce}Map rendering failed: {0}", exception.getMessage())); - PluginLogger.warning("Rendering from {0} failed: {1}: {2}", - player.getName(), - exception.getClass().getCanonicalName(), - exception.getMessage()); - } - }); + PluginLogger.warning("Rendering from {0} failed: {1}: {2}", + player.getName(), + exception.getClass().getCanonicalName(), + exception.getMessage()); + } + }); + } + //Added to fix bug with rendering displaying after error + finally { + ActionBar.removeMessage(player); + } } @Override diff --git a/src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java b/src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java index 706b627..b60768d 100644 --- a/src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java +++ b/src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.gui; @@ -29,13 +47,9 @@ import fr.zcraft.zlib.components.i18n.I; import fr.zcraft.zlib.tools.PluginLogger; import fr.zcraft.zlib.tools.items.ItemStackBuilder; import org.bukkit.ChatColor; -import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.material.Dye; -import java.util.Arrays; import java.util.Random; @@ -106,7 +120,7 @@ public class ConfirmDeleteMapGui extends ActionGui /* ** Item representation of the image being deleted ** */ - action("", 13, new ItemStackBuilder(Material.EMPTY_MAP) + action("", 13, new ItemStackBuilder(Material.FILLED_MAP) /// The title of the map deletion item .title(I.t(getPlayerLocale(), "{red}You're about to destroy this map...")) /// The end, in the lore, of a title starting with “You're about to destroy this map...”. @@ -134,32 +148,21 @@ public class ConfirmDeleteMapGui extends ActionGui private ItemStack createDeleteSubButton() { - // Orange? Nooo. In the real world this is red. True story. - return createSubButton(DyeColor.ORANGE, ChatColor.RED + "Delete the map", DELETE_MESSAGES); + return createSubButton(Material.RED_STAINED_GLASS_PANE, ChatColor.RED + "Delete the map", DELETE_MESSAGES); } private ItemStack createCancelSubButton() { - // YES. Purple = lime. BECAUSE. Just accept it. - return createSubButton(DyeColor.PURPLE, ChatColor.GREEN + "Cancel", CANCEL_MESSAGES); + return createSubButton(Material.LIME_STAINED_GLASS_PANE, ChatColor.GREEN + "Cancel", CANCEL_MESSAGES); } - private ItemStack createSubButton(DyeColor color, String title, String[] messages) + private ItemStack createSubButton(Material color, String title, String[] messages) { - Dye pane = new Dye(Material.STAINED_GLASS_PANE); - pane.setColor(color); - - ItemStack subButton = pane.toItemStack(1); - ItemMeta meta = subButton.getItemMeta(); - - meta.setDisplayName(title); - meta.setLore(Arrays.asList( - "", - ChatColor.GRAY + messages[random.nextInt(messages.length)] - )); - - subButton.setItemMeta(meta); - return subButton; + return new ItemStackBuilder(color) + .title(title) + .loreSeparator() + .longLore(ChatColor.GRAY + messages[random.nextInt(messages.length)]) + .item(); } @GuiAction ("cancel") diff --git a/src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java b/src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java index f7e48ce..465508e 100644 --- a/src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java +++ b/src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.gui; @@ -35,7 +53,7 @@ import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -public class MapDetailGui extends ExplorerGui +public class MapDetailGui extends ExplorerGui { private final ImageMap map; @@ -47,7 +65,7 @@ public class MapDetailGui extends ExplorerGui @Override protected ItemStack getViewItem(int x, int y) { - final Material partMaterial = y % 2 == x % 2 ? Material.EMPTY_MAP : Material.PAPER; + final Material partMaterial = y % 2 == x % 2 ? Material.MAP : Material.PAPER; final ItemStackBuilder builder = new ItemStackBuilder(partMaterial) .title(I.t(getPlayerLocale(), "{green}Map part")) @@ -61,10 +79,10 @@ public class MapDetailGui extends ExplorerGui } @Override - protected ItemStack getViewItem(Short mapId) + protected ItemStack getViewItem(Integer mapId) { final int index = ((PosterMap) map).getIndex(mapId); - final Material partMaterial = index % 2 == 0 ? Material.EMPTY_MAP : Material.PAPER; + final Material partMaterial = index % 2 == 0 ? Material.MAP : Material.PAPER; final ItemStackBuilder builder = new ItemStackBuilder(partMaterial) .title(I.t(getPlayerLocale(), "{green}Map part")) @@ -95,7 +113,7 @@ public class MapDetailGui extends ExplorerGui } @Override - protected ItemStack getPickedUpItem(Short mapId) + protected ItemStack getPickedUpItem(Integer mapId) { if (!Permissions.GET.grantedTo(getPlayer())) return null; @@ -149,7 +167,7 @@ public class MapDetailGui extends ExplorerGui if (canRename) { - action("rename", renameSlot, new ItemStackBuilder(Material.BOOK_AND_QUILL) + action("rename", renameSlot, new ItemStackBuilder(Material.WRITABLE_BOOK) .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.")) ); diff --git a/src/main/java/fr/moribus/imageonmap/gui/MapListGui.java b/src/main/java/fr/moribus/imageonmap/gui/MapListGui.java index 51dc27d..8d8053d 100644 --- a/src/main/java/fr/moribus/imageonmap/gui/MapListGui.java +++ b/src/main/java/fr/moribus/imageonmap/gui/MapListGui.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.gui; @@ -29,8 +47,10 @@ import fr.zcraft.zlib.components.gui.ExplorerGui; import fr.zcraft.zlib.components.gui.Gui; import fr.zcraft.zlib.components.i18n.I; import fr.zcraft.zlib.tools.items.ItemStackBuilder; +import org.bukkit.Color; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.MapMeta; public class MapListGui extends ExplorerGui @@ -58,34 +78,41 @@ public class MapListGui extends ExplorerGui mapDescription = I.t(getPlayerLocale(), "{white}Poster map ({0} parts)", poster.getMapCount()); } } - ItemStackBuilder builder = new ItemStackBuilder(Material.MAP) + + ItemStackBuilder builder = new ItemStackBuilder(Material.FILLED_MAP) /// Displayed title of a map on the list GUI - .title(I.t(getPlayerLocale(), "{green}{bold}{0}", map.getName())) + .title(I.tl(getPlayerLocale(), "{green}{bold}{0}", map.getName())) .lore(mapDescription) .loreLine() /// 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.tl(getPlayerLocale(), "{gray}Map ID: {0}", map.getId())) .loreLine(); if (Permissions.GET.grantedTo(getPlayer())) - builder.lore(I.t(getPlayerLocale(), "{gray}» {white}Left-click{gray} to get this map")); + builder.lore(I.tl(getPlayerLocale(), "{gray}» {white}Left-click{gray} to get this map")); - builder.lore(I.t(getPlayerLocale(), "{gray}» {white}Right-click{gray} for details and options")); + builder.lore(I.tl(getPlayerLocale(), "{gray}» {white}Right-click{gray} for details and options")); - return builder.item(); + final ItemStack mapItem = builder.item(); + + final MapMeta meta = (MapMeta) mapItem.getItemMeta(); + meta.setColor(Color.GREEN); + mapItem.setItemMeta(meta); + + return mapItem; } @Override protected ItemStack getEmptyViewItem() { ItemStackBuilder builder = new ItemStackBuilder(Material.BARRIER) - .title(I.t(getPlayerLocale(), "{red}You don't have any map.")); + .title(I.tl(getPlayerLocale(), "{red}You don't have any map.")); if (Permissions.NEW.grantedTo(getPlayer())) - builder.longLore(I.t(getPlayerLocale(), "{gray}Get started by creating a new one using {white}/tomap [resize]{gray}!")); + builder.longLore(I.tl(getPlayerLocale(), "{gray}Get started by creating a new one using {white}/tomap [resize]{gray}!")); else - builder.longLore(I.t(getPlayerLocale(), "{gray}Unfortunately, you are not allowed to create one.")); + builder.longLore(I.tl(getPlayerLocale(), "{gray}Unfortunately, you are not allowed to create one.")); return builder.item(); } @@ -104,7 +131,7 @@ public class MapListGui extends ExplorerGui if (map instanceof SingleMap) { - return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName()); + return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName(), false); } else if (map instanceof PosterMap) { @@ -128,7 +155,7 @@ public class MapListGui extends ExplorerGui setData(maps); /// The maps list GUI title - setTitle(I.t(getPlayerLocale(), "{black}Your maps {reset}({0})", maps.length)); + setTitle(I.tl(getPlayerLocale(), "{black}Your maps {reset}({0})", maps.length)); setKeepHorizontalScrollingSpace(true); diff --git a/src/main/java/fr/moribus/imageonmap/image/ImageIOExecutor.java b/src/main/java/fr/moribus/imageonmap/image/ImageIOExecutor.java index 64f2045..7ff54ce 100644 --- a/src/main/java/fr/moribus/imageonmap/image/ImageIOExecutor.java +++ b/src/main/java/fr/moribus/imageonmap/image/ImageIOExecutor.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.image; @@ -35,6 +53,7 @@ public class ImageIOExecutor extends Worker { static public void loadImage(final File file, final Renderer mapRenderer) { + submitQuery(new WorkerRunnable() { @Override @@ -60,12 +79,12 @@ public class ImageIOExecutor extends Worker }); } - static public void saveImage(short mapID, BufferedImage image) + static public void saveImage(int mapID, BufferedImage image) { saveImage(ImageOnMap.getPlugin().getImageFile(mapID), image); } - static public void saveImage(short[] mapsIDs, PosterImage image) + static public void saveImage(int[] mapsIDs, PosterImage image) { for(int i = 0, c = mapsIDs.length; i < c; i++) { @@ -75,7 +94,7 @@ public class ImageIOExecutor extends Worker static public void deleteImage(ImageMap map) { - short[] mapsIDs = map.getMapsIDs(); + int[] mapsIDs = map.getMapsIDs(); for(int i = 0, c = mapsIDs.length; i < c; i++) { deleteImage(ImageOnMap.getPlugin().getImageFile(mapsIDs[i])); diff --git a/src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java b/src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java index 390ccdd..1112c0b 100644 --- a/src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java +++ b/src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java @@ -1,23 +1,42 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.image; +import fr.moribus.imageonmap.PluginConfiguration; import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.MapManager; import fr.zcraft.zlib.components.i18n.I; @@ -25,9 +44,9 @@ import fr.zcraft.zlib.components.worker.Worker; import fr.zcraft.zlib.components.worker.WorkerAttributes; import fr.zcraft.zlib.components.worker.WorkerCallback; import fr.zcraft.zlib.components.worker.WorkerRunnable; +import org.bukkit.Bukkit; import javax.imageio.ImageIO; -import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; @@ -38,11 +57,10 @@ import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.Future; - @WorkerAttributes (name = "Image Renderer", queriesMainThread = true) public class ImageRendererExecutor extends Worker { - static public void Render(final URL url, final boolean scaling, final UUID playerUUID, WorkerCallback callback) + static public void render(final URL url, final ImageUtils.ScalingType scaling, final UUID playerUUID, final int width, final int height, WorkerCallback callback) { submitQuery(new WorkerRunnable() { @@ -64,54 +82,67 @@ public class ImageRendererExecutor extends Worker final BufferedImage image = ImageIO.read(stream); 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.get() > 0 || PluginConfiguration.LIMIT_SIZE_Y.get() > 0) && !Bukkit.getPlayer(playerUUID).hasPermission("imageonmap.bypasssize")) { + if(PluginConfiguration.LIMIT_SIZE_X.get() > 0) { + if(image.getWidth() > PluginConfiguration.LIMIT_SIZE_X.get()) throw new IOException(I.t("The image is too wide!")); + } + if(PluginConfiguration.LIMIT_SIZE_Y.get() > 0) { + if(image.getHeight() > PluginConfiguration.LIMIT_SIZE_Y.get()) throw new IOException(I.t("The image is too tall!")); + } + } + + if(scaling != ImageUtils.ScalingType.NONE && height <= 1 && width <= 1) { + return renderSingle(scaling.resize(image, ImageMap.WIDTH, ImageMap.HEIGHT), playerUUID); + } - if (scaling) return RenderSingle(image, playerUUID); - else return RenderPoster(image, playerUUID); + final BufferedImage resizedImage = scaling.resize(image, ImageMap.WIDTH * width, ImageMap.HEIGHT * height); + return renderPoster(resizedImage, playerUUID); + //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 futureMapID = submitToMainThread(new Callable() + final Future futureMapID = submitToMainThread(new Callable() { @Override - public Short call() throws Exception + public Integer call() throws Exception { return MapManager.getNewMapsIds(1)[0]; } }); - - final BufferedImage finalImage = ResizeImage(image, ImageMap.WIDTH, ImageMap.HEIGHT); - - final short mapID = futureMapID.get(); - ImageIOExecutor.saveImage(mapID, finalImage); + + final int mapID = futureMapID.get(); + ImageIOExecutor.saveImage(mapID, image); submitToMainThread(new Callable() { @Override public Void call() throws Exception { - Renderer.installRenderer(finalImage, mapID); + Renderer.installRenderer(image, mapID); return null; } - }); return MapManager.createMap(playerUUID, mapID); } - static private ImageMap RenderPoster(final BufferedImage image, final UUID playerUUID) throws Throwable + static private ImageMap renderPoster(final BufferedImage image, final UUID playerUUID) throws Throwable { final PosterImage poster = new PosterImage(image); final int mapCount = poster.getImagesCount(); MapManager.checkMapLimit(mapCount, playerUUID); - final Future futureMapsIds = submitToMainThread(new Callable() + final Future futureMapsIds = submitToMainThread(new Callable() { @Override - public short[] call() throws Exception + public int[] call() throws Exception { return MapManager.getNewMapsIds(mapCount); } @@ -119,10 +150,14 @@ public class ImageRendererExecutor extends Worker poster.splitImages(); - final short[] mapsIDs = futureMapsIds.get(); + final int[] mapsIDs = futureMapsIds.get(); ImageIOExecutor.saveImage(mapsIDs, poster); + if(PluginConfiguration.SAVE_FULL_IMAGE.get()) { + ImageIOExecutor.saveImage(ImageMap.getFullImageFile(mapsIDs[0], mapsIDs[mapsIDs.length - 1]), image); + } + submitToMainThread(new Callable() { @Override @@ -136,33 +171,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; - } -} +} \ No newline at end of file diff --git a/src/main/java/fr/moribus/imageonmap/image/ImageUtils.java b/src/main/java/fr/moribus/imageonmap/image/ImageUtils.java new file mode 100644 index 0000000..560c657 --- /dev/null +++ b/src/main/java/fr/moribus/imageonmap/image/ImageUtils.java @@ -0,0 +1,133 @@ +/* + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) + * + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. + * + * 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.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; + } +} \ No newline at end of file diff --git a/src/main/java/fr/moribus/imageonmap/image/MapInitEvent.java b/src/main/java/fr/moribus/imageonmap/image/MapInitEvent.java index ca8e078..ef50037 100644 --- a/src/main/java/fr/moribus/imageonmap/image/MapInitEvent.java +++ b/src/main/java/fr/moribus/imageonmap/image/MapInitEvent.java @@ -1,43 +1,61 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.image; import fr.moribus.imageonmap.ImageOnMap; +import fr.moribus.imageonmap.map.MapManager; import fr.zcraft.zlib.core.ZLib; -import java.io.File; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.entity.Entity; +import org.bukkit.entity.HumanEntity; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPickupItemEvent; import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerItemHeldEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.map.MapView; +import java.io.File; public class MapInitEvent implements Listener { static public void init() @@ -54,7 +72,7 @@ public class MapInitEvent implements Listener for(Player player : Bukkit.getOnlinePlayers()) { - initMap(player.getItemInHand()); + initMap(player.getInventory().getItemInMainHand()); } } @@ -78,10 +96,10 @@ public class MapInitEvent implements Listener } @EventHandler - public void onPlayerPickup(PlayerPickupItemEvent event) + public void onPlayerPickup(EntityPickupItemEvent event) { - ItemStack item = event.getItem().getItemStack(); - initMap(item); + if (!(event.getEntity() instanceof HumanEntity)) return; + initMap(event.getItem().getItemStack()); } @EventHandler @@ -99,21 +117,23 @@ public class MapInitEvent implements Listener static public void initMap(ItemStack item) { - if (item != null && item.getType() == Material.MAP) + if (item != null && item.getType() == Material.FILLED_MAP) { - initMap(item.getDurability()); + initMap(MapManager.getMapIdFromItemStack(item)); } } - static public void initMap(short id) + static public void initMap(int id) { - initMap(Bukkit.getMap(id)); + initMap(Bukkit.getServer().getMap(id)); } static public void initMap(MapView map) { - if(map == null) return; - if(Renderer.isHandled(map)) return; + if(map == null) { + return;} + if(Renderer.isHandled(map)) { + return;} File imageFile = ImageOnMap.getPlugin().getImageFile(map.getId()); if(imageFile.isFile()) diff --git a/src/main/java/fr/moribus/imageonmap/image/PosterImage.java b/src/main/java/fr/moribus/imageonmap/image/PosterImage.java index 6924019..60589c0 100644 --- a/src/main/java/fr/moribus/imageonmap/image/PosterImage.java +++ b/src/main/java/fr/moribus/imageonmap/image/PosterImage.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.image; diff --git a/src/main/java/fr/moribus/imageonmap/image/Renderer.java b/src/main/java/fr/moribus/imageonmap/image/Renderer.java index 1aa306f..aa89e26 100644 --- a/src/main/java/fr/moribus/imageonmap/image/Renderer.java +++ b/src/main/java/fr/moribus/imageonmap/image/Renderer.java @@ -1,31 +1,50 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.image; import fr.zcraft.zlib.tools.PluginLogger; -import java.awt.image.BufferedImage; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.map.MapCanvas; import org.bukkit.map.MapRenderer; import org.bukkit.map.MapView; +import java.awt.image.BufferedImage; + public class Renderer extends MapRenderer { static public boolean isHandled(MapView map) @@ -38,7 +57,7 @@ public class Renderer extends MapRenderer return false; } - static public void installRenderer(PosterImage image, short[] mapsIds) + static public void installRenderer(PosterImage image, int[] mapsIds) { for(int i = 0; i < mapsIds.length; i++) { @@ -46,12 +65,12 @@ public class Renderer extends MapRenderer } } - static public void installRenderer(BufferedImage image, short mapID) + static public void installRenderer(BufferedImage image, int mapID) { MapView map = Bukkit.getMap(mapID); if(map == null) { - PluginLogger.warning("Could not install renderer for map {0} : the Minecraft map does not exist", mapID); + PluginLogger.warning("Could not install renderer for map {0}: the Minecraft map does not exist", mapID); } else { @@ -92,7 +111,6 @@ public class Renderer extends MapRenderer { //Render only once to avoid overloading the server if (image == null) return; - canvas.drawImage(0, 0, image); image = null; } diff --git a/src/main/java/fr/moribus/imageonmap/map/ImageMap.java b/src/main/java/fr/moribus/imageonmap/map/ImageMap.java index bd71fad..0c0bf9e 100644 --- a/src/main/java/fr/moribus/imageonmap/map/ImageMap.java +++ b/src/main/java/fr/moribus/imageonmap/map/ImageMap.java @@ -1,23 +1,42 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.map; +import fr.moribus.imageonmap.ImageOnMap; import fr.moribus.imageonmap.ui.MapItemManager; import fr.zcraft.zlib.components.i18n.I; import org.bukkit.Material; @@ -26,6 +45,7 @@ import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -47,7 +67,6 @@ public abstract class ImageMap implements ConfigurationSerializable private final UUID userUUID; private final Type mapType; private String name; - protected ImageMap(UUID userUUID, Type mapType) { this(userUUID, mapType, null, null); @@ -68,15 +87,15 @@ public abstract class ImageMap implements ConfigurationSerializable } - public abstract short[] getMapsIDs(); - public abstract boolean managesMap(short mapID); + public abstract int[] getMapsIDs(); + public abstract boolean managesMap(int mapID); public abstract int getMapCount(); public boolean managesMap(ItemStack item) { if(item == null) return false; - if(item.getType() != Material.MAP) return false; - return managesMap(item.getDurability()); + if(item.getType() != Material.FILLED_MAP) return false; + return managesMap(MapManager.getMapIdFromItemStack(item)); } public boolean give(Player player) @@ -84,6 +103,11 @@ public abstract class ImageMap implements ConfigurationSerializable return MapItemManager.give(player, this); } + public static File getFullImageFile(int mapIDstart, int mapIDend) + { + return new File(ImageOnMap.getPlugin().getImagesDirectory(), "_"+mapIDstart+"-"+mapIDend+".png"); + } + /* ====== Serialization methods ====== */ static public ImageMap fromConfig(Map map, UUID userUUID) throws InvalidConfigurationException diff --git a/src/main/java/fr/moribus/imageonmap/map/MapManager.java b/src/main/java/fr/moribus/imageonmap/map/MapManager.java index fa58f99..d06cf8c 100644 --- a/src/main/java/fr/moribus/imageonmap/map/MapManager.java +++ b/src/main/java/fr/moribus/imageonmap/map/MapManager.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.map; @@ -28,6 +46,8 @@ import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.MapMeta; import org.bukkit.scheduler.BukkitTask; import java.io.File; @@ -53,7 +73,7 @@ abstract public class MapManager if(autosaveTask != null) autosaveTask.cancel(); } - static public boolean managesMap(short mapID) + static public boolean managesMap(int mapID) { synchronized(playerMaps) { @@ -68,7 +88,7 @@ abstract public class MapManager static public boolean managesMap(ItemStack item) { if(item == null) return false; - if(item.getType() != Material.MAP) return false; + if(item.getType() != Material.FILLED_MAP) return false; synchronized(playerMaps) { @@ -80,16 +100,17 @@ abstract public class MapManager return false; } - static public ImageMap createMap(UUID playerUUID, short mapID) throws MapManagerException + static public ImageMap createMap(UUID playerUUID, int mapID) throws MapManagerException { ImageMap newMap = new SingleMap(playerUUID, mapID); addMap(newMap); return newMap; } - static public ImageMap createMap(PosterImage image, UUID playerUUID, short[] mapsIDs) throws MapManagerException + static public ImageMap createMap(PosterImage image, UUID playerUUID, int[] mapsIDs) throws MapManagerException { ImageMap newMap; + if(image.getImagesCount() == 1) { newMap = new SingleMap(playerUUID, mapsIDs[0]); @@ -102,15 +123,28 @@ abstract public class MapManager return newMap; } - static public short[] getNewMapsIds(int amount) + static public int[] getNewMapsIds(int amount) { - short[] mapsIds = new short[amount]; + int[] mapsIds = new int[amount]; for(int i = 0; i < amount; i++) { mapsIds[i] = Bukkit.createMap(Bukkit.getWorlds().get(0)).getId(); } return mapsIds; } + + /** + * Returns the map ID from an ItemStack + * @param item The item stack + * @return The map ID, or 0 if invalid. + */ + static public int getMapIdFromItemStack(final ItemStack item) + { + final ItemMeta meta = item.getItemMeta(); + if (!(meta instanceof MapMeta)) return 0; + + return ((MapMeta) meta).hasMapId() ? ((MapMeta) meta).getMapId() : 0; + } static public void addMap(ImageMap map) throws MapManagerException { @@ -173,7 +207,7 @@ abstract public class MapManager * @param mapId The ID of the Minecraft map. * @return The {@link ImageMap}. */ - static public ImageMap getMap(short mapId) + static public ImageMap getMap(int mapId) { synchronized(playerMaps) { @@ -204,8 +238,8 @@ abstract public class MapManager static public ImageMap getMap(ItemStack item) { if(item == null) return null; - if(item.getType() != Material.MAP) return null; - return getMap(item.getDurability()); + if(item.getType() != Material.FILLED_MAP) return null; + return getMap(getMapIdFromItemStack(item)); } static public void clear(Inventory inventory) @@ -306,13 +340,31 @@ abstract public class MapManager } return mapCount; } + + /** + * Returns the total number of images rendered by ImageOnMap. + * + * @return The count. + */ + static public int getImagesCount() + { + int imagesCount = 0; + synchronized(playerMaps) + { + for(PlayerMapStore tStore : playerMaps) + { + imagesCount += tStore.getImagesCount(); + } + } + return imagesCount; + } /** * Returns if the given map ID is valid and exists in the current save. * @param mapId the map ID. * @return true if the given map ID is valid and exists in the current save, false otherwise. */ - static public boolean mapIdExists(short mapId) + static public boolean mapIdExists(int mapId) { try { diff --git a/src/main/java/fr/moribus/imageonmap/map/MapManagerException.java b/src/main/java/fr/moribus/imageonmap/map/MapManagerException.java index 7fc3c49..60e9adf 100644 --- a/src/main/java/fr/moribus/imageonmap/map/MapManagerException.java +++ b/src/main/java/fr/moribus/imageonmap/map/MapManagerException.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.map; diff --git a/src/main/java/fr/moribus/imageonmap/map/PlayerMapStore.java b/src/main/java/fr/moribus/imageonmap/map/PlayerMapStore.java index 0c8d531..057c9e0 100644 --- a/src/main/java/fr/moribus/imageonmap/map/PlayerMapStore.java +++ b/src/main/java/fr/moribus/imageonmap/map/PlayerMapStore.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.map; @@ -50,7 +68,7 @@ public class PlayerMapStore implements ConfigurationSerializable this.playerUUID = playerUUID; } - public synchronized boolean managesMap(short mapID) + public synchronized boolean managesMap(int mapID) { for(ImageMap map : mapList) { @@ -62,7 +80,7 @@ public class PlayerMapStore implements ConfigurationSerializable public synchronized boolean managesMap(ItemStack item) { if(item == null) return false; - if(item.getType() != Material.MAP) return false; + if(item.getType() != Material.FILLED_MAP) return false; for(ImageMap map : mapList) { @@ -182,6 +200,11 @@ public class PlayerMapStore implements ConfigurationSerializable { return this.mapCount; } + + public synchronized int getImagesCount() + { + return this.mapList.size(); + } /* ****** Serializing ***** */ @@ -258,6 +281,7 @@ public class PlayerMapStore implements ConfigurationSerializable try { getToolConfig().save(mapsFile); + } catch (IOException ex) { diff --git a/src/main/java/fr/moribus/imageonmap/map/PosterMap.java b/src/main/java/fr/moribus/imageonmap/map/PosterMap.java index 37199ef..1c3690c 100644 --- a/src/main/java/fr/moribus/imageonmap/map/PosterMap.java +++ b/src/main/java/fr/moribus/imageonmap/map/PosterMap.java @@ -1,172 +1,198 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.map; +import org.bukkit.block.BlockFace; import org.bukkit.configuration.InvalidConfigurationException; import java.util.List; import java.util.Map; import java.util.UUID; -public class PosterMap extends ImageMap -{ - protected final short[] mapsIDs; - protected final int columnCount; - protected final int rowCount; - - public PosterMap(UUID userUUID, short[] mapsIDs, String id, String name, int columnCount, int rowCount) - { - super(userUUID, Type.POSTER, id, name); - this.mapsIDs = mapsIDs; - this.columnCount = Math.max(columnCount, 0); - this.rowCount = Math.max(rowCount, 0); - } - - public PosterMap(UUID userUUID, short[] mapsIDs, int columnCount, int rowCount) - { - this(userUUID, mapsIDs, null, null, columnCount, rowCount); - } - - @Override - public short[] getMapsIDs() - { - return mapsIDs; - } +public class PosterMap extends ImageMap { + protected final int[] mapsIDs; + protected final int columnCount; + protected final int rowCount; - @Override - public boolean managesMap(short mapID) - { - for(int i = 0; i < mapsIDs.length; i++) - { - if(mapsIDs[i] == mapID) return true; - } - - return false; - } + public PosterMap(UUID userUUID, int[] mapsIDs, String id, String name, int columnCount, int rowCount) { + super(userUUID, Type.POSTER, id, name); + this.mapsIDs = mapsIDs; + this.columnCount = Math.max(columnCount, 0); + this.rowCount = Math.max(rowCount, 0); + } - /* ====== Serialization methods ====== */ - - public PosterMap(Map map, UUID userUUID) throws InvalidConfigurationException - { - super(map, userUUID, Type.POSTER); - - columnCount = getFieldValue(map, "columns"); - rowCount = getFieldValue(map, "rows"); - - List idList = getFieldValue(map, "mapsIDs"); - mapsIDs = new short[idList.size()]; - for(int i = 0, c = idList.size(); i < c; i++) - { - mapsIDs[i] = (short) ((int) idList.get(i)); - } - } - - @Override - protected void postSerialize(Map map) - { - map.put("columns", columnCount); - map.put("rows", rowCount); - map.put("mapsIDs", mapsIDs); - } - - /* ====== Getters & Setters ====== */ - - /** - * Returns the amount of columns in the poster map - * @return The number of columns, or 0 if this data is missing - */ - public int getColumnCount() - { - return columnCount; - } - - /** - * Returns the amount of rows in the poster map - * @return The number of rows, or 0 if this data is missing - */ - public int getRowCount() - { - return rowCount; - } - - public int getColumnAt(int i) - { - if(columnCount == 0) return 0; - return (i % columnCount); - } - - public int getRowAt(int i) - { - if(columnCount == 0) return 0; - return (i / columnCount); - } - - public int getIndexAt(int col, int row) - { - return columnCount * row + col; - } + public PosterMap(UUID userUUID, int[] mapsIDs, int columnCount, int rowCount) { + this(userUUID, mapsIDs, null, null, columnCount, rowCount); + } - /** - * Returns the map id at the given column and line. - * - * @param x The x coordinate. Starts at 0. - * @param y The y coordinate. Starts at 0. - * @return The Minecraft map ID. - * - * @throws ArrayIndexOutOfBoundsException if the given coordinates are too big (out of the poster). - */ - public short getMapIdAt(int x, int y) - { - return mapsIDs[y * columnCount + x]; - } - - public short getMapIdAtReverseY(int index) - { - int x = index % (columnCount); - int y = index / (columnCount); - return getMapIdAt(x, rowCount - y - 1); - } - - public short getMapIdAt(int index) - { - return mapsIDs[index]; - } - - public boolean hasColumnData() - { - return rowCount != 0 && columnCount != 0; - } + @Override + public int[] getMapsIDs() { + return mapsIDs; + } - @Override - public int getMapCount() - { - return mapsIDs.length; - } - - public int getIndex(short mapID) - { - for(int i = 0; i < mapsIDs.length; i++) - { - if(mapsIDs[i] == mapID) return i; - } - - throw new IllegalArgumentException("Invalid map ID"); - } + @Override + public boolean managesMap(int mapID) { + for (int i = 0; i < mapsIDs.length; i++) { + if (mapsIDs[i] == mapID) + return true; + } + + return false; + } + + /* ====== Serialization methods ====== */ + + public PosterMap(Map map, UUID userUUID) throws InvalidConfigurationException { + super(map, userUUID, Type.POSTER); + + columnCount = getFieldValue(map, "columns"); + rowCount = getFieldValue(map, "rows"); + + List idList = getFieldValue(map, "mapsIDs"); + mapsIDs = new int[idList.size()]; + for (int i = 0, c = idList.size(); i < c; i++) { + mapsIDs[i] = idList.get(i); + } + } + + @Override + protected void postSerialize(Map map) { + map.put("columns", columnCount); + map.put("rows", rowCount); + map.put("mapsIDs", mapsIDs); + } + + /* ====== Getters & Setters ====== */ + + /** + * Returns the amount of columns in the poster map + * + * @return The number of columns, or 0 if this data is missing + */ + public int getColumnCount() { + return columnCount; + } + + /** + * Returns the amount of rows in the poster map + * + * @return The number of rows, or 0 if this data is missing + */ + public int getRowCount() { + return rowCount; + } + + public int getColumnAt(int i) { + if (columnCount == 0) + return 0; + return (i % columnCount); + } + + public int getRowAt(int i) { + if (columnCount == 0) + return 0; + return (i / columnCount); + } + + public int getIndexAt(int col, int row) { + return columnCount * row + col; + } + + /** + * Returns the map id at the given column and line. + * + * @param x + * The x coordinate. Starts at 0. + * @param y + * The y coordinate. Starts at 0. + * @return The Minecraft map ID. + * + * @throws ArrayIndexOutOfBoundsException + * if the given coordinates are too big (out of the poster). + */ + public int getMapIdAt(int x, int y) { + return mapsIDs[y * columnCount + x]; + } + + + public int getMapIdAtReverseY(int index) { + int x = index % (columnCount); + int y = index / (columnCount); + return getMapIdAt(x, rowCount - y - 1); + } + + + public int getMapIdAtReverseZ(int index, BlockFace orientation, BlockFace bf) { + int x = 0, y = 0; + switch (bf) { + case UP: + x = index % (columnCount); + y = index / (columnCount); + break; + case DOWN: + x = (columnCount - 1) - index % (columnCount); + y = index / (columnCount); + break; + } + + return getMapIdAt(x, rowCount - y - 1); + + } + + public int getMapIdAt(int index) { + return mapsIDs[index]; + } + + public boolean hasColumnData() { + return rowCount != 0 && columnCount != 0; + } + + @Override + public int getMapCount() { + return mapsIDs.length; + } + + public int getIndex(int mapID) { + for (int i = 0; i < mapsIDs.length; i++) { + if (mapsIDs[i] == mapID) + return i; + } + + throw new IllegalArgumentException("Invalid map ID"); + } } diff --git a/src/main/java/fr/moribus/imageonmap/map/SingleMap.java b/src/main/java/fr/moribus/imageonmap/map/SingleMap.java index 1695161..d37e2a2 100644 --- a/src/main/java/fr/moribus/imageonmap/map/SingleMap.java +++ b/src/main/java/fr/moribus/imageonmap/map/SingleMap.java @@ -1,50 +1,69 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.map; +import org.bukkit.configuration.InvalidConfigurationException; + import java.util.Map; import java.util.UUID; -import org.bukkit.configuration.InvalidConfigurationException; public class SingleMap extends ImageMap { - protected final short mapID; + protected final int mapID; - public SingleMap(UUID ownerUUID, short mapID, String id, String name) + public SingleMap(UUID ownerUUID, int mapID, String id, String name) { super(ownerUUID, Type.SINGLE, id, name); this.mapID = mapID; } - public SingleMap(UUID ownerUUID, short mapID) + public SingleMap(UUID ownerUUID, int mapID) { this(ownerUUID, mapID, null, null); } @Override - public short[] getMapsIDs() + public int[] getMapsIDs() { - return new short[]{mapID}; + return new int[]{mapID}; } @Override - public boolean managesMap(short mapID) + public boolean managesMap(int mapID) { return this.mapID == mapID; } @@ -60,8 +79,7 @@ public class SingleMap extends ImageMap public SingleMap(Map map, UUID userUUID) throws InvalidConfigurationException { super(map, userUUID, Type.SINGLE); - int _mapID = getFieldValue(map, "mapID"); - mapID = (short) _mapID;//Meh + mapID = getFieldValue(map, "mapID"); } @Override diff --git a/src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java b/src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java index c9d1fab..772962f 100644 --- a/src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java +++ b/src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.migration; diff --git a/src/main/java/fr/moribus/imageonmap/migration/OldSavedMap.java b/src/main/java/fr/moribus/imageonmap/migration/OldSavedMap.java index 6751aa9..695b86b 100644 --- a/src/main/java/fr/moribus/imageonmap/migration/OldSavedMap.java +++ b/src/main/java/fr/moribus/imageonmap/migration/OldSavedMap.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.migration; diff --git a/src/main/java/fr/moribus/imageonmap/migration/OldSavedPoster.java b/src/main/java/fr/moribus/imageonmap/migration/OldSavedPoster.java index 0c1b7d5..98ef5f0 100644 --- a/src/main/java/fr/moribus/imageonmap/migration/OldSavedPoster.java +++ b/src/main/java/fr/moribus/imageonmap/migration/OldSavedPoster.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.migration; @@ -21,12 +39,14 @@ package fr.moribus.imageonmap.migration; import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.MapManager; import fr.moribus.imageonmap.map.PosterMap; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import org.bukkit.configuration.Configuration; import org.bukkit.configuration.InvalidConfigurationException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + class OldSavedPoster { private final String userName; @@ -78,7 +98,11 @@ class OldSavedPoster public ImageMap toImageMap(UUID userUUID) { - return new PosterMap(userUUID, mapsIds, null, "poster", 0, 0); + // Converts the maps IDs to int as MC 1.13.2+ uses integer ids + final int[] mapsIdsInt = new int[mapsIds.length]; + Arrays.setAll(mapsIdsInt, i -> mapsIds[i]); + + return new PosterMap(userUUID, mapsIdsInt, null, "poster", 0, 0); } public void serialize(Configuration configuration) diff --git a/src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java b/src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java index 3c37e97..482b72f 100644 --- a/src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java +++ b/src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.migration; @@ -23,6 +41,8 @@ import fr.moribus.imageonmap.map.MapManager; import fr.zcraft.zlib.components.i18n.I; import fr.zcraft.zlib.tools.PluginLogger; import fr.zcraft.zlib.tools.mojang.UUIDFetcher; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -37,14 +57,8 @@ import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.UUID; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.StringUtils; +import java.util.*; +import java.util.stream.Collectors; /** * This class represents and executes the ImageOnMap v3.x migration process @@ -427,7 +441,7 @@ public class V3Migrator implements Runnable ArrayDeque remainingMaps = new ArrayDeque<>(); ArrayDeque remainingPosters = new ArrayDeque<>(); - ArrayDeque missingMapIds = new ArrayDeque<>(); + ArrayDeque missingMapIds = new ArrayDeque<>(); UUID playerUUID; OldSavedMap map; @@ -441,7 +455,7 @@ public class V3Migrator implements Runnable } else if(!map.isMapValid()) { - missingMapIds.add(map.getMapId()); + missingMapIds.add((int) map.getMapId()); } else { @@ -461,7 +475,7 @@ public class V3Migrator implements Runnable } else if(!poster.isMapValid()) { - missingMapIds.addAll(Arrays.asList(ArrayUtils.toObject(poster.getMapsIds()))); + missingMapIds.addAll(Arrays.stream(ArrayUtils.toObject(poster.getMapsIds())).map(id -> (int) id).collect(Collectors.toList())); } else { diff --git a/src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java b/src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java index 6f9309b..e16aad7 100644 --- a/src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java +++ b/src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.ui; @@ -26,8 +44,7 @@ import fr.zcraft.zlib.components.i18n.I; import fr.zcraft.zlib.core.ZLib; import fr.zcraft.zlib.tools.items.ItemStackBuilder; import fr.zcraft.zlib.tools.items.ItemUtils; -import org.bukkit.GameMode; -import org.bukkit.Material; +import org.bukkit.*; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -37,6 +54,8 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.MapMeta; import java.util.ArrayDeque; import java.util.HashMap; @@ -46,250 +65,262 @@ import java.util.UUID; public class MapItemManager implements Listener { static private HashMap> mapItemCache; - + static public void init() { - mapItemCache = new HashMap(); + mapItemCache = new HashMap<>(); ZLib.registerEvents(new MapItemManager()); } - + static public void exit() { - if(mapItemCache != null) mapItemCache.clear(); + if (mapItemCache != null) mapItemCache.clear(); mapItemCache = null; } - + static public boolean give(Player player, ImageMap map) { - if(map instanceof PosterMap) return give(player, (PosterMap) map); - else if(map instanceof SingleMap) return give(player, (SingleMap) map); + if (map instanceof PosterMap) return give(player, (PosterMap) map); + else if (map instanceof SingleMap) return give(player, (SingleMap) map); return false; } - + static public boolean give(Player player, SingleMap map) { return give(player, createMapItem(map)); } - + static public boolean give(Player player, PosterMap map) { - if(!map.hasColumnData()) + if (!map.hasColumnData()) return giveParts(player, map); return give(player, SplatterMapManager.makeSplatterMap(map)); } - + static public boolean giveParts(Player player, PosterMap map) { boolean inventoryFull = false; - + ItemStack mapPartItem; - for(int i = 0, c = map.getMapCount(); i < c; i++) + for (int i = 0, c = map.getMapCount(); i < c; i++) { - if(map.hasColumnData()) - { - mapPartItem = createMapItem(map, map.getColumnAt(i), map.getRowAt(i)); - } - else - { - mapPartItem = createMapItem(map, i); - } + mapPartItem = map.hasColumnData() ? createMapItem(map, map.getColumnAt(i), map.getRowAt(i)) : createMapItem(map, i); inventoryFull = give(player, mapPartItem) || inventoryFull; } - + return inventoryFull; } - + static public int giveCache(Player player) { Queue cache = getCache(player); Inventory inventory = player.getInventory(); int givenItemsCount = 0; - - while(inventory.firstEmpty() >= 0 && !cache.isEmpty()) + + while (inventory.firstEmpty() >= 0 && !cache.isEmpty()) { - inventory.addItem(cache.poll()); + give(player, cache.poll()); givenItemsCount++; } - + return givenItemsCount; } - - static private boolean give(Player player, ItemStack item) + + static private boolean give(final Player player, final ItemStack item) { - if(player.getInventory().firstEmpty() <= -1) + boolean given = ItemUtils.give(player, item); + + if (given) { - getCache(player).add(item); - return true; - } - else - { - player.getInventory().addItem(item); - return false; + player.playSound(player.getLocation(), Sound.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, 1, 1); } + + return !given; } - + static public ItemStack createMapItem(SingleMap map) { - return createMapItem(map.getMapsIDs()[0], map.getName()); + return createMapItem(map.getMapsIDs()[0], map.getName(), false); } - + static public ItemStack createMapItem(PosterMap map, int index) { - /// The name of a map item given to a player, if splatter maps are not used. 0 = map name; 1 = index. - return createMapItem(map.getMapIdAt(index), getMapTitle(map, index)); + return createMapItem(map.getMapIdAt(index), getMapTitle(map, index), true); } - + static public ItemStack createMapItem(PosterMap map, int x, int y) { - /// The name of a map item given to a player, if splatter maps are not used. 0 = map name; 1 = row; 2 = column. - return createMapItem(map.getMapIdAt(x, y), getMapTitle(map, y, x)); + return createMapItem(map.getMapIdAt(x, y), getMapTitle(map, y, x), true); } - + static public String getMapTitle(PosterMap map, int row, int column) { + /// The name of a map item given to a player, if splatter maps are not used. 0 = map name; 1 = row; 2 = column. return I.t("{0} (row {1}, column {2})", map.getName(), row + 1, column + 1); } - + static public String getMapTitle(PosterMap map, int index) { + /// The name of a map item given to a player, if splatter maps are not used. 0 = map name; 1 = index. return I.t("{0} (part {1})", map.getName(), index + 1); } - - static public ItemStack createMapItem(short mapID, String text) + + static public ItemStack createMapItem(int mapID, String text, boolean isMapPart) { - return new ItemStackBuilder(Material.MAP) - .data(mapID) + final ItemStack mapItem = new ItemStackBuilder(Material.FILLED_MAP) .title(text) .hideAttributes() .item(); + + final MapMeta meta = (MapMeta) mapItem.getItemMeta(); + meta.setMapId(mapID); + meta.setColor(isMapPart ? Color.LIME : Color.GREEN); + mapItem.setItemMeta(meta); + + return mapItem; } /** * Returns the item to place to display the (col;row) part of the given poster. * * @param map The map to take the part from. - * @param x The x coordinate of the part to display. Starts at 0. - * @param y The y coordinate of the part to display. Starts at 0. - * + * @param x The x coordinate of the part to display. Starts at 0. + * @param y The y coordinate of the part to display. Starts at 0. * @return The map. - * * @throws ArrayIndexOutOfBoundsException If x;y is not inside the map. */ static public ItemStack createSubMapItem(ImageMap map, int x, int y) { - if(map instanceof PosterMap && ((PosterMap) map).hasColumnData()) + if (map instanceof PosterMap && ((PosterMap) map).hasColumnData()) { return MapItemManager.createMapItem((PosterMap) map, x, y); } else { - if(x != 0 || y != 0) + if (x != 0 || y != 0) { throw new ArrayIndexOutOfBoundsException(); // Coherence } - return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName()); + return createMapItem(map.getMapsIDs()[0], map.getName(), false); } } - + static public int getCacheSize(Player player) { return getCache(player).size(); } - + static private Queue getCache(Player player) { Queue cache = mapItemCache.get(player.getUniqueId()); - if(cache == null) + if (cache == null) { cache = new ArrayDeque<>(); mapItemCache.put(player.getUniqueId(), cache); } return cache; } - + static private String getMapTitle(ItemStack item) { ImageMap map = MapManager.getMap(item); - if(map instanceof SingleMap) + if (map instanceof SingleMap) { return map.getName(); } else { PosterMap poster = (PosterMap) map; - int index = poster.getIndex(item.getDurability()); - if(poster.hasColumnData()) + int index = poster.getIndex(MapManager.getMapIdFromItemStack(item)); + if (poster.hasColumnData()) return getMapTitle(poster, poster.getRowAt(index), poster.getColumnAt(index)); - + return getMapTitle(poster, index); } } - + static private void onItemFramePlace(ItemFrame frame, Player player, PlayerInteractEntityEvent event) { - if(frame.getItem().getType() != Material.AIR) return; - if(!MapManager.managesMap(player.getItemInHand())) return; - event.setCancelled(true); - - if(SplatterMapManager.hasSplatterAttributes(player.getItemInHand())) + final ItemStack mapItem = player.getInventory().getItemInMainHand(); + + if (frame.getItem().getType() != Material.AIR) return; + if (!MapManager.managesMap(mapItem)) return; + + + if (SplatterMapManager.hasSplatterAttributes(mapItem)) { - if(!SplatterMapManager.placeSplatterMap(frame, player)) - return; + if (!SplatterMapManager.placeSplatterMap(frame, player,event)){ + event.setCancelled(true); //In case of an error allow to cancel map placement + return;} } else { - ItemStack is = new ItemStack(Material.MAP, 1, player.getItemInHand().getDurability()); - frame.setItem(is); + // If the item has a display name, bot not one from an anvil by the player, we remove it + // If it is not displayed on hover on the wall. + if (mapItem.hasItemMeta() && mapItem.getItemMeta().hasDisplayName() && mapItem.getItemMeta().getDisplayName().startsWith("§r")) + { + + final ItemStack frameItem = mapItem.clone(); + final ItemMeta meta = frameItem.getItemMeta(); + + meta.setDisplayName(null); + frameItem.setItemMeta(meta); + + frame.setItem(frameItem); + } + + else{ + frame.setItem(mapItem); + } + } - + + ItemUtils.consumeItem(player); } - + static private void onItemFrameRemove(ItemFrame frame, Player player, EntityDamageByEntityEvent event) { ItemStack item = frame.getItem(); - if(frame.getItem().getType() != Material.MAP) return; - - if(player.isSneaking()) + if (frame.getItem().getType() != Material.FILLED_MAP) return; + + if (player.isSneaking()) { - PosterMap poster = SplatterMapManager.removeSplatterMap(frame); - if(poster != null) + PosterMap poster = SplatterMapManager.removeSplatterMap(frame,player); + if (poster != null) { event.setCancelled(true); - - if(player.getGameMode() != GameMode.CREATIVE || !SplatterMapManager.hasSplatterMap(player, poster)) + + if (player.getGameMode() != GameMode.CREATIVE || !SplatterMapManager.hasSplatterMap(player, poster)) poster.give(player); - + return; } } - - if(!MapManager.managesMap(frame.getItem())) return; - + + if (!MapManager.managesMap(frame.getItem())) return; + frame.setItem(new ItemStackBuilder(item) .title(getMapTitle(item)) .hideAttributes() .item()); - + } - - @EventHandler(priority = EventPriority.HIGHEST) + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) static public void onEntityDamage(EntityDamageByEntityEvent event) { - if(event.isCancelled()) return; - if(!(event.getEntity() instanceof ItemFrame)) return; - if(!(event.getDamager() instanceof Player)) return; - - onItemFrameRemove((ItemFrame)event.getEntity(), (Player)event.getDamager(), event); + if (!(event.getEntity() instanceof ItemFrame)) return; + if (!(event.getDamager() instanceof Player)) return; + + onItemFrameRemove((ItemFrame) event.getEntity(), (Player) event.getDamager(), event); } - - @EventHandler(priority = EventPriority.HIGHEST) + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) static public void onEntityInteract(PlayerInteractEntityEvent event) { - if(event.isCancelled()) return; - if(!(event.getRightClicked() instanceof ItemFrame)) return; - - onItemFramePlace((ItemFrame)event.getRightClicked(), event.getPlayer(), event); + if (!(event.getRightClicked() instanceof ItemFrame)) return; + onItemFramePlace((ItemFrame) event.getRightClicked(), event.getPlayer(), event); } } diff --git a/src/main/java/fr/moribus/imageonmap/ui/PosterOnASurface.java b/src/main/java/fr/moribus/imageonmap/ui/PosterOnASurface.java new file mode 100644 index 0000000..b6334ee --- /dev/null +++ b/src/main/java/fr/moribus/imageonmap/ui/PosterOnASurface.java @@ -0,0 +1,236 @@ +/* + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) + * + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. + * + * 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.ui; + +import fr.moribus.imageonmap.map.PosterMap; +import fr.zcraft.zlib.tools.world.FlatLocation; +import fr.zcraft.zlib.tools.world.WorldUtils; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Entity; +import org.bukkit.entity.ItemFrame; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public class PosterOnASurface { + + public FlatLocation loc1; + public FlatLocation loc2; + + public ItemFrame[] frames; + + public boolean isValid(Player p) { + ItemFrame curFrame; + + + FlatLocation l = loc1.clone(); + + BlockFace bf = WorldUtils.get4thOrientation(p.getLocation()); + + l.subtract(loc2); + + + int distX = Math.abs(l.getBlockX()); + int distZ = Math.abs(l.getBlockZ()); + + frames = new ItemFrame[distX * distZ]; + l = loc1.clone(); + for (int x = 0; x < distX; x++) { + for (int z = 0; z < distZ; z++) { + + curFrame = getEmptyFrameAt(l, l.getFacing()); + + if (curFrame == null) + return false; + + frames[z * distX + x] = curFrame; + + switch (bf) { + case NORTH: + case SOUTH: + l.addH(0, 1, bf); + break; + case EAST: + case WEST: + l.addH(1, 0, bf); + break; + } + + } + + switch (bf) { + case NORTH: + case SOUTH: + l.addH(1, -distZ, bf); + break; + case EAST: + case WEST: + l.addH(-distZ, 1, bf); + break; + } + } + return true; + } + + public void expand() { + + } + + /** + * Return the list of map Frames associated with a specific map + * */ + static public ItemFrame[] getMatchingMapFrames(PosterMap map, FlatLocation location, int mapId, BlockFace bf) { + int mapIndex = map.getIndex(mapId); + //int x = map.getColumnAt(mapIndex), y = map.getRowAt(mapIndex); + int x=0,y=0; + switch(bf){ + case EAST: + case WEST: + y=map.getColumnCount()-1; + break; + case NORTH: + case SOUTH: + y=map.getRowCount()-1; + break; + } + return getMatchingMapFrames(map, location.clone().addH(x, y,bf),bf).clone(); + } + + static public ItemFrame[] getMatchingMapFrames(PosterMap map, FlatLocation location, BlockFace bf) { + ItemFrame[] frames = new ItemFrame[map.getMapCount()]; + FlatLocation loc = location.clone(); + + + + int X=0; + int Y=0; + switch (bf){ + case EAST: + case WEST: + /*X=map.getRowCount(); + Y=map.getColumnCount(); + break;*/ + case NORTH: + case SOUTH: + + Y=map.getRowCount(); + X=map.getColumnCount(); + break; + + } + + for (int y = 0; y < Y; ++y) { + for (int x = 0; x < X; ++x) { + int mapIndex = map.getIndexAt(x, y); + + ItemFrame frame = getMapFrameAt(loc, map); + if (frame != null) + frames[mapIndex] = frame; + switch (bf){ + case EAST: + case WEST: + loc.addH( 0,-1,bf); + break; + case NORTH: + case SOUTH: + loc.addH( 1,0,bf); + break; + } + + + } + + switch (bf){ + case EAST: + case WEST: + loc.addH( 1,map.getColumnCount(),bf);//test + + break; + case NORTH: + case SOUTH: + loc.addH(-map.getColumnCount(), -1,bf); + break; + } + + } + + return frames; + } + + static public ItemFrame getMapFrameAt(FlatLocation location, PosterMap map) { + Entity entities[] = location.getChunk().getEntities(); + + for (Entity entity : entities) { + if (!(entity instanceof ItemFrame)) + continue; + if (!WorldUtils.blockEquals(location, entity.getLocation())) + continue; + ItemFrame frame = (ItemFrame) entity; + if (frame.getFacing() != location.getFacing()) + continue; + ItemStack item = frame.getItem(); + if (item.getType() != Material.FILLED_MAP) + continue; + if (!map.managesMap(item)) + continue; + return frame; + } + + return null; + } + + static public ItemFrame getEmptyFrameAt(Location location, BlockFace facing) { + Entity entities[] = location.getChunk().getEntities(); + + for (Entity entity : entities) { + if (!(entity instanceof ItemFrame)) + continue; + if (!WorldUtils.blockEquals(location, entity.getLocation())) + continue; + ItemFrame frame = (ItemFrame) entity; + if (frame.getFacing() != facing) + continue; + ItemStack item = frame.getItem(); + if (item.getType() != Material.AIR) + continue; + return frame; + } + + return null; + } +} diff --git a/src/main/java/fr/moribus/imageonmap/ui/PosterWall.java b/src/main/java/fr/moribus/imageonmap/ui/PosterWall.java index 8db4630..f8db508 100644 --- a/src/main/java/fr/moribus/imageonmap/ui/PosterWall.java +++ b/src/main/java/fr/moribus/imageonmap/ui/PosterWall.java @@ -1,19 +1,37 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.ui; @@ -44,7 +62,7 @@ public class PosterWall int distX = FlatLocation.flatBlockDistanceX(loc1, loc2); int distY = FlatLocation.flatBlockDistanceY(loc1, loc2); - + frames = new ItemFrame[distX * distY]; for(int x = 0; x < distX; x++) @@ -65,12 +83,10 @@ public class PosterWall public void expand() { - - - + } - static public ItemFrame[] getMatchingMapFrames(PosterMap map, FlatLocation location, short mapId) + static public ItemFrame[] getMatchingMapFrames(PosterMap map, FlatLocation location, int mapId) { int mapIndex = map.getIndex(mapId); int x = map.getColumnAt(mapIndex), y = map.getRowAt(mapIndex); @@ -111,7 +127,7 @@ public class PosterWall ItemFrame frame = (ItemFrame) entity; if(frame.getFacing() != location.getFacing()) continue; ItemStack item = frame.getItem(); - if(item.getType() != Material.MAP) continue; + if(item.getType() != Material.FILLED_MAP) continue; if(!map.managesMap(item)) continue; return frame; } diff --git a/src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java b/src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java index ba7b930..e0858ab 100644 --- a/src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java +++ b/src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java @@ -1,135 +1,356 @@ /* - * Copyright (C) 2013 Moribus - * Copyright (C) 2015 ProkopyL + * Copyright or © or Copr. Moribus (2013) + * Copyright or © or Copr. ProkopyL (2015) + * Copyright or © or Copr. Amaury Carrade (2016 – 2020) + * Copyright or © or Copr. Vlammar (2019 – 2020) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is a computer program whose purpose is to allow insertion of + * custom images in a Minecraft world. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.ui; +import com.google.common.collect.ImmutableMap; import fr.moribus.imageonmap.image.MapInitEvent; import fr.moribus.imageonmap.map.ImageMap; import fr.moribus.imageonmap.map.MapManager; import fr.moribus.imageonmap.map.PosterMap; -import fr.zcraft.zlib.components.gui.GuiUtils; import fr.zcraft.zlib.components.i18n.I; -import fr.zcraft.zlib.tools.items.GlowEffect; +import fr.zcraft.zlib.components.nbt.NBT; +import fr.zcraft.zlib.components.nbt.NBTCompound; +import fr.zcraft.zlib.components.nbt.NBTException; +import fr.zcraft.zlib.components.nbt.NBTList; +import fr.zcraft.zlib.tools.PluginLogger; import fr.zcraft.zlib.tools.items.ItemStackBuilder; +import fr.zcraft.zlib.tools.reflection.NMSException; +import fr.zcraft.zlib.tools.text.MessageSender; import fr.zcraft.zlib.tools.world.FlatLocation; +import fr.zcraft.zlib.tools.world.WorldUtils; import org.bukkit.ChatColor; +import org.bukkit.Color; import org.bukkit.Material; +import org.bukkit.Rotation; +import org.bukkit.block.BlockFace; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.MapMeta; -abstract public class SplatterMapManager -{ - private SplatterMapManager() {} - - static public ItemStack makeSplatterMap(PosterMap map) - { - return new ItemStackBuilder(Material.MAP) - .data(map.getMapIdAt(0)) - .title(ChatColor.GOLD, map.getName()).title(ChatColor.DARK_GRAY, " - ").title(ChatColor.GRAY, I.t("Splatter Map")) - .loreLine(ChatColor.GRAY, map.getId()) - .loreLine() - /// Title in a splatter map tooltip - .loreLine(ChatColor.BLUE, I.t("Item frames needed")) - /// Size of a map stored in a splatter map - .loreLine(ChatColor.GRAY, I.t("{0} × {1}", map.getColumnCount(), map.getRowCount())) - .loreLine() - /// Title in a splatter map tooltip - .loreLine(ChatColor.BLUE, I.t("How to use this?")) - .lore(GuiUtils.generateLore(ChatColor.GRAY + I.t("Place empty item frames on a wall, enough to host the whole map. Then, right-click on the bottom-left frame with this map."))) - .loreLine() - .lore(GuiUtils.generateLore(ChatColor.GRAY + I.t("Shift-click one of the placed maps to remove the whole poster in one shot."))) - .glow() - .hideAttributes() - .item(); - } - - static public boolean hasSplatterAttributes(ItemStack itemStack) - { - return GlowEffect.hasGlow(itemStack); - } - - static public boolean isSplatterMap(ItemStack itemStack) - { - return hasSplatterAttributes(itemStack) && MapManager.managesMap(itemStack); - } - - static public boolean hasSplatterMap(Player player, PosterMap map) - { - Inventory playerInventory = player.getInventory(); - - for(int i = 0; i < playerInventory.getSize(); ++i) - { - ItemStack item = playerInventory.getItem(i); - if(isSplatterMap(item) && map.managesMap(item)) - return true; - } - - return false; - } - - static public boolean placeSplatterMap(ItemFrame startFrame, Player player) - { - ImageMap map = MapManager.getMap(player.getItemInHand()); - if(map == null || !(map instanceof PosterMap)) return false; - PosterMap poster = (PosterMap) map; - - FlatLocation startLocation = new FlatLocation(startFrame.getLocation(), startFrame.getFacing()); - FlatLocation endLocation = startLocation.clone().add(poster.getColumnCount(), poster.getRowCount()); - PosterWall wall = new PosterWall(); - - wall.loc1 = startLocation; - wall.loc2 = endLocation; - - if(!wall.isValid()) - { - player.sendMessage(I.t("{ce}There is not enough space to place this map ({0} × {1}).", poster.getColumnCount(), poster.getRowCount())); - return false; - } - - int i = 0; - for(ItemFrame frame : wall.frames) - { - short id = poster.getMapIdAtReverseY(i); - frame.setItem(new ItemStack(Material.MAP, 1, id)); - MapInitEvent.initMap(id); - ++i; - } - - return true; - } - - static public PosterMap removeSplatterMap(ItemFrame startFrame) - { - ImageMap map = MapManager.getMap(startFrame.getItem()); - if(map == null || !(map instanceof PosterMap)) return null; - PosterMap poster = (PosterMap) map; - if(!poster.hasColumnData()) return null; - FlatLocation loc = new FlatLocation(startFrame.getLocation(), startFrame.getFacing()); - ItemFrame[] matchingFrames = PosterWall.getMatchingMapFrames(poster, loc, startFrame.getItem().getDurability()); - if(matchingFrames == null) return null; - - for(ItemFrame frame : matchingFrames) - { - if(frame != null) frame.setItem(null); - } - - return poster; - } +abstract public class SplatterMapManager { + private SplatterMapManager() { + } + + static public ItemStack makeSplatterMap(PosterMap map) { + + + + final ItemStack splatter = new ItemStackBuilder(Material.FILLED_MAP).title(ChatColor.GOLD, map.getName()) + .title(ChatColor.DARK_GRAY, " - ").title(ChatColor.GRAY, I.t("Splatter Map")) + .title(ChatColor.DARK_GRAY, " - ") + .title(ChatColor.GRAY, I.t("{0} × {1}", map.getColumnCount(), map.getRowCount())) + .loreLine(ChatColor.GRAY, map.getId()).loreLine() + /// Title in a splatter map tooltip + .loreLine(ChatColor.BLUE, I.t("Item frames needed")) + /// Size of a map stored in a splatter map + .loreLine(ChatColor.GRAY, + I.t("{0} × {1} (total {2} frames)", map.getColumnCount(), map.getRowCount(), + map.getColumnCount() * map.getRowCount())) + .loreLine() + /// Title in a splatter map tooltip + .loreLine(ChatColor.BLUE, I.t("How to use this?")) + .longLore( + ChatColor.GRAY + + I.t("Place empty item frames on a wall, enough to host the whole map. Then, right-click on the bottom-left frame with this map."), + 40) + .loreLine() + .longLore(ChatColor.GRAY + + I.t("Shift-click one of the placed maps to remove the whole poster in one shot."), 40) + .hideAttributes().craftItem(); + + final MapMeta meta = (MapMeta) splatter.getItemMeta(); + meta.setMapId(map.getMapIdAt(0)); + meta.setColor(Color.GREEN); + splatter.setItemMeta(meta); + + return addSplatterAttribute(splatter); + } + + /** + * To identify image on maps for the auto-splattering to work, we mark the + * items using an enchantment maps are not supposed to have (Mending). + * + * Then we check if the map is enchanted at all to know if it's a splatter + * map. This ensure compatibility with old splatter maps from 3.x, where + * zLib's glow effect was used. + * + * An AttributeModifier (using zLib's attributes system) is not used, + * because Minecraft (or Spigot) removes them from maps in 1.14+, so that + * wasn't stable enough (and the glowing effect of enchantments is + * prettier). + * + * @param itemStack + * The item stack to mark as a splatter map. + * @return The modified item stack. The instance may be different if the + * passed item stack is not a craft item stack; that's why the + * instance is returned. + */ + static public ItemStack addSplatterAttribute(final ItemStack itemStack) { + try { + final NBTCompound nbt = NBT.fromItemStack(itemStack); + final NBTList enchantments = new NBTList(); + final NBTCompound protection = new NBTCompound(); + + protection.put("id", "minecraft:mending"); + protection.put("lvl", 1); + enchantments.add(protection); + + nbt.put("Enchantments", enchantments); + + return NBT.addToItemStack(itemStack, nbt, false); + } catch (NBTException | NMSException e) { + PluginLogger.error("Unable to set Splatter Map attribute on item", e); + return itemStack; + } + } + + /** + * Checks if an item have the splatter attribute set (i.e. if the item is + * enchanted in any way). + * + * @param itemStack + * The item to check. + * @return True if the attribute was detected. + */ + static public boolean hasSplatterAttributes(ItemStack itemStack) { + try { + final NBTCompound nbt = NBT.fromItemStack(itemStack); + if (!nbt.containsKey("Enchantments")) + return false; + final Object enchantments = nbt.get("Enchantments"); + if (!(enchantments instanceof NBTList)) + return false; + return !((NBTList) enchantments).isEmpty(); + } catch (NMSException e) { + PluginLogger.error("Unable to get Splatter Map attribute on item", e); + return false; + } + } + + /** + * Return true if it is a platter map + * + * @param itemStack + * The item to check. + * @return True if is a splatter map + */ + static public boolean isSplatterMap(ItemStack itemStack) { + if(itemStack==null) return false; + return hasSplatterAttributes(itemStack) && MapManager.managesMap(itemStack); + } + + + //TODO doc a faire + static public boolean hasSplatterMap(Player player, PosterMap map) { + Inventory playerInventory = player.getInventory(); + + for (int i = 0; i < playerInventory.getSize(); ++i) { + ItemStack item = playerInventory.getItem(i); + if (isSplatterMap(item) && map.managesMap(item)) + return true; + } + + return false; + } + + /** + * Place a splatter map + * + * @param startFrame + * Frame clicked by the player + * @param player + * Player placing map + * @return true if the map was correctly placed + */ + static public boolean placeSplatterMap(ItemFrame startFrame, Player player, PlayerInteractEntityEvent event) { + ImageMap map = MapManager.getMap(player.getInventory().getItemInMainHand()); + + if (!(map instanceof PosterMap)) + return false; + PosterMap poster = (PosterMap) map; + PosterWall wall = new PosterWall(); + + if (startFrame.getFacing().equals(BlockFace.DOWN) || startFrame.getFacing().equals(BlockFace.UP)) { + // If it is on floor or ceiling + PosterOnASurface surface = new PosterOnASurface(); + FlatLocation startLocation = new FlatLocation(startFrame.getLocation(), startFrame.getFacing()); + FlatLocation endLocation = startLocation.clone().addH(poster.getColumnCount(), poster.getRowCount(), + WorldUtils.get4thOrientation(player.getLocation())); + + surface.loc1 = startLocation; + surface.loc2 = endLocation; + + if (!surface.isValid(player)) { + MessageSender.sendActionBarMessage(player, + I.t("{ce}There is not enough space to place this map ({0} × {1}).", poster.getColumnCount(), + poster.getRowCount())); + + + return false; + } + + int i = 0; + for (ItemFrame frame : surface.frames) { + BlockFace bf = WorldUtils.get4thOrientation(player.getLocation()); + int id = poster.getMapIdAtReverseZ(i, bf, startFrame.getFacing()); + Rotation rot = Rotation.NONE; + switch(frame.getFacing()){ + case UP: + break; + case DOWN: + rot = Rotation.FLIPPED; + break; + } + //Rotation management relative to player rotation the default position is North, when on ceiling we flipped the rotation + frame.setItem(new ItemStackBuilder(Material.FILLED_MAP).nbt(ImmutableMap.of("map", id)).craftItem()); + if(i==0){//First map need to be rotate one time CounterClockwise + rot=rot.rotateCounterClockwise(); + } + + switch (bf) { + case NORTH: + if (frame.getFacing() == BlockFace.DOWN) { + rot = rot.rotateClockwise(); + rot = rot.rotateClockwise(); + } + frame.setRotation(rot); + break; + case EAST: + rot = rot.rotateClockwise(); + frame.setRotation(rot); + break; + case SOUTH: + if (frame.getFacing() == BlockFace.UP) { + rot = rot.rotateClockwise(); + rot = rot.rotateClockwise(); + } + frame.setRotation(rot); + break; + case WEST: + rot = rot.rotateCounterClockwise(); + frame.setRotation(rot); + break; + } + + + + + + MapInitEvent.initMap(id); + i++; + } + } else { + // If it is on a wall NSEW + FlatLocation startLocation = new FlatLocation(startFrame.getLocation(), startFrame.getFacing()); + FlatLocation endLocation = startLocation.clone().add(poster.getColumnCount(), poster.getRowCount()); + + wall.loc1 = startLocation; + wall.loc2 = endLocation; + + if (!wall.isValid()) { + MessageSender.sendActionBarMessage(player, + I.t("{ce}There is not enough space to place this map ({0} × {1}).", poster.getColumnCount(), + poster.getRowCount())); + return false; + } + + int i = 0; + for (ItemFrame frame : wall.frames) { + + int id = poster.getMapIdAtReverseY(i); + frame.setItem(new ItemStackBuilder(Material.FILLED_MAP).nbt(ImmutableMap.of("map", id)).craftItem()); + + //Force reset of rotation + if(i==0){//First map need to be rotate one time Clockwise + frame.setRotation(Rotation.NONE.rotateCounterClockwise()); + } + else{frame.setRotation(Rotation.NONE);} + MapInitEvent.initMap(id); + ++i; + } + } + return true; + } + + /** + * Remove splattermap + * + * @param startFrame + * Frame clicked by the player + * @param player + * The player removing the map + * @return + */ + static public PosterMap removeSplatterMap(ItemFrame startFrame, Player player) { + final ImageMap map = MapManager.getMap(startFrame.getItem()); + if (!(map instanceof PosterMap)) + return null; + PosterMap poster = (PosterMap) map; + if (!poster.hasColumnData()) + return null; + FlatLocation loc = new FlatLocation(startFrame.getLocation(), startFrame.getFacing()); + ItemFrame[] matchingFrames=null; + + switch(startFrame.getFacing()){ + case UP: + case DOWN: + matchingFrames = PosterOnASurface.getMatchingMapFrames(poster, loc, + MapManager.getMapIdFromItemStack(startFrame.getItem()),WorldUtils.get4thOrientation(player.getLocation()));//startFrame.getFacing()); + break; + + case NORTH: + case SOUTH: + case EAST: + case WEST: + matchingFrames = PosterWall.getMatchingMapFrames(poster, loc, + MapManager.getMapIdFromItemStack(startFrame.getItem())); + } + + if (matchingFrames == null) + return null; + + for (ItemFrame frame : matchingFrames) { + if (frame != null) + frame.setItem(null); + } + + return poster; + } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 5ffe7d4..7d84e64 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -2,7 +2,7 @@ # Plugin language. Empty: system language. -# Available: en_US (default, fallback) and fr_FR. +# Available: en-US (default, fallback), fr-FR, ru-RU, de-DE. lang: @@ -16,3 +16,13 @@ collect-data: true # 0 means unlimited. map-global-limit: 0 map-player-limit: 0 + + +#Maximum size in pixels for an image to be. 0 is unlimited. +limit-map-size-x: 0 +limit-map-size-y: 0 + + +#Should the full image be saved when a map is rendered? +save-full-image: false + diff --git a/src/main/resources/i18n/de_DE.po b/src/main/resources/i18n/de_DE.po new file mode 100644 index 0000000..a9995e8 --- /dev/null +++ b/src/main/resources/i18n/de_DE.po @@ -0,0 +1,540 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-04-23 13:50+0200\n" +"PO-Revision-Date: 2020-05-25 14:39+0200\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.3.1\n" +"Last-Translator: squeezer\n" +"Language: de_DE\n" + +#. / 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:141 +#, java-format +msgid "{0} (row {1}, column {2})" +msgstr "" + +#. / 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:147 +#, java-format +msgid "{0} (part {1})" +msgstr "" + +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:55 +msgid "Splatter Map" +msgstr "" + +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:57 +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:79 +#, java-format +msgid "{0} × {1}" +msgstr "" + +#. / Title in a splatter map tooltip +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:60 +msgid "Item frames needed" +msgstr "Rahmen benötigt" + +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:63 +#, java-format +msgid "{0} × {1} (total {2} frames)" +msgstr "" + +#. / Title in a splatter map tooltip +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:67 +msgid "How to use this?" +msgstr "Wie benutzt man das?" + +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:70 +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 "" +"Platziere leere Rahmen an die Wand, mit ausreichend Platz für alle " +"Kartenteile. Mit der Karte in der Hand rechtsklicke auf den Rahmen unten " +"links." + +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:74 +msgid "" +"Shift-click one of the placed maps to remove the whole poster in one shot." +msgstr "" +"Shift-Klick auf eines der platzierten Maps und das gesamte Poster zu " +"entfernen." + +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:187 +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:250 +msgid "{ce}There is not enough space to place this map ({0} × {1})." +msgstr "{ce}Der Platz reicht für diese Map nicht aus ({0} × {1})." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:172 +msgid "Error while preparing migration" +msgstr "Fehler während Migrationsvorbereitung" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:173 +msgid "Aborting migration. No change has been made." +msgstr "Breche Migration ab. Es wurden keine Änderungen vorgenommen." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:185 +msgid "Error while migrating" +msgstr "Fehler bei der Migrierung" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:186 +msgid "Aborting migration. Some changes may already have been made." +msgstr "Breche Migration ab. Änderungen können bereits gemacht worden sein." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:187 +msgid "" +"Before trying to migrate again, you must recover player files from the " +"backups, and then move the backups away from the plugin directory to avoid " +"overwriting them." +msgstr "" +"Vor der erneuten Migration müssen die Spieler-Dateien aus den Backups " +"wiederhergestellt und die Backups an einen anderen Ort verschoben werden, " +"damit diese nicht überschrieben werden." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:199 +msgid "Looking for configuration files to migrate..." +msgstr "Suche nach Konfigurationsdateien zum Migrieren..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:202 +#, java-format +msgid "Detected former posters file {0}" +msgstr "Erkenne vorherige Poster-Datei {0}" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:205 +#, java-format +msgid "Detected former maps file {0}" +msgstr "Erkenne vorherige Karten-Datei {0}" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:209 +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:412 +msgid "There is nothing to migrate. Stopping." +msgstr "Nichts zum Migrieren. Stoppe." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:214 +msgid "Done." +msgstr "Fertig." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:228 +msgid "Backup directories already exists." +msgstr "Backup-Ordner existieren bereits." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:229 +msgid "" +"This means that a migration has already been done, or may not have ended " +"well." +msgstr "" +"Das bedeutet, dass die Migration bereits erledigt wurde oder nicht geglückt " +"ist." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:230 +msgid "" +"To start a new migration, you must move away the backup directories so they " +"are not overwritten." +msgstr "" +"Um eine neue Migration zu startet, müssen die Backup-Ordner zunächst " +"verschoben werden, damit sie nicht überschrieben werden." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:243 +msgid "Backing up map data before migrating..." +msgstr "Sichere Karten-Daten bevor Migration..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:267 +msgid "Backup complete." +msgstr "Sicherung fertiggestellt." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:348 +msgid "Fetching UUIDs from Mojang..." +msgstr "Frage UUIDs von Mojang ab..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:355 +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:383 +msgid "An error occurred while fetching the UUIDs from Mojang" +msgstr "Ein Fehler ist während der Abfrage von UUIDs bei Mojang aufgetreten" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:360 +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:388 +msgid "The migration worker has been interrupted" +msgstr "Die Migration wurde unterbrochen" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:363 +#, java-format +msgid "Fetching done. {0} UUID have been retrieved." +msgid_plural "Fetching done. {0} UUIDs have been retrieved." +msgstr[0] "Abfrage fertig. {0} UUID erhalten." +msgstr[1] "Abfrage fertig. {0} UUIDs erhalten." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:374 +#, java-format +msgid "Mojang did not find UUIDs for {0} player at the current time." +msgid_plural "Mojang did not find UUIDs for {0} players at the current time." +msgstr[0] "Mojang findet zurzeit keine UUIDs für {0} Spieler." +msgstr[1] "Mojang findet zurzeit keine UUIDs für {0} Spieler." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:375 +msgid "" +"The Mojang servers limit requests rate at one per second, this may take some " +"time..." +msgstr "" +"Die Mojang Server limitieren die Abfrage auf eine pro Sekunde, dies kann " +"eine Weile dauern..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:394 +#, java-format +msgid "Mojang did not find player data for {0} player" +msgid_plural "Mojang did not find player data for {0} players" +msgstr[0] "Mojang findet keine Spielerdaten für {0} Spieler" +msgstr[1] "Mojang findet keine Spielerdaten für {0} Spieler" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:396 +msgid "The following players do not exist or do not have paid accounts :" +msgstr "" +"Die folgenden Spieler existieren nicht oder haben keine bezahlten Accounts :" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:411 +msgid "Mojang could not find any of the registered players." +msgstr "Mojang konnte keinen der registrierten Spieler finden." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:421 +msgid "Merging map data..." +msgstr "Füge Kartendaten zusammen..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:471 +#, java-format +msgid "{0} registered minecraft map is missing from the save." +msgid_plural "{0} registered minecraft maps are missing from the save." +msgstr[0] "{0} registrierte Minecraft Karte fehlt im save." +msgstr[1] "{0} registrierte Minecraft Karten fehlen im save." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:472 +msgid "" +"These maps will not be migrated, but this could mean the save has been " +"altered or corrupted." +msgstr "" +"Diese Karten werden nicht migriert, das könnte bedeuten, dass der save " +"verändert oder beschädigt ist." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:473 +#, java-format +msgid "The following maps are missing : {0} " +msgstr "Die folgenden Karten fehlen : {0} " + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:479 +msgid "Saving changes..." +msgstr "Speichere Veränderungen..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:485 +msgid "Cleaning up old data files..." +msgstr "Säubere alte Daten..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:492 +msgid "Deleting old map data file..." +msgstr "Lösche alte Karten-Daten..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:497 +#, java-format +msgid "{0} map could not be migrated." +msgid_plural "{0} maps could not be migrated." +msgstr[0] "{0} Karte konnte nicht migriert werden." +msgstr[1] "{0} Karten konnten nicht migriert werden." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:515 +msgid "Deleting old poster data file..." +msgstr "Lösche alte Poster Daten..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:520 +#, java-format +msgid "{0} poster could not be migrated." +msgid_plural "{0} posters could not be migrated." +msgstr[0] "{0} Poster konnte nicht migriert werden." +msgstr[1] "{0} Poster konnten nicht migriert werden." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:533 +msgid "Data that has not been migrated will be kept in the old data files." +msgstr "Nicht migrierte Daten verbleiben in den alten Daten-Files." + +#: src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java:34 +msgid "Migration is already running." +msgstr "Migration läuft bereits." + +#: src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java:50 +msgid "Waiting for migration to finish..." +msgstr "Warte auf Abschluss der Migration..." + +#: src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java:58 +msgid "" +"Migration thread has been interrupted while waiting to finish. It may not " +"have ended correctly." +msgstr "" +"Migrationsvorgang wurde während des Wartens auf Beendigung unterbrochen. " +"Dies wurde eventuell nicht korrekt beendet." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java:37 +msgid "A migration process is already running. Check console for details." +msgstr "Eine Migration ist bereits im Gange. Siehe Konsole für Details." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java:41 +msgid "Migration started. See console for details." +msgstr "Migration gestartet. Siehe Konsole für Details." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:50 +msgid "You are going to delete" +msgstr "Du bist im Inbegriff zu löschen" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:53 +msgid "Are you sure ? " +msgstr "Bist du sicher? " + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:55 +msgid "[Confirm]" +msgstr "[Bestätige]" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:57 +msgid "{red}This map will be deleted {bold}forever{red}!" +msgstr "{red}Diese Karte wird {bold}unwiderruflich {red}gelöscht!" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:70 +msgid "Map successfully deleted." +msgstr "Karte erfolgreich gelöscht." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java:75 +#: src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java:57 +msgid "This map does not exist." +msgstr "Diese Karte existiert nicht." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java:40 +msgid "You have no remaining map." +msgstr "Du hast keine Karte mehr übrig." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java:48 +msgid "" +"Your inventory is full! Make some space before requesting the remaining maps." +msgstr "Dein Inventar ist voll! Mach Platz bevor du weitere Karten anforderst." + +#: 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] "Es steht {0} Karte aus." +msgstr[1] "Es stehen {0} Karten aus." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:47 +msgid "You must give an URL to take the image from." +msgstr "Du musst eine URL zu einem Bild angeben." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:55 +msgid "Invalid URL." +msgstr "Ungültige URL." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:70 +msgid "Invalid Stretching mode." +msgstr "Ungültiger Strecken-Modus." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:51 +msgid "No map found." +msgstr "Keine Karte gefunden." + +#: 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} Karte gefunden." +msgstr[1] "{white}{bold}{0} Karten gefunden." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:81 +msgid "{white}Click{gray} to get this map" +msgstr "{white}Klicke{gray} um die Karte zu erhalten" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java:41 +msgid "The requested map was too big to fit in your inventory." +msgstr "Die angeforderte Karte ist zu groß um in dein Inventar zu passen." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java:42 +#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:69 +msgid "Use '/maptool getremaining' to get the remaining maps." +msgstr "Nutze '/maptool getremaining' um die übrigen Karten zu erhalten." + +#: src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java:40 +msgid "You need to give a map name." +msgstr "Du musst einen Kartennamen angeben." + +#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:56 +msgid "Rendering..." +msgstr "Rendere..." + +#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:64 +msgid "Rendering finished!" +msgstr "Rendern abgeschlossen!" + +#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:68 +msgid "The rendered map was too big to fit in your inventory." +msgstr "Die gerenderte Karte ist zu groß um in dein Inventar zu passen." + +#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:77 +msgid "{ce}Map rendering failed: {0}" +msgstr "{ce}Rendern der Karte gescheitert: {0}" + +#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:102 +#, java-format +msgid "HTTP error: {0} {1}" +msgstr "HTTP Fehler: {0} {1}" + +#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:108 +msgid "The given URL is not a valid image" +msgstr "Die angegebene URL ist kein gültiges Bild" + +#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:29 +#, java-format +msgid "You have too many maps (maximum : {0})." +msgstr "Du hast zu viele Karten (Maximum : {0})." + +#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:30 +msgid "The server ImageOnMap limit has been reached." +msgstr "Das Limit für ImageOnMap wurde auf diesem Server erreicht." + +#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:31 +msgid "The given map does not exist." +msgstr "Die angegebene Karte existiert nicht." + +#. / The default display name of a map +#: src/main/java/fr/moribus/imageonmap/map/ImageMap.java:44 +msgid "Map" +msgstr "Karte" + +#. / Displayed title of a map on the list GUI +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:66 +msgid "{green}{bold}{0}" +msgstr "" + +#. / Map ID displayed in the tooltip of a map on the list GUI +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:71 +msgid "{gray}Map ID: {0}" +msgstr "{gray}Karten-ID: {0}" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:75 +msgid "{gray}» {white}Left-click{gray} to get this map" +msgstr "{gray}» {white}Linksklick{gray} um diese Karte zu erhalten" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:77 +msgid "{gray}» {white}Right-click{gray} for details and options" +msgstr "{gray}» {white}Rechtsklick{gray} für Details und Optionen" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:92 +msgid "{red}You don't have any map." +msgstr "{red}Du hast keine Karte." + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:95 +msgid "" +"{gray}Get started by creating a new one using {white}/tomap [resize]" +"{gray}!" +msgstr "" +"{gray}Für den Anfang erstelle mit {white}/tomap [resize]{gray} eine " +"neue!" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:97 +msgid "{gray}Unfortunately, you are not allowed to create one." +msgstr "{gray}Leider ist dir nicht erlaubt eine neue zu erstellen." + +#. / The maps list GUI title +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:140 +msgid "{black}Your maps {reset}({0})" +msgstr "{black}Deine Karten {reset}({0})" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:69 +msgid "Image Editor" +msgstr "Bildbearbeiter" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:73 +msgid "Resize image" +msgstr "Bild skalieren" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:74 +msgid "Enabled" +msgstr "Aktivieren" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:74 +msgid "Disabled" +msgstr "Deaktivieren" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:76 +msgid "" +"You can automatically resize the image to a certain number of blocks (or " +"item frames)." +msgstr "" +"Du kannst das Bild automatisch auf eine bestimmte Anzahl an Blöcken (oder " +"Rahmen) skalieren." + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:78 +msgid "Original size (in blocks)" +msgstr "Originalgröße (in Blöcken)" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:79 +msgid "Loading..." +msgstr "Lade..." + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:81 +msgid "{gray}» {white}Click{gray} to disable resize" +msgstr "{gray}» {white}Klicke{gray} um Skalierung zu deaktivieren" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:81 +msgid "{gray}» {white}Click{gray} to enable resize" +msgstr "{gray}» {white}Klicke{gray} um Skalierung zu aktivieren" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:97 +#, java-format +msgid "Current size: {0} × {1}" +msgstr "Aktuelle Größe: {0} × {1}" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:100 +msgid "- 10" +msgstr "" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:104 +msgid "{gray}» {white}Click{gray} to decrease the image's width by 10 blocks" +msgstr "" +"{gray}» {white}Klicke{gray} um die Bildbreite um 10 Blöcke zu verringern" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:105 +msgid "{gray}» {white}Click{gray} to decrease the image's height by 10 blocks" +msgstr "{gray}» {white}Klicke{gray} um die Bildhöhe um 10 Blöcke zu verringern" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:110 +msgid "- 1" +msgstr "" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:114 +msgid "{gray}» {white}Click{gray} to decrease the image's width by one block" +msgstr "{gray}» {white}Klicke{gray} um die Bildbreite um1 Block zu verringern" + +#: src/main/java/fr/moribus/imageonmap/gui/RenderGui.java:115 +msgid "{gray}» {white}Click{gray} to decrease the image's height by one block" +msgstr "" +"{gray}» {white}Klicke{gray} um dieBildhöhe um einen Block zu verringern" + +#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:162 +#: 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}Dir ist es nicht mehr gestattet dies zu tuen." + +#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:172 +msgid "{gray}Map successfully deleted." +msgstr "{gray}Karte erfolgreich gelöscht." + +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:208 +msgid "{ce}Map names can't be empty." +msgstr "{ce}Kartenname darf nicht leer sein." + +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:213 +msgid "{cs}Map successfully renamed." +msgstr "{cs}Karte erfolgreich umbenannt." diff --git a/src/main/resources/i18n/en_US.po b/src/main/resources/i18n/en_US.po index 3a09331..9fee665 100644 --- a/src/main/resources/i18n/en_US.po +++ b/src/main/resources/i18n/en_US.po @@ -108,8 +108,8 @@ msgid "Rendering..." msgstr "Rendering..." #: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:67 -msgid "{cst}Rendering finished!" -msgstr "{cst}Rendering finished!" +msgid "Rendering finished!" +msgstr "Rendering finished!" #: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:70 msgid "The rendered map was too big to fit in your inventory." @@ -560,11 +560,17 @@ msgid "Item frames needed" msgstr "Item frames needed" #. Size of a map stored in a splatter map -#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:50 +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:56 #, java-format msgid "{0} × {1}" msgstr "{0} × {1}" +#. Size of a map stored in a splatter map, including the total frames count +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:62 +#, java-format +msgid "{0} × {1} (total {2} frames)" +msgstr "{0} × {1} (total {2} frames)" + #. Title in a splatter map tooltip #: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:53 msgid "How to use this?" diff --git a/src/main/resources/i18n/fr_FR.po b/src/main/resources/i18n/fr_FR.po index 2bd5bcd..c1d12c7 100644 --- a/src/main/resources/i18n/fr_FR.po +++ b/src/main/resources/i18n/fr_FR.po @@ -9,7 +9,7 @@ msgstr "" "Report-Msgid-Bugs-To: \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" +"Last-Translator: Gabriel Cnudde\n" "Language-Team: \n" "Language: fr_FR\n" "MIME-Version: 1.0\n" @@ -47,11 +47,17 @@ msgid "Item frames needed" msgstr "Cadres requis" #. Size of a map stored in a splatter map -#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:51 +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:56 #, java-format msgid "{0} × {1}" msgstr "{0} × {1}" +#. Size of a map stored in a splatter map, including the total frames count +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:62 +#, java-format +msgid "{0} × {1} (total {2} frames)" +msgstr "{0} × {1} (soit {2} cadres)" + #. Title in a splatter map tooltip #: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:54 msgid "How to use this?" @@ -222,8 +228,8 @@ msgstr "" #, java-format msgid "Mojang did not find player data for {0} player" msgid_plural "Mojang did not find player data for {0} players" -msgstr[0] "Mojang did not find player data for {0} player" -msgstr[1] "Mojang did not find player data for {0} players" +msgstr[0] "Mojang n'a pas trouvé de données de joueurs pour {0} joueur" +msgstr[1] "Mojang n'a pas trouvé de données de joueurs pour {0} joueurs" #: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:400 msgid "The following players do not exist or do not have paid accounts :" @@ -371,8 +377,8 @@ 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é !" +msgid "Rendering finished!" +msgstr "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." diff --git a/src/main/resources/i18n/ru_RU.po b/src/main/resources/i18n/ru_RU.po new file mode 100644 index 0000000..10c9c06 --- /dev/null +++ b/src/main/resources/i18n/ru_RU.po @@ -0,0 +1,595 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-07-10 03:07+0200\n" +"PO-Revision-Date: 2016-07-10 03:08+0200\n" +"Last-Translator: danechek\n" +"Language-Team: \n" +"Language: ru_RU\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n < 1 || n > 1);\n" +"X-Generator: Poedit 1.8.7.1\n" + +#: src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java:40 +msgid "You need to give a map name." +msgstr "Вам нужно дать имя карте." + +#: 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 "Такая карта не существует." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteConfirmCommand.java:39 +msgid "You are going to delete" +msgstr "Вы собираетесь удалить" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteConfirmCommand.java:42 +msgid "Are you sure ? " +msgstr "Вы уверены? " + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteConfirmCommand.java:44 +msgid "[Confirm]" +msgstr "[Подтвердить]" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteConfirmCommand.java:46 +msgid "{red}This map will be deleted {bold}forever{red}!" +msgstr "{red}Эта карта будет удалена {bold}навсегда{red}!" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteNoConfirmCommand.java:46 +msgid "Map successfully deleted." +msgstr "Карта успешно удалена." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java:38 +msgid "The requested map was too big to fit in your inventory." +msgstr "Запрашиваемая карта слишком большая для вашего инвентаря." + +#: 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 "Используйте '/maptool getremaining', чтобы получить остальные карты." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java:38 +msgid "You have no remaining map." +msgstr "У вас нет остальных карт." + +#: 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 "" +"Ваш инвентарь заполнен! Освободите место перед тем, как запросить остальные карты." + +#: 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] "Осталась {0} карта." +msgstr[1] "Осталось {0} карт." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:49 +msgid "No map found." +msgstr "Карта не найдена." + +#: 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} карта найдена." +msgstr[1] "{white}{bold}{0} карты найдены." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java:79 +msgid "{white}Click{gray} to get this map" +msgstr "{white}Кликните{gray}, чтобы получить эту карту" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java:36 +msgid "A migration process is already running. Check console for details." +msgstr "Процесс миграции уже запущен. Проверьте консоль, чтобы уточнить детали." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java:40 +msgid "Migration started. See console for details." +msgstr "Миграция начата. Смотрите консоль, чтобы уточнить детали." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:44 +msgid "You must give an URL to take the image from." +msgstr "Вы должны дать URL, откуда будет взято изображение." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:52 +msgid "Invalid URL." +msgstr "Неверный URL" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:61 +msgid "Rendering..." +msgstr "Прорисовка..." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:67 +msgid "Rendering finished!" +msgstr "Прорисовка завершена!" + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:70 +msgid "The rendered map was too big to fit in your inventory." +msgstr "Прорисованная карта слишком большая для вашего инвентаря." + +#: src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java:78 +msgid "{ce}Map rendering failed: {0}" +msgstr "{ce}Ошибока прорисовки карты: {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}Подтвердить удаление" + +#. 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}Вы собираетесь уничтожить эту карту..." + +#. 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}навсегда{red}." + +#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:114 +msgid "{gray}Name: {white}{0}" +msgstr "{gray}Имя: {white}{0}" + +#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:115 +msgid "{gray}Map ID: {white}{0}" +msgstr "{gray}ID карты: {white}{0}" + +#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:116 +msgid "{gray}Maps inside: {white}{0}" +msgstr "{gray}Карты внутри: {white}{0}" + +#: src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java:178 +msgid "{gray}Map successfully deleted." +msgstr "{gray}Карта успешно удалена." + +#: 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}Часть карты" + +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:55 +msgid "{gray}Column: {white}{0}" +msgstr "{gray}Столбец: {white}{0}" + +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:56 +msgid "{gray}Row: {white}{0}" +msgstr "{gray}Строка: {white}{0}" + +#: 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}Кликните{gray}, чтобы получить эту часть" + +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:72 +msgid "{gray}Part: {white}{0}" +msgstr "{gray}Часть: {white}{0}" + +#. Title of the map details GUI +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:114 +msgid "Your maps » {black}{0}" +msgstr "Ваши карты » {black}{0}" + +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:136 +msgid "{blue}Rename this image" +msgstr "{blue}Переименуйте это изображение" + +#: 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}Кликните сюда, чтобы переименовать это изображение; это используется для вашей собственной " +"организации." + +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:141 +msgid "{red}Delete this image" +msgstr "{red}Удалить это изображение" + +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:142 +msgid "" +"{gray}Deletes this map {white}forever{gray}. This action cannot be undone!" +msgstr "" +"{gray}Удаляет эту карту {white}навсегда{gray}. Это действие не может быть завершено!" + +#: 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}Вам будет предложено подтвердить свой выбор, если вы кликните здесь." + +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:156 +msgid "{green}« Back" +msgstr "{green}« Назад" + +#: src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java:157 +msgid "{gray}Go back to the list." +msgstr "{gray}Вернуться к списку." + +#. 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}Одиночная карта" + +#. 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}Постер ({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}Постер ({0} parts)" + +#. 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}ID карты: {0}" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:69 +msgid "{gray}» {white}Left-click{gray} to get this map" +msgstr "{gray}» {white}ЛКМ{gray} для получения этой карты" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:70 +msgid "{gray}» {white}Right-click{gray} for details and options" +msgstr "{gray}» {white}ПКМ{gray} для деталей и опций" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:79 +msgid "{red}You don't have any map." +msgstr "{red}У вас нет карт." + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:80 +msgid "" +"{gray}Get started by creating a new one using {white}/tomap [resize]" +"{gray}!" +msgstr "" +"{gray}Начните создание новой с помощью {white}/tomap [resize]" +"{gray}!" + +#. The maps list GUI title +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:119 +msgid "{black}Your maps {reset}({0})" +msgstr "{black}Ваши карты {reset}({0})" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:148 +msgid "{blue}Usage statistics" +msgstr "{blue}Статистика использования" + +#: 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} изображение прорисовано" +msgstr[1] "{white}{0}{gray} изображения прорисованы" + +#: 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} Minecraft карта использована" +msgstr[1] "{white}{0}{gray} Minecraft карты использованы" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:156 +msgid "{blue}Minecraft maps limits" +msgstr "{blue}Minecraft лимит карт" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:158 +msgid "{gray}Server-wide limit: {white}unlimited" +msgstr "{gray}Лимит на сервере: {white}неограничено" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:159 +msgid "{gray}Server-wide limit: {white}{0}" +msgstr "{gray}Лимит на сервере: {white}{0}" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:161 +msgid "{gray}Per-player limit: {white}unlimited" +msgstr "{gray}Лимит для игрокаt: {white}неограничено" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:162 +msgid "{gray}Per-player limit: {white}{0}" +msgstr "{gray}Лимит для игрока: {white}{0}" + +#: src/main/java/fr/moribus/imageonmap/gui/MapListGui.java:164 +msgid "{white}{0} %{gray} of your quota used" +msgstr "{white}{0} %{gray} часть, используемая вами" + +#: 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} карта осталась" +msgstr[1] "{white}{0}{gray} карт осталось" + +#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:73 +#, java-format +msgid "HTTP error : {0} {1}" +msgstr "HTTP ошибка : {0} {1}" + +#: src/main/java/fr/moribus/imageonmap/image/ImageRendererExecutor.java:79 +msgid "The given URL is not a valid image" +msgstr "Указанный URL имеет неверный формат изображения" + +#. The default display name of a map +#: src/main/java/fr/moribus/imageonmap/map/ImageMap.java:44 +msgid "Map" +msgstr "Карта" + +#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:29 +#, java-format +msgid "You have too many maps (maximum : {0})." +msgstr "Вы имеете слишком много карт (максимум : {0})." + +#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:30 +msgid "The server ImageOnMap limit has been reached." +msgstr "Лимит карт на сервере достигнут." + +#: src/main/java/fr/moribus/imageonmap/map/MapManagerException.java:31 +msgid "The given map does not exist." +msgstr "Данная карта не существует." + +#: src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java:34 +msgid "Migration is already running." +msgstr "Миграция уже запущена." + +#: src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java:50 +msgid "Waiting for migration to finish..." +msgstr "Подождите окончания миграции..." + +#: src/main/java/fr/moribus/imageonmap/migration/MigratorExecutor.java:58 +msgid "" +"Migration thread has been interrupted while waiting to finish. It may not " +"have ended correctly." +msgstr "" +"Поток миграции был прерван во время ожидания завершения. Может быть " +"не завершено корректно." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:176 +msgid "Error while preparing migration" +msgstr "Ошибка во время подготовки миграции" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:177 +msgid "Aborting migration. No change has been made." +msgstr "Прерываю миграции. Изменения не будут применены." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:189 +msgid "Error while migrating" +msgstr "Ошибка во время миграции" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:190 +msgid "Aborting migration. Some changes may already have been made." +msgstr "Прерываю миграции. Некоторые изменения могут быть применены." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:191 +msgid "" +"Before trying to migrate again, you must recover player files from the " +"backups, and then move the backups away from the plugin directory to avoid " +"overwriting them." +msgstr "" +"Перед попыткой повторной миграции, вы должны восстановить файлы игроков из " +"бэкапов, затем переместить резервные копии из каталога плагинов, чтобы избежать " +"их перезаписи." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:203 +msgid "Looking for configuration files to migrate..." +msgstr "Ищем файлы для конфигурации миграции..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:206 +#, java-format +msgid "Detected former posters file {0}" +msgstr "Обнаружен файл прошлых постеров{0}" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:209 +#, java-format +msgid "Detected former maps file {0}" +msgstr "Обнаружен файл прошлых постеров {0}" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:213 +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:416 +msgid "There is nothing to migrate. Stopping." +msgstr "Нечему мигрировать. Останавливаю." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:218 +msgid "Done." +msgstr "Завершено." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:232 +msgid "Backup directories already exists." +msgstr "Бэкап каталоги уже существуют." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:233 +msgid "" +"This means that a migration has already been done, or may not have ended " +"well." +msgstr "" +"Это означает, что миграция уже выполнена, или, возможно, не закончилась" +"хорошо." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:234 +msgid "" +"To start a new migration, you must move away the backup directories so they " +"are not overwritten." +msgstr "" +"Чтобы начать новую миграцию, вы должны переместить каталоги бэкапов, чтобы " +"они не перезаписались." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:247 +msgid "Backing up map data before migrating..." +msgstr "Резервное копирование карт перед миграцией..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:271 +msgid "Backup complete." +msgstr "Бэкап завершён." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:352 +msgid "Fetching UUIDs from Mojang..." +msgstr "Получаем UUIDs от Mojang..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:359 +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:387 +msgid "An error occurred while fetching the UUIDs from Mojang" +msgstr "Произошла ошибка при получении UUIDs от Mojang" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:364 +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:392 +msgid "The migration worker has been interrupted" +msgstr "Миграционный работник был прерван" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:367 +#, java-format +msgid "Fetching done. {0} UUID have been retrieved." +msgid_plural "Fetching done. {0} UUIDs have been retrieved." +msgstr[0] "Получение завершено. {0} UUID был получен." +msgstr[1] "Получение завершено. {0} UUIDs были получены." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:378 +#, java-format +msgid "Mojang did not find UUIDs for {0} player at the current time." +msgid_plural "Mojang did not find UUIDs for {0} players at the current time." +msgstr[0] "Mojang не нашёл UUIDs для {0} игрока на текущее время." +msgstr[1] "Mojang не нашёл UUIDs для {0} игроков на текущее время." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:379 +msgid "" +"The Mojang servers limit requests rate at one per second, this may take some " +"time..." +msgstr "" +"Серверы Mojang имеют ограничение запросов, это может занять некоторое " +"время..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:398 +#, java-format +msgid "Mojang did not find player data for {0} player" +msgid_plural "Mojang did not find player data for {0} players" +msgstr[0] "Mojang не нашёл данных для игрока {0}" +msgstr[1] "Mojang не нашёл данных для игроков {0}" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:400 +msgid "The following players do not exist or do not have paid accounts :" +msgstr "Следующие игроки не существуют или не имеют платных аккаунтов:" + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:415 +msgid "Mojang could not find any of the registered players." +msgstr "Mojang не удалось найти существующих игроков." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:425 +msgid "Merging map data..." +msgstr "Объединяю данные карт..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:475 +#, java-format +msgid "{0} registered minecraft map is missing from the save." +msgid_plural "{0} registered minecraft maps are missing from the save." +msgstr[0] "{0} зарегистрированная minecraft карта отсутствует в сохранении." +msgstr[1] "{0} зарегистрированные minecraft карты отсутствуют в сохранении." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:476 +msgid "" +"These maps will not be migrated, but this could mean the save has been " +"altered or corrupted." +msgstr "" +"Эти карты не будут перенесены, но это может означать, что сохранение было " +"изменено или повреждено." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:477 +#, java-format +msgid "The following maps are missing : {0} " +msgstr "Следующие карты отсутствуют : {0} " + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:483 +msgid "Saving changes..." +msgstr "Сохраняю изменения..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:489 +msgid "Cleaning up old data files..." +msgstr "Очищаю устаревшие данные файлов..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:496 +msgid "Deleting old map data file..." +msgstr "Удаляю устаревший файл карты..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:501 +#, java-format +msgid "{0} map could not be migrated." +msgid_plural "{0} maps could not be migrated." +msgstr[0] "{0} карта не может быть перенесена." +msgstr[1] "{0} карты не могут быть перенесены." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:519 +msgid "Deleting old poster data file..." +msgstr "Удаление устаревшего файла данных постера..." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:524 +#, java-format +msgid "{0} poster could not be migrated." +msgid_plural "{0} posters could not be migrated." +msgstr[0] "{0} постер не может быть перенесён." +msgstr[1] "{0} постеры не могут быть перенесены." + +#: src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java:537 +msgid "Data that has not been migrated will be kept in the old data files." +msgstr "Данные, которые не были перенесены, будут сохранены в старых файлах данных." + +#. 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 +#, java-format +msgid "{0} (part {1})" +msgstr "{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} (строка {1}, столбец {2})" + +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:44 +msgid "Splatter Map" +msgstr "Размещаю карту" + +#. Title in a splatter map tooltip +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:48 +msgid "Item frames needed" +msgstr "Нужны рамки для предметов" + +#. Size of a map stored in a splatter map +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:56 +#, java-format +msgid "{0} × {1}" +msgstr "{0} × {1}" + +#. Size of a map stored in a splatter map, including the total frames count +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:62 +#, java-format +msgid "{0} × {1} (total {2} frames)" +msgstr "{0} × {1} (всего {2} рамок)" + +#. Title in a splatter map tooltip +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:53 +msgid "How to use this?" +msgstr "Как использовать это?" + +#: 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." +msgstr "" +"Поместите пустые рамки на стену, столько, чтобы разместить всю карту. Теперь, ПКМ по" +"нижней левой рамке этой картой." + +#: src/main/java/fr/moribus/imageonmap/ui/SplatterMapManager.java:56 +msgid "" +"Shift-click one of the placed maps to remove the whole poster in one shot." +msgstr "" +"Shift-клик по одной из размещенных карт для удаления всего постера за один раз." + +#: 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}Здесь недостаточно места для размещения этой картй ({0} × {1})." diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 17bd4fe..1f6cfe3 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,7 @@ name: ImageOnMap main: fr.moribus.imageonmap.ImageOnMap -version: 3.1 +version: "4.0" +api-version: "1.13" commands: tomap: @@ -23,7 +24,6 @@ permissions: imageonmap.explore: true imageonmap.rename: true imageonmap.delete: true - imageonmap.administrative: false imageonmap.userender: description: "Allows you to use /tomap and related commands (/maptool getremaing). Alias of imageonmap.new."