mirror of
https://github.com/zDevelopers/ImageOnMap.git
synced 2025-01-21 06:51:20 +01:00
Migration is now fully functional !
* NEW: Refactored PluginLogger for multi-thread usage and message formatting. * NEW: Posters and maps that could not be migrated are now saved back to their original files. * NEW: Moved the maptool-migration command to the /maptool migrate subcommand. * NEW: PosterMap can now be used without having row/column count information. * NEW: Added a detailed help message for the migration command. * BUG: Fixed UUIDFetcher's HTTP GET request sending. * BUG: Fixed Name->UUID time-specific matching. * OPT: Removed the CommandPermission structure, it is actually useless. * OPT: Renamed Migrator to MigratorExecutor.
This commit is contained in:
parent
6725c15002
commit
2a49d94d1e
@ -23,7 +23,7 @@ import fr.moribus.imageonmap.image.ImageIOExecutor;
|
||||
import fr.moribus.imageonmap.image.ImageRendererExecutor;
|
||||
import fr.moribus.imageonmap.image.MapInitEvent;
|
||||
import fr.moribus.imageonmap.map.MapManager;
|
||||
import fr.moribus.imageonmap.migration.Migrator;
|
||||
import fr.moribus.imageonmap.migration.MigratorExecutor;
|
||||
import fr.moribus.imageonmap.migration.V3Migrator;
|
||||
import fr.moribus.imageonmap.ui.MapItemManager;
|
||||
import java.io.File;
|
||||
@ -61,6 +61,7 @@ public final class ImageOnMap extends JavaPlugin
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
PluginLogger.init(this);
|
||||
// Creating the images and maps directories if necessary
|
||||
try
|
||||
{
|
||||
@ -69,7 +70,7 @@ public final class ImageOnMap extends JavaPlugin
|
||||
}
|
||||
catch(IOException ex)
|
||||
{
|
||||
PluginLogger.LogError("FATAL : " + ex.getMessage(), null);
|
||||
PluginLogger.error("FATAL : " + ex.getMessage(), null);
|
||||
this.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
@ -83,7 +84,6 @@ public final class ImageOnMap extends JavaPlugin
|
||||
Commands.init(this);
|
||||
MapInitEvent.init(this);
|
||||
MapItemManager.init();
|
||||
Migrator.startWorker();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -93,7 +93,8 @@ public final class ImageOnMap extends JavaPlugin
|
||||
ImageRendererExecutor.stop();
|
||||
MapManager.exit();
|
||||
MapItemManager.exit();
|
||||
Migrator.stopWorker();
|
||||
MigratorExecutor.waitForMigration();
|
||||
PluginLogger.exit();
|
||||
}
|
||||
|
||||
private File checkPluginDirectory(File primaryFile, File... alternateFiles) throws IOException
|
||||
|
@ -65,7 +65,7 @@ public class MetricsLite
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
PluginLogger.LogError("Failed to start MetricsLite", e);
|
||||
PluginLogger.error("Failed to start MetricsLite", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ public class MetricsLite
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
PluginLogger.LogWarning("[Metrics] ", e);
|
||||
PluginLogger.warning("[Metrics] ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -219,7 +219,7 @@ public class MetricsLite
|
||||
configuration.load(getConfigFile());
|
||||
} catch (IOException | InvalidConfigurationException ex) {
|
||||
if (debug) {
|
||||
PluginLogger.LogInfo("[Metrics] " + ex.getMessage());
|
||||
PluginLogger.info("[Metrics] " + ex.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -408,7 +408,7 @@ public class MetricsLite
|
||||
gzos = new GZIPOutputStream(baos);
|
||||
gzos.write(input.getBytes("UTF-8"));
|
||||
} catch (IOException e) {
|
||||
PluginLogger.LogError("MetricsLite GZIP error : ", e);
|
||||
PluginLogger.error("MetricsLite GZIP error : ", e);
|
||||
} finally {
|
||||
if (gzos != null) try {
|
||||
gzos.close();
|
||||
|
@ -18,33 +18,112 @@
|
||||
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
abstract public class PluginLogger
|
||||
{
|
||||
static private Plugin plugin;
|
||||
static private Thread mainThread;
|
||||
static private HashMap<Thread, PluginThreadLogger> loggers;
|
||||
|
||||
static public void init(Plugin plugin)
|
||||
{
|
||||
PluginLogger.plugin = plugin;
|
||||
mainThread = Thread.currentThread();
|
||||
loggers = new HashMap<>();
|
||||
}
|
||||
|
||||
static public void exit()
|
||||
{
|
||||
plugin = null;
|
||||
mainThread = null;
|
||||
loggers = null;
|
||||
}
|
||||
|
||||
static public void log(Level level, String message, Throwable ex)
|
||||
{
|
||||
getLogger().log(level, message, ex);
|
||||
}
|
||||
|
||||
static public void log(Level level, String message, Object...args)
|
||||
{
|
||||
getLogger().log(level, message, args);
|
||||
}
|
||||
|
||||
static public void log(Level level, String message, Throwable ex, Object... args)
|
||||
{
|
||||
log(level, message + " : " + ex.getMessage(), args);
|
||||
}
|
||||
|
||||
static public void info(String message, Object...args)
|
||||
{
|
||||
log(Level.INFO, message, args);
|
||||
}
|
||||
|
||||
static public void warning(String message, Object... args)
|
||||
{
|
||||
log(Level.WARNING, message, args);
|
||||
}
|
||||
|
||||
static public void warning(String message, Throwable ex)
|
||||
{
|
||||
warning(message + " : " + ex.getMessage());
|
||||
}
|
||||
|
||||
static public void error(String message)
|
||||
{
|
||||
log(Level.SEVERE, message);
|
||||
}
|
||||
|
||||
static public void error(String message, Throwable ex)
|
||||
{
|
||||
log(Level.SEVERE, message, ex);
|
||||
}
|
||||
|
||||
static public void error(String message, Throwable ex, Object... args)
|
||||
{
|
||||
log(Level.SEVERE, message, ex, args);
|
||||
}
|
||||
|
||||
static private Logger getLogger()
|
||||
{
|
||||
return ImageOnMap.getPlugin().getLogger();
|
||||
Thread currentThread = Thread.currentThread();
|
||||
if(currentThread.equals(mainThread)) return plugin.getLogger();
|
||||
return getLogger(currentThread);
|
||||
}
|
||||
|
||||
static public void LogInfo(String message)
|
||||
static private Logger getLogger(Thread thread)
|
||||
{
|
||||
getLogger().log(Level.INFO, message);
|
||||
PluginThreadLogger logger = loggers.get(thread);
|
||||
if(logger == null)
|
||||
{
|
||||
logger = new PluginThreadLogger(thread);
|
||||
loggers.put(thread, logger);
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
|
||||
static public void LogWarning(String message)
|
||||
static private class PluginThreadLogger extends Logger
|
||||
{
|
||||
getLogger().log(Level.WARNING, message);
|
||||
}
|
||||
|
||||
static public void LogWarning(String message, Throwable ex)
|
||||
{
|
||||
getLogger().log(Level.WARNING, message, ex);
|
||||
}
|
||||
|
||||
static public void LogError(String message, Throwable ex)
|
||||
{
|
||||
getLogger().log(Level.SEVERE, message, ex);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,18 +65,12 @@ abstract public class Command
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasPermission(CommandSender sender)
|
||||
{
|
||||
if(!commandGroup.getPermission().hasPermission(sender)) return false;
|
||||
return canExecute(sender);
|
||||
}
|
||||
|
||||
public void execute(CommandSender sender, String[] args)
|
||||
{
|
||||
this.sender = sender; this.args = args;
|
||||
try
|
||||
{
|
||||
if(!hasPermission(sender))
|
||||
if(!canExecute(sender))
|
||||
throw new CommandException(this, Reason.SENDER_NOT_AUTHORIZED);
|
||||
run();
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public class CommandException extends Exception
|
||||
case SENDER_NOT_AUTHORIZED:
|
||||
return "You do not have the permission to use this command.";
|
||||
default:
|
||||
PluginLogger.LogWarning("Unknown CommandException caught", this);
|
||||
PluginLogger.warning("Unknown CommandException caught", this);
|
||||
return "An unknown error suddenly happened.";
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +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 org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public abstract class CommandPermission
|
||||
{
|
||||
abstract public boolean hasPermission(CommandSender sender);
|
||||
|
||||
static public final CommandPermission OP_ONLY = new CommandPermission()
|
||||
{
|
||||
@Override
|
||||
public boolean hasPermission(CommandSender sender)
|
||||
{
|
||||
return sender.isOp();
|
||||
}
|
||||
};
|
||||
|
||||
static public CommandPermission bukkitPermission(final String permission)
|
||||
{
|
||||
return new CommandPermission()
|
||||
{
|
||||
@Override
|
||||
public boolean hasPermission(CommandSender sender)
|
||||
{
|
||||
return sender.hasPermission(permission);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static public CommandPermission bukkitPermission(Plugin plugin, String permission)
|
||||
{
|
||||
final String permissionName = plugin.getName().toLowerCase()
|
||||
+ "." + permission.toLowerCase();
|
||||
return bukkitPermission(permissionName);
|
||||
}
|
||||
}
|
@ -18,10 +18,9 @@
|
||||
|
||||
package fr.moribus.imageonmap.commands;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.commands.maptool.MigrateCommand;
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import fr.moribus.imageonmap.commands.maptool.*;
|
||||
import fr.moribus.imageonmap.commands.migration.*;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
@ -36,10 +35,7 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Prokopyl<prokopylmc@gmail.com>
|
||||
*/
|
||||
|
||||
public enum Commands implements TabCompleter, CommandExecutor
|
||||
{
|
||||
MAPTOOL(new String[]{"maptool"},
|
||||
@ -48,22 +44,17 @@ public enum Commands implements TabCompleter, CommandExecutor
|
||||
GetCommand.class,
|
||||
DeleteConfirmCommand.class,
|
||||
DeleteNoConfirmCommand.class,
|
||||
GetRemainingCommand.class
|
||||
GetRemainingCommand.class,
|
||||
MigrateCommand.class
|
||||
),
|
||||
TOMAP(MAPTOOL, NewCommand.class, "tomap"),
|
||||
MAPTOOL_MIGRATION(new String[]{"maptool-migration"}, CommandPermission.OP_ONLY,
|
||||
StartCommand.class
|
||||
);
|
||||
TOMAP(MAPTOOL, NewCommand.class, "tomap");
|
||||
|
||||
|
||||
static private JavaPlugin plugin;
|
||||
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 final CommandPermission commandPermission;
|
||||
private String description = "";
|
||||
|
||||
private Commands(Commands shortcutCommandGroup, Class<? extends Command> commandClass, String ... names)
|
||||
@ -71,23 +62,16 @@ public enum Commands implements TabCompleter, CommandExecutor
|
||||
this.names = names;
|
||||
this.commandsClasses = new Class[]{commandClass};
|
||||
this.shortcutCommandGroup = shortcutCommandGroup;
|
||||
this.commandPermission = shortcutCommandGroup.getPermission();
|
||||
initCommands();
|
||||
}
|
||||
|
||||
private Commands(String[] names, CommandPermission permission, Class<? extends Command> ... commandsClasses)
|
||||
{
|
||||
this.names = names;
|
||||
this.commandsClasses = commandsClasses;
|
||||
this.shortcutCommandGroup = null;
|
||||
this.commandPermission = permission;
|
||||
initDescriptions();
|
||||
initCommands();
|
||||
}
|
||||
|
||||
private Commands(String[] names, Class<? extends Command> ... commandsClasses)
|
||||
{
|
||||
this(names, CommandPermission.bukkitPermission(ImageOnMap.getPlugin(), names[0]), commandsClasses);
|
||||
this.names = names;
|
||||
this.commandsClasses = commandsClasses;
|
||||
this.shortcutCommandGroup = null;
|
||||
initDescriptions();
|
||||
initCommands();
|
||||
}
|
||||
|
||||
private void initDescriptions()
|
||||
@ -96,7 +80,7 @@ public enum Commands implements TabCompleter, CommandExecutor
|
||||
InputStream stream = getClass().getClassLoader().getResourceAsStream(fileName);
|
||||
if(stream == null)
|
||||
{
|
||||
PluginLogger.LogWarning("Could not load description file for the " + getUsualName() + " command");
|
||||
PluginLogger.warning("Could not load description file for the " + getUsualName() + " command");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -154,7 +138,7 @@ public enum Commands implements TabCompleter, CommandExecutor
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLogger.LogWarning("Exception while initializing command", ex);
|
||||
PluginLogger.warning("Exception while initializing command", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,6 +325,5 @@ public enum Commands implements TabCompleter, CommandExecutor
|
||||
public String getDescription(String commandName) { return commandsDescriptions.get(commandName); }
|
||||
public boolean isShortcutCommand() { return shortcutCommandGroup != null; }
|
||||
public Commands getShortcutCommandGroup() { return shortcutCommandGroup; }
|
||||
public CommandPermission getPermission() { return commandPermission; }
|
||||
|
||||
}
|
||||
|
@ -73,25 +73,27 @@ public class HelpCommand extends Command
|
||||
if(!command.canExecute(sender))
|
||||
warning("You do not have the permission to use this command.");
|
||||
|
||||
sender.sendMessage("§l§6 ||== ImageOnMap help ==||\n" +
|
||||
"§l§6 |Usage : §r" + command.getUsageString());
|
||||
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(help);
|
||||
sender.sendMessage(message + "\n" + help);
|
||||
}
|
||||
}
|
||||
catch(IOException ex)
|
||||
{
|
||||
sender.sendMessage(message);
|
||||
warning("Could not read help for this command.");
|
||||
PluginLogger.LogWarning("Could not read help for the command : " + command.getName(), ex);
|
||||
PluginLogger.warning("Could not read help for the command : " + command.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class DeleteNoConfirmCommand extends Command
|
||||
}
|
||||
catch (MapManagerException ex)
|
||||
{
|
||||
PluginLogger.LogWarning("A non-existent map was requested to be deleted", ex);
|
||||
PluginLogger.warning("A non-existent map was requested to be deleted", ex);
|
||||
warning("This map does not exist.");
|
||||
}
|
||||
}
|
||||
|
@ -16,17 +16,16 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.commands.migration;
|
||||
package fr.moribus.imageonmap.commands.maptool;
|
||||
|
||||
import fr.moribus.imageonmap.commands.*;
|
||||
import fr.moribus.imageonmap.migration.Migrator;
|
||||
import fr.moribus.imageonmap.worker.WorkerCallback;
|
||||
import fr.moribus.imageonmap.migration.MigratorExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@CommandInfo(name = "start")
|
||||
public class StartCommand extends Command
|
||||
@CommandInfo(name = "migrate")
|
||||
public class MigrateCommand extends Command
|
||||
{
|
||||
public StartCommand(Commands commandGroup) {
|
||||
public MigrateCommand(Commands commandGroup) {
|
||||
super(commandGroup);
|
||||
}
|
||||
|
||||
@ -34,28 +33,20 @@ public class StartCommand extends Command
|
||||
protected void run() throws CommandException
|
||||
{
|
||||
final CommandSender cmdSender = sender;
|
||||
if(Migrator.isMigrationRunning())
|
||||
if(MigratorExecutor.isRunning())
|
||||
{
|
||||
error("A migration process is already running. Check console for details.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Migrator.runMigration(new WorkerCallback<Void>()
|
||||
{
|
||||
@Override
|
||||
public void finished(Void result)
|
||||
{
|
||||
info(cmdSender, "Migration finished. See console for details.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errored(Throwable exception)
|
||||
{
|
||||
warning(cmdSender, "Migration ended unexpectedly. See console for details.");
|
||||
}
|
||||
});
|
||||
|
||||
info("Migration started. See console for details.");
|
||||
MigratorExecutor.migrate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(CommandSender sender)
|
||||
{
|
||||
return sender.isOp();
|
||||
}
|
||||
}
|
@ -79,7 +79,7 @@ public class NewCommand extends Command
|
||||
public void errored(Throwable exception)
|
||||
{
|
||||
player.sendMessage("§cMap rendering failed : " + exception.getMessage());
|
||||
PluginLogger.LogWarning("Rendering from '" + player.getName() + "' failed", exception);
|
||||
PluginLogger.warning("Rendering from '{0}' failed", exception, player.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -170,7 +170,6 @@ public class ImageRendererExecutor extends Worker
|
||||
int x, y;
|
||||
x = (destinationW - finalW) / 2;
|
||||
y = (destinationH - finalH) / 2;
|
||||
PluginLogger.LogInfo(finalW + " " + finalH + " : " + x + " " + y);
|
||||
|
||||
BufferedImage newImage = new BufferedImage(destinationW, destinationH, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
|
@ -111,6 +111,11 @@ abstract public class MapManager
|
||||
getPlayerMapStore(map.getUserUUID()).addMap(map);
|
||||
}
|
||||
|
||||
static public void insertMap(ImageMap map)
|
||||
{
|
||||
getPlayerMapStore(map.getUserUUID()).insertMap(map);
|
||||
}
|
||||
|
||||
static public void deleteMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
getPlayerMapStore(map.getUserUUID()).deleteMap(map);
|
||||
|
@ -69,6 +69,11 @@ public class PlayerMapStore implements ConfigurationSerializable
|
||||
public synchronized void addMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
checkMapLimit(map);
|
||||
insertMap(map);
|
||||
}
|
||||
|
||||
public synchronized void insertMap(ImageMap map)
|
||||
{
|
||||
_addMap(map);
|
||||
notifyModification();
|
||||
}
|
||||
@ -201,15 +206,15 @@ public class PlayerMapStore implements ConfigurationSerializable
|
||||
}
|
||||
catch(InvalidConfigurationException ex)
|
||||
{
|
||||
PluginLogger.LogWarning("Could not load map data : " + ex.getMessage());
|
||||
PluginLogger.warning("Could not load map data : ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
try { checkMapLimit(0); }
|
||||
catch(MapManagerException ex)
|
||||
{
|
||||
PluginLogger.LogWarning("Map limit exceeded for player " + playerUUID.toString() +
|
||||
" (" + mapList.size() + " maps loaded).");
|
||||
PluginLogger.warning("Map limit exceeded for player '{0}' ({1} maps loaded)",
|
||||
playerUUID.toString(),mapList.size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,9 +251,8 @@ public class PlayerMapStore implements ConfigurationSerializable
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
PluginLogger.LogError("Could not save maps file for player " + playerUUID.toString(), ex);
|
||||
PluginLogger.error("Could not save maps file for player '{0}'", ex, playerUUID.toString());
|
||||
}
|
||||
PluginLogger.LogInfo("Saving maps file for " + playerUUID.toString());
|
||||
synchronized(this) {modified = false;}
|
||||
}
|
||||
}
|
||||
|
@ -33,16 +33,13 @@ public class PosterMap extends ImageMap
|
||||
{
|
||||
super(userUUID, Type.POSTER, id, name);
|
||||
this.mapsIDs = mapsIDs;
|
||||
this.columnCount = columnCount;
|
||||
this.rowCount = rowCount;
|
||||
this.columnCount = Math.max(columnCount, 0);
|
||||
this.rowCount = Math.max(rowCount, 0);
|
||||
}
|
||||
|
||||
public PosterMap(UUID userUUID, short[] mapsIDs, int columnCount, int rowCount)
|
||||
{
|
||||
super(userUUID, Type.POSTER, null, null);
|
||||
this.mapsIDs = mapsIDs;
|
||||
this.columnCount = columnCount;
|
||||
this.rowCount = rowCount;
|
||||
this(userUUID, mapsIDs, null, null, columnCount, rowCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -89,11 +86,19 @@ public class PosterMap extends ImageMap
|
||||
|
||||
/* ====== Getters & Setters ====== */
|
||||
|
||||
/**
|
||||
* Returns the amount of columns in the poster map
|
||||
* @return The number of columns, or 0 if this data is missing
|
||||
*/
|
||||
public int getColumnCount()
|
||||
{
|
||||
return columnCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of rows in the poster map
|
||||
* @return The number of rows, or 0 if this data is missing
|
||||
*/
|
||||
public int getRowCount()
|
||||
{
|
||||
return rowCount;
|
||||
@ -101,13 +106,20 @@ public class PosterMap extends ImageMap
|
||||
|
||||
public int getColumnAt(int i)
|
||||
{
|
||||
if(columnCount == 0) return 0;
|
||||
return (i % columnCount) + 1;
|
||||
}
|
||||
|
||||
public int getRowAt(int i)
|
||||
{
|
||||
if(columnCount == 0) return 0;
|
||||
return (i / columnCount) + 1;
|
||||
}
|
||||
|
||||
public boolean hasColumnData()
|
||||
{
|
||||
return rowCount != 0 && columnCount != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMapCount()
|
||||
|
@ -26,10 +26,15 @@ public class SingleMap extends ImageMap
|
||||
{
|
||||
protected final short mapID;
|
||||
|
||||
public SingleMap(UUID ownerUUID, short mapID, String id, String name)
|
||||
{
|
||||
super(ownerUUID, Type.SINGLE, id, name);
|
||||
this.mapID = mapID;
|
||||
}
|
||||
|
||||
public SingleMap(UUID ownerUUID, short mapID)
|
||||
{
|
||||
super(ownerUUID, Type.SINGLE);
|
||||
this.mapID = mapID;
|
||||
this(ownerUUID, mapID, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,74 +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 fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.worker.Worker;
|
||||
import fr.moribus.imageonmap.worker.WorkerCallback;
|
||||
import fr.moribus.imageonmap.worker.WorkerRunnable;
|
||||
|
||||
public class Migrator extends Worker
|
||||
{
|
||||
static private Migrator instance;
|
||||
static private V3Migrator migrator;
|
||||
|
||||
static public void startWorker()
|
||||
{
|
||||
if(instance != null) stopWorker();
|
||||
instance = new Migrator();
|
||||
instance.init();
|
||||
}
|
||||
|
||||
static public void stopWorker()
|
||||
{
|
||||
instance.exit();
|
||||
instance = null;
|
||||
}
|
||||
|
||||
private Migrator()
|
||||
{
|
||||
super("Migration");
|
||||
}
|
||||
|
||||
static public boolean isMigrationStarted()
|
||||
{
|
||||
return migrator != null;
|
||||
}
|
||||
|
||||
static public boolean isMigrationRunning()
|
||||
{
|
||||
return migrator != null && migrator.isRunning();
|
||||
}
|
||||
|
||||
static public boolean runMigration(WorkerCallback<Void> callback)
|
||||
{
|
||||
if(isMigrationRunning()) return false;
|
||||
if(!isMigrationStarted()) migrator = new V3Migrator(ImageOnMap.getPlugin());
|
||||
instance.submitQuery(new WorkerRunnable<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run() throws Throwable
|
||||
{
|
||||
migrator.run();
|
||||
return null;
|
||||
}
|
||||
}, callback);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Moribus
|
||||
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package fr.moribus.imageonmap.migration;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
|
||||
public class MigratorExecutor
|
||||
{
|
||||
static private Thread migratorThread;
|
||||
|
||||
static public void migrate()
|
||||
{
|
||||
if(isRunning())
|
||||
{
|
||||
PluginLogger.error("Migration is already running.");
|
||||
return;
|
||||
}
|
||||
migratorThread = new Thread(new V3Migrator(ImageOnMap.getPlugin()), "ImageOnMap-Migration");
|
||||
migratorThread.start();
|
||||
}
|
||||
|
||||
static public boolean isRunning()
|
||||
{
|
||||
return migratorThread != null && migratorThread.isAlive();
|
||||
}
|
||||
|
||||
static public void waitForMigration()
|
||||
{
|
||||
if(isRunning())
|
||||
{
|
||||
PluginLogger.info("Waiting for migration to finish ...");
|
||||
try
|
||||
{
|
||||
migratorThread.join();
|
||||
}
|
||||
catch(InterruptedException ex)
|
||||
{
|
||||
PluginLogger.error("Migration thread has been interrupted while wating to finish. It may not have ended correctly.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -18,7 +18,12 @@
|
||||
|
||||
package fr.moribus.imageonmap.migration;
|
||||
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.SingleMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
|
||||
class OldSavedMap
|
||||
@ -54,6 +59,20 @@ class OldSavedMap
|
||||
userName = data.get(2);
|
||||
}
|
||||
|
||||
public ImageMap toImageMap(UUID userUUID)
|
||||
{
|
||||
return new SingleMap(userUUID, mapId, null, mapName);
|
||||
}
|
||||
|
||||
public void serialize(Configuration configuration)
|
||||
{
|
||||
ArrayList<String> data = new ArrayList<String>();
|
||||
data.add(Short.toString(mapId));
|
||||
data.add(mapName);
|
||||
data.add(userName);
|
||||
configuration.set(mapName, data);
|
||||
}
|
||||
|
||||
public short getMapId() {return mapId;}
|
||||
public String getUserName() {return userName;}
|
||||
}
|
||||
|
@ -18,16 +18,23 @@
|
||||
|
||||
package fr.moribus.imageonmap.migration;
|
||||
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.PosterMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
|
||||
class OldSavedPoster
|
||||
{
|
||||
private String userName;
|
||||
private short[] mapsIds;
|
||||
private final String userName;
|
||||
private final String posterName;
|
||||
private final short[] mapsIds;
|
||||
|
||||
public OldSavedPoster(Object rawData) throws InvalidConfigurationException
|
||||
public OldSavedPoster(Object rawData, String key) throws InvalidConfigurationException
|
||||
{
|
||||
posterName = key;
|
||||
List<String> data;
|
||||
try
|
||||
{
|
||||
@ -68,5 +75,24 @@ class OldSavedPoster
|
||||
return false;
|
||||
}
|
||||
|
||||
public ImageMap toImageMap(UUID userUUID)
|
||||
{
|
||||
return new PosterMap(userUUID, mapsIds, null, "poster", 0, 0);
|
||||
}
|
||||
|
||||
public void serialize(Configuration configuration)
|
||||
{
|
||||
ArrayList<String> data = new ArrayList<String>();
|
||||
data.add(userName);
|
||||
|
||||
for(short mapId : mapsIds)
|
||||
{
|
||||
data.add(Short.toString(mapId));
|
||||
}
|
||||
|
||||
configuration.set(posterName, data);
|
||||
|
||||
}
|
||||
|
||||
public String getUserName() {return userName;}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ abstract public class UUIDFetcher
|
||||
for(String name : remainingNames)
|
||||
{
|
||||
user = fetchOriginalUUID(name);
|
||||
uuids.put(user.name, user.uuid);
|
||||
uuids.put(name, user.uuid);
|
||||
Thread.sleep(timeBetweenRequests);
|
||||
}
|
||||
|
||||
@ -151,7 +151,6 @@ abstract public class UUIDFetcher
|
||||
static private User fetchOriginalUUID(String name) throws IOException
|
||||
{
|
||||
HttpURLConnection connection = getGETConnection(TIMED_PROFILE_URL + name + "?at=" + NAME_CHANGE_TIMESTAMP);
|
||||
sendRequest(connection);
|
||||
|
||||
JSONObject object;
|
||||
|
||||
@ -187,16 +186,11 @@ abstract public class UUIDFetcher
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setUseCaches(false);
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
static private void sendRequest(HttpURLConnection connection) throws IOException
|
||||
{
|
||||
OutputStream stream = connection.getOutputStream();
|
||||
stream.flush();
|
||||
stream.close();
|
||||
}
|
||||
|
||||
private static void writeBody(HttpURLConnection connection, List<String> names) throws IOException
|
||||
{
|
||||
OutputStream stream = connection.getOutputStream();
|
||||
@ -208,9 +202,9 @@ abstract public class UUIDFetcher
|
||||
|
||||
private static Object readResponse(HttpURLConnection connection) throws IOException, ParseException
|
||||
{
|
||||
return new JSONParser().parse(new InputStreamReader(connection.getInputStream()));
|
||||
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) + "-" +
|
||||
|
@ -19,6 +19,8 @@
|
||||
package fr.moribus.imageonmap.migration;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import fr.moribus.imageonmap.map.MapManager;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@ -28,6 +30,7 @@ import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@ -42,7 +45,7 @@ import org.bukkit.plugin.Plugin;
|
||||
/**
|
||||
* This class represents and executes the ImageOnMap v3.x migration process
|
||||
*/
|
||||
public class V3Migrator
|
||||
public class V3Migrator implements Runnable
|
||||
{
|
||||
/**
|
||||
* The name of the former images directory
|
||||
@ -111,12 +114,12 @@ public class V3Migrator
|
||||
/**
|
||||
* The list of all the posters to migrate
|
||||
*/
|
||||
private final ArrayList<OldSavedPoster> postersToMigrate;
|
||||
private final ArrayDeque<OldSavedPoster> postersToMigrate;
|
||||
|
||||
/**
|
||||
* The list of all the single maps to migrate
|
||||
*/
|
||||
private final ArrayList<OldSavedMap> mapsToMigrate;
|
||||
private final ArrayDeque<OldSavedMap> mapsToMigrate;
|
||||
|
||||
/**
|
||||
* The set of all the user names to retreive the UUID from Mojang
|
||||
@ -145,8 +148,8 @@ public class V3Migrator
|
||||
backupsPrev3Directory = new File(dataFolder, BACKUPS_PREV3_DIRECTORY_NAME);
|
||||
backupsPostv3Directory = new File(dataFolder, BACKUPS_POSTV3_DIRECTORY_NAME);
|
||||
|
||||
postersToMigrate = new ArrayList<>();
|
||||
mapsToMigrate = new ArrayList<>();
|
||||
postersToMigrate = new ArrayDeque<>();
|
||||
mapsToMigrate = new ArrayDeque<>();
|
||||
userNamesToFetch = new HashSet<>();
|
||||
}
|
||||
|
||||
@ -166,21 +169,22 @@ public class V3Migrator
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
logError("Error while preparing migration", ex);
|
||||
logError("Aborting migration. No change has been made.");
|
||||
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
|
||||
PluginLogger.error("Error while preparing migration");
|
||||
PluginLogger.error("Aborting migration. No change has been made.", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
mergeMapData();
|
||||
saveChanges();
|
||||
cleanup();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
logError("Error while migrating", ex);
|
||||
logError("Aborting migration. Some changes may already have been made.");
|
||||
logError("Before trying to migrate again, you must recover player files from the backups, and then move the backups away from the plugin directory to avoid overwriting them.");
|
||||
PluginLogger.error("Error while migrating", ex);
|
||||
PluginLogger.error("Aborting migration. Some changes may already have been made.");
|
||||
PluginLogger.error("Before trying to migrate again, you must recover player files from the backups, and then move the backups away from the plugin directory to avoid overwriting them.");
|
||||
|
||||
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
@ -194,22 +198,22 @@ public class V3Migrator
|
||||
*/
|
||||
private boolean spotFilesToMigrate()
|
||||
{
|
||||
logInfo("Looking for configuration files to migrate ...");
|
||||
PluginLogger.info("Looking for configuration files to migrate ...");
|
||||
|
||||
if(!oldPostersFile.exists()) oldPostersFile = null;
|
||||
else logInfo("Detected former posters file " + OLD_POSTERS_FILE_NAME);
|
||||
else PluginLogger.info("Detected former posters file {0}", OLD_POSTERS_FILE_NAME);
|
||||
|
||||
if(!oldMapsFile.exists()) oldMapsFile = null;
|
||||
else logInfo("Detected former maps file " + OLD_POSTERS_FILE_NAME);
|
||||
else PluginLogger.info("Detected former maps file {0}", OLD_MAPS_FILE_NAME);
|
||||
|
||||
if(oldPostersFile == null && oldMapsFile == null)
|
||||
{
|
||||
logInfo("There is nothing to migrate. Stopping.");
|
||||
PluginLogger.info("There is nothing to migrate. Stopping.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
logInfo("Done.");
|
||||
PluginLogger.info("Done.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -223,9 +227,9 @@ public class V3Migrator
|
||||
if((backupsPrev3Directory.exists() && backupsPrev3Directory.list().length == 0)
|
||||
|| (backupsPostv3Directory.exists() && backupsPostv3Directory.list().length == 0))
|
||||
{
|
||||
logError("Backup directories already exists.");
|
||||
logError("This means that a migration has already been done, or may not have ended well.");
|
||||
logError("To start a new migration, you must move away the backup directories so they are not overwritten.");
|
||||
PluginLogger.error("Backup directories already exists.");
|
||||
PluginLogger.error("This means that a migration has already been done, or may not have ended well.");
|
||||
PluginLogger.error("To start a new migration, you must move away the backup directories so they are not overwritten.");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -238,18 +242,18 @@ public class V3Migrator
|
||||
*/
|
||||
private void backupMapData() throws IOException
|
||||
{
|
||||
logInfo("Backing up map data before migrating ...");
|
||||
PluginLogger.info("Backing up map data before migrating ...");
|
||||
|
||||
if(!backupsPrev3Directory.exists()) backupsPrev3Directory.mkdirs();
|
||||
if(!backupsPostv3Directory.exists()) backupsPostv3Directory.mkdirs();
|
||||
|
||||
if(oldMapsFile.exists())
|
||||
if(oldMapsFile != null && oldMapsFile.exists())
|
||||
{
|
||||
File oldMapsFileBackup = new File(backupsPrev3Directory, oldMapsFile.getName());
|
||||
verifiedBackupCopy(oldMapsFile, oldMapsFileBackup);
|
||||
}
|
||||
|
||||
if(oldPostersFile.exists())
|
||||
if(oldPostersFile != null && oldPostersFile.exists())
|
||||
{
|
||||
File oldPostersFileBackup = new File(backupsPrev3Directory, oldPostersFile.getName());
|
||||
verifiedBackupCopy(oldPostersFile, oldPostersFileBackup);
|
||||
@ -262,7 +266,7 @@ public class V3Migrator
|
||||
verifiedBackupCopy(mapFile, backupFile);
|
||||
}
|
||||
|
||||
logInfo("Backup complete.");
|
||||
PluginLogger.info("Backup complete.");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -287,37 +291,45 @@ public class V3Migrator
|
||||
*/
|
||||
private boolean loadOldFiles()
|
||||
{
|
||||
FileConfiguration oldPosters = YamlConfiguration.loadConfiguration(oldPostersFile);
|
||||
|
||||
OldSavedPoster oldPoster;
|
||||
for(String key : oldPosters.getKeys(false))
|
||||
if(oldPostersFile != null)
|
||||
{
|
||||
try
|
||||
FileConfiguration oldPosters = YamlConfiguration.loadConfiguration(oldPostersFile);
|
||||
|
||||
OldSavedPoster oldPoster;
|
||||
for(String key : oldPosters.getKeys(false))
|
||||
{
|
||||
oldPoster = new OldSavedPoster(oldPosters.get(key));
|
||||
userNamesToFetch.add(oldPoster.getUserName());
|
||||
postersToMigrate.add(oldPoster);
|
||||
}
|
||||
catch(InvalidConfigurationException ex)
|
||||
{
|
||||
logWarning("Could not read poster data for key " + key, ex);
|
||||
if("IdCount".equals(key)) continue;
|
||||
try
|
||||
{
|
||||
oldPoster = new OldSavedPoster(oldPosters.get(key), key);
|
||||
userNamesToFetch.add(oldPoster.getUserName());
|
||||
postersToMigrate.add(oldPoster);
|
||||
}
|
||||
catch(InvalidConfigurationException ex)
|
||||
{
|
||||
PluginLogger.warning("Could not read poster data for key '{0}'", ex, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileConfiguration oldMaps = YamlConfiguration.loadConfiguration(oldMapsFile);
|
||||
OldSavedMap oldMap;
|
||||
|
||||
for(String key : oldMaps.getKeys(false))
|
||||
if(oldMapsFile != null)
|
||||
{
|
||||
try
|
||||
FileConfiguration oldMaps = YamlConfiguration.loadConfiguration(oldMapsFile);
|
||||
OldSavedMap oldMap;
|
||||
|
||||
for(String key : oldMaps.getKeys(false))
|
||||
{
|
||||
oldMap = new OldSavedMap(oldMaps.get(key));
|
||||
|
||||
if(!posterContains(oldMap)) mapsToMigrate.add(oldMap);
|
||||
}
|
||||
catch(InvalidConfigurationException ex)
|
||||
{
|
||||
logWarning("Could not read poster data for key " + key, ex);
|
||||
try
|
||||
{
|
||||
if("IdCount".equals(key)) continue;
|
||||
oldMap = new OldSavedMap(oldMaps.get(key));
|
||||
|
||||
if(!posterContains(oldMap)) mapsToMigrate.add(oldMap);
|
||||
}
|
||||
catch(InvalidConfigurationException ex)
|
||||
{
|
||||
PluginLogger.warning("Could not read poster data for key '{0}'", ex, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,22 +343,22 @@ public class V3Migrator
|
||||
*/
|
||||
private void fetchUUIDs() throws IOException, InterruptedException
|
||||
{
|
||||
logInfo("Fetching UUIDs from Mojang ...");
|
||||
PluginLogger.info("Fetching UUIDs from Mojang ...");
|
||||
try
|
||||
{
|
||||
usersUUIDs = UUIDFetcher.fetch(new ArrayList<String>(userNamesToFetch));
|
||||
}
|
||||
catch(IOException ex)
|
||||
{
|
||||
logError("An error occured while fetching the UUIDs from Mojang", ex);
|
||||
PluginLogger.error("An error occured while fetching the UUIDs from Mojang", ex);
|
||||
throw ex;
|
||||
}
|
||||
catch(InterruptedException ex)
|
||||
{
|
||||
logError("The migration worker has been interrupted", ex);
|
||||
PluginLogger.error("The migration worker has been interrupted", ex);
|
||||
throw ex;
|
||||
}
|
||||
logInfo("Fetching done. " + usersUUIDs.size() + " UUIDs have been retreived.");
|
||||
PluginLogger.info("Fetching done. {0} UUIDs have been retreived.", usersUUIDs.size());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -357,8 +369,8 @@ public class V3Migrator
|
||||
{
|
||||
if(usersUUIDs.size() == userNamesToFetch.size()) return true;
|
||||
int remainingUsersCount = userNamesToFetch.size() - usersUUIDs.size();
|
||||
logInfo("Mojang did not find UUIDs for "+remainingUsersCount+" players.");
|
||||
logInfo("The Mojang servers limit requests rate at one per second, this may take some time...");
|
||||
PluginLogger.info("Mojang did not find UUIDs for {0} players at the current time.", remainingUsersCount);
|
||||
PluginLogger.info("The Mojang servers limit requests rate at one per second, this may take some time...");
|
||||
|
||||
try
|
||||
{
|
||||
@ -366,51 +378,143 @@ public class V3Migrator
|
||||
}
|
||||
catch(IOException ex)
|
||||
{
|
||||
logError("An error occured while fetching the UUIDs from Mojang", ex);
|
||||
PluginLogger.error("An error occured while fetching the UUIDs from Mojang");
|
||||
throw ex;
|
||||
}
|
||||
catch(InterruptedException ex)
|
||||
{
|
||||
logError("The migration worker has been interrupted", ex);
|
||||
PluginLogger.error("The migration worker has been interrupted");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if(usersUUIDs.size() != userNamesToFetch.size())
|
||||
{
|
||||
PluginLogger.warning("Mojang did not find player data for {0} players",
|
||||
userNamesToFetch.size() - usersUUIDs.size());
|
||||
PluginLogger.warning("The following players do not exist or do not have paid accounts :");
|
||||
|
||||
String missingUsersList = "";
|
||||
|
||||
for(String user : userNamesToFetch)
|
||||
{
|
||||
if(!usersUUIDs.containsKey(user)) missingUsersList += user + ",";
|
||||
}
|
||||
missingUsersList = missingUsersList.substring(0, missingUsersList.length());
|
||||
|
||||
PluginLogger.info(missingUsersList);
|
||||
}
|
||||
if(usersUUIDs.size() <= 0)
|
||||
{
|
||||
logInfo("Mojang could not find any of the registered players.");
|
||||
logInfo("There is nothing to migrate. Stopping.");
|
||||
PluginLogger.info("Mojang could not find any of the registered players.");
|
||||
PluginLogger.info("There is nothing to migrate. Stopping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void mergeMapData()
|
||||
{
|
||||
PluginLogger.info("Merging map data ...");
|
||||
|
||||
ArrayDeque<OldSavedMap> remainingMaps = new ArrayDeque<>();
|
||||
ArrayDeque<OldSavedPoster> remainingPosters = new ArrayDeque<>();
|
||||
|
||||
UUID playerUUID;
|
||||
OldSavedMap map;
|
||||
while(!mapsToMigrate.isEmpty())
|
||||
{
|
||||
map = mapsToMigrate.pop();
|
||||
playerUUID = usersUUIDs.get(map.getUserName());
|
||||
if(playerUUID == null)
|
||||
{
|
||||
remainingMaps.add(map);
|
||||
}
|
||||
else
|
||||
{
|
||||
MapManager.insertMap(map.toImageMap(playerUUID));
|
||||
}
|
||||
}
|
||||
mapsToMigrate.addAll(remainingMaps);
|
||||
|
||||
OldSavedPoster poster;
|
||||
while(!postersToMigrate.isEmpty())
|
||||
{
|
||||
poster = postersToMigrate.pop();
|
||||
playerUUID = usersUUIDs.get(poster.getUserName());
|
||||
if(playerUUID == null)
|
||||
{
|
||||
remainingPosters.add(poster);
|
||||
}
|
||||
else
|
||||
{
|
||||
MapManager.insertMap(poster.toImageMap(playerUUID));
|
||||
}
|
||||
}
|
||||
postersToMigrate.addAll(remainingPosters);
|
||||
}
|
||||
|
||||
private void saveChanges()
|
||||
{
|
||||
PluginLogger.info("Saving changes ...");
|
||||
MapManager.save();
|
||||
}
|
||||
|
||||
private void cleanup() throws IOException
|
||||
{
|
||||
PluginLogger.info("Cleaning up old data files ...");
|
||||
|
||||
//Cleaning maps file
|
||||
if(oldMapsFile != null)
|
||||
{
|
||||
if(mapsToMigrate.isEmpty())
|
||||
{
|
||||
PluginLogger.info("Deleting old map data file ...");
|
||||
oldMapsFile.delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
PluginLogger.info("{0} maps could not be migrated.", mapsToMigrate.size());
|
||||
YamlConfiguration mapConfig = new YamlConfiguration();
|
||||
mapConfig.set("IdCount", mapsToMigrate.size());
|
||||
|
||||
for(OldSavedMap map : mapsToMigrate)
|
||||
{
|
||||
map.serialize(mapConfig);
|
||||
}
|
||||
|
||||
mapConfig.save(oldMapsFile);
|
||||
}
|
||||
}
|
||||
|
||||
//Cleaning posters file
|
||||
if(oldPostersFile != null)
|
||||
{
|
||||
if(postersToMigrate.isEmpty())
|
||||
{
|
||||
PluginLogger.info("Deleting old poster data file ...");
|
||||
oldPostersFile.delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
PluginLogger.info("{0} posters could not be migrated.", postersToMigrate.size());
|
||||
YamlConfiguration posterConfig = new YamlConfiguration();
|
||||
posterConfig.set("IdCount", postersToMigrate.size());
|
||||
|
||||
for(OldSavedPoster poster : postersToMigrate)
|
||||
{
|
||||
poster.serialize(posterConfig);
|
||||
}
|
||||
|
||||
posterConfig.save(oldPostersFile);
|
||||
}
|
||||
}
|
||||
|
||||
PluginLogger.info("Data that has not been migrated will be kept in the old data files.");
|
||||
}
|
||||
|
||||
/* ****** Utils ***** */
|
||||
static public void logInfo(String message)
|
||||
{
|
||||
System.out.println("[ImageOnMap-Migration][INFO] " + message);
|
||||
}
|
||||
|
||||
static public void logWarning(String message)
|
||||
{
|
||||
System.err.println("[ImageOnMap-Migration][WARN] " + message);
|
||||
}
|
||||
|
||||
static public void logWarning(String message, Exception ex)
|
||||
{
|
||||
logWarning(message + " : " + ex.getMessage());
|
||||
}
|
||||
|
||||
static public void logError(String message)
|
||||
{
|
||||
System.err.println("[ImageOnMap-Migration][ERROR] " + message);
|
||||
}
|
||||
|
||||
static public void logError(String message, Exception ex)
|
||||
{
|
||||
logError(message + " : " + ex.getMessage());
|
||||
}
|
||||
|
||||
|
||||
public synchronized boolean isRunning()
|
||||
{
|
||||
return isRunning;
|
||||
@ -424,6 +528,7 @@ public class V3Migrator
|
||||
/**
|
||||
* Executes the full migration, and defines the running status of the migration
|
||||
*/
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
setRunning(true);
|
||||
|
@ -64,12 +64,20 @@ public class MapItemManager implements Listener
|
||||
short[] mapsIDs = map.getMapsIDs();
|
||||
boolean inventoryFull = false;
|
||||
|
||||
String mapName;
|
||||
for(int i = 0, c = mapsIDs.length; i < c; i++)
|
||||
{
|
||||
inventoryFull = give(player,
|
||||
createMapItem(mapsIDs[i], map.getName() +
|
||||
if(map.hasColumnData())
|
||||
{
|
||||
mapName = map.getName() +
|
||||
" (row " + map.getRowAt(i) +
|
||||
", column " + map.getColumnAt(i) + ")")) || inventoryFull;
|
||||
", column " + map.getColumnAt(i) + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
mapName = map.getName();
|
||||
}
|
||||
inventoryFull = give(player, createMapItem(mapsIDs[i], mapName)) || inventoryFull;
|
||||
}
|
||||
|
||||
return inventoryFull;
|
||||
|
@ -48,7 +48,7 @@ public abstract class Worker
|
||||
{
|
||||
if(thread != null && thread.isAlive())
|
||||
{
|
||||
PluginLogger.LogWarning("Restarting " + name + " thread.");
|
||||
PluginLogger.warning("Restarting '{0}' thread.", name);
|
||||
exit();
|
||||
}
|
||||
callbackManager.init();
|
||||
@ -118,7 +118,7 @@ public abstract class Worker
|
||||
|
||||
private Thread createThread()
|
||||
{
|
||||
return new Thread("ImageOnMap " + name)
|
||||
return new Thread("ImageOnMap-" + name)
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
|
36
src/main/resources/help/maptool/migrate.txt
Normal file
36
src/main/resources/help/maptool/migrate.txt
Normal file
@ -0,0 +1,36 @@
|
||||
Migrates the Map database to the new V3.x format, that uses UUIDs
|
||||
instead of player names to designate players (among other improvements).
|
||||
Migration runs in a separate thread, therefore its progress can only be
|
||||
watched from the server console.
|
||||
|
||||
The migration will run the following steps :
|
||||
- Checking if there are files to migrate. If not, the migration stops.
|
||||
- Checking if there are backups from a previous migration.
|
||||
If there are, the migration stops.
|
||||
- Loading the old map and poster data to memory.
|
||||
- Backing up old files and new files, to the backups_pre-v3 and
|
||||
backups_post-v3 subdirectories respectively.
|
||||
Backup's integrity are chacked using file size and SHA1 checksum.
|
||||
If integrity could not be proved, the migration stops.
|
||||
- Retreiving the UUIDs of the players from Mojang's servers.
|
||||
- Checking if some UUIDs could not be retreived.
|
||||
If there are, this means some of your players may have changed names
|
||||
before the migration started. The plugin will therefore try to retreive
|
||||
them specifying a time, back when usernames could not be changed.
|
||||
If some names could still not be matched to their UUIDs, then these are
|
||||
probably non-paid accounts.
|
||||
If no UUID has been retreived at all, the migration stops.
|
||||
§c--- From this step, changes to disk will be made, and you will have to use§r
|
||||
§c--- backups if you want to revert back from before the migration started.§r
|
||||
- Merging the old map data with the new one, if there is any
|
||||
(which can be the case if your player started to use newer
|
||||
versions of ImageOnMap before the migration started).
|
||||
- Saving all this merged map data to disk.
|
||||
- Removing the old map data from their former files, leaving only the data
|
||||
that could not be migrated due to usernames that could not be matched to
|
||||
their UUIDs.
|
||||
Original data is still present in the appropriate backup directory,
|
||||
just in case.
|
||||
|
||||
Note that this plugin will NEVER delete nor overwrite any backup directory.
|
||||
Moving or deleting these backups is left to the administrator's responsibility.
|
@ -8,9 +8,6 @@ commands:
|
||||
usage: /<command> [URL]
|
||||
maptool:
|
||||
description: manage maps
|
||||
maptool-migration:
|
||||
description: Manages the ImageOnMap migrations
|
||||
permission: op
|
||||
permissions:
|
||||
imageonmap.userender:
|
||||
description: Allows you to use /tomap
|
||||
|
Loading…
Reference in New Issue
Block a user