From 9681494c1c6353057f395e659f24fa34a2220245 Mon Sep 17 00:00:00 2001 From: BONNe1704 Date: Wed, 24 Jul 2019 13:43:29 +0300 Subject: [PATCH] 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. --- .../challenges/ChallengesManager.java | 87 ++----------------- .../challenges/database/object/Challenge.java | 16 +++- .../database/object/ChallengeLevel.java | 16 +++- .../database/object/ChallengesPlayerData.java | 14 +-- .../challenges/tasks/TryToComplete.java | 2 +- 5 files changed, 46 insertions(+), 89 deletions(-) diff --git a/src/main/java/world/bentobox/challenges/ChallengesManager.java b/src/main/java/world/bentobox/challenges/ChallengesManager.java index f8bca18..137b196 100644 --- a/src/main/java/world/bentobox/challenges/ChallengesManager.java +++ b/src/main/java/world/bentobox/challenges/ChallengesManager.java @@ -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 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 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 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 playerDataList = this.playersDatabase.loadObjects(); - - playerDataList.forEach(challengesPlayerData -> { - - Map fixedChallengeStatus = new HashMap<>(); - challengesPlayerData.getChallengeStatus().forEach((challenge, count) -> - fixedChallengeStatus.put(challenge.toLowerCase(), count)); - challengesPlayerData.setChallengeStatus(fixedChallengeStatus); - - Map fixedChallengeTimestamp = new HashMap<>(); - challengesPlayerData.getChallengesTimestamp().forEach((challenge, count) -> - fixedChallengeTimestamp.put(challenge.toLowerCase(), count)); - challengesPlayerData.setChallengesTimestamp(fixedChallengeTimestamp); - - Set 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)); } } \ No newline at end of file diff --git a/src/main/java/world/bentobox/challenges/database/object/Challenge.java b/src/main/java/world/bentobox/challenges/database/object/Challenge.java index 20ae133..f7d3a19 100644 --- a/src/main/java/world/bentobox/challenges/database/object/Challenge.java +++ b/src/main/java/world/bentobox/challenges/database/object/Challenge.java @@ -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); } } diff --git a/src/main/java/world/bentobox/challenges/database/object/ChallengeLevel.java b/src/main/java/world/bentobox/challenges/database/object/ChallengeLevel.java index 37fe1a9..7cbf761 100644 --- a/src/main/java/world/bentobox/challenges/database/object/ChallengeLevel.java +++ b/src/main/java/world/bentobox/challenges/database/object/ChallengeLevel.java @@ -425,6 +425,20 @@ public class ChallengeLevel implements DataObject, Comparable // --------------------------------------------------------------------- + /** + * 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 } else { - return uniqueId.equals(other.uniqueId); + return uniqueId.equalsIgnoreCase(other.uniqueId); } } diff --git a/src/main/java/world/bentobox/challenges/database/object/ChallengesPlayerData.java b/src/main/java/world/bentobox/challenges/database/object/ChallengesPlayerData.java index e8984c7..5ff36a8 100644 --- a/src/main/java/world/bentobox/challenges/database/object/ChallengesPlayerData.java +++ b/src/main/java/world/bentobox/challenges/database/object/ChallengesPlayerData.java @@ -53,20 +53,20 @@ public class ChallengesPlayerData implements DataObject * completed */ @Expose - private Map challengeStatus = new HashMap<>(); + private Map 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 challengesTimestamp = new HashMap<>(); + private Map challengesTimestamp = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); /** * Set of Strings that contains all challenge levels that are completed. */ @Expose - private Set levelsDone = new HashSet<>(); + private Set 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); } } } \ No newline at end of file diff --git a/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java b/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java index ee1aaed..8c630fa 100644 --- a/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java +++ b/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java @@ -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;