Implement completed challenge storage by island (#55).

Rework methods that access to ChallengesPlayerData object. Methods that access to this object will be private and use UUID and String where possible.
Add public methods that could use previously mentioned methods to access ChallengesPlayerData object.
Implement these methods in all places.

Add ability to enable/disable island storage in config (no-gui for now).
Disable challenge GUI opening, if user does not have island.
This commit is contained in:
BONNe 2019-02-18 01:29:42 +02:00
parent f9b941059e
commit 4db59d6c19
11 changed files with 503 additions and 312 deletions

View File

@ -14,10 +14,10 @@ import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.Util;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.database.object.ChallengeLevel;
@ -70,6 +70,11 @@ public class ChallengesManager
*/
private ChallengesAddon addon;
/**
* This variable allows to access ChallengesAddon settings.
*/
private Settings settings;
// ---------------------------------------------------------------------
// Section: Constants
@ -94,6 +99,8 @@ public class ChallengesManager
public ChallengesManager(ChallengesAddon addon)
{
this.addon = addon;
this.settings = addon.getChallengesSettings();
// Set up the configs
this.challengeDatabase = new Database<>(addon, Challenge.class);
this.levelDatabase = new Database<>(addon, ChallengeLevel.class);
@ -281,6 +288,7 @@ public class ChallengesManager
}
}
// ---------------------------------------------------------------------
// Section: Other storing related methods
// ---------------------------------------------------------------------
@ -319,24 +327,13 @@ public class ChallengesManager
/**
* Load player from database into the cache or create new player data
* Load player/island from database into the cache or create new player/island data
*
* @param user - user to add
* @param uniqueID - uniqueID to add
*/
private void addPlayer(@NonNull User user)
private void addPlayerData(@NonNull UUID uniqueID)
{
this.addPlayer(user.getUniqueId());
}
/**
* Load player from database into the cache or create new player data
*
* @param userID - userID to add
*/
private void addPlayer(@NonNull UUID userID)
{
if (this.playerCacheData.containsKey(userID))
if (this.playerCacheData.containsKey(uniqueID))
{
return;
}
@ -344,20 +341,20 @@ public class ChallengesManager
// The player is not in the cache
// Check if the player exists in the database
if (this.playersDatabase.objectExists(userID.toString()))
if (this.playersDatabase.objectExists(uniqueID.toString()))
{
// Load player from database
ChallengesPlayerData data = this.playersDatabase.loadObject(userID.toString());
ChallengesPlayerData data = this.playersDatabase.loadObject(uniqueID.toString());
// Store in cache
this.playerCacheData.put(userID, data);
this.playerCacheData.put(uniqueID, data);
}
else
{
// Create the player data
ChallengesPlayerData pd = new ChallengesPlayerData(userID.toString());
ChallengesPlayerData pd = new ChallengesPlayerData(uniqueID.toString());
this.playersDatabase.saveObject(pd);
// Add to cache
this.playerCacheData.put(userID, pd);
this.playerCacheData.put(uniqueID, pd);
}
}
@ -374,7 +371,7 @@ public class ChallengesManager
{
this.saveChallenges();
this.saveLevels();
this.savePlayers();
this.savePlayersData();
}
@ -417,129 +414,165 @@ public class ChallengesManager
/**
* This method saves all players to database.
* This method saves all players/islands to database.
*/
private void savePlayers()
private void savePlayersData()
{
this.playerCacheData.values().forEach(this.playersDatabase::saveObject);
}
/**
* This method saves player with given UUID.
* @param playerUUID users UUID.
* This method saves player/island with given UUID.
* @param uniqueID user/island UUID.
*/
private void savePlayer(UUID playerUUID)
private void savePlayerData(@NonNull UUID uniqueID)
{
if (this.playerCacheData.containsKey(playerUUID))
if (this.playerCacheData.containsKey(uniqueID))
{
this.playersDatabase.saveObject(this.playerCacheData.get(playerUUID));
this.playersDatabase.saveObject(this.playerCacheData.get(uniqueID));
}
}
// ---------------------------------------------------------------------
// Section: Player Data related methods
// Section: Private methods that is used to process player/island data.
// ---------------------------------------------------------------------
/**
* This method returns all players who have done at least one challenge in given world.
* @param world World in which must search challenges.
* @return List with players who have done at least on challenge.
*/
public List<Player> getPlayers(World world)
{
List<String> allChallengeList = this.getAllChallengesNames(world);
// This is using Database, as some users may not be in the cache.
return this.playersDatabase.loadObjects().stream().filter(playerData ->
allChallengeList.stream().anyMatch(playerData::isChallengeDone)).
map(playerData -> Bukkit.getPlayer(UUID.fromString(playerData.getUniqueId()))).
collect(Collectors.toList());
}
/**
* This method returns how many times a player has done a challenge before
* @param user - user
* @param challenge - challenge
* @return - number of times
*/
public long getChallengeTimes(User user, Challenge challenge)
{
this.addPlayer(user);
return this.playerCacheData.get(user.getUniqueId()).getTimes(challenge.getUniqueId());
}
/**
* Checks if a challenge is complete or not
* This method returns UUID that corresponds to player or player's island in given world.
*
* @param user - User who must be checked.
* @param challenge - Challenge
* @param user of type User
* @param world of type World
* @return UUID
*/
private UUID getDataUniqueID(User user, World world)
{
return this.getDataUniqueID(user.getUniqueId(), world);
}
/**
* This method returns UUID that corresponds to player or player's island in given world.
*
* @param userID of type User
* @param world of type World
* @return UUID
*/
private UUID getDataUniqueID(UUID userID, World world)
{
if (this.settings.isStoreAsIslandData())
{
Island island = this.addon.getIslands().getIsland(world, userID);
if (island == null)
{
// If storage is in island mode and user does not have island, then it can happen.
// This should never happen ...
// Just return random UUID and hope that it will not be necessary.
return UUID.randomUUID();
}
else
{
// Unfortunately, island does not store UUID, just a string.
return UUID.fromString(island.getUniqueId());
}
}
else
{
return userID;
}
}
/**
* Checks if a challengeID is complete or not
*
* @param storageDataID - PlayerData ID object who must be checked.
* @param challengeID - Challenge uniqueID
* @return - true if completed
*/
public boolean isChallengeComplete(User user, Challenge challenge)
private long getChallengeTimes(UUID storageDataID, String challengeID)
{
return this.isChallengeComplete(user.getUniqueId(), challenge);
this.addPlayerData(storageDataID);
return this.playerCacheData.get(storageDataID).getTimes(challengeID);
}
/**
* Checks if a challenge is complete or not
* Checks if a challenge with given ID is complete or not
*
* @param user - User who must be checked.
* @param challenge - Challenge
* @param storageDataID - PlayerData ID object who must be checked.
* @param challengeID - Challenge uniqueID
* @return - true if completed
*/
public boolean isChallengeComplete(UUID user, Challenge challenge)
private boolean isChallengeComplete(UUID storageDataID, String challengeID)
{
return this.isChallengeComplete(user, challenge.getUniqueId());
this.addPlayerData(storageDataID);
return this.playerCacheData.get(storageDataID).isChallengeDone(challengeID);
}
/**
* Checks if a challenge is complete or not
* Sets the challenge with given ID as complete and increments the number of times it has been
* completed
*
* @param user - User who must be checked.
* @param challenge - Challenge
* @return - true if completed
* @param storageDataID - playerData ID
* @param challengeID - challengeID
*/
public boolean isChallengeComplete(UUID user, String challenge)
private void setChallengeComplete(@NonNull UUID storageDataID, @NonNull String challengeID)
{
this.addPlayer(user);
return this.playerCacheData.get(user).isChallengeDone(challenge);
this.addPlayerData(storageDataID);
this.playerCacheData.get(storageDataID).setChallengeDone(challengeID);
// Save
this.savePlayerData(storageDataID);
}
/**
* Get the status on every level
* Reset the challenge with given ID to zero time / not done
*
* @param user - user
* @param world - world
* @param storageDataID - playerData ID
* @param challengeID - challenge ID
*/
private void resetChallenge(@NonNull UUID storageDataID, @NonNull String challengeID)
{
this.addPlayerData(storageDataID);
this.playerCacheData.get(storageDataID).setChallengeTimes(challengeID, 0);
// Save
this.savePlayerData(storageDataID);
}
/**
* Resets all the challenges for user in world
*
* @param storageDataID - island owner's UUID
* @param worldName - world
*/
private void resetAllChallenges(@NonNull UUID storageDataID, @NonNull String worldName)
{
this.addPlayerData(storageDataID);
this.playerCacheData.get(storageDataID).reset(worldName);
// Save
this.savePlayerData(storageDataID);
}
/**
* Get the status on every level for required world and playerData
*
* @param storageDataID - playerData ID
* @param worldName - World Name where levels should be searched.
* @return Level status - how many challenges still to do on which level
*/
public List<LevelStatus> getChallengeLevelStatus(User user, World world)
private List<LevelStatus> getAllChallengeLevelStatus(UUID storageDataID, String worldName)
{
return this.getChallengeLevelStatus(user.getUniqueId(), Util.getWorld(world).getName());
}
this.addPlayerData(storageDataID);
ChallengesPlayerData playerData = this.playerCacheData.get(storageDataID);
/**
* Get the status on every level
*
* @param user - user
* @param world - world
* @return Level status - how many challenges still to do on which level
*/
public List<LevelStatus> getChallengeLevelStatus(UUID user, String world)
{
this.addPlayer(user);
ChallengesPlayerData playerData = this.playerCacheData.get(user);
List<ChallengeLevel> challengeLevelList = this.getLevels(world);
List<ChallengeLevel> challengeLevelList = this.getLevels(worldName);
List<LevelStatus> result = new ArrayList<>();
@ -547,7 +580,7 @@ public class ChallengesManager
ChallengeLevel previousLevel = null;
int doneChallengeCount = 0;
// For each challenge level, check how many the user has done
// For each challenge level, check how many the storageDataID has done
for (ChallengeLevel level : challengeLevelList)
{
// To find how many challenges user still must do in previous level, we must
@ -574,171 +607,15 @@ public class ChallengesManager
}
/**
* Check is user can see given level.
*
* @param user - user
* @param level - level
* @return true if level is unlocked
*/
public boolean isLevelUnlocked(User user, ChallengeLevel level)
{
return this.isLevelUnlocked(user.getUniqueId(), level);
}
/**
* Check is user can see given level.
*
* @param user - user
* @param level - level
* @return true if level is unlocked
*/
public boolean isLevelUnlocked(UUID user, ChallengeLevel level)
{
this.addPlayer(user);
return this.getChallengeLevelStatus(user, level.getWorld()).stream().
filter(LevelStatus::isUnlocked).
anyMatch(lv -> lv.getLevel().equals(level));
}
/**
* Sets the challenge as complete and increments the number of times it has been
* completed
*
* @param user - user
* @param challenge - challenge
*/
public void setChallengeComplete(@NonNull User user, @NonNull Challenge challenge)
{
this.setChallengeComplete(user.getUniqueId(), challenge);
}
/**
* Sets the challenge as complete and increments the number of times it has been
* completed
*
* @param user - user
* @param challenge - challenge
*/
public void setChallengeComplete(@NonNull UUID user, @NonNull Challenge challenge)
{
this.addPlayer(user);
this.playerCacheData.get(user).setChallengeDone(challenge.getUniqueId());
// Save
this.savePlayer(user);
}
/**
* Reset the challenge to zero time / not done
*
* @param user - user
* @param challenge - challenge
*/
public void resetChallenge(@NonNull User user, @NonNull Challenge challenge)
{
this.resetChallenge(user.getUniqueId(), challenge);
}
/**
* Reset the challenge to zero time / not done
*
* @param user - user
* @param challenge - challenge
*/
public void resetChallenge(@NonNull UUID user, @NonNull Challenge challenge)
{
this.addPlayer(user);
this.playerCacheData.get(user).setChallengeTimes(challenge.getUniqueId(), 0);
// Save
this.savePlayer(user);
}
/**
* Resets all the challenges for user in world
*
* @param userID - island owner's UUID
* @param world - world
*/
public void resetAllChallenges(@NonNull UUID userID, @NonNull World world)
{
this.addPlayer(userID);
this.playerCacheData.get(userID).reset(world);
// Save
this.savePlayer(userID);
}
/**
* Resets all the challenges for user in world
*
* @param user - island owner's UUID
* @param world - world
*/
public void resetAllChallenges(@NonNull User user, @NonNull World world)
{
this.resetAllChallenges(user.getUniqueId(), world);
}
/**
* This method returns if given user has been already completed given level.
* @param level Level that must be checked.
* @param user User who need to be checked.
* @return true, if level is already completed.
*/
public boolean isLevelCompleted(@NonNull User user, @NonNull ChallengeLevel level)
{
this.addPlayer(user);
return this.playerCacheData.get(user.getUniqueId()).isLevelDone(level.getUniqueId());
}
/**
* This method checks all level challenges and checks if all challenges are done.
* @param level Level that must be checked.
* @param user User who need to be checked.
* @return true, if all challenges are done, otherwise false.
*/
public boolean validateLevelCompletion(@NonNull User user, @NonNull ChallengeLevel level)
{
this.addPlayer(user);
ChallengesPlayerData playerData = this.playerCacheData.get(user.getUniqueId());
long doneChallengeCount = level.getChallenges().stream().filter(playerData::isChallengeDone).count();
return level.getChallenges().size() == doneChallengeCount;
}
/**
* This method sets given level as completed.
* @param level Level that must be completed.
* @param user User who complete level.
*/
public void setLevelComplete(@NonNull User user, @NonNull ChallengeLevel level)
{
this.addPlayer(user);
this.playerCacheData.get(user.getUniqueId()).addCompletedLevel(level.getUniqueId());
// Save
this.savePlayer(user.getUniqueId());
}
/**
* This method returns LevelStatus object for given challenge level.
* @param user User which level status must be acquired.
* @param storageDataID User which level status must be acquired.
* @param level Level which status must be calculated.
* @return LevelStatus fof given level.
* @return LevelStatus of given level.
*/
public LevelStatus getChallengeLevelStatus(UUID user, ChallengeLevel level)
private LevelStatus getChallengeLevelStatus(@NonNull UUID storageDataID, @NonNull ChallengeLevel level)
{
List<LevelStatus> statusList = this.getChallengeLevelStatus(user, level.getWorld());
List<LevelStatus> statusList = this.getAllChallengeLevelStatus(storageDataID, level.getWorld());
for (LevelStatus status : statusList)
{
@ -752,6 +629,285 @@ public class ChallengesManager
}
/**
* Check is playerData can see given level.
* TODO: not an optimal way. Faster would be to check previous level challenges.
* @param storageDataID - playerData ID
* @param level - level
* @return true if level is unlocked
*/
private boolean isLevelUnlocked(@NonNull UUID storageDataID, ChallengeLevel level)
{
this.addPlayerData(storageDataID);
return this.getAllChallengeLevelStatus(storageDataID, level.getWorld()).stream().
filter(LevelStatus::isUnlocked).
anyMatch(lv -> lv.getLevel().equals(level));
}
/**
* This method returns if given user has been already completed given level.
* @param levelID Level that must be checked.
* @param storageDataID User who need to be checked.
* @return true, if level is already completed.
*/
private boolean isLevelCompleted(@NonNull UUID storageDataID, @NonNull String levelID)
{
this.addPlayerData(storageDataID);
return this.playerCacheData.get(storageDataID).isLevelDone(levelID);
}
/**
* This method checks all level challenges and checks if all challenges are done.
* @param level Level that must be checked.
* @param storageDataID User who need to be checked.
* @return true, if all challenges are done, otherwise false.
*/
private boolean validateLevelCompletion(@NonNull UUID storageDataID, @NonNull ChallengeLevel level)
{
this.addPlayerData(storageDataID);
ChallengesPlayerData playerData = this.playerCacheData.get(storageDataID);
long doneChallengeCount = level.getChallenges().stream().filter(playerData::isChallengeDone).count();
return level.getChallenges().size() == doneChallengeCount;
}
/**
* This method sets given level as completed.
* @param levelID Level that must be completed.
* @param storageDataID User who complete level.
*/
private void setLevelComplete(@NonNull UUID storageDataID, @NonNull String levelID)
{
this.addPlayerData(storageDataID);
this.playerCacheData.get(storageDataID).addCompletedLevel(levelID);
// Save
this.savePlayerData(storageDataID);
}
// ---------------------------------------------------------------------
// Section: Public methods for processing player/island data.
// ---------------------------------------------------------------------
/**
* This method returns if given user has completed given challenge in world.
* @param user - User that must be checked.
* @param world - World where challenge operates.
* @param challenge - Challenge that must be checked.
* @return True, if challenge is completed, otherwise - false.
*/
public boolean isChallengeComplete(User user, World world, Challenge challenge)
{
return this.isChallengeComplete(user.getUniqueId(), world, challenge.getUniqueId());
}
/**
* This method returns if given user has completed given challenge in world.
* @param user - User that must be checked.
* @param world - World where challenge operates.
* @param challenge - Challenge that must be checked.
* @return True, if challenge is completed, otherwise - false.
*/
public boolean isChallengeComplete(UUID user, World world, Challenge challenge)
{
return this.isChallengeComplete(user, world, challenge.getUniqueId());
}
/**
* This method returns if given user has completed given challenge in world.
* @param user - User that must be checked.
* @param world - World where challenge operates.
* @param challengeID - Challenge that must be checked.
* @return True, if challenge is completed, otherwise - false.
*/
public boolean isChallengeComplete(UUID user, World world, String challengeID)
{
world = Util.getWorld(world);
return this.isChallengeComplete(this.getDataUniqueID(user, world), challengeID);
}
/**
* This method sets given challenge as completed.
* @param user - Targeted user.
* @param world - World where completion must be called.
* @param challenge - That must be completed.
*/
public void setChallengeComplete(User user, World world, Challenge challenge)
{
this.setChallengeComplete(user.getUniqueId(), world, challenge);
}
/**
* This method sets given challenge as completed.
* @param userID - Targeted user.
* @param world - World where completion must be called.
* @param challenge - That must be completed.
*/
public void setChallengeComplete(UUID userID, World world, Challenge challenge)
{
world = Util.getWorld(world);
this.setChallengeComplete(this.getDataUniqueID(userID, world), challenge.getUniqueId());
}
/**
* This method resets given challenge.
* @param userID - Targeted user.
* @param world - World where reset must be called.
* @param challenge - That must be reset.
*/
public void resetChallenge(UUID userID, World world, Challenge challenge)
{
world = Util.getWorld(world);
this.resetChallenge(this.getDataUniqueID(userID, world), challenge.getUniqueId());
}
/**
* This method resets all challenges in given world.
* @param user - Targeted user.
* @param world - World where challenges must be reset.
*/
public void resetAllChallenges(User user, World world)
{
world = Util.getWorld(world);
this.resetChallenge(this.getDataUniqueID(user, world), world.getName());
}
/**
* This method resets all challenges in given world.
* @param userID - Targeted user.
* @param world - World where challenges must be reset.
*/
public void resetAllChallenges(UUID userID, World world)
{
world = Util.getWorld(world);
this.resetChallenge(this.getDataUniqueID(userID, world), world.getName());
}
/**
* Checks if a challenge is complete or not
*
* @param user - User that must be checked.
* @param world - World where challenge operates.
* @param challenge - Challenge that must be checked.
* @return - true if completed
*/
public long getChallengeTimes(User user, World world, Challenge challenge)
{
world = Util.getWorld(world);
return this.getChallengeTimes(this.getDataUniqueID(user, world), challenge.getUniqueId());
}
/**
* This method returns if given user has been already completed given level.
* @param world World where level must be checked.
* @param level Level that must be checked.
* @param user User who need to be checked.
* @return true, if level is already completed.
*/
public boolean isLevelCompleted(User user, World world, ChallengeLevel level)
{
world = Util.getWorld(world);
return this.isLevelCompleted(this.getDataUniqueID(user, world), level.getUniqueId());
}
/**
* This method returns if given user has unlocked given level.
* @param world World where level must be checked.
* @param level Level that must be checked.
* @param user User who need to be checked.
* @return true, if level is already completed.
*/
public boolean isLevelUnlocked(User user, World world, ChallengeLevel level)
{
world = Util.getWorld(world);
return this.isLevelUnlocked(this.getDataUniqueID(user, world), level);
}
/**
* This method sets given level as completed.
* @param world World where level must be completed.
* @param level Level that must be completed.
* @param user User who need to be updated.
*/
public void setLevelComplete(User user, World world, ChallengeLevel level)
{
world = Util.getWorld(world);
this.setLevelComplete(this.getDataUniqueID(user, world), level.getUniqueId());
}
/**
* This method checks all level challenges and checks if all challenges are done.
* @param world World where level must be validated.
* @param level Level that must be validated.
* @param user User who need to be validated.
* @return true, if all challenges are done, otherwise false.
*/
public boolean validateLevelCompletion(User user, World world, ChallengeLevel level)
{
world = Util.getWorld(world);
return this.validateLevelCompletion(this.getDataUniqueID(user, world), level);
}
/**
* 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)
{
world = Util.getWorld(world);
return this.getChallengeLevelStatus(this.getDataUniqueID(user, world), level);
}
/**
* 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(UUID user, World world, ChallengeLevel level)
{
world = Util.getWorld(world);
return this.getChallengeLevelStatus(this.getDataUniqueID(user, world), level);
}
/**
* Get the status on every level for required world and user
*
* @param user - user which levels should be checked
* @param world - World where levels should be searched.
* @return Level status - how many challenges still to do on which level
*/
public List<LevelStatus> getAllChallengeLevelStatus(User user, World world)
{
world = Util.getWorld(world);
return this.getAllChallengeLevelStatus(this.getDataUniqueID(user, world), world.getName());
}
// ---------------------------------------------------------------------
// Section: Challenges related methods
// ---------------------------------------------------------------------
@ -902,6 +1058,7 @@ public class ChallengesManager
/**
* This method removes challenge from cache and memory.
* TODO: This will not remove challenge from user data. Probably should do it.
* @param challenge that must be removed.
*/
public void deleteChallenge(Challenge challenge)
@ -1092,6 +1249,7 @@ public class ChallengesManager
/**
* This method removes challenge level from cache and memory.
* TODO: This will not remove level from user data. Probably should do it.
* @param challengeLevel Level that must be removed.
*/
public void deleteChallengeLevel(ChallengeLevel challengeLevel)
@ -1134,7 +1292,7 @@ public class ChallengesManager
});
this.playerCacheData.put(UUID.fromString(playerData.getUniqueId()), playerData);
this.savePlayer(UUID.fromString(playerData.getUniqueId()));
this.savePlayerData(UUID.fromString(playerData.getUniqueId()));
});
}
}

