diff --git a/src/main/java/world/bentobox/challenges/ChallengesManager.java b/src/main/java/world/bentobox/challenges/ChallengesManager.java index 137b196..721800c 100644 --- a/src/main/java/world/bentobox/challenges/ChallengesManager.java +++ b/src/main/java/world/bentobox/challenges/ChallengesManager.java @@ -13,6 +13,7 @@ import world.bentobox.bentobox.api.logs.LogEntry; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.Database; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.IslandWorldManager; import world.bentobox.bentobox.util.Util; import world.bentobox.challenges.database.object.Challenge; import world.bentobox.challenges.database.object.ChallengeLevel; @@ -74,6 +75,11 @@ public class ChallengesManager */ private Settings settings; + /** + * Island world manager allows to detect which world refferes to which gamemode addon. + */ + private IslandWorldManager islandWorldManager; + // --------------------------------------------------------------------- // Section: Constants @@ -98,6 +104,8 @@ public class ChallengesManager public ChallengesManager(ChallengesAddon addon) { this.addon = addon; + this.islandWorldManager = addon.getPlugin().getIWM(); + this.settings = addon.getChallengesSettings(); // Set up the configs @@ -366,7 +374,7 @@ public class ChallengesManager */ private boolean isValidLevel(@NonNull ChallengeLevel level) { - if (!this.addon.getPlugin().getIWM().inWorld(Bukkit.getWorld(level.getWorld()))) + if (!this.islandWorldManager.inWorld(Bukkit.getWorld(level.getWorld()))) { return false; } @@ -717,15 +725,15 @@ public class ChallengesManager /** - * Resets all the challenges for user in world + * Resets all the challenges for user in given GameMode. * * @param storageDataID - island owner's UUID - * @param worldName - world + * @param gameMode - GameMode name. */ - private void resetAllChallenges(@NonNull String storageDataID, @NonNull String worldName) + private void resetAllChallenges(@NonNull String storageDataID, @NonNull String gameMode) { this.addPlayerData(storageDataID); - this.playerCacheData.get(storageDataID).reset(worldName); + this.playerCacheData.get(storageDataID).reset(gameMode); // Save this.savePlayerData(storageDataID); } @@ -735,15 +743,15 @@ public class ChallengesManager * Get the status on every level for required world and playerData * * @param storageDataID - playerData ID - * @param worldName - World Name where levels should be searched. + * @param gameMode - World Name where levels should be searched. * @return Level status - how many challenges still to do on which level */ - private List getAllChallengeLevelStatus(String storageDataID, String worldName) + private List getAllChallengeLevelStatus(String storageDataID, String gameMode) { this.addPlayerData(storageDataID); ChallengesPlayerData playerData = this.playerCacheData.get(storageDataID); - List challengeLevelList = this.getLevels(worldName); + List challengeLevelList = this.getLevels(gameMode); List result = new ArrayList<>(); @@ -781,22 +789,40 @@ public class ChallengesManager /** * This method returns LevelStatus object for given challenge level. * @param storageDataID User which level status must be acquired. + * @param world World where level is living. * @param level Level which status must be calculated. * @return LevelStatus of given level. */ - private LevelStatus getChallengeLevelStatus(@NonNull String storageDataID, @NonNull ChallengeLevel level) + private LevelStatus getChallengeLevelStatus(@NonNull String storageDataID, World world, @NonNull ChallengeLevel level) { - List statusList = this.getAllChallengeLevelStatus(storageDataID, level.getWorld()); + this.addPlayerData(storageDataID); + ChallengesPlayerData playerData = this.playerCacheData.get(storageDataID); - for (LevelStatus status : statusList) + List challengeLevelList = this.getLevels(world); + + int levelIndex = challengeLevelList.indexOf(level); + + if (levelIndex == -1) { - if (status.getLevel().equals(level)) - { - return status; - } + return null; } + else + { + ChallengeLevel previousLevel = levelIndex < 1 ? null : challengeLevelList.get(levelIndex - 1); - return null; + int challengesToDo = previousLevel == null ? 0 : + (previousLevel.getChallenges().size() - level.getWaiverAmount()); + + // As level already contains unique ids of challenges, just iterate through them. + int doneChallengeCount = (int) level.getChallenges().stream().filter(playerData::isChallengeDone).count(); + + return new LevelStatus( + level, + previousLevel, + challengesToDo, + level.getChallenges().size() == doneChallengeCount, + challengesToDo <= 0); + } } @@ -807,13 +833,18 @@ public class ChallengesManager * @param level - level * @return true if level is unlocked */ - private boolean isLevelUnlocked(@NonNull String storageDataID, ChallengeLevel level) + private boolean isLevelUnlocked(@NonNull String storageDataID, + World world, + ChallengeLevel level) { this.addPlayerData(storageDataID); - return this.getAllChallengeLevelStatus(storageDataID, level.getWorld()).stream(). - filter(LevelStatus::isUnlocked). - anyMatch(lv -> lv.getLevel().equals(level)); + return this.islandWorldManager.getAddon(world).filter(gameMode -> + this.getAllChallengeLevelStatus(storageDataID, gameMode.getDescription().getName()). + stream(). + filter(LevelStatus::isUnlocked). + anyMatch(lv -> lv.getLevel().equals(level))). + isPresent(); } @@ -1034,21 +1065,22 @@ public class ChallengesManager */ public void resetAllChallenges(UUID userID, World world, UUID adminID) { - world = Util.getWorld(world); - String storageID = this.getDataUniqueID(userID, world); + String storageID = this.getDataUniqueID(userID, Util.getWorld(world)); - this.resetAllChallenges(storageID, world.getName()); - this.addLogEntry(storageID, new LogEntry.Builder("RESET_ALL"). - data("user-id", userID.toString()). - data("admin-id", adminID == null ? "ISLAND_RESET" : adminID.toString()). - build()); + this.islandWorldManager.getAddon(world).ifPresent(gameMode -> { + this.resetAllChallenges(storageID, gameMode.getDescription().getName()); + this.addLogEntry(storageID, new LogEntry.Builder("RESET_ALL"). + data("user-id", userID.toString()). + data("admin-id", adminID == null ? "ISLAND_RESET" : adminID.toString()). + build()); - // Fire event that admin resets user challenge - Bukkit.getServer().getPluginManager().callEvent( - new ChallengeResetAllEvent(world.getName(), - userID, - adminID != null, - adminID == null ? "ISLAND_RESET" : "RESET_ALL")); + // Fire event that admin resets user challenge + Bukkit.getServer().getPluginManager().callEvent( + new ChallengeResetAllEvent(gameMode.getDescription().getName(), + userID, + adminID != null, + adminID == null ? "ISLAND_RESET" : "RESET_ALL")); + }); } @@ -1089,7 +1121,7 @@ public class ChallengesManager */ public boolean isLevelUnlocked(User user, World world, ChallengeLevel level) { - return this.isLevelUnlocked(this.getDataUniqueID(user, Util.getWorld(world)), level); + return this.isLevelUnlocked(this.getDataUniqueID(user, Util.getWorld(world)), world, level); } @@ -1129,19 +1161,6 @@ public class ChallengesManager } - /** - * This method returns LevelStatus object for given challenge level. - * @param world World where level must be validated. - * @param level Level that must be validated. - * @param user User who need to be validated. - * @return LevelStatus of given level. - */ - public LevelStatus getChallengeLevelStatus(User user, World world, ChallengeLevel level) - { - return this.getChallengeLevelStatus(this.getDataUniqueID(user, Util.getWorld(world)), level); - } - - /** * This method returns LevelStatus object for given challenge level. * @param world World where level must be validated. @@ -1151,7 +1170,7 @@ public class ChallengesManager */ public LevelStatus getChallengeLevelStatus(UUID user, World world, ChallengeLevel level) { - return this.getChallengeLevelStatus(this.getDataUniqueID(user, Util.getWorld(world)), level); + return this.getChallengeLevelStatus(this.getDataUniqueID(user, Util.getWorld(world)), world, level); } @@ -1164,8 +1183,11 @@ public class ChallengesManager */ public List getAllChallengeLevelStatus(User user, World world) { - world = Util.getWorld(world); - return this.getAllChallengeLevelStatus(this.getDataUniqueID(user, world), world.getName()); + return this.islandWorldManager.getAddon(world).map(gameMode -> + this.getAllChallengeLevelStatus( + this.getDataUniqueID(user, Util.getWorld(world)), + gameMode.getDescription().getName())). + orElse(Collections.emptyList()); } @@ -1182,19 +1204,13 @@ public class ChallengesManager */ public List getAllChallengesNames(@NonNull World world) { - World gameWorld = Util.getWorld(world); - - if (gameWorld == null) - { - return Collections.emptyList(); - } - - // TODO: Probably need to check also database. - return this.challengeCacheData.values().stream(). + return this.islandWorldManager.getAddon(world).map(gameMode -> + this.challengeCacheData.values().stream(). sorted(Comparator.comparing(Challenge::getOrder)). - filter(challenge -> challenge.matchWorld(gameWorld.getName())). + filter(challenge -> challenge.matchGameMode(gameMode.getDescription().getName())). map(Challenge::getUniqueId). - collect(Collectors.toList()); + collect(Collectors.toList())). + orElse(Collections.emptyList()); } @@ -1206,18 +1222,12 @@ public class ChallengesManager */ public List getAllChallenges(@NonNull World world) { - World gameWorld = Util.getWorld(world); - - if (gameWorld == null) - { - return Collections.emptyList(); - } - - // TODO: Probably need to check also database. - return this.challengeCacheData.values().stream(). - filter(challenge -> challenge.matchWorld(gameWorld.getName())). + return this.islandWorldManager.getAddon(world).map(gameMode -> + this.challengeCacheData.values().stream(). sorted(Comparator.comparing(Challenge::getOrder)). - collect(Collectors.toList()); + filter(challenge -> challenge.matchGameMode(gameMode.getDescription().getName())). + collect(Collectors.toList())). + orElse(Collections.emptyList()); } @@ -1372,28 +1382,23 @@ public class ChallengesManager */ public List getLevels(@NonNull World world) { - world = Util.getWorld(world); - - if (world == null) - { - return Collections.emptyList(); - } - - return this.getLevels(world.getName()); + return this.islandWorldManager.getAddon(world).map(gameMode -> + this.getLevels(gameMode.getDescription().getName())). + orElse(Collections.emptyList()); } /** - * This method returns list of challenge levels in given world. - * @param world for which levels must be searched. - * @return List with challenges in given world. + * This method returns list of challenge levels in given gameMode. + * @param gameMode for which levels must be searched. + * @return List with challengeLevel in given gameMode. */ - public List getLevels(String world) + private List getLevels(String gameMode) { // TODO: Probably need to check also database. return this.levelCacheData.values().stream(). sorted(ChallengeLevel::compareTo). - filter(level -> level.matchWorld(world)). + filter(level -> level.matchGameMode(gameMode)). collect(Collectors.toList()); } @@ -1595,27 +1600,21 @@ public class ChallengesManager */ public boolean hasAnyChallengeData(@NonNull World world) { - world = Util.getWorld(world); - - if (world == null) - { - return false; - } - - return this.hasAnyChallengeData(world.getName()); + return this.islandWorldManager.getAddon(world).filter(gameMode -> + this.hasAnyChallengeData(gameMode.getDescription().getName())).isPresent(); } /** - * This method returns if in given world has any stored challenge or level. - * @param worldName World name that needs to be checked - * @return true if world has any challenge or level, otherwise false + * This method returns if in given gameMode has any stored challenge or level. + * @param gameMode GameMode addon name that needs to be checked + * @return true if gameMode has any challenge or level, otherwise false */ - public boolean hasAnyChallengeData(@NonNull String worldName) + public boolean hasAnyChallengeData(@NonNull String gameMode) { return this.challengeDatabase.loadObjects().stream().anyMatch( - challenge -> challenge.matchWorld(worldName)) || + challenge -> challenge.matchGameMode(gameMode)) || this.levelDatabase.loadObjects().stream().anyMatch( - level -> level.matchWorld(worldName)); + level -> level.matchGameMode(gameMode)); } } \ No newline at end of file diff --git a/src/main/java/world/bentobox/challenges/commands/CompleteChallengeCommand.java b/src/main/java/world/bentobox/challenges/commands/CompleteChallengeCommand.java index 5369299..22e0c99 100644 --- a/src/main/java/world/bentobox/challenges/commands/CompleteChallengeCommand.java +++ b/src/main/java/world/bentobox/challenges/commands/CompleteChallengeCommand.java @@ -11,6 +11,7 @@ import world.bentobox.bentobox.util.Util; import world.bentobox.challenges.ChallengesAddon; import world.bentobox.challenges.database.object.Challenge; import world.bentobox.challenges.tasks.TryToComplete; +import world.bentobox.challenges.utils.Utils; /** @@ -58,7 +59,7 @@ public class CompleteChallengeCommand extends CompositeCommand else if (!args.get(0).isEmpty()) { // Add world name back at the start - String challengeName = Util.getWorld(this.getWorld()).getName() + "_" + args.get(0); + String challengeName = Utils.getGameMode(this.getWorld()) + "_" + args.get(0); Challenge challenge = this.addon.getChallengesManager().getChallenge(challengeName); int count = args.size() == 2 ? Integer.valueOf(args.get(1)) : 1; @@ -102,7 +103,7 @@ public class CompleteChallengeCommand extends CompositeCommand case 3: // Create suggestions with all challenges that is available for users. returnList.addAll(this.addon.getChallengesManager().getAllChallengesNames(this.getWorld()).stream(). - map(challenge -> challenge.substring(Util.getWorld(this.getWorld()).getName().length() + 1)). + map(challenge -> challenge.substring(Utils.getGameMode(this.getWorld()).length() + 1)). collect(Collectors.toList())); break; diff --git a/src/main/java/world/bentobox/challenges/commands/admin/CompleteCommand.java b/src/main/java/world/bentobox/challenges/commands/admin/CompleteCommand.java index 1354c92..71bb16c 100644 --- a/src/main/java/world/bentobox/challenges/commands/admin/CompleteCommand.java +++ b/src/main/java/world/bentobox/challenges/commands/admin/CompleteCommand.java @@ -11,7 +11,7 @@ import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.util.Util; import world.bentobox.challenges.ChallengesAddon; import world.bentobox.challenges.database.object.Challenge; -import world.bentobox.challenges.tasks.TryToComplete; +import world.bentobox.challenges.utils.Utils; /** @@ -92,7 +92,7 @@ public class CompleteCommand extends CompositeCommand } // Add world name back at the start - String challengeName = Util.getWorld(this.getWorld()).getName() + "_" + args.get(1); + String challengeName = Utils.getGameMode(this.getWorld()) + "_" + args.get(1); Challenge challenge = this.addon.getChallengesManager().getChallenge(challengeName); if (challenge != null) @@ -169,7 +169,7 @@ public class CompleteCommand extends CompositeCommand case 4: // Create suggestions with all challenges that is available for users. returnList.addAll(this.addon.getChallengesManager().getAllChallengesNames(this.getWorld()).stream(). - map(challenge -> challenge.substring(Util.getWorld(this.getWorld()).getName().length() + 1)). + map(challenge -> challenge.substring(Utils.getGameMode(this.getWorld()).length() + 1)). collect(Collectors.toList())); break; diff --git a/src/main/java/world/bentobox/challenges/commands/admin/ResetCommand.java b/src/main/java/world/bentobox/challenges/commands/admin/ResetCommand.java index 4208193..2084254 100644 --- a/src/main/java/world/bentobox/challenges/commands/admin/ResetCommand.java +++ b/src/main/java/world/bentobox/challenges/commands/admin/ResetCommand.java @@ -11,7 +11,7 @@ import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.util.Util; import world.bentobox.challenges.ChallengesAddon; import world.bentobox.challenges.database.object.Challenge; -import world.bentobox.challenges.tasks.TryToComplete; +import world.bentobox.challenges.utils.Utils; /** @@ -110,7 +110,7 @@ public class ResetCommand extends CompositeCommand } else { - String challengeName = Util.getWorld(this.getWorld()).getName() + "_" + args.get(1); + String challengeName = Utils.getGameMode(this.getWorld()) + "_" + args.get(1); Challenge challenge = this.addon.getChallengesManager().getChallenge(challengeName); if (challenge != null) @@ -187,7 +187,7 @@ public class ResetCommand extends CompositeCommand case 4: // Create suggestions with all challenges that is available for users. returnList.addAll(this.addon.getChallengesManager().getAllChallengesNames(this.getWorld()).stream(). - map(challenge -> challenge.substring(Util.getWorld(this.getWorld()).getName().length() + 1)). + map(challenge -> challenge.substring(Utils.getGameMode(this.getWorld()).length() + 1)). collect(Collectors.toList())); returnList.add("all"); 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 f7d3a19..928398d 100644 --- a/src/main/java/world/bentobox/challenges/database/object/Challenge.java +++ b/src/main/java/world/bentobox/challenges/database/object/Challenge.java @@ -979,16 +979,18 @@ 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 match if given gameMode relates to current challenge. It is detected + * via challenge uniqueId, as it always must start with gameMode 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 + * and readjust to store GameMode name instead of world name. + * @param gameMode Name that must be checked. + * @return {@code true} if current challenge relates to given gameMode name, otherwise * {@code false}. */ - public boolean matchWorld(String worldName) + public boolean matchGameMode(String gameMode) { - return this.uniqueId.regionMatches(true, 0, worldName, 0, worldName.length()); + return gameMode != null && + this.uniqueId.regionMatches(true, 0, gameMode, 0, gameMode.length()); } 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 7cbf761..ae22355 100644 --- a/src/main/java/world/bentobox/challenges/database/object/ChallengeLevel.java +++ b/src/main/java/world/bentobox/challenges/database/object/ChallengeLevel.java @@ -426,16 +426,19 @@ 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 + * This method match if given gameMode relates to current level. It is detected + * via level uniqueId, as it always must start with gameMode name. + * + * This method is created to avoid issues with capital letters in world names in 1.14. + * It is reused for GameMode storage change. + * @param gameMode Name that must be checked. + * @return {@code true} if current level relates to given gameMode name, otherwise * {@code false}. */ - public boolean matchWorld(String worldName) + public boolean matchGameMode(String gameMode) { - return this.uniqueId.regionMatches(true, 0, worldName, 0, worldName.length()); + return gameMode != null && + this.uniqueId.regionMatches(true, 0, gameMode, 0, gameMode.length()); } 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 5ff36a8..820c17a 100644 --- a/src/main/java/world/bentobox/challenges/database/object/ChallengesPlayerData.java +++ b/src/main/java/world/bentobox/challenges/database/object/ChallengesPlayerData.java @@ -197,15 +197,15 @@ public class ChallengesPlayerData implements DataObject /** - * Resets all challenges and levels in world for this player + * Resets all challenges and levels in GameMode for this player * - * @param worldName world which challenges must be reset. + * @param gameMode GameMode which challenges must be reset. */ - public void reset(@NonNull String worldName) + public void reset(@NonNull String gameMode) { - 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())); + challengeStatus.keySet().removeIf(n -> n.regionMatches(true, 0, gameMode, 0, gameMode.length())); + challengesTimestamp.keySet().removeIf(n -> n.regionMatches(true, 0, gameMode, 0, gameMode.length())); + levelsDone.removeIf(n -> n.regionMatches(true, 0, gameMode, 0, gameMode.length())); } diff --git a/src/main/java/world/bentobox/challenges/panel/admin/AdminGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/AdminGUI.java index d8b504e..8e148a9 100644 --- a/src/main/java/world/bentobox/challenges/panel/admin/AdminGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/admin/AdminGUI.java @@ -5,7 +5,10 @@ import org.bukkit.Material; import org.bukkit.World; import org.bukkit.inventory.ItemStack; +import java.util.Optional; + import net.wesjd.anvilgui.AnvilGUI; +import world.bentobox.bentobox.api.addons.GameModeAddon; import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.builders.PanelBuilder; import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; @@ -15,6 +18,7 @@ import world.bentobox.challenges.ChallengesAddon; import world.bentobox.challenges.panel.CommonGUI; import world.bentobox.challenges.panel.util.ConfirmationGUI; import world.bentobox.challenges.utils.GuiUtils; +import world.bentobox.challenges.utils.Utils; /** @@ -208,7 +212,7 @@ public class AdminGUI extends CommonGUI this.user.getPlayer(), "unique_id", (player, reply) -> { - String newName = Util.getWorld(this.world).getName() + "_" + reply; + String newName = Utils.getGameMode(this.world) + "_" + reply; if (!this.addon.getChallengesManager().containsChallenge(newName)) { @@ -244,7 +248,7 @@ public class AdminGUI extends CommonGUI this.user.getPlayer(), "unique_id", (player, reply) -> { - String newName = Util.getWorld(this.world).getName() + "_" + reply; + String newName = Utils.getGameMode(this.world) + "_" + reply; if (!this.addon.getChallengesManager().containsLevel(newName)) { diff --git a/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java b/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java index 8c630fa..074dcc9 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.matchWorld(Util.getWorld(this.world).getName())) + !this.challenge.matchGameMode(Utils.getGameMode(this.world))) { this.user.sendMessage("general.errors.wrong-world"); result = EMPTY_RESULT; diff --git a/src/main/java/world/bentobox/challenges/utils/Utils.java b/src/main/java/world/bentobox/challenges/utils/Utils.java index 8f59a9d..ecc4ecd 100644 --- a/src/main/java/world/bentobox/challenges/utils/Utils.java +++ b/src/main/java/world/bentobox/challenges/utils/Utils.java @@ -2,10 +2,13 @@ package world.bentobox.challenges.utils; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.List; +import world.bentobox.bentobox.BentoBox; + /** * Util methods used in different situations. @@ -78,4 +81,18 @@ public class Utils material.equals(Material.WRITTEN_BOOK) || material.equals(Material.FILLED_MAP); } + + + /** + * This method transforms given World into GameMode name. If world is not a GameMode + * world then it returns null. + * @param world World which gameMode name must be found out. + * @return GameMode name or null. + */ + public static String getGameMode(World world) + { + return BentoBox.getInstance().getIWM().getAddon(world). + map(gameModeAddon -> gameModeAddon.getDescription().getName()). + orElse(null); + } }