Release 0.6.0

This commit is contained in:
BONNe1704 2019-02-25 12:22:57 +02:00
commit 6fbc24ef85
49 changed files with 3066 additions and 2146 deletions

25
pom.xml
View File

@ -6,7 +6,7 @@
<groupId>world.bentobox</groupId> <groupId>world.bentobox</groupId>
<artifactId>challenges</artifactId> <artifactId>challenges</artifactId>
<version>0.5.1</version> <version>0.6.0-SNAPSHOT</version>
<name>Challenges</name> <name>Challenges</name>
<description>Challenges is an add-on for BentoBox, an expandable Minecraft Bukkit plugin for island-type games like SkyBlock, AcidIsland or CaveBlock.</description> <description>Challenges is an add-on for BentoBox, an expandable Minecraft Bukkit plugin for island-type games like SkyBlock, AcidIsland or CaveBlock.</description>
@ -56,9 +56,14 @@
<id>codemc-repo</id> <id>codemc-repo</id>
<url>https://repo.codemc.org/repository/maven-public/</url> <url>https://repo.codemc.org/repository/maven-public/</url>
</repository> </repository>
<!--Vault Repo is down.-->
<!--<repository>-->
<!--<id>vault-repo</id>-->
<!--<url>http://nexus.hc.to/content/repositories/pub_releases</url>-->
<!--</repository>-->
<repository> <repository>
<id>vault-repo</id> <id>jitpack.io</id>
<url>http://nexus.hc.to/content/repositories/pub_releases</url> <url>https://jitpack.io</url>
</repository> </repository>
<repository> <repository>
<id>wesjd-repo</id> <id>wesjd-repo</id>
@ -100,26 +105,20 @@
<dependency> <dependency>
<groupId>world.bentobox</groupId> <groupId>world.bentobox</groupId>
<artifactId>bentobox</artifactId> <artifactId>bentobox</artifactId>
<version>1.2.1</version> <version>1.3.0</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>world.bentobox</groupId> <groupId>world.bentobox</groupId>
<artifactId>level</artifactId> <artifactId>level</artifactId>
<version>1.2.1-SNAPSHOT</version> <version>1.3.0</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.milkbowl.vault</groupId> <groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId> <artifactId>VaultAPI</artifactId>
<version>1.7</version> <version>68f14ec</version>
<scope>provided</scope> <scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.wesjd</groupId> <groupId>net.wesjd</groupId>

View File

@ -2,13 +2,22 @@ package world.bentobox.challenges;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import world.bentobox.bentobox.api.addons.Addon; import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.configuration.Config; import world.bentobox.bentobox.api.configuration.Config;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.hooks.VaultHook; import world.bentobox.bentobox.hooks.VaultHook;
import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.challenges.commands.ChallengesCommand; import world.bentobox.challenges.commands.ChallengesCommand;
import world.bentobox.challenges.commands.ChallengesUserCommand;
import world.bentobox.challenges.commands.admin.Challenges; import world.bentobox.challenges.commands.admin.Challenges;
import world.bentobox.challenges.commands.admin.ChallengesAdminCommand;
import world.bentobox.challenges.handlers.*;
import world.bentobox.challenges.listeners.ResetListener; import world.bentobox.challenges.listeners.ResetListener;
import world.bentobox.challenges.listeners.SaveListener; import world.bentobox.challenges.listeners.SaveListener;
import world.bentobox.level.Level; import world.bentobox.level.Level;
@ -63,6 +72,21 @@ public class ChallengesAddon extends Addon {
*/ */
private static final String PERMISSION_PREFIX = "addon"; private static final String PERMISSION_PREFIX = "addon";
/**
* This flag allows to complete challenges in any part of the world. It will not limit
* player to their island. Useful for skygrid without protection flags.
*/
public static Flag CHALLENGES_WORLD_PROTECTION =
new Flag.Builder("CHALLENGES_WORLD_PROTECTION", Material.GRASS_BLOCK).type(Flag.Type.WORLD_SETTING).defaultSetting(true).build();
/**
* This flag allows to define which users can complete challenge. F.e. it can be set
* that only Island owner can complete challenge.
* By default it is set to Visitor.
*/
public static Flag CHALLENGES_ISLAND_PROTECTION =
new Flag.Builder("CHALLENGES_ISLAND_PROTECTION", Material.COMMAND_BLOCK).defaultRank(RanksManager.VISITOR_RANK).build();
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Methods // Section: Methods
@ -93,29 +117,56 @@ public class ChallengesAddon extends Addon {
return; return;
} }
// Check if addon is not disabled before.
if (this.getState().equals(State.DISABLED))
{
Bukkit.getLogger().severe("Challenges Addon is not available or disabled!");
return;
}
// Challenges Manager // Challenges Manager
this.challengesManager = new ChallengesManager(this); this.challengesManager = new ChallengesManager(this);
// Challenge import setup // Challenge import setup
this.importManager = new ChallengesImportManager(this); this.importManager = new ChallengesImportManager(this);
List<GameModeAddon> hookedGameModes = new ArrayList<>();
this.getPlugin().getAddonsManager().getGameModeAddons().forEach(gameModeAddon -> { this.getPlugin().getAddonsManager().getGameModeAddons().forEach(gameModeAddon -> {
if (!this.settings.getDisabledGameModes().contains(gameModeAddon.getDescription().getName())) if (!this.settings.getDisabledGameModes().contains(gameModeAddon.getDescription().getName()))
{ {
if (gameModeAddon.getPlayerCommand().isPresent()) if (gameModeAddon.getPlayerCommand().isPresent())
{ {
new ChallengesCommand(this, gameModeAddon.getPlayerCommand().get()); new ChallengesCommand(this, gameModeAddon.getPlayerCommand().get());
this.hooked = true; this.hooked = true;
}
hookedGameModes.add(gameModeAddon);
}
if (gameModeAddon.getAdminCommand().isPresent()) if (gameModeAddon.getAdminCommand().isPresent())
{ {
new Challenges(this, gameModeAddon.getAdminCommand().get()); new Challenges(this, gameModeAddon.getAdminCommand().get());
this.hooked = true; this.hooked = true;
} }
CHALLENGES_WORLD_PROTECTION.addGameModeAddon(gameModeAddon);
CHALLENGES_ISLAND_PROTECTION.addGameModeAddon(gameModeAddon);
} }
}); });
if (this.hooked) { if (this.hooked) {
// Create general challenge commands
if (this.settings.isUseCommonGUI())
{
new ChallengesUserCommand(this,
this.settings.getUserCommand(),
hookedGameModes);
new ChallengesAdminCommand(this,
this.settings.getAdminCommand(),
hookedGameModes);
}
// Try to find Level addon and if it does not exist, display a warning // Try to find Level addon and if it does not exist, display a warning
Optional<Addon> level = this.getAddonByName("Level"); Optional<Addon> level = this.getAddonByName("Level");
@ -148,6 +199,19 @@ public class ChallengesAddon extends Addon {
this.registerListener(new ResetListener(this)); this.registerListener(new ResetListener(this));
// Register the autosave listener. // Register the autosave listener.
this.registerListener(new SaveListener(this)); this.registerListener(new SaveListener(this));
// Register Flags
this.getPlugin().getFlagsManager().registerFlag(CHALLENGES_ISLAND_PROTECTION);
this.getPlugin().getFlagsManager().registerFlag(CHALLENGES_WORLD_PROTECTION);
// Register Request Handlers
this.registerRequestHandler(new ChallengeListRequestHandler(this));
this.registerRequestHandler(new LevelListRequestHandler(this));
this.registerRequestHandler(new ChallengeDataRequestHandler(this));
this.registerRequestHandler(new LevelDataRequestHandler(this));
this.registerRequestHandler(new CompletedChallengesRequestHandler(this));
} else { } else {
this.logError("Challenges could not hook into AcidIsland or BSkyBlock so will not do anything!"); this.logError("Challenges could not hook into AcidIsland or BSkyBlock so will not do anything!");
this.setState(State.DISABLED); this.setState(State.DISABLED);

View File

@ -3,25 +3,24 @@ package world.bentobox.challenges;
import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNull;
import java.util.ArrayList; import java.util.*;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Player;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.Database; import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
import world.bentobox.challenges.database.object.Challenge; import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.database.object.ChallengeLevel; import world.bentobox.challenges.database.object.ChallengeLevel;
import world.bentobox.challenges.database.object.ChallengesPlayerData; import world.bentobox.challenges.database.object.ChallengesPlayerData;
import world.bentobox.challenges.events.ChallengeCompletedEvent;
import world.bentobox.challenges.events.ChallengeResetAllEvent;
import world.bentobox.challenges.events.ChallengeResetEvent;
import world.bentobox.challenges.events.LevelCompletedEvent;
import world.bentobox.challenges.utils.LevelStatus; import world.bentobox.challenges.utils.LevelStatus;
@ -63,13 +62,18 @@ public class ChallengesManager
/** /**
* This is local cache that links UUID with corresponding player challenge data. * This is local cache that links UUID with corresponding player challenge data.
*/ */
private Map<UUID, ChallengesPlayerData> playerCacheData; private Map<String, ChallengesPlayerData> playerCacheData;
/** /**
* This variable allows to access ChallengesAddon. * This variable allows to access ChallengesAddon.
*/ */
private ChallengesAddon addon; private ChallengesAddon addon;
/**
* This variable allows to access ChallengesAddon settings.
*/
private Settings settings;
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Constants // Section: Constants
@ -94,6 +98,8 @@ public class ChallengesManager
public ChallengesManager(ChallengesAddon addon) public ChallengesManager(ChallengesAddon addon)
{ {
this.addon = addon; this.addon = addon;
this.settings = addon.getChallengesSettings();
// Set up the configs // Set up the configs
this.challengeDatabase = new Database<>(addon, Challenge.class); this.challengeDatabase = new Database<>(addon, Challenge.class);
this.levelDatabase = new Database<>(addon, ChallengeLevel.class); this.levelDatabase = new Database<>(addon, ChallengeLevel.class);
@ -272,8 +278,7 @@ public class ChallengesManager
{ {
try try
{ {
UUID uuid = UUID.fromString(playerData.getUniqueId()); this.playerCacheData.put(playerData.getUniqueId(), playerData);
this.playerCacheData.put(uuid, playerData);
} }
catch (Exception e) catch (Exception e)
{ {
@ -281,6 +286,7 @@ public class ChallengesManager
} }
} }
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Other storing related methods // Section: Other storing related methods
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
@ -319,24 +325,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 String uniqueID)
{ {
this.addPlayer(user.getUniqueId()); if (this.playerCacheData.containsKey(uniqueID))
}
/**
* 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))
{ {
return; return;
} }
@ -344,20 +339,20 @@ public class ChallengesManager
// The player is not in the cache // The player is not in the cache
// Check if the player exists in the database // Check if the player exists in the database
if (this.playersDatabase.objectExists(userID.toString())) if (this.playersDatabase.objectExists(uniqueID.toString()))
{ {
// Load player from database // Load player from database
ChallengesPlayerData data = this.playersDatabase.loadObject(userID.toString()); ChallengesPlayerData data = this.playersDatabase.loadObject(uniqueID.toString());
// Store in cache // Store in cache
this.playerCacheData.put(userID, data); this.playerCacheData.put(uniqueID, data);
} }
else else
{ {
// Create the player data // Create the player data
ChallengesPlayerData pd = new ChallengesPlayerData(userID.toString()); ChallengesPlayerData pd = new ChallengesPlayerData(uniqueID.toString());
this.playersDatabase.saveObject(pd); this.playersDatabase.saveObject(pd);
// Add to cache // Add to cache
this.playerCacheData.put(userID, pd); this.playerCacheData.put(uniqueID, pd);
} }
} }
@ -374,7 +369,7 @@ public class ChallengesManager
{ {
this.saveChallenges(); this.saveChallenges();
this.saveLevels(); this.saveLevels();
this.savePlayers(); this.savePlayersData();
} }
@ -417,129 +412,195 @@ 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.playerCacheData.values().forEach(this.playersDatabase::saveObject);
} }
/** /**
* This method saves player with given UUID. * This method saves player/island with given UUID.
* @param playerUUID users UUID. * @param uniqueID user/island UUID.
*/ */
private void savePlayer(UUID playerUUID) private void savePlayerData(@NonNull String uniqueID)
{ {
if (this.playerCacheData.containsKey(playerUUID)) if (this.playerCacheData.containsKey(uniqueID))
{ {
this.playersDatabase.saveObject(this.playerCacheData.get(playerUUID)); // Clean History Data
ChallengesPlayerData cachedData = this.playerCacheData.get(uniqueID);
if (this.settings.getLifeSpan() > 0)
{
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR, -this.settings.getLifeSpan());
long survivalTime = calendar.getTimeInMillis();
Iterator<LogEntry> entryIterator = cachedData.getHistory().iterator();
while (entryIterator.hasNext() && this.shouldBeRemoved(entryIterator.next(), survivalTime))
{
entryIterator.remove();
}
}
this.playersDatabase.saveObject(cachedData);
} }
} }
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// 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. * This method returns if given log entry stored time stamp is older then survivalTime.
* @param world World in which must search challenges. * @param entry Entry that must be checed.
* @return List with players who have done at least on challenge. * @param survivalTime TimeStamp value.
* @return true, if log entry is too old for database.
*/ */
public List<Player> getPlayers(World world) private boolean shouldBeRemoved(LogEntry entry, long survivalTime)
{ {
List<String> allChallengeList = this.getAllChallengesNames(world); return entry.getTimestamp() < survivalTime;
// 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 user of type User
* @param challenge - Challenge * @param world of type World
* @return UUID
*/
private String 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 String 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 "";
}
else
{
// Unfortunately, island does not store UUID, just a string.
return island.getUniqueId();
}
}
else
{
return userID.toString();
}
}
/**
* 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 * @return - true if completed
*/ */
public boolean isChallengeComplete(User user, Challenge challenge) private long getChallengeTimes(String 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 storageDataID - PlayerData ID object who must be checked.
* @param challenge - Challenge * @param challengeID - Challenge uniqueID
* @return - true if completed * @return - true if completed
*/ */
public boolean isChallengeComplete(UUID user, Challenge challenge) private boolean isChallengeComplete(String 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 storageDataID - playerData ID
* @param challenge - Challenge * @param challengeID - challengeID
* @return - true if completed
*/ */
public boolean isChallengeComplete(UUID user, String challenge) private void setChallengeComplete(@NonNull String storageDataID, @NonNull String challengeID)
{ {
this.addPlayer(user); this.addPlayerData(storageDataID);
return this.playerCacheData.get(user).isChallengeDone(challenge); 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 storageDataID - playerData ID
* @param world - world * @param challengeID - challenge ID
*/
private void resetChallenge(@NonNull String 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 String 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 * @return Level status - how many challenges still to do on which level
*/ */
public List<LevelStatus> getChallengeLevelStatus(User user, World world) private List<LevelStatus> getAllChallengeLevelStatus(String storageDataID, String worldName)
{ {
return this.getChallengeLevelStatus(user.getUniqueId(), Util.getWorld(world).getName()); this.addPlayerData(storageDataID);
} ChallengesPlayerData playerData = this.playerCacheData.get(storageDataID);
List<ChallengeLevel> challengeLevelList = this.getLevels(worldName);
/**
* 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<LevelStatus> result = new ArrayList<>(); List<LevelStatus> result = new ArrayList<>();
@ -547,7 +608,7 @@ public class ChallengesManager
ChallengeLevel previousLevel = null; ChallengeLevel previousLevel = null;
int doneChallengeCount = 0; 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) for (ChallengeLevel level : challengeLevelList)
{ {
// To find how many challenges user still must do in previous level, we must // To find how many challenges user still must do in previous level, we must
@ -574,146 +635,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(User user, Challenge challenge)
{
this.addPlayer(user);
this.playerCacheData.get(user.getUniqueId()).setChallengeDone(challenge.getUniqueId());
// Save
this.savePlayer(user.getUniqueId());
}
/**
* Reset the challenge to zero time / not done
*
* @param user - user
* @param challenge - challenge
*/
public void resetChallenge(@NonNull User user, @NonNull Challenge challenge)
{
this.addPlayer(user);
this.playerCacheData.get(user.getUniqueId()).setChallengeTimes(challenge.getUniqueId(), 0);
// Save
this.savePlayer(user.getUniqueId());
}
/**
* 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. * 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. * @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 String storageDataID, @NonNull ChallengeLevel level)
{ {
List<LevelStatus> statusList = this.getChallengeLevelStatus(user, level.getWorld()); List<LevelStatus> statusList = this.getAllChallengeLevelStatus(storageDataID, level.getWorld());
for (LevelStatus status : statusList) for (LevelStatus status : statusList)
{ {
@ -727,6 +657,374 @@ 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 String 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 String 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 String 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 String storageDataID, @NonNull String levelID)
{
this.addPlayerData(storageDataID);
this.playerCacheData.get(storageDataID).addCompletedLevel(levelID);
// Save
this.savePlayerData(storageDataID);
}
/**
* This methods adds given log entry to database.
*
* @param storageDataID of type UUID
* @param entry of type LogEntry
*/
private void addLogEntry(@NonNull String storageDataID, @NonNull LogEntry entry)
{
// Store data only if it is enabled.
if (this.settings.isStoreHistory())
{
this.addPlayerData(storageDataID);
this.playerCacheData.get(storageDataID).addHistoryRecord(entry);
// 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)
{
String storageID = this.getDataUniqueID(userID, Util.getWorld(world));
this.setChallengeComplete(storageID, challenge.getUniqueId());
this.addLogEntry(storageID, new LogEntry.Builder("COMPLETE").
data("user-id", userID.toString()).
data("challenge-id", challenge.getUniqueId()).
build());
// Fire event that user completes challenge
Bukkit.getServer().getPluginManager().callEvent(
new ChallengeCompletedEvent(challenge.getUniqueId(),
userID,
false,
1));
}
/**
* 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.
* @param adminID - admin who sets challenge as completed.
*/
public void setChallengeComplete(UUID userID, World world, Challenge challenge, UUID adminID)
{
String storageID = this.getDataUniqueID(userID, Util.getWorld(world));
this.setChallengeComplete(storageID, challenge.getUniqueId());
this.addLogEntry(storageID, new LogEntry.Builder("COMPLETE").
data("user-id", userID.toString()).
data("challenge-id", challenge.getUniqueId()).
data("admin-id", adminID == null ? "OP" : adminID.toString()).
build());
// Fire event that admin completes user challenge
Bukkit.getServer().getPluginManager().callEvent(
new ChallengeCompletedEvent(challenge.getUniqueId(),
userID,
true,
1));
}
/**
* 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, UUID adminID)
{
String storageID = this.getDataUniqueID(userID, Util.getWorld(world));
this.resetChallenge(storageID, challenge.getUniqueId());
this.addLogEntry(storageID, new LogEntry.Builder("RESET").
data("user-id", userID.toString()).
data("challenge-id", challenge.getUniqueId()).
data("admin-id", adminID == null ? "RESET" : adminID.toString()).
build());
// Fire event that admin resets user challenge
Bukkit.getServer().getPluginManager().callEvent(
new ChallengeResetEvent(challenge.getUniqueId(),
userID,
true,
"RESET"));
}
/**
* 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)
{
this.resetAllChallenges(user.getUniqueId(), world, null);
}
/**
* This method resets all challenges in given world.
* @param userID - Targeted user.
* @param world - World where challenges must be reset.
* @param adminID - admin iD
*/
public void resetAllChallenges(UUID userID, World world, UUID adminID)
{
world = Util.getWorld(world);
String storageID = this.getDataUniqueID(userID, 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());
// Fire event that admin resets user challenge
Bukkit.getServer().getPluginManager().callEvent(
new ChallengeResetAllEvent(world.getName(),
userID,
adminID != null,
adminID == null ? "ISLAND_RESET" : "RESET_ALL"));
}
/**
* 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)
{
return this.isLevelCompleted(this.getDataUniqueID(user, Util.getWorld(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)
{
return this.isLevelUnlocked(this.getDataUniqueID(user, Util.getWorld(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)
{
String storageID = this.getDataUniqueID(user, Util.getWorld(world));
this.setLevelComplete(storageID, level.getUniqueId());
this.addLogEntry(storageID, new LogEntry.Builder("COMPLETE_LEVEL").
data("user-id", user.getUniqueId().toString()).
data("level", level.getUniqueId()).build());
// Fire event that user completes level
Bukkit.getServer().getPluginManager().callEvent(
new LevelCompletedEvent(level.getUniqueId(),
user.getUniqueId(),
false));
}
/**
* 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)
{
return this.validateLevelCompletion(this.getDataUniqueID(user, Util.getWorld(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)
{
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.
* @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)
{
return this.getChallengeLevelStatus(this.getDataUniqueID(user, Util.getWorld(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 // Section: Challenges related methods
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
@ -877,6 +1175,7 @@ public class ChallengesManager
/** /**
* This method removes challenge from cache and memory. * 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. * @param challenge that must be removed.
*/ */
public void deleteChallenge(Challenge challenge) public void deleteChallenge(Challenge challenge)
@ -1067,6 +1366,7 @@ public class ChallengesManager
/** /**
* This method removes challenge level from cache and memory. * 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. * @param challengeLevel Level that must be removed.
*/ */
public void deleteChallengeLevel(ChallengeLevel challengeLevel) public void deleteChallengeLevel(ChallengeLevel challengeLevel)
@ -1108,8 +1408,8 @@ public class ChallengesManager
} }
}); });
this.playerCacheData.put(UUID.fromString(playerData.getUniqueId()), playerData); this.playerCacheData.put(playerData.getUniqueId(), playerData);
this.savePlayer(UUID.fromString(playerData.getUniqueId())); this.savePlayerData(playerData.getUniqueId());
}); });
} }
} }