View File

@ -46,6 +46,11 @@ public class Settings implements DataObject
@ConfigEntry(path = "free-challenges-first")
private boolean freeChallengesFirst = true;
@ConfigComment("")
@ConfigComment("This indicate if challenges data will be stored per island (true) or per player (false).")
@ConfigEntry(path = "store-island-data")
private boolean storeAsIslandData = false;
@ConfigComment("")
@ConfigComment("This allows to change lore description line length. By default it is 25, but some server")
@ConfigComment("owners may like it to be larger.")
@ -105,7 +110,7 @@ public class Settings implements DataObject
* Configuration version
*/
@ConfigComment("")
private String configVersion = "v1.1";
private String configVersion = "v1.2";
// ---------------------------------------------------------------------
// Section: Methods
@ -213,6 +218,16 @@ public class Settings implements DataObject
}
/**
* This method returns the storeAsIslandData object.
* @return the storeAsIslandData object.
*/
public boolean isStoreAsIslandData()
{
return storeAsIslandData;
}
/**
* This method sets the configVersion object value.
* @param configVersion the configVersion object new value.
@ -312,4 +327,14 @@ public class Settings implements DataObject
{
this.loreLineLength = loreLineLength;
}
/**
* This method sets the storeAsIslandData object value.
* @param storeAsIslandData the storeAsIslandData object new value.
*/
public void setStoreAsIslandData(boolean storeAsIslandData)
{
this.storeAsIslandData = storeAsIslandData;
}
}

