Fix issue with wrongly applied world name lowercasing.

It looks like, exist plugins that keep capital letters in world names. That mean, it is not correct to lowercasing any id's.
To fix it, now, instead of lowercasing, challenges should be case insensitive.
This commit is contained in:
BONNe1704 2019-07-24 13:43:29 +03:00
parent 2a30185922
commit 9681494c1c
5 changed files with 46 additions and 89 deletions

View File

@ -107,82 +107,11 @@ public class ChallengesManager
this.playersDatabase = new Database<>(addon, ChallengesPlayerData.class);
// Init all cache objects.
this.challengeCacheData = new HashMap<>();
this.levelCacheData = new HashMap<>();
this.playerCacheData = new HashMap<>();
this.challengeCacheData = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
this.levelCacheData = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
this.playerCacheData = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
this.load();
// TODO: Remove this code after some time, as this is just a protective code against invalid world names.
if (Bukkit.getBukkitVersion().startsWith("1.14"))
{
Set<Challenge> updatedChallenges = new HashSet<>();
this.challengeCacheData.values().forEach(challengeObject -> {
if (challengeObject.getUniqueId().matches(".*[A-Z]+.*"))
{
challengeObject.setUniqueId(challengeObject.getUniqueId().toLowerCase());
challengeObject.setLevel(challengeObject.getLevel().toLowerCase());
updatedChallenges.add(challengeObject);
this.addon.logWarning("Challenge addon fixed your data for Challenge " +
challengeObject.getUniqueId() +
". 1.14 does not allow to use capital letters in world names.");
}
});
Set<ChallengeLevel> updatedLevels = new HashSet<>();
this.levelCacheData.values().forEach(levelObject -> {
if (levelObject.getUniqueId().matches(".*[A-Z]+.*"))
{
levelObject.setUniqueId(levelObject.getUniqueId().toLowerCase());
levelObject.setWorld(levelObject.getWorld().toLowerCase());
Set<String> correctNames = levelObject.getChallenges().stream().
map(String::toLowerCase).
collect(Collectors.toSet());
levelObject.setChallenges(correctNames);
updatedLevels.add(levelObject);
this.addon.logWarning("Challenge addon fixed your data for Challenge Level " +
levelObject.getUniqueId() +
". 1.14 does not allow to use capital letters in world names.");
}
});
// As at least one challenge or level was corrupted we must update all player data objects!
if (!updatedLevels.isEmpty() || !updatedChallenges.isEmpty())
{
List<ChallengesPlayerData> playerDataList = this.playersDatabase.loadObjects();
playerDataList.forEach(challengesPlayerData -> {
Map<String, Integer> fixedChallengeStatus = new HashMap<>();
challengesPlayerData.getChallengeStatus().forEach((challenge, count) ->
fixedChallengeStatus.put(challenge.toLowerCase(), count));
challengesPlayerData.setChallengeStatus(fixedChallengeStatus);
Map<String, Long> fixedChallengeTimestamp = new HashMap<>();
challengesPlayerData.getChallengesTimestamp().forEach((challenge, count) ->
fixedChallengeTimestamp.put(challenge.toLowerCase(), count));
challengesPlayerData.setChallengesTimestamp(fixedChallengeTimestamp);
Set<String> fixedLevelsDone = new HashSet<>();
challengesPlayerData.getLevelsDone().forEach(level -> fixedLevelsDone.add(level.toLowerCase()));
challengesPlayerData.setLevelsDone(fixedLevelsDone);
this.playersDatabase.saveObject(challengesPlayerData);
this.addon.logWarning("Challenge addon fixed your data for PlayerData " +
challengesPlayerData.getUniqueId() +
". 1.14 does not allow to use capital letters in world names.");
});
}
}
}
@ -1263,7 +1192,7 @@ public class ChallengesManager
// TODO: Probably need to check also database.
return this.challengeCacheData.values().stream().
sorted(Comparator.comparing(Challenge::getOrder)).
filter(challenge -> challenge.getUniqueId().startsWith(gameWorld.getName())).
filter(challenge -> challenge.matchWorld(gameWorld.getName())).
map(Challenge::getUniqueId).
collect(Collectors.toList());
}
@ -1286,7 +1215,7 @@ public class ChallengesManager
// TODO: Probably need to check also database.
return this.challengeCacheData.values().stream().
filter(challenge -> challenge.getUniqueId().startsWith(gameWorld.getName())).
filter(challenge -> challenge.matchWorld(gameWorld.getName())).
sorted(Comparator.comparing(Challenge::getOrder)).
collect(Collectors.toList());
}
@ -1464,7 +1393,7 @@ public class ChallengesManager
// TODO: Probably need to check also database.
return this.levelCacheData.values().stream().
sorted(ChallengeLevel::compareTo).
filter(challenge -> challenge.getUniqueId().startsWith(world)).
filter(level -> level.matchWorld(world)).
collect(Collectors.toList());
}
@ -1685,8 +1614,8 @@ public class ChallengesManager
public boolean hasAnyChallengeData(@NonNull String worldName)
{
return this.challengeDatabase.loadObjects().stream().anyMatch(
challenge -> challenge.getUniqueId().startsWith(worldName)) ||
challenge -> challenge.matchWorld(worldName)) ||
this.levelDatabase.loadObjects().stream().anyMatch(
level -> level.getUniqueId().startsWith(worldName));
level -> level.matchWorld(worldName));
}
}