View File

@ -1,170 +0,0 @@
package world.bentobox.challenges;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionType;
/**
* Class that parses a string into an ItemStack
* Used for converting config file entries to objects
* @author tastybento
*
* @deprecated
* @see world.bentobox.bentobox.util.ItemParser#parse(String)
*/
@Deprecated
public class ParseItem {
private final ItemStack item;
private ChallengesAddon addon;
public ParseItem(ChallengesAddon addon, String s) {
this.addon = addon;
item = parseItem(s);
}
/**
* Parse a string into an itemstack
* @param s - input string
* @return ItemStack or null if parsing failed
*/
private ItemStack parseItem(String s) {
String[] part = s.split(":");
if (part.length > 0 && (part[0].equalsIgnoreCase("POTION") || part[0].equalsIgnoreCase("TIPPED_ARROW"))) {
return potion(s, part);
}
// Material:Qty
if (part.length == 2) {
return two(s, part);
} else if (part.length == 3) {
return three(s, part);
}
showError(s);
return null;
}
private ItemStack potion(String s, String[] part) {
/*
* # Format POTION:NAME:<LEVEL>:<EXTENDED>:<SPLASH/LINGER>:QTY
# LEVEL, EXTENDED, SPLASH, LINGER are optional.
# LEVEL is a number, 1 or 2
# LINGER is for V1.9 servers and later
# Examples:
# POTION:STRENGTH:1:EXTENDED:SPLASH:1
# POTION:INSTANT_DAMAGE:2::LINGER:2
# POTION:JUMP:2:NOTEXTENDED:NOSPLASH:1
# POTION:WEAKNESS::::1 - any weakness potion
*/
ItemStack result = new ItemStack(Material.POTION);
if (part[0].equalsIgnoreCase("TIPPED_ARROW")) {
result = new ItemStack(Material.TIPPED_ARROW);
} else if (part[0].equalsIgnoreCase("SPLASH_POTION")) {
result = new ItemStack(Material.SPLASH_POTION);
} else if (part[0].equalsIgnoreCase("LINGERING_POTION")) {
result = new ItemStack(Material.LINGERING_POTION);
}
int reqAmount = 0;
String amount = "1";
String level = "1";
String ext = "";
String splashLinger = "";
switch (part.length) {
case 3:
amount = part[2];
break;
case 4:
level = part[2];
amount = part[3];
break;
case 5:
level = part[2];
ext = part[3];
amount = part[4];
break;
case 6:
level = part[2];
ext = part[3];
splashLinger = part[4];
amount = part[5];
break;
default:
// Because I don't know!
return null;
}
// Parse the quantity
try {
reqAmount = Integer.parseInt(amount);
} catch (Exception e) {
addon.getLogger().severe(() -> "Could not parse the quantity of the potion or tipped arrow " + s);
return null;
}
result.setAmount(reqAmount);
// Parse the legacy splash / linger
if (splashLinger.equalsIgnoreCase("SPLASH")) {
result = new ItemStack(Material.SPLASH_POTION);
} else if (splashLinger.equalsIgnoreCase("LINGER")) {
result = new ItemStack(Material.LINGERING_POTION);
}
// Parse the type of potion
PotionMeta potionMeta = (PotionMeta)(result.getItemMeta());
PotionType type = PotionType.valueOf(part[1].toUpperCase());
boolean isUpgraded = (level.isEmpty() || level.equalsIgnoreCase("1")) ? false: true;
boolean isExtended = ext.equalsIgnoreCase("EXTENDED") ? true : false;
PotionData data = new PotionData(type, isExtended, isUpgraded);
potionMeta.setBasePotionData(data);
result.setItemMeta(potionMeta);
return result;
}
private ItemStack three(String s, String[] part) {
// Rearrange
String[] twoer = {part[0], part[2]};
ItemStack result = two(s, twoer);
if (result == null) {
showError(s);
return null;
}
return result;
}
private void showError(String s) {
addon.getLogger().severe(() -> "Problem with " + s + " in config.yml!");
}
private ItemStack two(String s, String[] part) {
int reqAmount = 0;
try {
reqAmount = Integer.parseInt(part[1]);
} catch (Exception e) {
showError(s);
return null;
}
Material reqItem = Material.getMaterial(part[0].toUpperCase() + "_ITEM");
if (reqItem == null) {
// Try the item
reqItem = Material.getMaterial(part[0].toUpperCase());
}
if (reqItem == null) {
showError(s);
return null;
}
return new ItemStack(reqItem, reqAmount);
}
/**
* @return the item
*/
public ItemStack getItem() {
return item;
}
}

View File

@ -1,6 +1,8 @@
package world.bentobox.challenges; package world.bentobox.challenges;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -19,37 +21,73 @@ import world.bentobox.bentobox.database.objects.DataObject;
public class Settings implements DataObject public class Settings implements DataObject
{ {
@ConfigComment("") @ConfigComment("")
@ConfigComment("Reset Challenges - if this is true, player's challenges will reset when they") @ConfigComment("Allows to define common challenges command that will open User GUI")
@ConfigComment("reset an island or if they are kicked or leave a team. Prevents exploiting the") @ConfigComment("with all GameMode selection or Challenges from user world.")
@ConfigComment("challenges by doing them repeatedly.") @ConfigComment("This will not affect /{gamemode_user} challenges command.")
@ConfigEntry(path = "reset-challenges") @ConfigEntry(path = "commands.user", needsReset = true)
private boolean resetChallenges = true; private String userCommand = "challenges c";
@ConfigComment("") @ConfigComment("")
@ConfigComment("Broadcast 1st time challenge completion messages to all players.") @ConfigComment("Allows to define common challenges command that will open Admin GUI")
@ConfigComment("Change to false if the spam becomes too much.") @ConfigComment("with all GameMode selection.")
@ConfigEntry(path = "broadcast-messages") @ConfigComment("This will not affect /{gamemode_admin} challenges command.")
private boolean broadcastMessages = true; @ConfigEntry(path = "commands.admin", needsReset = true)
private String adminCommand = "challengesadmin chadmin";
@ConfigComment("")
@ConfigComment("This enables/disables common command that will be independent from")
@ConfigComment("all GameModes. For admins it will open selection with all GameModes")
@ConfigComment("(unless there is one), but for users it will open GUI that corresponds")
@ConfigComment("to their world (unless it is specified other way in Admin GUI).")
@ConfigEntry(path = "commands.single-gui", needsReset = true)
private boolean useCommonGUI = false;
@ConfigComment("")
@ConfigComment("This allows for admins to define which GUI will be opened for admins")
@ConfigComment("when users calls single-gui command.")
@ConfigComment("Acceptable values:")
@ConfigComment(" - CURRENT_WORLD - will open GUI that corresponds to user location.")
@ConfigComment(" - GAMEMODE_LIST - will open GUI with all installed game modes.")
@ConfigEntry(path = "commands.single-gamemode")
private GuiMode userGuiMode = GuiMode.CURRENT_WORLD;
@ConfigComment("")
@ConfigComment("This indicate if player challenges data history will be stored or not.")
@ConfigEntry(path = "history.store-history-data")
private boolean storeHistory = false;
@ConfigComment("")
@ConfigComment("This allows to specify an amount of time in days when history data will")
@ConfigComment("be removed. 0 means that data will not be removed.")
@ConfigEntry(path = "history.lifespan")
private int lifeSpan = 14;
@ConfigComment("") @ConfigComment("")
@ConfigComment("Remove non-repeatable challenges from the challenge GUI when complete.") @ConfigComment("Remove non-repeatable challenges from the challenge GUI when complete.")
@ConfigEntry(path = "remove-complete-one-time-challenges") @ConfigEntry(path = "gui-settings.remove-complete-one-time-challenges")
private boolean removeCompleteOneTimeChallenges = false; private boolean removeCompleteOneTimeChallenges = false;
@ConfigComment("") @ConfigComment("")
@ConfigComment("Add enchanted glow to completed challenges") @ConfigComment("Add enchanted glow to completed challenges")
@ConfigEntry(path = "add-completed-glow") @ConfigEntry(path = "gui-settings.add-completed-glow")
private boolean addCompletedGlow = true; private boolean addCompletedGlow = true;
@ConfigComment("")
@ConfigComment("This allows to change default locked level icon. This option may be")
@ConfigComment("overwritten by each challenge level. If challenge level has specified")
@ConfigComment("their locked level icon, then it will be used, instead of this one.")
@ConfigEntry(path = "gui-settings.locked-level-icon")
private ItemStack lockedLevelIcon = new ItemStack(Material.BOOK);
@ConfigComment("") @ConfigComment("")
@ConfigComment("This indicate if free challenges must be at the start (true) or at the end (false) of list.") @ConfigComment("This indicate if free challenges must be at the start (true) or at the end (false) of list.")
@ConfigEntry(path = "free-challenges-first") @ConfigEntry(path = "gui-settings.free-challenges-first")
private boolean freeChallengesFirst = true; private boolean freeChallengesFirst = true;
@ConfigComment("") @ConfigComment("")
@ConfigComment("This allows to change lore description line length. By default it is 25, but some server") @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.") @ConfigComment("owners may like it to be larger.")
@ConfigEntry(path = "lore-length") @ConfigEntry(path = "gui-settings.lore-length")
private int loreLineLength = 25; private int loreLineLength = 25;
@ConfigComment("") @ConfigComment("")
@ -68,7 +106,7 @@ public class Settings implements DataObject
@ConfigComment(" - R - Reward String: '*.experience-reward', '*.money-reward', '*.not-repeatable'") @ConfigComment(" - R - Reward String: '*.experience-reward', '*.money-reward', '*.not-repeatable'")
@ConfigComment("By adding 'i' after Q or R (requirements and rewards) will display list of items, blocks") @ConfigComment("By adding 'i' after Q or R (requirements and rewards) will display list of items, blocks")
@ConfigComment("and entities that are defined in challenge and can be customized under 'challenges.gui.description.*'") @ConfigComment("and entities that are defined in challenge and can be customized under 'challenges.gui.description.*'")
@ConfigEntry(path = "challenge-lore-message") @ConfigEntry(path = "gui-settings.challenge-lore-message")
private String challengeLoreMessage = "LSTDEQiWRi"; private String challengeLoreMessage = "LSTDEQiWRi";
@ConfigComment("") @ConfigComment("")
@ -84,9 +122,27 @@ public class Settings implements DataObject
@ConfigComment(" - R - Reward String: '*.experience-reward', '*.money-reward', '*.not-repeatable'") @ConfigComment(" - R - Reward String: '*.experience-reward', '*.money-reward', '*.not-repeatable'")
@ConfigComment("By adding 'i' after R (rewards) will display list of items that are defined in challenge") @ConfigComment("By adding 'i' after R (rewards) will display list of items that are defined in challenge")
@ConfigComment("and can be customized under 'challenges.gui.description.*'") @ConfigComment("and can be customized under 'challenges.gui.description.*'")
@ConfigEntry(path = "level-lore-message") @ConfigEntry(path = "gui-settings.level-lore-message")
private String levelLoreMessage = "STDARi"; private String levelLoreMessage = "STDARi";
@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("Reset Challenges - if this is true, player's challenges will reset when users")
@ConfigComment("reset an island or if users are kicked or leave a team. Prevents exploiting the")
@ConfigComment("challenges by doing them repeatedly.")
@ConfigEntry(path = "reset-challenges")
private boolean resetChallenges = true;
@ConfigComment("")
@ConfigComment("Broadcast 1st time challenge completion messages to all players.")
@ConfigComment("Change to false if the spam becomes too much.")
@ConfigEntry(path = "broadcast-messages")
private boolean broadcastMessages = true;
@ConfigComment("") @ConfigComment("")
@ConfigComment("This list stores GameModes in which Challenges addon should not work.") @ConfigComment("This list stores GameModes in which Challenges addon should not work.")
@ConfigComment("To disable addon it is necessary to write its name in new line that starts with -. Example:") @ConfigComment("To disable addon it is necessary to write its name in new line that starts with -. Example:")
@ -105,7 +161,8 @@ public class Settings implements DataObject
* Configuration version * Configuration version
*/ */
@ConfigComment("") @ConfigComment("")
private String configVersion = "v1.1"; private String configVersion = "v2";
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Methods // Section: Methods
@ -213,6 +270,107 @@ public class Settings implements DataObject
} }
/**
* This method returns the storeAsIslandData object.
* @return the storeAsIslandData object.
*/
public boolean isStoreAsIslandData()
{
return storeAsIslandData;
}
/**
* This method returns the storeHistory object.
* @return the storeHistory object.
*/
public boolean isStoreHistory()
{
return storeHistory;
}
/**
* This method returns the userCommand value.
* @return the value of userCommand.
*/
public String getUserCommand()
{
return userCommand;
}
/**
* This method returns the adminCommand value.
* @return the value of adminCommand.
*/
public String getAdminCommand()
{
return adminCommand;
}
/**
* This method returns the useCommonGUI value.
* @return the value of useCommonGUI.
*/
public boolean isUseCommonGUI()
{
return useCommonGUI;
}
/**
* This method returns the userGuiMode value.
* @return the value of userGuiMode.
*/
public GuiMode getUserGuiMode()
{
return userGuiMode;
}
/**
* This method returns the lifeSpan value.
* @return the value of lifeSpan.
*/
public int getLifeSpan()
{
return lifeSpan;
}
/**
* This method returns the lockedLevelIcon value.
* @return the value of lockedLevelIcon.
*/
public ItemStack getLockedLevelIcon()
{
return lockedLevelIcon.clone();
}
/**
* This method sets the lockedLevelIcon value.
* @param lockedLevelIcon the lockedLevelIcon new value.
*
*/
public void setLockedLevelIcon(ItemStack lockedLevelIcon)
{
this.lockedLevelIcon = lockedLevelIcon;
}
/**
* This method sets the userGuiMode value.
* @param userGuiMode the userGuiMode new value.
*/
public void setUserGuiMode(GuiMode userGuiMode)
{
this.userGuiMode = userGuiMode;
}
/** /**
* This method sets the configVersion object value. * This method sets the configVersion object value.
* @param configVersion the configVersion object new value. * @param configVersion the configVersion object new value.
@ -312,4 +470,86 @@ public class Settings implements DataObject
{ {
this.loreLineLength = loreLineLength; 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;
}
/**
* This method sets the storeHistory object value.
* @param storeHistory the storeHistory object new value.
*/
public void setStoreHistory(boolean storeHistory)
{
this.storeHistory = storeHistory;
}
/**
* This method sets the userCommand value.
* @param userCommand the userCommand new value.
*/
public void setUserCommand(String userCommand)
{
this.userCommand = userCommand;
}
/**
* This method sets the adminCommand value.
* @param adminCommand the adminCommand new value.
*/
public void setAdminCommand(String adminCommand)
{
this.adminCommand = adminCommand;
}
/**
* This method sets the useCommonGUI value.
* @param useCommonGUI the useCommonGUI new value.
*/
public void setUseCommonGUI(boolean useCommonGUI)
{
this.useCommonGUI = useCommonGUI;
}
/**
* This method sets the lifeSpan value.
* @param lifeSpan the lifeSpan new value.
*
*/
public void setLifeSpan(int lifeSpan)
{
this.lifeSpan = lifeSpan;
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum holds all possible values for Gui Opening for users.
*/
public enum GuiMode
{
/**
* Opens user GUI with list of all GameModes.
*/
GAMEMODE_LIST,
/**
* Opens user GUI with challenges in given world.
*/
CURRENT_WORLD
}
} }

View File

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

View File