View File

@ -8,35 +8,49 @@ import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.panel.user.ChallengesGUI;
public class ChallengesCommand extends CompositeCommand {
public class ChallengesCommand extends CompositeCommand
{
public static final String CHALLENGE_COMMAND = "challenges";
public ChallengesCommand(ChallengesAddon addon, CompositeCommand cmd) {
public ChallengesCommand(ChallengesAddon addon, CompositeCommand cmd)
{
super(addon, cmd, CHALLENGE_COMMAND);
}
@Override
public boolean execute(User user, String label, List<String> args) {
public boolean execute(User user, String label, List<String> args)
{
// Open up the challenges GUI
if (user.isPlayer()) {
new ChallengesGUI((ChallengesAddon) this.getAddon(),
this.getWorld(),
user,
this.getTopLabel(),
this.getPermissionPrefix()).build();
return true;
if (user.isPlayer())
{
if (this.getPlugin().getIslands().getIsland(this.getWorld(), user.getUniqueId()) != null)
{
new ChallengesGUI((ChallengesAddon) this.getAddon(),
this.getWorld(),
user,
this.getTopLabel(),
this.getPermissionPrefix()).build();
return true;
}
else
{
user.sendMessage("general.errors.no-island");
return false;
}
}
// Show help
showHelp(this, user);
return false;
}
@Override
public void setup() {
public void setup()
{
this.setPermission(CHALLENGE_COMMAND);
this.setParametersHelp("challenges.commands.user.parameters");
this.setParametersHelp("challen/ges.commands.user.parameters");
this.setDescription("challenges.commands.user.description");
}
}

View File

@ -57,8 +57,7 @@ public class CompleteChallenge extends CompositeCommand {
return false;
}
// Complete challenge
User target = User.getInstance(targetUUID);
manager.setChallengeComplete(target, this.manager.getChallenge(args.get(1)));
manager.setChallengeComplete(targetUUID, this.getWorld(), this.manager.getChallenge(args.get(1)));
user.sendMessage("general.success");
return true;
}

View File

@ -61,8 +61,7 @@ public class ResetChallenge extends CompositeCommand {
return false;
}
// Complete challenge
User target = User.getInstance(targetUUID);
manager.resetChallenge(target, manager.getChallenge(args.get(1)));
manager.resetChallenge(targetUUID, this.getWorld(), manager.getChallenge(args.get(1)));
user.sendMessage("general.success");
return true;
}

View File

@ -2,14 +2,9 @@ package world.bentobox.challenges.database.object;
import com.google.gson.annotations.Expose;
import org.bukkit.World;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
import world.bentobox.bentobox.database.objects.DataObject;
import world.bentobox.bentobox.util.Util;
/**
* Stores the player's challenge situation
@ -172,11 +167,10 @@ public class ChallengesPlayerData implements DataObject
/**
* Resets all challenges and levels in world for this player
*
* @param world world which challenges must be reset.
* @param worldName world which challenges must be reset.
*/
public void reset(World world)
public void reset(String worldName)
{
String worldName = Util.getWorld(world).getName();
challengeStatus.keySet().removeIf(n -> n.startsWith(worldName));
challengesTimestamp.keySet().removeIf(n -> n.startsWith(worldName));
levelsDone.removeIf(n -> n.startsWith(worldName));

View File

@ -271,9 +271,9 @@ public abstract class CommonGUI
// Some values to avoid overchecking.
ChallengesManager manager = this.addon.getChallengesManager();
final boolean isCompletedOnce = manager.isChallengeComplete(user.getUniqueId(), challenge);
final boolean isCompletedOnce = manager.isChallengeComplete(user.getUniqueId(), world, challenge);
final long doneTimes = challenge.isRepeatable() ?
manager.getChallengeTimes(this.user, challenge) :
manager.getChallengeTimes(this.user, this.world, challenge) :
isCompletedOnce ? 0 : 1;
boolean isCompletedAll = isCompletedOnce && challenge.isRepeatable() &&
challenge.getMaxTimes() > 0 && doneTimes >= challenge.getMaxTimes();
@ -677,7 +677,7 @@ public abstract class CommonGUI
List<String> result = new ArrayList<>();
ChallengesManager manager = this.addon.getChallengesManager();
LevelStatus status = manager.getChallengeLevelStatus(user.getUniqueId(), level);
LevelStatus status = manager.getChallengeLevelStatus(user.getUniqueId(), this.world, level);
// Used to know if blocks, entities, items should be added after requirements and rewards.
char prevChar = ' ';
@ -699,7 +699,7 @@ public abstract class CommonGUI
if (!status.isComplete())
{
int doneChallengeCount = (int) level.getChallenges().stream().
filter(challenge -> this.addon.getChallengesManager().isChallengeComplete(user.getUniqueId(), challenge)).
filter(challenge -> this.addon.getChallengesManager().isChallengeComplete(user.getUniqueId(), world, challenge)).
count();
result.add(this.user.getTranslation("challenges.gui.level-description.completed-challenges-of",

View File

@ -272,15 +272,15 @@ public class TryToComplete
}
// Mark as complete
this.manager.setChallengeComplete(this.user, this.challenge);
this.manager.setChallengeComplete(this.user, this.world, this.challenge);
if (!result.repeat)
{
ChallengeLevel level = this.manager.getLevel(this.challenge);
if (!this.manager.isLevelCompleted(this.user, level))
if (!this.manager.isLevelCompleted(this.user, this.world, level))
{
if (this.manager.validateLevelCompletion(this.user, level))
if (this.manager.validateLevelCompletion(this.user, this.world, level))
{
// Item rewards
for (ItemStack reward : level.getRewardItems())
@ -318,7 +318,7 @@ public class TryToComplete
}
}
this.manager.setLevelComplete(this.user, level);
this.manager.setLevelComplete(this.user, this.world, level);
}
}
}
@ -357,20 +357,20 @@ public class TryToComplete
}
// Check if user has unlocked challenges level.
else if (!this.challenge.getLevel().equals(ChallengesManager.FREE) &&
!this.manager.isLevelUnlocked(this.user, this.manager.getLevel(this.challenge.getLevel())))
!this.manager.isLevelUnlocked(this.user, this.world, this.manager.getLevel(this.challenge.getLevel())))
{
this.user.sendMessage("challenges.errors.challenge-level-not-available");
result = EMPTY_RESULT;
}
// Check max times
else if (this.challenge.isRepeatable() && this.challenge.getMaxTimes() > 0 &&
this.manager.getChallengeTimes(this.user, this.challenge) >= this.challenge.getMaxTimes())
this.manager.getChallengeTimes(this.user, this.world, this.challenge) >= this.challenge.getMaxTimes())
{
this.user.sendMessage("challenges.errors.not-repeatable");
result = EMPTY_RESULT;
}
// Check repeatability
else if (!this.challenge.isRepeatable() && this.manager.isChallengeComplete(this.user, this.challenge))
else if (!this.challenge.isRepeatable() && this.manager.isChallengeComplete(this.user, this.world, this.challenge))
{
this.user.sendMessage("challenges.errors.not-repeatable");
result = EMPTY_RESULT;
@ -546,7 +546,7 @@ public class TryToComplete
// Return the result
return new ChallengeResult().setMeetsRequirements().setRepeat(
this.manager.isChallengeComplete(this.user, this.challenge));
this.manager.isChallengeComplete(this.user, this.world, this.challenge));
}

