mirror of
https://github.com/zDevelopers/ImageOnMap.git
synced 2024-06-29 16:15:00 +02:00
Merge pull request #19 from AmauryCarrade/feature-explorer-gui-13
This commit is contained in:
commit
a2cdb02834
49
pom.xml
49
pom.xml
|
@ -5,24 +5,65 @@
|
||||||
<artifactId>ImageOnMap</artifactId>
|
<artifactId>ImageOnMap</artifactId>
|
||||||
<version>2.99</version>
|
<version>2.99</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.compiler.source>1.7</maven.compiler.source>
|
<maven.compiler.source>1.7</maven.compiler.source>
|
||||||
<maven.compiler.target>1.7</maven.compiler.target>
|
<maven.compiler.target>1.7</maven.compiler.target>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>2.3</version>
|
||||||
|
<configuration>
|
||||||
|
<artifactSet>
|
||||||
|
<includes>
|
||||||
|
<include>fr.zcraft:zlib</include>
|
||||||
|
</includes>
|
||||||
|
</artifactSet>
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>fr.zcraft.zlib</pattern>
|
||||||
|
<shadedPattern>fr.moribus.imageonmap</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>spigot-repo</id>
|
<id>spigot-repo</id>
|
||||||
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
|
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>zDevelopers</id>
|
||||||
|
<url>http://maven.carrade.eu/artifactory/snapshots</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
<dependencies>
|
|
||||||
<!-- Dependency information -->
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bukkit</groupId>
|
<groupId>org.bukkit</groupId>
|
||||||
<artifactId>bukkit</artifactId>
|
<artifactId>bukkit</artifactId>
|
||||||
<version>1.8-R0.1-SNAPSHOT</version>
|
<version>1.8.3-R0.1-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>fr.zcraft</groupId>
|
||||||
|
<artifactId>zlib</artifactId>
|
||||||
|
<version>0.99-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -18,7 +18,14 @@
|
||||||
|
|
||||||
package fr.moribus.imageonmap;
|
package fr.moribus.imageonmap;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.commands.Commands;
|
import fr.moribus.imageonmap.commands.maptool.DeleteConfirmCommand;
|
||||||
|
import fr.moribus.imageonmap.commands.maptool.DeleteNoConfirmCommand;
|
||||||
|
import fr.moribus.imageonmap.commands.maptool.ExploreCommand;
|
||||||
|
import fr.moribus.imageonmap.commands.maptool.GetCommand;
|
||||||
|
import fr.moribus.imageonmap.commands.maptool.GetRemainingCommand;
|
||||||
|
import fr.moribus.imageonmap.commands.maptool.ListCommand;
|
||||||
|
import fr.moribus.imageonmap.commands.maptool.MigrateCommand;
|
||||||
|
import fr.moribus.imageonmap.commands.maptool.NewCommand;
|
||||||
import fr.moribus.imageonmap.image.ImageIOExecutor;
|
import fr.moribus.imageonmap.image.ImageIOExecutor;
|
||||||
import fr.moribus.imageonmap.image.ImageRendererExecutor;
|
import fr.moribus.imageonmap.image.ImageRendererExecutor;
|
||||||
import fr.moribus.imageonmap.image.MapInitEvent;
|
import fr.moribus.imageonmap.image.MapInitEvent;
|
||||||
|
@ -26,11 +33,15 @@ import fr.moribus.imageonmap.map.MapManager;
|
||||||
import fr.moribus.imageonmap.migration.MigratorExecutor;
|
import fr.moribus.imageonmap.migration.MigratorExecutor;
|
||||||
import fr.moribus.imageonmap.migration.V3Migrator;
|
import fr.moribus.imageonmap.migration.V3Migrator;
|
||||||
import fr.moribus.imageonmap.ui.MapItemManager;
|
import fr.moribus.imageonmap.ui.MapItemManager;
|
||||||
|
import fr.zcraft.zlib.components.commands.Commands;
|
||||||
|
import fr.zcraft.zlib.components.gui.Gui;
|
||||||
|
import fr.zcraft.zlib.core.ZPlugin;
|
||||||
|
import fr.zcraft.zlib.tools.PluginLogger;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
|
|
||||||
public final class ImageOnMap extends JavaPlugin
|
public final class ImageOnMap extends ZPlugin
|
||||||
{
|
{
|
||||||
static private final String IMAGES_DIRECTORY_NAME = "images";
|
static private final String IMAGES_DIRECTORY_NAME = "images";
|
||||||
static private final String MAPS_DIRECTORY_NAME = "maps";
|
static private final String MAPS_DIRECTORY_NAME = "maps";
|
||||||
|
@ -58,10 +69,10 @@ public final class ImageOnMap extends JavaPlugin
|
||||||
return new File(imagesDirectory, "map"+mapID+".png");
|
return new File(imagesDirectory, "map"+mapID+".png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings ("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void onEnable()
|
public void onEnable()
|
||||||
{
|
{
|
||||||
PluginLogger.init(this);
|
|
||||||
// Creating the images and maps directories if necessary
|
// Creating the images and maps directories if necessary
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -70,31 +81,44 @@ public final class ImageOnMap extends JavaPlugin
|
||||||
}
|
}
|
||||||
catch(IOException ex)
|
catch(IOException ex)
|
||||||
{
|
{
|
||||||
PluginLogger.error("FATAL : " + ex.getMessage(), null);
|
PluginLogger.error("FATAL : " + ex.getMessage());
|
||||||
this.setEnabled(false);
|
this.setEnabled(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadComponents(Gui.class, Commands.class, ImageIOExecutor.class, ImageRendererExecutor.class);
|
||||||
|
|
||||||
//Init all the things !
|
//Init all the things !
|
||||||
PluginConfiguration.init(this);
|
PluginConfiguration.init(this);
|
||||||
MetricsLite.startMetrics();
|
MetricsLite.startMetrics();
|
||||||
ImageIOExecutor.start();
|
|
||||||
ImageRendererExecutor.start();
|
|
||||||
MapManager.init();
|
MapManager.init();
|
||||||
Commands.init(this);
|
|
||||||
MapInitEvent.init(this);
|
MapInitEvent.init(this);
|
||||||
MapItemManager.init();
|
MapItemManager.init();
|
||||||
|
|
||||||
|
Commands.register(
|
||||||
|
"maptool",
|
||||||
|
NewCommand.class,
|
||||||
|
ListCommand.class,
|
||||||
|
GetCommand.class,
|
||||||
|
DeleteConfirmCommand.class,
|
||||||
|
DeleteNoConfirmCommand.class,
|
||||||
|
GetRemainingCommand.class,
|
||||||
|
ExploreCommand.class,
|
||||||
|
MigrateCommand.class
|
||||||
|
);
|
||||||
|
|
||||||
|
Commands.registerShortcut("maptool", NewCommand.class, "tomap");
|
||||||
|
Commands.registerShortcut("maptool", ExploreCommand.class, "maps");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable()
|
public void onDisable()
|
||||||
{
|
{
|
||||||
ImageIOExecutor.stop();
|
|
||||||
ImageRendererExecutor.stop();
|
|
||||||
MapManager.exit();
|
MapManager.exit();
|
||||||
MapItemManager.exit();
|
MapItemManager.exit();
|
||||||
MigratorExecutor.waitForMigration();
|
MigratorExecutor.waitForMigration();
|
||||||
PluginLogger.exit();
|
|
||||||
|
super.onDisable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private File checkPluginDirectory(File primaryFile, File... alternateFiles) throws IOException
|
private File checkPluginDirectory(File primaryFile, File... alternateFiles) throws IOException
|
||||||
|
@ -108,5 +132,4 @@ public final class ImageOnMap extends JavaPlugin
|
||||||
throw new IOException("Could not create '" + primaryFile.getName() + "' plugin directory.");
|
throw new IOException("Could not create '" + primaryFile.getName() + "' plugin directory.");
|
||||||
return primaryFile;
|
return primaryFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ package fr.moribus.imageonmap;
|
||||||
* either expressed or implied, of anybody else.
|
* either expressed or implied, of anybody else.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import fr.zcraft.zlib.tools.PluginLogger;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 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()
|
|
||||||
{
|
|
||||||
Thread currentThread = Thread.currentThread();
|
|
||||||
if(currentThread.equals(mainThread)) return plugin.getLogger();
|
|
||||||
return getLogger(currentThread);
|
|
||||||
}
|
|
||||||
|
|
||||||
static private Logger getLogger(Thread thread)
|
|
||||||
{
|
|
||||||
PluginThreadLogger logger = loggers.get(thread);
|
|
||||||
if(logger == null)
|
|
||||||
{
|
|
||||||
logger = new PluginThreadLogger(thread);
|
|
||||||
loggers.put(thread, logger);
|
|
||||||
}
|
|
||||||
return logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
static private class PluginThreadLogger extends Logger
|
|
||||||
{
|
|
||||||
private final String loggerName;
|
|
||||||
public PluginThreadLogger(Thread thread)
|
|
||||||
{
|
|
||||||
super(plugin.getClass().getCanonicalName(), null);
|
|
||||||
setParent(plugin.getLogger());
|
|
||||||
setLevel(Level.ALL);
|
|
||||||
loggerName = "[" + thread.getName() + "] ";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void log(LogRecord logRecord)
|
|
||||||
{
|
|
||||||
logRecord.setMessage(loggerName + logRecord.getMessage());
|
|
||||||
super.log(logRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,268 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,329 +0,0 @@
|
||||||
/*
|
|
||||||
* 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; }
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,140 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
77
src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java
Normal file
77
src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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.map.ImageMap;
|
||||||
|
import fr.moribus.imageonmap.map.MapManager;
|
||||||
|
import fr.zcraft.zlib.components.commands.Command;
|
||||||
|
import fr.zcraft.zlib.components.commands.CommandException;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class IoMCommand extends Command
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> getMatchingMapNames(Player player, String prefix)
|
||||||
|
{
|
||||||
|
return getMatchingMapNames(MapManager.getMapList(player.getUniqueId()), prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> getMatchingMapNames(Iterable<? extends ImageMap> maps, String prefix)
|
||||||
|
{
|
||||||
|
List<String> matches = new ArrayList<>();
|
||||||
|
|
||||||
|
for(ImageMap map : maps)
|
||||||
|
{
|
||||||
|
if(map.getId().startsWith(prefix)) matches.add(map.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,20 +18,18 @@
|
||||||
|
|
||||||
package fr.moribus.imageonmap.commands.maptool;
|
package fr.moribus.imageonmap.commands.maptool;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.commands.*;
|
import fr.moribus.imageonmap.commands.IoMCommand;
|
||||||
import fr.moribus.imageonmap.map.ImageMap;
|
import fr.moribus.imageonmap.map.ImageMap;
|
||||||
|
import fr.zcraft.zlib.components.commands.CommandException;
|
||||||
|
import fr.zcraft.zlib.components.commands.CommandInfo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@CommandInfo(name = "delete", usageParameters = "[tool name]")
|
@CommandInfo (name = "delete", usageParameters = "[tool name]")
|
||||||
public class DeleteConfirmCommand extends Command
|
public class DeleteConfirmCommand extends IoMCommand
|
||||||
{
|
{
|
||||||
|
|
||||||
public DeleteConfirmCommand(Commands commandGroup) {
|
|
||||||
super(commandGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run() throws CommandException
|
protected void run() throws CommandException
|
||||||
{
|
{
|
||||||
ImageMap map = getMapFromArgs();
|
ImageMap map = getMapFromArgs();
|
||||||
tellRaw("{text:\"You are going to delete \",extra:[{text:\""+ map.getId() +"\",color:gold},{text:\". Are you sure ? \",color:white}," +
|
tellRaw("{text:\"You are going to delete \",extra:[{text:\""+ map.getId() +"\",color:gold},{text:\". Are you sure ? \",color:white}," +
|
||||||
|
@ -45,8 +43,7 @@ public class DeleteConfirmCommand extends Command
|
||||||
{
|
{
|
||||||
if(args.length == 1)
|
if(args.length == 1)
|
||||||
return getMatchingMapNames(playerSender(), args[0]);
|
return getMatchingMapNames(playerSender(), args[0]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,25 +18,23 @@
|
||||||
|
|
||||||
package fr.moribus.imageonmap.commands.maptool;
|
package fr.moribus.imageonmap.commands.maptool;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.PluginLogger;
|
import fr.moribus.imageonmap.commands.IoMCommand;
|
||||||
import fr.moribus.imageonmap.commands.*;
|
|
||||||
import fr.moribus.imageonmap.map.ImageMap;
|
import fr.moribus.imageonmap.map.ImageMap;
|
||||||
import fr.moribus.imageonmap.map.MapManager;
|
import fr.moribus.imageonmap.map.MapManager;
|
||||||
import fr.moribus.imageonmap.map.MapManagerException;
|
import fr.moribus.imageonmap.map.MapManagerException;
|
||||||
import java.util.List;
|
import fr.zcraft.zlib.components.commands.CommandException;
|
||||||
|
import fr.zcraft.zlib.components.commands.CommandInfo;
|
||||||
|
import fr.zcraft.zlib.tools.PluginLogger;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@CommandInfo(name = "delete-noconfirm", usageParameters = "[map name]")
|
|
||||||
public class DeleteNoConfirmCommand extends Command
|
@CommandInfo (name = "delete-noconfirm", usageParameters = "[map name]")
|
||||||
|
public class DeleteNoConfirmCommand extends IoMCommand
|
||||||
{
|
{
|
||||||
|
|
||||||
public DeleteNoConfirmCommand(Commands commandGroup) {
|
|
||||||
super(commandGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run() throws CommandException
|
protected void run() throws CommandException
|
||||||
{
|
{
|
||||||
Player player = playerSender();
|
Player player = playerSender();
|
||||||
ImageMap map = getMapFromArgs();
|
ImageMap map = getMapFromArgs();
|
||||||
|
|
|
@ -16,15 +16,22 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package fr.moribus.imageonmap.commands;
|
package fr.moribus.imageonmap.commands.maptool;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
import fr.moribus.imageonmap.commands.IoMCommand;
|
||||||
@Target({ElementType.TYPE})
|
import fr.moribus.imageonmap.gui.MapListGui;
|
||||||
public @interface CommandInfo
|
import fr.zcraft.zlib.components.commands.CommandException;
|
||||||
|
import fr.zcraft.zlib.components.commands.CommandInfo;
|
||||||
|
import fr.zcraft.zlib.components.gui.Gui;
|
||||||
|
|
||||||
|
|
||||||
|
@CommandInfo (name = "explore")
|
||||||
|
public class ExploreCommand extends IoMCommand
|
||||||
{
|
{
|
||||||
String name();
|
@Override
|
||||||
String usageParameters() default "";
|
protected void run() throws CommandException
|
||||||
String[] aliases() default {};
|
{
|
||||||
|
Gui.open(playerSender(), new MapListGui());
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -18,17 +18,16 @@
|
||||||
|
|
||||||
package fr.moribus.imageonmap.commands.maptool;
|
package fr.moribus.imageonmap.commands.maptool;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.commands.*;
|
import fr.moribus.imageonmap.commands.IoMCommand;
|
||||||
import java.util.List;
|
import fr.zcraft.zlib.components.commands.CommandException;
|
||||||
|
import fr.zcraft.zlib.components.commands.CommandInfo;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@CommandInfo(name = "get")
|
import java.util.List;
|
||||||
public class GetCommand extends Command
|
|
||||||
|
@CommandInfo (name = "get")
|
||||||
|
public class GetCommand extends IoMCommand
|
||||||
{
|
{
|
||||||
public GetCommand(Commands commandGroup) {
|
|
||||||
super(commandGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run() throws CommandException
|
protected void run() throws CommandException
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,20 +18,15 @@
|
||||||
|
|
||||||
package fr.moribus.imageonmap.commands.maptool;
|
package fr.moribus.imageonmap.commands.maptool;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.commands.Command;
|
import fr.moribus.imageonmap.commands.IoMCommand;
|
||||||
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 fr.moribus.imageonmap.ui.MapItemManager;
|
||||||
|
import fr.zcraft.zlib.components.commands.CommandException;
|
||||||
|
import fr.zcraft.zlib.components.commands.CommandInfo;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@CommandInfo(name = "getremaining", aliases = {"getrest"})
|
@CommandInfo (name = "getremaining", aliases = {"getrest"})
|
||||||
public class GetRemainingCommand extends Command
|
public class GetRemainingCommand extends IoMCommand
|
||||||
{
|
{
|
||||||
public GetRemainingCommand(Commands commandGroup) {
|
|
||||||
super(commandGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run() throws CommandException
|
protected void run() throws CommandException
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,19 +18,18 @@
|
||||||
|
|
||||||
package fr.moribus.imageonmap.commands.maptool;
|
package fr.moribus.imageonmap.commands.maptool;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.commands.*;
|
import fr.moribus.imageonmap.commands.IoMCommand;
|
||||||
import fr.moribus.imageonmap.map.ImageMap;
|
import fr.moribus.imageonmap.map.ImageMap;
|
||||||
import fr.moribus.imageonmap.map.MapManager;
|
import fr.moribus.imageonmap.map.MapManager;
|
||||||
import java.util.List;
|
import fr.zcraft.zlib.components.commands.CommandException;
|
||||||
|
import fr.zcraft.zlib.components.commands.CommandInfo;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@CommandInfo(name = "list")
|
import java.util.List;
|
||||||
public class ListCommand extends Command
|
|
||||||
|
@CommandInfo (name = "list")
|
||||||
|
public class ListCommand extends IoMCommand
|
||||||
{
|
{
|
||||||
public ListCommand(Commands commandGroup) {
|
|
||||||
super(commandGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run() throws CommandException
|
protected void run() throws CommandException
|
||||||
{
|
{
|
||||||
|
@ -52,5 +51,4 @@ public class ListCommand extends Command
|
||||||
}
|
}
|
||||||
player.sendMessage(sMapList);
|
player.sendMessage(sMapList);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,21 +18,18 @@
|
||||||
|
|
||||||
package fr.moribus.imageonmap.commands.maptool;
|
package fr.moribus.imageonmap.commands.maptool;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.commands.*;
|
import fr.moribus.imageonmap.commands.IoMCommand;
|
||||||
import fr.moribus.imageonmap.migration.MigratorExecutor;
|
import fr.moribus.imageonmap.migration.MigratorExecutor;
|
||||||
|
import fr.zcraft.zlib.components.commands.CommandException;
|
||||||
|
import fr.zcraft.zlib.components.commands.CommandInfo;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
@CommandInfo(name = "migrate")
|
@CommandInfo (name = "migrate")
|
||||||
public class MigrateCommand extends Command
|
public class MigrateCommand extends IoMCommand
|
||||||
{
|
{
|
||||||
public MigrateCommand(Commands commandGroup) {
|
|
||||||
super(commandGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run() throws CommandException
|
protected void run() throws CommandException
|
||||||
{
|
{
|
||||||
final CommandSender cmdSender = sender;
|
|
||||||
if(MigratorExecutor.isRunning())
|
if(MigratorExecutor.isRunning())
|
||||||
{
|
{
|
||||||
error("A migration process is already running. Check console for details.");
|
error("A migration process is already running. Check console for details.");
|
||||||
|
|
|
@ -18,25 +18,21 @@
|
||||||
|
|
||||||
package fr.moribus.imageonmap.commands.maptool;
|
package fr.moribus.imageonmap.commands.maptool;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.PluginLogger;
|
import fr.moribus.imageonmap.commands.IoMCommand;
|
||||||
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.image.ImageRendererExecutor;
|
||||||
import fr.moribus.imageonmap.map.ImageMap;
|
import fr.moribus.imageonmap.map.ImageMap;
|
||||||
import fr.moribus.imageonmap.worker.WorkerCallback;
|
import fr.zcraft.zlib.components.commands.CommandException;
|
||||||
import java.net.MalformedURLException;
|
import fr.zcraft.zlib.components.commands.CommandInfo;
|
||||||
import java.net.URL;
|
import fr.zcraft.zlib.components.worker.WorkerCallback;
|
||||||
|
import fr.zcraft.zlib.tools.PluginLogger;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@CommandInfo(name = "new", usageParameters = "<URL> [resize]")
|
import java.net.MalformedURLException;
|
||||||
public class NewCommand extends Command
|
import java.net.URL;
|
||||||
|
|
||||||
|
@CommandInfo (name = "new", usageParameters = "<URL> [resize]")
|
||||||
|
public class NewCommand extends IoMCommand
|
||||||
{
|
{
|
||||||
public NewCommand(Commands commandGroup) {
|
|
||||||
super(commandGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run() throws CommandException
|
protected void run() throws CommandException
|
||||||
{
|
{
|
||||||
|
@ -83,5 +79,4 @@ public class NewCommand extends Command
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
194
src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java
Normal file
194
src/main/java/fr/moribus/imageonmap/gui/ConfirmDeleteMapGui.java
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
* 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.gui;
|
||||||
|
|
||||||
|
import fr.moribus.imageonmap.map.ImageMap;
|
||||||
|
import fr.moribus.imageonmap.map.MapManager;
|
||||||
|
import fr.moribus.imageonmap.map.MapManagerException;
|
||||||
|
import fr.zcraft.zlib.components.gui.ActionGui;
|
||||||
|
import fr.zcraft.zlib.components.gui.Gui;
|
||||||
|
import fr.zcraft.zlib.components.gui.GuiAction;
|
||||||
|
import fr.zcraft.zlib.tools.PluginLogger;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.DyeColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.material.Dye;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
|
||||||
|
public class ConfirmDeleteMapGui extends ActionGui
|
||||||
|
{
|
||||||
|
static private final int BUTTONS_WIDTH = 4;
|
||||||
|
|
||||||
|
static private final int FIRST_SLOT_DELETE_BUTTON = 27;
|
||||||
|
static private final int SHIFT_CANCEL_BUTTON = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The messages randomly displayed in the lore of the “delete” buttons.
|
||||||
|
*/
|
||||||
|
static private final String[] DELETE_MESSAGES = new String[]{
|
||||||
|
"Please", "I'm still alive", "Don't do that", "I'm still loving you", "I want to live",
|
||||||
|
"Please please", "Please please please", "What are you doing?!", "Nooooo!",
|
||||||
|
"Click and I'll be dead", "Why?", "Please don't do that", "Think about my family",
|
||||||
|
"Click, I don't like you anymore.", "I don't hate you.", "Click, I'm ready.",
|
||||||
|
"I'm a green button.", "I'm different.", "Thanks anyway.", "Excuse me.", "Get mad.",
|
||||||
|
"Sorry!", "My fault!", "I don't blame you.", "No hard feelings.",
|
||||||
|
"But I need to protect the humans!", "Noooo!", "I'm scared!", "What are you doing?",
|
||||||
|
"It burns.", "This is not good.", "Can't breathe.", "Thanks anyway.", "These things happen.",
|
||||||
|
"That was nobody's fault.", "I probably deserved it.", "I blame myself."
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The messages randomly displayed in the lore of the “cancel” buttons.
|
||||||
|
*/
|
||||||
|
static private final String[] CANCEL_MESSAGES = new String[] {
|
||||||
|
"Yay!", "Still aliiiive!", "Click click click", "Yes do that", "I'm a red button.",
|
||||||
|
"Please click here", "The other button is ugly", "Save me", "This is the good choice",
|
||||||
|
"Click, I want to live!", "I'll be dead another day anyway", "Are you sure?",
|
||||||
|
"So you're still loving me?", "Please save me", "Take me with you.",
|
||||||
|
"Excuse me.", "Don't make lemonade.", "Sleep mode activated.", "Hybernating.",
|
||||||
|
"Your business is appreciated.", "Hey! It's me! Don't shoot!", "Wheee!", "Hurray!",
|
||||||
|
"You have excellent aim!", "Please please please"
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map being deleted.
|
||||||
|
*/
|
||||||
|
private final ImageMap mapToDelete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A source of randomness.
|
||||||
|
*
|
||||||
|
* Yes, this javadoc comment is REALLY useful. Trust me.
|
||||||
|
*/
|
||||||
|
private final Random random = new Random();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param mapToDelete The map being deleted.
|
||||||
|
*/
|
||||||
|
public ConfirmDeleteMapGui(ImageMap mapToDelete)
|
||||||
|
{
|
||||||
|
this.mapToDelete = mapToDelete;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onUpdate()
|
||||||
|
{
|
||||||
|
setTitle(mapToDelete.getName() + " » " + ChatColor.BLACK + "Confirm deletion");
|
||||||
|
setSize(6 * 9);
|
||||||
|
|
||||||
|
/* ** Item representation of the image being deleted ** */
|
||||||
|
|
||||||
|
ItemStack beingDeleted = new ItemStack(Material.EMPTY_MAP);
|
||||||
|
ItemMeta meta = beingDeleted.getItemMeta();
|
||||||
|
|
||||||
|
meta.setDisplayName(ChatColor.RED + "You're about to destroy this map...");
|
||||||
|
meta.setLore(Arrays.asList(
|
||||||
|
ChatColor.RED + "..." + ChatColor.ITALIC + "forever" + ChatColor.RED + ".",
|
||||||
|
"",
|
||||||
|
ChatColor.GRAY + "Name: " + ChatColor.WHITE + mapToDelete.getName(),
|
||||||
|
ChatColor.GRAY + "Map ID: " + ChatColor.WHITE + mapToDelete.getId(),
|
||||||
|
ChatColor.GRAY + "Maps inside: " + ChatColor.WHITE + mapToDelete.getMapsIDs().length
|
||||||
|
));
|
||||||
|
|
||||||
|
beingDeleted.setItemMeta(meta);
|
||||||
|
|
||||||
|
action("", 13, beingDeleted);
|
||||||
|
|
||||||
|
|
||||||
|
/* ** Buttons ** */
|
||||||
|
|
||||||
|
int slot = FIRST_SLOT_DELETE_BUTTON;
|
||||||
|
for(; slot < getSize() - (9 - BUTTONS_WIDTH); slot++)
|
||||||
|
{
|
||||||
|
action("delete", slot, createDeleteSubButton());
|
||||||
|
action("cancel", slot + SHIFT_CANCEL_BUTTON, createCancelSubButton());
|
||||||
|
|
||||||
|
if((slot + 1) % 9 == (9 - BUTTONS_WIDTH - 1))
|
||||||
|
slot += 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack createDeleteSubButton()
|
||||||
|
{
|
||||||
|
// Orange? Nooo. In the real world this is red. True story.
|
||||||
|
return createSubButton(DyeColor.ORANGE, ChatColor.RED + "Delete the map", DELETE_MESSAGES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack createCancelSubButton()
|
||||||
|
{
|
||||||
|
// YES. Purple = lime. BECAUSE. Just accept it.
|
||||||
|
return createSubButton(DyeColor.PURPLE, ChatColor.GREEN + "Cancel", CANCEL_MESSAGES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack createSubButton(DyeColor color, String title, String[] messages)
|
||||||
|
{
|
||||||
|
Dye pane = new Dye(Material.STAINED_GLASS_PANE);
|
||||||
|
pane.setColor(color);
|
||||||
|
|
||||||
|
ItemStack subButton = pane.toItemStack(1);
|
||||||
|
ItemMeta meta = subButton.getItemMeta();
|
||||||
|
|
||||||
|
meta.setDisplayName(title);
|
||||||
|
meta.setLore(Arrays.asList(
|
||||||
|
"",
|
||||||
|
ChatColor.GRAY + messages[random.nextInt(messages.length)]
|
||||||
|
));
|
||||||
|
|
||||||
|
subButton.setItemMeta(meta);
|
||||||
|
return subButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuiAction ("cancel")
|
||||||
|
protected void cancel()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuiAction ("delete")
|
||||||
|
protected void delete()
|
||||||
|
{
|
||||||
|
MapManager.clear(getPlayer().getInventory(), mapToDelete);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MapManager.deleteMap(mapToDelete);
|
||||||
|
getPlayer().sendMessage(ChatColor.GRAY + "Map successfully deleted.");
|
||||||
|
}
|
||||||
|
catch (MapManagerException ex)
|
||||||
|
{
|
||||||
|
PluginLogger.warning("Error while deleting map", ex);
|
||||||
|
getPlayer().sendMessage(ChatColor.RED + ex.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// We try to open the map list GUI, if the map was deleted, before the details GUI
|
||||||
|
// (so the grandparent GUI)..
|
||||||
|
if (getParent() != null && getParent().getParent() != null)
|
||||||
|
Gui.open(getPlayer(), getParent().getParent());
|
||||||
|
else
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
166
src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java
Normal file
166
src/main/java/fr/moribus/imageonmap/gui/MapDetailGui.java
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* 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.gui;
|
||||||
|
|
||||||
|
import fr.moribus.imageonmap.map.ImageMap;
|
||||||
|
import fr.moribus.imageonmap.map.PosterMap;
|
||||||
|
import fr.moribus.imageonmap.map.SingleMap;
|
||||||
|
import fr.moribus.imageonmap.ui.MapItemManager;
|
||||||
|
import fr.zcraft.zlib.components.gui.ExplorerGui;
|
||||||
|
import fr.zcraft.zlib.components.gui.Gui;
|
||||||
|
import fr.zcraft.zlib.components.gui.GuiAction;
|
||||||
|
import fr.zcraft.zlib.components.gui.GuiUtils;
|
||||||
|
import fr.zcraft.zlib.components.gui.PromptGui;
|
||||||
|
import fr.zcraft.zlib.tools.Callback;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
|
||||||
|
public class MapDetailGui extends ExplorerGui
|
||||||
|
{
|
||||||
|
private final ImageMap map;
|
||||||
|
|
||||||
|
public MapDetailGui(ImageMap map)
|
||||||
|
{
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemStack getViewItem(int x, int y)
|
||||||
|
{
|
||||||
|
Material partMaterial = Material.PAPER;
|
||||||
|
if((y % 2 == 0 && x % 2 == 0) || (y % 2 == 1 && x % 2 == 1))
|
||||||
|
partMaterial = Material.EMPTY_MAP;
|
||||||
|
|
||||||
|
ItemStack part = new ItemStack(partMaterial);
|
||||||
|
ItemMeta meta = part.getItemMeta();
|
||||||
|
|
||||||
|
meta.setDisplayName(ChatColor.GREEN + "Map part");
|
||||||
|
meta.setLore(Arrays.asList(
|
||||||
|
ChatColor.GRAY + "Column: " + ChatColor.WHITE + (y + 1),
|
||||||
|
ChatColor.GRAY + "Row: " + ChatColor.WHITE + (x + 1),
|
||||||
|
"",
|
||||||
|
ChatColor.GRAY + "» Click to get only this part"
|
||||||
|
));
|
||||||
|
|
||||||
|
part.setItemMeta(meta);
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemStack getPickedUpItem(int x, int y)
|
||||||
|
{
|
||||||
|
if(map instanceof SingleMap)
|
||||||
|
{
|
||||||
|
return MapItemManager.createMapItem((SingleMap)map);
|
||||||
|
}
|
||||||
|
else if(map instanceof PosterMap)
|
||||||
|
{
|
||||||
|
return MapItemManager.createMapItem((PosterMap)map, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Unsupported map type : " + map.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemStack getEmptyViewItem()
|
||||||
|
{
|
||||||
|
if(map instanceof SingleMap)
|
||||||
|
{
|
||||||
|
return getViewItem(0, 0);
|
||||||
|
}
|
||||||
|
else return super.getEmptyViewItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onUpdate()
|
||||||
|
{
|
||||||
|
setTitle("Your maps » " + ChatColor.BLACK + map.getName());
|
||||||
|
setKeepHorizontalScrollingSpace(true);
|
||||||
|
|
||||||
|
if(map instanceof PosterMap)
|
||||||
|
setDataShape(((PosterMap) map).getColumnCount(), ((PosterMap) map).getRowCount());
|
||||||
|
else
|
||||||
|
setData(null); // Fallback to the empty view item.
|
||||||
|
|
||||||
|
|
||||||
|
action("rename", getSize() - 7, GuiUtils.makeItem(Material.BOOK_AND_QUILL, ChatColor.BLUE + "Rename this image", Arrays.asList(
|
||||||
|
ChatColor.GRAY + "Click here to rename this image;",
|
||||||
|
ChatColor.GRAY + "this is used for your own organization."
|
||||||
|
)));
|
||||||
|
|
||||||
|
action("delete", getSize() - 6, GuiUtils.makeItem(Material.BARRIER, ChatColor.RED + "Delete this image", Arrays.asList(
|
||||||
|
ChatColor.GRAY + "Deletes this map " + ChatColor.WHITE + "forever" + ChatColor.GRAY + ".",
|
||||||
|
ChatColor.GRAY + "This action cannot be undone!",
|
||||||
|
"",
|
||||||
|
ChatColor.GRAY + "You will be asked to confirm your",
|
||||||
|
ChatColor.GRAY + "choice if you click here."
|
||||||
|
)));
|
||||||
|
|
||||||
|
|
||||||
|
// To keep the controls centered, the back button is shifted to the right when the
|
||||||
|
// arrow isn't displayed, so when the map fit on the grid without sliders.
|
||||||
|
int backSlot = getSize() - 4;
|
||||||
|
|
||||||
|
if(map instanceof PosterMap && ((PosterMap) map).getColumnCount() <= INVENTORY_ROW_SIZE)
|
||||||
|
backSlot++;
|
||||||
|
|
||||||
|
action("back", backSlot, GuiUtils.makeItem(Material.EMERALD, ChatColor.GREEN + "« Back", Collections.singletonList(
|
||||||
|
ChatColor.GRAY + "Go back to the list."
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GuiAction ("rename")
|
||||||
|
public void rename()
|
||||||
|
{
|
||||||
|
PromptGui.prompt(getPlayer(), new Callback<String>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void call(String newName)
|
||||||
|
{
|
||||||
|
if (newName == null || newName.isEmpty())
|
||||||
|
{
|
||||||
|
getPlayer().sendMessage(ChatColor.RED + "Map names can't be empty.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
map.rename(newName);
|
||||||
|
getPlayer().sendMessage(ChatColor.GRAY + "Map successfully renamed.");
|
||||||
|
}
|
||||||
|
}, map.getName(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuiAction ("delete")
|
||||||
|
public void delete()
|
||||||
|
{
|
||||||
|
Gui.open(getPlayer(), new ConfirmDeleteMapGui(map), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuiAction ("back")
|
||||||
|
public void back()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
185
src/main/java/fr/moribus/imageonmap/gui/MapListGui.java
Normal file
185
src/main/java/fr/moribus/imageonmap/gui/MapListGui.java
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
* 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.gui;
|
||||||
|
|
||||||
|
import fr.moribus.imageonmap.PluginConfiguration;
|
||||||
|
import fr.moribus.imageonmap.map.ImageMap;
|
||||||
|
import fr.moribus.imageonmap.map.MapManager;
|
||||||
|
import fr.moribus.imageonmap.map.PosterMap;
|
||||||
|
import fr.moribus.imageonmap.map.SingleMap;
|
||||||
|
import fr.moribus.imageonmap.ui.MapItemManager;
|
||||||
|
import fr.zcraft.zlib.components.gui.ExplorerGui;
|
||||||
|
import fr.zcraft.zlib.components.gui.Gui;
|
||||||
|
import fr.zcraft.zlib.components.gui.GuiUtils;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.DecimalFormatSymbols;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
|
||||||
|
public class MapListGui extends ExplorerGui<ImageMap>
|
||||||
|
{
|
||||||
|
private final NumberFormat bigNumbersFormatter = new DecimalFormat("###,###,###,###", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemStack getViewItem(ImageMap map)
|
||||||
|
{
|
||||||
|
String mapDescription;
|
||||||
|
if (map instanceof SingleMap)
|
||||||
|
mapDescription = "Single map";
|
||||||
|
else
|
||||||
|
mapDescription = "Poster map (" + ((PosterMap) map).getColumnCount() + "×" + ((PosterMap) map).getRowCount() + ")";
|
||||||
|
|
||||||
|
ItemStack icon = GuiUtils.makeItem(Material.MAP, ChatColor.GREEN + "" + ChatColor.BOLD + map.getName(), Arrays.asList(
|
||||||
|
ChatColor.WHITE + mapDescription,
|
||||||
|
"",
|
||||||
|
ChatColor.GRAY + "Map ID: " + map.getId(),
|
||||||
|
"",
|
||||||
|
ChatColor.GRAY + "» Left-click to get this map",
|
||||||
|
ChatColor.GRAY + "» Right-click for details and options"
|
||||||
|
));
|
||||||
|
|
||||||
|
return GuiUtils.hideItemAttributes(icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemStack getEmptyViewItem()
|
||||||
|
{
|
||||||
|
ItemStack empty = new ItemStack(Material.BARRIER);
|
||||||
|
ItemMeta meta = empty.getItemMeta();
|
||||||
|
|
||||||
|
meta.setDisplayName(ChatColor.RED + "You don't have any map.");
|
||||||
|
meta.setLore(Arrays.asList(
|
||||||
|
ChatColor.GRAY + "Get started by creating a new one",
|
||||||
|
ChatColor.GRAY + "using " + ChatColor.WHITE + "/tomap <URL> [resize]" + ChatColor.GRAY + "!"
|
||||||
|
));
|
||||||
|
|
||||||
|
empty.setItemMeta(meta);
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onRightClick(ImageMap data)
|
||||||
|
{
|
||||||
|
Gui.open(getPlayer(), new MapDetailGui(data), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemStack getPickedUpItem(ImageMap map)
|
||||||
|
{
|
||||||
|
if (map instanceof SingleMap)
|
||||||
|
{
|
||||||
|
return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
MapItemManager.give(getPlayer(), map);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onUpdate()
|
||||||
|
{
|
||||||
|
ImageMap[] maps = MapManager.getMaps(getPlayer().getUniqueId());
|
||||||
|
setData(maps);
|
||||||
|
setTitle(ChatColor.BLACK + "Your maps " + ChatColor.RESET + "(" + maps.length + ")");
|
||||||
|
|
||||||
|
setKeepHorizontalScrollingSpace(true);
|
||||||
|
|
||||||
|
|
||||||
|
/* ** Statistics ** */
|
||||||
|
|
||||||
|
int imagesCount = MapManager.getMapList(getPlayer().getUniqueId()).size();
|
||||||
|
int mapPartCount = MapManager.getMapPartCount(getPlayer().getUniqueId());
|
||||||
|
|
||||||
|
int mapGlobalLimit = PluginConfiguration.MAP_GLOBAL_LIMIT.getInteger();
|
||||||
|
int mapPersonalLimit = PluginConfiguration.MAP_PLAYER_LIMIT.getInteger();
|
||||||
|
|
||||||
|
int mapPartGloballyLeft = mapGlobalLimit - MapManager.getMapCount();
|
||||||
|
int mapPartPersonallyLeft = mapPersonalLimit - mapPartCount;
|
||||||
|
|
||||||
|
int mapPartLeft;
|
||||||
|
if (mapGlobalLimit <= 0 && mapPersonalLimit <= 0)
|
||||||
|
mapPartLeft = -1;
|
||||||
|
else if (mapGlobalLimit <= 0)
|
||||||
|
mapPartLeft = mapPartPersonallyLeft;
|
||||||
|
else if (mapPersonalLimit <= 0)
|
||||||
|
mapPartLeft = mapPartGloballyLeft;
|
||||||
|
else
|
||||||
|
mapPartLeft = Math.min(mapPartGloballyLeft, mapPartPersonallyLeft);
|
||||||
|
|
||||||
|
double percentageUsed = mapPartLeft < 0 ? 0 : ((double) mapPartCount) / ((double) (mapPartCount + mapPartLeft)) * 100;
|
||||||
|
|
||||||
|
|
||||||
|
ItemStack statistics = new ItemStack(Material.ENCHANTED_BOOK);
|
||||||
|
ItemMeta meta = statistics.getItemMeta();
|
||||||
|
|
||||||
|
meta.setDisplayName(ChatColor.BLUE + "Usage statistics");
|
||||||
|
meta.setLore(Arrays.asList(
|
||||||
|
"",
|
||||||
|
getStatisticText("Images rendered", imagesCount),
|
||||||
|
getStatisticText("Minecraft maps used", mapPartCount)
|
||||||
|
));
|
||||||
|
|
||||||
|
if (mapPartLeft >= 0)
|
||||||
|
{
|
||||||
|
List<String> lore = meta.getLore();
|
||||||
|
|
||||||
|
lore.add("");
|
||||||
|
lore.add(ChatColor.BLUE + "Minecraft maps limits");
|
||||||
|
|
||||||
|
lore.add("");
|
||||||
|
lore.add(getStatisticText("Server-wide limit", mapGlobalLimit, true));
|
||||||
|
lore.add(getStatisticText("Per-player limit", mapPersonalLimit, true));
|
||||||
|
|
||||||
|
lore.add("");
|
||||||
|
lore.add(getStatisticText("Current consumption", ((int) Math.rint(percentageUsed)) + " %"));
|
||||||
|
lore.add(getStatisticText("Maps left", mapPartLeft));
|
||||||
|
|
||||||
|
meta.setLore(lore);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiUtils.hideItemAttributes(meta);
|
||||||
|
|
||||||
|
statistics.setItemMeta(meta);
|
||||||
|
action("", getSize() - 5, statistics);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getStatisticText(String title, Integer value)
|
||||||
|
{
|
||||||
|
return getStatisticText(title, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getStatisticText(String title, Integer value, boolean zeroIsUnlimited)
|
||||||
|
{
|
||||||
|
return getStatisticText(title, zeroIsUnlimited && value <= 0 ? "unlimited" : bigNumbersFormatter.format(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getStatisticText(String title, String value)
|
||||||
|
{
|
||||||
|
return ChatColor.GRAY + title + ": " + ChatColor.WHITE + value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,53 +20,36 @@ package fr.moribus.imageonmap.image;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.ImageOnMap;
|
import fr.moribus.imageonmap.ImageOnMap;
|
||||||
import fr.moribus.imageonmap.map.ImageMap;
|
import fr.moribus.imageonmap.map.ImageMap;
|
||||||
import fr.moribus.imageonmap.worker.Worker;
|
import fr.zcraft.zlib.components.worker.Worker;
|
||||||
import fr.moribus.imageonmap.worker.WorkerCallback;
|
import fr.zcraft.zlib.components.worker.WorkerAttributes;
|
||||||
import fr.moribus.imageonmap.worker.WorkerRunnable;
|
import fr.zcraft.zlib.components.worker.WorkerRunnable;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
|
|
||||||
|
|
||||||
|
@WorkerAttributes (name = "Image IO")
|
||||||
public class ImageIOExecutor extends Worker
|
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)
|
static public void loadImage(final File file, final Renderer mapRenderer)
|
||||||
{
|
{
|
||||||
instance.submitQuery(new WorkerRunnable<Void>()
|
submitQuery(new WorkerRunnable<Void>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Void run() throws Exception
|
||||||
{
|
{
|
||||||
@Override
|
BufferedImage image = ImageIO.read(file);
|
||||||
public Void run() throws Exception
|
mapRenderer.setImage(image);
|
||||||
{
|
return null;
|
||||||
BufferedImage image = ImageIO.read(file);
|
}
|
||||||
mapRenderer.setImage(image);
|
});
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static public void saveImage(final File file, final BufferedImage image)
|
static public void saveImage(final File file, final BufferedImage image)
|
||||||
{
|
{
|
||||||
instance.submitQuery(new WorkerRunnable<Void>()
|
submitQuery(new WorkerRunnable<Void>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Void run() throws Throwable
|
public Void run() throws Throwable
|
||||||
|
@ -101,7 +84,7 @@ public class ImageIOExecutor extends Worker
|
||||||
|
|
||||||
static public void deleteImage(final File file)
|
static public void deleteImage(final File file)
|
||||||
{
|
{
|
||||||
instance.submitQuery(new WorkerRunnable<Void>()
|
submitQuery(new WorkerRunnable<Void>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Void run() throws Throwable
|
public Void run() throws Throwable
|
||||||
|
@ -109,7 +92,6 @@ public class ImageIOExecutor extends Worker
|
||||||
Files.delete(file.toPath());
|
Files.delete(file.toPath());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,46 +18,29 @@
|
||||||
|
|
||||||
package fr.moribus.imageonmap.image;
|
package fr.moribus.imageonmap.image;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.PluginLogger;
|
|
||||||
import fr.moribus.imageonmap.map.ImageMap;
|
import fr.moribus.imageonmap.map.ImageMap;
|
||||||
import fr.moribus.imageonmap.map.MapManager;
|
import fr.moribus.imageonmap.map.MapManager;
|
||||||
import fr.moribus.imageonmap.worker.Worker;
|
import fr.zcraft.zlib.components.worker.Worker;
|
||||||
import fr.moribus.imageonmap.worker.WorkerCallback;
|
import fr.zcraft.zlib.components.worker.WorkerAttributes;
|
||||||
import fr.moribus.imageonmap.worker.WorkerRunnable;
|
import fr.zcraft.zlib.components.worker.WorkerCallback;
|
||||||
import java.awt.Graphics;
|
import fr.zcraft.zlib.components.worker.WorkerRunnable;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
|
|
||||||
|
|
||||||
|
@WorkerAttributes (name = "Image Renderer", queriesMainThread = true)
|
||||||
public class ImageRendererExecutor extends Worker
|
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)
|
static public void Test(WorkerCallback callback)
|
||||||
{
|
{
|
||||||
instance.submitQuery(new WorkerRunnable<Void>()
|
submitQuery(new WorkerRunnable<Void>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Void run() throws Throwable
|
public Void run() throws Throwable
|
||||||
|
@ -70,15 +53,15 @@ public class ImageRendererExecutor extends Worker
|
||||||
|
|
||||||
static public void Render(final URL url, final boolean scaling, final UUID playerUUID, WorkerCallback<ImageMap> callback)
|
static public void Render(final URL url, final boolean scaling, final UUID playerUUID, WorkerCallback<ImageMap> callback)
|
||||||
{
|
{
|
||||||
instance.submitQuery(new WorkerRunnable<ImageMap>()
|
submitQuery(new WorkerRunnable<ImageMap>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public ImageMap run() throws Throwable
|
public ImageMap run() throws Throwable
|
||||||
{
|
{
|
||||||
final BufferedImage image = ImageIO.read(url);
|
final BufferedImage image = ImageIO.read(url);
|
||||||
if(image == null) throw new IOException("The given URL is not a valid image");
|
if (image == null) throw new IOException("The given URL is not a valid image");
|
||||||
|
|
||||||
if(scaling) return RenderSingle(image, playerUUID);
|
if (scaling) return RenderSingle(image, playerUUID);
|
||||||
else return RenderPoster(image, playerUUID);
|
else return RenderPoster(image, playerUUID);
|
||||||
}
|
}
|
||||||
}, callback);
|
}, callback);
|
||||||
|
@ -87,7 +70,7 @@ public class ImageRendererExecutor extends Worker
|
||||||
static private ImageMap RenderSingle(final BufferedImage image, final UUID playerUUID) throws Throwable
|
static private ImageMap RenderSingle(final BufferedImage image, final UUID playerUUID) throws Throwable
|
||||||
{
|
{
|
||||||
MapManager.checkMapLimit(1, playerUUID);
|
MapManager.checkMapLimit(1, playerUUID);
|
||||||
Future<Short> futureMapID = instance.submitToMainThread(new Callable<Short>()
|
Future<Short> futureMapID = submitToMainThread(new Callable<Short>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Short call() throws Exception
|
public Short call() throws Exception
|
||||||
|
@ -101,7 +84,7 @@ public class ImageRendererExecutor extends Worker
|
||||||
final short mapID = futureMapID.get();
|
final short mapID = futureMapID.get();
|
||||||
ImageIOExecutor.saveImage(mapID, finalImage);
|
ImageIOExecutor.saveImage(mapID, finalImage);
|
||||||
|
|
||||||
instance.submitToMainThread(new Callable<Void>()
|
submitToMainThread(new Callable<Void>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Void call() throws Exception
|
public Void call() throws Exception
|
||||||
|
@ -121,7 +104,7 @@ public class ImageRendererExecutor extends Worker
|
||||||
final int mapCount = poster.getImagesCount();
|
final int mapCount = poster.getImagesCount();
|
||||||
|
|
||||||
MapManager.checkMapLimit(mapCount, playerUUID);
|
MapManager.checkMapLimit(mapCount, playerUUID);
|
||||||
final Future<short[]> futureMapsIds = instance.submitToMainThread(new Callable<short[]>()
|
final Future<short[]> futureMapsIds = submitToMainThread(new Callable<short[]>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public short[] call() throws Exception
|
public short[] call() throws Exception
|
||||||
|
@ -136,7 +119,7 @@ public class ImageRendererExecutor extends Worker
|
||||||
|
|
||||||
ImageIOExecutor.saveImage(mapsIDs, poster);
|
ImageIOExecutor.saveImage(mapsIDs, poster);
|
||||||
|
|
||||||
instance.submitToMainThread(new Callable<Void>()
|
submitToMainThread(new Callable<Void>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Void call() throws Exception
|
public Void call() throws Exception
|
||||||
|
@ -178,5 +161,4 @@ public class ImageRendererExecutor extends Worker
|
||||||
graphics.dispose();
|
graphics.dispose();
|
||||||
return newImage;
|
return newImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,9 @@ import org.bukkit.entity.ItemFrame;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||||
|
import org.bukkit.event.player.PlayerPickupItemEvent;
|
||||||
import org.bukkit.event.world.ChunkLoadEvent;
|
import org.bukkit.event.world.ChunkLoadEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.map.MapView;
|
import org.bukkit.map.MapView;
|
||||||
|
@ -73,6 +75,26 @@ public class MapInitEvent implements Listener
|
||||||
initMap(item);
|
initMap(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerPickup(PlayerPickupItemEvent event)
|
||||||
|
{
|
||||||
|
ItemStack item = event.getItem().getItemStack();
|
||||||
|
initMap(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerInventoryPlace(InventoryClickEvent event)
|
||||||
|
{
|
||||||
|
switch(event.getAction())
|
||||||
|
{
|
||||||
|
case PLACE_ALL:
|
||||||
|
case PLACE_ONE:
|
||||||
|
case PLACE_SOME:
|
||||||
|
case SWAP_WITH_CURSOR:
|
||||||
|
initMap(event.getCursor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static protected void initMap(ItemStack item)
|
static protected void initMap(ItemStack item)
|
||||||
{
|
{
|
||||||
if (item != null && item.getType() == Material.MAP)
|
if (item != null && item.getType() == Material.MAP)
|
||||||
|
|
|
@ -18,15 +18,14 @@
|
||||||
|
|
||||||
package fr.moribus.imageonmap.map;
|
package fr.moribus.imageonmap.map;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.ui.MapItemManager;
|
import fr.moribus.imageonmap.ui.*;
|
||||||
import java.util.HashMap;
|
import org.bukkit.*;
|
||||||
import java.util.Map;
|
import org.bukkit.configuration.*;
|
||||||
import java.util.UUID;
|
import org.bukkit.configuration.serialization.*;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.entity.*;
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
import org.bukkit.inventory.*;
|
||||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
|
||||||
import org.bukkit.entity.Player;
|
import java.util.*;
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
public abstract class ImageMap implements ConfigurationSerializable
|
public abstract class ImageMap implements ConfigurationSerializable
|
||||||
{
|
{
|
||||||
|
@ -160,6 +159,11 @@ public abstract class ImageMap implements ConfigurationSerializable
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized Type getType()
|
||||||
|
{
|
||||||
|
return mapType;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void rename(String id, String name)
|
public synchronized void rename(String id, String name)
|
||||||
{
|
{
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
|
@ -61,7 +61,7 @@ abstract public class MapManager
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public boolean managesMap(ItemStack item)
|
static public boolean managesMap(ItemStack item)
|
||||||
{
|
{
|
||||||
synchronized(playerMaps)
|
synchronized(playerMaps)
|
||||||
|
@ -73,7 +73,7 @@ abstract public class MapManager
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public ImageMap createMap(UUID playerUUID, short mapID) throws MapManagerException
|
static public ImageMap createMap(UUID playerUUID, short mapID) throws MapManagerException
|
||||||
{
|
{
|
||||||
ImageMap newMap = new SingleMap(playerUUID, mapID);
|
ImageMap newMap = new SingleMap(playerUUID, mapID);
|
||||||
|
@ -139,10 +139,66 @@ abstract public class MapManager
|
||||||
return getPlayerMapStore(playerUUID).getMapList();
|
return getPlayerMapStore(playerUUID).getMapList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public ImageMap[] getMaps(UUID playerUUID)
|
||||||
|
{
|
||||||
|
return getPlayerMapStore(playerUUID).getMaps();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of minecraft maps used by the images rendered by the given player.
|
||||||
|
*
|
||||||
|
* @param playerUUID The player's UUID.
|
||||||
|
*
|
||||||
|
* @return The count.
|
||||||
|
*/
|
||||||
|
static public int getMapPartCount(UUID playerUUID)
|
||||||
|
{
|
||||||
|
return getPlayerMapStore(playerUUID).getMapCount();
|
||||||
|
}
|
||||||
|
|
||||||
static public ImageMap getMap(UUID playerUUID, String mapId)
|
static public ImageMap getMap(UUID playerUUID, String mapId)
|
||||||
{
|
{
|
||||||
return getPlayerMapStore(playerUUID).getMap(mapId);
|
return getPlayerMapStore(playerUUID).getMap(mapId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link ImageMap} this map belongs to.
|
||||||
|
*
|
||||||
|
* @param mapId The ID of the Minecraft map.
|
||||||
|
* @return The {@link ImageMap}.
|
||||||
|
*/
|
||||||
|
static public ImageMap getMap(short mapId)
|
||||||
|
{
|
||||||
|
synchronized(playerMaps)
|
||||||
|
{
|
||||||
|
for(PlayerMapStore mapStore : playerMaps)
|
||||||
|
{
|
||||||
|
if(mapStore.managesMap(mapId))
|
||||||
|
{
|
||||||
|
for(ImageMap map : mapStore.getMapList())
|
||||||
|
{
|
||||||
|
if(map.managesMap(mapId))
|
||||||
|
{
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link ImageMap} this map belongs to.
|
||||||
|
*
|
||||||
|
* @param item The map, as an {@link ItemStack}.
|
||||||
|
* @return The {@link ImageMap}.
|
||||||
|
*/
|
||||||
|
static public ImageMap getMap(ItemStack item)
|
||||||
|
{
|
||||||
|
return getMap(item.getDurability());
|
||||||
|
}
|
||||||
|
|
||||||
static public void clear(Inventory inventory)
|
static public void clear(Inventory inventory)
|
||||||
{
|
{
|
||||||
|
@ -192,7 +248,12 @@ abstract public class MapManager
|
||||||
}
|
}
|
||||||
getPlayerMapStore(userUUID).checkMapLimit(newMapsCount);
|
getPlayerMapStore(userUUID).checkMapLimit(newMapsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total number of minecraft maps used by ImageOnMap images.
|
||||||
|
*
|
||||||
|
* @return The count.
|
||||||
|
*/
|
||||||
static public int getMapCount()
|
static public int getMapCount()
|
||||||
{
|
{
|
||||||
int mapCount = 0;
|
int mapCount = 0;
|
||||||
|
|
|
@ -20,8 +20,15 @@ package fr.moribus.imageonmap.map;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.ImageOnMap;
|
import fr.moribus.imageonmap.ImageOnMap;
|
||||||
import fr.moribus.imageonmap.PluginConfiguration;
|
import fr.moribus.imageonmap.PluginConfiguration;
|
||||||
import fr.moribus.imageonmap.PluginLogger;
|
|
||||||
import fr.moribus.imageonmap.map.MapManagerException.Reason;
|
import fr.moribus.imageonmap.map.MapManagerException.Reason;
|
||||||
|
import fr.zcraft.zlib.tools.PluginLogger;
|
||||||
|
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;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -29,12 +36,6 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
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
|
public class PlayerMapStore implements ConfigurationSerializable
|
||||||
{
|
{
|
||||||
|
@ -127,6 +128,11 @@ public class PlayerMapStore implements ConfigurationSerializable
|
||||||
return new ArrayList(mapList);
|
return new ArrayList(mapList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized ImageMap[] getMaps()
|
||||||
|
{
|
||||||
|
return mapList.toArray(new ImageMap[mapList.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized ImageMap getMap(String mapId)
|
public synchronized ImageMap getMap(String mapId)
|
||||||
{
|
{
|
||||||
for(ImageMap map : mapList)
|
for(ImageMap map : mapList)
|
||||||
|
|
|
@ -18,10 +18,11 @@
|
||||||
|
|
||||||
package fr.moribus.imageonmap.map;
|
package fr.moribus.imageonmap.map;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
|
||||||
|
|
||||||
public class PosterMap extends ImageMap
|
public class PosterMap extends ImageMap
|
||||||
{
|
{
|
||||||
|
@ -115,6 +116,20 @@ public class PosterMap extends ImageMap
|
||||||
if(columnCount == 0) return 0;
|
if(columnCount == 0) return 0;
|
||||||
return (i / columnCount) + 1;
|
return (i / columnCount) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the map id at the given column and line.
|
||||||
|
*
|
||||||
|
* @param col The column. Starts at 0.
|
||||||
|
* @param row The row. Starts at 0.
|
||||||
|
* @return The Minecraft map ID.
|
||||||
|
*
|
||||||
|
* @throws ArrayIndexOutOfBoundsException if the given coordinates are too big (out of the poster).
|
||||||
|
*/
|
||||||
|
public short getMapIdAt(int col, int row)
|
||||||
|
{
|
||||||
|
return mapsIDs[getColumnCount() * col + row];
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasColumnData()
|
public boolean hasColumnData()
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
package fr.moribus.imageonmap.migration;
|
package fr.moribus.imageonmap.migration;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.ImageOnMap;
|
import fr.moribus.imageonmap.ImageOnMap;
|
||||||
import fr.moribus.imageonmap.PluginLogger;
|
import fr.zcraft.zlib.tools.PluginLogger;
|
||||||
|
|
||||||
|
|
||||||
public class MigratorExecutor
|
public class MigratorExecutor
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,222 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -19,8 +19,14 @@
|
||||||
package fr.moribus.imageonmap.migration;
|
package fr.moribus.imageonmap.migration;
|
||||||
|
|
||||||
import fr.moribus.imageonmap.ImageOnMap;
|
import fr.moribus.imageonmap.ImageOnMap;
|
||||||
import fr.moribus.imageonmap.PluginLogger;
|
|
||||||
import fr.moribus.imageonmap.map.MapManager;
|
import fr.moribus.imageonmap.map.MapManager;
|
||||||
|
import fr.zcraft.zlib.tools.PluginLogger;
|
||||||
|
import fr.zcraft.zlib.tools.mojang.UUIDFetcher;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -37,10 +43,6 @@ import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
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
|
* This class represents and executes the ImageOnMap v3.x migration process
|
||||||
|
@ -350,7 +352,7 @@ public class V3Migrator implements Runnable
|
||||||
}
|
}
|
||||||
catch(IOException ex)
|
catch(IOException ex)
|
||||||
{
|
{
|
||||||
PluginLogger.error("An error occured while fetching the UUIDs from Mojang", ex);
|
PluginLogger.error("An error occurred while fetching the UUIDs from Mojang", ex);
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
catch(InterruptedException ex)
|
catch(InterruptedException ex)
|
||||||
|
@ -358,12 +360,12 @@ public class V3Migrator implements Runnable
|
||||||
PluginLogger.error("The migration worker has been interrupted", ex);
|
PluginLogger.error("The migration worker has been interrupted", ex);
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
PluginLogger.info("Fetching done. {0} UUIDs have been retreived.", usersUUIDs.size());
|
PluginLogger.info("Fetching done. {0} UUIDs have been retrieved.", usersUUIDs.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the UUIDs that could not be retreived via Mojang's standard API
|
* Fetches the UUIDs that could not be retrieved via Mojang's standard API
|
||||||
* @return true if at least one UUID has been retreived, false otherwise
|
* @return true if at least one UUID has been retrieved, false otherwise
|
||||||
*/
|
*/
|
||||||
private boolean fetchMissingUUIDs() throws IOException, InterruptedException
|
private boolean fetchMissingUUIDs() throws IOException, InterruptedException
|
||||||
{
|
{
|
||||||
|
@ -378,7 +380,7 @@ public class V3Migrator implements Runnable
|
||||||
}
|
}
|
||||||
catch(IOException ex)
|
catch(IOException ex)
|
||||||
{
|
{
|
||||||
PluginLogger.error("An error occured while fetching the UUIDs from Mojang");
|
PluginLogger.error("An error occurred while fetching the UUIDs from Mojang");
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
catch(InterruptedException ex)
|
catch(InterruptedException ex)
|
||||||
|
|
|
@ -21,10 +21,8 @@ package fr.moribus.imageonmap.ui;
|
||||||
import fr.moribus.imageonmap.map.ImageMap;
|
import fr.moribus.imageonmap.map.ImageMap;
|
||||||
import fr.moribus.imageonmap.map.PosterMap;
|
import fr.moribus.imageonmap.map.PosterMap;
|
||||||
import fr.moribus.imageonmap.map.SingleMap;
|
import fr.moribus.imageonmap.map.SingleMap;
|
||||||
import java.util.ArrayDeque;
|
import fr.zcraft.zlib.components.gui.GuiUtils;
|
||||||
import java.util.HashMap;
|
import org.bukkit.ChatColor;
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.UUID;
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
@ -32,6 +30,11 @@ import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class MapItemManager implements Listener
|
public class MapItemManager implements Listener
|
||||||
{
|
{
|
||||||
static private HashMap<UUID, Queue<ItemStack>> mapItemCache;
|
static private HashMap<UUID, Queue<ItemStack>> mapItemCache;
|
||||||
|
@ -56,7 +59,7 @@ public class MapItemManager implements Listener
|
||||||
|
|
||||||
static public boolean give(Player player, SingleMap map)
|
static public boolean give(Player player, SingleMap map)
|
||||||
{
|
{
|
||||||
return give(player, createMapItem(map.getMapsIDs()[0], map.getName()));
|
return give(player, createMapItem(map));
|
||||||
}
|
}
|
||||||
|
|
||||||
static public boolean give(Player player, PosterMap map)
|
static public boolean give(Player player, PosterMap map)
|
||||||
|
@ -69,7 +72,7 @@ public class MapItemManager implements Listener
|
||||||
{
|
{
|
||||||
if(map.hasColumnData())
|
if(map.hasColumnData())
|
||||||
{
|
{
|
||||||
mapName = map.getName() +
|
mapName = map.getName() +
|
||||||
" (row " + map.getRowAt(i) +
|
" (row " + map.getRowAt(i) +
|
||||||
", column " + map.getColumnAt(i) + ")";
|
", column " + map.getColumnAt(i) + ")";
|
||||||
}
|
}
|
||||||
|
@ -112,16 +115,70 @@ public class MapItemManager implements Listener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public ItemStack createMapItem(SingleMap map)
|
||||||
|
{
|
||||||
|
return createMapItem(map.getMapsIDs()[0], map.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
static public ItemStack createMapItem(PosterMap map, int x, int y)
|
||||||
|
{
|
||||||
|
String mapName;
|
||||||
|
if(map.hasColumnData())
|
||||||
|
{
|
||||||
|
mapName = map.getName() +
|
||||||
|
" (row " + x +
|
||||||
|
", column " + y + ")";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mapName = map.getName();
|
||||||
|
}
|
||||||
|
return createMapItem(map.getMapIdAt(x, y), mapName);
|
||||||
|
}
|
||||||
|
|
||||||
static public ItemStack createMapItem(short mapID, String text)
|
static public ItemStack createMapItem(short mapID, String text)
|
||||||
{
|
{
|
||||||
ItemStack itemMap = new ItemStack(Material.MAP, 1, mapID);
|
ItemStack itemMap = new ItemStack(Material.MAP, 1, mapID);
|
||||||
|
|
||||||
ItemMeta meta = itemMap.getItemMeta();
|
ItemMeta meta = itemMap.getItemMeta();
|
||||||
meta.setDisplayName(text);
|
meta.setDisplayName(ChatColor.RESET + text);
|
||||||
|
GuiUtils.hideItemAttributes(meta);
|
||||||
itemMap.setItemMeta(meta);
|
itemMap.setItemMeta(meta);
|
||||||
|
|
||||||
return itemMap;
|
return itemMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the item to place to display the (col;row) part of the given poster.
|
||||||
|
*
|
||||||
|
* @param col The column to display. Starts at 0.
|
||||||
|
* @param row The row to display. Starts at 0.
|
||||||
|
*
|
||||||
|
* @return The map.
|
||||||
|
*
|
||||||
|
* @throws ArrayIndexOutOfBoundsException If col;row is not inside the map.
|
||||||
|
*/
|
||||||
|
static public ItemStack createSubMapItem(ImageMap map, int col, int row)
|
||||||
|
{
|
||||||
|
if(map instanceof PosterMap && ((PosterMap) map).hasColumnData())
|
||||||
|
{
|
||||||
|
return MapItemManager.createMapItem(
|
||||||
|
((PosterMap) map).getMapIdAt(row, col),
|
||||||
|
map.getName() +
|
||||||
|
" (row " + (row + 1) +
|
||||||
|
", column " + (col + 1) + ")"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(row != 0 || col != 0)
|
||||||
|
{
|
||||||
|
throw new ArrayIndexOutOfBoundsException(); // Coherence
|
||||||
|
}
|
||||||
|
|
||||||
|
return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static public int getCacheSize(Player player)
|
static public int getCacheSize(Player player)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,132 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
|
@ -1,152 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,199 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
/*
|
|
||||||
* 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,6 +8,9 @@ commands:
|
||||||
usage: /<command> [URL]
|
usage: /<command> [URL]
|
||||||
maptool:
|
maptool:
|
||||||
description: manage maps
|
description: manage maps
|
||||||
|
maps:
|
||||||
|
description: manage maps through a GUI
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
imageonmap.userender:
|
imageonmap.userender:
|
||||||
description: Allows you to use /tomap
|
description: Allows you to use /tomap
|
||||||
|
|
Loading…
Reference in New Issue
Block a user