@ -0,0 +1,106 @@
package world.bentobox.challenges.commands;
import java.util.List;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.Settings;
import world.bentobox.challenges.panel.GameModesGUI;
/**
* This class provides all necessary thing to implement challenges user command
*/
public class ChallengesUserCommand extends CompositeCommand
{
/**
* Constructor that inits command with given string.
* @param addon Challenges Addon
* @param commands String that contains main command and its alias separated via whitespace.
* @param gameModeAddons List with GameModes where challenges addon operates.
*/
public ChallengesUserCommand(ChallengesAddon addon, String commands, List<GameModeAddon> gameModeAddons)
{
super(addon,
commands.split(" ")[0],
commands.split(" "));
this.gameModeAddons = gameModeAddons;
this.addon = addon;
}
/**
* {@inheritDoc}
*/
@Override
public void setup()
{
this.setOnlyPlayer(true);
this.setPermission("challenges");
this.setParametersHelp("challenges.commands.user.parameters");
this.setDescription("challenges.commands.user.description");
}
/**
* {@inheritDoc}
*/
@Override
public boolean execute(User user, String label, List<String> args)
{
// It is not necessary to check 0, as in that case addon will not be hooked.
if (this.gameModeAddons.size() == 1)
{
this.gameModeAddons.get(0).getPlayerCommand().ifPresent(compositeCommand ->
user.performCommand(compositeCommand.getTopLabel() + " challenges"));
return true;
}
else if (this.addon.getChallengesSettings().getUserGuiMode() == Settings.GuiMode.CURRENT_WORLD)
{
// Find GameMode and run command
for (GameModeAddon addon : this.gameModeAddons)
{
if (addon.inWorld(user.getWorld()))
{
addon.getPlayerCommand().ifPresent(compositeCommand ->
user.performCommand(compositeCommand.getTopLabel() + " challenges"));
return true;
}
}
}
else if (this.addon.getChallengesSettings().getUserGuiMode() == Settings.GuiMode.GAMEMODE_LIST)
{
new GameModesGUI(this.addon,
this.getWorld(),
user,
this.getTopLabel(),
this.getPermissionPrefix(),
false,
this.gameModeAddons).build();
return true;
}
return false;
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* List with hooked GameMode addons.
*/
private List<GameModeAddon> gameModeAddons;
/**
* Challenges addon for easier operations.
*/
private ChallengesAddon addon;
}

View File

@ -0,0 +1,87 @@
package world.bentobox.challenges.commands.admin;
import java.util.List;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.panel.GameModesGUI;
/**
* This class provides all necessary thing to implement challenges admin command
*/
public class ChallengesAdminCommand extends CompositeCommand
{
/**
* Constructor that inits command with given string.
* @param addon Challenges Addon
* @param commands String that contains main command and its alias separated via whitespace.
* @param gameModeAddons List with GameModes where challenges addon operates.
*/
public ChallengesAdminCommand(ChallengesAddon addon, String commands, List<GameModeAddon> gameModeAddons)
{
super(addon,
commands.split(" ")[0],
commands.split(" "));
this.gameModeAddons = gameModeAddons;
this.addon = addon;
}
/**
* {@inheritDoc}
*/
@Override
public void setup()
{
this.setPermission("admin.challenges");
this.setParametersHelp("challenges.commands.admin.main.parameters");
this.setDescription("challenges.commands.admin.main.description");
}
/**
* {@inheritDoc}
*/
@Override
public boolean execute(User user, String label, List<String> args)
{
// For single game mode just open correct gui.
if (this.gameModeAddons.size() == 1)
{
this.gameModeAddons.get(0).getAdminCommand().ifPresent(compositeCommand ->
user.performCommand(compositeCommand.getTopLabel() + " challenges"));
}
else
{
new GameModesGUI(this.addon,
this.getWorld(),
user,
this.getTopLabel(),
this.getPermissionPrefix(),
true,
this.gameModeAddons).build();
}
return true;
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable stores challenges addon.
*/
private ChallengesAddon addon;
/**
* This variable stores List with game modes where challenges addon are hooked in.
*/
private List<GameModeAddon> gameModeAddons;
}

View File

@ -13,6 +13,7 @@ import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@Deprecated
public class CompleteChallenge extends CompositeCommand { public class CompleteChallenge extends CompositeCommand {
private ChallengesManager manager; private ChallengesManager manager;
@ -56,8 +57,7 @@ public class CompleteChallenge extends CompositeCommand {
return false; return false;
} }
// Complete challenge // Complete challenge
User target = User.getInstance(targetUUID); manager.setChallengeComplete(targetUUID, this.getWorld(), this.manager.getChallenge(args.get(1)), user.getUniqueId());
manager.setChallengeComplete(target, this.manager.getChallenge(args.get(1)));
user.sendMessage("general.success"); user.sendMessage("general.success");
return true; return true;
} }

View File

@ -1,52 +0,0 @@
package world.bentobox.challenges.commands.admin;
import java.util.List;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.panel.CreateChallengeListener;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.user.User;
/**
* @deprecated Challenges can be creaded via GUI.
*/
@Deprecated
public class CreateChallenge extends CompositeCommand {
/**
* Admin command to make challenges
* @param parent
*/
public CreateChallenge(Addon addon, CompositeCommand parent) {
super(addon, parent, "create");
new CreateSurrounding(addon, this);
}
@Override
public void setup() {
this.setOnlyPlayer(true);
this.setPermission("admin.challenges");
this.setParametersHelp("challenges.commands.admin.create.parameters");
this.setDescription("challenges.commands.admin.create.description");
}
@Override
public boolean execute(User user, String label, List<String> args) {
if (args.isEmpty()) {
user.sendMessage("challenges.errors.no-name");
return false;
}
new PanelBuilder()
.name(args.get(0))
.size(49)
.listener(new CreateChallengeListener((ChallengesAddon) getAddon(), user))
.user(user)
.build();
return true;
}
}

View File

@ -1,125 +0,0 @@
package world.bentobox.challenges.commands.admin;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
/**
* Command to create a surrounding type challenge
* @author tastybento
* @deprecated Required blocks can be added via GUI. Not necessary.
*/
@Deprecated
public class CreateSurrounding extends CompositeCommand implements Listener {
HashMap<UUID,SurroundChallengeBuilder> inProgress = new HashMap<>();
/**
* Admin command to make surrounding challenges
* @param parent
*/
public CreateSurrounding(Addon addon, CompositeCommand parent) {
super(addon, parent, "surrounding");
addon.getServer().getPluginManager().registerEvents(this, addon.getPlugin());
}
@Override
public void setup() {
this.setOnlyPlayer(true);
this.setPermission("admin.challenges");
this.setParametersHelp("challenges.commands.admin.surrounding.parameters");
this.setDescription("challenges.commands.admin.surrounding.description");
}
@Override
public boolean execute(User user, String label, List<String> args) {
if (args.isEmpty()) {
user.sendMessage("challenges.errors.no-name");
return false;
}
// Tell user to hit objects to add to the surrounding object requirements
user.sendMessage("challenges.messages.admin.hit-things");
inProgress.put(user.getUniqueId(), new SurroundChallengeBuilder((ChallengesAddon) getAddon()).owner(user).name(args.get(0)));
return true;
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent e) {
e.setCancelled(inProgress.containsKey(e.getPlayer().getUniqueId()) ? true : false);
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onPlayerQuit(PlayerQuitEvent e) {
inProgress.remove(e.getPlayer().getUniqueId());
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public boolean onPlayerInteract(PlayerInteractEvent e) {
if (e.getAction().equals(Action.LEFT_CLICK_BLOCK) && inProgress.containsKey(e.getPlayer().getUniqueId())) {
// Prevent damage
e.setCancelled(true);
inProgress.get(e.getPlayer().getUniqueId()).addBlock(e.getClickedBlock().getType());
User.getInstance(e.getPlayer()).sendMessage("challenges.messages.admin.you-added", "[thing]", Util.prettifyText(e.getClickedBlock().getType().toString()));
return true;
}
if (e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
return finished(e, e.getPlayer().getUniqueId());
}
return false;
}
private boolean finished(Cancellable e, UUID uuid) {
if (inProgress.containsKey(uuid)) {
e.setCancelled(true);
boolean status = inProgress.get(uuid).build();
if (status) {
inProgress.get(uuid).getOwner().sendMessage("challenges.messages.admin.challenge-created", "[challenge]", inProgress.get(uuid).getName());
}
inProgress.remove(uuid);
return status;
}
return false;
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public boolean onPlayerInteract(PlayerInteractAtEntityEvent e) {
return finished(e, e.getPlayer().getUniqueId());
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public boolean onLeft(EntityDamageByEntityEvent e) {
if (!(e.getDamager() instanceof Player)) {
return false;
}
Player player = (Player)e.getDamager();
if (inProgress.containsKey(player.getUniqueId())) {
// Prevent damage
e.setCancelled(true);
inProgress.get(player.getUniqueId()).addEntity(e.getEntityType());
User.getInstance(player).sendMessage("challenges.messages.admin.you-added", "[thing]", Util.prettifyText(e.getEntityType().toString()));
return true;
}
return false;
}
}

View File

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

View File

@ -1,84 +0,0 @@
package world.bentobox.challenges.commands.admin;
import java.util.EnumMap;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.bentobox.api.user.User;
/**
* Enables the state of a Surrounding Challenge to be stored as it is built
* @author tastybento
* @deprecated Levels and challenges can be created via GUI. Not necessary command.
*/
@Deprecated
public class SurroundChallengeBuilder {
private ChallengesAddon addon;
private String name;
private User owner;
private Map<Material, Integer> reqBlocks = new EnumMap<>(Material.class);
private Map<EntityType, Integer> reqEntities = new EnumMap<>(EntityType.class);
public SurroundChallengeBuilder(ChallengesAddon addon) {
this.addon = addon;
}
SurroundChallengeBuilder name(String name) {
this.name = name;
return this;
}
SurroundChallengeBuilder owner(User user) {
this.owner = user;
return this;
}
SurroundChallengeBuilder addBlock(Material mat) {
reqBlocks.computeIfPresent(mat, (material, amount) -> amount + 1);
reqBlocks.putIfAbsent(mat, 1);
return this;
}
SurroundChallengeBuilder addEntity(EntityType ent) {
reqEntities.computeIfPresent(ent, (type, amount) -> amount + 1);
reqEntities.putIfAbsent(ent, 1);
return this;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the owner
*/
public User getOwner() {
return owner;
}
/**
* @return the reqBlocks
*/
public Map<Material, Integer> getReqBlocks() {
return reqBlocks;
}
/**
* @return the reqEntities
*/
public Map<EntityType, Integer> getReqEntities() {
return reqEntities;
}
public boolean build() {
return false; //addon.getChallengesManager().createSurroundingChallenge(this);
}
}

View File

@ -47,6 +47,12 @@ public class ChallengeLevel implements DataObject, Comparable<ChallengeLevel>
@Expose @Expose
private ItemStack icon = new ItemStack(Material.BOOK); private ItemStack icon = new ItemStack(Material.BOOK);
@ConfigComment("")
@ConfigComment("ItemStack that represents current level when it is locked. Will be used")
@ConfigComment("as icon in GUIs. Will overwrite icon defined in addon settings.")
@Expose
private ItemStack lockedIcon = null;
@ConfigComment("") @ConfigComment("")
@ConfigComment("World that this level applies in. String.") @ConfigComment("World that this level applies in. String.")
@Expose @Expose
@ -142,6 +148,16 @@ public class ChallengeLevel implements DataObject, Comparable<ChallengeLevel>
} }
/**
* This method returns the closedIcon value.
* @return the value of closedIcon.
*/
public ItemStack getLockedIcon()
{
return lockedIcon;
}
/** /**
* This method returns the world value. * This method returns the world value.
* @return the value of world. * @return the value of world.
@ -282,6 +298,17 @@ public class ChallengeLevel implements DataObject, Comparable<ChallengeLevel>
} }
/**
* This method sets the closedIcon value.
* @param closedIcon the closedIcon new value.
*
*/
public void setLockedIcon(ItemStack closedIcon)
{
this.lockedIcon = closedIcon;
}
/** /**
* This method sets the world value. * This method sets the world value.
* @param world the world new value. * @param world the world new value.

View File

@ -2,14 +2,14 @@ package world.bentobox.challenges.database.object;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import org.bukkit.World; import org.eclipse.jdt.annotation.NonNull;
import java.util.HashMap; import java.util.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.database.objects.DataObject; import world.bentobox.bentobox.database.objects.DataObject;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.database.objects.adapters.Adapter;
import world.bentobox.bentobox.database.objects.adapters.LogEntryListAdapter;
/** /**
* Stores the player's challenge situation * Stores the player's challenge situation
@ -68,6 +68,13 @@ public class ChallengesPlayerData implements DataObject
@Expose @Expose
private Set<String> levelsDone = new HashSet<>(); private Set<String> levelsDone = new HashSet<>();
/**
* Stores history about challenge completion.
*/
@Adapter(LogEntryListAdapter.class)
@Expose
private List<LogEntry> history = new LinkedList<>();
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Getters // Section: Getters
@ -115,6 +122,16 @@ public class ChallengesPlayerData implements DataObject
} }
/**
* This method returns the history object.
* @return the history object.
*/
public List<LogEntry> getHistory()
{
return history;
}
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Setters // Section: Setters
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
@ -164,6 +181,16 @@ public class ChallengesPlayerData implements DataObject
} }
/**
* This method sets the history object value.
* @param history the history object new value.
*/
public void setHistory(List<LogEntry> history)
{
this.history = history;
}
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Other Methods // Section: Other Methods
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
@ -172,11 +199,10 @@ public class ChallengesPlayerData implements DataObject
/** /**
* Resets all challenges and levels in world for this player * 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(@NonNull String worldName)
{ {
String worldName = Util.getWorld(world).getName();
challengeStatus.keySet().removeIf(n -> n.startsWith(worldName)); challengeStatus.keySet().removeIf(n -> n.startsWith(worldName));
challengesTimestamp.keySet().removeIf(n -> n.startsWith(worldName)); challengesTimestamp.keySet().removeIf(n -> n.startsWith(worldName));
levelsDone.removeIf(n -> n.startsWith(worldName)); levelsDone.removeIf(n -> n.startsWith(worldName));
@ -189,7 +215,7 @@ public class ChallengesPlayerData implements DataObject
* *
* @param challengeName - unique challenge name * @param challengeName - unique challenge name
*/ */
public void setChallengeDone(String challengeName) public void setChallengeDone(@NonNull String challengeName)
{ {
int times = challengeStatus.getOrDefault(challengeName, 0) + 1; int times = challengeStatus.getOrDefault(challengeName, 0) + 1;
challengeStatus.put(challengeName, times); challengeStatus.put(challengeName, times);
@ -203,7 +229,7 @@ public class ChallengesPlayerData implements DataObject
* @param challengeName - unique challenge name * @param challengeName - unique challenge name
* @param times - the number of times to set * @param times - the number of times to set
*/ */
public void setChallengeTimes(String challengeName, int times) public void setChallengeTimes(@NonNull String challengeName, @NonNull int times)
{ {
challengeStatus.put(challengeName, times); challengeStatus.put(challengeName, times);
challengesTimestamp.put(challengeName, System.currentTimeMillis()); challengesTimestamp.put(challengeName, System.currentTimeMillis());
@ -216,7 +242,7 @@ public class ChallengesPlayerData implements DataObject
* @param challengeName - unique challenge name * @param challengeName - unique challenge name
* @return true if done at least once * @return true if done at least once
*/ */
public boolean isChallengeDone(String challengeName) public boolean isChallengeDone(@NonNull String challengeName)
{ {
return this.getTimes(challengeName) > 0; return this.getTimes(challengeName) > 0;
} }
@ -228,7 +254,7 @@ public class ChallengesPlayerData implements DataObject
* @param challengeName - unique challenge name * @param challengeName - unique challenge name
* @return - number of times * @return - number of times
*/ */
public int getTimes(String challengeName) public int getTimes(@NonNull String challengeName)
{ {
return challengeStatus.getOrDefault(challengeName, 0); return challengeStatus.getOrDefault(challengeName, 0);
} }
@ -238,7 +264,7 @@ public class ChallengesPlayerData implements DataObject
* This method adds given level id to completed level set. * This method adds given level id to completed level set.
* @param uniqueId from ChallengeLevel object. * @param uniqueId from ChallengeLevel object.
*/ */
public void addCompletedLevel(String uniqueId) public void addCompletedLevel(@NonNull String uniqueId)
{ {
this.levelsDone.add(uniqueId); this.levelsDone.add(uniqueId);
} }
@ -249,12 +275,23 @@ public class ChallengesPlayerData implements DataObject
* @param uniqueId of ChallengeLevel object. * @param uniqueId of ChallengeLevel object.
* @return <code>true</code> if level is completed, otherwise <code>false</code> * @return <code>true</code> if level is completed, otherwise <code>false</code>
*/ */
public boolean isLevelDone(String uniqueId) public boolean isLevelDone(@NonNull String uniqueId)
{ {
return !this.levelsDone.isEmpty() && this.levelsDone.contains(uniqueId); return !this.levelsDone.isEmpty() && this.levelsDone.contains(uniqueId);
} }
/**
* This method adds given LogEntry to history.
*
* @param entry of type LogEntry
*/
public void addHistoryRecord(@NonNull LogEntry entry)
{
this.history.add(entry);
}
/** /**
* @see Object#hashCode() * @see Object#hashCode()
* @return object hashCode value. * @return object hashCode value.

View File

@ -0,0 +1,154 @@
package world.bentobox.challenges.events;
import java.util.UUID;
import world.bentobox.bentobox.api.events.PremadeEvent;
/**
* This Event is fired when challenge is completed.
*/
public class ChallengeCompletedEvent extends PremadeEvent
{
/**
* Constructor creates a new ChallengeCompletedEvent instance.
*
* @param challengeID of type String
* @param playerUUID of type UUID
* @param admin of type boolean
* @param completionCount of type int
*/
public ChallengeCompletedEvent(
String challengeID,
UUID playerUUID,
boolean admin,
int completionCount)
{
this.challengeID = challengeID;
this.playerUUID = playerUUID;
this.admin = admin;
this.completionCount = completionCount;
}
// ---------------------------------------------------------------------
// Section: Getters and setters
// ---------------------------------------------------------------------
/**
* This method returns the challengeID value.
*
* @return the value of challengeID.
*/
public String getChallengeID()
{
return challengeID;
}
/**
* This method sets the challengeID value.
*
* @param challengeID the challengeID new value.
*/
public void setChallengeID(String challengeID)
{
this.challengeID = challengeID;
}
/**
* This method returns the playerUUID value.
*
* @return the value of playerUUID.
*/
public UUID getPlayerUUID()
{
return playerUUID;
}
/**
* This method sets the playerUUID value.
*
* @param playerUUID the playerUUID new value.
*/
public void setPlayerUUID(UUID playerUUID)
{
this.playerUUID = playerUUID;
}
/**
* This method returns the admin value.
*
* @return the value of admin.
*/
public boolean isAdmin()
{
return admin;
}
/**
* This method sets the admin value.
*
* @param admin the admin new value.
*/
public void setAdmin(boolean admin)
{
this.admin = admin;
}
/**
* This method returns the completionCount value.
*
* @return the value of completionCount.
*/
public int getCompletionCount()
{
return completionCount;
}
/**
* This method sets the completionCount value.
*
* @param completionCount the completionCount new value.
*/
public void setCompletionCount(int completionCount)
{
this.completionCount = completionCount;
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Completed challenge ID
*/
private String challengeID;
/**
* User who completes challenge
*/
private UUID playerUUID;
/**
* Indicates if admin completes challenge
*/
private boolean admin;
/**
* Count of completions
*/
private int completionCount;
}

View File

@ -0,0 +1,152 @@
package world.bentobox.challenges.events;
import java.util.UUID;
import world.bentobox.bentobox.api.events.PremadeEvent;
/**
* This event is fired when all challenges in given world is reset.
*/
public class ChallengeResetAllEvent extends PremadeEvent
{
/**
* Constructor creates a new ChallengeResetAllEvent instance.
*
* @param worldName of type String
* @param playerUUID of type UUID
* @param admin of type boolean
* @param reason of type String
*/
public ChallengeResetAllEvent(
String worldName,
UUID playerUUID,
boolean admin,
String reason)
{
this.worldName = worldName;
this.playerUUID = playerUUID;
this.admin = admin;
this.reason = reason;
}
// ---------------------------------------------------------------------
// Section: Getters and setters
// ---------------------------------------------------------------------
/**
* This method returns the worldName value.
*
* @return the value of worldName.
*/
public String getWorldName()
{
return worldName;
}
/**
* This method sets the worldName value.
*
* @param worldName the worldName new value.
*/
public void setWorldName(String worldName)
{
this.worldName = worldName;
}
/**
* This method returns the playerUUID value.
*
* @return the value of playerUUID.
*/
public UUID getPlayerUUID()
{
return playerUUID;
}
/**
* This method sets the playerUUID value.
*
* @param playerUUID the playerUUID new value.
*/
public void setPlayerUUID(UUID playerUUID)
{
this.playerUUID = playerUUID;
}
/**
* This method returns the admin value.
*
* @return the value of admin.
*/
public boolean isAdmin()
{
return admin;
}
/**
* This method sets the admin value.
*
* @param admin the admin new value.
*/
public void setAdmin(boolean admin)
{
this.admin = admin;
}
/**
* This method returns the reason value.
*
* @return the value of reason.
*/
public String getReason()
{
return reason;
}
/**
* This method sets the reason value.
*
* @param reason the reason new value.
*/
public void setReason(String reason)
{
this.reason = reason;
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* World where challenges are reset
*/
private String worldName;
/**
* User who resets challenges
*/
private UUID playerUUID;
/**
* Indicates if admin resets challenges
*/
private boolean admin;
/**
* Reset Reason
*/
private String reason;
}

View File

@ -0,0 +1,149 @@
package world.bentobox.challenges.events;
import java.util.UUID;
import world.bentobox.bentobox.api.events.PremadeEvent;
/**
* This event is fired when single challenge is reset by admin.
*/
public class ChallengeResetEvent extends PremadeEvent
{
/**
* Constructor creates a new ChallengeResetEvent instance.
*
* @param challengeID of type String
* @param playerUUID of type UUID
* @param admin of type boolean
* @param reason of type String
*/
public ChallengeResetEvent(
String challengeID,
UUID playerUUID,
boolean admin,
String reason)
{
this.challengeID = challengeID;
this.playerUUID = playerUUID;
this.admin = admin;
this.reason = reason;
}
// ---------------------------------------------------------------------
// Section: Getters and setters
// ---------------------------------------------------------------------
/**
* This method returns the challengeID value.
* @return the value of challengeID.
*/
public String getChallengeID()
{
return challengeID;
}
/**
* This method sets the challengeID value.
* @param challengeID the challengeID new value.
*
*/
public void setChallengeID(String challengeID)
{
this.challengeID = challengeID;
}
/**
* This method returns the playerUUID value.
* @return the value of playerUUID.
*/
public UUID getPlayerUUID()
{
return playerUUID;
}
/**
* This method sets the playerUUID value.
* @param playerUUID the playerUUID new value.
*
*/
public void setPlayerUUID(UUID playerUUID)
{
this.playerUUID = playerUUID;
}
/**
* This method returns the admin value.
* @return the value of admin.
*/
public boolean isAdmin()
{
return admin;
}
/**
* This method sets the admin value.
* @param admin the admin new value.
*
*/
public void setAdmin(boolean admin)
{
this.admin = admin;
}
/**
* This method returns the reason value.
* @return the value of reason.
*/
public String getReason()
{
return reason;
}
/**
* This method sets the reason value.
* @param reason the reason new value.
*
*/
public void setReason(String reason)
{
this.reason = reason;
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Completed challenge ID
*/
private String challengeID;
/**
* User who completes challenge
*/
private UUID playerUUID;
/**
* Indicates if admin completes challenge
*/
private boolean admin;
/**
* Reset Reason
*/
private String reason;
}

View File

@ -0,0 +1,123 @@
package world.bentobox.challenges.events;
import java.util.UUID;
import world.bentobox.bentobox.api.events.PremadeEvent;
/**
* This event is fired when challenge level is completed.
*/
public class LevelCompletedEvent extends PremadeEvent
{
/**
* Constructor creates a new LevelCompletedEvent instance.
*
* @param levelID of type String
* @param playerUUID of type UUID
* @param admin of type boolean
*/
public LevelCompletedEvent(
String levelID,
UUID playerUUID,
boolean admin)
{
this.levelID = levelID;
this.playerUUID = playerUUID;
this.admin = admin;
}
// ---------------------------------------------------------------------
// Section: Getters and setters
// ---------------------------------------------------------------------
/**
* This method returns the levelID value.
*
* @return the value of levelID.
*/
public String getLevelID()
{
return levelID;
}
/**
* This method sets the levelID value.
*
* @param levelID the levelID new value.
*/
public void setLevelID(String levelID)
{
this.levelID = levelID;
}
/**
* This method returns the playerUUID value.
*
* @return the value of playerUUID.
*/
public UUID getPlayerUUID()
{
return playerUUID;
}
/**
* This method sets the playerUUID value.
*
* @param playerUUID the playerUUID new value.
*/
public void setPlayerUUID(UUID playerUUID)
{
this.playerUUID = playerUUID;
}
/**
* This method returns the admin value.
*
* @return the value of admin.
*/
public boolean isAdmin()
{
return admin;
}
/**
* This method sets the admin value.
*
* @param admin the admin new value.
*/
public void setAdmin(boolean admin)
{
this.admin = admin;
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Completed level ID
*/
private String levelID;
/**
* User who completes challenge
*/
private UUID playerUUID;
/**
* Indicates if admin completes challenge
*/
private boolean admin;
}

View File

@ -0,0 +1,106 @@
package world.bentobox.challenges.handlers;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import world.bentobox.bentobox.api.addons.request.AddonRequestHandler;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.database.object.Challenge;
/**
* This handler returns data for requested challenge.
*/
public class ChallengeDataRequestHandler extends AddonRequestHandler
{
/**
* Constructor creates a new ChallengesDataRequestHandler instance.
*
* @param addon of type ChallengesAddon
*/
public ChallengeDataRequestHandler(ChallengesAddon addon)
{
super("challenge-data");
this.addon = addon;
}
/**
* @param metaData Required meta data.
* @return Map that returns information about challenges
* @see AddonRequestHandler#handle(Map<String, Object>)
*/
@Override
public Object handle(Map<String, Object> metaData)
{
/*
What we need in the metaData:
0. "challenge-name" -> String
What we will return:
- Empty Map if challenge is not given or not found
- Map that contains information about given challenge:
- uniqueId: the same id that was passed to this handler.
- name: String object of display name for challenge.
- icon: ItemStack object that represents challenge.
- levelId: String object of levelId that this challenge is linked.
- order: Integer object of order number for given challenge.
- deployed: boolean object of deployment status.
- description: List of strings that represents challenges description.
- type: String object that represents challenges type.
- repeatable: boolean object of repeatable option.
- maxTimes: Integer object that represents how many times challenge can be completed.
*/
if (metaData == null ||
metaData.isEmpty() ||
metaData.get("challenge-name") == null ||
!(metaData.get("challenge-name") instanceof String))
{
return Collections.emptyMap();
}
Challenge challenge = this.addon.getChallengesManager().getChallenge((String) metaData.get("challenge-name"));
Map<String, Object> challengeDataMap;
if (challenge == null)
{
challengeDataMap = Collections.emptyMap();
}
else
{
challengeDataMap = new HashMap<>();
challengeDataMap.put("uniqueId", challenge.getUniqueId());
challengeDataMap.put("name", challenge.getFriendlyName());
challengeDataMap.put("icon", challenge.getIcon());
challengeDataMap.put("levelId", challenge.getLevel());
challengeDataMap.put("order", challenge.getOrder());
challengeDataMap.put("deployed", challenge.isDeployed());
challengeDataMap.put("description", challenge.getDescription());
challengeDataMap.put("type", challenge.getChallengeType().toString());
challengeDataMap.put("repeatable", challenge.isRepeatable());
challengeDataMap.put("maxTimes", challenge.isRepeatable() ? challenge.getMaxTimes() : 1);
}
return challengeDataMap;
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Variable stores challenges addon.
*/
private ChallengesAddon addon;
}

View File

@ -0,0 +1,66 @@
package world.bentobox.challenges.handlers;
import org.bukkit.Bukkit;
import java.util.Collections;
import java.util.Map;
import world.bentobox.bentobox.api.addons.request.AddonRequestHandler;
import world.bentobox.challenges.ChallengesAddon;
/**
* This handler returns all challenges that is operating in given world.
*/
public class ChallengeListRequestHandler extends AddonRequestHandler
{
/**
* Constructor creates a new CompletedChallengesRequestHandler instance.
*
* @param addon of type ChallengesAddon
*/
public ChallengeListRequestHandler(ChallengesAddon addon)
{
super("challenge-list");
this.addon = addon;
}
/**
* @param metaData Required meta data.
* @return Set of strings that contains completed challenges.
* @see AddonRequestHandler#handle(Map <String, Object>)
*/
@Override
public Object handle(Map<String, Object> metaData)
{
/*
What we need in the metaData:
0. "world-name" -> String
What we will return:
- List of challenges in given world.
*/
if (metaData == null ||
metaData.isEmpty() ||
metaData.get("world-name") == null ||
!(metaData.get("world-name") instanceof String) ||
Bukkit.getWorld((String) metaData.get("world-name")) == null)
{
return Collections.emptyList();
}
return this.addon.getChallengesManager().getAllChallengesNames(Bukkit.getWorld((String) metaData.get("world-name")));
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Variable stores challenges addon.
*/
private ChallengesAddon addon;
}

View File

@ -0,0 +1,80 @@
package world.bentobox.challenges.handlers;
import org.bukkit.Bukkit;
import org.bukkit.World;
import java.util.*;
import java.util.stream.Collectors;
import world.bentobox.bentobox.api.addons.request.AddonRequestHandler;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.ChallengesManager;
/**
* This Request Handler returns completed challenges for user in given world.
*/
public class CompletedChallengesRequestHandler extends AddonRequestHandler
{
/**
* Constructor creates a new CompletedChallengesRequestHandler instance.
*
* @param addon of type ChallengesAddon
*/
public CompletedChallengesRequestHandler(ChallengesAddon addon)
{
super("completed-challenges");
this.addon = addon;
}
/**
* @param metaData Required meta data.
* @return Set of strings that contains completed challenges.
* @see AddonRequestHandler#handle(Map<String, Object>)
*/
@Override
public Object handle(Map<String, Object> metaData)
{
/*
What we need in the metaData:
0. "player" -> UUID
1. "world-name" -> String
What we will return:
- Empty Set if player or given world is not valid.
- Set of completed challenges in given world (or empty list if user haven't completed any challenge)
*/
if (metaData == null ||
metaData.isEmpty() ||
metaData.get("world-name") == null ||
!(metaData.get("world-name") instanceof String) ||
metaData.get("player") == null ||
!(metaData.get("player") instanceof UUID) ||
Bukkit.getWorld((String) metaData.get("world-name")) == null)
{
return Collections.emptySet();
}
World world = Bukkit.getWorld((String) metaData.get("world-name"));
UUID player = (UUID) metaData.get("player");
ChallengesManager manager = this.addon.getChallengesManager();
return manager.getAllChallengesNames(world).stream().
filter(challenge -> manager.isChallengeComplete(player, world, challenge)).
collect(Collectors.toSet());
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Variable stores challenges addon.
*/
private ChallengesAddon addon;
}

View File

@ -0,0 +1,98 @@
package world.bentobox.challenges.handlers;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import world.bentobox.bentobox.api.addons.request.AddonRequestHandler;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.database.object.ChallengeLevel;
/**
* This handler returns Data map of requested level.
*/
public class LevelDataRequestHandler extends AddonRequestHandler
{
/**
* Constructor creates a new LevelDataRequestHandler instance.
*
* @param addon of type ChallengesAddon
*/
public LevelDataRequestHandler(ChallengesAddon addon)
{
super("level-data");
this.addon = addon;
}
/**
* @param metaData Required meta data.
* @return Map that returns information about level
* @see AddonRequestHandler#handle(Map <String, Object>)
*/
@Override
public Object handle(Map<String, Object> metaData)
{
/*
What we need in the metaData:
0. "level-name" -> String
What we will return:
- Empty Map if level is not given or not found
- Map that contains information about given level:
- uniqueId: the same id that was passed to this handler.
- name: String object of display name for level.
- icon: ItemStack object that represents level.
- order: Integer object of order number for given level.
- message: String object that represents level unlock message.
- world: String object that represents world name where level operates.
- waiveramount: Integer object of waiver amount for given level.
- challenges: List of strings that represents challenges that is owned by given level.
*/
if (metaData == null ||
metaData.isEmpty() ||
metaData.get("level-name") == null ||
!(metaData.get("level-name") instanceof String))
{
return Collections.emptyMap();
}
ChallengeLevel level = this.addon.getChallengesManager().getLevel((String) metaData.get("level-name"));
Map<String, Object> levelDataMap;
if (level == null)
{
levelDataMap = Collections.emptyMap();
}
else
{
levelDataMap = new HashMap<>();
levelDataMap.put("uniqueId", level.getUniqueId());
levelDataMap.put("name", level.getFriendlyName());
levelDataMap.put("icon", level.getIcon());
levelDataMap.put("order", level.getOrder());
levelDataMap.put("message", level.getUnlockMessage());
levelDataMap.put("world", level.getWorld());
levelDataMap.put("challenges", level.getChallenges());
levelDataMap.put("waiveramount", level.getWaiverAmount());
}
return levelDataMap;
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Variable stores challenges addon.
*/
private ChallengesAddon addon;
}

View File

@ -0,0 +1,67 @@
package world.bentobox.challenges.handlers;
import org.bukkit.Bukkit;
import java.util.Collections;
import java.util.Map;
import world.bentobox.bentobox.api.addons.request.AddonRequestHandler;
import world.bentobox.challenges.ChallengesAddon;
/**
* This handler returns all levels that is working in given world.
*/
public class LevelListRequestHandler extends AddonRequestHandler
{
/**
* Constructor creates a new CompletedChallengesRequestHandler instance.
*
* @param addon of type ChallengesAddon
*/
public LevelListRequestHandler(ChallengesAddon addon)
{
super("level-list");
this.addon = addon;
}
/**
* @param metaData Required meta data.
* @return List of strings that contains levels in given world
* @see AddonRequestHandler#handle(Map <String, Object>)
*/
@Override
public Object handle(Map<String, Object> metaData)
{
/*
What we need in the metaData:
0. "world-name" -> String
What we will return:
- List of levels in given world.
*/
if (metaData == null ||
metaData.isEmpty() ||
metaData.get("world-name") == null ||
!(metaData.get("world-name") instanceof String) ||
Bukkit.getWorld((String) metaData.get("world-name")) == null)
{
return Collections.emptyList();
}
return this.addon.getChallengesManager().getLevels(Bukkit.getWorld((String) metaData.get("world-name")));
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Variable stores challenges addon.
*/
private ChallengesAddon addon;
}

View File

@ -28,7 +28,7 @@ public class ResetListener implements Listener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onIslandReset(IslandEvent e) { public void onIslandReset(IslandEvent e) {
if (e.getReason().equals(Reason.CREATED) || (addon.getChallengesSettings().isResetChallenges() && e.getReason().equals(Reason.RESETTED))) { if (e.getReason().equals(Reason.CREATED) || (addon.getChallengesSettings().isResetChallenges() && e.getReason().equals(Reason.RESETTED))) {
addon.getChallengesManager().resetAllChallenges(e.getOwner(), e.getLocation().getWorld()); addon.getChallengesManager().resetAllChallenges(e.getOwner(), e.getLocation().getWorld(), e.getOwner());
} }
} }
} }

View File

@ -1,69 +0,0 @@
package world.bentobox.challenges.panel;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.bentobox.api.panels.Panel;
import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User;
/**
* @deprecated All panels are reworked.
*/
@Deprecated
public class AdminEditGUI implements ClickHandler {
private ChallengesAddon addon;
private User requester;
private Challenge challenge;
private World world;
private String permPrefix;
private String label;
private User target;
/**
* Shows the admin panel for the challenge for a player
* @param addon addon
* @param requester admin user
* @param target target of admin
* @param challenge challenge
* @param world world
* @param permPrefix permission prefix for world
* @param label command label
*/
public AdminEditGUI(ChallengesAddon addon, User requester, User target, Challenge challenge, World world,
String permPrefix, String label) {
super();
this.addon = addon;
this.requester = requester;
this.target = target;
this.challenge = challenge;
this.world = world;
this.permPrefix = permPrefix;
this.label = label;
new PanelBuilder().size(27).user(requester).name(requester.getTranslation("challenges.admin.gui-title"))
.item(new PanelItemBuilder().icon(challenge.getIcon()).name("Icon").build())
.item(9, new PanelItemBuilder().icon(new ItemStack(Material.WHITE_BANNER)).name("Description").description(challenge.getDescription()).build())
.item(18, new PanelItemBuilder().icon(new ItemStack(Material.GREEN_STAINED_GLASS_PANE)).name("Active").build())
.item(27, new PanelItemBuilder().icon(new ItemStack(Material.BOOK)).name("Edit required items").clickHandler(this).build())
.build();
}
@Override
public boolean onClick(Panel panel, User user, ClickType clickType, int slot) {
if (slot == 27) {
new RequiredPanel(challenge, user, panel);
}
return true;
}
}

View File

@ -1,66 +0,0 @@
package world.bentobox.challenges.panel;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.bentobox.api.panels.Panel;
import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User;
/**
* @deprecated All panels are reworked.
*/
@Deprecated
public class AdminGUI implements ClickHandler {
private ChallengesAddon addon;
private User player;
private Challenge challenge;
private World world;
private String permPrefix;
private String label;
/**
* Shows the admin panel for the challenge
* @param addon
* @param player
* @param challenge
* @param world
* @param permPrefix
* @param label
*/
public AdminGUI(ChallengesAddon addon, User player, Challenge challenge, World world,
String permPrefix, String label) {
super();
this.addon = addon;
this.player = player;
this.challenge = challenge;
this.world = world;
this.permPrefix = permPrefix;
this.label = label;
new PanelBuilder().size(27).user(player).name(player.getTranslation("challenges.admin.gui-title"))
.item(new PanelItemBuilder().icon(challenge.getIcon()).name("Icon").build())
.item(9, new PanelItemBuilder().icon(new ItemStack(Material.WHITE_BANNER)).name("Description").description(challenge.getDescription()).build())
.item(18, new PanelItemBuilder().icon(new ItemStack(Material.GREEN_STAINED_GLASS_PANE)).name("Active").build())
.item(27, new PanelItemBuilder().icon(new ItemStack(Material.BOOK)).name("Edit required items").clickHandler(this).build())
.build();
}
@Override
public boolean onClick(Panel panel, User user, ClickType clickType, int slot) {
if (slot == 27) {
new RequiredPanel(challenge, user, panel);
}
return true;
}
}

View File

@ -1,248 +0,0 @@
package world.bentobox.challenges.panel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.ChallengesManager;
import world.bentobox.challenges.database.object.ChallengeLevel;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.LevelStatus;
import world.bentobox.challenges.commands.ChallengesCommand;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.database.object.Challenge.ChallengeType;
import world.bentobox.bentobox.api.panels.Panel;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User;
/**
* @deprecated All panels are reworked.
*/
@Deprecated
public class ChallengesPanels {
private ChallengesAddon addon;
private ChallengesManager manager;
private User user;
private ChallengeLevel level;
private World world;
private String permPrefix;
private String label;
public ChallengesPanels(ChallengesAddon addon, User user, String level, World world, String permPrefix, String label) {
this.addon = addon;
this.manager = addon.getChallengesManager();
this.user = user;
this.world = world;
this.permPrefix = permPrefix;
this.label = label;
if (manager.getAllChallenges(world).isEmpty()) {
addon.getLogger().severe("There are no challenges set up!");
user.sendMessage("general.errors.general");
return;
}
if (level.isEmpty()) {
level = manager.getLevels(world).iterator().next().getUniqueId();
}
this.level = this.manager.getLevel(level);
// Check if level is valid
if (!manager.isLevelUnlocked(user, this.level)) {
return;
}
PanelBuilder panelBuilder = new PanelBuilder()
.name(user.getTranslation("challenges.gui-title"));
addChallengeItems(panelBuilder);
addNavigation(panelBuilder);
addFreeChallanges(panelBuilder);
// Create the panel
Panel panel = panelBuilder.build();
panel.open(user);
}
private void addChallengeItems(PanelBuilder panelBuilder) {
List<Challenge> levelChallenges = manager.getLevelChallenges(level);
// Only show a control panel for the level requested.
for (Challenge challenge : levelChallenges) {
createItem(panelBuilder, challenge);
}
}
private void addFreeChallanges(PanelBuilder panelBuilder) {
manager.getFreeChallenges(world).forEach(challenge -> createItem(panelBuilder, challenge));
}
/**
* Creates a panel item for challenge if appropriate and adds it to panelBuilder
* @param panelBuilder
* @param challenge
*/
private void createItem(PanelBuilder panelBuilder, Challenge challenge) {
// Check completion
boolean completed = manager.isChallengeComplete(user, challenge);
// If challenge is removed after completion, remove it
if (completed && challenge.isRemoveWhenCompleted()) {
return;
}
PanelItem item = new PanelItemBuilder()
.icon(challenge.getIcon())
.name(challenge.getFriendlyName().isEmpty() ? challenge.getUniqueId() : challenge.getFriendlyName())
.description(challengeDescription(challenge))
.glow(completed)
.clickHandler((panel, player, c, s) -> {
new TryToComplete(addon).user(player).manager(manager).challenge(challenge)
.world(world).permPrefix(permPrefix).label(label).build();
return true;
})
.build();
if (challenge.getOrder() >= 0) {
panelBuilder.item(challenge.getOrder(),item);
} else {
panelBuilder.item(item);
}
}
private void addNavigation(PanelBuilder panelBuilder) {
// TODO: This if fix for wrong getNumberOfChallengesStillToDo() issue. #23
LevelStatus previousStatus = null;
// Add navigation to other levels
for (LevelStatus status: manager.getChallengeLevelStatus(user, world)) {
if (status.getLevel().getUniqueId().equals(level)) {
// Skip if this is the current level
previousStatus = status;
continue;
}
// Create a nice name for the level
String name = status.getLevel().getFriendlyName().isEmpty() ? status.getLevel().getUniqueId() : status.getLevel().getFriendlyName();
if (status.isUnlocked()) {
// Clicking on this icon will open up this level's challenges
PanelItem item = new PanelItemBuilder()
.icon(new ItemStack(Material.ENCHANTED_BOOK))
.name(name)
.description(GuiUtils.stringSplit(
user.getTranslation("challenges.navigation","[level]",name),
this.addon.getChallengesSettings().getLoreLineLength()))
.clickHandler((p, u, c, s) -> {
u.closeInventory();
u.performCommand(label + " " + ChallengesCommand.CHALLENGE_COMMAND + " " + status.getLevel().getUniqueId());
return true;
})
.build();
panelBuilder.item(item);
} else {
// Clicking on this icon will do nothing because the challenge is not unlocked yet
String previousLevelName = status.getPreviousLevel().getFriendlyName().isEmpty() ? status.getPreviousLevel().getUniqueId() : status.getPreviousLevel().getFriendlyName();
PanelItem item = new PanelItemBuilder()
.icon(new ItemStack(Material.BOOK))
.name(name)
.description(GuiUtils.stringSplit(
user.getTranslation("challenges.to-complete",
"[challengesToDo]", String.valueOf(previousStatus != null ? previousStatus.getNumberOfChallengesStillToDo() : ""),
"[thisLevel]", previousLevelName),
this.addon.getChallengesSettings().getLoreLineLength()))
.build();
panelBuilder.item(item);
}
previousStatus = status;
}
}
/**
* Creates the challenge description for the "item" in the inventory
*
* @param challenge
* @return List of strings splitting challenge string into 25 chars long
*/
private List<String> challengeDescription(Challenge challenge) {
List<String> result = new ArrayList<String>();
String level = challenge.getLevel();
if (!level.isEmpty()) {
result.addAll(splitTrans(user, "challenges.level", "[level]", level));
}
// Check if completed or not
boolean complete = addon.getChallengesManager().isChallengeComplete(user, challenge);
int maxTimes = challenge.getMaxTimes();
long doneTimes = addon.getChallengesManager().getChallengeTimes(user, challenge);
if (complete) {
result.add(user.getTranslation("challenges.complete"));
}
if (challenge.isRepeatable()) {
if (maxTimes == 0) {
// Check if the player has maxed out the challenge
if (doneTimes < maxTimes) {
result.addAll(splitTrans(user, "challenges.completed-times","[donetimes]", String.valueOf(doneTimes),"[maxtimes]", String.valueOf(maxTimes)));
} else {
result.addAll(splitTrans(user, "challenges.maxed-reached","[donetimes]", String.valueOf(doneTimes),"[maxtimes]", String.valueOf(maxTimes)));
}
}
}
if (!complete || (complete && challenge.isRepeatable())) {
result.addAll(challenge.getDescription());
if (challenge.getChallengeType().equals(ChallengeType.INVENTORY)) {
if (challenge.isTakeItems()) {
result.addAll(splitTrans(user, "challenges.item-take-warning"));
}
} else if (challenge.getChallengeType().equals(ChallengeType.ISLAND)) {
result.addAll(splitTrans(user, "challenges.items-closeby"));
}
}
if (complete && (!challenge.getChallengeType().equals(ChallengeType.INVENTORY) || !challenge.isRepeatable())) {
result.addAll(splitTrans(user, "challenges.not-repeatable"));
return result;
}
double moneyReward = 0;
int expReward = 0;
String rewardText = "";
if (!complete) {
// First time
moneyReward = challenge.getRewardMoney();
rewardText = challenge.getRewardText();
expReward = challenge.getRewardExperience();
if (!rewardText.isEmpty()) {
result.addAll(splitTrans(user, "challenges.first-time-rewards"));
}
} else {
// Repeat challenge
moneyReward = challenge.getRepeatMoneyReward();
rewardText = challenge.getRepeatRewardText();
expReward = challenge.getRepeatExperienceReward();
if (!rewardText.isEmpty()) {
result.addAll(splitTrans(user, "challenges.repeat-rewards"));
}
}
if (!rewardText.isEmpty()) {
result.addAll(splitTrans(user,rewardText));
}
if (expReward > 0) {
result.addAll(splitTrans(user,"challenges.exp-reward", "[reward]", String.valueOf(expReward)));
}
if (addon.getPlugin().getSettings().isUseEconomy() && moneyReward > 0) {
result.addAll(splitTrans(user,"challenges.money-reward", "[reward]", String.valueOf(moneyReward)));
}
// Final placeholder change for [label]
result.replaceAll(x -> x.replace("[label]", label));
return result;
}
private Collection<? extends String> splitTrans(User user, String string, String...strings) {
return GuiUtils.stringSplit(user.getTranslation(string, strings),
this.addon.getChallengesSettings().getLoreLineLength());
}
}

View File

@ -1,320 +0,0 @@
package world.bentobox.challenges.panel;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import world.bentobox.bentobox.api.panels.Panel;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.ChallengesManager;
import world.bentobox.challenges.commands.ChallengesCommand;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.database.object.Challenge.ChallengeType;
import world.bentobox.challenges.database.object.ChallengeLevel;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.LevelStatus;
/**
* @deprecated All panels are reworked.
*/
@Deprecated
public class ChallengesPanels2 {
public enum Mode {
ADMIN,
EDIT,
PLAYER
}
private ChallengesAddon addon;
private ChallengesManager manager;
private User requester;
private ChallengeLevel level;
private World world;
private String permPrefix;
private String label;
private Mode mode;
private User target;
public ChallengesPanels2(ChallengesAddon addon, User requester, User target, String level, World world, String permPrefix, String label, Mode mode) {
this.addon = addon;
this.manager = addon.getChallengesManager();
this.requester = requester;
this.target = target;
this.world = world;
this.permPrefix = permPrefix;
this.label = label;
this.mode = mode;
if (manager.getAllChallenges(world).isEmpty()) {
addon.getLogger().severe("There are no challenges set up!");
requester.sendMessage("general.errors.general");
return;
}
if (level.isEmpty()) {
// TODO: open the farthest challenge panel
level = manager.getLevels(world).iterator().next().getUniqueId();
}
this.level = manager.getLevel(level);
// Check if level is valid
if (mode.equals(Mode.PLAYER) && !manager.isLevelUnlocked(requester, this.level)) {
return;
}
PanelBuilder panelBuilder = new PanelBuilder();
switch (mode) {
case ADMIN:
panelBuilder.name(requester.getTranslation("challenges.admin.gui-title"));
break;
case EDIT:
panelBuilder.name(requester.getTranslation("challenges.admin.edit-gui-title"));
break;
case PLAYER:
panelBuilder.name(requester.getTranslation("challenges.gui-title"));
break;
default:
break;
}
addChallengeItems(panelBuilder);
addNavigation(panelBuilder);
addFreeChallanges(panelBuilder);
// Create the panel
Panel panel = panelBuilder.build();
panel.open(requester);
}
private void addChallengeItems(PanelBuilder panelBuilder) {
// Only show a control panel for the level requested.
for (Challenge challenge : manager.getLevelChallenges(level)) {
createItem(panelBuilder, challenge);
}
}
private void addFreeChallanges(PanelBuilder panelBuilder) {
manager.getFreeChallenges(world).forEach(challenge -> createItem(panelBuilder, challenge));
}
/**
* Creates a panel item for challenge if appropriate and adds it to panelBuilder
* @param panelBuilder
* @param challenge
*/
private void createItem(PanelBuilder panelBuilder, Challenge challenge) {
// For admin, glow means activated. For user, glow means done
boolean glow = false;
switch (mode) {
case ADMIN:
glow = challenge.isDeployed();
break;
case EDIT:
glow = manager.isChallengeComplete(requester, challenge);
break;
case PLAYER:
glow = manager.isChallengeComplete(requester, challenge);
break;
default:
break;
}
// If not admin and challenge is removed after completion, remove it
if (mode.equals(Mode.PLAYER) && glow && challenge.isRemoveWhenCompleted()) {
return;
}
PanelItemBuilder itemBuilder = new PanelItemBuilder()
.icon(challenge.getIcon())
.name(challenge.getFriendlyName().isEmpty() ? challenge.getUniqueId() : challenge.getFriendlyName())
.description(challengeDescription(challenge))
.glow(glow);
if (mode.equals(Mode.ADMIN)) {
// Admin click
itemBuilder.clickHandler((panel, player, c, s) -> {
new AdminGUI(addon, player, challenge, world, permPrefix, label);
return true;
});
} else if (mode.equals(Mode.EDIT)) {
// Admin edit click
itemBuilder.clickHandler((panel, player, c, s) -> {
new AdminEditGUI(addon, player, target, challenge, world, permPrefix, label);
return true;
});
} else {
// Player click
itemBuilder.clickHandler((panel, player, c, s) -> {
new TryToComplete(addon, player, challenge, world, label, permPrefix).build();
return true;
});
}
// If the challenge has a specific slot allocated, use it
if (challenge.getOrder() >= 0) {
panelBuilder.item(challenge.getOrder(),itemBuilder.build());
} else {
panelBuilder.item(itemBuilder.build());
}
}
private void addNavigation(PanelBuilder panelBuilder) {
// TODO: This if fix for wrong getNumberOfChallengesStillToDo() issue. #23
LevelStatus previousStatus = null;
// Add navigation to other levels
for (LevelStatus status: manager.getChallengeLevelStatus(requester, world)) {
if (status.getLevel().getUniqueId().equalsIgnoreCase(level.getUniqueId())) {
// Skip if this is the current level
previousStatus = status;
continue;
}
// Create a nice name for the level
String name = status.getLevel().getFriendlyName().isEmpty() ? status.getLevel().getUniqueId() : status.getLevel().getFriendlyName();
if (mode.equals(Mode.ADMIN) || mode.equals(Mode.EDIT) || status.isUnlocked()) {
// Clicking on this icon will open up this level's challenges
PanelItem item = new PanelItemBuilder()
.icon(new ItemStack(Material.ENCHANTED_BOOK))
.name(name)
.description(GuiUtils.stringSplit(
requester.getTranslation("challenges.navigation","[level]",name),
this.addon.getChallengesSettings().getLoreLineLength()))
.clickHandler((p, u, c, s) -> {
u.closeInventory();
u.performCommand(label + " " + ChallengesCommand.CHALLENGE_COMMAND + " " + status.getLevel().getUniqueId());
return true;
})
.build();
panelBuilder.item(item);
} else {
// Clicking on this icon will do nothing because the challenge is not unlocked yet
String previousLevelName = status.getPreviousLevel().getFriendlyName().isEmpty() ? status.getPreviousLevel().getUniqueId() : status.getPreviousLevel().getFriendlyName();
PanelItem item = new PanelItemBuilder()
.icon(new ItemStack(Material.BOOK))
.name(name)
.description(GuiUtils.stringSplit(requester.getTranslation("challenges.to-complete",
"[challengesToDo]", String.valueOf(previousStatus != null ? previousStatus.getNumberOfChallengesStillToDo() : ""),
"[thisLevel]", previousLevelName),
this.addon.getChallengesSettings().getLoreLineLength()))
.build();
panelBuilder.item(item);
}
previousStatus = status;
}
}
/**
* Creates the challenge description for the "item" in the inventory
*
* @param challenge
* @return List of strings splitting challenge string into 25 chars long
*/
private List<String> challengeDescription(Challenge challenge) {
List<String> result = new ArrayList<String>();
String level = challenge.getLevel();
if (!level.isEmpty()) {
result.addAll(splitTrans(requester, "challenges.level", "[level]", level));
}
if (mode.equals(Mode.ADMIN)) {
if ((!challenge.getChallengeType().equals(ChallengeType.INVENTORY) || !challenge.isRepeatable())) {
result.addAll(splitTrans(requester, "challenges.not-repeatable"));
} else {
result.addAll(splitTrans(requester, "challenges.repeatable", "[maxtimes]", String.valueOf(challenge.getMaxTimes())));
}
if (challenge.getChallengeType().equals(ChallengeType.INVENTORY) && challenge.isTakeItems()) {
result.addAll(splitTrans(requester, "challenges.item-take-warning"));
}
result.addAll(addRewards(challenge, true, true));
} else {
// Check if completed or not
boolean complete = addon.getChallengesManager().isChallengeComplete(requester, challenge);
int maxTimes = challenge.getMaxTimes();
long doneTimes = addon.getChallengesManager().getChallengeTimes(requester, challenge);
if (complete) {
result.add(requester.getTranslation("challenges.complete"));
}
if (challenge.isRepeatable()) {
if (maxTimes == 0) {
// Check if the player has maxed out the challenge
if (doneTimes < maxTimes) {
result.addAll(splitTrans(requester, "challenges.completed-times","[donetimes]", String.valueOf(doneTimes),"[maxtimes]", String.valueOf(maxTimes)));
} else {
result.addAll(splitTrans(requester, "challenges.maxed-reached","[donetimes]", String.valueOf(doneTimes),"[maxtimes]", String.valueOf(maxTimes)));
}
}
}
if (!complete || (complete && challenge.isRepeatable())) {
result.addAll(challenge.getDescription());
if (challenge.getChallengeType().equals(ChallengeType.INVENTORY)) {
if (challenge.isTakeItems()) {
result.addAll(splitTrans(requester, "challenges.item-take-warning"));
}
} else if (challenge.getChallengeType().equals(ChallengeType.ISLAND)) {
result.addAll(splitTrans(requester, "challenges.items-closeby"));
}
}
if (complete && (!challenge.getChallengeType().equals(ChallengeType.INVENTORY) || !challenge.isRepeatable())) {
result.addAll(splitTrans(requester, "challenges.not-repeatable"));
result.replaceAll(x -> x.replace("[label]", label));
return result;
}
result.addAll(addRewards(challenge, complete, false));
}
// Final placeholder change for [label]
result.replaceAll(x -> x.replace("[label]", label));
return result;
}
private List<String> addRewards(Challenge challenge, boolean complete, boolean admin) {
List<String> result = new ArrayList<>();
double moneyReward = 0;
int expReward = 0;
String rewardText = "";
if (admin || !complete) {
// First time
moneyReward = challenge.getRewardMoney();
rewardText = challenge.getRewardText();
expReward = challenge.getRewardExperience();
if (!rewardText.isEmpty()) {
result.addAll(splitTrans(requester, "challenges.first-time-rewards"));
}
}
if (admin || complete){
// Repeat challenge
moneyReward = challenge.getRepeatMoneyReward();
rewardText = challenge.getRepeatRewardText();
expReward = challenge.getRepeatExperienceReward();
if (!rewardText.isEmpty()) {
result.addAll(splitTrans(requester, "challenges.repeat-rewards"));
}
}
if (!rewardText.isEmpty()) {
result.addAll(splitTrans(requester,rewardText));
}
if (expReward > 0) {
result.addAll(splitTrans(requester,"challenges.exp-reward", "[reward]", String.valueOf(expReward)));
}
if (addon.getPlugin().getSettings().isUseEconomy() && moneyReward > 0) {
result.addAll(splitTrans(requester,"challenges.money-reward", "[reward]", String.valueOf(moneyReward)));
}
return result;
}
private Collection<? extends String> splitTrans(User user, String string, String...strings) {
return GuiUtils.stringSplit(user.getTranslation(string, strings),
this.addon.getChallengesSettings().getLoreLineLength());
}
}

View File

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

View File

@ -1,40 +0,0 @@
package world.bentobox.challenges.panel;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.bentobox.api.panels.PanelListener;
import world.bentobox.bentobox.api.user.User;
/**
* @deprecated All panels are reworked.
*/
@Deprecated
public class CreateChallengeListener implements PanelListener {
private ChallengesAddon addon;
private User user;
public CreateChallengeListener(ChallengesAddon addon, User user) {
this.addon = addon;
this.user = user;
}
@Override
public void setup() {
// Nothing to setup
}
@Override
public void onInventoryClose(InventoryCloseEvent event) {
addon.getChallengesManager().createChallenge("uniqueID");
}
@Override
public void onInventoryClick(User user, InventoryClickEvent event) {
// Allow drag and drop
event.setCancelled(false);
}
}

View File

@ -1,18 +0,0 @@
package world.bentobox.challenges.panel;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.user.User;
/**
* @deprecated All panels are reworked.
*/
@Deprecated
public class CreateChallengePanel {
public CreateChallengePanel(ChallengesAddon addon, User user) {
new PanelBuilder().size(49).listener(new CreateChallengeListener(addon, user)).user(user).build();
}
}

View File

@ -0,0 +1,138 @@
package world.bentobox.challenges.panel;
import org.bukkit.Material;
import org.bukkit.World;
import java.util.List;
import java.util.Optional;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class process GameModeGui opening.
*/
public class GameModesGUI extends CommonGUI
{
/**
* {@inheritDoc}
* @param adminMode - boolean that indicate if Gui is in admin mode.
* @param gameModeAddons - List with GameModes where Challenges addon is integrated.
*/
public GameModesGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix,
boolean adminMode,
List<GameModeAddon> gameModeAddons)
{
super(addon, world, user, topLabel, permissionPrefix);
this.adminMode = adminMode;
this.gameModeAddons = gameModeAddons;
}
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name("challenges.gui.title.game-modes");
GuiUtils.fillBorder(panelBuilder, this.adminMode ?
Material.BLACK_STAINED_GLASS_PANE :
Material.BLUE_STAINED_GLASS_PANE);
int elementIndex;
if (this.gameModeAddons.size() < 8)
{
if (this.gameModeAddons.size() == 7)
{
elementIndex = 19;
}
else
{
elementIndex = 22 - this.gameModeAddons.size() / 2;
}
}
else
{
elementIndex = 10;
}
for (GameModeAddon gameModeAddon : this.gameModeAddons)
{
if (!panelBuilder.slotOccupied(elementIndex))
{
panelBuilder.item(elementIndex++, this.createGameModeIcon(gameModeAddon));
}
else
{
// Find first open slot
while (panelBuilder.slotOccupied(elementIndex))
{
elementIndex++;
}
}
}
panelBuilder.build();
}
/**
* This method creates icon that will display given GameMode addon.
* @param gameModeAddon GameMode addon.
* @return PanelItem that acts as icon for given GameMode.
*/
private PanelItem createGameModeIcon(GameModeAddon gameModeAddon)
{
return new PanelItemBuilder().
name(gameModeAddon.getDescription().getName()).
description(gameModeAddon.getDescription().getDescription()).
icon(Material.PAPER).
clickHandler((panel, user, clickType, slot) -> {
Optional<CompositeCommand> command;
if (this.adminMode)
{
command = gameModeAddon.getAdminCommand();
}
else
{
command = gameModeAddon.getPlayerCommand();
}
command.ifPresent(compositeCommand ->
user.performCommand(compositeCommand.getTopLabel() + " challenges"));
return true;
}).
build();
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* List with game mode addons which must be showed in current GUI.
*/
private List<GameModeAddon> gameModeAddons;
/**
* Stores if current GUI is in Admin Mode or not.
*/
private boolean adminMode;
}

View File

@ -1,165 +0,0 @@
package world.bentobox.challenges.panel;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.ItemStack;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.bentobox.api.panels.Panel;
import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler;
import world.bentobox.bentobox.api.panels.PanelListener;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
/**
* Handles the requirements for a challenge
* Items, blocks, entities
* @author tastybento
* @deprecated All panels are reworked.
*/
@Deprecated
public class RequiredPanel implements ClickHandler, PanelListener {
private static final int CONTROL_NUMBER = 4;
private Challenge challenge;
private User user;
private Panel panel;
private Panel referringPanel;
/**
* @param challenge
* @param user
*/
public RequiredPanel(Challenge challenge, User user, Panel referringPanel) {
this.challenge = challenge;
this.user = user;
this.panel = openPanel();
this.referringPanel = referringPanel;
}
private Panel openPanel() {
PanelBuilder pb = new PanelBuilder().listener(this).name("Required Items").size(49);
// Add the name and description icon
pb.item(new PanelItemBuilder().icon(Material.BOOK).name(challenge.getFriendlyName()).description(challenge.getDescription()).clickHandler(this).build());
// Add take all button
pb.item(new PanelItemBuilder().icon(Material.BOOK).name("Take Items").description(challenge.isTakeItems() ? "Yes" : "No").clickHandler(this).build());
// Add save button
pb.item(new PanelItemBuilder().icon(Material.BOOK).name("Save").clickHandler(this).build());
// Add cancel button
pb.item(new PanelItemBuilder().icon(Material.BOOK).name("Cancel").clickHandler(this).build());
switch (challenge.getChallengeType()) {
case INVENTORY:
// Show the required items in the inventory
challenge.getRequiredItems().stream().map(i -> new PanelItemBuilder().icon(i).clickHandler(this).build()).forEach(pb::item);
return pb.user(user).build();
case ISLAND:
// Create the blocks required
challenge.getRequiredBlocks().entrySet().stream().map(en -> new ItemStack(en.getKey(), en.getValue())).map(i -> new PanelItemBuilder().icon(i).clickHandler(this).build()).forEach(pb::item);
// Create the entities required
challenge.getRequiredEntities().entrySet().stream().map(this::toSpawnEgg).map(i -> new PanelItemBuilder()
.icon(i)
.name(Util.prettifyText(i.getType().toString()))
.description("Entity")
.clickHandler(this)
.build()).forEach(pb::item);
return pb.user(user).build();
case OTHER:
break;
default:
break;
}
return panel;
}
private ItemStack toSpawnEgg(Entry<EntityType, Integer> en) {
Material mat = Material.getMaterial(en.getKey().name() + "_SPAWN_EGG");
if (mat != null) {
return new ItemStack(mat, en.getValue());
} else {
return new ItemStack(Material.COW_SPAWN_EGG);
}
}
@Override
public boolean onClick(Panel panel, User user, ClickType clickType, int slot) {
Bukkit.getLogger().info("DEBUG: slot = " + slot);
return slot < CONTROL_NUMBER;
}
@Override
public void setup() {
// nothing to do
}
@Override
public void onInventoryClose(InventoryCloseEvent event) {
}
@Override
public void onInventoryClick(User user, InventoryClickEvent event) {
// Allow drag and drop
event.setCancelled(event.getRawSlot() < CONTROL_NUMBER);
Bukkit.getLogger().info("DEBUG: inv slot = " + event.getSlot());
Bukkit.getLogger().info("DEBUG: inv slot type = " + event.getSlotType());
if (event.getSlot() == 1) {
// Take items
challenge.setTakeItems(!challenge.isTakeItems());
// Update item
event.getInventory().setItem(event.getSlot(), new PanelItemBuilder().icon(Material.BOOK).name("Take Items").description(challenge.isTakeItems() ? "Yes" : "No").build().getItem());
return;
}
if (event.getSlot() == 3) {
// Cancel
referringPanel.open(user);
return;
// Return to previous panel
}
// Save
if (event.getSlot() != 2) {
return;
}
// Save changes
switch (challenge.getChallengeType()) {
case INVENTORY:
List<ItemStack> reqItems = new ArrayList<>();
// Skip first item
for (int i = CONTROL_NUMBER; i < event.getInventory().getSize(); i++) {
if (event.getInventory().getItem(i) != null) {
reqItems.add(event.getInventory().getItem(i));
}
}
challenge.setRequiredItems(reqItems);
user.sendMessage("challenges.admin.saved");
// TODO: save challenges
event.getInventory().setItem(event.getSlot(), new PanelItemBuilder().icon(Material.BOOK).name("Save").description("Saved").build().getItem());
break;
case ISLAND:
break;
case OTHER:
break;
default:
break;
}
}
}

View File

@ -440,7 +440,7 @@ public class EditChallengeGUI extends CommonGUI
icon = new ItemStack(Material.DROPPER); icon = new ItemStack(Material.DROPPER);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challenge.getOrder(), -1, 54, (status, value) -> { new NumberGUI(this.user, this.challenge.getOrder(), -1, 54, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challenge.setOrder(value); this.challenge.setOrder(value);
@ -648,7 +648,7 @@ public class EditChallengeGUI extends CommonGUI
icon = new ItemStack(Material.COBBLESTONE_WALL); icon = new ItemStack(Material.COBBLESTONE_WALL);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challenge.getSearchRadius(), 0, (status, value) -> { new NumberGUI(this.user, this.challenge.getSearchRadius(), 0, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challenge.setSearchRadius(value); this.challenge.setSearchRadius(value);
@ -764,7 +764,7 @@ public class EditChallengeGUI extends CommonGUI
icon = new ItemStack(Material.EXPERIENCE_BOTTLE); icon = new ItemStack(Material.EXPERIENCE_BOTTLE);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challenge.getRequiredExperience(), 0, (status, value) -> { new NumberGUI(this.user, this.challenge.getRequiredExperience(), 0, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challenge.setRequiredExperience(value); this.challenge.setRequiredExperience(value);
@ -843,7 +843,7 @@ public class EditChallengeGUI extends CommonGUI
{ {
icon = new ItemStack(Material.GOLD_INGOT); icon = new ItemStack(Material.GOLD_INGOT);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challenge.getRequiredMoney(), 0, (status, value) -> { new NumberGUI(this.user, this.challenge.getRequiredMoney(), 0, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challenge.setRequiredMoney(value); this.challenge.setRequiredMoney(value);
@ -969,7 +969,7 @@ public class EditChallengeGUI extends CommonGUI
"[value]", Integer.toString(this.challenge.getRewardExperience()))); "[value]", Integer.toString(this.challenge.getRewardExperience())));
icon = new ItemStack(Material.EXPERIENCE_BOTTLE); icon = new ItemStack(Material.EXPERIENCE_BOTTLE);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challenge.getRewardExperience(), 0, (status, value) -> { new NumberGUI(this.user, this.challenge.getRewardExperience(), 0, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challenge.setRewardExperience(value); this.challenge.setRewardExperience(value);
@ -995,7 +995,7 @@ public class EditChallengeGUI extends CommonGUI
{ {
icon = new ItemStack(Material.GOLD_INGOT); icon = new ItemStack(Material.GOLD_INGOT);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challenge.getRewardMoney(), 0, (status, value) -> { new NumberGUI(this.user, this.challenge.getRewardMoney(), 0, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challenge.setRewardMoney(value); this.challenge.setRewardMoney(value);
@ -1076,7 +1076,7 @@ public class EditChallengeGUI extends CommonGUI
icon = new ItemStack(Material.COBBLESTONE_WALL); icon = new ItemStack(Material.COBBLESTONE_WALL);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challenge.getMaxTimes(), 0, (status, value) -> { new NumberGUI(this.user, this.challenge.getMaxTimes(), 0, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challenge.setMaxTimes(value); this.challenge.setMaxTimes(value);
@ -1167,7 +1167,7 @@ public class EditChallengeGUI extends CommonGUI
icon = new ItemStack(Material.GLASS_BOTTLE); icon = new ItemStack(Material.GLASS_BOTTLE);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challenge.getRepeatExperienceReward(), 0, (status, value) -> { new NumberGUI(this.user, this.challenge.getRepeatExperienceReward(), 0, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challenge.setRepeatExperienceReward(value); this.challenge.setRepeatExperienceReward(value);
@ -1196,6 +1196,7 @@ public class EditChallengeGUI extends CommonGUI
new NumberGUI(this.user, new NumberGUI(this.user,
this.challenge.getRepeatMoneyReward(), this.challenge.getRepeatMoneyReward(),
0, 0,
lineLength,
(status, value) -> { (status, value) -> {
if (status) if (status)
{ {

View File

@ -116,6 +116,7 @@ public class EditLevelGUI extends CommonGUI
panelBuilder.item(10, this.createButton(Button.NAME)); panelBuilder.item(10, this.createButton(Button.NAME));
panelBuilder.item(19, this.createButton(Button.ICON)); panelBuilder.item(19, this.createButton(Button.ICON));
panelBuilder.item(28, this.createButton(Button.CLOSED_ICON));
panelBuilder.item(22, this.createButton(Button.UNLOCK_MESSAGE)); panelBuilder.item(22, this.createButton(Button.UNLOCK_MESSAGE));
panelBuilder.item(25, this.createButton(Button.ORDER)); panelBuilder.item(25, this.createButton(Button.ORDER));
@ -330,7 +331,7 @@ public class EditLevelGUI extends CommonGUI
{ {
name = this.user.getTranslation("challenges.gui.buttons.admin.icon"); name = this.user.getTranslation("challenges.gui.buttons.admin.icon");
description = Collections.singletonList(this.user.getTranslation( description = Collections.singletonList(this.user.getTranslation(
"challenges.gui.descriptions.admin.icon-challenge")); "challenges.gui.descriptions.admin.icon-level"));
icon = this.challengeLevel.getIcon(); icon = this.challengeLevel.getIcon();
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new AnvilGUI(this.addon.getPlugin(), new AnvilGUI(this.addon.getPlugin(),
@ -357,6 +358,55 @@ public class EditLevelGUI extends CommonGUI
glow = false; glow = false;
break; break;
} }
case CLOSED_ICON:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.locked-icon");
description = Collections.singletonList(this.user.getTranslation(
"challenges.gui.descriptions.admin.locked-icon"));
boolean isNull = this.challengeLevel.getLockedIcon() == null;
if (isNull)
{
icon = new ItemStack(Material.BARRIER);
}
else
{
icon = this.challengeLevel.getLockedIcon().clone();
}
clickHandler = (panel, user, clickType, slot) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
isNull ? "NULL" : icon.getType().name(),
(player, reply) -> {
if (reply.equals("NULL"))
{
this.challengeLevel.setLockedIcon(null);
this.build();
return reply;
}
Material material = Material.getMaterial(reply);
if (material != null)
{
this.challengeLevel.setLockedIcon(new ItemStack(material));
this.build();
}
else
{
this.user.sendMessage("challenges.errors.wrong-icon", "[value]", reply);
}
return reply;
});
return true;
};
glow = false;
break;
}
case UNLOCK_MESSAGE: case UNLOCK_MESSAGE:
{ {
name = this.user.getTranslation("challenges.gui.buttons.admin.description"); name = this.user.getTranslation("challenges.gui.buttons.admin.description");
@ -388,7 +438,7 @@ public class EditLevelGUI extends CommonGUI
"[value]", Integer.toString(this.challengeLevel.getOrder()))); "[value]", Integer.toString(this.challengeLevel.getOrder())));
icon = new ItemStack(Material.DROPPER); icon = new ItemStack(Material.DROPPER);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getOrder(), -1, 54, (status, value) -> { new NumberGUI(this.user, this.challengeLevel.getOrder(), -1, 54, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challengeLevel.setOrder(value); this.challengeLevel.setOrder(value);
@ -412,7 +462,7 @@ public class EditLevelGUI extends CommonGUI
icon = new ItemStack(Material.REDSTONE_TORCH); icon = new ItemStack(Material.REDSTONE_TORCH);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getWaiverAmount(), 0, (status, value) -> { new NumberGUI(this.user, this.challengeLevel.getWaiverAmount(), 0, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challengeLevel.setWaiverAmount(value); this.challengeLevel.setWaiverAmount(value);
@ -500,7 +550,7 @@ public class EditLevelGUI extends CommonGUI
"[value]", Integer.toString(this.challengeLevel.getRewardExperience()))); "[value]", Integer.toString(this.challengeLevel.getRewardExperience())));
icon = new ItemStack(Material.EXPERIENCE_BOTTLE); icon = new ItemStack(Material.EXPERIENCE_BOTTLE);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getRewardExperience(), 0, (status, value) -> { new NumberGUI(this.user, this.challengeLevel.getRewardExperience(), 0, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challengeLevel.setRewardExperience(value); this.challengeLevel.setRewardExperience(value);
@ -526,7 +576,7 @@ public class EditLevelGUI extends CommonGUI
{ {
icon = new ItemStack(Material.GOLD_INGOT); icon = new ItemStack(Material.GOLD_INGOT);
clickHandler = (panel, user, clickType, slot) -> { clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getRewardMoney(), 0, (status, value) -> { new NumberGUI(this.user, this.challengeLevel.getRewardMoney(), 0, lineLength, (status, value) -> {
if (status) if (status)
{ {
this.challengeLevel.setRewardMoney(value); this.challengeLevel.setRewardMoney(value);
@ -596,10 +646,10 @@ public class EditLevelGUI extends CommonGUI
() -> new LinkedHashMap<>(challengeList.size()))); () -> new LinkedHashMap<>(challengeList.size())));
// Open select gui // Open select gui
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, value) -> { new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> {
if (status) if (status)
{ {
manager.addChallengeToLevel(value, this.challengeLevel); valueSet.forEach(challenge -> manager.addChallengeToLevel(challenge, this.challengeLevel));
} }
this.build(); this.build();
@ -629,10 +679,10 @@ public class EditLevelGUI extends CommonGUI
() -> new LinkedHashMap<>(challengeList.size()))); () -> new LinkedHashMap<>(challengeList.size())));
// Open select gui // Open select gui
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, value) -> { new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> {
if (status) if (status)
{ {
manager.removeChallengeFromLevel(value, this.challengeLevel); valueSet.forEach(challenge -> manager.removeChallengeFromLevel(challenge, this.challengeLevel));
} }
this.build(); this.build();
@ -663,6 +713,7 @@ public class EditLevelGUI extends CommonGUI
{ {
NAME, NAME,
ICON, ICON,
CLOSED_ICON,
UNLOCK_MESSAGE, UNLOCK_MESSAGE,
ORDER, ORDER,
WAIVER_AMOUNT, WAIVER_AMOUNT,

View File

@ -3,15 +3,18 @@ package world.bentobox.challenges.panel.admin;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.wesjd.anvilgui.AnvilGUI; import net.wesjd.anvilgui.AnvilGUI;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder; import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon; import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.Settings;
import world.bentobox.challenges.panel.CommonGUI; import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.NumberGUI; import world.bentobox.challenges.panel.util.NumberGUI;
import world.bentobox.challenges.utils.GuiUtils; import world.bentobox.challenges.utils.GuiUtils;
@ -52,6 +55,7 @@ public class EditSettingsGUI extends CommonGUI
CommonGUI parentGUI) CommonGUI parentGUI)
{ {
super(addon, world, user, topLabel, permissionPrefix, parentGUI); super(addon, world, user, topLabel, permissionPrefix, parentGUI);
this.settings = this.addon.getChallengesSettings();
} }
@ -66,198 +70,393 @@ public class EditSettingsGUI extends CommonGUI
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name( PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.settings-title")); this.user.getTranslation("challenges.gui.title.admin.settings-title"));
final int lineLength = this.addon.getChallengesSettings().getLoreLineLength();
GuiUtils.fillBorder(panelBuilder); GuiUtils.fillBorder(panelBuilder);
// resetChallenges panelBuilder.item(19, this.getSettingsButton(Button.RESET_CHALLENGES));
panelBuilder.item(28, this.getSettingsButton(Button.BROADCAST));
List<String> description = new ArrayList<>(2); panelBuilder.item(20, this.getSettingsButton(Button.GLOW_COMPLETED));
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reset-on-new")); panelBuilder.item(29, this.getSettingsButton(Button.REMOVE_COMPLETED));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.addon.getChallengesSettings().isResetChallenges() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
panelBuilder.item(19, new PanelItemBuilder(). panelBuilder.item(12, this.getSettingsButton(Button.LOCKED_LEVEL_ICON));
name(this.user.getTranslation("challenges.gui.buttons.admin.reset-on-new")). panelBuilder.item(21, this.getSettingsButton(Button.FREE_AT_TOP));
description(GuiUtils.stringSplit(description, lineLength)). panelBuilder.item(30, this.getSettingsButton(Button.GAMEMODE_GUI));
icon(Material.LAVA_BUCKET).
clickHandler((panel, user1, clickType, i) -> {
this.addon.getChallengesSettings().setResetChallenges(
!this.addon.getChallengesSettings().isResetChallenges());
this.build();
return true;
}).
glow(this.addon.getChallengesSettings().isResetChallenges()).
build());
// broadcastMessages panelBuilder.item(14, this.getSettingsButton(Button.LORE_LENGTH));
description.clear(); panelBuilder.item(23, this.getSettingsButton(Button.CHALLENGE_LORE));
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.broadcast")); panelBuilder.item(32, this.getSettingsButton(Button.LEVEL_LORE));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.addon.getChallengesSettings().isBroadcastMessages() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
panelBuilder.item(20, new PanelItemBuilder(). panelBuilder.item(24, this.getSettingsButton(Button.HISTORY));
name(this.user.getTranslation("challenges.gui.buttons.admin.broadcast")).
description(GuiUtils.stringSplit(description, lineLength)).
icon(Material.JUKEBOX).
clickHandler((panel, user1, clickType, i) -> {
this.addon.getChallengesSettings().setBroadcastMessages(
!this.addon.getChallengesSettings().isBroadcastMessages());
this.build();
return true;
}).
glow(this.addon.getChallengesSettings().isBroadcastMessages()).
build());
// removeCompleteOneTimeChallenges if (this.settings.isStoreHistory())
description.clear(); {
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-completed")); panelBuilder.item(33, this.getSettingsButton(Button.PURGE_HISTORY));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", }
"[value]",
this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
panelBuilder.item(21, new PanelItemBuilder(). panelBuilder.item(25, this.getSettingsButton(Button.STORE_MODE));
name(this.user.getTranslation("challenges.gui.buttons.admin.remove-completed")).
description(GuiUtils.stringSplit(description, lineLength)).
icon(Material.MAGMA_BLOCK).
clickHandler((panel, user1, clickType, i) -> {
this.addon.getChallengesSettings().setRemoveCompleteOneTimeChallenges(
!this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges());
this.build();
return true;
}).
glow(this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges()).
build());
// addCompletedGlow
description.clear();
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.glow"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.addon.getChallengesSettings().isAddCompletedGlow() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
panelBuilder.item(22, new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin.glow")).
description(GuiUtils.stringSplit(description, lineLength)).
icon(Material.GLOWSTONE).
clickHandler((panel, user1, clickType, i) -> {
this.addon.getChallengesSettings().setAddCompletedGlow(
!this.addon.getChallengesSettings().isAddCompletedGlow());
this.build();
return true;
}).
glow(this.addon.getChallengesSettings().isAddCompletedGlow()).
build());
// freeChallengesAtTheTop
description.clear();
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.free-at-top"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.addon.getChallengesSettings().isAddCompletedGlow() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
panelBuilder.item(23, new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin.free-at-top")).
description(GuiUtils.stringSplit(description, lineLength)).
icon(Material.FILLED_MAP).
clickHandler((panel, user1, clickType, i) -> {
this.addon.getChallengesSettings().setFreeChallengesFirst(
!this.addon.getChallengesSettings().isFreeChallengesFirst());
this.build();
return true;
}).
glow(this.addon.getChallengesSettings().isFreeChallengesFirst()).
build());
// Challenge Lore Message
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.challenge-lore"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", this.addon.getChallengesSettings().getChallengeLoreMessage()));
panelBuilder.item(24, new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin.challenge-lore")).
description(GuiUtils.stringSplit(description, lineLength)).
icon(Material.PAPER).
clickHandler((panel, user1, clickType, i) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
this.addon.getChallengesSettings().getChallengeLoreMessage(),
(player, reply) -> {
this.addon.getChallengesSettings().setChallengeLoreMessage(reply);
this.build();
return reply;
});
return true;
}).
glow(false).
build());
// Level Lore Message
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.level-lore"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", this.addon.getChallengesSettings().getLevelLoreMessage()));
panelBuilder.item(33, new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin.level-lore")).
description(GuiUtils.stringSplit(description, lineLength)).
icon(Material.PAPER).
clickHandler((panel, user1, clickType, i) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
this.addon.getChallengesSettings().getLevelLoreMessage(),
(player, reply) -> {
this.addon.getChallengesSettings().setLevelLoreMessage(reply);
this.build();
return reply;
});
return true;
}).
glow(false).
build());
// Lore line length
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.line-length"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.addon.getChallengesSettings().getLoreLineLength())));
panelBuilder.item(25, new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin.line-length")).
description(GuiUtils.stringSplit(description, lineLength)).
icon(Material.ANVIL).
clickHandler((panel, user1, clickType, i) -> {
new NumberGUI(this.user,
this.addon.getChallengesSettings().getLoreLineLength(),
0,
(status, value) -> {
if (status)
{
this.addon.getChallengesSettings().setLoreLineLength(value);
}
this.build();
});
return true;
}).
glow(this.addon.getChallengesSettings().isFreeChallengesFirst()).
build());
// Return Button // Return Button
panelBuilder.item(44, this.returnButton); panelBuilder.item(44, this.returnButton);
panelBuilder.build(); panelBuilder.build();
} }
private PanelItem getSettingsButton(Button button)
{
ItemStack icon;
String name;
List<String> description;
boolean glow;
PanelItem.ClickHandler clickHandler;
switch (button)
{
case RESET_CHALLENGES:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reset-on-new"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isResetChallenges() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.reset-on-new");
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setResetChallenges(
!this.settings.isResetChallenges());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isResetChallenges();
break;
}
case BROADCAST:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.broadcast"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isBroadcastMessages() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
description = new ArrayList<>(2);
name = this.user.getTranslation("challenges.gui.buttons.admin.broadcast");
icon = new ItemStack(Material.JUKEBOX);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setBroadcastMessages(
!this.settings.isBroadcastMessages());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isBroadcastMessages();
break;
}
case REMOVE_COMPLETED:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-completed"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isRemoveCompleteOneTimeChallenges() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.remove-completed");
icon = new ItemStack(Material.MAGMA_BLOCK);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setRemoveCompleteOneTimeChallenges(
!this.settings.isRemoveCompleteOneTimeChallenges());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isRemoveCompleteOneTimeChallenges();
break;
}
case LORE_LENGTH:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.line-length"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.settings.getLoreLineLength())));
name = this.user.getTranslation("challenges.gui.buttons.admin.line-length");
icon = new ItemStack(Material.ANVIL);
clickHandler = (panel, user1, clickType, i) -> {
new NumberGUI(this.user,
this.settings.getLoreLineLength(),
0,
this.settings.getLoreLineLength(),
(status, value) -> {
if (status)
{
this.settings.setLoreLineLength(value);
}
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
});
return true;
};
glow = false;
break;
}
case LEVEL_LORE:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.level-lore"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", this.settings.getLevelLoreMessage()));
name = this.user.getTranslation("challenges.gui.buttons.admin.level-lore");
icon = new ItemStack(Material.PAPER);
clickHandler = (panel, user1, clickType, i) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
this.settings.getLevelLoreMessage(),
(player, reply) -> {
this.settings.setLevelLoreMessage(reply);
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return reply;
});
return true;
};
glow = false;
break;
}
case CHALLENGE_LORE:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.challenge-lore"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", this.settings.getChallengeLoreMessage()));
name = this.user.getTranslation("challenges.gui.buttons.admin.challenge-lore");
icon = new ItemStack(Material.PAPER);
clickHandler = (panel, user1, clickType, i) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
this.settings.getChallengeLoreMessage(),
(player, reply) -> {
this.settings.setChallengeLoreMessage(reply);
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return reply;
});
return true;
};
glow = false;
break;
}
case FREE_AT_TOP:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.free-at-top"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isAddCompletedGlow() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.free-at-top");
icon = new ItemStack(Material.FILLED_MAP);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setFreeChallengesFirst(!this.settings.isFreeChallengesFirst());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isFreeChallengesFirst();
break;
}
case GLOW_COMPLETED:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.glow"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isAddCompletedGlow() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.glow");
icon = new ItemStack(Material.GLOWSTONE);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setAddCompletedGlow(!this.settings.isAddCompletedGlow());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isAddCompletedGlow();
break;
}
case GAMEMODE_GUI:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.gui-view-mode"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.getUserGuiMode().equals(Settings.GuiMode.GAMEMODE_LIST) ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.gui-view-mode");
icon = new ItemStack(Material.GLOWSTONE);
clickHandler = (panel, user1, clickType, i) -> {
if (this.settings.getUserGuiMode().equals(Settings.GuiMode.GAMEMODE_LIST))
{
this.settings.setUserGuiMode(Settings.GuiMode.CURRENT_WORLD);
}
else
{
this.settings.setUserGuiMode(Settings.GuiMode.GAMEMODE_LIST);
}
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.getUserGuiMode().equals(Settings.GuiMode.GAMEMODE_LIST);
break;
}
case HISTORY:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.history-store"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isStoreHistory() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.history-store");
icon = new ItemStack(Material.GLOWSTONE);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setStoreHistory(!this.settings.isStoreHistory());
// Need to rebuild all as new buttons will show up.
this.build();
return true;
};
glow = this.settings.isStoreHistory();
break;
}
case PURGE_HISTORY:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.history-lifespan"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.settings.getLifeSpan())));
name = this.user.getTranslation("challenges.gui.buttons.admin.history-lifespan");
icon = new ItemStack(Material.ANVIL);
clickHandler = (panel, user1, clickType, i) -> {
new NumberGUI(this.user,
this.settings.getLifeSpan(),
0,
this.settings.getLoreLineLength(),
(status, value) -> {
if (status)
{
this.settings.setLifeSpan(value);
}
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
});
return true;
};
glow = false;
break;
}
case STORE_MODE:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.island-store"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isStoreAsIslandData() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.island-store");
icon = new ItemStack(Material.GLOWSTONE);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setStoreAsIslandData(!this.settings.isStoreAsIslandData());
// TODO: Data Migration must be added here.
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isStoreAsIslandData();
break;
}
case LOCKED_LEVEL_ICON:
{
description = new ArrayList<>(1);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.default-locked-icon"));
name = this.user.getTranslation("challenges.gui.buttons.admin.default-locked-icon");
icon = this.settings.getLockedLevelIcon();
clickHandler = (panel, user, clickType, slot) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
this.settings.getLockedLevelIcon().getType().name(),
(player, reply) -> {
Material material = Material.getMaterial(reply);
if (material != null)
{
this.settings.setLockedLevelIcon(new ItemStack(material));
this.build();
}
else
{
this.user.sendMessage("challenges.errors.wrong-icon", "[value]", reply);
}
return reply;
});
return true;
};
glow = false;
break;
}
default:
return new PanelItemBuilder().build();
}
return new PanelItem(icon, name, GuiUtils.stringSplit(description, this.settings.getLoreLineLength()), glow, clickHandler, false);
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This enum holds all settings buttons that must have been displayed in this panel.
*/
private enum Button
{
RESET_CHALLENGES,
BROADCAST,
REMOVE_COMPLETED,
LORE_LENGTH,
LEVEL_LORE,
CHALLENGE_LORE,
FREE_AT_TOP,
GAMEMODE_GUI,
HISTORY,
PURGE_HISTORY,
STORE_MODE,
GLOW_COMPLETED,
LOCKED_LEVEL_ICON
}
/**
* This allows faster access to challenges settings object.
*/
private Settings settings;
} }