View File

@ -175,8 +175,7 @@ public class ListUsersGUI extends CommonGUI
{
int lineLength = this.addon.getChallengesSettings().getLoreLineLength();
if (this.addon.getIslands().hasIsland(this.world, player.getUniqueId()) ||
this.addon.getIslands().inTeam(this.world, player.getUniqueId()))
if (this.addon.getIslands().getIsland(this.world, player.getUniqueId()) != null)
{
return new PanelItemBuilder().name(player.getName()).icon(player.getName()).clickHandler(
(panel, user1, clickType, slot) -> {
@ -190,7 +189,7 @@ public class ListUsersGUI extends CommonGUI
for (Challenge challenge : manager.getAllChallenges(this.world))
{
if (!manager.isChallengeComplete(player.getUniqueId(), challenge))
if (!manager.isChallengeComplete(player.getUniqueId(), this.world, challenge))
{
challengeDescriptionMap.put(challenge, this.generateChallengeDescription(challenge, player));
}
@ -199,7 +198,7 @@ public class ListUsersGUI extends CommonGUI
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> {
if (status)
{
valueSet.forEach(challenge -> manager.setChallengeComplete(player.getUniqueId(), challenge));
valueSet.forEach(challenge -> manager.setChallengeComplete(player.getUniqueId(), this.world, challenge));
}
this.build();
@ -210,7 +209,7 @@ public class ListUsersGUI extends CommonGUI
for (Challenge challenge : manager.getAllChallenges(this.world))
{
if (manager.isChallengeComplete(player.getUniqueId(), challenge))
if (manager.isChallengeComplete(player.getUniqueId(), this.world, challenge))
{
challengeDescriptionMap.put(challenge, this.generateChallengeDescription(challenge, player));
}
@ -219,7 +218,7 @@ public class ListUsersGUI extends CommonGUI
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> {
if (status)
{
valueSet.forEach(challenge -> manager.resetChallenge(player.getUniqueId(), challenge));
valueSet.forEach(challenge -> manager.resetChallenge(player.getUniqueId(), this.world, challenge));
}
this.build();

View File

@ -46,7 +46,7 @@ public class ChallengesGUI extends CommonGUI
super(addon, world, user, topLabel, permissionPrefix);
this.challengesManager = this.addon.getChallengesManager();
this.levelStatusList = this.challengesManager.getChallengeLevelStatus(this.user, this.world);
this.levelStatusList = this.challengesManager.getAllChallengeLevelStatus(this.user, this.world);
for (LevelStatus levelStatus : this.levelStatusList)
{
@ -148,7 +148,7 @@ public class ChallengesGUI extends CommonGUI
if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges())
{
freeChallenges.removeIf(challenge -> !challenge.isRepeatable() &&
this.challengesManager.isChallengeComplete(this.user, challenge));
this.challengesManager.isChallengeComplete(this.user, this.world, challenge));
}
final int freeChallengesCount = freeChallenges.size();
@ -218,7 +218,7 @@ public class ChallengesGUI extends CommonGUI
if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges())
{
challenges.removeIf(challenge -> !challenge.isRepeatable() &&
this.challengesManager.isChallengeComplete(this.user, challenge));
this.challengesManager.isChallengeComplete(this.user, this.world, challenge));
}
final int challengesCount = challenges.size();
@ -366,7 +366,7 @@ public class ChallengesGUI extends CommonGUI
return true;
}).
glow(this.addon.getChallengesSettings().isAddCompletedGlow() &&
this.challengesManager.isChallengeComplete(this.user, challenge)).
this.challengesManager.isChallengeComplete(this.user, this.world, challenge)).
build();
}
@ -413,7 +413,7 @@ public class ChallengesGUI extends CommonGUI
return true;
};
glow = this.addon.getChallengesSettings().isAddCompletedGlow() &&
this.challengesManager.isLevelCompleted(this.user, level.getLevel());
this.challengesManager.isLevelCompleted(this.user, this.world, level.getLevel());
}
else
{

View File

@ -22,6 +22,9 @@ add-completed-glow: true
# This indicate if free challenges must be at the start (true) or at the end (false) of list.
free-challenges-first: true
#
# This indicate if challenges data will be stored per island (true) or per player (false).
store-island-data: true
#
# This allows to change lore description line length. By default it is 25, but some server
# owners may like it to be larger.
lore-length: 25
@ -65,4 +68,4 @@ disabled-gamemodes: []
#
uniqueId: config
#
configVersion: v1.1
configVersion: v1.2