View File

@ -978,6 +978,20 @@ public class Challenge implements DataObject
// ---------------------------------------------------------------------
/**
* This method match if given worldName relates to current challenge. It is detected
* via challenge uniqueId, as it always must start with world name.
* This method is created to avoid issues with capital letters in world names in 1.14
* @param worldName Name that must be checked.
* @return {@code true} if current challenge relates to given world name, otherwise
* {@code false}.
*/
public boolean matchWorld(String worldName)
{
return this.uniqueId.regionMatches(true, 0, worldName, 0, worldName.length());
}
/**
* @see java.lang.Object#hashCode()
* @return int
@ -1018,7 +1032,7 @@ public class Challenge implements DataObject
}
else
{
return uniqueId.equals(other.uniqueId);
return uniqueId.equalsIgnoreCase(other.uniqueId);
}
}

View File

@ -425,6 +425,20 @@ public class ChallengeLevel implements DataObject, Comparable<ChallengeLevel>
// ---------------------------------------------------------------------
/**
* This method match if given worldName relates to current level. It is detected
* via level uniqueId, as it always must start with world name.
* This method is created to avoid issues with capital letters in world names in 1.14
* @param worldName Name that must be checked.
* @return {@code true} if current level relates to given world name, otherwise
* {@code false}.
*/
public boolean matchWorld(String worldName)
{
return this.uniqueId.regionMatches(true, 0, worldName, 0, worldName.length());
}
/**
* {@inheritDoc}
*/
@ -494,7 +508,7 @@ public class ChallengeLevel implements DataObject, Comparable<ChallengeLevel>
}
else
{
return uniqueId.equals(other.uniqueId);
return uniqueId.equalsIgnoreCase(other.uniqueId);
}
}

View File

@ -53,20 +53,20 @@ public class ChallengesPlayerData implements DataObject
* completed
*/
@Expose
private Map<String, Integer> challengeStatus = new HashMap<>();
private Map<String, Integer> challengeStatus = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
/**
* Map of challenges completion time where key is challenges unique id and value is
* timestamp when challenge was completed last time.
*/
@Expose
private Map<String, Long> challengesTimestamp = new HashMap<>();
private Map<String, Long> challengesTimestamp = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
/**
* Set of Strings that contains all challenge levels that are completed.
*/
@Expose
private Set<String> levelsDone = new HashSet<>();
private Set<String> levelsDone = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
/**
* Stores history about challenge completion.
@ -203,9 +203,9 @@ public class ChallengesPlayerData implements DataObject
*/
public void reset(@NonNull String worldName)
{
challengeStatus.keySet().removeIf(n -> n.startsWith(worldName));
challengesTimestamp.keySet().removeIf(n -> n.startsWith(worldName));
levelsDone.removeIf(n -> n.startsWith(worldName));
challengeStatus.keySet().removeIf(n -> n.regionMatches(true, 0, worldName, 0, worldName.length()));
challengesTimestamp.keySet().removeIf(n -> n.regionMatches(true, 0, worldName, 0, worldName.length()));
levelsDone.removeIf(n -> n.regionMatches(true, 0, worldName, 0, worldName.length()));
}
@ -345,7 +345,7 @@ public class ChallengesPlayerData implements DataObject
}
else
{
return uniqueId.equals(other.uniqueId);
return uniqueId.equalsIgnoreCase(other.uniqueId);
}
}
}

View File

@ -516,7 +516,7 @@ public class TryToComplete
result = EMPTY_RESULT;
}
else if (Util.getWorld(this.world) != Util.getWorld(this.user.getWorld()) ||
!this.challenge.getUniqueId().startsWith(Util.getWorld(this.world).getName()))
!this.challenge.matchWorld(Util.getWorld(this.world).getName()))
{
this.user.sendMessage("general.errors.wrong-world");
result = EMPTY_RESULT;