View File

@ -175,8 +175,7 @@ public class ListUsersGUI extends CommonGUI
{ {
int lineLength = this.addon.getChallengesSettings().getLoreLineLength(); int lineLength = this.addon.getChallengesSettings().getLoreLineLength();
if (this.addon.getIslands().hasIsland(this.world, player.getUniqueId()) || if (this.addon.getIslands().getIsland(this.world, player.getUniqueId()) != null)
this.addon.getIslands().inTeam(this.world, player.getUniqueId()))
{ {
return new PanelItemBuilder().name(player.getName()).icon(player.getName()).clickHandler( return new PanelItemBuilder().name(player.getName()).icon(player.getName()).clickHandler(
(panel, user1, clickType, slot) -> { (panel, user1, clickType, slot) -> {
@ -190,21 +189,19 @@ public class ListUsersGUI extends CommonGUI
for (Challenge challenge : manager.getAllChallenges(this.world)) 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)); challengeDescriptionMap.put(challenge, this.generateChallengeDescription(challenge, player));
} }
} }
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, value) -> { new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> {
if (status) if (status)
{ {
manager.setChallengeComplete(User.getInstance(player), value); valueSet.forEach(challenge -> manager.setChallengeComplete(player.getUniqueId(), this.world, challenge, this.user.getUniqueId()));
}
else
{
this.build();
} }
this.build();
}); });
break; break;
case RESET: case RESET:
@ -212,28 +209,26 @@ public class ListUsersGUI extends CommonGUI
for (Challenge challenge : manager.getAllChallenges(this.world)) 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)); challengeDescriptionMap.put(challenge, this.generateChallengeDescription(challenge, player));
} }
} }
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, value) -> { new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> {
if (status) if (status)
{ {
manager.resetChallenge(User.getInstance(player), value); valueSet.forEach(challenge -> manager.resetChallenge(player.getUniqueId(), this.world, challenge, this.user.getUniqueId()));
}
else
{
this.build();
} }
this.build();
}); });
break; break;
case RESET_ALL: case RESET_ALL:
new ConfirmationGUI(this.user, status -> { new ConfirmationGUI(this.user, status -> {
if (status) if (status)
{ {
manager.resetAllChallenges(this.user, this.world); manager.resetAllChallenges(player.getUniqueId(), this.world, this.user.getUniqueId());
} }
this.build(); this.build();

View File

@ -175,15 +175,19 @@ public class ManageBlocksGUI extends CommonGUI
} }
else else
{ {
new NumberGUI(this.user, this.materialMap.get(material), 1, (status, value) -> { new NumberGUI(this.user,
if (status) this.materialMap.get(material),
{ 1,
// Update value only when something changes. this.addon.getChallengesSettings().getLoreLineLength(),
this.materialMap.put(material, value); (status, value) -> {
} if (status)
{
// Update value only when something changes.
this.materialMap.put(material, value);
}
this.build(); this.build();
}); });
} }
return true; return true;
}). }).

