diff --git a/pom.xml b/pom.xml index 9407c79..2eca825 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,10 @@ fr.zcraft.quartzlib fr.zcraft.imageonmap.quartzlib + + org.bstats.bukkit.Metrics + fr.moribus.imageonmap + true @@ -72,6 +76,7 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + zdevelopers-quartzlib https://maven.zcraft.fr/QuartzLib @@ -93,12 +98,12 @@ fr.zcraft quartzlib - 0.0.2 + 0.0.1-SNAPSHOT org.bstats bstats-bukkit - 1.5 + 1.8 compile diff --git a/src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java b/src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java index d24160a..15a6395 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/IoMCommand.java @@ -49,11 +49,12 @@ import org.bukkit.entity.Player; public abstract class IoMCommand extends Command { - protected void sanityCheckAssert() { + protected boolean isSanityCheckFinished() { if (ImageOnMap.getPlugin().isMapIdCorrupted()) { warning(sender, I.t("You can't perform this command as long as the sanity check is ongoing.")); - return; + return false; } + return true; } protected ImageMap getMapFromArgs() throws CommandException { diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java index ebb715c..f555e38 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/DeleteCommand.java @@ -74,7 +74,10 @@ public class DeleteCommand extends IoMCommand { @Override protected void run() throws CommandException { - sanityCheckAssert(); + if (!isSanityCheckFinished()) { + return; + } + ArrayList arguments = getArgs(); final boolean confirm = hasFlag("confirm"); diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java index 02a6803..1f3bff2 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/ExploreCommand.java @@ -56,7 +56,9 @@ import org.bukkit.entity.Player; public class ExploreCommand extends IoMCommand { @Override protected void run() throws CommandException { - sanityCheckAssert(); + if (!isSanityCheckFinished()) { + return; + } ArrayList arguments = getArgs(); if (arguments.size() > 1) { throwInvalidArgument(I.t("Too many parameters!")); diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java index 19770bf..d150610 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetCommand.java @@ -53,7 +53,9 @@ import org.bukkit.entity.Player; public class GetCommand extends IoMCommand { @Override protected void run() throws CommandException { - sanityCheckAssert(); + if (!isSanityCheckFinished()) { + return; + } ArrayList arguments = getArgs(); if (arguments.size() > 2) { diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java index 679b95b..5bcf3eb 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/GetRemainingCommand.java @@ -49,7 +49,9 @@ import org.bukkit.entity.Player; public class GetRemainingCommand extends IoMCommand { @Override protected void run() throws CommandException { - sanityCheckAssert(); + if (!isSanityCheckFinished()) { + return; + } Player player = playerSender(); if (MapItemManager.getCacheSize(player) <= 0) { diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/GiveCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/GiveCommand.java index 70de977..1aaca34 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/GiveCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/GiveCommand.java @@ -58,7 +58,9 @@ public class GiveCommand extends IoMCommand { @Override protected void run() throws CommandException { - sanityCheckAssert(); + if (!isSanityCheckFinished()) { + return; + } if (args.length < 2) { throwInvalidArgument(I.t("You must give a valid player name and a map name.")); return; diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java index 09a7d6f..e03cf86 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/ListCommand.java @@ -58,7 +58,9 @@ import org.bukkit.entity.Player; public class ListCommand extends IoMCommand { @Override protected void run() throws CommandException { - sanityCheckAssert(); + if (!isSanityCheckFinished()) { + return; + } ArrayList arguments = getArgs(); if (arguments.size() > 1) { throwInvalidArgument(I.t("Too many parameters!")); diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java index 0130c84..b58eb1e 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/MigrateCommand.java @@ -48,7 +48,9 @@ import org.bukkit.command.CommandSender; public class MigrateCommand extends IoMCommand { @Override protected void run() throws CommandException { - sanityCheckAssert(); + if (!isSanityCheckFinished()) { + return; + } if (MigratorExecutor.isRunning()) { error(I.t("A migration process is already running. Check console for details.")); } else { diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java index c84f120..05e67b3 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/NewCommand.java @@ -74,7 +74,9 @@ public class NewCommand extends IoMCommand { @Override protected void run() throws CommandException { - sanityCheckAssert(); + if (!isSanityCheckFinished()) { + return; + } final Player player = playerSender(); ImageUtils.ScalingType scaling = ImageUtils.ScalingType.NONE; URL url; diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/RenameCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/RenameCommand.java index a1201a4..bf91e0d 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/RenameCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/RenameCommand.java @@ -34,7 +34,9 @@ public class RenameCommand extends IoMCommand { @Override protected void run() throws CommandException { - sanityCheckAssert(); + if (!isSanityCheckFinished()) { + return; + } ArrayList argList = getArgs(); if (argList.size() != 2) { diff --git a/src/main/java/fr/moribus/imageonmap/commands/maptool/UpdateCommand.java b/src/main/java/fr/moribus/imageonmap/commands/maptool/UpdateCommand.java index f05cadd..29c8913 100644 --- a/src/main/java/fr/moribus/imageonmap/commands/maptool/UpdateCommand.java +++ b/src/main/java/fr/moribus/imageonmap/commands/maptool/UpdateCommand.java @@ -61,7 +61,9 @@ import org.bukkit.entity.Player; public class UpdateCommand extends IoMCommand { @Override protected void run() throws CommandException { - sanityCheckAssert(); + if (!isSanityCheckFinished()) { + return; + } //TODO fix the issue where to many quick usage of offlineNameFetch will return null ArrayList arguments = getArgs(); String warningMsg; diff --git a/src/main/java/fr/moribus/imageonmap/integrity/MapIdChecker.java b/src/main/java/fr/moribus/imageonmap/integrity/MapIdChecker.java index 35e1a1c..9163922 100644 --- a/src/main/java/fr/moribus/imageonmap/integrity/MapIdChecker.java +++ b/src/main/java/fr/moribus/imageonmap/integrity/MapIdChecker.java @@ -1,28 +1,128 @@ package fr.moribus.imageonmap.integrity; +import fr.moribus.imageonmap.map.MapManager; +import fr.zcraft.quartzlib.components.nbt.NBTReadFile; import fr.zcraft.quartzlib.tools.PluginLogger; -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; +import fr.zcraft.quartzlib.tools.reflection.Reflection; +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; import org.bukkit.Bukkit; public class MapIdChecker { public static void check() { - int idcount; - int idmax; + int idCount = 0; + int idMax = 0; + String worldFolder = Bukkit.getWorlds().get(0).getWorldFolder().getAbsolutePath(); - try (BufferedReader reader = new BufferedReader(new FileReader(worldFolder + "/data/idcounts.dat"))) { - //test - PluginLogger.info(reader.readLine()); - } catch (IOException ex) { - ex.printStackTrace(); + + NBTReadFile nbtReader = new NBTReadFile(); + nbtReader.read(new File(worldFolder + "/data/idcounts.dat")); + + try { + Object compound = Reflection.call(nbtReader.tagCompound, "getCompound", "data"); + idCount = (int) Reflection.call(compound, "getInt", "map"); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); } - // MapManager.getNextAvailableMapID() + //I use the term set instead of map to avoid confusion when designing the java map + // (confusion with minecraft map and java map). + Map> idSet = MapManager.getMapIdSet(); + Map> conflict = new HashMap<>(); + Map> sane = new HashMap<>(); + for (Map.Entry> entry : idSet.entrySet()) { + //We are searching for the max used id + for (int id : entry.getValue()) { + if (idMax < id) { + idMax = id; + } + } - // if (idmax > idcount) { - //Not good - //} + //if the ids overlap on the same player that mean the newer id (the last in the set) is not corrupted, + // each older map that use this id need to be deleted + List idRead = new ArrayList<>(); + List idBad = new ArrayList<>(); + for (Integer id : entry.getValue()) { + + if (idRead.contains(id) || idBad.contains(id)) { + idRead.remove(id); + if (!idBad.contains(id)) { + idBad.add(id); + } + + } else { + idRead.add(id); + } + } + if (!idBad.isEmpty()) { + PluginLogger + .info("Corruption detected, there are some ids that are overlapping for the player's uuid " + + entry.getKey()); + } + + //repare + /*try { + + boolean nextMap = false; + for (Integer id : idBad) { + for (ImageMap map : MapManager.getPlayerMapStore(entry.getKey()).getMapList()) { + for (Integer mapId : map.getMapsIDs()) { + if (nextMap) { + continue; + } + if (mapId == id) { + map.getMapsIDs(); + MapManager.getPlayerMapStore(entry.getKey()).deleteMap(map); + nextMap = true; + } + } + nextMap = false; + } + } + } catch (MapManagerException e) { + e.printStackTrace(); + }*/ + + + + } + + //We search for a common usage of map id between different player. + //if an id is used between various player it's possible by looking at the id overlapping to find out the + // corrupted map, if not possible (same area) we throw a warning. This is not a critical + // error but this needs an operator to manually delete the corrupted map. + + //REPARATION + //if the map id used by IoM are used by + if (idMax > idCount) { + PluginLogger.info("Corruption detected, idmax > idcount need to create additional maps"); + /*nbtReader = new NBTReadFile(); + nbtReader.read(new File(worldFolder + "/data/idcounts.dat")); + + try { + Object compound = Reflection.call(nbtReader.tagCompound, "getCompound", "data"); + idCount = (int) Reflection.call(compound, "setInt", "map",idMax); + nbtReader.write(new File(worldFolder + "/data/idcounts.dat"), compound); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + }*/ + + //int[] mapids = MapManager.getNewMapsIds(idMax - idCount); + PluginLogger.info("number of map to create" + (idMax - idCount)); + /*StringBuilder s = new StringBuilder(); + for (int id : mapids) { + s = s.append(" " + id); + } + PluginLogger.info("ids " + s);*/ + + } + PluginLogger.info("id max" + idMax); + PluginLogger.info("id count" + idCount); } }