added checks and started repair in case of corruption on enable

This commit is contained in:
Vlammar 2021-04-05 16:49:29 +02:00
parent 2f1d51ed4b
commit 217d96c5b0
13 changed files with 155 additions and 28 deletions

View File

@ -30,6 +30,10 @@
<pattern>fr.zcraft.quartzlib</pattern>
<shadedPattern>fr.zcraft.imageonmap.quartzlib</shadedPattern>
</relocation>
<relocation>
<pattern>org.bstats.bukkit.Metrics</pattern>
<shadedPattern>fr.moribus.imageonmap</shadedPattern>
</relocation>
</relocations>
<minimizeJar>true</minimizeJar>
</configuration>
@ -72,6 +76,7 @@
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<!-- quartzLib -->
<repository>
<id>zdevelopers-quartzlib</id>
<url>https://maven.zcraft.fr/QuartzLib</url>
@ -93,12 +98,12 @@
<dependency>
<groupId>fr.zcraft</groupId>
<artifactId>quartzlib</artifactId>
<version>0.0.2</version>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>1.5</version>
<version>1.8</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@ -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 {

View File

@ -74,7 +74,10 @@ public class DeleteCommand extends IoMCommand {
@Override
protected void run() throws CommandException {
sanityCheckAssert();
if (!isSanityCheckFinished()) {
return;
}
ArrayList<String> arguments = getArgs();
final boolean confirm = hasFlag("confirm");

View File

@ -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<String> arguments = getArgs();
if (arguments.size() > 1) {
throwInvalidArgument(I.t("Too many parameters!"));

View File

@ -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<String> arguments = getArgs();
if (arguments.size() > 2) {

View File

@ -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) {

View File

@ -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;

View File

@ -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<String> arguments = getArgs();
if (arguments.size() > 1) {
throwInvalidArgument(I.t("Too many parameters!"));

View File

@ -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 {

View File

@ -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;

View File

@ -34,7 +34,9 @@ public class RenameCommand extends IoMCommand {
@Override
protected void run() throws CommandException {
sanityCheckAssert();
if (!isSanityCheckFinished()) {
return;
}
ArrayList<String> argList = getArgs();
if (argList.size() != 2) {

View File

@ -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<String> arguments = getArgs();
String warningMsg;

View File

@ -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<UUID, List<Integer>> idSet = MapManager.getMapIdSet();
Map<Integer, List<UUID>> conflict = new HashMap<>();
Map<Integer, List<UUID>> sane = new HashMap<>();
for (Map.Entry<UUID, List<Integer>> 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<Integer> idRead = new ArrayList<>();
List<Integer> 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);
}
}