View File

@ -189,15 +189,19 @@ public class ManageEntitiesGUI extends CommonGUI
} }
else else
{ {
new NumberGUI(this.user, this.requiredEntities.get(entity), 1, (status, value) -> { new NumberGUI(this.user,
if (status) this.requiredEntities.get(entity),
{ 1,
// Update value only when something changes. this.addon.getChallengesSettings().getLoreLineLength(),
this.requiredEntities.put(entity, value); (status, value) -> {
} if (status)
{
// Update value only when something changes.
this.requiredEntities.put(entity, value);
}
this.build(); this.build();
}); });
} }
return true; return true;
}). }).

View File

@ -14,7 +14,7 @@ import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.ChallengesManager; import world.bentobox.challenges.ChallengesManager;
import world.bentobox.challenges.database.object.Challenge; import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.panel.CommonGUI; import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.TryToComplete; import world.bentobox.challenges.tasks.TryToComplete;
import world.bentobox.challenges.utils.GuiUtils; import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.LevelStatus; import world.bentobox.challenges.utils.LevelStatus;
@ -46,7 +46,7 @@ public class ChallengesGUI extends CommonGUI
super(addon, world, user, topLabel, permissionPrefix); super(addon, world, user, topLabel, permissionPrefix);
this.challengesManager = this.addon.getChallengesManager(); 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) for (LevelStatus levelStatus : this.levelStatusList)
{ {
@ -148,7 +148,7 @@ public class ChallengesGUI extends CommonGUI
if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges()) if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges())
{ {
freeChallenges.removeIf(challenge -> !challenge.isRepeatable() && freeChallenges.removeIf(challenge -> !challenge.isRepeatable() &&
this.challengesManager.isChallengeComplete(this.user, challenge)); this.challengesManager.isChallengeComplete(this.user, this.world, challenge));
} }
final int freeChallengesCount = freeChallenges.size(); final int freeChallengesCount = freeChallenges.size();
@ -218,7 +218,7 @@ public class ChallengesGUI extends CommonGUI
if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges()) if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges())
{ {
challenges.removeIf(challenge -> !challenge.isRepeatable() && challenges.removeIf(challenge -> !challenge.isRepeatable() &&
this.challengesManager.isChallengeComplete(this.user, challenge)); this.challengesManager.isChallengeComplete(this.user, this.world, challenge));
} }
final int challengesCount = challenges.size(); final int challengesCount = challenges.size();
@ -366,7 +366,7 @@ public class ChallengesGUI extends CommonGUI
return true; return true;
}). }).
glow(this.addon.getChallengesSettings().isAddCompletedGlow() && glow(this.addon.getChallengesSettings().isAddCompletedGlow() &&
this.challengesManager.isChallengeComplete(this.user, challenge)). this.challengesManager.isChallengeComplete(this.user, this.world, challenge)).
build(); build();
} }
@ -413,11 +413,20 @@ public class ChallengesGUI extends CommonGUI
return true; return true;
}; };
glow = this.addon.getChallengesSettings().isAddCompletedGlow() && glow = this.addon.getChallengesSettings().isAddCompletedGlow() &&
this.challengesManager.isLevelCompleted(this.user, level.getLevel()); this.challengesManager.isLevelCompleted(this.user, this.world, level.getLevel());
} }
else else
{ {
icon = new ItemStack(Material.BOOK); if (level.getLevel().getLockedIcon() != null)
{
// Clone will prevent issues with description storing.
// It can be done only here as it can be null.
icon = level.getLevel().getLockedIcon().clone();
}
else
{
icon = this.addon.getChallengesSettings().getLockedLevelIcon();
}
description = GuiUtils.stringSplit( description = GuiUtils.stringSplit(
this.user.getTranslation("challenges.gui.descriptions.level-locked", this.user.getTranslation("challenges.gui.descriptions.level-locked",

View File

@ -2,9 +2,8 @@ package world.bentobox.challenges.panel.util;
import org.bukkit.Material; import org.bukkit.Material;
import java.util.ArrayList; import org.bukkit.event.inventory.ClickType;
import java.util.List; import java.util.*;
import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.PanelItem;
@ -20,13 +19,14 @@ import world.bentobox.challenges.utils.GuiUtils;
*/ */
public class SelectChallengeGUI public class SelectChallengeGUI
{ {
public SelectChallengeGUI(User user, Map<Challenge, List<String>> challengesDescriptionMap, int lineLength, BiConsumer<Boolean, Challenge> consumer) public SelectChallengeGUI(User user, Map<Challenge, List<String>> challengesDescriptionMap, int lineLength, BiConsumer<Boolean, Set<Challenge>> consumer)
{ {
this.consumer = consumer; this.consumer = consumer;
this.user = user; this.user = user;
this.challengesList = new ArrayList<>(challengesDescriptionMap.keySet()); this.challengesList = new ArrayList<>(challengesDescriptionMap.keySet());
this.challengesDescriptionMap = challengesDescriptionMap; this.challengesDescriptionMap = challengesDescriptionMap;
this.lineLength = lineLength; this.lineLength = lineLength;
this.selectedChallenges = new HashSet<>(this.challengesList.size());
this.build(0); this.build(0);
} }
@ -129,14 +129,46 @@ public class SelectChallengeGUI
*/ */
private PanelItem createChallengeButton(Challenge challenge) private PanelItem createChallengeButton(Challenge challenge)
{ {
List<String> description;
if (this.selectedChallenges.contains(challenge))
{
description = new ArrayList<>();
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.selected"));
description.addAll(this.challengesDescriptionMap.get(challenge));
}
else
{
description = this.challengesDescriptionMap.get(challenge);
}
return new PanelItemBuilder(). return new PanelItemBuilder().
name(challenge.getFriendlyName()). name(challenge.getFriendlyName()).
description(GuiUtils.stringSplit(this.challengesDescriptionMap.get(challenge), this.lineLength)). description(GuiUtils.stringSplit(description, this.lineLength)).
icon(challenge.getIcon()). icon(challenge.getIcon()).
clickHandler((panel, user1, clickType, slot) -> { clickHandler((panel, user1, clickType, slot) -> {
this.consumer.accept(true, challenge); if (clickType == ClickType.RIGHT)
{
// If challenge is not selected, then select :)
if (!this.selectedChallenges.remove(challenge))
{
this.selectedChallenges.add(challenge);
}
// Reset button.
panel.getInventory().setItem(slot, this.createChallengeButton(challenge).getItem());
}
else
{
this.selectedChallenges.add(challenge);
this.consumer.accept(true, this.selectedChallenges);
}
return true; return true;
}).build(); }).
glow(this.selectedChallenges.contains(challenge)).
build();
} }
@ -148,7 +180,7 @@ public class SelectChallengeGUI
/** /**
* This variable stores consumer. * This variable stores consumer.
*/ */
private BiConsumer<Boolean, Challenge> consumer; private BiConsumer<Boolean, Set<Challenge>> consumer;
/** /**
* User who runs GUI. * User who runs GUI.
@ -160,6 +192,11 @@ public class SelectChallengeGUI
*/ */
private List<Challenge> challengesList; private List<Challenge> challengesList;
/**
* Selected challenges that will be returned to consumer.
*/
private Set<Challenge> selectedChallenges;
/** /**
* Map that contains all challenge descriptions * Map that contains all challenge descriptions
*/ */

View File

@ -1,9 +1,10 @@
/** /**
* *
*/ */
package world.bentobox.challenges.panel; package world.bentobox.challenges.tasks;
import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -271,15 +272,15 @@ public class TryToComplete
} }
// Mark as complete // Mark as complete
this.manager.setChallengeComplete(this.user, this.challenge); this.manager.setChallengeComplete(this.user, this.world, this.challenge);
if (!result.repeat) if (!result.repeat)
{ {
ChallengeLevel level = this.manager.getLevel(this.challenge); 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 // Item rewards
for (ItemStack reward : level.getRewardItems()) for (ItemStack reward : level.getRewardItems())
@ -317,7 +318,7 @@ public class TryToComplete
} }
} }
this.manager.setLevelComplete(this.user, level); this.manager.setLevelComplete(this.user, this.world, level);
} }
} }
} }
@ -349,27 +350,36 @@ public class TryToComplete
result = EMPTY_RESULT; result = EMPTY_RESULT;
} }
// Player is not on island // Player is not on island
else if (!this.addon.getIslands().userIsOnIsland(this.user.getWorld(), this.user)) else if (ChallengesAddon.CHALLENGES_WORLD_PROTECTION.isSetForWorld(this.world) &&
!this.addon.getIslands().userIsOnIsland(this.user.getWorld(), this.user))
{ {
this.user.sendMessage("challenges.errors.not-on-island"); this.user.sendMessage("challenges.errors.not-on-island");
result = EMPTY_RESULT; result = EMPTY_RESULT;
} }
// Check player permission
else if (!this.addon.getIslands().getIslandAt(this.user.getLocation()).
map(i -> i.isAllowed(this.user, ChallengesAddon.CHALLENGES_ISLAND_PROTECTION)).
orElse(false))
{
this.user.sendMessage("challenges.errors.no-rank");
result = EMPTY_RESULT;
}
// Check if user has unlocked challenges level. // Check if user has unlocked challenges level.
else if (!this.challenge.getLevel().equals(ChallengesManager.FREE) && 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"); this.user.sendMessage("challenges.errors.challenge-level-not-available");
result = EMPTY_RESULT; result = EMPTY_RESULT;
} }
// Check max times // Check max times
else if (this.challenge.isRepeatable() && this.challenge.getMaxTimes() > 0 && 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"); this.user.sendMessage("challenges.errors.not-repeatable");
result = EMPTY_RESULT; result = EMPTY_RESULT;
} }
// Check repeatability // 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"); this.user.sendMessage("challenges.errors.not-repeatable");
result = EMPTY_RESULT; result = EMPTY_RESULT;
@ -492,53 +502,60 @@ public class TryToComplete
{ {
// Run through inventory // Run through inventory
List<ItemStack> required = new ArrayList<>(this.challenge.getRequiredItems()); List<ItemStack> required = new ArrayList<>(this.challenge.getRequiredItems());
for (ItemStack req : required)
{
// Check for FIREWORK_ROCKET, ENCHANTED_BOOK, WRITTEN_BOOK, POTION and FILLED_MAP because these have unique meta when created
switch (req.getType())
{
case FIREWORK_ROCKET:
case ENCHANTED_BOOK:
case WRITTEN_BOOK:
case FILLED_MAP:
// Get how many items are in the inventory. Item stacks amounts need to be summed
int numInInventory =
Arrays.stream(this.user.getInventory().getContents()).filter(Objects::nonNull).
filter(i -> i.getType().equals(req.getType())).
mapToInt(ItemStack::getAmount).
sum();
if (numInInventory < req.getAmount()) // Players in creative game mode has got all items. No point to search for them.
{ if (this.user.getPlayer().getGameMode() != GameMode.CREATIVE)
this.user.sendMessage("challenges.errors.not-enough-items", {
"[items]", for (ItemStack req : required)
Util.prettifyText(req.getType().toString())); {
return EMPTY_RESULT; // Check for FIREWORK_ROCKET, ENCHANTED_BOOK, WRITTEN_BOOK, POTION and
} // FILLED_MAP because these have unique meta when created
break; switch (req.getType())
default: {
// General checking case FIREWORK_ROCKET:
if (!this.user.getInventory().containsAtLeast(req, req.getAmount())) case ENCHANTED_BOOK:
{ case WRITTEN_BOOK:
this.user.sendMessage("challenges.errors.not-enough-items", case FILLED_MAP:
"[items]", // Get how many items are in the inventory. Item stacks amounts need to be summed
Util.prettifyText(req.getType().toString())); int numInInventory =
return EMPTY_RESULT; Arrays.stream(this.user.getInventory().getContents()).
} filter(Objects::nonNull).
filter(i -> i.getType().equals(req.getType())).
mapToInt(ItemStack::getAmount).
sum();
if (numInInventory < req.getAmount())
{
this.user.sendMessage("challenges.errors.not-enough-items",
"[items]",
Util.prettifyText(req.getType().toString()));
return EMPTY_RESULT;
}
break;
default:
// General checking
if (!this.user.getInventory().containsAtLeast(req, req.getAmount()))
{
this.user.sendMessage("challenges.errors.not-enough-items",
"[items]",
Util.prettifyText(req.getType().toString()));
return EMPTY_RESULT;
}
break;
}
}
// If remove items, then remove them
if (this.challenge.isTakeItems())
{
this.removeItems(required);
} }
} }
// If remove items, then remove them
if (this.challenge.isTakeItems())
{
this.removeItems(required);
}
// Return the result // Return the result
return new ChallengeResult().setMeetsRequirements().setRepeat( return new ChallengeResult().setMeetsRequirements().setRepeat(
this.manager.isChallengeComplete(this.user, this.challenge)); this.manager.isChallengeComplete(this.user, this.world, this.challenge));
} }
@ -796,8 +813,11 @@ public class TryToComplete
{ {
this.user.sendMessage("challenges.errors.incorrect"); this.user.sendMessage("challenges.errors.incorrect");
} }
else if (this.user.getPlayer().getTotalExperience() < this.challenge.getRequiredExperience()) else if (this.user.getPlayer().getTotalExperience() < this.challenge.getRequiredExperience() &&
this.user.getPlayer().getGameMode() != GameMode.CREATIVE)
{ {
// Players in creative gamemode has infinite amount of EXP.
this.user.sendMessage("challenges.errors.not-enough-experience", this.user.sendMessage("challenges.errors.not-enough-experience",
"[value]", "[value]",
Integer.toString(this.challenge.getRequiredExperience())); Integer.toString(this.challenge.getRequiredExperience()));
@ -816,8 +836,10 @@ public class TryToComplete
this.addon.getEconomyProvider().withdraw(this.user, this.challenge.getRequiredMoney()); this.addon.getEconomyProvider().withdraw(this.user, this.challenge.getRequiredMoney());
} }
if (this.challenge.isTakeExperience()) if (this.challenge.isTakeExperience() &&
this.user.getPlayer().getGameMode() != GameMode.CREATIVE)
{ {
// Cannot take anything from creative game mode.
this.user.getPlayer().setTotalExperience( this.user.getPlayer().setTotalExperience(
this.user.getPlayer().getTotalExperience() - this.challenge.getRequiredExperience()); this.user.getPlayer().getTotalExperience() - this.challenge.getRequiredExperience());
} }

