mirror of
https://github.com/zDevelopers/ImageOnMap.git
synced 2025-01-24 00:01:47 +01:00
Merge branch 'indev'
This commit is contained in:
commit
ec6b4ec997
21
licenseheader.txt
Normal file
21
licenseheader.txt
Normal file
@ -0,0 +1,21 @@
|
||||
<#if licenseFirst??>
|
||||
${licenseFirst}
|
||||
</#if>
|
||||
${licensePrefix}Copyright (C) 2013 Moribus
|
||||
${licensePrefix}Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
${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?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?replace(" +$", "", "r")}
|
||||
${licensePrefix}You should have received a copy of the GNU General Public License
|
||||
${licensePrefix}along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
<#if licenseLast??>
|
||||
${licenseLast}
|
||||
</#if>
|
18
nb-configuration.xml
Normal file
18
nb-configuration.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-shared-configuration>
|
||||
<!--
|
||||
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||
The configuration is intended to be shared among all the users of project and
|
||||
therefore it is assumed to be part of version control checkout.
|
||||
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||
-->
|
||||
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||
<!--
|
||||
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||
-->
|
||||
<netbeans.hint.licensePath>${project.basedir}/licenseheader.txt</netbeans.hint.licensePath>
|
||||
</properties>
|
||||
</project-shared-configuration>
|
@ -1,30 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import fr.moribus.imageonmap.commands.MapToolCommand;
|
||||
import fr.moribus.imageonmap.commands.ImageRenduCommande;
|
||||
import fr.moribus.imageonmap.commands.Commands;
|
||||
import fr.moribus.imageonmap.image.ImageIOExecutor;
|
||||
import fr.moribus.imageonmap.image.ImageRendererExecutor;
|
||||
import fr.moribus.imageonmap.image.MapInitEvent;
|
||||
import fr.moribus.imageonmap.map.MapManager;
|
||||
import fr.moribus.imageonmap.migration.MigratorExecutor;
|
||||
import fr.moribus.imageonmap.migration.V3Migrator;
|
||||
import fr.moribus.imageonmap.ui.MapItemManager;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.SingleMap;
|
||||
|
||||
public final class ImageOnMap extends JavaPlugin
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
public ImageOnMap()
|
||||
{
|
||||
imagesDirectory = new File(this.getDataFolder(), IMAGES_DIRECTORY_NAME);
|
||||
mapsDirectory = new File(this.getDataFolder(), MAPS_DIRECTORY_NAME);
|
||||
plugin = this;
|
||||
}
|
||||
|
||||
@ -33,169 +51,62 @@ public final class ImageOnMap extends JavaPlugin
|
||||
return plugin;
|
||||
}
|
||||
|
||||
private boolean dossierCree;
|
||||
private FileConfiguration customConfig = null;
|
||||
private File customConfigFile = null;
|
||||
/* liste contenant les maps ne pouvant être placé dans l'inventaire du joueur. Je le fous ici afin que ce soit
|
||||
accessible de partout dans le plugin. */
|
||||
private HashMap<String, ArrayList<ItemStack>> cache = new HashMap<String, ArrayList<ItemStack>>();
|
||||
|
||||
// Index des maps chargées sur le serveur
|
||||
public ArrayList<Short> mapChargee = new ArrayList<Short>();
|
||||
public File getImagesDirectory() {return imagesDirectory;}
|
||||
public File getMapsDirectory() {return mapsDirectory;}
|
||||
public File getImageFile(short mapID)
|
||||
{
|
||||
return new File(imagesDirectory, "map"+mapID+".png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
// On crée si besoin le dossier où les images seront stockées
|
||||
dossierCree = ImgUtility.CreeRepImg(this);
|
||||
|
||||
// On ajoute si besoin les params par défaut du plugin
|
||||
ImgUtility.CreeSectionConfig(this);
|
||||
if (getConfig().get("map_path") == null)
|
||||
PluginLogger.init(this);
|
||||
// Creating the images and maps directories if necessary
|
||||
try
|
||||
{
|
||||
getConfig().set("map_path", getServer().getWorlds().get(0).getName());
|
||||
imagesDirectory = checkPluginDirectory(imagesDirectory, V3Migrator.getOldImagesDirectory(this));
|
||||
checkPluginDirectory(mapsDirectory);
|
||||
}
|
||||
else if (getConfig().get("map_path") != getServer().getWorlds().get(0).getName())
|
||||
catch(IOException ex)
|
||||
{
|
||||
getConfig().set("map_path", getServer().getWorlds().get(0).getName());
|
||||
}
|
||||
|
||||
if (getConfig().getBoolean("import-maps"))
|
||||
{
|
||||
ImgUtility.ImporterConfig(this);
|
||||
}
|
||||
|
||||
if (this.getConfig().getBoolean("collect-data"))
|
||||
{
|
||||
try
|
||||
{
|
||||
MetricsLite metrics = new MetricsLite(this);
|
||||
metrics.start();
|
||||
getLogger().info("Metrics launched for ImageOnMap");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
PluginLogger.LogError("Failed to start Plugin metrics", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (dossierCree)
|
||||
{
|
||||
getCommand("tomap").setExecutor(new ImageRenduCommande(this));
|
||||
getCommand("maptool").setExecutor(new MapToolCommand(this));
|
||||
getServer().getPluginManager().registerEvents(new SendMapOnFrameEvent(this), this);
|
||||
getServer().getPluginManager().registerEvents(new SendMapOnInvEvent(this), this);
|
||||
this.saveDefaultConfig();
|
||||
//ChargerMap();
|
||||
}
|
||||
else
|
||||
{
|
||||
getLogger().info("[ImageOnMap] An error occured ! Unable to create Image folder. Plugin will NOT work !");
|
||||
PluginLogger.error("FATAL : " + ex.getMessage(), null);
|
||||
this.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//Init all the things !
|
||||
PluginConfiguration.init(this);
|
||||
MetricsLite.startMetrics();
|
||||
ImageIOExecutor.start();
|
||||
ImageRendererExecutor.start();
|
||||
MapManager.init();
|
||||
Commands.init(this);
|
||||
MapInitEvent.init(this);
|
||||
MapItemManager.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable()
|
||||
{
|
||||
getLogger().info("Stopping ImageOnMap");
|
||||
ImageIOExecutor.stop();
|
||||
ImageRendererExecutor.stop();
|
||||
MapManager.exit();
|
||||
MapItemManager.exit();
|
||||
MigratorExecutor.waitForMigration();
|
||||
PluginLogger.exit();
|
||||
}
|
||||
|
||||
public void ChargerMap()
|
||||
private File checkPluginDirectory(File primaryFile, File... alternateFiles) throws IOException
|
||||
{
|
||||
Set<String> cle = getCustomConfig().getKeys(false);
|
||||
int nbMap = 0, nbErr = 0;
|
||||
for (String s : cle)
|
||||
if(primaryFile.exists()) return primaryFile;
|
||||
for(File file : alternateFiles)
|
||||
{
|
||||
if (getCustomConfig().getStringList(s).size() >= 3)
|
||||
{
|
||||
ImageMap map;
|
||||
String stringID = getCustomConfig().getStringList(s).get(0);
|
||||
try
|
||||
{
|
||||
map = new SingleMap(Short.valueOf(stringID));
|
||||
|
||||
map.load();
|
||||
nbMap++;
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
PluginLogger.LogWarning("Could not parse map ID from config", e);
|
||||
nbErr++;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
PluginLogger.LogError("Could not load map ID " + stringID, e);
|
||||
nbErr++;
|
||||
}
|
||||
}
|
||||
|
||||
if(file.exists()) return file;
|
||||
}
|
||||
PluginLogger.LogInfo(nbMap + " maps successfuly loaded.");
|
||||
if (nbErr != 0)
|
||||
PluginLogger.LogWarning(nbErr + " couldn't be loaded.");
|
||||
if(!primaryFile.mkdirs())
|
||||
throw new IOException("Could not create '" + primaryFile.getName() + "' plugin directory.");
|
||||
return primaryFile;
|
||||
}
|
||||
|
||||
/* Méthodes pour charger / recharger / sauvegarder
|
||||
* le fichier conf des maps (map.yml).
|
||||
* Je les ai juste copié depuis un tuto du wiki Bukkit.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void reloadCustomConfig()
|
||||
{
|
||||
if (customConfigFile == null)
|
||||
{
|
||||
customConfigFile = new File(getDataFolder(), "map.yml");
|
||||
}
|
||||
customConfig = YamlConfiguration.loadConfiguration(customConfigFile);
|
||||
|
||||
// Look for defaults in the jar
|
||||
InputStream defConfigStream = this.getResource("map.yml");
|
||||
if (defConfigStream != null)
|
||||
{
|
||||
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream);
|
||||
customConfig.setDefaults(defConfig);
|
||||
}
|
||||
}
|
||||
|
||||
public FileConfiguration getCustomConfig()
|
||||
{
|
||||
if (customConfig == null)
|
||||
{
|
||||
reloadCustomConfig();
|
||||
}
|
||||
return customConfig;
|
||||
}
|
||||
|
||||
public void saveCustomConfig()
|
||||
{
|
||||
if (customConfig == null || customConfigFile == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
getCustomConfig().save(customConfigFile);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
getLogger().log(Level.SEVERE, "Could not save config to " + customConfigFile, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<ItemStack> getRemainingMaps(String j)
|
||||
{
|
||||
return cache.get(j);
|
||||
}
|
||||
|
||||
public void setRemainingMaps(String j, ArrayList<ItemStack> remaining)
|
||||
{
|
||||
cache.put(j, remaining);
|
||||
}
|
||||
|
||||
public void removeRemaingMaps(String j)
|
||||
{
|
||||
cache.remove(j);
|
||||
}
|
||||
}
|
||||
|
@ -1,266 +0,0 @@
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.BlockCommandSender;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
import fr.moribus.imageonmap.map.SingleMap;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public class ImgUtility
|
||||
{
|
||||
|
||||
// Vérifie que c'est bien un joueur qui exécute la commande
|
||||
static public boolean VerifierIdentite(CommandSender sender)
|
||||
{
|
||||
if (sender instanceof Player)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (sender instanceof ConsoleCommandSender)
|
||||
{System.out.println(ChatColor.RED + "Cette commande ne peut être utilisée dans la console !"); return false;}
|
||||
else if (sender instanceof BlockCommandSender)
|
||||
{System.out.println(ChatColor.RED + "Cette commande ne peut être utilisée par un bloc-commande !"); return false;}
|
||||
else
|
||||
{System.out.println(ChatColor.RED + "Cette commande ne peut être lancée de cette façon !"); return false;}
|
||||
}
|
||||
|
||||
// Creation du dossier où sera stocké les images
|
||||
static public boolean CreeRepImg(ImageOnMap plugin)
|
||||
{
|
||||
File dossier;
|
||||
dossier = new File(plugin.getDataFolder().getPath() + "/Image");
|
||||
if (!dossier.exists())
|
||||
{
|
||||
return dossier.mkdirs();
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CreeSectionConfig(ImageOnMap plugin)
|
||||
{
|
||||
if(plugin.getConfig().get("Limit-map-by-server") == null)
|
||||
plugin.getConfig().set("Limit-map-by-server", 0);
|
||||
if(plugin.getConfig().get("Limit-map-by-player") == null)
|
||||
plugin.getConfig().set("Limit-map-by-player", 0);
|
||||
if(plugin.getConfig().get("collect-data") == null)
|
||||
plugin.getConfig().set("collect-data", true);
|
||||
if(plugin.getConfig().get("import-maps") == null)
|
||||
plugin.getConfig().set("import-maps", true);
|
||||
if(plugin.getConfig().get("send-entire-maps") == null)
|
||||
plugin.getConfig().set("send-entire-maps", 0);
|
||||
plugin.saveConfig();
|
||||
|
||||
}
|
||||
|
||||
static int getNombreDeMaps(ImageOnMap plugin)
|
||||
{
|
||||
int nombre = 0;
|
||||
Set<String> cle = plugin.getCustomConfig().getKeys(false);
|
||||
for (String s: cle)
|
||||
{
|
||||
if(plugin.getCustomConfig().getStringList(s).size() >= 3)
|
||||
{
|
||||
nombre++;
|
||||
}
|
||||
}
|
||||
return nombre;
|
||||
}
|
||||
|
||||
static int getNombreDeMapsParJoueur(ImageOnMap plugin, String pseudo)
|
||||
{
|
||||
int nombre = 0;
|
||||
Set<String> cle = plugin.getCustomConfig().getKeys(false);
|
||||
for (String s: cle)
|
||||
{
|
||||
if(plugin.getCustomConfig().getStringList(s).size() >= 3 && plugin.getCustomConfig().getStringList(s).get(2).contentEquals(pseudo))
|
||||
{
|
||||
nombre++;
|
||||
}
|
||||
}
|
||||
return nombre;
|
||||
}
|
||||
|
||||
static boolean EstDansFichier(ImageOnMap plugin, short id)
|
||||
{
|
||||
Set<String> cle = plugin.getCustomConfig().getKeys(false);
|
||||
for (String s: cle)
|
||||
{
|
||||
if(plugin.getCustomConfig().getStringList(s).size() >= 3 && Short.parseShort(plugin.getCustomConfig().getStringList(s).get(0)) == id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean EstDansFichier(ImageOnMap plugin, short id, String pseudo)
|
||||
{
|
||||
Set<String> cle = plugin.getCustomConfig().getKeys(false);
|
||||
for (String s: cle)
|
||||
{
|
||||
if(plugin.getCustomConfig().getStringList(s).size() >= 3 && Short.parseShort(plugin.getCustomConfig().getStringList(s).get(0)) == id && plugin.getCustomConfig().getStringList(s).get(2).contentEquals(pseudo))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean ImporterConfig(ImageOnMap plugin)
|
||||
{
|
||||
Set<String> cle = plugin.getConfig().getKeys(false);
|
||||
|
||||
plugin.getLogger().info("Start importing maps config to maps.yml...");
|
||||
int i = 0;
|
||||
for (String s: cle)
|
||||
{
|
||||
if(plugin.getConfig().getStringList(s).size() >= 3)
|
||||
{
|
||||
//plugin.getLogger().info("Importing "+ plugin.getConfig().getStringList(s).get(1));
|
||||
ArrayList<String> liste = new ArrayList<String>();
|
||||
liste.add(String.valueOf(plugin.getConfig().getStringList(s).get(0)));
|
||||
liste.add(plugin.getConfig().getStringList(s).get(1));
|
||||
liste.add(plugin.getConfig().getStringList(s).get(2));
|
||||
plugin.getCustomConfig().set(plugin.getConfig().getStringList(s).get(1), liste);
|
||||
plugin.getConfig().set(s, null);
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
plugin.getLogger().info("Importing finished. "+ i+ "maps were imported");
|
||||
plugin.getConfig().set("import-maps", false);
|
||||
plugin.saveConfig();
|
||||
plugin.saveCustomConfig();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fait la même chose que EstDansFichier() mais en retournant un objet MapView
|
||||
@SuppressWarnings("deprecation")
|
||||
static MapView getMap(ImageOnMap plugin, short id)
|
||||
{
|
||||
MapView map;
|
||||
if(!ImgUtility.EstDansFichier(plugin, id))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
map = Bukkit.getMap(id);
|
||||
if(map == null)
|
||||
{
|
||||
plugin.getLogger().warning("Map#"+ id+ " exists in maps.yml but not in the world folder !");
|
||||
return null;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static public boolean RemoveMap(ImageOnMap plugin, short id)
|
||||
{
|
||||
@SuppressWarnings("deprecation")
|
||||
MapView carte = Bukkit.getMap(id);
|
||||
|
||||
Set<String> cle = plugin.getCustomConfig().getKeys(false);
|
||||
for (String s: cle)
|
||||
{
|
||||
if(plugin.getCustomConfig().getStringList(s).size() >= 3)
|
||||
{
|
||||
if(carte == null && id == Short.parseShort(plugin.getCustomConfig().getStringList(s).get(0)))
|
||||
{
|
||||
//joueur.sendMessage("Suppression de la map dans fichier conf");
|
||||
plugin.getCustomConfig().set(s, null);
|
||||
plugin.saveCustomConfig();
|
||||
File map = new File("./plugins/ImageOnMap/Image/" + s + ".png");
|
||||
boolean isDeleted = map.delete();
|
||||
//joueur.sendMessage("The picture have been deleted");
|
||||
|
||||
if(isDeleted)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
plugin.getLogger().warning("Picture "+ s+ ".png cannot be deleted !");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
else if(id == Short.parseShort(plugin.getCustomConfig().getStringList(s).get(0)))
|
||||
{
|
||||
//joueur.sendMessage("Suppression de la map dans fichier conf + fichier dat");
|
||||
SingleMap.SupprRendu(carte);
|
||||
/*if(plugin.getConfig().get("delete") != null);
|
||||
{
|
||||
ArrayList<String> ListeSuppr = (ArrayList<String>) plugin.getConfig().getStringList("delete");
|
||||
ListeSuppr.add(plugin.getCustomConfig().getStringList(s).get(0));
|
||||
plugin.getConfig().set("delete", ListeSuppr);
|
||||
}*/
|
||||
plugin.getCustomConfig().set(s, null);
|
||||
plugin.saveCustomConfig();
|
||||
plugin.saveConfig();
|
||||
File map = new File("./plugins/ImageOnMap/Image/" + s + ".png");
|
||||
boolean isDeleted = map.delete();
|
||||
//joueur.sendMessage("DEBUG: booléen isDeleted :"+ isDeleted+ "; Nom de la map : "+ plugin.getServer().getWorlds().get(0).getName());
|
||||
//joueur.sendMessage("The map has been deleted");
|
||||
if(isDeleted)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
plugin.getLogger().warning("Picture "+ s+ ".png cannot be deleted !");
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//plugin.getLogger().info("No map with id"+ id+ " was found");
|
||||
return false;
|
||||
}
|
||||
|
||||
static public ArrayList<String> getListMapByPlayer(ImageOnMap plugin, String pseudo)
|
||||
{
|
||||
ArrayList<String> listeMap = new ArrayList<String>();
|
||||
Set<String> cle = plugin.getCustomConfig().getKeys(false);
|
||||
for (String s: cle)
|
||||
{
|
||||
if(plugin.getCustomConfig().getStringList(s).size() >= 3 && pseudo.equalsIgnoreCase(plugin.getCustomConfig().getStringList(s).get(2)))
|
||||
{
|
||||
listeMap.add(plugin.getCustomConfig().getStringList(s).get(0));
|
||||
}
|
||||
}
|
||||
return listeMap;
|
||||
}
|
||||
|
||||
static public void AddMap(ItemStack map, Inventory inv, ArrayList<ItemStack> restant)
|
||||
{
|
||||
HashMap<Integer,ItemStack> reste = inv.addItem(map);
|
||||
|
||||
if(!reste.isEmpty())
|
||||
{
|
||||
restant.add(reste.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
public static BufferedImage scaleImage(Image image, int width, int height)
|
||||
{
|
||||
BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = newImage.createGraphics();
|
||||
g.drawImage(image, 0, 0, width, height, null);
|
||||
g.dispose();
|
||||
return newImage;
|
||||
}
|
||||
}
|
@ -47,10 +47,27 @@ import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class MetricsLite {
|
||||
public class MetricsLite
|
||||
{
|
||||
/**
|
||||
* Starts MetricsLite, unless disabled in config
|
||||
*/
|
||||
|
||||
static public void startMetrics()
|
||||
{
|
||||
if(!PluginConfiguration.COLLECT_DATA.getBoolean()) return;
|
||||
try
|
||||
{
|
||||
MetricsLite metrics = new MetricsLite(ImageOnMap.getPlugin());
|
||||
metrics.start();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
PluginLogger.error("Failed to start MetricsLite", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
@ -180,7 +197,7 @@ public class MetricsLite {
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
|
||||
PluginLogger.warning("[Metrics] ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -200,14 +217,9 @@ public class MetricsLite {
|
||||
try {
|
||||
// Reload the metrics file
|
||||
configuration.load(getConfigFile());
|
||||
} catch (IOException ex) {
|
||||
} catch (IOException | InvalidConfigurationException ex) {
|
||||
if (debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
||||
}
|
||||
return true;
|
||||
} catch (InvalidConfigurationException ex) {
|
||||
if (debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
||||
PluginLogger.info("[Metrics] " + ex.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -263,7 +275,7 @@ public class MetricsLite {
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
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/
|
||||
@ -396,7 +408,7 @@ public class MetricsLite {
|
||||
gzos = new GZIPOutputStream(baos);
|
||||
gzos.write(input.getBytes("UTF-8"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
PluginLogger.error("MetricsLite GZIP error : ", e);
|
||||
} finally {
|
||||
if (gzos != null) try {
|
||||
gzos.close();
|
||||
@ -489,7 +501,8 @@ public class MetricsLite {
|
||||
default:
|
||||
if (chr < ' ') {
|
||||
String t = "000" + Integer.toHexString(chr);
|
||||
builder.append("\\u" + t.substring(t.length() - 4));
|
||||
builder.append("\\u");
|
||||
builder.append(t.substring(t.length() - 4));
|
||||
} else {
|
||||
builder.append(chr);
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
public class PlayerListener implements Listener
|
||||
{
|
||||
ImageOnMap plugin;
|
||||
HashMap<String, SendEntireMapTask> hmap;
|
||||
int send;
|
||||
|
||||
PlayerListener(ImageOnMap p)
|
||||
{
|
||||
plugin = p;
|
||||
hmap = new HashMap<String, SendEntireMapTask>();
|
||||
send = plugin.getConfig().getInt("send-entire-maps");
|
||||
}
|
||||
@EventHandler
|
||||
public void OnPlayerLogin(PlayerLoginEvent event)
|
||||
{
|
||||
if(send > 0)
|
||||
{
|
||||
Player joueur = event.getPlayer();
|
||||
hmap.put(joueur.getName(), new SendEntireMapTask(plugin, event.getPlayer()));
|
||||
hmap.get(joueur.getName()).runTaskTimer(plugin, 40, 20);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void OnPlayerLeft(PlayerQuitEvent event)
|
||||
{
|
||||
if(send > 0)
|
||||
{
|
||||
Player joueur = event.getPlayer();
|
||||
hmap.get(joueur.getName()).cancel();
|
||||
}
|
||||
}
|
||||
}
|
125
src/main/java/fr/moribus/imageonmap/PluginConfiguration.java
Normal file
125
src/main/java/fr/moribus/imageonmap/PluginConfiguration.java
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public enum PluginConfiguration
|
||||
{
|
||||
//Configuration field Names, with default values
|
||||
COLLECT_DATA("collect-data", true),
|
||||
MAP_GLOBAL_LIMIT("map-global-limit", 0, "Limit-map-by-server"),
|
||||
MAP_PLAYER_LIMIT("map-player-limit", 0, "Limit-map-by-player");
|
||||
|
||||
private final String fieldName;
|
||||
private final Object defaultValue;
|
||||
private final String[] deprecatedNames;
|
||||
|
||||
private PluginConfiguration(String fieldName, Object defaultValue, String ... deprecatedNames)
|
||||
{
|
||||
this.fieldName = fieldName;
|
||||
this.defaultValue = defaultValue;
|
||||
this.deprecatedNames = deprecatedNames;
|
||||
}
|
||||
|
||||
public Object get()
|
||||
{
|
||||
return getConfig().get(fieldName, defaultValue);
|
||||
}
|
||||
|
||||
public Object getDefaultValue()
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public boolean isDefined()
|
||||
{
|
||||
return getConfig().contains(fieldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return get().toString();
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
return getConfig().getString(fieldName, (String)defaultValue);
|
||||
}
|
||||
|
||||
public int getInteger()
|
||||
{
|
||||
return getConfig().getInt(fieldName, (Integer)defaultValue);
|
||||
}
|
||||
|
||||
public boolean getBoolean()
|
||||
{
|
||||
return getConfig().getBoolean(fieldName, (Boolean)defaultValue);
|
||||
}
|
||||
|
||||
private boolean init()
|
||||
{
|
||||
boolean affected = false;
|
||||
|
||||
if(!isDefined())
|
||||
{
|
||||
getConfig().set(fieldName, defaultValue);
|
||||
affected = true;
|
||||
}
|
||||
|
||||
for(String deprecatedName : deprecatedNames)
|
||||
{
|
||||
if(getConfig().contains(deprecatedName))
|
||||
{
|
||||
getConfig().set(fieldName, getConfig().get(deprecatedName));
|
||||
getConfig().set(deprecatedName, null);
|
||||
affected = true;
|
||||
}
|
||||
}
|
||||
return affected;
|
||||
}
|
||||
|
||||
/* ===== Static API ===== */
|
||||
|
||||
static private Plugin plugin;
|
||||
static public FileConfiguration getConfig()
|
||||
{
|
||||
return plugin.getConfig();
|
||||
}
|
||||
|
||||
static public void init(Plugin plugin)
|
||||
{
|
||||
PluginConfiguration.plugin = plugin;
|
||||
loadDefaultValues();
|
||||
}
|
||||
|
||||
static private void loadDefaultValues()
|
||||
{
|
||||
boolean affected = false;
|
||||
|
||||
for(PluginConfiguration configField : PluginConfiguration.values())
|
||||
{
|
||||
if(configField.init()) affected = true;
|
||||
}
|
||||
|
||||
if(affected) plugin.saveConfig();
|
||||
}
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2014 ProkopyL
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@ -12,39 +13,117 @@
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
abstract public class PluginLogger
|
||||
{
|
||||
static private Plugin plugin;
|
||||
static private Thread mainThread;
|
||||
static private HashMap<Thread, PluginThreadLogger> loggers;
|
||||
|
||||
static public void init(Plugin plugin)
|
||||
{
|
||||
PluginLogger.plugin = plugin;
|
||||
mainThread = Thread.currentThread();
|
||||
loggers = new HashMap<>();
|
||||
}
|
||||
|
||||
static public void exit()
|
||||
{
|
||||
plugin = null;
|
||||
mainThread = null;
|
||||
loggers = null;
|
||||
}
|
||||
|
||||
static public void log(Level level, String message, Throwable ex)
|
||||
{
|
||||
getLogger().log(level, message, ex);
|
||||
}
|
||||
|
||||
static public void log(Level level, String message, Object...args)
|
||||
{
|
||||
getLogger().log(level, message, args);
|
||||
}
|
||||
|
||||
static public void log(Level level, String message, Throwable ex, Object... args)
|
||||
{
|
||||
log(level, message + " : " + ex.getMessage(), args);
|
||||
}
|
||||
|
||||
static public void info(String message, Object...args)
|
||||
{
|
||||
log(Level.INFO, message, args);
|
||||
}
|
||||
|
||||
static public void warning(String message, Object... args)
|
||||
{
|
||||
log(Level.WARNING, message, args);
|
||||
}
|
||||
|
||||
static public void warning(String message, Throwable ex)
|
||||
{
|
||||
warning(message + " : " + ex.getMessage());
|
||||
}
|
||||
|
||||
static public void error(String message)
|
||||
{
|
||||
log(Level.SEVERE, message);
|
||||
}
|
||||
|
||||
static public void error(String message, Throwable ex)
|
||||
{
|
||||
log(Level.SEVERE, message, ex);
|
||||
}
|
||||
|
||||
static public void error(String message, Throwable ex, Object... args)
|
||||
{
|
||||
log(Level.SEVERE, message, ex, args);
|
||||
}
|
||||
|
||||
static private Logger getLogger()
|
||||
{
|
||||
return ImageOnMap.getPlugin().getLogger();
|
||||
Thread currentThread = Thread.currentThread();
|
||||
if(currentThread.equals(mainThread)) return plugin.getLogger();
|
||||
return getLogger(currentThread);
|
||||
}
|
||||
|
||||
static public void LogInfo(String message)
|
||||
static private Logger getLogger(Thread thread)
|
||||
{
|
||||
getLogger().log(Level.INFO, message);
|
||||
PluginThreadLogger logger = loggers.get(thread);
|
||||
if(logger == null)
|
||||
{
|
||||
logger = new PluginThreadLogger(thread);
|
||||
loggers.put(thread, logger);
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
|
||||
static public void LogWarning(String message)
|
||||
static private class PluginThreadLogger extends Logger
|
||||
{
|
||||
getLogger().log(Level.WARNING, message);
|
||||
}
|
||||
private final String loggerName;
|
||||
public PluginThreadLogger(Thread thread)
|
||||
{
|
||||
super(plugin.getClass().getCanonicalName(), null);
|
||||
setParent(plugin.getLogger());
|
||||
setLevel(Level.ALL);
|
||||
loggerName = "[" + thread.getName() + "] ";
|
||||
}
|
||||
|
||||
static public void LogWarning(String message, Throwable ex)
|
||||
{
|
||||
getLogger().log(Level.WARNING, message, ex);
|
||||
}
|
||||
|
||||
static public void LogError(String message, Throwable ex)
|
||||
{
|
||||
getLogger().log(Level.SEVERE, message, ex);
|
||||
@Override
|
||||
public void log(LogRecord logRecord)
|
||||
{
|
||||
logRecord.setMessage(loggerName + logRecord.getMessage());
|
||||
super.log(logRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,107 +0,0 @@
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import fr.moribus.imageonmap.image.Renderer;
|
||||
import fr.moribus.imageonmap.image.ImageRendererThread;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.map.MapPalette;
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
public class SavedMap
|
||||
{
|
||||
|
||||
ImageOnMap plugin;
|
||||
String nomImg, nomJoueur, nomMonde;
|
||||
short idMap;
|
||||
BufferedImage image;
|
||||
boolean loaded = false;
|
||||
|
||||
SavedMap(ImageOnMap plug, String nomJ, short id, BufferedImage img, String nomM)
|
||||
{
|
||||
plugin = plug;
|
||||
nomJoueur = nomJ;
|
||||
idMap = id;
|
||||
image = img;
|
||||
nomImg = "map" + id;
|
||||
nomMonde = nomM;
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
SavedMap(ImageOnMap plug, short id) throws IOException
|
||||
{
|
||||
idMap = id;
|
||||
plugin = plug;
|
||||
Set<String> cle = plugin.getCustomConfig().getKeys(false);
|
||||
for (String s : cle)
|
||||
{
|
||||
if (plugin.getCustomConfig().getStringList(s).size() >= 3 && Short.valueOf(plugin.getCustomConfig().getStringList(s).get(0)) == id)
|
||||
{
|
||||
//System.out.println(tmp);
|
||||
//MapView carte = Bukkit.getMap(Short.parseShort(plugin.getConfig().getStringList(s).get(0)));
|
||||
nomImg = plugin.getCustomConfig().getStringList(s).get(1);
|
||||
nomJoueur = plugin.getCustomConfig().getStringList(s).get(2);
|
||||
image = ImageIO.read(new File("./plugins/ImageOnMap/Image/" + nomImg + ".png"));
|
||||
loaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!loaded)
|
||||
{
|
||||
//plugin.getLogger().info("No map was loaded");
|
||||
}
|
||||
}
|
||||
|
||||
public void saveMap() throws IOException
|
||||
{
|
||||
if (!loaded)
|
||||
{
|
||||
PluginLogger.LogWarning("Tried to save a map that wasn't loaded. ID:" + idMap);
|
||||
return;
|
||||
}
|
||||
plugin.getLogger().info("Saving map " + idMap);
|
||||
|
||||
// Enregistrement de l'image sur le disque dur
|
||||
File outputfile = new File("./plugins/ImageOnMap/Image/" + nomImg + ".png");
|
||||
ImageIO.write(MapPalette.resizeImage(image), "png", outputfile);
|
||||
// Enregistrement de la map dans la config
|
||||
ArrayList<String> liste = new ArrayList<String>();
|
||||
liste.add(String.valueOf(idMap));
|
||||
liste.add(nomImg);
|
||||
liste.add(nomJoueur);
|
||||
liste.add(nomMonde);
|
||||
plugin.getCustomConfig().set(nomImg, liste);
|
||||
plugin.saveCustomConfig();
|
||||
if (!plugin.mapChargee.contains(idMap))
|
||||
{
|
||||
plugin.mapChargee.add(idMap);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public Boolean LoadMap()
|
||||
{
|
||||
MapView carte = Bukkit.getMap(idMap);
|
||||
if (carte != null && loaded)
|
||||
{
|
||||
ImageRendererThread.SupprRendu(carte);
|
||||
carte.addRenderer(new Renderer(image));
|
||||
if (!plugin.mapChargee.contains(idMap))
|
||||
{
|
||||
plugin.mapChargee.add(idMap);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
public class SavedPoster
|
||||
{
|
||||
ImageOnMap plugin;
|
||||
short[] ids;
|
||||
private FileConfiguration customConfig = null;
|
||||
private File customConfigFile = null;
|
||||
String posterName, playerName;
|
||||
|
||||
public SavedPoster(ImageOnMap plugin, short[] ids, String playerName, String posterName)
|
||||
{
|
||||
this.ids = ids;
|
||||
this.plugin = plugin;
|
||||
this.playerName = playerName;
|
||||
this.posterName = posterName;
|
||||
}
|
||||
|
||||
public SavedPoster(ImageOnMap plugin, short[] ids, String playerName)
|
||||
{
|
||||
this(plugin, ids, playerName, null);
|
||||
}
|
||||
|
||||
public SavedPoster(ImageOnMap plugin)
|
||||
{
|
||||
this(plugin, null, null, null);
|
||||
}
|
||||
|
||||
public SavedPoster(ImageOnMap p, String id)
|
||||
{
|
||||
plugin = p;
|
||||
posterName = id;
|
||||
ArrayList<String> liste = (ArrayList<String>) getCustomConfig().getStringList(posterName);
|
||||
if (!liste.isEmpty() || liste != null)
|
||||
{
|
||||
playerName = liste.get(0);
|
||||
ids = new short[liste.size() - 1];
|
||||
for (int i = 0; i < ids.length; i++)
|
||||
{
|
||||
ids[i] = Short.parseShort(liste.get(i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String Save() throws IOException
|
||||
{
|
||||
int increment = increment();
|
||||
ArrayList<String> liste = new ArrayList<String>();
|
||||
liste.add(playerName);
|
||||
for (int i = 0; i < ids.length; i++)
|
||||
{
|
||||
liste.add(String.valueOf(ids[i]));
|
||||
}
|
||||
posterName = "poster" + increment;
|
||||
getCustomConfig().set(posterName, liste);
|
||||
saveCustomConfig();
|
||||
return posterName;
|
||||
}
|
||||
|
||||
public void Remove() throws IOException
|
||||
{
|
||||
if (posterName == null || posterName.isEmpty()) return;
|
||||
for (int i = 0; i < ids.length; i++)
|
||||
{
|
||||
ImgUtility.RemoveMap(plugin, ids[i]);
|
||||
}
|
||||
getCustomConfig().set(posterName, null);
|
||||
saveCustomConfig();
|
||||
}
|
||||
|
||||
int increment()
|
||||
{
|
||||
int i;
|
||||
if (getCustomConfig().get("IdCount") != null)
|
||||
{
|
||||
i = getCustomConfig().getInt("IdCount");
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
i++;
|
||||
this.getCustomConfig().set("IdCount", i);
|
||||
return i;
|
||||
}
|
||||
|
||||
String getId()
|
||||
{
|
||||
return posterName;
|
||||
}
|
||||
|
||||
public ArrayList<String> getListMapByPlayer(ImageOnMap plugin, String pseudo)
|
||||
{
|
||||
ArrayList<String> listeMap = new ArrayList<String>();
|
||||
Set<String> cle = getCustomConfig().getKeys(false);
|
||||
for (String s : cle)
|
||||
{
|
||||
if (getCustomConfig().getStringList(s).size() > 1 && pseudo.equalsIgnoreCase(getCustomConfig().getStringList(s).get(0)))
|
||||
{
|
||||
listeMap.add(s);
|
||||
}
|
||||
}
|
||||
return listeMap;
|
||||
}
|
||||
|
||||
/* Méthodes pour charger / recharger / sauvegarder
|
||||
* le fichier conf des Posters (poster.yml).
|
||||
* Je les ai juste copié depuis un tuto du wiki Bukkit...
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void reloadCustomConfig()
|
||||
{
|
||||
if (customConfigFile == null)
|
||||
{
|
||||
customConfigFile = new File(plugin.getDataFolder(), "poster.yml");
|
||||
}
|
||||
customConfig = YamlConfiguration.loadConfiguration(customConfigFile);
|
||||
|
||||
// Look for defaults in the jar
|
||||
InputStream defConfigStream = plugin.getResource("poster.yml");
|
||||
if (defConfigStream != null)
|
||||
{
|
||||
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream);
|
||||
customConfig.setDefaults(defConfig);
|
||||
}
|
||||
}
|
||||
|
||||
public FileConfiguration getCustomConfig()
|
||||
{
|
||||
if (customConfig == null)
|
||||
{
|
||||
reloadCustomConfig();
|
||||
}
|
||||
return customConfig;
|
||||
}
|
||||
|
||||
public void saveCustomConfig() throws IOException
|
||||
{
|
||||
if (customConfig == null || customConfigFile == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
getCustomConfig().save(customConfigFile);
|
||||
}
|
||||
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class SendEntireMapTask extends BukkitRunnable
|
||||
{
|
||||
ImageOnMap plugin;
|
||||
Player joueur;
|
||||
ArrayList<Short> listeMap;
|
||||
List<Short> partListe;
|
||||
boolean allsent;
|
||||
int index, toIndex, nbSend;
|
||||
|
||||
SendEntireMapTask(ImageOnMap p, Player j)
|
||||
{
|
||||
plugin = p;
|
||||
joueur = j;
|
||||
allsent = false;
|
||||
index = 0;
|
||||
nbSend = plugin.getConfig().getInt("send-entire-maps");
|
||||
toIndex = nbSend;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(nbSend > 0)
|
||||
{
|
||||
if(listeMap == null)
|
||||
{
|
||||
//plugin.getLogger().info("test de nullité");
|
||||
listeMap = new ArrayList<Short>();
|
||||
listeMap.addAll(plugin.mapChargee);
|
||||
}
|
||||
else if(listeMap.equals(plugin.mapChargee) != true)
|
||||
{
|
||||
//plugin.getLogger().info("taille des maps : " + listeMap.size()+ " ; "+ plugin.mapChargee.size());
|
||||
//plugin.getLogger().info("test d'égalité");
|
||||
listeMap.clear();
|
||||
listeMap.addAll(plugin.mapChargee);
|
||||
allsent = false;
|
||||
}
|
||||
if(!allsent)
|
||||
{
|
||||
//plugin.getLogger().info("test 1");
|
||||
if(toIndex > listeMap.size())
|
||||
{
|
||||
//plugin.getLogger().info("test 3");
|
||||
partListe = listeMap.subList(index, listeMap.size());
|
||||
index = listeMap.size();
|
||||
toIndex = listeMap.size() + nbSend;
|
||||
allsent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//plugin.getLogger().info("taille des index : " + index+ " ; "+ toIndex+ ". taille de la map : "
|
||||
// + listeMap.size());
|
||||
//plugin.getLogger().info("test 2");
|
||||
partListe = listeMap.subList(index, toIndex);
|
||||
index = toIndex;
|
||||
toIndex += nbSend;
|
||||
}
|
||||
for(int i= 0; i< partListe.size(); i++)
|
||||
{
|
||||
//plugin.getLogger().info("test 4");
|
||||
MapView map = Bukkit.getMap(partListe.get(i));
|
||||
joueur.sendMap(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import fr.moribus.imageonmap.map.SingleMap;
|
||||
|
||||
public class SendMapOnFrameEvent implements Listener
|
||||
{
|
||||
|
||||
ImageOnMap plugin;
|
||||
Chunk chunk;
|
||||
Entity[] entites;
|
||||
ItemFrame frame;
|
||||
|
||||
SendMapOnFrameEvent(ImageOnMap plug)
|
||||
{
|
||||
plugin = plug;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChunkLoad(ChunkLoadEvent event)
|
||||
{
|
||||
chunk = event.getChunk();
|
||||
entites = chunk.getEntities().clone();
|
||||
for (Entity entite : entites)
|
||||
{
|
||||
if (entite instanceof ItemFrame)
|
||||
{
|
||||
ArrayList<Short> ListeId = plugin.mapChargee;
|
||||
frame = (ItemFrame) entite;
|
||||
ItemStack stack = frame.getItem();
|
||||
if (stack.getType() == Material.MAP && !ListeId.contains(stack.getDurability()))
|
||||
{
|
||||
try
|
||||
{
|
||||
new SingleMap(stack.getDurability()).load();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogger.LogWarning("Could not send frame map", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import fr.moribus.imageonmap.map.SingleMap;
|
||||
|
||||
public class SendMapOnInvEvent implements Listener
|
||||
{
|
||||
ImageOnMap plugin;
|
||||
|
||||
SendMapOnInvEvent(ImageOnMap p)
|
||||
{
|
||||
plugin = p;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInv(PlayerItemHeldEvent event)
|
||||
{
|
||||
Player joueur = event.getPlayer();
|
||||
int slot = event.getNewSlot();
|
||||
ItemStack stack = joueur.getInventory().getItem(slot);
|
||||
|
||||
if (stack != null && stack.getType() == Material.MAP)
|
||||
{
|
||||
|
||||
ArrayList<Short> listeId = plugin.mapChargee;
|
||||
Set<String> cle = plugin.getCustomConfig().getKeys(false);
|
||||
for (String s : cle)
|
||||
{
|
||||
|
||||
if (!listeId.contains(stack.getDurability()))
|
||||
{
|
||||
if (plugin.getCustomConfig().getStringList(s).get(0).equals(String.valueOf(stack.getDurability())))
|
||||
{
|
||||
try
|
||||
{
|
||||
new SingleMap(stack.getDurability()).load();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogger.LogWarning("Could not send inventory map.", e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
public class TacheTraitementMajMap extends TacheTraitementMap
|
||||
{
|
||||
private ImageMap m;
|
||||
|
||||
public TacheTraitementMajMap(ImageMap m, URL url, Player joueur)
|
||||
{
|
||||
super(url);
|
||||
setJoueur(joueur);
|
||||
this.m = m;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traiterMap(BufferedImage img) throws IOException
|
||||
{
|
||||
m.setImage(img);
|
||||
m.save();
|
||||
m.send(getJoueur());
|
||||
}
|
||||
}
|
@ -1,194 +0,0 @@
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import fr.moribus.imageonmap.image.DownloadImageThread;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public abstract class TacheTraitementMap extends BukkitRunnable
|
||||
{
|
||||
private Player joueur;
|
||||
private DownloadImageThread renduImg;
|
||||
private PlayerInventory inv;
|
||||
private ItemStack map;
|
||||
private ImageOnMap plugin;
|
||||
private boolean resized, renamed;
|
||||
private ExecutorService dlImg;
|
||||
private Future<BufferedImage> futurDlImg;
|
||||
private int compteurExec;
|
||||
|
||||
protected TacheTraitementMap(URL url)
|
||||
{
|
||||
renduImg = new DownloadImageThread(url);
|
||||
dlImg = Executors.newSingleThreadExecutor();
|
||||
futurDlImg = dlImg.submit(renduImg);
|
||||
plugin = (ImageOnMap) Bukkit.getPluginManager().getPlugin("ImageOnMap");
|
||||
}
|
||||
|
||||
public TacheTraitementMap(Player j, URL url, boolean rs, boolean rn)
|
||||
{
|
||||
this(url);
|
||||
joueur = j;
|
||||
inv = joueur.getInventory();
|
||||
resized = rs;
|
||||
renamed = rn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
compteurExec = 0;
|
||||
if (!futurDlImg.isDone())
|
||||
{
|
||||
compteurExec++;
|
||||
if (compteurExec > 20)
|
||||
{
|
||||
joueur.sendMessage("TIMEOUT: the render took too many time");
|
||||
futurDlImg.cancel(true);
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!futurDlImg.isCancelled())
|
||||
{
|
||||
cancel();
|
||||
int nbImage = 1;
|
||||
if (plugin.getConfig().getInt("Limit-map-by-server") != 0 && nbImage + ImgUtility.getNombreDeMaps(plugin) > plugin.getConfig().getInt("Limit-map-by-server"))
|
||||
{
|
||||
joueur.sendMessage("ERROR: cannot render " + nbImage + " picture(s): the limit of maps per server would be exceeded.");
|
||||
return;
|
||||
}
|
||||
if (!joueur.hasPermission("imageonmap.nolimit"))
|
||||
{
|
||||
if (plugin.getConfig().getInt("Limit-map-by-player") != 0 && nbImage + ImgUtility.getNombreDeMapsParJoueur(plugin, joueur.getName()) > plugin.getConfig().getInt("Limit-map-by-player"))
|
||||
{
|
||||
joueur.sendMessage(ChatColor.RED + "ERROR: cannot render " + nbImage + " picture(s): the limit of maps allowed for you (per player) would be exceeded.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
BufferedImage dlimg = futurDlImg.get();
|
||||
traiterMap(dlimg);
|
||||
joueur.sendMessage("Image successfuly downloaded !");
|
||||
}
|
||||
catch (InterruptedException ex)
|
||||
{
|
||||
joueur.sendMessage(ChatColor.RED + "Download task has been interrupted unexpectedly. Check server console for details.");
|
||||
PluginLogger.LogError("Download task has been interrupted", ex);
|
||||
}
|
||||
catch (ExecutionException ex)
|
||||
{
|
||||
joueur.sendMessage(ChatColor.RED + "Download failed : " + ex.getMessage());
|
||||
joueur.sendMessage(ChatColor.RED + "Please check your URL");
|
||||
}
|
||||
catch(IOException ex)
|
||||
{
|
||||
joueur.sendMessage(ChatColor.RED + "Failed to process the image. Check server console for details.");
|
||||
PluginLogger.LogError("Image processing failed", ex);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
joueur.sendMessage(ChatColor.RED + "An error occured. See the console for details");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void traiterMap(BufferedImage img) throws IOException;
|
||||
|
||||
protected Player getJoueur()
|
||||
{
|
||||
return joueur;
|
||||
}
|
||||
|
||||
protected void setJoueur(Player joueur)
|
||||
{
|
||||
this.joueur = joueur;
|
||||
}
|
||||
|
||||
protected DownloadImageThread getRenduImg()
|
||||
{
|
||||
return renduImg;
|
||||
}
|
||||
|
||||
protected void setRenduImg(DownloadImageThread renduImg)
|
||||
{
|
||||
this.renduImg = renduImg;
|
||||
}
|
||||
|
||||
protected PlayerInventory getInv()
|
||||
{
|
||||
return inv;
|
||||
}
|
||||
|
||||
protected void setInv(PlayerInventory inv)
|
||||
{
|
||||
this.inv = inv;
|
||||
}
|
||||
|
||||
protected ItemStack getMap()
|
||||
{
|
||||
return map;
|
||||
}
|
||||
|
||||
protected void setMap(ItemStack map)
|
||||
{
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
protected ImageOnMap getPlugin()
|
||||
{
|
||||
return plugin;
|
||||
}
|
||||
|
||||
protected void setPlugin(ImageOnMap plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
protected boolean isResized()
|
||||
{
|
||||
return resized;
|
||||
}
|
||||
|
||||
protected void setResized(boolean resized)
|
||||
{
|
||||
this.resized = resized;
|
||||
}
|
||||
|
||||
protected boolean isRenamed()
|
||||
{
|
||||
return renamed;
|
||||
}
|
||||
|
||||
protected void setRenamed(boolean renamed)
|
||||
{
|
||||
this.renamed = renamed;
|
||||
}
|
||||
|
||||
protected int getCompteurExec()
|
||||
{
|
||||
return compteurExec;
|
||||
}
|
||||
|
||||
protected void setCompteurExec(int compteurExec)
|
||||
{
|
||||
this.compteurExec = compteurExec;
|
||||
}
|
||||
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.ImageMap.Type;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
public class TacheTraitementNouvelleMap extends TacheTraitementMap
|
||||
{
|
||||
private final Type type;
|
||||
|
||||
public TacheTraitementNouvelleMap(Player player, URL url, Type type, boolean rs, boolean rn)
|
||||
{
|
||||
super(player, url, rs, rn);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traiterMap(BufferedImage img) throws IOException
|
||||
{
|
||||
ImageMap m = ImageMap.Type.createNewMap(type, img, getJoueur());
|
||||
|
||||
m.load();
|
||||
m.give(getJoueur().getInventory());
|
||||
m.save();
|
||||
}
|
||||
|
||||
}
|
268
src/main/java/fr/moribus/imageonmap/commands/Command.java
Normal file
268
src/main/java/fr/moribus/imageonmap/commands/Command.java
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands;
|
||||
|
||||
import fr.moribus.imageonmap.commands.CommandException.Reason;
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.MapManager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
abstract public class Command
|
||||
{
|
||||
static private final String IMAGEONMAP_GLOBAL_PERMISSION = "imageonmap.userender";
|
||||
|
||||
protected final Commands commandGroup;
|
||||
protected final String commandName;
|
||||
protected final String usageParameters;
|
||||
protected final String commandDescription;
|
||||
protected final String[] aliases;
|
||||
|
||||
protected CommandSender sender;
|
||||
protected String[] args;
|
||||
|
||||
abstract protected void run() throws CommandException;
|
||||
|
||||
public Command(Commands commandGroup)
|
||||
{
|
||||
this.commandGroup = commandGroup;
|
||||
|
||||
CommandInfo commandInfo = this.getClass().getAnnotation(CommandInfo.class);
|
||||
if(commandInfo == null)
|
||||
throw new IllegalArgumentException("Command has no CommandInfo annotation");
|
||||
|
||||
commandName = commandInfo.name().toLowerCase();
|
||||
usageParameters = commandInfo.usageParameters();
|
||||
commandDescription = commandGroup.getDescription(commandName);
|
||||
aliases = commandInfo.aliases();
|
||||
}
|
||||
|
||||
public boolean canExecute(CommandSender sender)
|
||||
{
|
||||
return sender.hasPermission("imageonmap." + commandGroup.getUsualName())
|
||||
|| sender.hasPermission(IMAGEONMAP_GLOBAL_PERMISSION);
|
||||
}
|
||||
|
||||
protected List<String> complete() throws CommandException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void execute(CommandSender sender, String[] args)
|
||||
{
|
||||
this.sender = sender; this.args = args;
|
||||
try
|
||||
{
|
||||
if(!canExecute(sender))
|
||||
throw new CommandException(this, Reason.SENDER_NOT_AUTHORIZED);
|
||||
run();
|
||||
}
|
||||
catch(CommandException ex)
|
||||
{
|
||||
warning(ex.getReasonString());
|
||||
}
|
||||
this.sender = null; this.args = null;
|
||||
}
|
||||
|
||||
public List<String> tabComplete(CommandSender sender, String[] args)
|
||||
{
|
||||
List<String> result = null;
|
||||
this.sender = sender; this.args = args;
|
||||
try
|
||||
{
|
||||
if(canExecute(sender))
|
||||
result = complete();
|
||||
}
|
||||
catch(CommandException ex){}
|
||||
|
||||
this.sender = null; this.args = null;
|
||||
if(result == null) result = new ArrayList<String>();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public String getUsageString()
|
||||
{
|
||||
return "/" + commandGroup.getUsualName() + " " + commandName + " " + usageParameters;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return commandName;
|
||||
}
|
||||
|
||||
public Commands getCommandGroup()
|
||||
{
|
||||
return commandGroup;
|
||||
}
|
||||
|
||||
public String[] getAliases()
|
||||
{
|
||||
return aliases;
|
||||
}
|
||||
|
||||
public boolean matches(String name)
|
||||
{
|
||||
if(commandName.equals(name.toLowerCase())) return true;
|
||||
|
||||
for(String alias : aliases)
|
||||
{
|
||||
if(alias.equals(name)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
///////////// Common methods for commands /////////////
|
||||
|
||||
protected void throwInvalidArgument(String reason) throws CommandException
|
||||
{
|
||||
throw new CommandException(this, Reason.INVALID_PARAMETERS, reason);
|
||||
}
|
||||
|
||||
protected Player playerSender() throws CommandException
|
||||
{
|
||||
if(!(sender instanceof Player))
|
||||
throw new CommandException(this, Reason.COMMANDSENDER_EXPECTED_PLAYER);
|
||||
return (Player)sender;
|
||||
}
|
||||
|
||||
protected ImageMap getMapFromArgs() throws CommandException
|
||||
{
|
||||
return getMapFromArgs(playerSender(), 0, true);
|
||||
}
|
||||
|
||||
protected ImageMap getMapFromArgs(Player player, int index, boolean expand) throws CommandException
|
||||
{
|
||||
if(args.length <= index) throwInvalidArgument("You need to give a map name.");
|
||||
|
||||
ImageMap map;
|
||||
String mapName = args[index];
|
||||
|
||||
if(expand)
|
||||
{
|
||||
for(int i = index + 1, c = args.length; i < c; i++)
|
||||
{
|
||||
mapName += " " + args[i];
|
||||
}
|
||||
}
|
||||
|
||||
mapName = mapName.trim();
|
||||
|
||||
map = MapManager.getMap(player.getUniqueId(), mapName);
|
||||
|
||||
if(map == null) error("This map does not exist.");
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
///////////// Methods for command execution /////////////
|
||||
|
||||
static protected void info(CommandSender sender, String message)
|
||||
{
|
||||
sender.sendMessage("§7" + message);
|
||||
}
|
||||
|
||||
protected void info(String message)
|
||||
{
|
||||
info(sender, message);
|
||||
}
|
||||
|
||||
static protected void warning(CommandSender sender, String message)
|
||||
{
|
||||
sender.sendMessage("§c" + message);
|
||||
}
|
||||
|
||||
protected void warning(String message)
|
||||
{
|
||||
info(sender, message);
|
||||
}
|
||||
|
||||
protected void error(String message) throws CommandException
|
||||
{
|
||||
throw new CommandException(this, Reason.COMMAND_ERROR, message);
|
||||
}
|
||||
|
||||
protected void tellRaw(String rawMessage) throws CommandException
|
||||
{
|
||||
Player player = playerSender();
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(),
|
||||
"tellraw " + player.getName() + " " + rawMessage);
|
||||
}
|
||||
|
||||
///////////// Methods for autocompletion /////////////
|
||||
|
||||
protected List<String> getMatchingSubset(String prefix, String... list)
|
||||
{
|
||||
return getMatchingSubset(Arrays.asList(list), prefix);
|
||||
}
|
||||
|
||||
protected List<String> getMatchingSubset(Iterable<? extends String> list, String prefix)
|
||||
{
|
||||
List<String> matches = new ArrayList<String>();
|
||||
|
||||
for(String item : list)
|
||||
{
|
||||
if(item.startsWith(prefix)) matches.add(item);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
protected List<String> getMatchingPlayerNames(String prefix)
|
||||
{
|
||||
return getMatchingPlayerNames(Bukkit.getOnlinePlayers(), prefix);
|
||||
}
|
||||
|
||||
protected List<String> getMatchingPlayerNames(Iterable<? extends Player> players, String prefix)
|
||||
{
|
||||
List<String> matches = new ArrayList<String>();
|
||||
|
||||
for(Player player : players)
|
||||
{
|
||||
if(player.getName().startsWith(prefix)) matches.add(player.getName());
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
protected List<String> getMatchingMapNames(Player player, String prefix)
|
||||
{
|
||||
return getMatchingToolNames(MapManager.getMapList(player.getUniqueId()), prefix);
|
||||
}
|
||||
|
||||
protected List<String> getMatchingToolNames(Iterable<? extends ImageMap> maps, String prefix)
|
||||
{
|
||||
List<String> matches = new ArrayList<String>();
|
||||
|
||||
for(ImageMap map : maps)
|
||||
{
|
||||
if(map.getId().startsWith(prefix)) matches.add(map.getId());
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands;
|
||||
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
|
||||
public class CommandException extends Exception
|
||||
{
|
||||
public enum Reason
|
||||
{
|
||||
COMMANDSENDER_EXPECTED_PLAYER,
|
||||
INVALID_PARAMETERS,
|
||||
COMMAND_ERROR,
|
||||
SENDER_NOT_AUTHORIZED
|
||||
}
|
||||
|
||||
private final Reason reason;
|
||||
private final Command command;
|
||||
private final String extra;
|
||||
|
||||
public CommandException(Command command, Reason reason, String extra)
|
||||
{
|
||||
this.command = command;
|
||||
this.reason = reason;
|
||||
this.extra = extra;
|
||||
}
|
||||
|
||||
public CommandException(Command command, Reason reason)
|
||||
{
|
||||
this(command, reason, "");
|
||||
}
|
||||
|
||||
public Reason getReason() { return reason; }
|
||||
|
||||
public String getReasonString()
|
||||
{
|
||||
switch(reason)
|
||||
{
|
||||
case COMMANDSENDER_EXPECTED_PLAYER:
|
||||
return "You must be a player to use this command.";
|
||||
case INVALID_PARAMETERS:
|
||||
return "Invalid arguments : " + extra +"\n§r" +
|
||||
"Usage : " + command.getUsageString() + "\n" +
|
||||
"For more information, use /" +
|
||||
command.getCommandGroup().getUsualName() + " help " +
|
||||
command.getName();
|
||||
case COMMAND_ERROR:
|
||||
return extra.isEmpty() ? "An unknown error suddenly happened." : extra;
|
||||
case SENDER_NOT_AUTHORIZED:
|
||||
return "You do not have the permission to use this command.";
|
||||
default:
|
||||
PluginLogger.warning("Unknown CommandException caught", this);
|
||||
return "An unknown error suddenly happened.";
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface CommandInfo
|
||||
{
|
||||
String name();
|
||||
String usageParameters() default "";
|
||||
String[] aliases() default {};
|
||||
}
|
329
src/main/java/fr/moribus/imageonmap/commands/Commands.java
Normal file
329
src/main/java/fr/moribus/imageonmap/commands/Commands.java
Normal file
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands;
|
||||
|
||||
import fr.moribus.imageonmap.commands.maptool.MigrateCommand;
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import fr.moribus.imageonmap.commands.maptool.*;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
|
||||
public enum Commands implements TabCompleter, CommandExecutor
|
||||
{
|
||||
MAPTOOL(new String[]{"maptool"},
|
||||
NewCommand.class,
|
||||
ListCommand.class,
|
||||
GetCommand.class,
|
||||
DeleteConfirmCommand.class,
|
||||
DeleteNoConfirmCommand.class,
|
||||
GetRemainingCommand.class,
|
||||
MigrateCommand.class
|
||||
),
|
||||
TOMAP(MAPTOOL, NewCommand.class, "tomap");
|
||||
|
||||
static private final Commands[] commandGroups = Commands.class.getEnumConstants();
|
||||
private final Commands shortcutCommandGroup;
|
||||
private final String[] names;
|
||||
private final Class<? extends Command>[] commandsClasses;
|
||||
private final ArrayList<Command> commands = new ArrayList<>();
|
||||
private final HashMap<String, String> commandsDescriptions = new HashMap<>();
|
||||
private String description = "";
|
||||
|
||||
private Commands(Commands shortcutCommandGroup, Class<? extends Command> commandClass, String ... names)
|
||||
{
|
||||
this.names = names;
|
||||
this.commandsClasses = new Class[]{commandClass};
|
||||
this.shortcutCommandGroup = shortcutCommandGroup;
|
||||
initCommands();
|
||||
}
|
||||
|
||||
private Commands(String[] names, Class<? extends Command> ... commandsClasses)
|
||||
{
|
||||
this.names = names;
|
||||
this.commandsClasses = commandsClasses;
|
||||
this.shortcutCommandGroup = null;
|
||||
initDescriptions();
|
||||
initCommands();
|
||||
}
|
||||
|
||||
private void initDescriptions()
|
||||
{
|
||||
String fileName = "help/" + getUsualName() + ".txt";
|
||||
InputStream stream = getClass().getClassLoader().getResourceAsStream(fileName);
|
||||
if(stream == null)
|
||||
{
|
||||
PluginLogger.warning("Could not load description file for the " + getUsualName() + " command");
|
||||
return;
|
||||
}
|
||||
|
||||
Scanner scanner = new Scanner(stream);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
//Getting the group's description
|
||||
//And then each command's description
|
||||
int colonIndex, firstSpaceIndex;
|
||||
boolean isGroupDescription = true;
|
||||
while (scanner.hasNextLine())
|
||||
{
|
||||
String line = scanner.nextLine();
|
||||
colonIndex = line.indexOf(':');
|
||||
if(isGroupDescription)
|
||||
{
|
||||
firstSpaceIndex = line.indexOf(' ');
|
||||
if(colonIndex > 0 && firstSpaceIndex > colonIndex)
|
||||
isGroupDescription = false;
|
||||
}
|
||||
|
||||
if(isGroupDescription)
|
||||
{
|
||||
builder.append(line).append('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
commandsDescriptions.put(line.substring(0, colonIndex).trim(),
|
||||
line.substring(colonIndex + 1).trim());
|
||||
}
|
||||
}
|
||||
|
||||
scanner.close();
|
||||
description = builder.toString().trim();
|
||||
|
||||
}
|
||||
|
||||
private void initCommands()
|
||||
{
|
||||
for (Class<? extends Command> commandClass : commandsClasses)
|
||||
{
|
||||
addCommand(commandClass);
|
||||
}
|
||||
|
||||
if(!isShortcutCommand()) addCommand(HelpCommand.class);
|
||||
}
|
||||
|
||||
private void addCommand(Class<? extends Command> commandClass)
|
||||
{
|
||||
Constructor<? extends Command> constructor;
|
||||
try
|
||||
{
|
||||
constructor = commandClass.getConstructor(Commands.class);
|
||||
commands.add(constructor.newInstance(isShortcutCommand() ? shortcutCommandGroup : this));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLogger.warning("Exception while initializing command", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean executeMatchingCommand(CommandSender sender, String[] args)
|
||||
{
|
||||
if(isShortcutCommand())
|
||||
{
|
||||
commands.get(0).execute(sender, args);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(args.length <= 0)
|
||||
{
|
||||
sender.sendMessage(getUsage()); return false;
|
||||
}
|
||||
|
||||
String commandName = args[0];
|
||||
String[] commandArgs = getCommandArgsFromGroupArgs(args);
|
||||
|
||||
return executeMatchingCommand(sender, commandName, commandArgs);
|
||||
}
|
||||
|
||||
private boolean executeMatchingCommand(CommandSender sender, String commandName, String[] args)
|
||||
{
|
||||
Command command = getMatchingCommand(commandName);
|
||||
if(command != null)
|
||||
{
|
||||
command.execute(sender, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
sender.sendMessage(getUsage());
|
||||
}
|
||||
return command != null;
|
||||
}
|
||||
|
||||
static public void init(JavaPlugin plugin)
|
||||
{
|
||||
org.bukkit.command.PluginCommand bukkitCommand;
|
||||
for(Commands commandGroup : commandGroups)
|
||||
{
|
||||
bukkitCommand = plugin.getCommand(commandGroup.getUsualName());
|
||||
bukkitCommand.setAliases(commandGroup.getAliases());
|
||||
bukkitCommand.setExecutor(commandGroup);
|
||||
bukkitCommand.setTabCompleter(commandGroup);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, org.bukkit.command.Command cmd, String label, String[] args)
|
||||
{
|
||||
return tabComplete(sender, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, org.bukkit.command.Command cmd, String label, String[] args)
|
||||
{
|
||||
return executeMatchingCommand(sender, args);
|
||||
}
|
||||
|
||||
public List<String> tabComplete(CommandSender sender, String[] args)
|
||||
{
|
||||
if(isShortcutCommand()) return commands.get(0).tabComplete(sender, args);
|
||||
if(args.length <= 1) return tabComplete(sender, args.length == 1 ? args[0] : null);
|
||||
String commandName = args[0];
|
||||
String[] commandArgs = getCommandArgsFromGroupArgs(args);
|
||||
return tabCompleteMatching(sender, commandName, commandArgs);
|
||||
}
|
||||
|
||||
public List<String> tabComplete(CommandSender sender, String commandName)
|
||||
{
|
||||
ArrayList<String> matchingCommands = new ArrayList<String>();
|
||||
for(Command command : commands)
|
||||
{
|
||||
if(!command.canExecute(sender)) continue;
|
||||
if(commandName == null || command.getName().startsWith(commandName.toLowerCase()))
|
||||
{
|
||||
matchingCommands.add(command.getName());
|
||||
}
|
||||
}
|
||||
return matchingCommands;
|
||||
}
|
||||
|
||||
private List<String> tabCompleteMatching(CommandSender sender, String commandName, String[] args)
|
||||
{
|
||||
Command command = getMatchingCommand(commandName);
|
||||
if(command != null)
|
||||
{
|
||||
return command.tabComplete(sender, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
}
|
||||
|
||||
static public String[] getCommandArgsFromGroupArgs(String[] args)
|
||||
{
|
||||
String[] commandArgs = new String[args.length - 1];
|
||||
|
||||
for(int i = 0; i < commandArgs.length; i++)
|
||||
{
|
||||
commandArgs[i] = args[i + 1];
|
||||
}
|
||||
|
||||
return commandArgs;
|
||||
}
|
||||
|
||||
public Command getMatchingCommand(String commandName)
|
||||
{
|
||||
for(Command command : commands)
|
||||
{
|
||||
if(command.matches(commandName))
|
||||
{
|
||||
return command;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static public boolean execute(CommandSender sender, String commandName, String[] args)
|
||||
{
|
||||
Commands commandGroup = getMatchingCommandGroup(commandName);
|
||||
if(commandGroup == null) return false;
|
||||
commandGroup.executeMatchingCommand(sender, args);
|
||||
return true;
|
||||
}
|
||||
|
||||
static public List<String> tabComplete(CommandSender sender, String commandName, String[] args)
|
||||
{
|
||||
Commands commandGroup = getMatchingCommandGroup(commandName);
|
||||
if(commandGroup == null) return new ArrayList<String>();
|
||||
return commandGroup.tabComplete(sender, args);
|
||||
}
|
||||
|
||||
static private Commands getMatchingCommandGroup(String commandName)
|
||||
{
|
||||
Commands commandGroup = null;
|
||||
for(Commands tCommandGroup : commandGroups)
|
||||
{
|
||||
if(tCommandGroup.matches(commandName))
|
||||
{
|
||||
commandGroup = tCommandGroup;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return commandGroup;
|
||||
}
|
||||
|
||||
public boolean matches(String name)
|
||||
{
|
||||
name = name.toLowerCase();
|
||||
for(String commandName : names)
|
||||
{
|
||||
if(commandName.equals(name)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String[] getCommandsNames()
|
||||
{
|
||||
String[] commandsNames = new String[commands.size()];
|
||||
|
||||
for(int i = 0; i < commands.size(); i++)
|
||||
{
|
||||
commandsNames[i] = commands.get(i).getName();
|
||||
}
|
||||
|
||||
return commandsNames;
|
||||
}
|
||||
|
||||
protected String getUsage()
|
||||
{
|
||||
if(isShortcutCommand()) return "§cUsage : " + commands.get(0).getUsageString();
|
||||
return "§cUsage : /" + getUsualName() +
|
||||
" <" + StringUtils.join(getCommandsNames(), "|") + ">";
|
||||
}
|
||||
|
||||
public String getUsualName() { return names[0]; }
|
||||
public String[] getNames() { return names.clone(); }
|
||||
public List<String> getAliases() { return Arrays.asList(names).subList(1, names.length);}
|
||||
public Command[] getCommands() { return commands.toArray(new Command[commands.size()]);}
|
||||
public String getDescription() { return description; }
|
||||
public String getDescription(String commandName) { return commandsDescriptions.get(commandName); }
|
||||
public boolean isShortcutCommand() { return shortcutCommandGroup != null; }
|
||||
public Commands getShortcutCommandGroup() { return shortcutCommandGroup; }
|
||||
|
||||
}
|
140
src/main/java/fr/moribus/imageonmap/commands/HelpCommand.java
Normal file
140
src/main/java/fr/moribus/imageonmap/commands/HelpCommand.java
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands;
|
||||
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
@CommandInfo(name = "help", usageParameters = "<command name>")
|
||||
public class HelpCommand extends Command
|
||||
{
|
||||
|
||||
public HelpCommand(Commands commandGroup) {
|
||||
super(commandGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() throws CommandException
|
||||
{
|
||||
if(args.length < 1)
|
||||
groupHelp();
|
||||
else
|
||||
commandHelp();
|
||||
}
|
||||
|
||||
private void groupHelp() throws CommandException
|
||||
{
|
||||
sender.sendMessage(commandGroup.getDescription());
|
||||
|
||||
String tCommandName;
|
||||
String tDescription;
|
||||
for(Command tCommand: commandGroup.getCommands())
|
||||
{
|
||||
if(!tCommand.canExecute(sender)) continue;
|
||||
tCommandName = tCommand.getName();
|
||||
tDescription = commandGroup.getDescription(tCommandName);
|
||||
tCommandName = commandGroup.getUsualName() + " " + tCommandName;
|
||||
if(tDescription == null)
|
||||
sender.sendMessage("§6/" + tCommandName + "§r");
|
||||
else
|
||||
sender.sendMessage("§6/" + tCommandName + " : §r" + tDescription);
|
||||
}
|
||||
}
|
||||
|
||||
private void commandHelp() throws CommandException
|
||||
{
|
||||
Command command = commandGroup.getMatchingCommand(args[0]);
|
||||
if(command == null)
|
||||
{
|
||||
error("The specified command does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!command.canExecute(sender))
|
||||
warning("You do not have the permission to use this command.");
|
||||
|
||||
String message = "§l§6 ||== ImageOnMap help ==||\n" +
|
||||
"§l§6 |Usage : §r" + command.getUsageString();
|
||||
|
||||
try
|
||||
{
|
||||
String help = getHelpText(command);
|
||||
if(help.isEmpty())
|
||||
{
|
||||
sender.sendMessage(message);
|
||||
warning("There is no help message for this command.");
|
||||
}
|
||||
else
|
||||
{
|
||||
sender.sendMessage(message + "\n" + help);
|
||||
}
|
||||
}
|
||||
catch(IOException ex)
|
||||
{
|
||||
sender.sendMessage(message);
|
||||
warning("Could not read help for this command.");
|
||||
PluginLogger.warning("Could not read help for the command : " + command.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private String getHelpText(Command command) throws IOException
|
||||
{
|
||||
String fileName = "help/"+ commandGroup.getUsualName() +
|
||||
"/" + command.getName() + ".txt";
|
||||
|
||||
StringBuilder result = new StringBuilder("");
|
||||
|
||||
InputStream stream = getClass().getClassLoader().getResourceAsStream(fileName);
|
||||
if(stream == null) return "";
|
||||
|
||||
Scanner scanner = new Scanner(stream);
|
||||
|
||||
while (scanner.hasNextLine())
|
||||
{
|
||||
String line = scanner.nextLine();
|
||||
result.append("§l§9 |§r").append(line).append("\n");
|
||||
}
|
||||
|
||||
scanner.close();
|
||||
|
||||
return result.toString().trim();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List<String> complete() throws CommandException
|
||||
{
|
||||
if(args.length != 1) return null;
|
||||
|
||||
ArrayList<String> matches = new ArrayList<String>();
|
||||
|
||||
for(Command command : commandGroup.getCommands())
|
||||
{
|
||||
if(command.getName().startsWith(args[0]))
|
||||
matches.add(command.getName());
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
package fr.moribus.imageonmap.commands;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.ImgUtility;
|
||||
import fr.moribus.imageonmap.TacheTraitementMap;
|
||||
import fr.moribus.imageonmap.TacheTraitementNouvelleMap;
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class ImageRenduCommande implements CommandExecutor
|
||||
{
|
||||
Player joueur;
|
||||
boolean renderName, imgSvg;
|
||||
ImageOnMap plugin;
|
||||
boolean resize, rename;
|
||||
|
||||
public ImageRenduCommande(ImageOnMap p)
|
||||
{
|
||||
plugin = p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)
|
||||
{
|
||||
// On vérifie si celui qui exécute la commande est bien un joueur
|
||||
if (!ImgUtility.VerifierIdentite(sender))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
joueur = (Player) sender;
|
||||
resize = false;
|
||||
rename = true;
|
||||
|
||||
if (!joueur.hasPermission("imageonmap.userender"))
|
||||
{
|
||||
joueur.sendMessage("You are not allowed to use this command ( " + cmd.getName() + " )!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length < 1)
|
||||
{
|
||||
joueur.sendMessage(ChatColor.RED + "You must enter image url.");
|
||||
return false;
|
||||
}
|
||||
|
||||
URL url;
|
||||
try
|
||||
{
|
||||
url = new URL(args[0]);
|
||||
}
|
||||
catch (MalformedURLException ex)
|
||||
{
|
||||
joueur.sendMessage("§cInvalid URL.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageMap.Type type = ImageMap.Type.POSTER;
|
||||
|
||||
if (args.length >= 2)
|
||||
{
|
||||
if(args[1].equals("resize"))
|
||||
{
|
||||
type = ImageMap.Type.SINGLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
joueur.sendMessage("Invalid argument.");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TacheTraitementMap tache = new TacheTraitementNouvelleMap(joueur, url, type, resize, rename);
|
||||
tache.runTaskTimer(plugin, 0, 5);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,265 +0,0 @@
|
||||
package fr.moribus.imageonmap.commands;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.ImgUtility;
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import fr.moribus.imageonmap.SavedPoster;
|
||||
import fr.moribus.imageonmap.TacheTraitementMajMap;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.PosterMap;
|
||||
import fr.moribus.imageonmap.map.SingleMap;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class MapToolCommand implements CommandExecutor
|
||||
{
|
||||
short id;
|
||||
ImageOnMap plugin;
|
||||
MapView map;
|
||||
Player joueur;
|
||||
Inventory inv;
|
||||
|
||||
public MapToolCommand(ImageOnMap p)
|
||||
{
|
||||
plugin = p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args)
|
||||
{
|
||||
if (!ImgUtility.VerifierIdentite(sender))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
joueur = (Player) sender;
|
||||
inv = joueur.getInventory();
|
||||
|
||||
if (args.length < 1)
|
||||
{
|
||||
joueur.sendMessage("Map tools usage:"
|
||||
+ "\n/" + ChatColor.GOLD + label + ChatColor.RESET + " get [id]: get the map corresponding to this id"
|
||||
+ "\n/" + ChatColor.GOLD + label + ChatColor.RESET + " delete [id]: remove the map corresponding to this id"
|
||||
+ "\n/" + ChatColor.GOLD + label + ChatColor.RESET + " list: show all ids of maps in your possession");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args[0].equalsIgnoreCase("get"))
|
||||
{
|
||||
try
|
||||
{
|
||||
id = Short.parseShort(args[1]);
|
||||
}
|
||||
catch (NumberFormatException err)
|
||||
{
|
||||
joueur.sendMessage("you must enter a number !");
|
||||
return true;
|
||||
}
|
||||
|
||||
SingleMap smap;
|
||||
try
|
||||
{
|
||||
smap = new SingleMap(id);
|
||||
smap.load();
|
||||
if (inv.firstEmpty() == -1)
|
||||
{
|
||||
joueur.sendMessage("Your inventory is full, you can't take the map !");
|
||||
return true;
|
||||
}
|
||||
|
||||
smap.give(joueur.getInventory());
|
||||
joueur.sendMessage("Map " + ChatColor.ITALIC + id + ChatColor.RESET + " was added in your inventory.");
|
||||
|
||||
}
|
||||
catch (IllegalArgumentException ex)
|
||||
{
|
||||
joueur.sendMessage(ChatColor.RED + "Invalid argument : " + ex.getMessage());
|
||||
}
|
||||
catch(IOException ex)
|
||||
{
|
||||
joueur.sendMessage(ChatColor.RED + "Unable to load the map. Check server console for details.");
|
||||
PluginLogger.LogError("Could not load the map", ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (args[0].equalsIgnoreCase("set"))
|
||||
{
|
||||
ImageMap smap;
|
||||
try
|
||||
{
|
||||
if (args[1].startsWith("poster"))
|
||||
{
|
||||
smap = new PosterMap(args[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
id = Short.parseShort(args[1]);
|
||||
smap = new SingleMap(id);
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException err)
|
||||
{
|
||||
joueur.sendMessage("you must enter a number !");
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
joueur.sendMessage(ChatColor.RED + "ERROR while loading maps");
|
||||
return true;
|
||||
}
|
||||
|
||||
if(args.length < 3)
|
||||
{
|
||||
joueur.sendMessage("§cYou must enter a valid URL.");
|
||||
return true;
|
||||
}
|
||||
|
||||
URL url;
|
||||
try
|
||||
{
|
||||
url = new URL(args[2]);
|
||||
}
|
||||
catch (MalformedURLException ex)
|
||||
{
|
||||
joueur.sendMessage("§Invalid URL.");
|
||||
return true;
|
||||
}
|
||||
|
||||
TacheTraitementMajMap tache = new TacheTraitementMajMap(smap, url, joueur);
|
||||
tache.runTaskTimer(plugin, 0, 5);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (args[0].equalsIgnoreCase("delete"))
|
||||
{
|
||||
if (!joueur.hasPermission("imageonmap.usermmap"))
|
||||
{
|
||||
joueur.sendMessage("You are not allowed to delete map !");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 2 && args[1].startsWith("poster"))
|
||||
{
|
||||
SavedPoster poster = new SavedPoster(plugin, args[1]);
|
||||
try
|
||||
{
|
||||
poster.Remove();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
joueur.sendMessage("Unable to remove the entire poster, check the server log for more information");
|
||||
PluginLogger.LogError("Unable to remove the entire poster", ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length <= 1)
|
||||
{
|
||||
if (joueur.getItemInHand().getType() == Material.MAP)
|
||||
{
|
||||
id = joueur.getItemInHand().getDurability();
|
||||
}
|
||||
else
|
||||
{
|
||||
joueur.sendMessage(ChatColor.RED + "You must hold a map or enter an id");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
id = Short.parseShort(args[1]);
|
||||
}
|
||||
catch (NumberFormatException err)
|
||||
{
|
||||
joueur.sendMessage("you must enter a number !");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = ImgUtility.RemoveMap(plugin, id);
|
||||
|
||||
if (success)
|
||||
{
|
||||
joueur.sendMessage("Map#" + id + " was deleted");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
joueur.sendMessage(ChatColor.RED + "Can't delete delete Map#" + id + ": check the server log");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
else if (args[0].equalsIgnoreCase("list"))
|
||||
{
|
||||
String msg = "", msg2 = "";
|
||||
int compteur = 0;
|
||||
ArrayList<String> liste = new ArrayList<String>();
|
||||
|
||||
liste = ImgUtility.getListMapByPlayer(plugin, joueur.getName());
|
||||
|
||||
for (; compteur < liste.size(); compteur++)
|
||||
{
|
||||
msg += liste.get(compteur) + " ";
|
||||
}
|
||||
|
||||
SavedPoster tmp = new SavedPoster(plugin);
|
||||
ArrayList<String> listePoster = tmp.getListMapByPlayer(plugin, joueur.getName());
|
||||
for (int i = 0; i < listePoster.size(); i++)
|
||||
{
|
||||
msg2 += listePoster.get(i) + " ";
|
||||
}
|
||||
joueur.sendMessage(msg
|
||||
+ "\nYou have rendered " + ChatColor.DARK_PURPLE + (compteur + 1) + ChatColor.RESET + " pictures");
|
||||
joueur.sendMessage("Your posters: \n" + msg2);
|
||||
|
||||
}
|
||||
|
||||
else if (args[0].equalsIgnoreCase("getrest"))
|
||||
{
|
||||
if (plugin.getRemainingMaps(joueur.getName()) == null)
|
||||
{
|
||||
joueur.sendMessage("All maps have already be placed in your inventory");
|
||||
return true;
|
||||
}
|
||||
ArrayList<ItemStack> reste = plugin.getRemainingMaps(joueur.getName());
|
||||
ArrayList<ItemStack> restant = new ArrayList<ItemStack>();
|
||||
for (int i = 0; i < reste.size(); i++)
|
||||
{
|
||||
ImgUtility.AddMap(reste.get(i), inv, restant);
|
||||
}
|
||||
if (restant.isEmpty())
|
||||
{
|
||||
plugin.removeRemaingMaps(joueur.getName());
|
||||
joueur.sendMessage("All maps have been placed in your inventory");
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin.setRemainingMaps(joueur.getName(), restant);
|
||||
joueur.sendMessage(restant.size() + " maps can't be placed in your inventory. Please run " + ChatColor.GOLD + "/maptool getrest again");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands.maptool;
|
||||
|
||||
import fr.moribus.imageonmap.commands.*;
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import java.util.List;
|
||||
|
||||
@CommandInfo(name = "delete", usageParameters = "[tool name]")
|
||||
public class DeleteConfirmCommand extends Command
|
||||
{
|
||||
|
||||
public DeleteConfirmCommand(Commands commandGroup) {
|
||||
super(commandGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() throws CommandException
|
||||
{
|
||||
ImageMap map = getMapFromArgs();
|
||||
tellRaw("{text:\"You are going to delete \",extra:[{text:\""+ map.getId() +"\",color:gold},{text:\". Are you sure ? \",color:white}," +
|
||||
"{text:\"[Confirm]\", color:green, clickEvent:{action:run_command,value:\"/maptool delete-noconfirm "+ map.getId() +"\"}, " +
|
||||
"hoverEvent:{action:show_text,value:{text:\"This map will be deleted \",extra:[{text:\"forever\",color:red,bold:true,italic:true,underlined:true}, {text:\" !\", underlined:true}],underlined:true}}}]}");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> complete() throws CommandException
|
||||
{
|
||||
if(args.length == 1)
|
||||
return getMatchingMapNames(playerSender(), args[0]);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands.maptool;
|
||||
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import fr.moribus.imageonmap.commands.*;
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.MapManager;
|
||||
import fr.moribus.imageonmap.map.MapManagerException;
|
||||
import java.util.List;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
||||
@CommandInfo(name = "delete-noconfirm", usageParameters = "[map name]")
|
||||
public class DeleteNoConfirmCommand extends Command
|
||||
{
|
||||
|
||||
public DeleteNoConfirmCommand(Commands commandGroup) {
|
||||
super(commandGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() throws CommandException
|
||||
{
|
||||
Player player = playerSender();
|
||||
ImageMap map = getMapFromArgs();
|
||||
MapManager.clear(player.getInventory(), map);
|
||||
try
|
||||
{
|
||||
MapManager.deleteMap(map);
|
||||
info("Map successfully deleted.");
|
||||
}
|
||||
catch (MapManagerException ex)
|
||||
{
|
||||
PluginLogger.warning("A non-existent map was requested to be deleted", ex);
|
||||
warning("This map does not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> complete() throws CommandException
|
||||
{
|
||||
if(args.length == 1)
|
||||
return getMatchingMapNames(playerSender(), args[0]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands.maptool;
|
||||
|
||||
import fr.moribus.imageonmap.commands.*;
|
||||
import java.util.List;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@CommandInfo(name = "get")
|
||||
public class GetCommand extends Command
|
||||
{
|
||||
public GetCommand(Commands commandGroup) {
|
||||
super(commandGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() throws CommandException
|
||||
{
|
||||
Player player = playerSender();
|
||||
if(getMapFromArgs().give(player))
|
||||
{
|
||||
info("The requested map was too big to fit in your inventory.");
|
||||
info("Use '/maptool getremaining' to get the remaining maps.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> complete() throws CommandException
|
||||
{
|
||||
if(args.length == 1)
|
||||
return getMatchingMapNames(playerSender(), args[0]);
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands.maptool;
|
||||
|
||||
import fr.moribus.imageonmap.commands.Command;
|
||||
import fr.moribus.imageonmap.commands.CommandException;
|
||||
import fr.moribus.imageonmap.commands.CommandInfo;
|
||||
import fr.moribus.imageonmap.commands.Commands;
|
||||
import fr.moribus.imageonmap.ui.MapItemManager;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@CommandInfo(name = "getremaining", aliases = {"getrest"})
|
||||
public class GetRemainingCommand extends Command
|
||||
{
|
||||
public GetRemainingCommand(Commands commandGroup) {
|
||||
super(commandGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() throws CommandException
|
||||
{
|
||||
Player player = playerSender();
|
||||
|
||||
if(MapItemManager.getCacheSize(player) <= 0)
|
||||
{
|
||||
info("You have no remaining map.");
|
||||
return;
|
||||
}
|
||||
|
||||
int givenMaps = MapItemManager.giveCache(player);
|
||||
|
||||
if(givenMaps == 0)
|
||||
{
|
||||
error("Your inventory is full ! Make some space before requesting the remaining maps.");
|
||||
}
|
||||
else
|
||||
{
|
||||
info("There are " + MapItemManager.getCacheSize(player) + " maps remaining.");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands.maptool;
|
||||
|
||||
import fr.moribus.imageonmap.commands.*;
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.MapManager;
|
||||
import java.util.List;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@CommandInfo(name = "list")
|
||||
public class ListCommand extends Command
|
||||
{
|
||||
public ListCommand(Commands commandGroup) {
|
||||
super(commandGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() throws CommandException
|
||||
{
|
||||
Player player = playerSender();
|
||||
List<ImageMap> mapList = MapManager.getMapList(player.getUniqueId());
|
||||
|
||||
if(mapList.isEmpty())
|
||||
{
|
||||
info("No map found.");
|
||||
return;
|
||||
}
|
||||
|
||||
info(mapList.size() + " maps found.");
|
||||
|
||||
String sMapList = mapList.get(0).getId();
|
||||
for(int i = 1, c = mapList.size(); i < c; i++)
|
||||
{
|
||||
sMapList += "§7,§r" + mapList.get(i).getId();
|
||||
}
|
||||
player.sendMessage(sMapList);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands.maptool;
|
||||
|
||||
import fr.moribus.imageonmap.commands.*;
|
||||
import fr.moribus.imageonmap.migration.MigratorExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@CommandInfo(name = "migrate")
|
||||
public class MigrateCommand extends Command
|
||||
{
|
||||
public MigrateCommand(Commands commandGroup) {
|
||||
super(commandGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() throws CommandException
|
||||
{
|
||||
final CommandSender cmdSender = sender;
|
||||
if(MigratorExecutor.isRunning())
|
||||
{
|
||||
error("A migration process is already running. Check console for details.");
|
||||
}
|
||||
else
|
||||
{
|
||||
info("Migration started. See console for details.");
|
||||
MigratorExecutor.migrate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(CommandSender sender)
|
||||
{
|
||||
return sender.isOp();
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands.maptool;
|
||||
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import fr.moribus.imageonmap.commands.Command;
|
||||
import fr.moribus.imageonmap.commands.CommandException;
|
||||
import fr.moribus.imageonmap.commands.CommandInfo;
|
||||
import fr.moribus.imageonmap.commands.Commands;
|
||||
import fr.moribus.imageonmap.image.ImageRendererExecutor;
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.worker.WorkerCallback;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@CommandInfo(name = "new", usageParameters = "<URL> [resize]")
|
||||
public class NewCommand extends Command
|
||||
{
|
||||
public NewCommand(Commands commandGroup) {
|
||||
super(commandGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() throws CommandException
|
||||
{
|
||||
final Player player = playerSender();
|
||||
boolean scaling = false;
|
||||
URL url;
|
||||
|
||||
if(args.length < 1) throwInvalidArgument("You must give an URL to take the image from.");
|
||||
|
||||
try
|
||||
{
|
||||
url = new URL(args[0]);
|
||||
}
|
||||
catch(MalformedURLException ex)
|
||||
{
|
||||
throwInvalidArgument("Invalid URL.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(args.length >= 2)
|
||||
{
|
||||
if(args[1].equals("resize")) scaling = true;
|
||||
}
|
||||
|
||||
info("Rendering ...");
|
||||
ImageRendererExecutor.Render(url, scaling, player.getUniqueId(), new WorkerCallback<ImageMap>()
|
||||
{
|
||||
@Override
|
||||
public void finished(ImageMap result)
|
||||
{
|
||||
player.sendMessage("§7Rendering finished !");
|
||||
if(result.give(player))
|
||||
{
|
||||
info("The rendered map was too big to fit in your inventory.");
|
||||
info("Use '/maptool getremaining' to get the remaining maps.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errored(Throwable exception)
|
||||
{
|
||||
player.sendMessage("§cMap rendering failed : " + exception.getMessage());
|
||||
PluginLogger.warning("Rendering from '{0}' failed", exception, player.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package fr.moribus.imageonmap.image;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
|
||||
public class DownloadImageThread implements Callable<BufferedImage>
|
||||
{
|
||||
private final URL imageURL;
|
||||
private BufferedImage imgSrc;
|
||||
|
||||
public DownloadImageThread(URL imageURL)
|
||||
{
|
||||
this.imageURL = imageURL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage call() throws IOException
|
||||
{
|
||||
imgSrc = ImageIO.read(imageURL);
|
||||
|
||||
if(imgSrc == null) throw new IOException("URL does not points to a valid image.");
|
||||
|
||||
return imgSrc;
|
||||
}
|
||||
|
||||
}
|
115
src/main/java/fr/moribus/imageonmap/image/ImageIOExecutor.java
Normal file
115
src/main/java/fr/moribus/imageonmap/image/ImageIOExecutor.java
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.image;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.worker.Worker;
|
||||
import fr.moribus.imageonmap.worker.WorkerCallback;
|
||||
import fr.moribus.imageonmap.worker.WorkerRunnable;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class ImageIOExecutor extends Worker
|
||||
{
|
||||
static private ImageIOExecutor instance;
|
||||
|
||||
static public void start()
|
||||
{
|
||||
if(instance != null) stop();
|
||||
instance = new ImageIOExecutor();
|
||||
instance.init();
|
||||
}
|
||||
|
||||
static public void stop()
|
||||
{
|
||||
instance.exit();
|
||||
instance = null;
|
||||
}
|
||||
|
||||
private ImageIOExecutor()
|
||||
{
|
||||
super("Image IO");
|
||||
}
|
||||
|
||||
static public void loadImage(final File file, final Renderer mapRenderer)
|
||||
{
|
||||
instance.submitQuery(new WorkerRunnable<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run() throws Exception
|
||||
{
|
||||
BufferedImage image = ImageIO.read(file);
|
||||
mapRenderer.setImage(image);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static public void saveImage(final File file, final BufferedImage image)
|
||||
{
|
||||
instance.submitQuery(new WorkerRunnable<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run() throws Throwable
|
||||
{
|
||||
ImageIO.write(image, "png", file);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static public void saveImage(short mapID, BufferedImage image)
|
||||
{
|
||||
saveImage(ImageOnMap.getPlugin().getImageFile(mapID), image);
|
||||
}
|
||||
|
||||
static public void saveImage(short[] mapsIDs, PosterImage image)
|
||||
{
|
||||
for(int i = 0, c = mapsIDs.length; i < c; i++)
|
||||
{
|
||||
ImageIOExecutor.saveImage(ImageOnMap.getPlugin().getImageFile(mapsIDs[i]), image.getImageAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
static public void deleteImage(ImageMap map)
|
||||
{
|
||||
short[] mapsIDs = map.getMapsIDs();
|
||||
for(int i = 0, c = mapsIDs.length; i < c; i++)
|
||||
{
|
||||
deleteImage(ImageOnMap.getPlugin().getImageFile(mapsIDs[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static public void deleteImage(final File file)
|
||||
{
|
||||
instance.submitQuery(new WorkerRunnable<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run() throws Throwable
|
||||
{
|
||||
Files.delete(file.toPath());
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.image;
|
||||
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.MapManager;
|
||||
import fr.moribus.imageonmap.worker.Worker;
|
||||
import fr.moribus.imageonmap.worker.WorkerCallback;
|
||||
import fr.moribus.imageonmap.worker.WorkerRunnable;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class ImageRendererExecutor extends Worker
|
||||
{
|
||||
static private ImageRendererExecutor instance;
|
||||
|
||||
static public void start()
|
||||
{
|
||||
if(instance != null) stop();
|
||||
instance = new ImageRendererExecutor();
|
||||
instance.init();
|
||||
}
|
||||
|
||||
static public void stop()
|
||||
{
|
||||
instance.exit();
|
||||
instance = null;
|
||||
}
|
||||
|
||||
private ImageRendererExecutor()
|
||||
{
|
||||
super("Image IO", true);
|
||||
}
|
||||
|
||||
static public void Test(WorkerCallback callback)
|
||||
{
|
||||
instance.submitQuery(new WorkerRunnable<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run() throws Throwable
|
||||
{
|
||||
Thread.sleep(5000);
|
||||
return null;
|
||||
}
|
||||
}, callback);
|
||||
}
|
||||
|
||||
static public void Render(final URL url, final boolean scaling, final UUID playerUUID, WorkerCallback<ImageMap> callback)
|
||||
{
|
||||
instance.submitQuery(new WorkerRunnable<ImageMap>()
|
||||
{
|
||||
@Override
|
||||
public ImageMap run() throws Throwable
|
||||
{
|
||||
final BufferedImage image = ImageIO.read(url);
|
||||
if(image == null) throw new IOException("The given URL is not a valid image");
|
||||
|
||||
if(scaling) return RenderSingle(image, playerUUID);
|
||||
else return RenderPoster(image, playerUUID);
|
||||
}
|
||||
}, callback);
|
||||
}
|
||||
|
||||
static private ImageMap RenderSingle(final BufferedImage image, final UUID playerUUID) throws Throwable
|
||||
{
|
||||
MapManager.checkMapLimit(1, playerUUID);
|
||||
Future<Short> futureMapID = instance.submitToMainThread(new Callable<Short>()
|
||||
{
|
||||
@Override
|
||||
public Short 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);
|
||||
|
||||
instance.submitToMainThread(new Callable<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void call() throws Exception
|
||||
{
|
||||
Renderer.installRenderer(finalImage, mapID);
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return MapManager.createMap(playerUUID, mapID);
|
||||
}
|
||||
|
||||
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<short[]> futureMapsIds = instance.submitToMainThread(new Callable<short[]>()
|
||||
{
|
||||
@Override
|
||||
public short[] call() throws Exception
|
||||
{
|
||||
return MapManager.getNewMapsIds(mapCount);
|
||||
}
|
||||
});
|
||||
|
||||
poster.splitImages();
|
||||
|
||||
final short[] mapsIDs = futureMapsIds.get();
|
||||
|
||||
ImageIOExecutor.saveImage(mapsIDs, poster);
|
||||
|
||||
instance.submitToMainThread(new Callable<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void call() throws Exception
|
||||
{
|
||||
Renderer.installRenderer(poster, mapsIDs);
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
package fr.moribus.imageonmap.image;
|
||||
|
||||
import fr.moribus.imageonmap.image.PosterImage;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
|
||||
public class ImageRendererThread extends Thread
|
||||
{
|
||||
private String URL;
|
||||
private BufferedImage imgSrc;
|
||||
private BufferedImage[] img;
|
||||
private PosterImage poster;
|
||||
private boolean estPrete = false, resized;
|
||||
public boolean erreur = false;
|
||||
|
||||
public boolean isErreur()
|
||||
{
|
||||
return erreur;
|
||||
}
|
||||
|
||||
public ImageRendererThread(String u, boolean r)
|
||||
{
|
||||
URL = u;
|
||||
resized = r;
|
||||
}
|
||||
|
||||
public BufferedImage[] getImg()
|
||||
{
|
||||
if (estPrete)
|
||||
return img;
|
||||
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Boolean getStatut()
|
||||
{
|
||||
return estPrete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
URI uri = null;
|
||||
java.net.URL url = null;
|
||||
try
|
||||
{
|
||||
uri = URI.create(URL);
|
||||
url = uri.toURL();
|
||||
|
||||
|
||||
}
|
||||
catch (IllegalArgumentException | MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
erreur = true;
|
||||
return;
|
||||
}
|
||||
if(erreur != true)
|
||||
{
|
||||
try {
|
||||
imgSrc = ImageIO.read(url.openStream());
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
erreur = true;
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(resized)
|
||||
{
|
||||
img = new BufferedImage[1];
|
||||
Image i = imgSrc.getScaledInstance(128, 128, Image.SCALE_SMOOTH);
|
||||
BufferedImage imgScaled = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
|
||||
imgScaled.getGraphics().drawImage(i, 0, 0 , null);
|
||||
img[0] = imgScaled;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
int width = imgSrc.getWidth();
|
||||
int height = imgSrc.getHeight();
|
||||
|
||||
// Fonction qui cherche le multiple de 128 le plus proche
|
||||
// de la hauteur / largeur de l'image
|
||||
int tmpW = 0, tmpH = 0;
|
||||
int i = 1;
|
||||
while (tmpW < width)
|
||||
{
|
||||
|
||||
tmpW = i * 128;
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (tmpH < height)
|
||||
{
|
||||
|
||||
tmpH = i * 128;
|
||||
i++;
|
||||
}
|
||||
|
||||
// On crée un "canvas" = une image vide qui a une taille multiple de 128
|
||||
// dans laquelle on dessinera l'image téléchargées
|
||||
BufferedImage canvas = new BufferedImage(tmpW, tmpH, BufferedImage.TYPE_INT_ARGB);
|
||||
// On récupère l'objet Grapics2D, servant à dessiner dans notre canvas
|
||||
Graphics2D graph = canvas.createGraphics();
|
||||
|
||||
// Variable servant à cadrer l'image
|
||||
int centerX = 0, centerY = 0;
|
||||
centerX = (tmpW - imgSrc.getWidth()) / 2;
|
||||
centerY = (tmpH - imgSrc.getHeight()) / 2;
|
||||
//On déplace le point d'origine de graph afin que l'image soit dessinée au milieu du canvas
|
||||
graph.translate(centerX, centerY);
|
||||
//graph.rotate(45);
|
||||
// on dessine l'image dans le canvas
|
||||
graph.drawImage(imgSrc, null, null);
|
||||
|
||||
// on crée un Poster à partir de notre canvas
|
||||
poster = new PosterImage(canvas);
|
||||
img = poster.getImages();
|
||||
}
|
||||
|
||||
estPrete = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static public void SupprRendu(MapView map)
|
||||
{
|
||||
if (map.getRenderers().size() > 0)
|
||||
{
|
||||
int i = 0, t = map.getRenderers().size();
|
||||
while (i < t)
|
||||
{
|
||||
map.removeRenderer(map.getRenderers().get(i));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
95
src/main/java/fr/moribus/imageonmap/image/MapInitEvent.java
Normal file
95
src/main/java/fr/moribus/imageonmap/image/MapInitEvent.java
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.image;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
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.ItemFrame;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class MapInitEvent implements Listener
|
||||
{
|
||||
static public void init(Plugin plugin)
|
||||
{
|
||||
plugin.getServer().getPluginManager().registerEvents(new MapInitEvent(), plugin);
|
||||
|
||||
for(World world : Bukkit.getWorlds())
|
||||
{
|
||||
for(ItemFrame frame : world.getEntitiesByClass(ItemFrame.class))
|
||||
{
|
||||
initMap(frame.getItem());
|
||||
}
|
||||
}
|
||||
|
||||
for(Player player : Bukkit.getOnlinePlayers())
|
||||
{
|
||||
initMap(player.getItemInHand());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChunkLoad(ChunkLoadEvent event)
|
||||
{
|
||||
for (Entity entity : event.getChunk().getEntities())
|
||||
{
|
||||
if (entity instanceof ItemFrame)
|
||||
{
|
||||
initMap(((ItemFrame)entity).getItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInv(PlayerItemHeldEvent event)
|
||||
{
|
||||
ItemStack item = event.getPlayer().getInventory().getItem(event.getNewSlot());
|
||||
initMap(item);
|
||||
}
|
||||
|
||||
static protected void initMap(ItemStack item)
|
||||
{
|
||||
if (item != null && item.getType() == Material.MAP)
|
||||
{
|
||||
MapView map = Bukkit.getMap(item.getDurability());
|
||||
initMap(map);
|
||||
}
|
||||
}
|
||||
|
||||
static protected void initMap(MapView map)
|
||||
{
|
||||
if(Renderer.isHandled(map)) return;
|
||||
|
||||
File imageFile = ImageOnMap.getPlugin().getImageFile(map.getId());
|
||||
if(imageFile.isFile())
|
||||
{
|
||||
ImageIOExecutor.loadImage(imageFile, Renderer.installRenderer(map));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.image;
|
||||
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
@ -10,6 +26,10 @@ import java.awt.image.BufferedImage;
|
||||
*/
|
||||
public class PosterImage
|
||||
{
|
||||
static private final int WIDTH = 128;
|
||||
static private final int HEIGHT = 128;
|
||||
|
||||
private BufferedImage originalImage;
|
||||
private BufferedImage[] cutImages;
|
||||
private int lines;
|
||||
private int columns;
|
||||
@ -17,43 +37,50 @@ public class PosterImage
|
||||
private int remainderX, remainderY;
|
||||
|
||||
/**
|
||||
* Creates and splits a new Poster from an entire image
|
||||
* Creates a new Poster from an entire image
|
||||
* @param originalImage the original image
|
||||
*/
|
||||
public PosterImage(BufferedImage originalImage)
|
||||
{
|
||||
splitImages(originalImage);
|
||||
this.originalImage = originalImage;
|
||||
calculateDimensions();
|
||||
}
|
||||
|
||||
private void splitImages(BufferedImage originalImage)
|
||||
private void calculateDimensions()
|
||||
{
|
||||
int originalWidth = originalImage.getWidth();
|
||||
int originalHeight = originalImage.getHeight();
|
||||
|
||||
columns = (int) Math.ceil(originalWidth / ImageMap.WIDTH);
|
||||
lines = (int) Math.ceil(originalHeight / ImageMap.HEIGHT);
|
||||
columns = (int) Math.ceil(originalWidth / WIDTH);
|
||||
lines = (int) Math.ceil(originalHeight / HEIGHT);
|
||||
|
||||
remainderX = originalWidth % ImageMap.WIDTH;
|
||||
remainderY = originalHeight % ImageMap.HEIGHT;
|
||||
remainderX = originalWidth % WIDTH;
|
||||
remainderY = originalHeight % HEIGHT;
|
||||
|
||||
if(remainderX > 0) columns++;
|
||||
if(remainderY > 0) lines++;
|
||||
|
||||
cutImagesCount = columns * lines;
|
||||
}
|
||||
|
||||
public void splitImages()
|
||||
{
|
||||
cutImages = new BufferedImage[cutImagesCount];
|
||||
|
||||
int imageX;
|
||||
int imageY = (remainderY > 0) ? (remainderY - ImageMap.HEIGHT) / 2 : 0;
|
||||
int imageY = (remainderY - HEIGHT) / 2;
|
||||
for(int i = 0; i < lines; i++)
|
||||
{
|
||||
imageX = (remainderX > 0) ? (remainderX - ImageMap.WIDTH) / 2 : 0;
|
||||
imageX = (remainderX - WIDTH) / 2;
|
||||
for(int j = 0; j < columns; j++)
|
||||
{
|
||||
cutImages[i * columns + j] = makeSubImage(originalImage, imageX, imageY);
|
||||
imageX += ImageMap.WIDTH;
|
||||
imageX += WIDTH;
|
||||
}
|
||||
imageY += ImageMap.HEIGHT;
|
||||
imageY += HEIGHT;
|
||||
}
|
||||
|
||||
originalImage = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,7 +91,7 @@ public class PosterImage
|
||||
*/
|
||||
private BufferedImage makeSubImage(BufferedImage originalImage, int x, int y)
|
||||
{
|
||||
BufferedImage newImage = new BufferedImage(ImageMap.WIDTH, ImageMap.HEIGHT, BufferedImage.TYPE_INT_ARGB);
|
||||
BufferedImage newImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics graphics = newImage.getGraphics();
|
||||
|
||||
@ -73,13 +100,6 @@ public class PosterImage
|
||||
return newImage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private int boundValue(int min, int value, int max)
|
||||
{
|
||||
return Math.max(Math.min(value, max), min);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the split images
|
||||
|
@ -1,6 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.image;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.map.MapCanvas;
|
||||
import org.bukkit.map.MapRenderer;
|
||||
@ -8,11 +27,53 @@ import org.bukkit.map.MapView;
|
||||
|
||||
public class Renderer extends MapRenderer
|
||||
{
|
||||
private boolean isRendered;
|
||||
private final BufferedImage image;
|
||||
public Renderer(BufferedImage image)
|
||||
static public boolean isHandled(MapView map)
|
||||
{
|
||||
for(MapRenderer renderer : map.getRenderers())
|
||||
{
|
||||
if(renderer instanceof Renderer) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static public void installRenderer(PosterImage image, short[] mapsIds)
|
||||
{
|
||||
for(int i = 0; i < mapsIds.length; i++)
|
||||
{
|
||||
installRenderer(image.getImageAt(i), mapsIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static public void installRenderer(BufferedImage image, short mapID)
|
||||
{
|
||||
installRenderer(Bukkit.getMap(mapID)).setImage(image);
|
||||
}
|
||||
|
||||
static public Renderer installRenderer(MapView map)
|
||||
{
|
||||
Renderer renderer = new Renderer();
|
||||
removeRenderers(map);
|
||||
map.addRenderer(renderer);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
static public void removeRenderers(MapView map)
|
||||
{
|
||||
for(MapRenderer renderer : map.getRenderers())
|
||||
{
|
||||
map.removeRenderer(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage image;
|
||||
|
||||
protected Renderer()
|
||||
{
|
||||
this(null);
|
||||
}
|
||||
|
||||
protected Renderer(BufferedImage image)
|
||||
{
|
||||
isRendered = false;
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
@ -20,10 +81,19 @@ public class Renderer extends MapRenderer
|
||||
public void render(MapView v, final MapCanvas canvas, Player p)
|
||||
{
|
||||
//Render only once to avoid overloading the server
|
||||
if (!isRendered)
|
||||
{
|
||||
canvas.drawImage(0, 0, image);
|
||||
isRendered = true;
|
||||
}
|
||||
if (image == null) return;
|
||||
|
||||
canvas.drawImage(0, 0, image);
|
||||
image = null;
|
||||
}
|
||||
|
||||
public BufferedImage getImage()
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setImage(BufferedImage image)
|
||||
{
|
||||
this.image = image;
|
||||
}
|
||||
}
|
||||
|
@ -1,125 +1,174 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.map;
|
||||
|
||||
import fr.moribus.imageonmap.image.PosterImage;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import fr.moribus.imageonmap.ui.MapItemManager;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
public abstract class ImageMap
|
||||
public abstract class ImageMap implements ConfigurationSerializable
|
||||
{
|
||||
static public enum Type
|
||||
{
|
||||
SINGLE, POSTER;
|
||||
|
||||
static public ImageMap createNewMap(Type type, BufferedImage image, Player player)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case POSTER:
|
||||
return new PosterMap(new PosterImage(image), player);
|
||||
default:
|
||||
return new SingleMap(image, player);
|
||||
}
|
||||
}
|
||||
|
||||
static public Type fromString(String string)
|
||||
{
|
||||
switch(string.toLowerCase())
|
||||
{
|
||||
case "poster":
|
||||
case "multi":
|
||||
return POSTER;
|
||||
case "single":
|
||||
return SINGLE;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static public final int WIDTH = 128;
|
||||
static public final int HEIGHT = 128;
|
||||
static public final String DEFAULT_NAME = "Map";
|
||||
|
||||
protected String imageName;
|
||||
protected String ownerName;
|
||||
protected String worldName;
|
||||
private String id;
|
||||
private final UUID userUUID;
|
||||
private final Type mapType;
|
||||
private String name;
|
||||
|
||||
public abstract void load() throws IOException;
|
||||
public abstract void save() throws IOException;
|
||||
public abstract void give(Inventory inv);
|
||||
public abstract void setImage(BufferedImage image);
|
||||
public abstract void send(Player joueur);
|
||||
|
||||
public ImageMap()
|
||||
protected ImageMap(UUID userUUID, Type mapType)
|
||||
{
|
||||
this(null, null, null);
|
||||
this(userUUID, mapType, null, null);
|
||||
}
|
||||
|
||||
public ImageMap(String imageName, String ownerName, String worldName)
|
||||
protected ImageMap(UUID userUUID, Type mapType, String id, String name)
|
||||
{
|
||||
this.imageName = imageName;
|
||||
this.ownerName = ownerName;
|
||||
this.worldName = worldName;
|
||||
}
|
||||
this.userUUID = userUUID;
|
||||
this.mapType = mapType;
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
|
||||
|
||||
|
||||
protected void give(Inventory inventory, short mapID)
|
||||
{
|
||||
give(inventory, mapID, getImageName());
|
||||
}
|
||||
|
||||
protected void give(Inventory inventory, short mapID, String itemName)
|
||||
{
|
||||
ItemStack itemMap = new ItemStack(Material.MAP, 1, mapID);
|
||||
if(itemName != null)
|
||||
if(this.id == null)
|
||||
{
|
||||
ItemMeta meta = itemMap.getItemMeta();
|
||||
meta.setDisplayName(itemName);
|
||||
itemMap.setItemMeta(meta);
|
||||
if(this.name == null) this.name = DEFAULT_NAME;
|
||||
this.id = MapManager.getNextAvailableMapID(this.name, userUUID);
|
||||
}
|
||||
inventory.addItem(itemMap);
|
||||
}
|
||||
|
||||
// Getters & Setters
|
||||
|
||||
public String getImageName()
|
||||
public abstract short[] getMapsIDs();
|
||||
public abstract boolean managesMap(short mapID);
|
||||
public abstract int getMapCount();
|
||||
|
||||
public boolean managesMap(ItemStack item)
|
||||
{
|
||||
return imageName;
|
||||
if(item == null) return false;
|
||||
if(item.getType() != Material.MAP) return false;
|
||||
return managesMap(item.getDurability());
|
||||
}
|
||||
|
||||
public void setImageName(String imageName)
|
||||
public boolean give(Player player)
|
||||
{
|
||||
this.imageName = imageName;
|
||||
return MapItemManager.give(player, this);
|
||||
}
|
||||
|
||||
public boolean isNamed()
|
||||
/* ====== Serialization methods ====== */
|
||||
|
||||
static public ImageMap fromConfig(Map<String, Object> map, UUID userUUID) throws InvalidConfigurationException
|
||||
{
|
||||
return imageName != null;
|
||||
Type mapType;
|
||||
try
|
||||
{
|
||||
mapType = Type.valueOf((String) map.get("type"));
|
||||
}
|
||||
catch(ClassCastException ex)
|
||||
{
|
||||
throw new InvalidConfigurationException(ex);
|
||||
}
|
||||
|
||||
switch(mapType)
|
||||
{
|
||||
case SINGLE: return new SingleMap(map, userUUID);
|
||||
case POSTER: return new PosterMap(map, userUUID);
|
||||
default: throw new IllegalArgumentException("Unhandled map type given");
|
||||
}
|
||||
}
|
||||
|
||||
public String getOwnerName()
|
||||
protected ImageMap(Map<String, Object> map, UUID userUUID, Type mapType) throws InvalidConfigurationException
|
||||
{
|
||||
return ownerName;
|
||||
this(userUUID, mapType,
|
||||
(String) getNullableFieldValue(map, "id"),
|
||||
(String) getNullableFieldValue(map, "name"));
|
||||
|
||||
}
|
||||
|
||||
public void setOwnerName(String ownerName)
|
||||
protected abstract void postSerialize(Map<String, Object> map);
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize()
|
||||
{
|
||||
this.ownerName = ownerName;
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("id", getId());
|
||||
map.put("type", mapType.toString());
|
||||
map.put("name", getName());
|
||||
this.postSerialize(map);
|
||||
return map;
|
||||
}
|
||||
|
||||
public String getWorldName()
|
||||
static protected <T> T getFieldValue(Map<String, Object> map, String fieldName) throws InvalidConfigurationException
|
||||
{
|
||||
return worldName;
|
||||
T value = getNullableFieldValue(map, fieldName);
|
||||
if(value == null) throw new InvalidConfigurationException("Field value not found for \"" + fieldName + "\"");
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setWorldName(String worldName)
|
||||
static protected <T> T getNullableFieldValue(Map<String, Object> map, String fieldName) throws InvalidConfigurationException
|
||||
{
|
||||
this.worldName = worldName;
|
||||
try
|
||||
{
|
||||
return (T)map.get(fieldName);
|
||||
}
|
||||
catch(ClassCastException ex)
|
||||
{
|
||||
throw new InvalidConfigurationException("Invalid field \"" + fieldName + "\"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ====== Getters & Setters ====== */
|
||||
|
||||
public UUID getUserUUID()
|
||||
{
|
||||
return userUUID;
|
||||
}
|
||||
|
||||
public synchronized String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public synchronized String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public synchronized void rename(String id, String name)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void rename(String name)
|
||||
{
|
||||
if(getName().equals(name)) return;
|
||||
rename(MapManager.getNextAvailableMapID(name, getUserUUID()), name);
|
||||
}
|
||||
}
|
||||
|
254
src/main/java/fr/moribus/imageonmap/map/MapManager.java
Normal file
254
src/main/java/fr/moribus/imageonmap/map/MapManager.java
Normal file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.map;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.PluginConfiguration;
|
||||
import fr.moribus.imageonmap.image.ImageIOExecutor;
|
||||
import fr.moribus.imageonmap.image.PosterImage;
|
||||
import fr.moribus.imageonmap.map.MapManagerException.Reason;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
abstract public class MapManager
|
||||
{
|
||||
static private final long SAVE_DELAY = 200;
|
||||
static private final ArrayList<PlayerMapStore> playerMaps = new ArrayList<PlayerMapStore>();
|
||||
static private BukkitTask autosaveTask;
|
||||
|
||||
static public void init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static public void exit()
|
||||
{
|
||||
save();
|
||||
playerMaps.clear();
|
||||
if(autosaveTask != null) autosaveTask.cancel();
|
||||
}
|
||||
|
||||
static public boolean managesMap(short mapID)
|
||||
{
|
||||
synchronized(playerMaps)
|
||||
{
|
||||
for(PlayerMapStore mapStore : playerMaps)
|
||||
{
|
||||
if(mapStore.managesMap(mapID)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static public boolean managesMap(ItemStack item)
|
||||
{
|
||||
synchronized(playerMaps)
|
||||
{
|
||||
for(PlayerMapStore mapStore : playerMaps)
|
||||
{
|
||||
if(mapStore.managesMap(item)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static public ImageMap createMap(UUID playerUUID, short 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
|
||||
{
|
||||
ImageMap newMap;
|
||||
if(image.getImagesCount() == 1)
|
||||
{
|
||||
newMap = new SingleMap(playerUUID, mapsIDs[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
newMap = new PosterMap(playerUUID, mapsIDs, image.getColumns(), image.getLines());
|
||||
}
|
||||
addMap(newMap);
|
||||
return newMap;
|
||||
}
|
||||
|
||||
static public short[] getNewMapsIds(int amount)
|
||||
{
|
||||
short[] mapsIds = new short[amount];
|
||||
for(int i = 0; i < amount; i++)
|
||||
{
|
||||
mapsIds[i] = Bukkit.createMap(Bukkit.getWorlds().get(0)).getId();
|
||||
}
|
||||
return mapsIds;
|
||||
}
|
||||
|
||||
static public void addMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
getPlayerMapStore(map.getUserUUID()).addMap(map);
|
||||
}
|
||||
|
||||
static public void insertMap(ImageMap map)
|
||||
{
|
||||
getPlayerMapStore(map.getUserUUID()).insertMap(map);
|
||||
}
|
||||
|
||||
static public void deleteMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
getPlayerMapStore(map.getUserUUID()).deleteMap(map);
|
||||
ImageIOExecutor.deleteImage(map);
|
||||
}
|
||||
|
||||
static public void notifyModification(UUID playerUUID)
|
||||
{
|
||||
getPlayerMapStore(playerUUID).notifyModification();
|
||||
if(autosaveTask == null)
|
||||
Bukkit.getScheduler().runTaskLater(ImageOnMap.getPlugin(), new AutosaveRunnable(), SAVE_DELAY);
|
||||
}
|
||||
|
||||
static public String getNextAvailableMapID(String mapId, UUID playerUUID)
|
||||
{
|
||||
return getPlayerMapStore(playerUUID).getNextAvailableMapID(mapId);
|
||||
}
|
||||
|
||||
static public List<ImageMap> getMapList(UUID playerUUID)
|
||||
{
|
||||
return getPlayerMapStore(playerUUID).getMapList();
|
||||
}
|
||||
|
||||
static public ImageMap getMap(UUID playerUUID, String mapId)
|
||||
{
|
||||
return getPlayerMapStore(playerUUID).getMap(mapId);
|
||||
}
|
||||
|
||||
static public void clear(Inventory inventory)
|
||||
{
|
||||
for(int i = 0, c = inventory.getSize(); i < c; i++)
|
||||
{
|
||||
if(managesMap(inventory.getItem(i)))
|
||||
{
|
||||
inventory.setItem(i, new ItemStack(Material.AIR));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public void clear(Inventory inventory, ImageMap map)
|
||||
{
|
||||
for(int i = 0, c = inventory.getSize(); i < c; i++)
|
||||
{
|
||||
if(map.managesMap(inventory.getItem(i)))
|
||||
{
|
||||
inventory.setItem(i, new ItemStack(Material.AIR));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public void save()
|
||||
{
|
||||
synchronized(playerMaps)
|
||||
{
|
||||
for(PlayerMapStore tStore : playerMaps)
|
||||
{
|
||||
tStore.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public void checkMapLimit(ImageMap map) throws MapManagerException
|
||||
{
|
||||
checkMapLimit(map.getMapCount(), map.getUserUUID());
|
||||
}
|
||||
|
||||
static public void checkMapLimit(int newMapsCount, UUID userUUID) throws MapManagerException
|
||||
{
|
||||
int limit = PluginConfiguration.MAP_GLOBAL_LIMIT.getInteger();
|
||||
if(limit > 0)
|
||||
{
|
||||
if(getMapCount() + newMapsCount > limit)
|
||||
throw new MapManagerException(Reason.MAXIMUM_SERVER_MAPS_EXCEEDED);
|
||||
}
|
||||
getPlayerMapStore(userUUID).checkMapLimit(newMapsCount);
|
||||
}
|
||||
|
||||
static public int getMapCount()
|
||||
{
|
||||
int mapCount = 0;
|
||||
synchronized(playerMaps)
|
||||
{
|
||||
for(PlayerMapStore tStore : playerMaps)
|
||||
{
|
||||
mapCount += tStore.getMapCount();
|
||||
}
|
||||
}
|
||||
return mapCount;
|
||||
}
|
||||
|
||||
static private PlayerMapStore getPlayerMapStore(UUID playerUUID)
|
||||
{
|
||||
PlayerMapStore store;
|
||||
synchronized(playerMaps)
|
||||
{
|
||||
store = getExistingPlayerMapStore(playerUUID);
|
||||
if(store == null)
|
||||
{
|
||||
store = new PlayerMapStore(playerUUID);
|
||||
|
||||
playerMaps.add(store);
|
||||
store.load();
|
||||
}
|
||||
}
|
||||
return store;
|
||||
}
|
||||
|
||||
static private PlayerMapStore getExistingPlayerMapStore(UUID playerUUID)
|
||||
{
|
||||
synchronized(playerMaps)
|
||||
{
|
||||
for(PlayerMapStore mapStore : playerMaps)
|
||||
{
|
||||
if(mapStore.getUUID().equals(playerUUID)) return mapStore;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static private class AutosaveRunnable implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
synchronized(playerMaps)
|
||||
{
|
||||
for(PlayerMapStore toolStore : playerMaps)
|
||||
{
|
||||
if(toolStore.isModified()) toolStore.save();
|
||||
}
|
||||
autosaveTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.map;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
public class MapManagerException extends Exception
|
||||
{
|
||||
public enum Reason
|
||||
{
|
||||
MAXIMUM_PLAYER_MAPS_EXCEEDED("You have too many maps (maximum : {0})."),
|
||||
MAXIMUM_SERVER_MAPS_EXCEEDED("The server ImageOnMap limit has been reached."),
|
||||
IMAGEMAP_DOES_NOT_EXIST("The given map does not exist.");
|
||||
|
||||
private final String reasonString;
|
||||
private Reason(String reasonString)
|
||||
{
|
||||
this.reasonString = reasonString;
|
||||
}
|
||||
|
||||
public String getReasonString(Object ...arguments)
|
||||
{
|
||||
return MessageFormat.format(reasonString, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
private final Reason reason;
|
||||
|
||||
public MapManagerException(Reason reason, Object ...arguments)
|
||||
{
|
||||
super(reason.getReasonString(arguments));
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public Reason getReason() { return reason; }
|
||||
|
||||
}
|
258
src/main/java/fr/moribus/imageonmap/map/PlayerMapStore.java
Normal file
258
src/main/java/fr/moribus/imageonmap/map/PlayerMapStore.java
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.map;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.PluginConfiguration;
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import fr.moribus.imageonmap.map.MapManagerException.Reason;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class PlayerMapStore implements ConfigurationSerializable
|
||||
{
|
||||
private final UUID playerUUID;
|
||||
private final ArrayList<ImageMap> mapList = new ArrayList<ImageMap>();
|
||||
private boolean modified = false;
|
||||
private int mapCount = 0;
|
||||
|
||||
public PlayerMapStore(UUID playerUUID)
|
||||
{
|
||||
this.playerUUID = playerUUID;
|
||||
}
|
||||
|
||||
public synchronized boolean managesMap(short mapID)
|
||||
{
|
||||
for(ImageMap map : mapList)
|
||||
{
|
||||
if(map.managesMap(mapID)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized boolean managesMap(ItemStack item)
|
||||
{
|
||||
for(ImageMap map : mapList)
|
||||
{
|
||||
if(map.managesMap(item)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized void addMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
checkMapLimit(map);
|
||||
insertMap(map);
|
||||
}
|
||||
|
||||
public synchronized void insertMap(ImageMap map)
|
||||
{
|
||||
_addMap(map);
|
||||
notifyModification();
|
||||
}
|
||||
|
||||
private void _addMap(ImageMap map)
|
||||
{
|
||||
mapList.add(map);
|
||||
mapCount += map.getMapCount();
|
||||
}
|
||||
|
||||
public synchronized void deleteMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
_removeMap(map);
|
||||
notifyModification();
|
||||
}
|
||||
|
||||
private void _removeMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
if(!mapList.remove(map))
|
||||
{
|
||||
throw new MapManagerException(Reason.IMAGEMAP_DOES_NOT_EXIST);
|
||||
}
|
||||
mapCount -= map.getMapCount();
|
||||
}
|
||||
|
||||
public synchronized boolean mapExists(String id)
|
||||
{
|
||||
for(ImageMap map : mapList)
|
||||
{
|
||||
if(map.getId().equals(id)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getNextAvailableMapID(String mapId)
|
||||
{
|
||||
if(!mapExists(mapId)) return mapId;
|
||||
int id = 0;
|
||||
|
||||
do
|
||||
{
|
||||
id++;
|
||||
}while(mapExists(mapId + "-" + id));
|
||||
|
||||
return mapId + "-" + id;
|
||||
}
|
||||
|
||||
public synchronized List<ImageMap> getMapList()
|
||||
{
|
||||
return new ArrayList(mapList);
|
||||
}
|
||||
|
||||
public synchronized ImageMap getMap(String mapId)
|
||||
{
|
||||
for(ImageMap map : mapList)
|
||||
{
|
||||
if(map.getId().equals(mapId)) return map;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void checkMapLimit(ImageMap map) throws MapManagerException
|
||||
{
|
||||
checkMapLimit(map.getMapCount());
|
||||
}
|
||||
|
||||
public void checkMapLimit(int newMapsCount) throws MapManagerException
|
||||
{
|
||||
int limit = PluginConfiguration.MAP_PLAYER_LIMIT.getInteger();
|
||||
if(limit <= 0) return;
|
||||
|
||||
if(getMapCount() + newMapsCount > limit)
|
||||
throw new MapManagerException(Reason.MAXIMUM_PLAYER_MAPS_EXCEEDED, limit);
|
||||
}
|
||||
|
||||
/* ===== Getters & Setters ===== */
|
||||
|
||||
public UUID getUUID()
|
||||
{
|
||||
return playerUUID;
|
||||
}
|
||||
|
||||
public synchronized boolean isModified()
|
||||
{
|
||||
return modified;
|
||||
}
|
||||
|
||||
public synchronized void notifyModification()
|
||||
{
|
||||
this.modified = true;
|
||||
}
|
||||
|
||||
public synchronized int getMapCount()
|
||||
{
|
||||
return this.mapCount;
|
||||
}
|
||||
|
||||
/* ****** Serializing ***** */
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize()
|
||||
{
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
ArrayList<Map> list = new ArrayList<Map>();
|
||||
synchronized(this)
|
||||
{
|
||||
for(ImageMap tMap : mapList)
|
||||
{
|
||||
list.add(tMap.serialize());
|
||||
}
|
||||
}
|
||||
map.put("mapList", list);
|
||||
return map;
|
||||
}
|
||||
|
||||
private void loadFromConfig(ConfigurationSection section)
|
||||
{
|
||||
if(section == null) return;
|
||||
List<Map<String, Object>> list = (List<Map<String, Object>>) section.getList("mapList");
|
||||
if(list == null) return;
|
||||
|
||||
for(Map<String, Object> tMap : list)
|
||||
{
|
||||
try
|
||||
{
|
||||
ImageMap newMap = ImageMap.fromConfig(tMap, playerUUID);
|
||||
synchronized(this) {_addMap(newMap);}
|
||||
}
|
||||
catch(InvalidConfigurationException ex)
|
||||
{
|
||||
PluginLogger.warning("Could not load map data : ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
try { checkMapLimit(0); }
|
||||
catch(MapManagerException ex)
|
||||
{
|
||||
PluginLogger.warning("Map limit exceeded for player '{0}' ({1} maps loaded)",
|
||||
playerUUID.toString(),mapList.size());
|
||||
}
|
||||
}
|
||||
|
||||
/* ****** Configuration Files management ***** */
|
||||
|
||||
private FileConfiguration mapConfig = null;
|
||||
private File mapsFile = null;
|
||||
|
||||
private FileConfiguration getToolConfig()
|
||||
{
|
||||
if(mapConfig == null) load();
|
||||
|
||||
return mapConfig;
|
||||
}
|
||||
|
||||
public void load()
|
||||
{
|
||||
if(mapsFile == null)
|
||||
{
|
||||
mapsFile = new File(ImageOnMap.getPlugin().getMapsDirectory(), playerUUID.toString() + ".yml");
|
||||
if(!mapsFile.exists()) save();
|
||||
}
|
||||
mapConfig = YamlConfiguration.loadConfiguration(mapsFile);
|
||||
loadFromConfig(getToolConfig().getConfigurationSection("PlayerMapStore"));
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
if(mapsFile == null || mapConfig == null) return;
|
||||
getToolConfig().set("PlayerMapStore", this.serialize());
|
||||
try
|
||||
{
|
||||
getToolConfig().save(mapsFile);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
PluginLogger.error("Could not save maps file for player '{0}'", ex, playerUUID.toString());
|
||||
}
|
||||
synchronized(this) {modified = false;}
|
||||
}
|
||||
}
|
@ -1,158 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.map;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.image.Renderer;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
import fr.moribus.imageonmap.image.PosterImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.imageio.ImageIO;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.map.MapView;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
|
||||
public class PosterMap extends ImageMap
|
||||
{
|
||||
private PosterImage image;
|
||||
private final short[] mapsIDs;
|
||||
protected final short[] mapsIDs;
|
||||
protected final int columnCount;
|
||||
protected final int rowCount;
|
||||
|
||||
private FileConfiguration customConfig = null;
|
||||
private File customConfigFile = null;
|
||||
|
||||
public PosterMap(PosterImage image, Player player)
|
||||
public PosterMap(UUID userUUID, short[] mapsIDs, String id, String name, int columnCount, int rowCount)
|
||||
{
|
||||
super(null, player.getName(), player.getWorld().getName());
|
||||
this.image = image;
|
||||
|
||||
mapsIDs = new short[image.getImagesCount()];
|
||||
for (int i = 0; i < mapsIDs.length; i++)
|
||||
{
|
||||
mapsIDs[i] = Bukkit.createMap(player.getWorld()).getId();
|
||||
}
|
||||
super(userUUID, Type.POSTER, id, name);
|
||||
this.mapsIDs = mapsIDs;
|
||||
this.columnCount = Math.max(columnCount, 0);
|
||||
this.rowCount = Math.max(rowCount, 0);
|
||||
}
|
||||
|
||||
public PosterMap(String id) throws Exception
|
||||
public PosterMap(UUID userUUID, short[] mapsIDs, int columnCount, int rowCount)
|
||||
{
|
||||
this.imageName = id;
|
||||
List<String> svg = getCustomConfig().getStringList(imageName);
|
||||
if(svg != null && !svg.isEmpty())
|
||||
{
|
||||
this.ownerName = svg.get(0);
|
||||
mapsIDs = new short[svg.size()-1];
|
||||
for(int i = 0; i < mapsIDs.length; i++)
|
||||
{
|
||||
mapsIDs[i] = Short.parseShort(svg.get(i+1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Le poster est introuvable.");
|
||||
}
|
||||
this(userUUID, mapsIDs, null, null, columnCount, rowCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load()
|
||||
public short[] getMapsIDs()
|
||||
{
|
||||
return mapsIDs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean managesMap(short mapID)
|
||||
{
|
||||
for(int i = 0; i < mapsIDs.length; i++)
|
||||
{
|
||||
MapView map = Bukkit.getMap(mapsIDs[i]);
|
||||
SingleMap.SupprRendu(map);
|
||||
map.addRenderer(new Renderer(image.getImageAt(i)));
|
||||
if(mapsIDs[i] == mapID) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ====== Serialization methods ====== */
|
||||
|
||||
public PosterMap(Map<String, Object> map, UUID userUUID) throws InvalidConfigurationException
|
||||
{
|
||||
super(map, userUUID, Type.POSTER);
|
||||
|
||||
columnCount = getFieldValue(map, "columns");
|
||||
rowCount = getFieldValue(map, "rows");
|
||||
|
||||
List<Integer> 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
|
||||
public void save() throws IOException
|
||||
protected void postSerialize(Map<String, Object> map)
|
||||
{
|
||||
ImageOnMap plugin = ImageOnMap.getPlugin();
|
||||
map.put("columns", columnCount);
|
||||
map.put("rows", rowCount);
|
||||
map.put("mapsIDs", mapsIDs);
|
||||
}
|
||||
|
||||
for(int i = 0; i < mapsIDs.length; i++)
|
||||
{
|
||||
short mapID = mapsIDs[i];
|
||||
String mapName = "map" + mapID;
|
||||
File outputfile = new File("./plugins/ImageOnMap/Image/" + mapName + ".png");
|
||||
ImageIO.write(image.getImageAt(i), "png", outputfile);
|
||||
/* ====== Getters & Setters ====== */
|
||||
|
||||
// Enregistrement de la map dans la config
|
||||
ArrayList<String> liste = new ArrayList<String>();
|
||||
liste.add(String.valueOf(mapID));
|
||||
liste.add(mapName);
|
||||
liste.add(ownerName);
|
||||
liste.add(worldName);
|
||||
plugin.getCustomConfig().set(mapName, liste);
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
plugin.saveCustomConfig();
|
||||
/**
|
||||
* 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) + 1;
|
||||
}
|
||||
|
||||
public int getRowAt(int i)
|
||||
{
|
||||
if(columnCount == 0) return 0;
|
||||
return (i / columnCount) + 1;
|
||||
}
|
||||
|
||||
public boolean hasColumnData()
|
||||
{
|
||||
return rowCount != 0 && columnCount != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void give(Inventory inv)
|
||||
public int getMapCount()
|
||||
{
|
||||
String itemName;
|
||||
for(int i = 0; i < mapsIDs.length; i++)
|
||||
{
|
||||
itemName = "Map (row " + (image.getLineAt(i) + 1) + ", column " + (image.getColumnAt(i) + 1) + ")";
|
||||
give(inv, mapsIDs[i], itemName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(BufferedImage image)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Player player)
|
||||
{
|
||||
for(short mapID: mapsIDs)
|
||||
{
|
||||
player.sendMap(Bukkit.getMap(mapID));
|
||||
}
|
||||
}
|
||||
|
||||
private void reloadCustomConfig()
|
||||
{
|
||||
ImageOnMap plugin = (ImageOnMap)Bukkit.getPluginManager().getPlugin("ImageOnMap");
|
||||
if (customConfigFile == null)
|
||||
{
|
||||
customConfigFile = new File(plugin.getDataFolder(), "poster.yml");
|
||||
}
|
||||
customConfig = YamlConfiguration.loadConfiguration(customConfigFile);
|
||||
|
||||
// Look for defaults in the jar
|
||||
InputStream defConfigStream = plugin.getResource("poster.yml");
|
||||
if (defConfigStream != null)
|
||||
{
|
||||
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream);
|
||||
customConfig.setDefaults(defConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private FileConfiguration getCustomConfig()
|
||||
{
|
||||
if (customConfig == null)
|
||||
{
|
||||
reloadCustomConfig();
|
||||
}
|
||||
return customConfig;
|
||||
}
|
||||
|
||||
private void saveCustomConfig() throws IOException
|
||||
{
|
||||
ImageOnMap plugin = (ImageOnMap)Bukkit.getPluginManager().getPlugin("ImageOnMap");
|
||||
if (customConfig == null || customConfigFile == null) {
|
||||
return;
|
||||
}
|
||||
getCustomConfig().save(customConfigFile);
|
||||
return mapsIDs.length;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,118 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.map;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.ImgUtility;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
import fr.moribus.imageonmap.image.Renderer;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.imageio.ImageIO;
|
||||
import org.bukkit.map.MapRenderer;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
|
||||
public class SingleMap extends ImageMap
|
||||
{
|
||||
private final short mapID;
|
||||
private BufferedImage image;
|
||||
protected final short mapID;
|
||||
|
||||
public SingleMap(BufferedImage img, Player player)
|
||||
{
|
||||
this(img, null, player);
|
||||
}
|
||||
|
||||
public SingleMap(BufferedImage image, String imageName, Player player)
|
||||
{
|
||||
super(imageName, player.getName(), player.getWorld().getName());
|
||||
this.mapID = Bukkit.createMap(player.getWorld()).getId();
|
||||
this.image = ImgUtility.scaleImage(image, WIDTH, HEIGHT);
|
||||
}
|
||||
|
||||
public SingleMap(short mapID) throws IOException, IllegalArgumentException
|
||||
public SingleMap(UUID ownerUUID, short mapID, String id, String name)
|
||||
{
|
||||
super(ownerUUID, Type.SINGLE, id, name);
|
||||
this.mapID = mapID;
|
||||
}
|
||||
|
||||
//Testing if the map id exists
|
||||
MapView map = Bukkit.getMap(mapID);
|
||||
if(map == null)
|
||||
throw new IllegalArgumentException("Map ID '" + mapID + "' doesn't exist");
|
||||
|
||||
List<String> svg = ImageOnMap.getPlugin().getCustomConfig().getStringList("map" + mapID);
|
||||
String nomImg = svg.get(1);
|
||||
ownerName = svg.get(2);
|
||||
image = ImageIO.read(new File("./plugins/ImageOnMap/Image/" + nomImg + ".png"));
|
||||
public SingleMap(UUID ownerUUID, short mapID)
|
||||
{
|
||||
this(ownerUUID, mapID, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() throws IOException
|
||||
public short[] getMapsIDs()
|
||||
{
|
||||
String mapName = "map" + mapID;
|
||||
ImageOnMap plugin = ImageOnMap.getPlugin();
|
||||
|
||||
File outputfile = new File("./plugins/ImageOnMap/Image/" + mapName + ".png");
|
||||
ImageIO.write(image, "png", outputfile);
|
||||
|
||||
// Enregistrement de la map dans la config
|
||||
ArrayList<String> liste = new ArrayList<String>();
|
||||
liste.add(String.valueOf(mapID));
|
||||
liste.add(mapName);
|
||||
liste.add(ownerName);
|
||||
liste.add(worldName);
|
||||
plugin.getCustomConfig().set(mapName, liste);
|
||||
plugin.saveCustomConfig();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void give(Inventory inventory)
|
||||
{
|
||||
give(inventory, mapID);
|
||||
return new short[]{mapID};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load()
|
||||
public boolean managesMap(short mapID)
|
||||
{
|
||||
MapView map = Bukkit.getMap(mapID);
|
||||
SingleMap.SupprRendu(map);
|
||||
map.addRenderer(new Renderer(image));
|
||||
return this.mapID == mapID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNamed()
|
||||
public int getMapCount()
|
||||
{
|
||||
return imageName != null;
|
||||
return 1;
|
||||
}
|
||||
|
||||
public short getId()
|
||||
/* ====== Serialization methods ====== */
|
||||
|
||||
public SingleMap(Map<String, Object> map, UUID userUUID) throws InvalidConfigurationException
|
||||
{
|
||||
return mapID;
|
||||
super(map, userUUID, Type.SINGLE);
|
||||
int _mapID = getFieldValue(map, "mapID");
|
||||
mapID = (short) _mapID;//Meh
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(BufferedImage image)
|
||||
protected void postSerialize(Map<String, Object> map)
|
||||
{
|
||||
this.image = image;
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Player joueur)
|
||||
{
|
||||
joueur.sendMap(Bukkit.getMap(mapID));
|
||||
}
|
||||
|
||||
public static void SupprRendu(MapView map)
|
||||
{
|
||||
for(MapRenderer renderer : map.getRenderers())
|
||||
{
|
||||
map.removeRenderer(renderer);
|
||||
}
|
||||
map.put("mapID", mapID);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.migration;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
|
||||
public class MigratorExecutor
|
||||
{
|
||||
static private Thread migratorThread;
|
||||
|
||||
static public void migrate()
|
||||
{
|
||||
if(isRunning())
|
||||
{
|
||||
PluginLogger.error("Migration is already running.");
|
||||
return;
|
||||
}
|
||||
migratorThread = new Thread(new V3Migrator(ImageOnMap.getPlugin()), "ImageOnMap-Migration");
|
||||
migratorThread.start();
|
||||
}
|
||||
|
||||
static public boolean isRunning()
|
||||
{
|
||||
return migratorThread != null && migratorThread.isAlive();
|
||||
}
|
||||
|
||||
static public void waitForMigration()
|
||||
{
|
||||
if(isRunning())
|
||||
{
|
||||
PluginLogger.info("Waiting for migration to finish ...");
|
||||
try
|
||||
{
|
||||
migratorThread.join();
|
||||
}
|
||||
catch(InterruptedException ex)
|
||||
{
|
||||
PluginLogger.error("Migration thread has been interrupted while wating to finish. It may not have ended correctly.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.migration;
|
||||
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.SingleMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
|
||||
class OldSavedMap
|
||||
{
|
||||
private final short mapId;
|
||||
private final String mapName;
|
||||
private final String userName;
|
||||
|
||||
public OldSavedMap(Object rawData) throws InvalidConfigurationException
|
||||
{
|
||||
List<String> data;
|
||||
try
|
||||
{
|
||||
data = (List<String>) rawData;
|
||||
}
|
||||
catch(ClassCastException ex)
|
||||
{
|
||||
throw new InvalidConfigurationException("Invalid map data : " + ex.getMessage());
|
||||
}
|
||||
|
||||
if(data.size() < 3)
|
||||
throw new InvalidConfigurationException("Map data too short (given : " + data.size() + ", expected 3)");
|
||||
try
|
||||
{
|
||||
mapId = Short.parseShort(data.get(0));
|
||||
}
|
||||
catch(NumberFormatException ex)
|
||||
{
|
||||
throw new InvalidConfigurationException("Invalid map ID : " + ex.getMessage());
|
||||
}
|
||||
|
||||
mapName = data.get(1);
|
||||
userName = data.get(2);
|
||||
}
|
||||
|
||||
public ImageMap toImageMap(UUID userUUID)
|
||||
{
|
||||
return new SingleMap(userUUID, mapId, null, mapName);
|
||||
}
|
||||
|
||||
public void serialize(Configuration configuration)
|
||||
{
|
||||
ArrayList<String> data = new ArrayList<String>();
|
||||
data.add(Short.toString(mapId));
|
||||
data.add(mapName);
|
||||
data.add(userName);
|
||||
configuration.set(mapName, data);
|
||||
}
|
||||
|
||||
public short getMapId() {return mapId;}
|
||||
public String getUserName() {return userName;}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.migration;
|
||||
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
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;
|
||||
|
||||
class OldSavedPoster
|
||||
{
|
||||
private final String userName;
|
||||
private final String posterName;
|
||||
private final short[] mapsIds;
|
||||
|
||||
public OldSavedPoster(Object rawData, String key) throws InvalidConfigurationException
|
||||
{
|
||||
posterName = key;
|
||||
List<String> data;
|
||||
try
|
||||
{
|
||||
data = (List<String>) rawData;
|
||||
}
|
||||
catch(ClassCastException ex)
|
||||
{
|
||||
throw new InvalidConfigurationException("Invalid map data : " + ex.getMessage());
|
||||
}
|
||||
|
||||
if(data.size() < 2)
|
||||
throw new InvalidConfigurationException("Poster data too short (given : " + data.size() + ", expected at least 2)");
|
||||
userName = data.get(0);
|
||||
mapsIds = new short[data.size() - 1];
|
||||
|
||||
for(int i = 1, c = data.size(); i < c; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
mapsIds[i - 1] = Short.parseShort(data.get(i));
|
||||
}
|
||||
catch(NumberFormatException ex)
|
||||
{
|
||||
throw new InvalidConfigurationException("Invalid map ID : " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(OldSavedMap map)
|
||||
{
|
||||
short mapId = map.getMapId();
|
||||
|
||||
for(int i = 0, c = mapsIds.length; i < c; i++)
|
||||
{
|
||||
if(mapsIds[i] == mapId) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public ImageMap toImageMap(UUID userUUID)
|
||||
{
|
||||
return new PosterMap(userUUID, mapsIds, null, "poster", 0, 0);
|
||||
}
|
||||
|
||||
public void serialize(Configuration configuration)
|
||||
{
|
||||
ArrayList<String> data = new ArrayList<String>();
|
||||
data.add(userName);
|
||||
|
||||
for(short mapId : mapsIds)
|
||||
{
|
||||
data.add(Short.toString(mapId));
|
||||
}
|
||||
|
||||
configuration.set(posterName, data);
|
||||
|
||||
}
|
||||
|
||||
public String getUserName() {return userName;}
|
||||
}
|
222
src/main/java/fr/moribus/imageonmap/migration/UUIDFetcher.java
Normal file
222
src/main/java/fr/moribus/imageonmap/migration/UUIDFetcher.java
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.migration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
abstract public class UUIDFetcher
|
||||
{
|
||||
/**
|
||||
* The maximal amount of usernames to send to mojang per request
|
||||
* This allows not to overload mojang's service with too many usernames at a time
|
||||
*/
|
||||
static private final int MOJANG_USERNAMES_PER_REQUEST = 100;
|
||||
|
||||
/**
|
||||
* The maximal amount of requests to send to Mojang
|
||||
* The time limit for this amount is MOJANG_MAX_REQUESTS_TIME
|
||||
* Read : You can only send MOJANG_MAX_REQUESTS in MOJANG_MAX_REQUESTS_TIME seconds
|
||||
*/
|
||||
static private final int MOJANG_MAX_REQUESTS = 600;
|
||||
|
||||
/**
|
||||
* The timeframe for the Mojang request limit (in seconds)
|
||||
*/
|
||||
static private final int MOJANG_MAX_REQUESTS_TIME = 600;
|
||||
|
||||
/**
|
||||
* The minimum time between two requests to mojang (in milliseconds)
|
||||
*/
|
||||
static private final int TIME_BETWEEN_REQUESTS = 200;
|
||||
|
||||
/**
|
||||
* The (approximative) timestamp of the date when Mojang name changing feature
|
||||
* was announced to be released
|
||||
*/
|
||||
static private final int NAME_CHANGE_TIMESTAMP = 1420844400;
|
||||
|
||||
static private final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft";
|
||||
static private final String TIMED_PROFILE_URL = "https://api.mojang.com/users/profiles/minecraft/";
|
||||
|
||||
static public Map<String, UUID> fetch(List<String> names) throws IOException, InterruptedException
|
||||
{
|
||||
return fetch(names, MOJANG_USERNAMES_PER_REQUEST);
|
||||
}
|
||||
|
||||
static public Map<String, UUID> fetch(List<String> names, int limitByRequest) throws IOException, InterruptedException
|
||||
{
|
||||
Map<String, UUID> UUIDs = new HashMap<String, UUID>();
|
||||
int requests = (names.size() / limitByRequest) + 1;
|
||||
|
||||
List<String> tempNames;
|
||||
Map<String, UUID> tempUUIDs;
|
||||
|
||||
for(int i = 0; i < requests; i++)
|
||||
{
|
||||
tempNames = names.subList(limitByRequest * i, Math.min((limitByRequest * (i+1)) - 1, names.size()));
|
||||
tempUUIDs = rawFetch(tempNames);
|
||||
UUIDs.putAll(tempUUIDs);
|
||||
Thread.sleep(TIME_BETWEEN_REQUESTS);
|
||||
}
|
||||
|
||||
return UUIDs;
|
||||
}
|
||||
|
||||
static private Map<String, UUID> rawFetch(List<String> names) throws IOException
|
||||
{
|
||||
Map<String, UUID> uuidMap = new HashMap<String, UUID>();
|
||||
HttpURLConnection connection = getPOSTConnection(PROFILE_URL);
|
||||
|
||||
writeBody(connection, names);
|
||||
JSONArray array;
|
||||
try
|
||||
{
|
||||
array = (JSONArray) readResponse(connection);
|
||||
}
|
||||
catch(ParseException ex)
|
||||
{
|
||||
throw new IOException("Invalid response from server, unable to parse received JSON : " + ex.toString());
|
||||
}
|
||||
|
||||
for (Object profile : array)
|
||||
{
|
||||
JSONObject jsonProfile = (JSONObject) profile;
|
||||
String id = (String) jsonProfile.get("id");
|
||||
String name = (String) jsonProfile.get("name");
|
||||
uuidMap.put(name, fromMojangUUID(id));
|
||||
}
|
||||
|
||||
return uuidMap;
|
||||
}
|
||||
|
||||
static public void fetchRemaining(Collection<String> names, Map<String, UUID> uuids) throws IOException, InterruptedException
|
||||
{
|
||||
ArrayList<String> remainingNames = new ArrayList<>();
|
||||
|
||||
for(String name : names)
|
||||
{
|
||||
if(!uuids.containsKey(name)) remainingNames.add(name);
|
||||
}
|
||||
|
||||
int timeBetweenRequests;
|
||||
if(remainingNames.size() > MOJANG_MAX_REQUESTS)
|
||||
{
|
||||
timeBetweenRequests = (MOJANG_MAX_REQUESTS / MOJANG_MAX_REQUESTS_TIME) * 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeBetweenRequests = TIME_BETWEEN_REQUESTS;
|
||||
}
|
||||
|
||||
User user;
|
||||
for(String name : remainingNames)
|
||||
{
|
||||
user = fetchOriginalUUID(name);
|
||||
uuids.put(name, user.uuid);
|
||||
Thread.sleep(timeBetweenRequests);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static private User fetchOriginalUUID(String name) throws IOException
|
||||
{
|
||||
HttpURLConnection connection = getGETConnection(TIMED_PROFILE_URL + name + "?at=" + NAME_CHANGE_TIMESTAMP);
|
||||
|
||||
JSONObject object;
|
||||
|
||||
try
|
||||
{
|
||||
object = (JSONObject) readResponse(connection);
|
||||
}
|
||||
catch(ParseException ex)
|
||||
{
|
||||
throw new IOException("Invalid response from server, unable to parse received JSON : " + ex.toString());
|
||||
}
|
||||
|
||||
User user = new User();
|
||||
user.name = (String) object.get("name");
|
||||
user.uuid = fromMojangUUID((String)object.get("id"));
|
||||
return user;
|
||||
}
|
||||
|
||||
static private HttpURLConnection getPOSTConnection(String url) throws IOException
|
||||
{
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setUseCaches(false);
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
return connection;
|
||||
}
|
||||
|
||||
static private HttpURLConnection getGETConnection(String url) throws IOException
|
||||
{
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setUseCaches(false);
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
private static void writeBody(HttpURLConnection connection, List<String> names) throws IOException
|
||||
{
|
||||
OutputStream stream = connection.getOutputStream();
|
||||
String body = JSONArray.toJSONString(names);
|
||||
stream.write(body.getBytes());
|
||||
stream.flush();
|
||||
stream.close();
|
||||
}
|
||||
|
||||
private static Object readResponse(HttpURLConnection connection) throws IOException, ParseException
|
||||
{
|
||||
return new JSONParser().parse(new InputStreamReader(connection.getInputStream()));
|
||||
}
|
||||
|
||||
private static UUID fromMojangUUID(String id) //Mojang sends string UUIDs without dashes ...
|
||||
{
|
||||
return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" +
|
||||
id.substring(12, 16) + "-" + id.substring(16, 20) + "-" +
|
||||
id.substring(20, 32));
|
||||
}
|
||||
|
||||
static private class User
|
||||
{
|
||||
public String name;
|
||||
public UUID uuid;
|
||||
}
|
||||
|
||||
}
|
||||
|
611
src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java
Normal file
611
src/main/java/fr/moribus/imageonmap/migration/V3Migrator.java
Normal file
@ -0,0 +1,611 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.migration;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import fr.moribus.imageonmap.map.MapManager;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
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.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* This class represents and executes the ImageOnMap v3.x migration process
|
||||
*/
|
||||
public class V3Migrator implements Runnable
|
||||
{
|
||||
/**
|
||||
* The name of the former images directory
|
||||
*/
|
||||
static private final String OLD_IMAGES_DIRECTORY_NAME = "Image";
|
||||
|
||||
/**
|
||||
* The name of the former file that contained all the maps definitions (including posters)
|
||||
*/
|
||||
static private final String OLD_MAPS_FILE_NAME = "map.yml";
|
||||
|
||||
/**
|
||||
* The name of the former file that contained all the posters definitions
|
||||
*/
|
||||
static private final String OLD_POSTERS_FILE_NAME = "poster.yml";
|
||||
|
||||
/**
|
||||
* The name of the backup directory that will contain the pre-v3 files that
|
||||
* were present before the migration started
|
||||
*/
|
||||
static private final String BACKUPS_PREV3_DIRECTORY_NAME = "backups_pre-v3";
|
||||
|
||||
/**
|
||||
* The name of the backup directory that will contain the post-v3 files that
|
||||
* were present before the migration started
|
||||
*/
|
||||
static private final String BACKUPS_POSTV3_DIRECTORY_NAME = "backups_post-v3";
|
||||
|
||||
/**
|
||||
* Returns the former images directory of a given plugin
|
||||
* @param plugin The plugin.
|
||||
* @return the corresponding 'Image' directory
|
||||
*/
|
||||
static public File getOldImagesDirectory(Plugin plugin)
|
||||
{
|
||||
return new File(plugin.getDataFolder(), OLD_IMAGES_DIRECTORY_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* The plugin that is running the migration
|
||||
*/
|
||||
private final ImageOnMap plugin;
|
||||
|
||||
/**
|
||||
* The former file that contained all the posters definitions
|
||||
*/
|
||||
private File oldPostersFile;
|
||||
|
||||
/**
|
||||
* The former file that contained all the maps definitions (including posters)
|
||||
*/
|
||||
private File oldMapsFile;
|
||||
|
||||
/**
|
||||
* The backup directory that will contain the pre-v3 files that
|
||||
* were present before the migration started
|
||||
*/
|
||||
private final File backupsPrev3Directory;
|
||||
|
||||
/**
|
||||
* The backup directory that will contain the post-v3 files that
|
||||
* were present before the migration started
|
||||
*/
|
||||
private final File backupsPostv3Directory;
|
||||
|
||||
/**
|
||||
* The list of all the posters to migrate
|
||||
*/
|
||||
private final ArrayDeque<OldSavedPoster> postersToMigrate;
|
||||
|
||||
/**
|
||||
* The list of all the single maps to migrate
|
||||
*/
|
||||
private final ArrayDeque<OldSavedMap> mapsToMigrate;
|
||||
|
||||
/**
|
||||
* The set of all the user names to retreive the UUID from Mojang
|
||||
*/
|
||||
private final HashSet<String> userNamesToFetch;
|
||||
|
||||
/**
|
||||
* The map of all the usernames and their corresponding UUIDs
|
||||
*/
|
||||
private Map<String, UUID> usersUUIDs;
|
||||
|
||||
/**
|
||||
* Defines if the migration process is currently running
|
||||
*/
|
||||
private boolean isRunning = false;
|
||||
|
||||
public V3Migrator(ImageOnMap plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
|
||||
File dataFolder = plugin.getDataFolder();
|
||||
|
||||
oldPostersFile = new File(dataFolder, OLD_POSTERS_FILE_NAME);
|
||||
oldMapsFile = new File(dataFolder, OLD_MAPS_FILE_NAME);
|
||||
|
||||
backupsPrev3Directory = new File(dataFolder, BACKUPS_PREV3_DIRECTORY_NAME);
|
||||
backupsPostv3Directory = new File(dataFolder, BACKUPS_POSTV3_DIRECTORY_NAME);
|
||||
|
||||
postersToMigrate = new ArrayDeque<>();
|
||||
mapsToMigrate = new ArrayDeque<>();
|
||||
userNamesToFetch = new HashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the full migration
|
||||
*/
|
||||
private void migrate()
|
||||
{
|
||||
try
|
||||
{
|
||||
if(!spotFilesToMigrate()) return;
|
||||
if(checkForExistingBackups()) return;
|
||||
if(!loadOldFiles()) return;
|
||||
backupMapData();
|
||||
fetchUUIDs();
|
||||
if(!fetchMissingUUIDs()) return;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
PluginLogger.error("Error while preparing migration");
|
||||
PluginLogger.error("Aborting migration. No change has been made.", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mergeMapData();
|
||||
saveChanges();
|
||||
cleanup();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
PluginLogger.error("Error while migrating", ex);
|
||||
PluginLogger.error("Aborting migration. Some changes may already have been made.");
|
||||
PluginLogger.error("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.");
|
||||
|
||||
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/* ****** Actions ***** */
|
||||
|
||||
/**
|
||||
* Checks if there is any of the former files to be migrated
|
||||
* @return true if any former map or poster file exists, false otherwise
|
||||
*/
|
||||
private boolean spotFilesToMigrate()
|
||||
{
|
||||
PluginLogger.info("Looking for configuration files to migrate ...");
|
||||
|
||||
if(!oldPostersFile.exists()) oldPostersFile = null;
|
||||
else PluginLogger.info("Detected former posters file {0}", OLD_POSTERS_FILE_NAME);
|
||||
|
||||
if(!oldMapsFile.exists()) oldMapsFile = null;
|
||||
else PluginLogger.info("Detected former maps file {0}", OLD_MAPS_FILE_NAME);
|
||||
|
||||
if(oldPostersFile == null && oldMapsFile == null)
|
||||
{
|
||||
PluginLogger.info("There is nothing to migrate. Stopping.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
PluginLogger.info("Done.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if any existing backup directories exists
|
||||
* @return true if a non-empty backup directory exists, false otherwise
|
||||
*/
|
||||
private boolean checkForExistingBackups()
|
||||
{
|
||||
if((backupsPrev3Directory.exists() && backupsPrev3Directory.list().length == 0)
|
||||
|| (backupsPostv3Directory.exists() && backupsPostv3Directory.list().length == 0))
|
||||
{
|
||||
PluginLogger.error("Backup directories already exists.");
|
||||
PluginLogger.error("This means that a migration has already been done, or may not have ended well.");
|
||||
PluginLogger.error("To start a new migration, you must move away the backup directories so they are not overwritten.");
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates backups of the former map files, and of the existing map stores
|
||||
* @throws IOException
|
||||
*/
|
||||
private void backupMapData() throws IOException
|
||||
{
|
||||
PluginLogger.info("Backing up map data before migrating ...");
|
||||
|
||||
if(!backupsPrev3Directory.exists()) backupsPrev3Directory.mkdirs();
|
||||
if(!backupsPostv3Directory.exists()) backupsPostv3Directory.mkdirs();
|
||||
|
||||
if(oldMapsFile != null && oldMapsFile.exists())
|
||||
{
|
||||
File oldMapsFileBackup = new File(backupsPrev3Directory, oldMapsFile.getName());
|
||||
verifiedBackupCopy(oldMapsFile, oldMapsFileBackup);
|
||||
}
|
||||
|
||||
if(oldPostersFile != null && oldPostersFile.exists())
|
||||
{
|
||||
File oldPostersFileBackup = new File(backupsPrev3Directory, oldPostersFile.getName());
|
||||
verifiedBackupCopy(oldPostersFile, oldPostersFileBackup);
|
||||
}
|
||||
|
||||
File backupFile;
|
||||
for(File mapFile : plugin.getMapsDirectory().listFiles())
|
||||
{
|
||||
backupFile = new File(backupsPostv3Directory, mapFile.getName());
|
||||
verifiedBackupCopy(mapFile, backupFile);
|
||||
}
|
||||
|
||||
PluginLogger.info("Backup complete.");
|
||||
}
|
||||
|
||||
/**
|
||||
* An utility function to check if a map is actually part of a loaded poster
|
||||
* @param map The single map.
|
||||
* @return true if the map is part of a poster, false otherwise
|
||||
*/
|
||||
private boolean posterContains(OldSavedMap map)
|
||||
{
|
||||
for(OldSavedPoster poster : postersToMigrate)
|
||||
{
|
||||
if(poster.contains(map)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the former files into the corresponding arrays
|
||||
* Also fetches the names of all the users that have maps
|
||||
* @return true if any of the files contained readable map data, false otherwise
|
||||
*/
|
||||
private boolean loadOldFiles()
|
||||
{
|
||||
if(oldPostersFile != null)
|
||||
{
|
||||
FileConfiguration oldPosters = YamlConfiguration.loadConfiguration(oldPostersFile);
|
||||
|
||||
OldSavedPoster oldPoster;
|
||||
for(String key : oldPosters.getKeys(false))
|
||||
{
|
||||
if("IdCount".equals(key)) continue;
|
||||
try
|
||||
{
|
||||
oldPoster = new OldSavedPoster(oldPosters.get(key), key);
|
||||
userNamesToFetch.add(oldPoster.getUserName());
|
||||
postersToMigrate.add(oldPoster);
|
||||
}
|
||||
catch(InvalidConfigurationException ex)
|
||||
{
|
||||
PluginLogger.warning("Could not read poster data for key '{0}'", ex, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(oldMapsFile != null)
|
||||
{
|
||||
FileConfiguration oldMaps = YamlConfiguration.loadConfiguration(oldMapsFile);
|
||||
OldSavedMap oldMap;
|
||||
|
||||
for(String key : oldMaps.getKeys(false))
|
||||
{
|
||||
try
|
||||
{
|
||||
if("IdCount".equals(key)) continue;
|
||||
oldMap = new OldSavedMap(oldMaps.get(key));
|
||||
|
||||
if(!posterContains(oldMap)) mapsToMigrate.add(oldMap);
|
||||
}
|
||||
catch(InvalidConfigurationException ex)
|
||||
{
|
||||
PluginLogger.warning("Could not read poster data for key '{0}'", ex, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (postersToMigrate.size() > 0) || (mapsToMigrate.size() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches all the needed UUIDs from Mojang's UUID conversion service
|
||||
* @throws IOException if the fetcher could not connect to Mojang's servers
|
||||
* @throws InterruptedException if the thread was interrupted while fetching UUIDs
|
||||
*/
|
||||
private void fetchUUIDs() throws IOException, InterruptedException
|
||||
{
|
||||
PluginLogger.info("Fetching UUIDs from Mojang ...");
|
||||
try
|
||||
{
|
||||
usersUUIDs = UUIDFetcher.fetch(new ArrayList<String>(userNamesToFetch));
|
||||
}
|
||||
catch(IOException ex)
|
||||
{
|
||||
PluginLogger.error("An error occured while fetching the UUIDs from Mojang", ex);
|
||||
throw ex;
|
||||
}
|
||||
catch(InterruptedException ex)
|
||||
{
|
||||
PluginLogger.error("The migration worker has been interrupted", ex);
|
||||
throw ex;
|
||||
}
|
||||
PluginLogger.info("Fetching done. {0} UUIDs have been retreived.", usersUUIDs.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the UUIDs that could not be retreived via Mojang's standard API
|
||||
* @return true if at least one UUID has been retreived, false otherwise
|
||||
*/
|
||||
private boolean fetchMissingUUIDs() throws IOException, InterruptedException
|
||||
{
|
||||
if(usersUUIDs.size() == userNamesToFetch.size()) return true;
|
||||
int remainingUsersCount = userNamesToFetch.size() - usersUUIDs.size();
|
||||
PluginLogger.info("Mojang did not find UUIDs for {0} players at the current time.", remainingUsersCount);
|
||||
PluginLogger.info("The Mojang servers limit requests rate at one per second, this may take some time...");
|
||||
|
||||
try
|
||||
{
|
||||
UUIDFetcher.fetchRemaining(userNamesToFetch, usersUUIDs);
|
||||
}
|
||||
catch(IOException ex)
|
||||
{
|
||||
PluginLogger.error("An error occured while fetching the UUIDs from Mojang");
|
||||
throw ex;
|
||||
}
|
||||
catch(InterruptedException ex)
|
||||
{
|
||||
PluginLogger.error("The migration worker has been interrupted");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if(usersUUIDs.size() != userNamesToFetch.size())
|
||||
{
|
||||
PluginLogger.warning("Mojang did not find player data for {0} players",
|
||||
userNamesToFetch.size() - usersUUIDs.size());
|
||||
PluginLogger.warning("The following players do not exist or do not have paid accounts :");
|
||||
|
||||
String missingUsersList = "";
|
||||
|
||||
for(String user : userNamesToFetch)
|
||||
{
|
||||
if(!usersUUIDs.containsKey(user)) missingUsersList += user + ",";
|
||||
}
|
||||
missingUsersList = missingUsersList.substring(0, missingUsersList.length());
|
||||
|
||||
PluginLogger.info(missingUsersList);
|
||||
}
|
||||
if(usersUUIDs.size() <= 0)
|
||||
{
|
||||
PluginLogger.info("Mojang could not find any of the registered players.");
|
||||
PluginLogger.info("There is nothing to migrate. Stopping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void mergeMapData()
|
||||
{
|
||||
PluginLogger.info("Merging map data ...");
|
||||
|
||||
ArrayDeque<OldSavedMap> remainingMaps = new ArrayDeque<>();
|
||||
ArrayDeque<OldSavedPoster> remainingPosters = new ArrayDeque<>();
|
||||
|
||||
UUID playerUUID;
|
||||
OldSavedMap map;
|
||||
while(!mapsToMigrate.isEmpty())
|
||||
{
|
||||
map = mapsToMigrate.pop();
|
||||
playerUUID = usersUUIDs.get(map.getUserName());
|
||||
if(playerUUID == null)
|
||||
{
|
||||
remainingMaps.add(map);
|
||||
}
|
||||
else
|
||||
{
|
||||
MapManager.insertMap(map.toImageMap(playerUUID));
|
||||
}
|
||||
}
|
||||
mapsToMigrate.addAll(remainingMaps);
|
||||
|
||||
OldSavedPoster poster;
|
||||
while(!postersToMigrate.isEmpty())
|
||||
{
|
||||
poster = postersToMigrate.pop();
|
||||
playerUUID = usersUUIDs.get(poster.getUserName());
|
||||
if(playerUUID == null)
|
||||
{
|
||||
remainingPosters.add(poster);
|
||||
}
|
||||
else
|
||||
{
|
||||
MapManager.insertMap(poster.toImageMap(playerUUID));
|
||||
}
|
||||
}
|
||||
postersToMigrate.addAll(remainingPosters);
|
||||
}
|
||||
|
||||
private void saveChanges()
|
||||
{
|
||||
PluginLogger.info("Saving changes ...");
|
||||
MapManager.save();
|
||||
}
|
||||
|
||||
private void cleanup() throws IOException
|
||||
{
|
||||
PluginLogger.info("Cleaning up old data files ...");
|
||||
|
||||
//Cleaning maps file
|
||||
if(oldMapsFile != null)
|
||||
{
|
||||
if(mapsToMigrate.isEmpty())
|
||||
{
|
||||
PluginLogger.info("Deleting old map data file ...");
|
||||
oldMapsFile.delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
PluginLogger.info("{0} maps could not be migrated.", mapsToMigrate.size());
|
||||
YamlConfiguration mapConfig = new YamlConfiguration();
|
||||
mapConfig.set("IdCount", mapsToMigrate.size());
|
||||
|
||||
for(OldSavedMap map : mapsToMigrate)
|
||||
{
|
||||
map.serialize(mapConfig);
|
||||
}
|
||||
|
||||
mapConfig.save(oldMapsFile);
|
||||
}
|
||||
}
|
||||
|
||||
//Cleaning posters file
|
||||
if(oldPostersFile != null)
|
||||
{
|
||||
if(postersToMigrate.isEmpty())
|
||||
{
|
||||
PluginLogger.info("Deleting old poster data file ...");
|
||||
oldPostersFile.delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
PluginLogger.info("{0} posters could not be migrated.", postersToMigrate.size());
|
||||
YamlConfiguration posterConfig = new YamlConfiguration();
|
||||
posterConfig.set("IdCount", postersToMigrate.size());
|
||||
|
||||
for(OldSavedPoster poster : postersToMigrate)
|
||||
{
|
||||
poster.serialize(posterConfig);
|
||||
}
|
||||
|
||||
posterConfig.save(oldPostersFile);
|
||||
}
|
||||
}
|
||||
|
||||
PluginLogger.info("Data that has not been migrated will be kept in the old data files.");
|
||||
}
|
||||
|
||||
/* ****** Utils ***** */
|
||||
|
||||
public synchronized boolean isRunning()
|
||||
{
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
private synchronized void setRunning(boolean running)
|
||||
{
|
||||
this.isRunning = running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the full migration, and defines the running status of the migration
|
||||
*/
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
setRunning(true);
|
||||
migrate();
|
||||
setRunning(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes a standard file copy, and checks the integrity of the destination
|
||||
* file after the copy
|
||||
* @param sourceFile The file to copy
|
||||
* @param destinationFile The destination file
|
||||
* @throws IOException If the copy failed, if the integrity check failed, or if the destination file already exists
|
||||
*/
|
||||
static private void verifiedBackupCopy(File sourceFile, File destinationFile) throws IOException
|
||||
{
|
||||
if(destinationFile.exists())
|
||||
throw new IOException("Backup copy failed : destination file ("+destinationFile.getName()+") already exists.");
|
||||
|
||||
long sourceSize = sourceFile.length();
|
||||
String sourceCheckSum = fileCheckSum(sourceFile, "SHA1");
|
||||
|
||||
Path sourcePath = Paths.get(sourceFile.getAbsolutePath());
|
||||
Path destinationPath = Paths.get(destinationFile.getAbsolutePath());
|
||||
Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
long destinationSize = destinationFile.length();
|
||||
String destinationCheckSum = fileCheckSum(destinationFile, "SHA1");
|
||||
|
||||
if(sourceSize != destinationSize || !sourceCheckSum.equals(destinationCheckSum))
|
||||
{
|
||||
throw new IOException("Backup copy failed : source and destination files ("+sourceFile.getName()+") differ after copy.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the checksum of a given file
|
||||
* @param file The file to calculate the checksum of
|
||||
* @param algorithmName The name of the algorithm to use
|
||||
* @return The resulting checksum in hexadecimal format
|
||||
* @throws IOException
|
||||
*/
|
||||
static private String fileCheckSum(File file, String algorithmName) throws IOException
|
||||
{
|
||||
MessageDigest instance;
|
||||
try
|
||||
{
|
||||
instance = MessageDigest.getInstance(algorithmName);
|
||||
}
|
||||
catch(NoSuchAlgorithmException ex)
|
||||
{
|
||||
throw new IOException("Could not check file integrity because of NoSuchAlgorithmException : " + ex.getMessage());
|
||||
}
|
||||
|
||||
FileInputStream inputStream = new FileInputStream(file);
|
||||
|
||||
byte[] data = new byte[1024];
|
||||
int read = 0;
|
||||
|
||||
while((read = inputStream.read(data)) != -1)
|
||||
{
|
||||
instance.update(data);
|
||||
}
|
||||
|
||||
byte[] hashBytes = instance.digest();
|
||||
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
char hexChar;
|
||||
for(int i = 0; i < hashBytes.length; i++)
|
||||
{
|
||||
hexChar = Integer.toHexString((hashBytes[i] & 0xff) + 0x100).charAt(0);
|
||||
buffer.append(hexChar);
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
141
src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java
Normal file
141
src/main/java/fr/moribus/imageonmap/ui/MapItemManager.java
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.ui;
|
||||
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.PosterMap;
|
||||
import fr.moribus.imageonmap.map.SingleMap;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.HashMap;
|
||||
import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
public class MapItemManager implements Listener
|
||||
{
|
||||
static private HashMap<UUID, Queue<ItemStack>> mapItemCache;
|
||||
|
||||
static public void init()
|
||||
{
|
||||
mapItemCache = new HashMap();
|
||||
}
|
||||
|
||||
static public void exit()
|
||||
{
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
|
||||
static public boolean give(Player player, SingleMap map)
|
||||
{
|
||||
return give(player, createMapItem(map.getMapsIDs()[0], map.getName()));
|
||||
}
|
||||
|
||||
static public boolean give(Player player, PosterMap map)
|
||||
{
|
||||
short[] mapsIDs = map.getMapsIDs();
|
||||
boolean inventoryFull = false;
|
||||
|
||||
String mapName;
|
||||
for(int i = 0, c = mapsIDs.length; i < c; i++)
|
||||
{
|
||||
if(map.hasColumnData())
|
||||
{
|
||||
mapName = map.getName() +
|
||||
" (row " + map.getRowAt(i) +
|
||||
", column " + map.getColumnAt(i) + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
mapName = map.getName();
|
||||
}
|
||||
inventoryFull = give(player, createMapItem(mapsIDs[i], mapName)) || inventoryFull;
|
||||
}
|
||||
|
||||
return inventoryFull;
|
||||
}
|
||||
|
||||
static public int giveCache(Player player)
|
||||
{
|
||||
Queue<ItemStack> cache = getCache(player);
|
||||
Inventory inventory = player.getInventory();
|
||||
int givenItemsCount = 0;
|
||||
|
||||
while(inventory.firstEmpty() >= 0 && !cache.isEmpty())
|
||||
{
|
||||
inventory.addItem(cache.poll());
|
||||
givenItemsCount++;
|
||||
}
|
||||
|
||||
return givenItemsCount;
|
||||
}
|
||||
|
||||
static private boolean give(Player player, ItemStack item)
|
||||
{
|
||||
if(player.getInventory().firstEmpty() <= -1)
|
||||
{
|
||||
getCache(player).add(item);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.getInventory().addItem(item);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static public ItemStack createMapItem(short mapID, String text)
|
||||
{
|
||||
ItemStack itemMap = new ItemStack(Material.MAP, 1, mapID);
|
||||
|
||||
ItemMeta meta = itemMap.getItemMeta();
|
||||
meta.setDisplayName(text);
|
||||
itemMap.setItemMeta(meta);
|
||||
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
static public int getCacheSize(Player player)
|
||||
{
|
||||
return getCache(player).size();
|
||||
}
|
||||
|
||||
static private Queue<ItemStack> getCache(Player player)
|
||||
{
|
||||
Queue<ItemStack> cache = mapItemCache.get(player.getUniqueId());
|
||||
if(cache == null)
|
||||
{
|
||||
cache = new ArrayDeque<>();
|
||||
mapItemCache.put(player.getUniqueId(), cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
}
|
132
src/main/java/fr/moribus/imageonmap/worker/Worker.java
Normal file
132
src/main/java/fr/moribus/imageonmap/worker/Worker.java
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.worker;
|
||||
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public abstract class Worker
|
||||
{
|
||||
private final String name;
|
||||
private final ArrayDeque<WorkerRunnable> runQueue = new ArrayDeque<>();
|
||||
|
||||
private final WorkerCallbackManager callbackManager;
|
||||
private final WorkerMainThreadExecutor mainThreadExecutor;
|
||||
private Thread thread;
|
||||
|
||||
protected Worker(String name)
|
||||
{
|
||||
this(name, false);
|
||||
}
|
||||
|
||||
protected Worker(String name, boolean runMainThreadExecutor)
|
||||
{
|
||||
this.name = name;
|
||||
this.callbackManager = new WorkerCallbackManager(name);
|
||||
this.mainThreadExecutor = runMainThreadExecutor ? new WorkerMainThreadExecutor(name) : null;
|
||||
}
|
||||
|
||||
protected void init()
|
||||
{
|
||||
if(thread != null && thread.isAlive())
|
||||
{
|
||||
PluginLogger.warning("Restarting '{0}' thread.", name);
|
||||
exit();
|
||||
}
|
||||
callbackManager.init();
|
||||
if(mainThreadExecutor != null) mainThreadExecutor.init();
|
||||
thread = createThread();
|
||||
thread.start();
|
||||
}
|
||||
|
||||
protected void exit()
|
||||
{
|
||||
thread.interrupt();
|
||||
callbackManager.exit();
|
||||
if(mainThreadExecutor != null) mainThreadExecutor.exit();
|
||||
thread = null;
|
||||
}
|
||||
|
||||
private void run()
|
||||
{
|
||||
WorkerRunnable currentRunnable;
|
||||
|
||||
while(!Thread.interrupted())
|
||||
{
|
||||
synchronized(runQueue)
|
||||
{
|
||||
try
|
||||
{
|
||||
while(runQueue.isEmpty()) runQueue.wait();
|
||||
}
|
||||
catch(InterruptedException ex)
|
||||
{
|
||||
break;
|
||||
}
|
||||
currentRunnable = runQueue.pop();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
callbackManager.callback(currentRunnable, currentRunnable.run());
|
||||
}
|
||||
catch(Throwable ex)
|
||||
{
|
||||
callbackManager.callback(currentRunnable, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void submitQuery(WorkerRunnable runnable)
|
||||
{
|
||||
synchronized(runQueue)
|
||||
{
|
||||
runQueue.add(runnable);
|
||||
runQueue.notify();
|
||||
}
|
||||
}
|
||||
|
||||
protected void submitQuery(WorkerRunnable runnable, WorkerCallback callback)
|
||||
{
|
||||
callbackManager.setupCallback(runnable, callback);
|
||||
submitQuery(runnable);
|
||||
}
|
||||
|
||||
protected <T> Future<T> submitToMainThread(Callable<T> callable)
|
||||
{
|
||||
if(mainThreadExecutor != null) return mainThreadExecutor.submit(callable);
|
||||
return null;
|
||||
}
|
||||
|
||||
private Thread createThread()
|
||||
{
|
||||
return new Thread("ImageOnMap-" + name)
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Worker.this.run();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package fr.moribus.imageonmap.worker;
|
||||
|
||||
public interface WorkerCallback<T>
|
||||
{
|
||||
public void finished(T result);
|
||||
public void errored(Throwable exception);
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.worker;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.HashMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
class WorkerCallbackManager implements Runnable
|
||||
{
|
||||
static private final int WATCH_LOOP_DELAY = 5;
|
||||
|
||||
private final HashMap<WorkerRunnable, WorkerRunnableInfo> callbacks;
|
||||
private final ArrayDeque<WorkerRunnableInfo> callbackQueue;
|
||||
|
||||
private final String name;
|
||||
|
||||
private BukkitTask selfTask;
|
||||
|
||||
public WorkerCallbackManager(String name)
|
||||
{
|
||||
callbacks = new HashMap<>();
|
||||
callbackQueue = new ArrayDeque<>();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
selfTask = Bukkit.getScheduler().runTaskTimer(ImageOnMap.getPlugin(), this, 0, WATCH_LOOP_DELAY);
|
||||
}
|
||||
|
||||
public void setupCallback(WorkerRunnable runnable, WorkerCallback callback)
|
||||
{
|
||||
synchronized(callbacks)
|
||||
{
|
||||
callbacks.put(runnable, new WorkerRunnableInfo(callback));
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void callback(WorkerRunnable<T> runnable, T result)
|
||||
{
|
||||
callback(runnable, result, null);
|
||||
}
|
||||
|
||||
public <T> void callback(WorkerRunnable<T> runnable, T result, Throwable exception)
|
||||
{
|
||||
WorkerRunnableInfo<T> runnableInfo;
|
||||
synchronized(callbacks)
|
||||
{
|
||||
runnableInfo = callbacks.get(runnable);
|
||||
}
|
||||
if(runnableInfo == null) return;
|
||||
runnableInfo.setRunnableException(exception);
|
||||
runnableInfo.setResult(result);
|
||||
|
||||
enqueueCallback(runnableInfo);
|
||||
}
|
||||
|
||||
public void exit()
|
||||
{
|
||||
if(selfTask != null) selfTask.cancel();
|
||||
}
|
||||
|
||||
private void enqueueCallback(WorkerRunnableInfo runnableInfo)
|
||||
{
|
||||
synchronized(callbackQueue)
|
||||
{
|
||||
callbackQueue.add(runnableInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
WorkerRunnableInfo currentRunnableInfo;
|
||||
synchronized(callbackQueue)
|
||||
{
|
||||
if(callbackQueue.isEmpty()) return;
|
||||
currentRunnableInfo = callbackQueue.pop();
|
||||
}
|
||||
|
||||
currentRunnableInfo.runCallback();
|
||||
}
|
||||
|
||||
private class WorkerRunnableInfo<T>
|
||||
{
|
||||
private final WorkerCallback<T> callback;
|
||||
private T result;
|
||||
private Throwable runnableException;
|
||||
|
||||
public WorkerRunnableInfo(WorkerCallback callback)
|
||||
{
|
||||
this.callback = callback;
|
||||
this.runnableException = null;
|
||||
}
|
||||
|
||||
public WorkerCallback getCallback()
|
||||
{
|
||||
return callback;
|
||||
}
|
||||
|
||||
public void runCallback()
|
||||
{
|
||||
if(runnableCrashed())
|
||||
{
|
||||
callback.errored(runnableException);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback.finished(result);
|
||||
}
|
||||
}
|
||||
|
||||
public void setResult(T result)
|
||||
{
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public Throwable getRunnableException()
|
||||
{
|
||||
return runnableException;
|
||||
}
|
||||
|
||||
public void setRunnableException(Throwable runnableException)
|
||||
{
|
||||
this.runnableException = runnableException;
|
||||
}
|
||||
|
||||
public boolean runnableCrashed()
|
||||
{
|
||||
return this.runnableException != null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.worker;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
class WorkerMainThreadExecutor implements Runnable
|
||||
{
|
||||
static private final int WATCH_LOOP_DELAY = 1;
|
||||
|
||||
private final String name;
|
||||
private final ArrayDeque<WorkerFuture> mainThreadQueue = new ArrayDeque<>();
|
||||
private BukkitTask mainThreadTask;
|
||||
|
||||
public WorkerMainThreadExecutor(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
mainThreadTask = Bukkit.getScheduler().runTaskTimer(ImageOnMap.getPlugin(), this, 0, WATCH_LOOP_DELAY);
|
||||
}
|
||||
|
||||
public void exit()
|
||||
{
|
||||
mainThreadTask.cancel();
|
||||
mainThreadTask = null;
|
||||
}
|
||||
|
||||
public <T> Future<T> submit(Callable<T> callable)
|
||||
{
|
||||
WorkerFuture<T> future = new WorkerFuture<T>(callable);
|
||||
synchronized(mainThreadQueue)
|
||||
{
|
||||
mainThreadQueue.add(future);
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
WorkerFuture currentFuture;
|
||||
synchronized(mainThreadQueue)
|
||||
{
|
||||
if(mainThreadQueue.isEmpty()) return;
|
||||
currentFuture = mainThreadQueue.pop();
|
||||
}
|
||||
|
||||
currentFuture.runCallable();
|
||||
}
|
||||
|
||||
private class WorkerFuture<T> implements Future<T>
|
||||
{
|
||||
private final Callable<T> callable;
|
||||
private boolean isCancelled;
|
||||
private boolean isDone;
|
||||
private Exception executionException;
|
||||
private T value;
|
||||
|
||||
public WorkerFuture(Callable<T> callable)
|
||||
{
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
public void runCallable()
|
||||
{
|
||||
try
|
||||
{
|
||||
value = callable.call();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
executionException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
isDone = true;
|
||||
synchronized(this){this.notifyAll();}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning)
|
||||
{
|
||||
if(this.isCancelled || this.isDone) return false;
|
||||
this.isCancelled = true;
|
||||
this.isDone = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled()
|
||||
{
|
||||
return this.isCancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone()
|
||||
{
|
||||
return this.isDone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() throws InterruptedException, ExecutionException
|
||||
{
|
||||
waitForCompletion();
|
||||
if(executionException != null) throw new ExecutionException(executionException);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
|
||||
{
|
||||
waitForCompletion(timeout, unit);
|
||||
if(executionException != null) throw new ExecutionException(executionException);
|
||||
return value;
|
||||
}
|
||||
|
||||
private void waitForCompletion(long timeout) throws InterruptedException, TimeoutException
|
||||
{
|
||||
synchronized(this)
|
||||
{
|
||||
long remainingTime;
|
||||
long timeoutTime = System.currentTimeMillis() + timeout;
|
||||
while(!isDone)
|
||||
{
|
||||
remainingTime = timeoutTime - System.currentTimeMillis();
|
||||
if(remainingTime <= 0) throw new TimeoutException();
|
||||
this.wait(remainingTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForCompletion() throws InterruptedException
|
||||
{
|
||||
synchronized(this)
|
||||
{
|
||||
while(!isDone) this.wait();
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForCompletion(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException
|
||||
{
|
||||
long millis = 0;
|
||||
switch(unit)
|
||||
{
|
||||
case NANOSECONDS:
|
||||
millis = timeout / 10^6;
|
||||
break;
|
||||
case MICROSECONDS:
|
||||
millis = timeout / 10^3;
|
||||
break;
|
||||
case MILLISECONDS:
|
||||
millis = timeout;
|
||||
break;
|
||||
case SECONDS:
|
||||
millis = timeout * 10^3;
|
||||
break;
|
||||
case MINUTES:
|
||||
millis = timeout * 10^3 * 60;
|
||||
break;
|
||||
case HOURS:
|
||||
millis = timeout * 10^3 * 3600;
|
||||
break;
|
||||
case DAYS:
|
||||
millis = timeout * 10^3 * 3600 * 24;
|
||||
}
|
||||
waitForCompletion(millis);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package fr.moribus.imageonmap.worker;
|
||||
|
||||
public interface WorkerRunnable<T>
|
||||
{
|
||||
public T run() throws Throwable;
|
||||
}
|
8
src/main/resources/help/maptool.txt
Normal file
8
src/main/resources/help/maptool.txt
Normal file
@ -0,0 +1,8 @@
|
||||
This command manages and creates ImagesOnMaps.
|
||||
new: Creates a new ImageOnMap
|
||||
delete: Deletes a map.
|
||||
delete-noconfirm: Deletes a map. Deletion is permanent and made without confirmation
|
||||
get: Gives you a map.
|
||||
getremaining: Gives you the remaining maps that could not fit in your inventory
|
||||
list: Lists all the map you currently have.
|
||||
help : Use help for more information about a command.
|
4
src/main/resources/help/maptool/delete-noconfirm.txt
Normal file
4
src/main/resources/help/maptool/delete-noconfirm.txt
Normal file
@ -0,0 +1,4 @@
|
||||
Deletes a map, and removes all parts and copies from your inventory.
|
||||
§cWARNING: §r THERE WILL BE NO CONFIRMATION. MAP DELETION IS §lPERMANENT§r.
|
||||
|
||||
[map name] : The name of the map you want to delete.
|
5
src/main/resources/help/maptool/delete.txt
Normal file
5
src/main/resources/help/maptool/delete.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Deletes a map, and removes all parts and copies from your inventory.
|
||||
As deletion is permanent, a confirmation message will be shown
|
||||
to the sending player.
|
||||
|
||||
[map name] : The name of the map you want to delete.
|
3
src/main/resources/help/maptool/get.txt
Normal file
3
src/main/resources/help/maptool/get.txt
Normal file
@ -0,0 +1,3 @@
|
||||
Gives you a map, by putting it directly in your inventory.
|
||||
|
||||
<map name> : The name of the map you want to get.
|
5
src/main/resources/help/maptool/getremaining.txt
Normal file
5
src/main/resources/help/maptool/getremaining.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Gives you the remaining maps that could not fit in your inventory.
|
||||
|
||||
If you requested a multi-part (poster) map, and all the parts can't fit in
|
||||
your inventory, then only first ones are given to you, and the remaining
|
||||
ones are saved. You can then use this command to retreive them.
|
1
src/main/resources/help/maptool/list.txt
Normal file
1
src/main/resources/help/maptool/list.txt
Normal file
@ -0,0 +1 @@
|
||||
Gives you a list of all the maps you currently have.
|
36
src/main/resources/help/maptool/migrate.txt
Normal file
36
src/main/resources/help/maptool/migrate.txt
Normal file
@ -0,0 +1,36 @@
|
||||
Migrates the Map database to the new V3.x format, that uses UUIDs
|
||||
instead of player names to designate players (among other improvements).
|
||||
Migration runs in a separate thread, therefore its progress can only be
|
||||
watched from the server console.
|
||||
|
||||
The migration will run the following steps :
|
||||
- Checking if there are files to migrate. If not, the migration stops.
|
||||
- Checking if there are backups from a previous migration.
|
||||
If there are, the migration stops.
|
||||
- Loading the old map and poster data to memory.
|
||||
- Backing up old files and new files, to the backups_pre-v3 and
|
||||
backups_post-v3 subdirectories respectively.
|
||||
Backup's integrity are chacked using file size and SHA1 checksum.
|
||||
If integrity could not be proved, the migration stops.
|
||||
- Retreiving the UUIDs of the players from Mojang's servers.
|
||||
- Checking if some UUIDs could not be retreived.
|
||||
If there are, this means some of your players may have changed names
|
||||
before the migration started. The plugin will therefore try to retreive
|
||||
them specifying a time, back when usernames could not be changed.
|
||||
If some names could still not be matched to their UUIDs, then these are
|
||||
probably non-paid accounts.
|
||||
If no UUID has been retreived at all, the migration stops.
|
||||
§c--- From this step, changes to disk will be made, and you will have to use§r
|
||||
§c--- backups if you want to revert back from before the migration started.§r
|
||||
- Merging the old map data with the new one, if there is any
|
||||
(which can be the case if your player started to use newer
|
||||
versions of ImageOnMap before the migration started).
|
||||
- Saving all this merged map data to disk.
|
||||
- Removing the old map data from their former files, leaving only the data
|
||||
that could not be migrated due to usernames that could not be matched to
|
||||
their UUIDs.
|
||||
Original data is still present in the appropriate backup directory,
|
||||
just in case.
|
||||
|
||||
Note that this plugin will NEVER delete nor overwrite any backup directory.
|
||||
Moving or deleting these backups is left to the administrator's responsibility.
|
1
src/main/resources/help/maptool/new.txt
Normal file
1
src/main/resources/help/maptool/new.txt
Normal file
@ -0,0 +1 @@
|
||||
Creates a new ImageOnMap.
|
@ -8,8 +8,6 @@ commands:
|
||||
usage: /<command> [URL]
|
||||
maptool:
|
||||
description: manage maps
|
||||
usage: /<command>
|
||||
|
||||
permissions:
|
||||
imageonmap.userender:
|
||||
description: Allows you to use /tomap
|
||||
|
Loading…
Reference in New Issue
Block a user