View File

@ -2,8 +2,11 @@ name: Challenges
main: world.bentobox.challenges.ChallengesAddon main: world.bentobox.challenges.ChallengesAddon
version: ${version} version: ${version}
repository: 'BentoBoxWorld/Challenges' repository: 'BentoBoxWorld/Challenges'
metrics: true
authors: tastybento authors:
- tastybento
- BONNe
softdepend: AcidIsland, BSkyBlock, CaveBlock, SkyGrid, Level softdepend: AcidIsland, BSkyBlock, CaveBlock, SkyGrid, Level
@ -31,4 +34,4 @@ permissions:
default: true default: true
skygrid.admin.challenges: skygrid.admin.challenges:
description: Access challenge admin commands description: Access challenge admin commands
default: op default: op

View File

@ -1,10 +1,14 @@
########################################################################################## ##########################################################################################
# Example challenges.yml file. This is the same format as ASkyBlock. # Example challenges.yml file. This is the same format as ASkyBlock.
# Use the cimport command to import the challenges to your world. # Use the cimport command to import the challenges to your world.
# For example: /bsbadmin cimport # For example: /bsbadmin challenges import
# to overwrite previous challenges, use /bsbadmin cimport overwrite # to overwrite previous challenges, use /bsbadmin challenges import overwrite
# Once challenges are imported, you can edit them directly in the database folder. # Once challenges are imported, you can edit them directly in the database folder.
# BSkyBlock offers more features in the native challenge definition files. # BSkyBlock offers more features in the native challenge definition files.
# Do not use ASkyBlock format for editing challenges, as it misses a lot of functions that
# is added in new Challenges Add-on. This feature is just for admins who want to use old
# challenges for new BentoBox plugin.
# This is just a converter, not editor.
# #
########################################################################################## ##########################################################################################
# Rewards and required items have to be described using Bukkit Materials # Rewards and required items have to be described using Bukkit Materials

View File

@ -3,9 +3,97 @@
# You cannot edit it while the server is running because changes will # You cannot edit it while the server is running because changes will
# be lost! Use in-game settings GUI or edit when server is offline. # be lost! Use in-game settings GUI or edit when server is offline.
# #
commands:
#
# Allows to define common challenges command that will open User GUI
# with all GameMode selection or Challenges from user world.
# This will not affect /{gamemode_user} challenges command.
user: challenges c
#
# Allows to define common challenges command that will open Admin GUI
# with all GameMode selection.
# This will not affect /{gamemode_admin} challenges command.
admin: challengesadmin chadmin
#
# This enables/disables common command that will be independent from
# all GameModes. For admins it will open selection with all GameModes
# (unless there is one), but for users it will open GUI that corresponds
# to their world (unless it is specified other way in Admin GUI).
single-gui: false
#
# This allows for admins to define which GUI will be opened for admins
# when users calls single-gui command.
# Acceptable values:
# - CURRENT_WORLD - will open GUI that corresponds to user location.
# - GAMEMODE_LIST - will open GUI with all installed game modes.
single-gamemode: CURRENT_WORLD
history:
#
# This indicate if player challenges data history will be stored or not.
store-history-data: false
#
# This allows to specify an amount of time in days when history data will
# be removed. 0 means that data will not be removed.
lifespan: 14
gui-settings:
#
# Remove non-repeatable challenges from the challenge GUI when complete.
remove-complete-one-time-challenges: false
#
# Add enchanted glow to completed challenges
add-completed-glow: true
#
# This allows to change default locked level icon. This option may be
# overwritten by each challenge level. If challenge level has specified
# their locked level icon, then it will be used, instead of this one.
locked-level-icon:
==: org.bukkit.inventory.ItemStack
v: 1631
type: BOOK
#
# This indicate if free challenges must be at the start (true) or at the end (false) of list.
free-challenges-first: 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
#
# This string allows to change element order in Challenge description. Each letter represents
# one object from challenge description. If letter is not used, then its represented part
# will not be in description. If use any letter that is not recognized, then it will be
# ignored. Some strings can be customized via lang file under 'challenges.gui.challenge-description'.
# List of letters and their meaning:
# - L - Level String: '*.level'
# - S - Status String: '*.completed'
# - T - Times String: '*.completed-times', '*.completed-times-of' or '*.maxed-reached'
# - D - Description String: defined in challenge object - challenge.description
# - W - Warning String: '*.warning-items-take', '*.objects-close-by', '*.warning-entities-kill', '*.warning-blocks-remove'
# - E - Environment String: defined in challenge object - challenge.environment
# - Q - Requirement String: '*.required-level', '*.required-money', '*.required-experience'
# - R - Reward String: '*.experience-reward', '*.money-reward', '*.not-repeatable'
# By adding 'i' after Q or R (requirements and rewards) will display list of items, blocks
# and entities that are defined in challenge and can be customized under 'challenges.gui.description.*'
challenge-lore-message: LSTDEQiWRi
#
# This string allows to change element order in Level description. Each letter represents
# one object from level description. If letter is not used, then its represented part
# will not be in description. If use any letter that is not recognized, then it will be
# ignored. Some strings can be customized via lang file under 'challenges.gui.level-description'.
# List of letters and their meaning:
# - S - Status String: '*.completed'
# - T - Count of completed challenges String: '*.completed-challenges-of'
# - D - Description String: defined in level object - challengeLevel.unlockMessage
# - A - WaiverAmount String: '*.waver-amount'
# - R - Reward String: '*.experience-reward', '*.money-reward', '*.not-repeatable'
# By adding 'i' after R (rewards) will display list of items that are defined in challenge
# and can be customized under 'challenges.gui.description.*'
level-lore-message: STDARi
# #
# Reset Challenges - if this is true, player's challenges will reset when they # This indicate if challenges data will be stored per island (true) or per player (false).
# reset an island or if they are kicked or leave a team. Prevents exploiting the store-island-data: false
#
# Reset Challenges - if this is true, player's challenges will reset when users
# reset an island or if users are kicked or leave a team. Prevents exploiting the
# challenges by doing them repeatedly. # challenges by doing them repeatedly.
reset-challenges: true reset-challenges: true
# #
@ -13,50 +101,6 @@ reset-challenges: true
# Change to false if the spam becomes too much. # Change to false if the spam becomes too much.
broadcast-messages: true broadcast-messages: true
# #
# Remove non-repeatable challenges from the challenge GUI when complete.
remove-complete-one-time-challenges: false
#
# Add enchanted glow to completed challenges
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 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
#
# This string allows to change element order in Challenge description. Each letter represents
# one object from challenge description. If letter is not used, then its represented part
# will not be in description. If use any letter that is not recognized, then it will be
# ignored. Some strings can be customized via lang file under 'challenges.gui.challenge-description'.
# List of letters and their meaning:
# - L - Level String: '*.level'
# - S - Status String: '*.completed'
# - T - Times String: '*.completed-times', '*.completed-times-of' or '*.maxed-reached'
# - D - Description String: defined in challenge object - challenge.description
# - W - Warning String: '*.warning-items-take', '*.objects-close-by', '*.warning-entities-kill', '*.warning-blocks-remove'
# - E - Environment String: defined in challenge object - challenge.environment
# - Q - Requirement String: '*.required-level', '*.required-money', '*.required-experience'
# - R - Reward String: '*.experience-reward', '*.money-reward', '*.not-repeatable'
# By adding 'i' after Q or R (requirements and rewards) will display list of items, blocks
# and entities that are defined in challenge and can be customized under 'challenges.gui.description.*'
challenge-lore-message: LSTDEQiWRi
#
# This string allows to change element order in Level description. Each letter represents
# one object from level description. If letter is not used, then its represented part
# will not be in description. If use any letter that is not recognized, then it will be
# ignored. Some strings can be customized via lang file under 'challenges.gui.level-description'.
# List of letters and their meaning:
# - S - Status String: '*.completed'
# - T - Count of completed challenges String: '*.completed-challenges-of'
# - D - Description String: defined in level object - challengeLevel.unlockMessage
# - A - WaiverAmount String: '*.waver-amount'
# - R - Reward String: '*.experience-reward', '*.money-reward', '*.not-repeatable'
# By adding 'i' after R (rewards) will display list of items that are defined in challenge
# and can be customized under 'challenges.gui.description.*'
level-lore-message: STDARi
#
# This list stores GameModes in which Challenges addon should not work. # This list stores GameModes in which Challenges addon should not work.
# To disable addon it is necessary to write its name in new line that starts with -. Example: # To disable addon it is necessary to write its name in new line that starts with -. Example:
# disabled-gamemodes: # disabled-gamemodes:
@ -65,4 +109,4 @@ disabled-gamemodes: []
# #
uniqueId: config uniqueId: config
# #
configVersion: v1.1 configVersion: v2

View File

@ -78,6 +78,7 @@ challenges:
type: 'Challenge Type' type: 'Challenge Type'
deployment: 'Deployment' deployment: 'Deployment'
icon: 'Icon' icon: 'Icon'
locked-icon: 'Locked Icon'
description: 'Description' description: 'Description'
order: 'Order' order: 'Order'
environment: 'Environment' environment: 'Environment'
@ -136,6 +137,11 @@ challenges:
number: '[number]' number: '[number]'
level-lore: 'Level Description' level-lore: 'Level Description'
challenge-lore: 'Challenge Description' challenge-lore: 'Challenge Description'
gui-view-mode: 'Display All GameModes'
history-store: 'Challenges History'
history-lifespan: 'History LifeSpan'
island-store: 'Store per Island'
default-locked-icon: 'Locked Level Icon'
next: 'Next' next: 'Next'
previous: 'Previous' previous: 'Previous'
return: 'Return' return: 'Return'
@ -167,6 +173,7 @@ challenges:
deployment: 'Allows users to complete (view) challenge.' deployment: 'Allows users to complete (view) challenge.'
icon-challenge: 'Icon that will be displayed in GUI panels for this challenge.' icon-challenge: 'Icon that will be displayed in GUI panels for this challenge.'
icon-level: 'Icon that will be displayed in GUI panels for this level.' icon-level: 'Icon that will be displayed in GUI panels for this level.'
locked-icon: 'Icon that will be displayed in GUI panels if level is locked.'
description: 'Allows to edit description.' description: 'Allows to edit description.'
order: 'Allows to change order number.' order: 'Allows to change order number.'
environment: 'Allows to change environment where challenge operates.' environment: 'Allows to change environment where challenge operates.'
@ -218,6 +225,11 @@ challenges:
show-eggs: 'Switch entity view between Egg mode or Head mode.' show-eggs: 'Switch entity view between Egg mode or Head mode.'
level-lore: 'Allows to modify which elements of level description should be visible.' level-lore: 'Allows to modify which elements of level description should be visible.'
challenge-lore: 'Allows to modify which elements of challenge description should be visible.' challenge-lore: 'Allows to modify which elements of challenge description should be visible.'
gui-view-mode: 'Allows to set if /challenges GUI should show GameModes or challenges in players world.'
history-store: 'Allows to enable/disable challenges history storage.'
history-lifespan: 'Allows to modify how many days history data will be saved.|0 means forever.'
island-store: 'Allows to enable/disable challenges data string per island. This means that challenges will be the same on whole team, if this is enabled.|Will convert data on click.'
default-locked-icon: 'Allows to change default locked level icon.|This option can be overwritten by each level.'
current-value: '|&6Current value: [value].' current-value: '|&6Current value: [value].'
enabled: 'Active' enabled: 'Active'
disabled: 'Disabled' disabled: 'Disabled'
@ -307,4 +319,14 @@ challenges:
import-no-file: '&cCould not find challenges.yml file to import!' import-no-file: '&cCould not find challenges.yml file to import!'
no-load: '&cError: Could not load challenges.yml. [message]' no-load: '&cError: Could not load challenges.yml. [message]'
load-error: '&cError: Cannot load [value].' load-error: '&cError: Cannot load [value].'
version: 6 no-rank: "&cYou do not have rank to do that."
protection:
flags:
CHALLENGES_ISLAND_PROTECTION:
description: "&5&oToggle who can\n&5&ocomplete challenges"
name: "Challenges protection"
CHALLENGES_WORLD_PROTECTION:
description: "&5&oThis allows to enable/disable\n&5&orequirement for players to\n&5&obe on their island to\n&5&ocomplete a challenge."
name: "Challenges Island limitation"
hint: "No challenges outside island"
version: 9

View File

@ -1,124 +0,0 @@
package world.bentobox.challenges;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.inventory.ItemFactory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.inventory.meta.SpawnEggMeta;
import org.bukkit.plugin.PluginManager;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.ParseItem;
@RunWith(PowerMockRunner.class)
@Deprecated
public class ParseItemTest {
private static ChallengesAddon addon;
private static ItemFactory itemFactory;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
addon = mock(ChallengesAddon.class);
when(addon.getLogger()).thenReturn(Logger.getAnonymousLogger());
Server server = mock(Server.class);
World world = mock(World.class);
when(server.getLogger()).thenReturn(Logger.getAnonymousLogger());
when(server.getWorld("world")).thenReturn(world);
when(server.getVersion()).thenReturn("BSB_Mocking");
PluginManager pluginManager = mock(PluginManager.class);
when(server.getPluginManager()).thenReturn(pluginManager);
itemFactory = mock(ItemFactory.class);
when(server.getItemFactory()).thenReturn(itemFactory);
Bukkit.setServer(server);
SpawnEggMeta itemMeta = mock(SpawnEggMeta.class);
when(itemFactory.getItemMeta(any())).thenReturn(itemMeta);
when(Bukkit.getItemFactory()).thenReturn(itemFactory);
}
@Test
public void parseItemTest() {
// Nothing test
assertNull(new ParseItem(addon, "").getItem());
// other
assertNull(new ParseItem(addon, "::::::::::::::").getItem());
// other
assertNull(new ParseItem(addon, "anything:anything").getItem());
// Bad material
assertNull(new ParseItem(addon, "nosuchmaterial:2").getItem());
// Material
for (Material mat : Material.values()) {
ItemStack test = new ParseItem(addon, mat.name() + ":5").getItem();
if (test != null) {
if (test.getType().toString().endsWith("_ITEM") && !mat.toString().endsWith("_ITEM")) {
assertEquals(mat.toString() + "_ITEM", test.getType().toString());
} else {
assertEquals(mat, test.getType());
}
}
}
// Nothing amount
ItemStack test = new ParseItem(addon, "STONE:").getItem();
assertNull(test);
// Test 3
// Bad material
assertNull(new ParseItem(addon, "nosuchmaterial:2:2").getItem());
// Bad amount
assertNull(new ParseItem(addon, "STONE:1:sdfgsd").getItem());
// Missing amount = 1
test = new ParseItem(addon, "STONE:1:").getItem();
assertNotNull(test); // This is okay, it's just a 2
// Test Potions
PotionMeta itemMeta = mock(PotionMeta.class);
when(itemFactory.getItemMeta(any())).thenReturn(itemMeta);
when(Bukkit.getItemFactory()).thenReturn(itemFactory);
// Bad material
assertNull(new ParseItem(addon, "nosuchmaterial:JUMP:2:NOTEXTENDED:NOSPLASH:2").getItem());
// Bad amount
assertNull(new ParseItem(addon, "POTION:JUMP:2:NOTEXTENDED:NOSPLASH:asfdas").getItem());
test = new ParseItem(addon, "POTION:JUMP:2:NOTEXTENDED:NOSPLASH:").getItem();
assertNull(test);
test = new ParseItem(addon, "POTION:JUMP:2:NOTEXTENDED:NOSPLASH:1").getItem();
assertEquals(Material.POTION, test.getType());
test = new ParseItem(addon, "POTION:JUMP:2").getItem();
assertEquals(Material.POTION, test.getType());
test = new ParseItem(addon, "POTION:STRENGTH:1:EXTENDED:SPLASH:1").getItem();
assertEquals(Material.SPLASH_POTION, test.getType());
test = new ParseItem(addon, "POTION:INSTANT_DAMAGE:2::LINGER:2").getItem();
assertEquals(Material.LINGERING_POTION, test.getType());
test = new ParseItem(addon, "TIPPED_ARROW:STRENGTH:1:::1").getItem();
assertEquals(Material.TIPPED_ARROW, test.getType());
}
}

View File

@ -1,7 +1,7 @@
/** /**
* *
*/ */
package world.bentobox.challenges.panel; package world.bentobox.challenges.tasks;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@ -58,7 +58,7 @@ public class TryToCompleteTest {
} }
/** /**
* Test method for {@link world.bentobox.challenges.panel.TryToComplete#removeItems(java.util.List)}. * Test method for {@link TryToComplete#removeItems(java.util.List)}.
*/ */
@Test @Test
public void testRemoveItemsSuccess() { public void testRemoveItemsSuccess() {
@ -72,7 +72,7 @@ public class TryToCompleteTest {
} }
/** /**
* Test method for {@link world.bentobox.challenges.panel.TryToComplete#removeItems(java.util.List)}. * Test method for {@link TryToComplete#removeItems(java.util.List)}.
*/ */
@Test @Test
public void testRemoveItemsMax() { public void testRemoveItemsMax() {
@ -86,7 +86,7 @@ public class TryToCompleteTest {
} }
/** /**
* Test method for {@link world.bentobox.challenges.panel.TryToComplete#removeItems(java.util.List)}. * Test method for {@link TryToComplete#removeItems(java.util.List)}.
*/ */
@Test @Test
public void testRemoveItemsZero() { public void testRemoveItemsZero() {
@ -100,7 +100,7 @@ public class TryToCompleteTest {
} }
/** /**
* Test method for {@link world.bentobox.challenges.panel.TryToComplete#removeItems(java.util.List)}. * Test method for {@link TryToComplete#removeItems(java.util.List)}.
*/ */
@Test @Test
public void testRemoveItemsSuccessMultiple() { public void testRemoveItemsSuccessMultiple() {
@ -114,7 +114,7 @@ public class TryToCompleteTest {
} }
/** /**
* Test method for {@link world.bentobox.challenges.panel.TryToComplete#removeItems(java.util.List)}. * Test method for {@link TryToComplete#removeItems(java.util.List)}.
*/ */
@Test @Test
public void testRemoveItemsSuccessMultipleOther() { public void testRemoveItemsSuccessMultipleOther() {
@ -131,7 +131,7 @@ public class TryToCompleteTest {
} }
/** /**
* Test method for {@link world.bentobox.challenges.panel.TryToComplete#removeItems(java.util.List)}. * Test method for {@link TryToComplete#removeItems(java.util.List)}.
*/ */
@Test @Test
public void testRemoveItemsMultipleOtherFail() { public void testRemoveItemsMultipleOtherFail() {
@ -148,7 +148,7 @@ public class TryToCompleteTest {
} }
/** /**
* Test method for {@link world.bentobox.challenges.panel.TryToComplete#removeItems(java.util.List)}. * Test method for {@link TryToComplete#removeItems(java.util.List)}.
*/ */
@Test @Test
public void testRemoveItemsFail() { public void testRemoveItemsFail() {