Prepare 0.5.0 release.

This commit is contained in:
BONNe1704 2019-02-13 13:08:14 +02:00
commit 8845270a79
60 changed files with 12750 additions and 1438 deletions

View File

@ -1,25 +1,47 @@
# addon-challenges
Add-on for BentoBox to provide challenges for BSkyBlock and AcidIsland. This add-on will work
for both game modes.
# Challenges Addon
[![Build Status](https://ci.codemc.org/buildStatus/icon?job=BentoBoxWorld/Challenges)](https://ci.codemc.org/job/BentoBoxWorld/job/Challenges/)
Add-on for BentoBox to provide challenges for any BentoBox GameMode.
## Where to find
Currently Challenges Addon is in **Beta stage**, so it may or may not contain bugs... a lot of bugs. Also it means, that some features are not working or implemented.
Latest official **Beta Release is 0.5.0**, and you can download it from [Release tab](https://github.com/BentoBoxWorld/Challenges/releases)
Or you can try **nightly builds** where you can check and test new features that will be implemented in next release from [Jenkins Server](https://ci.codemc.org/job/BentoBoxWorld/job/Challenges/lastStableBuild/).
If you like this addon but something is missing or is not working as you want, you can always submit an [Issue request](https://github.com/BentoBoxWorld/Challenges/issues) or get a support in Discord [BentoBox ![icon](https://avatars2.githubusercontent.com/u/41555324?s=15&v=4)](https://discord.gg/JgWKvR)
## How to use
1. Place the addon jar in the addons folder of the BentoBox plugin
2. Restart the server
3. The addon will create a data folder and inside the folder will be a config.yml and an example challenges.yml
4. Edit the config.yml and challenges.yml files how you want. Note that unlike ASkyBlock, the challenges.yml is for *importing only*.
4. Edit the config.yml and challenges.yml files how you want. Note that unlike ASkyBlock, the challenges.yml is for *importing only* and faster start.
5. Restart the server
6. To import challenges into BSkyBlock do /bsb challenges import. To import into AcidIsland do /acid challenges import.
6. To import challenges into GameMode, you must run admin command and attach `challenges import` at the end. Or you can use challenges admin GUI to do the same.
## Compatibility
- [x] BSkyBlock - since 1.1 version
- [ ] AcidIsland - only in snapshots from #85 build.
- [x] SkyGrid
- [x] CaveBlock
## Config.yml
As most of BenotBox addons, config can be edited only when server is stopped. Otherwise all changes will be overwritten by server.
The config.yml has the following sections:
* Reset Challenges - if this is true, player's challenges will reset when they reset an island or if they are kicked or leave a team. Prevents exploiting the challenges by doing them repeatedly. Default is true
* Broadcast 1st time challenge completion messages to all players. Change to false if the spam becomes too much. Default is true.
* Remove non-repeatable challenges from the challenge GUI when complete. Default is false.
* Add enchanted glow to completed challenges. Default is true
* Free challenges location - You can decide, either free challenges will be at the top, or at the bottom.
* Description line length - allows to specify maximal line length in GUI icon descriptions.
* Challenge Description structure - allows to modify structure of challenge description.
* Level Description structure - allows to modify structure of Level description.
* Disabled GameModes - specify Game Modes where challenges will not work.
## Challenges.yml
@ -47,11 +69,4 @@ There are a few admin commands and more being written. The main challenge admin
* /bsbadmin challenges help : Show help for all the commands
* /bsbadmin challenges import [overwrite]: import challenges from challenges.yml
* /bsbadmin challenges complete <player> <unique challenge name>: Mark challenge complete
* /bsbadmin challenges reload : reload challenges from the database
* /bsbadmin challenges reset <player> <unique challenge name>: Reset challenge to 0 times / incomplete

31
pom.xml
View File

@ -6,7 +6,7 @@
<groupId>world.bentobox</groupId>
<artifactId>challenges</artifactId>
<version>0.3.1</version>
<version>0.5.0-SNAPSHOT</version>
<name>Challenges</name>
<description>Challenges is an add-on for BentoBox, an expandable Minecraft Bukkit plugin for island-type games like ASkyBlock or AcidIsland.</description>
@ -60,6 +60,10 @@
<id>vault-repo</id>
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
</repository>
<repository>
<id>wesjd-repo</id>
<url>https://nexus.wesjd.net/repository/thirdparty/</url>
</repository>
</repositories>
<dependencies>
@ -69,6 +73,12 @@
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
@ -90,7 +100,7 @@
<dependency>
<groupId>world.bentobox</groupId>
<artifactId>bentobox</artifactId>
<version>1.2</version>
<version>1.2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@ -111,6 +121,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.wesjd</groupId>
<artifactId>anvilgui</artifactId>
<version>1.2.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
@ -195,8 +210,16 @@
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<minimizeJar>false</minimizeJar>
<minimizeJar>true</minimizeJar>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -233,4 +256,4 @@
</plugins>
</build>
</project>
</project>

View File

@ -1,13 +1,18 @@
package world.bentobox.challenges;
import org.bukkit.Bukkit;
import org.bukkit.Bukkit;
import java.util.Optional;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.configuration.Config;
import world.bentobox.bentobox.hooks.VaultHook;
import world.bentobox.challenges.commands.ChallengesCommand;
import world.bentobox.challenges.commands.admin.Challenges;
import world.bentobox.challenges.listeners.ResetListener;
import world.bentobox.challenges.listeners.SaveListener;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.level.Level;
/**
* Add-on to BSkyBlock that enables challenges
@ -16,83 +21,261 @@ import world.bentobox.bentobox.api.commands.CompositeCommand;
*/
public class ChallengesAddon extends Addon {
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
private ChallengesManager challengesManager;
private String permissionPrefix = "addon";
private FreshSqueezedChallenges importManager;
private ChallengesImportManager importManager;
private Settings settings;
private boolean hooked;
/**
* This boolean indicate if economy is enabled.
*/
private boolean economyProvided;
/**
* VaultHook that process economy.
*/
private VaultHook vaultHook;
/**
* Level addon.
*/
private Level levelAddon;
/**
* This indicate if level addon exists.
*/
private boolean levelProvided;
// ---------------------------------------------------------------------
// Section: Constants
// ---------------------------------------------------------------------
/**
* Permission prefix for addon.
*/
private static final String PERMISSION_PREFIX = "addon";
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public void onLoad() {
// Save default config.yml
saveDefaultConfig();
this.saveDefaultConfig();
// Load the plugin's config
this.loadSettings();
}
/**
* {@inheritDoc}
*/
@Override
public void onEnable() {
// Check if it is enabled - it might be loaded, but not enabled.
if (getPlugin() == null || !getPlugin().isEnabled()) {
if (this.getPlugin() == null || !this.getPlugin().isEnabled()) {
Bukkit.getLogger().severe("BentoBox is not available or disabled!");
this.setState(State.DISABLED);
return;
}
// Challenges Manager
challengesManager = new ChallengesManager(this);
this.challengesManager = new ChallengesManager(this);
// Challenge import setup
importManager = new FreshSqueezedChallenges(this);
this.importManager = new ChallengesImportManager(this);
this.getPlugin().getAddonsManager().getGameModeAddons().forEach(gameModeAddon -> {
if (gameModeAddon.getPlayerCommand().isPresent())
if (!this.settings.getDisabledGameModes().contains(gameModeAddon.getDescription().getName()))
{
if (gameModeAddon.getPlayerCommand().isPresent())
{
new ChallengesCommand(this, gameModeAddon.getPlayerCommand().get());
this.hooked = true;
}
if (gameModeAddon.getAdminCommand().isPresent())
{
new Challenges(this, gameModeAddon.getAdminCommand().get());
this.hooked = true;
}
}
});
if (this.hooked) {
// Try to find Level addon and if it does not exist, display a warning
Optional<Addon> level = this.getAddonByName("Level");
if (!level.isPresent())
{
new ChallengesCommand(this, gameModeAddon.getPlayerCommand().get());
this.hooked = true;
this.logWarning("Level add-on not found so level challenges will not work!");
this.levelAddon = null;
}
else
{
this.levelProvided = true;
this.levelAddon = (Level) level.get();
}
if (gameModeAddon.getAdminCommand().isPresent())
Optional<VaultHook> vault = this.getPlugin().getVault();
if (!vault.isPresent() || !vault.get().hook())
{
new Challenges(this, gameModeAddon.getAdminCommand().get());
this.hooked = true;
this.vaultHook = null;
this.logWarning("Economy plugin not found so money options will not work!");
}
});
// If the add-on never hooks in, then it is useless
if (!hooked) {
logError("Challenges could not hook into AcidIsland or BSkyBlock so will not do anything!");
else
{
this.economyProvided = true;
this.vaultHook = vault.get();
}
// Register the reset listener
this.registerListener(new ResetListener(this));
// Register the autosave listener.
this.registerListener(new SaveListener(this));
} else {
this.logError("Challenges could not hook into AcidIsland or BSkyBlock so will not do anything!");
this.setState(State.DISABLED);
return;
}
// Try to find Level addon and if it does not exist, display a warning
if (!getAddonByName("Level").isPresent()) {
logWarning("Level add-on not found so level challenges will not work!");
}
// Register the reset listener
this.registerListener(new ResetListener(this));
// Register the autosave listener.
this.registerListener(new SaveListener(this));
// Done
}
/**
* {@inheritDoc}
*/
@Override
public void onDisable(){
if (challengesManager != null) {
challengesManager.save();
public void onReload()
{
if (this.hooked) {
this.challengesManager.save();
this.loadSettings();
this.getLogger().info("Challenges addon reloaded.");
}
}
public ChallengesManager getChallengesManager() {
return challengesManager;
/**
* {@inheritDoc}
*/
@Override
public void onDisable() {
if (this.hooked) {
this.challengesManager.save();
}
if (this.settings != null)
{
new Config<>(this, Settings.class).saveConfigObject(this.settings);
}
}
/**
* This method loads addon configuration settings in memory.
*/
private void loadSettings() {
this.settings = new Config<>(this, Settings.class).loadConfigObject();
if (this.settings == null) {
// Disable
this.logError("Challenges settings could not load! Addon disabled.");
this.setState(State.DISABLED);
}
}
// ---------------------------------------------------------------------
// Section: Getters
// ---------------------------------------------------------------------
/**
* @return challengesManager
*/
public ChallengesManager getChallengesManager() {
return this.challengesManager;
}
/**
* @return Permission Prefix.
*/
@Override
public String getPermissionPrefix() {
return permissionPrefix ;
return PERMISSION_PREFIX;
}
/**
* @return the importManager
*/
public FreshSqueezedChallenges getImportManager() {
return importManager;
public ChallengesImportManager getImportManager() {
return this.importManager;
}
/**
* @return the challenge settings.
*/
public Settings getChallengesSettings()
{
return this.settings;
}
/**
*
* @return economyProvided variable.
*/
public boolean isEconomyProvided()
{
return this.economyProvided;
}
/**
* Returns VaultHook. Used to get easier access to Economy. NEVER USE WITHOUT isEconomyProvided or null
* check.
* @return VaultHook or null.
*/
public VaultHook getEconomyProvider()
{
return vaultHook;
}
/**
*
* @return levelProvided variable.
*/
public boolean isLevelProvided()
{
return levelProvided;
}
/**
* This method returns Level addon. Used to easier access to Level. NEVER USE WITHOUT isLevelProvided or null
* @return LevelAddon or null.
*/
public Level getLevelAddon()
{
return levelAddon;
}
}

View File

@ -0,0 +1,377 @@
package world.bentobox.challenges;
import java.io.File;
import java.io.IOException;
import java.util.*;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import world.bentobox.bentobox.api.configuration.Config;
import world.bentobox.bentobox.util.ItemParser;
import world.bentobox.challenges.database.object.ChallengeLevel;
import world.bentobox.challenges.database.object.ChallengeLevels;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.database.object.Challenges;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
import world.bentobox.challenges.utils.GuiUtils;
/**
* Imports challenges
* @author tastybento
*
*/
public class ChallengesImportManager
{
private ChallengesAddon addon;
private YamlConfiguration chal;
/**
* Import challenges from challenges.yml
* @param challengesAddon
*/
public ChallengesImportManager(ChallengesAddon challengesAddon) {
this.addon = challengesAddon;
File challengeFile = new File(addon.getDataFolder(), "challenges.yml");
if (!challengeFile.exists()) {
addon.saveResource("challenges.yml",false);
}
}
/**
* Import challenges
* @param user - user
* @param world - world to import into
* @param overwrite - true if previous ones should be overwritten
* @return true if successful
*/
public boolean importChallenges(User user, World world, boolean overwrite) {
File challengeFile = new File(addon.getDataFolder(), "challenges.yml");
if (!challengeFile.exists()) {
user.sendMessage("challenges.errors.import-no-file");
return false;
}
chal = new YamlConfiguration();
try {
chal.load(challengeFile);
} catch (IOException | InvalidConfigurationException e) {
user.sendMessage("challenges.errors.no-load","[message]", e.getMessage());
return false;
}
makeLevels(user, world, overwrite);
makeChallenges(user, world, overwrite);
addon.getChallengesManager().save();
return true;
}
private void makeLevels(User user, World world, boolean overwrite) {
// Parse the levels
String levels = chal.getString("challenges.levels", "");
if (!levels.isEmpty()) {
user.sendMessage("challenges.messages.import-levels");
String[] lvs = levels.split(" ");
int order = 0;
for (String level : lvs) {
ChallengeLevel challengeLevel = new ChallengeLevel();
challengeLevel.setFriendlyName(level);
challengeLevel.setUniqueId(Util.getWorld(world).getName() + "_" + level);
challengeLevel.setOrder(order++);
challengeLevel.setWorld(Util.getWorld(world).getName());
challengeLevel.setWaiverAmount(chal.getInt("challenges.waiveramount"));
// Check if there is a level reward
ConfigurationSection unlock = chal.getConfigurationSection("challenges.levelUnlock." + level);
if (unlock != null) {
challengeLevel.setUnlockMessage(unlock.getString("message", ""));
challengeLevel.setRewardText(unlock.getString("rewardDesc",""));
challengeLevel.setRewardItems(parseItems(unlock.getString("itemReward","")));
challengeLevel.setRewardMoney(unlock.getInt("moneyReward"));
challengeLevel.setRewardExperience(unlock.getInt("expReward"));
challengeLevel.setRewardCommands(unlock.getStringList("commands"));
}
addon.getChallengesManager().loadLevel(challengeLevel, overwrite, user, false);
}
} else {
user.sendMessage("challenges.messages.no-levels");
}
}
/**
* Imports challenges
* @param overwrite
*/
private void makeChallenges(User user, World world, boolean overwrite) {
int size = 0;
// Parse the challenge file
ConfigurationSection chals = chal.getConfigurationSection("challenges.challengeList");
user.sendMessage("challenges.messages.import-challenges");
for (String challenge : chals.getKeys(false)) {
Challenge newChallenge = new Challenge();
newChallenge.setUniqueId(Util.getWorld(world).getName() + "_" + challenge);
newChallenge.setDeployed(true);
ConfigurationSection details = chals.getConfigurationSection(challenge);
newChallenge.setFriendlyName(details.getString("friendlyname", challenge));
newChallenge.setDescription(GuiUtils.stringSplit(
details.getString("description", ""),
this.addon.getChallengesSettings().getLoreLineLength()));
newChallenge.setIcon(ItemParser.parse(details.getString("icon", "") + ":1"));
if (details.getString("type", "").equalsIgnoreCase("level"))
{
// Fix for older version config
newChallenge.setChallengeType(Challenge.ChallengeType.OTHER);
}
else
{
newChallenge.setChallengeType(Challenge.ChallengeType.valueOf(details.getString("type","INVENTORY").toUpperCase()));
}
newChallenge.setTakeItems(details.getBoolean("takeItems",true));
newChallenge.setRewardText(details.getString("rewardText", ""));
newChallenge.setRewardCommands(details.getStringList("rewardcommands"));
newChallenge.setRewardMoney(details.getInt("moneyReward",0));
newChallenge.setRewardExperience(details.getInt("expReward"));
newChallenge.setRepeatable(details.getBoolean("repeatable"));
newChallenge.setRepeatRewardText(details.getString("repeatRewardText",""));
newChallenge.setRepeatMoneyReward(details.getInt("repearMoneyReward"));
newChallenge.setRepeatExperienceReward(details.getInt("repeatExpReward"));
newChallenge.setRepeatRewardCommands(details.getStringList("repeatrewardcommands"));
newChallenge.setMaxTimes(details.getInt("maxtimes"));
// TODO reset allowed
newChallenge.setRequiredMoney(details.getInt("requiredMoney"));
newChallenge.setRequiredExperience(details.getInt("requiredExp"));
String reqItems = details.getString("requiredItems","");
if (newChallenge.getChallengeType().equals(Challenge.ChallengeType.INVENTORY)) {
newChallenge.setRequiredItems(parseItems(reqItems));
} else if (newChallenge.getChallengeType().equals(Challenge.ChallengeType.OTHER)) {
newChallenge.setRequiredIslandLevel(Long.parseLong(reqItems));
} else if (newChallenge.getChallengeType().equals(Challenge.ChallengeType.ISLAND)) {
parseEntities(newChallenge, reqItems);
}
newChallenge.setRewardItems(parseItems(details.getString("itemReward", "")));
newChallenge.setRepeatItemReward(parseItems(details.getString("repeatItemReward", "")));
// Save
this.addon.getChallengesManager().addChallengeToLevel(newChallenge,
addon.getChallengesManager().getLevel(Util.getWorld(world).getName() + "_" + details.getString("level", "")));
if (addon.getChallengesManager().loadChallenge(newChallenge, overwrite, user, false)) {
size++;
}
}
user.sendMessage("challenges.messages.import-number", "[number]", String.valueOf(size));
}
/**
* Run through entity types and materials and try to match to the string given
* @param challenge - challenge to be adjusted
* @param string - string from YAML file
*/
private void parseEntities(Challenge challenge, String string) {
Map<EntityType, Integer> req = new EnumMap<>(EntityType.class);
Map<Material, Integer> blocks = new EnumMap<>(Material.class);
if (!string.isEmpty()) {
for (String s : string.split(" ")) {
String[] part = s.split(":");
try {
Arrays.asList(EntityType.values()).stream().filter(t -> t.name().equalsIgnoreCase(part[0])).forEach(t -> req.put(t, Integer.valueOf(part[1])));
Arrays.asList(Material.values()).stream().filter(t -> t.name().equalsIgnoreCase(part[0])).forEach(t -> blocks.put(t, Integer.valueOf(part[1])));
} catch (Exception e) {
addon.getLogger().severe("Cannot parse '" + s + "'. Skipping...");
}
}
}
challenge.setRequiredEntities(req);
challenge.setRequiredBlocks(blocks);
}
private List<ItemStack> parseItems(String reqList) {
List<ItemStack> result = new ArrayList<>();
if (!reqList.isEmpty()) {
for (String s : reqList.split(" ")) {
ItemStack item = ItemParser.parse(s);
if (item != null) {
result.add(item);
}
}
}
return result;
}
// ---------------------------------------------------------------------
// Section: Backward compatibility
// ---------------------------------------------------------------------
/**
* This method imports challenges form 0.3 and below version.
* @param user - user
* @param world - world to import into
* @param overwrite - true if previous ones should be overwritten
* @return true if successful
*/
public boolean importPreviousChallenges(User user, World world, boolean overwrite)
{
ChallengesManager manager = this.addon.getChallengesManager();
List<Challenges> challenges =
new Config<>(this.addon, Challenges.class).loadConfigObjects();
if (!challenges.isEmpty())
{
List<ChallengeLevels> levels =
new Config<>(this.addon, ChallengeLevels.class).loadConfigObjects();
for (ChallengeLevels level : levels)
{
ChallengeLevel newlevel = this.createLevel(level, world);
if (newlevel != null)
{
manager.loadLevel(newlevel, overwrite, user, false);
}
}
for (Challenges challenge : challenges)
{
Challenge newChallenge = this.createChallenge(challenge, world);
if (newChallenge == null)
{
continue;
}
manager.loadChallenge(newChallenge, overwrite, user, false);
if (challenge.getLevel().isEmpty() || challenge.getLevel().equals("FREE"))
{
newChallenge.setLevel(ChallengesManager.FREE);
}
else
{
String levelName = Util.getWorld(world).getName() + "_" + challenge.getLevel();
if (this.addon.getChallengesManager().containsLevel(levelName))
{
manager.addChallengeToLevel(newChallenge,
this.addon.getChallengesManager().getLevel(levelName));
}
}
}
}
return true;
}
/**
* This method creates new ChallengeLevel based on old level settings.
* @param level Old level object.
* @param world World where new challenge will operate.
* @return New level or null, if old level does not operate in this world.
*/
private ChallengeLevel createLevel(ChallengeLevels level, World world)
{
if (!level.getWorlds().isEmpty() &&
!level.getWorlds().contains(Util.getWorld(world).getName()))
{
return null;
}
ChallengeLevel newLevel = new ChallengeLevel();
newLevel.setUniqueId(Util.getWorld(world).getName() + "_" + level.getUniqueId());
newLevel.setFriendlyName(level.getFriendlyName());
newLevel.setOrder(level.getOrder());
newLevel.setWorld(Util.getWorld(world).getName());
newLevel.setUnlockMessage(level.getUnlockMessage());
newLevel.setWaiverAmount(level.getWaiveramount());
newLevel.setRewardText(level.getRewardDescription());
newLevel.setRewardMoney(level.getMoneyReward());
newLevel.setRewardExperience(level.getExpReward());
newLevel.setRewardItems(level.getRewardItems());
newLevel.setRewardCommands(level.getRewardCommands());
return newLevel;
}
/**
* This method creates new Challenge based on old challenges settings.
* @param challenge Old challenges object.
* @param world World where new challenge will operate.
* @return New Challenge or null, if old challenge does not operate in this world.
*/
private Challenge createChallenge(Challenges challenge, World world)
{
if (!challenge.getWorld().equals(Util.getWorld(world).getName()))
{
// Does not operate in given world.
return null;
}
Challenge newChallenge = new Challenge();
newChallenge.setUniqueId(challenge.getUniqueId());
newChallenge.setFriendlyName(challenge.getFriendlyName());
newChallenge.setRemoveWhenCompleted(challenge.isRemoveWhenCompleted());
newChallenge.setDeployed(challenge.isDeployed());
newChallenge.setIcon(challenge.getIcon());
newChallenge.setEnvironment(new HashSet<>(challenge.getEnvironment()));
switch (challenge.getChallengeType())
{
case INVENTORY:
newChallenge.setChallengeType(Challenge.ChallengeType.INVENTORY);
break;
case ISLAND:
newChallenge.setChallengeType(Challenge.ChallengeType.ISLAND);
break;
default:
newChallenge.setChallengeType(Challenge.ChallengeType.OTHER);
break;
}
newChallenge.setOrder(challenge.getSlot());
newChallenge.setDescription(challenge.getDescription());
newChallenge.setRequiredEntities(challenge.getRequiredEntities());
newChallenge.setRequiredItems(challenge.getRequiredItems());
newChallenge.setRequiredBlocks(challenge.getRequiredBlocks());
newChallenge.setRequiredMoney(challenge.getReqMoney());
newChallenge.setRequiredExperience(challenge.getReqExp());
newChallenge.setRequiredIslandLevel(challenge.getReqIslandlevel());
newChallenge.setRequiredPermissions(challenge.getReqPerms());
newChallenge.setTakeMoney(challenge.isTakeMoney());
newChallenge.setTakeItems(challenge.isTakeItems());
newChallenge.setSearchRadius(challenge.getSearchRadius());
newChallenge.setRewardText(challenge.getRewardText());
newChallenge.setRewardItems(challenge.getRewardItems());
newChallenge.setRewardMoney(challenge.getRewardMoney());
newChallenge.setRewardExperience(challenge.getRewardExp());
newChallenge.setRewardCommands(challenge.getRewardCommands());
newChallenge.setRepeatable(challenge.isRepeatable());
newChallenge.setMaxTimes(challenge.getMaxTimes());
newChallenge.setRepeatRewardText(challenge.getRepeatRewardText());
newChallenge.setRepeatItemReward(challenge.getRepeatItemReward());
newChallenge.setRepeatMoneyReward(challenge.getRepeatMoneyReward());
newChallenge.setRepeatExperienceReward(challenge.getRepeatExpReward());
newChallenge.setRepeatRewardCommands(challenge.getRepeatRewardCommands());
return newChallenge;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,193 +0,0 @@
package world.bentobox.challenges;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import world.bentobox.challenges.database.object.ChallengeLevels;
import world.bentobox.challenges.database.object.Challenges;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
/**
* Imports challenges
* @author tastybento
*
*/
public class FreshSqueezedChallenges {
private ChallengesAddon addon;
private YamlConfiguration chal;
/**
* Import challenges from challenges.yml
* @param challengesAddon
*/
public FreshSqueezedChallenges(ChallengesAddon challengesAddon) {
this.addon = challengesAddon;
File challengeFile = new File(addon.getDataFolder(), "challenges.yml");
if (!challengeFile.exists()) {
addon.saveResource("challenges.yml",false);
}
}
/**
* Import challenges
* @param user - user
* @param world - world to import into
* @param overwrite - true if previous ones should be overwritten
* @return true if successful
*/
public boolean importChallenges(User user, World world, boolean overwrite) {
File challengeFile = new File(addon.getDataFolder(), "challenges.yml");
if (!challengeFile.exists()) {
user.sendMessage("challenges.admin.import.no-file");
return false;
}
chal = new YamlConfiguration();
try {
chal.load(challengeFile);
} catch (IOException | InvalidConfigurationException e) {
user.sendMessage("challenges.admin.import.no-load","[message]", e.getMessage());
return false;
}
makeLevels(user);
makeChallenges(user, world, overwrite);
addon.getChallengesManager().save();
return true;
}
private void makeLevels(User user) {
// Parse the levels
String levels = chal.getString("challenges.levels", "");
if (!levels.isEmpty()) {
user.sendMessage("challenges.admin.import.levels", "[levels]", levels);
String[] lvs = levels.split(" ");
int order = 0;
for (String level : lvs) {
ChallengeLevels challengeLevel = new ChallengeLevels();
challengeLevel.setFriendlyName(level);
challengeLevel.setUniqueId(level);
challengeLevel.setOrder(order++);
challengeLevel.setWaiveramount(chal.getInt("challenges.waiveramount"));
// Check if there is a level reward
ConfigurationSection unlock = chal.getConfigurationSection("challenges.levelUnlock." + level);
if (unlock != null) {
challengeLevel.setUnlockMessage(unlock.getString("message"));
challengeLevel.setRewardDescription(unlock.getString("rewardDesc",""));
challengeLevel.setRewardItems(parseItems(unlock.getString("itemReward","")));
challengeLevel.setMoneyReward(unlock.getInt("moneyReward"));
challengeLevel.setExpReward(unlock.getInt("expReward"));
challengeLevel.setRewardCommands(unlock.getStringList("commands"));
}
addon.getChallengesManager().storeLevel(challengeLevel);
}
} else {
user.sendMessage("challenges.admin.import.no-levels");
}
}
/**
* Imports challenges
* @param overwrite
* @param args
*/
private void makeChallenges(User user, World world, boolean overwrite) {
int size = 0;
// Parse the challenge file
ConfigurationSection chals = chal.getConfigurationSection("challenges.challengeList");
for (String challenge : chals.getKeys(false)) {
Challenges newChallenge = new Challenges();
newChallenge.setUniqueId(Util.getWorld(world).getName() + "_" + challenge);
newChallenge.setDeployed(true);
ConfigurationSection details = chals.getConfigurationSection(challenge);
newChallenge.setFriendlyName(details.getString("friendlyname", challenge));
newChallenge.setWorld(Util.getWorld(world).getName());
newChallenge.setDescription(addon.getChallengesManager().stringSplit(details.getString("description", "")));
newChallenge.setIcon(new ParseItem(addon, details.getString("icon") + ":1").getItem());
newChallenge.setLevel(details.getString("level", ChallengesManager.FREE));
newChallenge.setChallengeType(Challenges.ChallengeType.valueOf(details.getString("type","INVENTORY").toUpperCase()));
newChallenge.setTakeItems(details.getBoolean("takeItems",true));
newChallenge.setRewardText(details.getString("rewardText", ""));
newChallenge.setRewardCommands(details.getStringList("rewardcommands"));
newChallenge.setRewardMoney(details.getInt("moneyReward",0));
newChallenge.setRewardExp(details.getInt("expReward"));
newChallenge.setRepeatable(details.getBoolean("repeatable"));
newChallenge.setRepeatRewardText(details.getString("repeatRewardText",""));
newChallenge.setRepeatMoneyReward(details.getInt("repearMoneyReward"));
newChallenge.setRepeatExpReward(details.getInt("repeatExpReward"));
newChallenge.setRepeatRewardCommands(details.getStringList("repeatrewardcommands"));
newChallenge.setMaxTimes(details.getInt("maxtimes"));
// TODO reset allowed
newChallenge.setReqMoney(details.getInt("requiredMoney"));
newChallenge.setReqExp(details.getInt("requiredExp"));
String reqItems = details.getString("requiredItems","");
if (newChallenge.getChallengeType().equals(Challenges.ChallengeType.INVENTORY)) {
newChallenge.setRequiredItems(parseItems(reqItems));
} else if (newChallenge.getChallengeType().equals(Challenges.ChallengeType.LEVEL)) {
newChallenge.setReqIslandlevel(Long.parseLong(reqItems));
} else if (newChallenge.getChallengeType().equals(Challenges.ChallengeType.ISLAND)) {
parseEntities(newChallenge, reqItems);
}
newChallenge.setRewardItems(parseItems(details.getString("itemReward")));
newChallenge.setRepeatItemReward(parseItems(details.getString("repeatItemReward")));
// Save
if (addon.getChallengesManager().storeChallenge(newChallenge, overwrite, user, false)) {
size++;
}
}
addon.getChallengesManager().sortChallenges();
user.sendMessage("challenges.admin.import.number", "[number]", String.valueOf(size));
}
/**
* Run through entity types and materials and try to match to the string given
* @param challenge - challenge to be adjusted
* @param string - string from YAML file
*/
private void parseEntities(Challenges challenge, String string) {
Map<EntityType, Integer> req = new EnumMap<>(EntityType.class);
Map<Material, Integer> blocks = new EnumMap<>(Material.class);
if (!string.isEmpty()) {
for (String s : string.split(" ")) {
String[] part = s.split(":");
try {
Arrays.asList(EntityType.values()).stream().filter(t -> t.name().equalsIgnoreCase(part[0])).forEach(t -> req.put(t, Integer.valueOf(part[1])));
Arrays.asList(Material.values()).stream().filter(t -> t.name().equalsIgnoreCase(part[0])).forEach(t -> blocks.put(t, Integer.valueOf(part[1])));
} catch (Exception e) {
addon.getLogger().severe("Cannot parse '" + s + "'. Skipping...");
}
}
}
challenge.setRequiredEntities(req);
challenge.setRequiredBlocks(blocks);
}
private List<ItemStack> parseItems(String reqList) {
List<ItemStack> result = new ArrayList<>();
if (!reqList.isEmpty()) {
for (String s : reqList.split(" ")) {
ItemStack item = new ParseItem(addon,s).getItem();
if (item != null) {
result.add(item);
}
}
}
return result;
}
}

View File

@ -11,7 +11,10 @@ import org.bukkit.potion.PotionType;
* 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;

View File

@ -0,0 +1,315 @@
package world.bentobox.challenges;
import java.util.HashSet;
import java.util.Set;
import world.bentobox.bentobox.api.configuration.ConfigComment;
import world.bentobox.bentobox.api.configuration.ConfigEntry;
import world.bentobox.bentobox.api.configuration.StoreAt;
import world.bentobox.bentobox.database.objects.DataObject;
@StoreAt(filename="config.yml", path="addons/Challenges")
@ConfigComment("Challenges [version] Configuration")
@ConfigComment("This config file is dynamic and saved when the server is shutdown.")
@ConfigComment("You cannot edit it while the server is running because changes will")
@ConfigComment("be lost! Use in-game settings GUI or edit when server is offline.")
@ConfigComment("")
public class Settings implements DataObject
{
@ConfigComment("")
@ConfigComment("Reset Challenges - if this is true, player's challenges will reset when they")
@ConfigComment("reset an island or if they 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("Remove non-repeatable challenges from the challenge GUI when complete.")
@ConfigEntry(path = "remove-complete-one-time-challenges")
private boolean removeCompleteOneTimeChallenges = false;
@ConfigComment("")
@ConfigComment("Add enchanted glow to completed challenges")
@ConfigEntry(path = "add-completed-glow")
private boolean addCompletedGlow = true;
@ConfigComment("")
@ConfigComment("This indicate if free challenges must be at the start (true) or at the end (false) of list.")
@ConfigEntry(path = "free-challenges-first")
private boolean freeChallengesFirst = true;
@ConfigComment("")
@ConfigComment("This allows to change lore description line length. By default it is 25, but some server")
@ConfigComment("owners may like it to be larger.")
@ConfigEntry(path = "lore-length")
private int loreLineLength = 25;
@ConfigComment("")
@ConfigComment("This string allows to change element order in Challenge description. Each letter represents")
@ConfigComment("one object from challenge description. If letter is not used, then its represented part")
@ConfigComment("will not be in description. If use any letter that is not recognized, then it will be")
@ConfigComment("ignored. Some strings can be customized via lang file under 'challenges.gui.challenge-description'.")
@ConfigComment("List of letters and their meaning: ")
@ConfigComment(" - L - Level String: '*.level'")
@ConfigComment(" - S - Status String: '*.completed'")
@ConfigComment(" - T - Times String: '*.completed-times', '*.completed-times-of' or '*.maxed-reached'")
@ConfigComment(" - D - Description String: defined in challenge object - challenge.description")
@ConfigComment(" - W - Warning String: '*.warning-items-take', '*.objects-close-by', '*.warning-entities-kill', '*.warning-blocks-remove'")
@ConfigComment(" - E - Environment String: defined in challenge object - challenge.environment")
@ConfigComment(" - Q - Requirement String: '*.required-level', '*.required-money', '*.required-experience'")
@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("and entities that are defined in challenge and can be customized under 'challenges.gui.description.*'")
@ConfigEntry(path = "challenge-lore-message")
private String challengeLoreMessage = "LSTDEQiWRi";
@ConfigComment("")
@ConfigComment("This string allows to change element order in Level description. Each letter represents")
@ConfigComment("one object from level description. If letter is not used, then its represented part")
@ConfigComment("will not be in description. If use any letter that is not recognized, then it will be")
@ConfigComment("ignored. Some strings can be customized via lang file under 'challenges.gui.level-description'.")
@ConfigComment("List of letters and their meaning: ")
@ConfigComment(" - S - Status String: '*.completed'")
@ConfigComment(" - T - Count of completed challenges String: '*.completed-challenges-of'")
@ConfigComment(" - D - Description String: defined in level object - challengeLevel.unlockMessage")
@ConfigComment(" - A - WaiverAmount String: '*.waver-amount'")
@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("and can be customized under 'challenges.gui.description.*'")
@ConfigEntry(path = "level-lore-message")
private String levelLoreMessage = "STDARi";
@ConfigComment("")
@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("disabled-gamemodes:")
@ConfigComment(" - BSkyBlock")
@ConfigEntry(path = "disabled-gamemodes")
private Set<String> disabledGameModes = new HashSet<>();
/**
* Default variable.
*/
@ConfigComment("")
private String uniqueId = "config";
/**
* Configuration version
*/
@ConfigComment("")
private String configVersion = "v1.1";
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method returns the challengeLoreMessage object.
* @return the challengeLoreMessage object.
*/
public String getChallengeLoreMessage()
{
return challengeLoreMessage;
}
/**
* This method returns the configVersion object.
* @return the configVersion object.
*/
public String getConfigVersion()
{
return configVersion;
}
@Override
public String getUniqueId()
{
return this.uniqueId;
}
/**
* @return resetChallenges value.
*/
public boolean isResetChallenges()
{
return this.resetChallenges;
}
/**
* @return broadcastMessages value.
*/
public boolean isBroadcastMessages()
{
return this.broadcastMessages;
}
/**
* @return removeCompleteOneTimeChallenges value.
*/
public boolean isRemoveCompleteOneTimeChallenges()
{
return this.removeCompleteOneTimeChallenges;
}
/**
* @return addCompletedGlow value.
*/
public boolean isAddCompletedGlow()
{
return this.addCompletedGlow;
}
/**
* @return disabledGameModes value.
*/
public Set<String> getDisabledGameModes()
{
return this.disabledGameModes;
}
/**
* @return freeChallengesFirst value.
*/
public boolean isFreeChallengesFirst()
{
return this.freeChallengesFirst;
}
/**
* This method returns the loreLineLength object.
* @return the loreLineLength object.
*/
public int getLoreLineLength()
{
return loreLineLength;
}
/**
* This method returns the levelLoreMessage object.
* @return the levelLoreMessage object.
*/
public String getLevelLoreMessage()
{
return levelLoreMessage;
}
/**
* This method sets the configVersion object value.
* @param configVersion the configVersion object new value.
*/
public void setConfigVersion(String configVersion)
{
this.configVersion = configVersion;
}
@Override
public void setUniqueId(String uniqueId)
{
this.uniqueId = uniqueId;
}
/**
* This method sets the challengeLoreMessage object value.
* @param challengeLoreMessage the challengeLoreMessage object new value.
*/
public void setChallengeLoreMessage(String challengeLoreMessage)
{
this.challengeLoreMessage = challengeLoreMessage;
}
/**
* This method sets the levelLoreMessage object value.
* @param levelLoreMessage the levelLoreMessage object new value.
*/
public void setLevelLoreMessage(String levelLoreMessage)
{
this.levelLoreMessage = levelLoreMessage;
}
/**
* @param resetChallenges new resetChallenges value.
*/
public void setResetChallenges(boolean resetChallenges)
{
this.resetChallenges = resetChallenges;
}
/**
* @param broadcastMessages new broadcastMessages value.
*/
public void setBroadcastMessages(boolean broadcastMessages)
{
this.broadcastMessages = broadcastMessages;
}
/**
* @param removeCompleteOneTimeChallenges new removeCompleteOneTimeChallenges value.
*/
public void setRemoveCompleteOneTimeChallenges(boolean removeCompleteOneTimeChallenges)
{
this.removeCompleteOneTimeChallenges = removeCompleteOneTimeChallenges;
}
/**
* @param addCompletedGlow new addCompletedGlow value.
*/
public void setAddCompletedGlow(boolean addCompletedGlow)
{
this.addCompletedGlow = addCompletedGlow;
}
/**
* @param disabledGameModes new disabledGameModes value.
*/
public void setDisabledGameModes(Set<String> disabledGameModes)
{
this.disabledGameModes = disabledGameModes;
}
/**
* @param freeChallengesFirst new freeChallengesFirst value.
*/
public void setFreeChallengesFirst(boolean freeChallengesFirst)
{
this.freeChallengesFirst = freeChallengesFirst;
}
/**
* This method sets the loreLineLength object value.
* @param loreLineLength the loreLineLength object new value.
*/
public void setLoreLineLength(int loreLineLength)
{
this.loreLineLength = loreLineLength;
}
}

View File

@ -3,10 +3,10 @@ package world.bentobox.challenges.commands;
import java.util.List;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.panel.ChallengesPanels2;
import world.bentobox.challenges.panel.ChallengesPanels2.Mode;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.panel.user.ChallengesGUI;
public class ChallengesCommand extends CompositeCommand {
public static final String CHALLENGE_COMMAND = "challenges";
@ -19,7 +19,11 @@ public class ChallengesCommand extends CompositeCommand {
public boolean execute(User user, String label, List<String> args) {
// Open up the challenges GUI
if (user.isPlayer()) {
new ChallengesPanels2((ChallengesAddon) getAddon(), user, user, args.isEmpty() ? "" : args.get(0), getWorld(), getPermissionPrefix(), getTopLabel(), Mode.PLAYER);
new ChallengesGUI((ChallengesAddon) this.getAddon(),
this.getWorld(),
user,
this.getTopLabel(),
this.getPermissionPrefix()).build();
return true;
}
// Show help
@ -30,8 +34,8 @@ public class ChallengesCommand extends CompositeCommand {
@Override
public void setup() {
this.setPermission(CHALLENGE_COMMAND);
this.setParametersHelp(CHALLENGE_COMMAND + ".parameters");
this.setDescription(CHALLENGE_COMMAND + ".description");
this.setParametersHelp("challenges.commands.user.parameters");
this.setDescription("challenges.commands.user.description");
}

View File

@ -3,10 +3,10 @@ package world.bentobox.challenges.commands.admin;
import java.util.List;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.panel.ChallengesPanels2;
import world.bentobox.challenges.panel.ChallengesPanels2.Mode;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.panel.admin.AdminGUI;
public class Challenges extends CompositeCommand {
@ -21,11 +21,11 @@ public class Challenges extends CompositeCommand {
@Override
public void setup() {
this.setPermission("admin.challenges");
this.setParametersHelp("challeneges.admin.parameters");
this.setDescription("challenges.admin.description");
this.setParametersHelp("challenges.commands.admin.main.parameters");
this.setDescription("challenges.commands.admin.main.description");
// Register sub commands
new ImportCommand(getAddon(), this);
new CompleteChallenge(getAddon(), this);
// new CompleteChallenge(getAddon(), this);
new ReloadChallenges(getAddon(), this);
new ResetChallenge(getAddon(), this);
//new ShowChallenges(getAddon(), this);
@ -37,7 +37,12 @@ public class Challenges extends CompositeCommand {
public boolean execute(User user, String label, List<String> args) {
// Open up the admin challenges GUI
if (user.isPlayer()) {
new ChallengesPanels2((ChallengesAddon) getAddon(), user, user, args.isEmpty() ? "" : args.get(0), getWorld(), getPermissionPrefix(), getTopLabel(), Mode.ADMIN);
new AdminGUI((ChallengesAddon) this.getAddon(),
this.getWorld(),
user,
this.getTopLabel(),
this.getPermissionPrefix()).build();
return true;
}
return false;

View File

@ -28,8 +28,8 @@ public class CompleteChallenge extends CompositeCommand {
@Override
public void setup() {
this.setPermission("admin.challenges");
this.setParametersHelp("challenges.admin.complete.parameters");
this.setDescription("challenges.admin.complete.description");
this.setParametersHelp("challenges.commands.admin.complete.parameters");
this.setDescription("challenges.commands.admin.complete.description");
manager = ((ChallengesAddon)getAddon()).getChallengesManager();
}
@ -51,13 +51,13 @@ public class CompleteChallenge extends CompositeCommand {
return false;
}
// Check for valid challenge name
if (!manager.isChallenge(getWorld(), args.get(1))) {
if (!manager.containsChallenge(args.get(1))) {
user.sendMessage("challenges.admin.complete.unknown-challenge");
return false;
}
// Complete challenge
User target = User.getInstance(targetUUID);
manager.setChallengeComplete(target, args.get(1), getWorld());
manager.setChallengeComplete(target, this.manager.getChallenge(args.get(1)));
user.sendMessage("general.success");
return true;
}
@ -70,7 +70,7 @@ public class CompleteChallenge extends CompositeCommand {
return Optional.of(Util.tabLimit(new ArrayList<>(Util.getOnlinePlayerList(user)), lastArg));
} else if (args.size() == 4) {
// Challenges in this world
return Optional.of(Util.tabLimit(manager.getAllChallengesList(getWorld()), lastArg));
return Optional.of(Util.tabLimit(manager.getAllChallengesNames(getWorld()), lastArg));
}
return Optional.empty();
}

View File

@ -9,6 +9,11 @@ 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 {
/**
@ -24,15 +29,15 @@ public class CreateChallenge extends CompositeCommand {
public void setup() {
this.setOnlyPlayer(true);
this.setPermission("admin.challenges");
this.setParametersHelp("challaneges.admin.create.parameters");
this.setDescription("challenges.admin.create.description");
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.sendRawMessage("not enough args");
user.sendMessage("challenges.errors.no-name");
return false;
}
new PanelBuilder()

View File

@ -25,8 +25,9 @@ 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<>();
@ -44,18 +45,18 @@ public class CreateSurrounding extends CompositeCommand implements Listener {
public void setup() {
this.setOnlyPlayer(true);
this.setPermission("admin.challenges");
this.setParametersHelp("challaneges.admin.create.surrounding.parameters");
this.setDescription("challenges.admin.create.surrounding.description");
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.admin.error.no-name");
user.sendMessage("challenges.errors.no-name");
return false;
}
// Tell user to hit objects to add to the surrounding object requirements
user.sendMessage("challenges.admin.create.surrounding.hit-things");
user.sendMessage("challenges.messages.admin.hit-things");
inProgress.put(user.getUniqueId(), new SurroundChallengeBuilder((ChallengesAddon) getAddon()).owner(user).name(args.get(0)));
return true;
}
@ -76,7 +77,7 @@ public class CreateSurrounding extends CompositeCommand implements Listener {
// Prevent damage
e.setCancelled(true);
inProgress.get(e.getPlayer().getUniqueId()).addBlock(e.getClickedBlock().getType());
User.getInstance(e.getPlayer()).sendMessage("challenges.admin.you-added", "[thing]", Util.prettifyText(e.getClickedBlock().getType().toString()));
User.getInstance(e.getPlayer()).sendMessage("challenges.messages.admin.you-added", "[thing]", Util.prettifyText(e.getClickedBlock().getType().toString()));
return true;
}
@ -91,7 +92,7 @@ public class CreateSurrounding extends CompositeCommand implements Listener {
e.setCancelled(true);
boolean status = inProgress.get(uuid).build();
if (status) {
inProgress.get(uuid).getOwner().sendMessage("challenges.admin.challenge-created", "[challenge]", inProgress.get(uuid).getName());
inProgress.get(uuid).getOwner().sendMessage("challenges.messages.admin.challenge-created", "[challenge]", inProgress.get(uuid).getName());
}
inProgress.remove(uuid);
return status;
@ -114,7 +115,7 @@ public class CreateSurrounding extends CompositeCommand implements Listener {
// Prevent damage
e.setCancelled(true);
inProgress.get(player.getUniqueId()).addEntity(e.getEntityType());
User.getInstance(player).sendMessage("challenges.admin.you-added", "[thing]", Util.prettifyText(e.getEntityType().toString()));
User.getInstance(player).sendMessage("challenges.messages.admin.you-added", "[thing]", Util.prettifyText(e.getEntityType().toString()));
return true;
}
return false;

View File

@ -29,8 +29,8 @@ public class ImportCommand extends CompositeCommand {
@Override
public void setup() {
this.setPermission("challenges.admin");
this.setParametersHelp("challenges.admin.import.parameters");
this.setDescription("challenges.admin.import.description");
this.setParametersHelp("challenges.commands.admin.import.parameters");
this.setDescription("challenges.commands.admin.import.description");
}
@Override

View File

@ -23,8 +23,8 @@ public class ReloadChallenges extends CompositeCommand {
@Override
public void setup() {
this.setPermission("admin.challenges");
this.setParametersHelp("challenges.admin.reload.parameters");
this.setDescription("challenges.admin.reload.description");
this.setParametersHelp("challenges.commands.admin.reload.parameters");
this.setDescription("challenges.commands.admin.reload.description");
manager = ((ChallengesAddon)getAddon()).getChallengesManager();
}

View File

@ -13,6 +13,11 @@ import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
/**
* @deprecated Challenges can be reset via GUI.
*/
@Deprecated
public class ResetChallenge extends CompositeCommand {
private ChallengesManager manager;
@ -28,8 +33,8 @@ public class ResetChallenge extends CompositeCommand {
@Override
public void setup() {
this.setPermission("admin.challenges");
this.setParametersHelp("challenges.admin.reset.parameters");
this.setDescription("challenges.admin.reset.description");
this.setParametersHelp("challenges.commands.admin.reset.parameters");
this.setDescription("challenges.commands.admin.reset.description");
manager = ((ChallengesAddon)getAddon()).getChallengesManager();
}
@ -51,13 +56,13 @@ public class ResetChallenge extends CompositeCommand {
return false;
}
// Check for valid challenge name
if (!manager.isChallenge(getWorld(), args.get(1))) {
user.sendMessage("challenges.admin.complete.unknown-challenge");
if (!manager.containsChallenge(args.get(1))) {
user.sendMessage("challenges.errors.unknown-challenge");
return false;
}
// Complete challenge
User target = User.getInstance(targetUUID);
manager.setResetChallenge(target, args.get(1), getWorld());
manager.resetChallenge(target, manager.getChallenge(args.get(1)));
user.sendMessage("general.success");
return true;
}
@ -70,7 +75,7 @@ public class ResetChallenge extends CompositeCommand {
return Optional.of(Util.tabLimit(new ArrayList<>(Util.getOnlinePlayerList(user)), lastArg));
} else if (args.size() == 4) {
// Challenges in this world
return Optional.of(Util.tabLimit(manager.getAllChallengesList(getWorld()), lastArg));
return Optional.of(Util.tabLimit(manager.getAllChallengesNames(getWorld()), lastArg));
}
return Optional.empty();
}

View File

@ -21,14 +21,14 @@ public class ShowChallenges extends CompositeCommand {
@Override
public void setup() {
this.setPermission("admin.challenges");
this.setParametersHelp("challaneges.admin.show.parameters");
this.setDescription("challenges.admin.show.description");
this.setParametersHelp("challenges.commands.admin.show.parameters");
this.setDescription("challenges.commands.admin.show.description");
}
@Override
public boolean execute(User user, String label, List<String> args) {
((ChallengesAddon)getAddon()).getChallengesManager().getAllChallengesList().forEach(user::sendRawMessage);
((ChallengesAddon)getAddon()).getChallengesManager().getAllChallengesNames(this.getWorld()).forEach(user::sendRawMessage);
return true;
}

View File

@ -12,8 +12,9 @@ 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;
@ -76,7 +77,7 @@ public class SurroundChallengeBuilder {
}
public boolean build() {
return addon.getChallengesManager().createSurroundingChallenge(this);
return false; //addon.getChallengesManager().createSurroundingChallenge(this);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,472 @@
package world.bentobox.challenges.database.object;
import com.google.gson.annotations.Expose;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import world.bentobox.bentobox.api.configuration.ConfigComment;
import world.bentobox.bentobox.database.objects.DataObject;
import world.bentobox.challenges.ChallengesManager;
/**
* Represent a challenge level
* @author tastybento
*
*/
public class ChallengeLevel implements DataObject, Comparable<ChallengeLevel>
{
/**
* Constructor ChallengeLevel creates a new ChallengeLevel instance.
*/
public ChallengeLevel()
{
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
@ConfigComment("")
@ConfigComment("Level name")
@Expose
private String uniqueId = ChallengesManager.FREE;
@ConfigComment("")
@ConfigComment("A friendly name for the level. If blank, level name is used.")
@Expose
private String friendlyName = "";
@ConfigComment("")
@ConfigComment("ItemStack that represents current level. Will be used as icon in GUIs.")
@Expose
private ItemStack icon = new ItemStack(Material.BOOK);
@ConfigComment("")
@ConfigComment("World that this level applies in. String.")
@Expose
private String world = "";
@ConfigComment("")
@ConfigComment("The ordering of the level, lowest to highest")
@Expose
private int order;
@ConfigComment("")
@ConfigComment("The number of undone challenges that can be left on this level before")
@ConfigComment("unlocking next level.")
@Expose
private int waiverAmount = 1;
@ConfigComment("")
@ConfigComment("The message shown when unlocking this level. Single line string.")
@Expose
private String unlockMessage = "";
@ConfigComment("")
@ConfigComment("")
@ConfigComment("If this is blank, the reward text will be auto-generated, otherwise")
@ConfigComment("this will be used.")
@Expose
private String rewardText = "";
@ConfigComment("")
@ConfigComment("List of items the player will receive on completing level.")
@ConfigComment("ItemStack List.")
@Expose
private List<ItemStack> rewardItems = new ArrayList<>();
@ConfigComment("")
@ConfigComment("Experience point reward on completing level.")
@Expose
private int rewardExperience = 0;
@ConfigComment("")
@ConfigComment("Money reward. Economy plugin or addon required for this option.")
@Expose
private int rewardMoney = 0;
@ConfigComment("")
@ConfigComment("Commands to run when the player completes all challenges in current")
@ConfigComment("level. String List")
@Expose
private List<String> rewardCommands = new ArrayList<>();
@ConfigComment("")
@ConfigComment("Set of all challenges that is linked with current level.")
@ConfigComment("String Set")
@Expose
private Set<String> challenges = new HashSet<>();
// ---------------------------------------------------------------------
// Section: Getters
// ---------------------------------------------------------------------
/**
* This method returns the uniqueId value.
* @return the value of uniqueId.
* @see DataObject#getUniqueId()
*/
@Override
public String getUniqueId()
{
return uniqueId;
}
/**
* This method returns the friendlyName value.
* @return the value of friendlyName.
*/
public String getFriendlyName()
{
return friendlyName;
}
/**
* This method returns the icon value.
* @return the value of icon.
*/
public ItemStack getIcon()
{
return icon.clone();
}
/**
* This method returns the world value.
* @return the value of world.
*/
public String getWorld()
{
return world;
}
/**
* This method returns the order value.
* @return the value of order.
*/
public int getOrder()
{
return order;
}
/**
* This method returns the waiverAmount value.
* @return the value of waiverAmount.
*/
public int getWaiverAmount()
{
return waiverAmount;
}
/**
* This method returns the unlockMessage value.
* @return the value of unlockMessage.
*/
public String getUnlockMessage()
{
return unlockMessage;
}
/**
* This method returns the rewardText value.
* @return the value of rewardText.
*/
public String getRewardText()
{
return rewardText;
}
/**
* This method returns the rewardItems value.
* @return the value of rewardItems.
*/
public List<ItemStack> getRewardItems()
{
return rewardItems;
}
/**
* This method returns the rewardExperience value.
* @return the value of rewardExperience.
*/
public int getRewardExperience()
{
return rewardExperience;
}
/**
* This method returns the rewardMoney value.
* @return the value of rewardMoney.
*/
public int getRewardMoney()
{
return rewardMoney;
}
/**
* This method returns the rewardCommands value.
* @return the value of rewardCommands.
*/
public List<String> getRewardCommands()
{
return rewardCommands;
}
/**
* This method returns the challenges value.
* @return the value of challenges.
*/
public Set<String> getChallenges()
{
return challenges;
}
// ---------------------------------------------------------------------
// Section: Setters
// ---------------------------------------------------------------------
/**
* This method sets the uniqueId value.
* @param uniqueId the uniqueId new value.
*
* @see DataObject#setUniqueId(String)
*/
@Override
public void setUniqueId(String uniqueId)
{
this.uniqueId = uniqueId;
}
/**
* This method sets the friendlyName value.
* @param friendlyName the friendlyName new value.
*
*/
public void setFriendlyName(String friendlyName)
{
this.friendlyName = friendlyName;
}
/**
* This method sets the icon value.
* @param icon the icon new value.
*
*/
public void setIcon(ItemStack icon)
{
this.icon = icon;
}
/**
* This method sets the world value.
* @param world the world new value.
*
*/
public void setWorld(String world)
{
this.world = world;
}
/**
* This method sets the order value.
* @param order the order new value.
*
*/
public void setOrder(int order)
{
this.order = order;
}
/**
* This method sets the waiverAmount value.
* @param waiverAmount the waiverAmount new value.
*
*/
public void setWaiverAmount(int waiverAmount)
{
this.waiverAmount = waiverAmount;
}
/**
* This method sets the unlockMessage value.
* @param unlockMessage the unlockMessage new value.
*
*/
public void setUnlockMessage(String unlockMessage)
{
this.unlockMessage = unlockMessage;
}
/**
* This method sets the rewardText value.
* @param rewardText the rewardText new value.
*
*/
public void setRewardText(String rewardText)
{
this.rewardText = rewardText;
}
/**
* This method sets the rewardItems value.
* @param rewardItems the rewardItems new value.
*
*/
public void setRewardItems(List<ItemStack> rewardItems)
{
this.rewardItems = rewardItems;
}
/**
* This method sets the rewardExperience value.
* @param rewardExperience the rewardExperience new value.
*
*/
public void setRewardExperience(int rewardExperience)
{
this.rewardExperience = rewardExperience;
}
/**
* This method sets the rewardMoney value.
* @param rewardMoney the rewardMoney new value.
*
*/
public void setRewardMoney(int rewardMoney)
{
this.rewardMoney = rewardMoney;
}
/**
* This method sets the rewardCommands value.
* @param rewardCommands the rewardCommands new value.
*
*/
public void setRewardCommands(List<String> rewardCommands)
{
this.rewardCommands = rewardCommands;
}
/**
* This method sets the challenges value.
* @param challenges the challenges new value.
*
*/
public void setChallenges(Set<String> challenges)
{
this.challenges = challenges;
}
// ---------------------------------------------------------------------
// Section: Other methods
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public int compareTo(ChallengeLevel o)
{
if (this.equals(o))
{
return 0;
}
else
{
if (this.getWorld().equals(o.getWorld()))
{
if (this.order == o.getOrder())
{
return this.getUniqueId().compareTo(o.getUniqueId());
}
else
{
return Integer.compare(this.order, o.getOrder());
}
}
else
{
return this.getWorld().compareTo(o.getWorld());
}
}
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((uniqueId == null) ? 0 : uniqueId.hashCode());
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (!(obj instanceof ChallengeLevel))
{
return false;
}
ChallengeLevel other = (ChallengeLevel) obj;
if (uniqueId == null)
{
return other.uniqueId == null;
}
else
{
return uniqueId.equals(other.uniqueId);
}
}
}

View File

@ -14,6 +14,7 @@ import world.bentobox.bentobox.database.objects.DataObject;
* @author tastybento
*
*/
@Deprecated
public class ChallengeLevels implements DataObject, Comparable<ChallengeLevels> {
public ChallengeLevels() {}

View File

@ -21,6 +21,7 @@ import world.bentobox.bentobox.database.objects.DataObject;
* @author tastybento
*
*/
@Deprecated
public class Challenges implements DataObject {
public Challenges() {}

View File

@ -1,17 +1,13 @@
/**
*
*/
package world.bentobox.challenges.database.object;
import com.google.gson.annotations.Expose;
import org.bukkit.World;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.bukkit.World;
import com.google.gson.annotations.Expose;
import world.bentobox.bentobox.database.objects.DataObject;
import world.bentobox.bentobox.util.Util;
@ -20,173 +16,286 @@ import world.bentobox.bentobox.util.Util;
* @author tastybento
*
*/
public class ChallengesPlayerData implements DataObject {
public class ChallengesPlayerData implements DataObject
{
/**
* Constructor ChallengesPlayerData creates a new ChallengesPlayerData instance.
*/
public ChallengesPlayerData()
{
}
@Expose
private String uniqueId = "";
/**
* Challenge map, where key = unique challenge name and Value = number of times completed
*/
@Expose
private Map<String, Integer> challengeStatus = new HashMap<>();
@Expose
private Map<String, Long> challengesTimestamp = new HashMap<>();
@Expose
private Set<String> levelsDone = new HashSet<>();
// Required for bean instantiation
public ChallengesPlayerData() {}
/**
* Creates a player data entry
*
* @param uniqueId - the player's UUID in string format
*/
public ChallengesPlayerData(String uniqueId)
{
this.uniqueId = uniqueId;
}
/**
* Mark a challenge as having been completed. Will increment the number of times and timestamp
* @param world - world of challenge
* @param challengeName - unique challenge name
*/
public void setChallengeDone(World world, String challengeName) {
String name = Util.getWorld(world).getName() + challengeName;
int times = challengeStatus.getOrDefault(name, 0) + 1;
challengeStatus.put(name, times);
challengesTimestamp.put(name, System.currentTimeMillis());
}
/**
* Set the number of times a challenge has been done
* @param world - world of challenge
* @param challengeName - unique challenge name
* @param times - the number of times to set
*
*/
public void setChallengeTimes(World world, String challengeName, int times) {
String name = Util.getWorld(world).getName() + challengeName;
challengeStatus.put(name, times);
challengesTimestamp.put(name, System.currentTimeMillis());
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Check if a challenge has been done
* @param challengeName - unique challenge name
* @return true if done at least once
*/
public boolean isChallengeDone(World world, String challengeName) {
return getTimes(world, challengeName) > 0;
}
/**
* Check how many times a challenge has been done
* @param challengeName - unique challenge name
* @return - number of times
*/
public int getTimes(World world, String challengeName) {
return challengeStatus.getOrDefault(Util.getWorld(world).getName() + challengeName, 0);
}
/**
* This variable stores each player UUID as string.
*/
@Expose
private String uniqueId = "";
/**
* Creates a player data entry
* @param uniqueId - the player's UUID in string format
*/
public ChallengesPlayerData(String uniqueId) {
this.uniqueId = uniqueId;
}
/**
* Challenge map, where key = unique challenge name and Value = number of times
* completed
*/
@Expose
private Map<String, Integer> challengeStatus = new HashMap<>();
/* (non-Javadoc)
* @see world.bentobox.bbox.database.objects.DataObject#getUniqueId()
*/
@Override
public String getUniqueId() {
return uniqueId;
}
/**
* Map of challenges completion time where key is challenges unique id and value is
* timestamp when challenge was completed last time.
*/
@Expose
private Map<String, Long> challengesTimestamp = new HashMap<>();
/* (non-Javadoc)
* @see world.bentobox.bbox.database.objects.DataObject#setUniqueId(java.lang.String)
*/
@Override
public void setUniqueId(String uniqueId) {
this.uniqueId = uniqueId;
}
/**
* Set of Strings that contains all challenge levels that are completed.
*/
@Expose
private Set<String> levelsDone = new HashSet<>();
/**
* @return the challengeStatus
*/
public Map<String, Integer> getChallengeStatus() {
return challengeStatus;
}
/**
* @param challengeStatus the challengeStatus to set
*/
public void setChallengeStatus(Map<String, Integer> challengeStatus) {
this.challengeStatus = challengeStatus;
}
/**
* @return the challengesTimestamp
*/
public Map<String, Long> getChallengesTimestamp() {
return challengesTimestamp;
}
/**
* @param challengesTimestamp the challengesTimestamp to set
*/
public void setChallengesTimestamp(Map<String, Long> challengesTimestamp) {
this.challengesTimestamp = challengesTimestamp;
}
/**
* @return the levelsDone
*/
public Set<String> getLevelsDone() {
return levelsDone;
}
/**
* @param levelsDone the levelsDone to set
*/
public void setLevelsDone(Set<String> levelsDone) {
this.levelsDone = levelsDone;
}
// ---------------------------------------------------------------------
// Section: Getters
// ---------------------------------------------------------------------
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uniqueId == null) ? 0 : uniqueId.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof ChallengesPlayerData)) {
return false;
}
ChallengesPlayerData other = (ChallengesPlayerData) obj;
if (uniqueId == null) {
if (other.uniqueId != null) {
return false;
}
} else if (!uniqueId.equals(other.uniqueId)) {
return false;
}
return true;
}
/**
* @return uniqueID
* @see DataObject#getUniqueId()
*/
@Override
public String getUniqueId()
{
return uniqueId;
}
/**
* Resets all challenges and levels in world for this player
* @param world
*/
public void reset(World world) {
String worldName = Util.getWorld(world).getName();
challengeStatus.keySet().removeIf(n -> n.startsWith(worldName));
challengesTimestamp.keySet().removeIf(n -> n.startsWith(worldName));
levelsDone.removeIf(n -> n.startsWith(worldName));
}
}
/**
* This method returns the challengeStatus value.
* @return the value of challengeStatus.
*/
public Map<String, Integer> getChallengeStatus()
{
return challengeStatus;
}
/**
* This method returns the challengesTimestamp value.
* @return the value of challengesTimestamp.
*/
public Map<String, Long> getChallengesTimestamp()
{
return challengesTimestamp;
}
/**
* This method returns the levelsDone value.
* @return the value of levelsDone.
*/
public Set<String> getLevelsDone()
{
return levelsDone;
}
// ---------------------------------------------------------------------
// Section: Setters
// ---------------------------------------------------------------------
/**
* @param uniqueId - unique ID the uniqueId to set
* @see DataObject#setUniqueId(String)
*/
@Override
public void setUniqueId(String uniqueId)
{
this.uniqueId = uniqueId;
}
/**
* This method sets the challengeStatus value.
* @param challengeStatus the challengeStatus new value.
*
*/
public void setChallengeStatus(Map<String, Integer> challengeStatus)
{
this.challengeStatus = challengeStatus;
}
/**
* This method sets the challengesTimestamp value.
* @param challengesTimestamp the challengesTimestamp new value.
*
*/
public void setChallengesTimestamp(Map<String, Long> challengesTimestamp)
{
this.challengesTimestamp = challengesTimestamp;
}
/**
* This method sets the levelsDone value.
* @param levelsDone the levelsDone new value.
*
*/
public void setLevelsDone(Set<String> levelsDone)
{
this.levelsDone = levelsDone;
}
// ---------------------------------------------------------------------
// Section: Other Methods
// ---------------------------------------------------------------------
/**
* Resets all challenges and levels in world for this player
*
* @param world world which challenges must be reset.
*/
public void reset(World world)
{
String worldName = Util.getWorld(world).getName();
challengeStatus.keySet().removeIf(n -> n.startsWith(worldName));
challengesTimestamp.keySet().removeIf(n -> n.startsWith(worldName));
levelsDone.removeIf(n -> n.startsWith(worldName));
}
/**
* Mark a challenge as having been completed. Will increment the number of times and
* timestamp
*
* @param challengeName - unique challenge name
*/
public void setChallengeDone(String challengeName)
{
int times = challengeStatus.getOrDefault(challengeName, 0) + 1;
challengeStatus.put(challengeName, times);
challengesTimestamp.put(challengeName, System.currentTimeMillis());
}
/**
* Set the number of times a challenge has been done
*
* @param challengeName - unique challenge name
* @param times - the number of times to set
*/
public void setChallengeTimes(String challengeName, int times)
{
challengeStatus.put(challengeName, times);
challengesTimestamp.put(challengeName, System.currentTimeMillis());
}
/**
* Check if a challenge has been done
*
* @param challengeName - unique challenge name
* @return true if done at least once
*/
public boolean isChallengeDone(String challengeName)
{
return this.getTimes(challengeName) > 0;
}
/**
* Check how many times a challenge has been done
*
* @param challengeName - unique challenge name
* @return - number of times
*/
public int getTimes(String challengeName)
{
return challengeStatus.getOrDefault(challengeName, 0);
}
/**
* This method adds given level id to completed level set.
* @param uniqueId from ChallengeLevel object.
*/
public void addCompletedLevel(String uniqueId)
{
this.levelsDone.add(uniqueId);
}
/**
* This method returns if given level is done.
* @param uniqueId of ChallengeLevel object.
* @return <code>true</code> if level is completed, otherwise <code>false</code>
*/
public boolean isLevelDone(String uniqueId)
{
return !this.levelsDone.isEmpty() && this.levelsDone.contains(uniqueId);
}
/**
* @see Object#hashCode()
* @return object hashCode value.
*/
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((uniqueId == null) ? 0 : uniqueId.hashCode());
return result;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
* @param obj Other object.
* @return boolean that indicate if objects are equals.
*/
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (!(obj instanceof ChallengesPlayerData))
{
return false;
}
ChallengesPlayerData other = (ChallengesPlayerData) obj;
if (uniqueId == null)
{
return other.uniqueId == null;
}
else
{
return uniqueId.equals(other.uniqueId);
}
}
}

View File

@ -7,6 +7,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.bentobox.api.events.island.IslandEvent;
import world.bentobox.bentobox.api.events.island.IslandEvent.Reason;
@ -26,7 +27,7 @@ public class ResetListener implements Listener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onIslandReset(IslandEvent e) {
if (e.getReason().equals(Reason.CREATED) || (addon.getConfig().getBoolean("resetchallenges") && 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());
}
}

View File

@ -23,7 +23,7 @@ public class SaveListener implements Listener
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onWorldSave(WorldSaveEvent e)
{
if (!this.addon.getChallengesManager().getAllChallengesList(e.getWorld()).isEmpty())
if (!this.addon.getChallengesManager().getAllChallenges(e.getWorld()).isEmpty())
{
this.addon.getChallengesManager().save();
}

View File

@ -6,18 +6,23 @@ import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.database.object.Challenges;
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 Challenges challenge;
private Challenge challenge;
private World world;
private String permPrefix;
private String label;
@ -33,7 +38,7 @@ public class AdminEditGUI implements ClickHandler {
* @param permPrefix permission prefix for world
* @param label command label
*/
public AdminEditGUI(ChallengesAddon addon, User requester, User target, Challenges challenge, World world,
public AdminEditGUI(ChallengesAddon addon, User requester, User target, Challenge challenge, World world,
String permPrefix, String label) {
super();
this.addon = addon;

View File

@ -6,18 +6,23 @@ import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.database.object.Challenges;
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 Challenges challenge;
private Challenge challenge;
private World world;
private String permPrefix;
private String label;
@ -31,7 +36,7 @@ public class AdminGUI implements ClickHandler {
* @param permPrefix
* @param label
*/
public AdminGUI(ChallengesAddon addon, User player, Challenges challenge, World world,
public AdminGUI(ChallengesAddon addon, User player, Challenge challenge, World world,
String permPrefix, String label) {
super();
this.addon = addon;

View File

@ -11,10 +11,12 @@ import org.bukkit.inventory.ItemStack;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.ChallengesManager;
import world.bentobox.challenges.LevelStatus;
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.Challenges;
import world.bentobox.challenges.database.object.Challenges.ChallengeType;
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;
@ -22,11 +24,15 @@ 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 String level;
private ChallengeLevel level;
private World world;
private String permPrefix;
private String label;
@ -39,17 +45,17 @@ public class ChallengesPanels {
this.permPrefix = permPrefix;
this.label = label;
if (manager.getChallengeList().isEmpty()) {
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.getChallengeList().keySet().iterator().next().getUniqueId();
level = manager.getLevels(world).iterator().next().getUniqueId();
}
this.level = level;
this.level = this.manager.getLevel(level);
// Check if level is valid
if (!manager.isLevelUnlocked(user, level, world)) {
if (!manager.isLevelUnlocked(user, this.level)) {
return;
}
PanelBuilder panelBuilder = new PanelBuilder()
@ -65,15 +71,15 @@ public class ChallengesPanels {
}
private void addChallengeItems(PanelBuilder panelBuilder) {
Set<Challenges> levelChallenges = manager.getChallenges(level, world);
List<Challenge> levelChallenges = manager.getLevelChallenges(level);
// Only show a control panel for the level requested.
for (Challenges challenge : levelChallenges) {
for (Challenge challenge : levelChallenges) {
createItem(panelBuilder, challenge);
}
}
private void addFreeChallanges(PanelBuilder panelBuilder) {
manager.getChallenges(ChallengesManager.FREE, world).forEach(challenge -> createItem(panelBuilder, challenge));
manager.getFreeChallenges(world).forEach(challenge -> createItem(panelBuilder, challenge));
}
@ -81,11 +87,10 @@ public class ChallengesPanels {
* Creates a panel item for challenge if appropriate and adds it to panelBuilder
* @param panelBuilder
* @param challenge
* @param user
*/
private void createItem(PanelBuilder panelBuilder, Challenges challenge) {
private void createItem(PanelBuilder panelBuilder, Challenge challenge) {
// Check completion
boolean completed = manager.isChallengeComplete(user, challenge.getUniqueId(), world);
boolean completed = manager.isChallengeComplete(user, challenge);
// If challenge is removed after completion, remove it
if (completed && challenge.isRemoveWhenCompleted()) {
return;
@ -96,16 +101,13 @@ public class ChallengesPanels {
.description(challengeDescription(challenge))
.glow(completed)
.clickHandler((panel, player, c, s) -> {
if (!challenge.getChallengeType().equals(ChallengeType.ICON)) {
new TryToComplete(addon).user(player).manager(manager).challenge(challenge)
new TryToComplete(addon).user(player).manager(manager).challenge(challenge)
.world(world).permPrefix(permPrefix).label(label).build();
//new TryToComplete(addon, player, manager, challenge, world, permPrefix, label);
}
return true;
})
.build();
if (challenge.getSlot() >= 0) {
panelBuilder.item(challenge.getSlot(),item);
if (challenge.getOrder() >= 0) {
panelBuilder.item(challenge.getOrder(),item);
} else {
panelBuilder.item(item);
}
@ -130,7 +132,9 @@ public class ChallengesPanels {
PanelItem item = new PanelItemBuilder()
.icon(new ItemStack(Material.ENCHANTED_BOOK))
.name(name)
.description(manager.stringSplit(user.getTranslation("challenges.navigation","[level]",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());
@ -144,7 +148,11 @@ public class ChallengesPanels {
PanelItem item = new PanelItemBuilder()
.icon(new ItemStack(Material.BOOK))
.name(name)
.description(manager.stringSplit(user.getTranslation("challenges.to-complete", "[challengesToDo]",String.valueOf(previousStatus != null ? previousStatus.getNumberOfChallengesStillToDo() : ""), "[thisLevel]", previousLevelName)))
.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);
}
@ -157,10 +165,9 @@ public class ChallengesPanels {
* Creates the challenge description for the "item" in the inventory
*
* @param challenge
* @param player
* @return List of strings splitting challenge string into 25 chars long
*/
private List<String> challengeDescription(Challenges challenge) {
private List<String> challengeDescription(Challenge challenge) {
List<String> result = new ArrayList<String>();
String level = challenge.getLevel();
if (!level.isEmpty()) {
@ -168,9 +175,9 @@ public class ChallengesPanels {
}
// Check if completed or not
boolean complete = addon.getChallengesManager().isChallengeComplete(user, challenge.getUniqueId(), world);
boolean complete = addon.getChallengesManager().isChallengeComplete(user, challenge);
int maxTimes = challenge.getMaxTimes();
long doneTimes = addon.getChallengesManager().checkChallengeTimes(user, challenge, world);
long doneTimes = addon.getChallengesManager().getChallengeTimes(user, challenge);
if (complete) {
result.add(user.getTranslation("challenges.complete"));
}
@ -206,7 +213,7 @@ public class ChallengesPanels {
// First time
moneyReward = challenge.getRewardMoney();
rewardText = challenge.getRewardText();
expReward = challenge.getRewardExp();
expReward = challenge.getRewardExperience();
if (!rewardText.isEmpty()) {
result.addAll(splitTrans(user, "challenges.first-time-rewards"));
}
@ -214,7 +221,7 @@ public class ChallengesPanels {
// Repeat challenge
moneyReward = challenge.getRepeatMoneyReward();
rewardText = challenge.getRepeatRewardText();
expReward = challenge.getRepeatExpReward();
expReward = challenge.getRepeatExperienceReward();
if (!rewardText.isEmpty()) {
result.addAll(splitTrans(user, "challenges.repeat-rewards"));
}
@ -235,6 +242,7 @@ public class ChallengesPanels {
}
private Collection<? extends String> splitTrans(User user, String string, String...strings) {
return addon.getChallengesManager().stringSplit(user.getTranslation(string, strings));
return GuiUtils.stringSplit(user.getTranslation(string, strings),
this.addon.getChallengesSettings().getLoreLineLength());
}
}

View File

@ -1,26 +1,32 @@
package world.bentobox.challenges.panel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
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.challenges.ChallengesAddon;
import world.bentobox.challenges.ChallengesManager;
import world.bentobox.challenges.LevelStatus;
import world.bentobox.challenges.commands.ChallengesCommand;
import world.bentobox.challenges.database.object.Challenges;
import world.bentobox.challenges.database.object.Challenges.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;
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 {
@ -31,7 +37,7 @@ public class ChallengesPanels2 {
private ChallengesAddon addon;
private ChallengesManager manager;
private User requester;
private String level;
private ChallengeLevel level;
private World world;
private String permPrefix;
private String label;
@ -48,18 +54,18 @@ public class ChallengesPanels2 {
this.label = label;
this.mode = mode;
if (manager.getChallengeList().isEmpty()) {
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.getChallengeList().keySet().iterator().next().getUniqueId();
level = manager.getLevels(world).iterator().next().getUniqueId();
}
this.level = level;
this.level = manager.getLevel(level);
// Check if level is valid
if (mode.equals(Mode.PLAYER) && !manager.isLevelUnlocked(requester, level, world)) {
if (mode.equals(Mode.PLAYER) && !manager.isLevelUnlocked(requester, this.level)) {
return;
}
PanelBuilder panelBuilder = new PanelBuilder();
@ -89,13 +95,13 @@ public class ChallengesPanels2 {
private void addChallengeItems(PanelBuilder panelBuilder) {
// Only show a control panel for the level requested.
for (Challenges challenge : manager.getChallenges(level, world)) {
for (Challenge challenge : manager.getLevelChallenges(level)) {
createItem(panelBuilder, challenge);
}
}
private void addFreeChallanges(PanelBuilder panelBuilder) {
manager.getChallenges(ChallengesManager.FREE, world).forEach(challenge -> createItem(panelBuilder, challenge));
manager.getFreeChallenges(world).forEach(challenge -> createItem(panelBuilder, challenge));
}
@ -103,9 +109,8 @@ public class ChallengesPanels2 {
* Creates a panel item for challenge if appropriate and adds it to panelBuilder
* @param panelBuilder
* @param challenge
* @param requester
*/
private void createItem(PanelBuilder panelBuilder, Challenges challenge) {
private void createItem(PanelBuilder panelBuilder, Challenge challenge) {
// For admin, glow means activated. For user, glow means done
boolean glow = false;
switch (mode) {
@ -113,10 +118,10 @@ public class ChallengesPanels2 {
glow = challenge.isDeployed();
break;
case EDIT:
glow = manager.isChallengeComplete(requester, challenge.getUniqueId(), world);
glow = manager.isChallengeComplete(requester, challenge);
break;
case PLAYER:
glow = manager.isChallengeComplete(requester, challenge.getUniqueId(), world);
glow = manager.isChallengeComplete(requester, challenge);
break;
default:
break;
@ -134,33 +139,27 @@ public class ChallengesPanels2 {
if (mode.equals(Mode.ADMIN)) {
// Admin click
itemBuilder.clickHandler((panel, player, c, s) -> {
if (!challenge.getChallengeType().equals(ChallengeType.ICON)) {
new AdminGUI(addon, player, challenge, world, permPrefix, label);
}
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) -> {
if (!challenge.getChallengeType().equals(ChallengeType.ICON)) {
new AdminEditGUI(addon, player, target, challenge, world, permPrefix, label);
}
new AdminEditGUI(addon, player, target, challenge, world, permPrefix, label);
return true;
});
} else {
// Player click
itemBuilder.clickHandler((panel, player, c, s) -> {
if (!challenge.getChallengeType().equals(ChallengeType.ICON)) {
new TryToComplete(addon, player, manager, challenge, world, permPrefix, label);
}
new TryToComplete(addon, player, challenge, world, label, permPrefix).build();
return true;
});
}
// If the challenge has a specific slot allocated, use it
if (challenge.getSlot() >= 0) {
panelBuilder.item(challenge.getSlot(),itemBuilder.build());
if (challenge.getOrder() >= 0) {
panelBuilder.item(challenge.getOrder(),itemBuilder.build());
} else {
panelBuilder.item(itemBuilder.build());
}
@ -172,7 +171,7 @@ public class ChallengesPanels2 {
// Add navigation to other levels
for (LevelStatus status: manager.getChallengeLevelStatus(requester, world)) {
if (status.getLevel().getUniqueId().equalsIgnoreCase(level)) {
if (status.getLevel().getUniqueId().equalsIgnoreCase(level.getUniqueId())) {
// Skip if this is the current level
previousStatus = status;
continue;
@ -185,7 +184,9 @@ public class ChallengesPanels2 {
PanelItem item = new PanelItemBuilder()
.icon(new ItemStack(Material.ENCHANTED_BOOK))
.name(name)
.description(manager.stringSplit(requester.getTranslation("challenges.navigation","[level]",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());
@ -199,7 +200,10 @@ public class ChallengesPanels2 {
PanelItem item = new PanelItemBuilder()
.icon(new ItemStack(Material.BOOK))
.name(name)
.description(manager.stringSplit(requester.getTranslation("challenges.to-complete", "[challengesToDo]",String.valueOf(previousStatus != null ? previousStatus.getNumberOfChallengesStillToDo() : ""), "[thisLevel]", previousLevelName)))
.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);
}
@ -212,10 +216,9 @@ public class ChallengesPanels2 {
* Creates the challenge description for the "item" in the inventory
*
* @param challenge
* @param player
* @return List of strings splitting challenge string into 25 chars long
*/
private List<String> challengeDescription(Challenges challenge) {
private List<String> challengeDescription(Challenge challenge) {
List<String> result = new ArrayList<String>();
String level = challenge.getLevel();
if (!level.isEmpty()) {
@ -234,9 +237,9 @@ public class ChallengesPanels2 {
result.addAll(addRewards(challenge, true, true));
} else {
// Check if completed or not
boolean complete = addon.getChallengesManager().isChallengeComplete(requester, challenge.getUniqueId(), world);
boolean complete = addon.getChallengesManager().isChallengeComplete(requester, challenge);
int maxTimes = challenge.getMaxTimes();
long doneTimes = addon.getChallengesManager().checkChallengeTimes(requester, challenge, world);
long doneTimes = addon.getChallengesManager().getChallengeTimes(requester, challenge);
if (complete) {
result.add(requester.getTranslation("challenges.complete"));
}
@ -274,7 +277,7 @@ public class ChallengesPanels2 {
return result;
}
private List<String> addRewards(Challenges challenge, boolean complete, boolean admin) {
private List<String> addRewards(Challenge challenge, boolean complete, boolean admin) {
List<String> result = new ArrayList<>();
double moneyReward = 0;
int expReward = 0;
@ -283,7 +286,7 @@ public class ChallengesPanels2 {
// First time
moneyReward = challenge.getRewardMoney();
rewardText = challenge.getRewardText();
expReward = challenge.getRewardExp();
expReward = challenge.getRewardExperience();
if (!rewardText.isEmpty()) {
result.addAll(splitTrans(requester, "challenges.first-time-rewards"));
}
@ -292,7 +295,7 @@ public class ChallengesPanels2 {
// Repeat challenge
moneyReward = challenge.getRepeatMoneyReward();
rewardText = challenge.getRepeatRewardText();
expReward = challenge.getRepeatExpReward();
expReward = challenge.getRepeatExperienceReward();
if (!rewardText.isEmpty()) {
result.addAll(splitTrans(requester, "challenges.repeat-rewards"));
}
@ -311,6 +314,7 @@ public class ChallengesPanels2 {
}
private Collection<? extends String> splitTrans(User user, String string, String...strings) {
return addon.getChallengesManager().stringSplit(user.getTranslation(string, strings));
return GuiUtils.stringSplit(user.getTranslation(string, strings),
this.addon.getChallengesSettings().getLoreLineLength());
}
}

View File

@ -0,0 +1,804 @@
package world.bentobox.challenges.panel;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import world.bentobox.bentobox.api.panels.PanelItem;
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.database.object.Challenge;
import world.bentobox.challenges.database.object.ChallengeLevel;
import world.bentobox.challenges.utils.LevelStatus;
/**
* This class contains common methods that will be used over all GUIs. It also allows
* easier navigation between different GUIs.
*/
public abstract class CommonGUI
{
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable stores parent gui.
*/
private CommonGUI parentGUI;
/**
* Variable stores Challenges addon.
*/
protected ChallengesAddon addon;
/**
* Variable stores world in which panel is referred to.
*/
protected World world;
/**
* Variable stores user who created this panel.
*/
protected User user;
/**
* Variable stores top label of command from which panel was called.
*/
protected String topLabel;
/**
* Variable stores permission prefix of command from which panel was called.
*/
protected String permissionPrefix;
/**
* Variable stores any value.
*/
protected Object valueObject;
/**
* This object holds current page index.
*/
protected int pageIndex;
/**
* This object holds PanelItem that allows to return to previous panel.
*/
protected PanelItem returnButton;
/**
* This enum contains buttons that is offten used in multiple GUIs.
*/
protected enum CommonButtons
{
NEXT,
PREVIOUS,
RETURN
}
// ---------------------------------------------------------------------
// Section: Constants
// ---------------------------------------------------------------------
protected static final String ADMIN = "admin";
protected static final String CHALLENGES = "challenges";
protected static final String IMPORT = "import";
protected static final String SETTINGS = "settings";
protected static final String DELETE = "delete";
protected static final String EDIT = "edit";
protected static final String ADD = "add";
protected static final String RESET = "reset";
protected static final String COMPLETE = "complete";
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* Default constructor that inits panels with minimal requirements, without parent panel.
*
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
*/
public CommonGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
this(addon, world, user, topLabel, permissionPrefix, null);
}
/**
* Default constructor that inits panels with minimal requirements.
*
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
* @param parentGUI Parent panel for current panel.
*/
public CommonGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
{
this.addon = addon;
this.world = world;
this.user = user;
this.topLabel = topLabel;
this.permissionPrefix = permissionPrefix;
this.parentGUI = parentGUI;
this.pageIndex = 0;
this.returnButton = new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.return")).
icon(Material.OAK_DOOR).
clickHandler((panel, user1, clickType, i) -> {
if (this.parentGUI == null)
{
this.user.closeInventory();
return true;
}
this.parentGUI.build();
return true;
}).build();
}
// ---------------------------------------------------------------------
// Section: Common methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
public abstract void build();
/**
* This method returns PanelItem that represents given Button.
* @param button Button that must be returned.
* @return PanelItem with requested functionality.
*/
protected PanelItem getButton(CommonButtons button)
{
ItemStack icon;
String name;
List<String> description;
PanelItem.ClickHandler clickHandler;
switch (button)
{
case NEXT:
{
name = this.user.getTranslation("challenges.gui.buttons.next");
description = Collections.emptyList();
icon = new ItemStack(Material.SIGN);
clickHandler = (panel, user, clickType, slot) -> {
this.pageIndex++;
this.build();
return true;
};
break;
}
case PREVIOUS:
{
name = this.user.getTranslation("challenges.gui.buttons.previous");
description = Collections.emptyList();
icon = new ItemStack(Material.SIGN);
clickHandler = (panel, user, clickType, slot) -> {
this.pageIndex--;
this.build();
return true;
};
break;
}
case RETURN:
return this.returnButton;
default:
return null;
}
return new PanelItem(icon, name, description, false, clickHandler, false);
}
/**
* This method sets new value to ValueObject variable.
* @param value new Value of valueObject.
*/
public void setValue(Object value)
{
this.valueObject = value;
}
// ---------------------------------------------------------------------
// Section: Generate Challenge Description
// ---------------------------------------------------------------------
/**
* This method generates and returns given challenge description. It is used here to avoid multiple
* duplicates, as it would be nice to have single place where challenge could be generated.
* @param challenge Challenge which description must be generated.
* @return List of strings that will be used in challenges description.
*/
protected List<String> generateChallengeDescription(Challenge challenge, Player user)
{
List<String> result = new ArrayList<>();
// Some values to avoid overchecking.
ChallengesManager manager = this.addon.getChallengesManager();
final boolean isCompletedOnce = manager.isChallengeComplete(user.getUniqueId(), challenge);
final long doneTimes = challenge.isRepeatable() ?
manager.getChallengeTimes(this.user, challenge) :
isCompletedOnce ? 0 : 1;
boolean isCompletedAll = isCompletedOnce && challenge.isRepeatable() &&
challenge.getMaxTimes() > 0 && doneTimes >= challenge.getMaxTimes();
// Used to know if blocks, entities, items should be added after requirements and rewards.
char prevChar = ' ';
for (char c : this.addon.getChallengesSettings().getChallengeLoreMessage().toLowerCase().toCharArray())
{
switch (c)
{
case 'l':
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.level",
"[level]", manager.getLevel(challenge).getFriendlyName()));
break;
}
case 's':
{
if (isCompletedOnce)
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.completed"));
}
break;
}
case 't':
{
if (challenge.isRepeatable())
{
if (challenge.getMaxTimes() > 0)
{
if (isCompletedAll)
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.maxed-reached",
"[donetimes]", String.valueOf(doneTimes),
"[maxtimes]", String.valueOf(challenge.getMaxTimes())));
}
else
{
result.add(this.user.getTranslation(
"challenges.gui.challenge-description.completed-times-of",
"[donetimes]", String.valueOf(doneTimes),
"[maxtimes]", String.valueOf(challenge.getMaxTimes())));
}
}
else
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.completed-times",
"[donetimes]", String.valueOf(doneTimes)));
}
}
break;
}
case 'd':
{
if (!isCompletedAll)
{
result.addAll(challenge.getDescription());
}
break;
}
case 'w':
{
if (!isCompletedAll)
{
if (challenge.getChallengeType().equals(Challenge.ChallengeType.INVENTORY))
{
if (challenge.isTakeItems())
{
result.add(this.user.getTranslation(
"challenges.gui.challenge-description.warning-items-take"));
}
}
else if (challenge.getChallengeType().equals(Challenge.ChallengeType.ISLAND))
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.objects-close-by"));
if (challenge.isRemoveEntities() && !challenge.getRequiredEntities().isEmpty())
{
result.add(this.user.getTranslation(
"challenges.gui.challenge-description.warning-entities-kill"));
}
if (challenge.isRemoveBlocks() && !challenge.getRequiredBlocks().isEmpty())
{
result.add(this.user.getTranslation(
"challenges.gui.challenge-description.warning-blocks-remove"));
}
}
}
break;
}
case 'e':
{
// Display only if there are limited environments
if (!isCompletedAll &&
!challenge.getEnvironment().isEmpty() &&
challenge.getEnvironment().size() != 3)
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.environment"));
if (challenge.getEnvironment().contains(World.Environment.NORMAL))
{
result.add(this.user.getTranslation("challenges.gui.descriptions.normal"));
}
if (challenge.getEnvironment().contains(World.Environment.NETHER))
{
result.add(this.user.getTranslation("challenges.gui.descriptions.nether"));
}
if (challenge.getEnvironment().contains(World.Environment.THE_END))
{
result.add(this.user.getTranslation("challenges.gui.descriptions.the-end"));
}
}
break;
}
case 'q':
{
if (!isCompletedAll && challenge.getChallengeType() == Challenge.ChallengeType.OTHER)
{
result.addAll(this.getChallengeRequirements(challenge));
}
break;
}
case 'r':
{
if (isCompletedAll)
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.not-repeatable"));
}
else
{
result.addAll(this.getChallengeRewards(challenge, isCompletedOnce));
}
break;
}
case 'i':
{
if (!isCompletedAll)
{
if (prevChar == 'q' && challenge.getChallengeType() != Challenge.ChallengeType.OTHER)
{
result.addAll(this.getChallengeRequiredItems(challenge));
}
else if (prevChar == 'r')
{
result.addAll(this.getChallengeRewardItems(challenge, isCompletedOnce, user));
}
}
break;
}
default:
{
break;
}
}
prevChar = c;
}
result.replaceAll(x -> x.replace("[label]", this.topLabel));
return result;
}
/**
* This method returns list of strings that contains basic information about challenge rewards.
* @param challenge which reward message must be created.
* @param isCompletedOnce indicate if must use repeat rewards
* @return list of strings that contains rewards message.
*/
private List<String> getChallengeRewards(Challenge challenge, boolean isCompletedOnce)
{
String rewardText;
double rewardMoney;
int rewardExperience;
if (!isCompletedOnce)
{
rewardText = challenge.getRewardText();
rewardMoney = challenge.getRewardMoney();
rewardExperience = challenge.getRewardExperience();
}
else
{
rewardText = challenge.getRepeatRewardText();
rewardMoney = challenge.getRepeatMoneyReward();
rewardExperience = challenge.getRepeatExperienceReward();
}
List<String> result = new ArrayList<>();
// Add reward text
result.add(rewardText);
// Add message about reward XP
if (rewardExperience > 0)
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.experience-reward",
"[value]", Integer.toString(rewardExperience)));
}
// Add message about reward money
if (this.addon.getPlugin().getSettings().isUseEconomy() && rewardMoney > 0)
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.money-reward",
"[value]", Double.toString(rewardMoney)));
}
return result;
}
/**
* This method returns list of strings that contains reward items and commands from given challenge.
* @param challenge Challenge which reward items and commands must be returned.
* @param isCompletedOnce Boolean that indicate if must use repeat rewards.
* @param user Target user for command string.
* @return List of strings that contains message from challenges.
*/
private List<String> getChallengeRewardItems(Challenge challenge, boolean isCompletedOnce, Player user)
{
List<String> result = new ArrayList<>();
List<ItemStack> rewardItems;
List<String> rewardCommands;
if (!isCompletedOnce)
{
rewardItems = challenge.getRewardItems();
rewardCommands = challenge.getRewardCommands();
}
else
{
rewardItems = challenge.getRepeatItemReward();
rewardCommands = challenge.getRepeatRewardCommands();
}
// Add message about reward items
if (!rewardItems.isEmpty())
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.reward-items"));
for (ItemStack itemStack : rewardItems)
{
result.add(this.user.getTranslation("challenges.gui.descriptions.item",
"[item]", itemStack.getType().name(),
"[count]", Integer.toString(itemStack.getAmount())));
if (itemStack.hasItemMeta() && itemStack.getEnchantments().isEmpty())
{
result.add(this.user.getTranslation("challenges.gui.descriptions.item-meta",
"[meta]", itemStack.getItemMeta().toString()));
}
for (Map.Entry<Enchantment, Integer> entry : itemStack.getEnchantments().entrySet())
{
result.add(this.user.getTranslation("challenges.gui.descriptions.item-enchant",
"[enchant]", entry.getKey().getKey().getKey(), "[level]", Integer.toString(entry.getValue())));
}
}
}
// Add message about reward commands
if (!rewardCommands.isEmpty())
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.reward-commands"));
for (String command : rewardCommands)
{
result.add(this.user.getTranslation("challenges.gui.descriptions.command",
"[command]", command.replace("[player]", user.getName()).replace("[SELF]", "")));
}
}
return result;
}
/**
* This method returns list of strings that contains basic information about challenge requirements.
* @param challenge which requirements message must be created.
* @return list of strings that contains requirements message.
*/
private List<String> getChallengeRequirements(Challenge challenge)
{
List<String> result = new ArrayList<>();
// Add message about required exp
if (challenge.getRequiredExperience() > 0)
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.required-experience",
"[value]", Integer.toString(challenge.getRequiredExperience())));
}
// Add message about required money
if (this.addon.isEconomyProvided() && challenge.getRequiredMoney() > 0)
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.required-money",
"[value]", Integer.toString(challenge.getRequiredMoney())));
}
// Add message about required island level
if (this.addon.isLevelProvided() && challenge.getRequiredIslandLevel() > 0)
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.required-island-level",
"[value]", Long.toString(challenge.getRequiredIslandLevel())));
}
return result;
}
/**
* This method returns list of strings that contains required items, entities and blocks from given challenge.
* @param challenge Challenge which requirement items, entities and blocks must be returned.
* @return List of strings that contains message from challenges.
*/
private List<String> getChallengeRequiredItems(Challenge challenge)
{
List<String> result = new ArrayList<>();
// Add message about required items
if (challenge.getChallengeType().equals(Challenge.ChallengeType.INVENTORY) &&
!challenge.getRequiredItems().isEmpty())
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.required-items"));
for (ItemStack itemStack : challenge.getRequiredItems())
{
result.add(this.user.getTranslation("challenges.gui.descriptions.item",
"[item]", itemStack.getType().name(),
"[count]", Integer.toString(itemStack.getAmount())));
if (itemStack.hasItemMeta() && itemStack.getEnchantments().isEmpty())
{
result.add(this.user.getTranslation("challenges.gui.descriptions.item-meta",
"[meta]", itemStack.getItemMeta().toString()));
}
for (Map.Entry<Enchantment, Integer> entry : itemStack.getEnchantments().entrySet())
{
result.add(this.user.getTranslation("challenges.gui.descriptions.item-enchant",
"[enchant]", entry.getKey().getKey().getKey(), "[level]", Integer.toString(entry.getValue())));
}
}
}
if (challenge.getChallengeType().equals(Challenge.ChallengeType.ISLAND) &&
(!challenge.getRequiredBlocks().isEmpty() || !challenge.getRequiredEntities().isEmpty()))
{
// Add required blocks
if (!challenge.getRequiredBlocks().isEmpty())
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.required-blocks"));
for (Map.Entry<Material, Integer> entry : challenge.getRequiredBlocks().entrySet())
{
result.add(this.user.getTranslation("challenges.gui.descriptions.block",
"[block]", entry.getKey().name(),
"[count]", Integer.toString(entry.getValue())));
}
}
// Add required entities
if (!challenge.getRequiredEntities().isEmpty())
{
result.add(this.user.getTranslation("challenges.gui.challenge-description.required-entities"));
for (Map.Entry<EntityType, Integer> entry : challenge.getRequiredEntities().entrySet())
{
result.add(this.user.getTranslation("challenges.gui.descriptions.entity",
"[entity]", entry.getKey().name(),
"[count]", Integer.toString(entry.getValue())));
}
}
}
return result;
}
// ---------------------------------------------------------------------
// Section: Generate Level Description
// ---------------------------------------------------------------------
/**
* This method generates level description string.
* @param level Level which string must be generated.
* @param user User who calls generation.
* @return List with generated description.
*/
protected List<String> generateLevelDescription(ChallengeLevel level, Player user)
{
List<String> result = new ArrayList<>();
ChallengesManager manager = this.addon.getChallengesManager();
LevelStatus status = manager.getChallengeLevelStatus(user.getUniqueId(), level);
// Used to know if blocks, entities, items should be added after requirements and rewards.
char prevChar = ' ';
for (char c : this.addon.getChallengesSettings().getChallengeLoreMessage().toLowerCase().toCharArray())
{
switch (c)
{
case 's':
{
if (status.isComplete())
{
result.add(this.user.getTranslation("challenges.gui.level-description.completed"));
}
break;
}
case 't':
{
if (!status.isComplete())
{
int doneChallengeCount = (int) level.getChallenges().stream().
filter(challenge -> this.addon.getChallengesManager().isChallengeComplete(user.getUniqueId(), challenge)).
count();
result.add(this.user.getTranslation("challenges.gui.level-description.completed-challenges-of",
"[number]", Integer.toString(doneChallengeCount),
"[max]", Integer.toString(level.getChallenges().size())));
}
break;
}
case 'd':
{
if (!status.isUnlocked())
{
result.add(level.getUnlockMessage());
}
break;
}
case 'a':
{
if (!status.isUnlocked() && !status.isComplete())
{
result.add(this.user.getTranslation("challenges.gui.level-description.waver-amount",
"[value]", Integer.toString(level.getWaiverAmount())));
}
break;
}
case 'r':
{
if (status.isUnlocked() && !status.isComplete())
{
if (level.getRewardExperience() > 0)
{
result.add(this.user
.getTranslation("challenges.gui.level-description.experience-reward",
"[value]", Integer.toString(level.getWaiverAmount())));
}
if (this.addon.isEconomyProvided() && level.getRewardMoney() > 0)
{
result.add(this.user.getTranslation("challenges.gui.level-description.money-reward",
"[value]", Integer.toString(level.getRewardMoney())));
}
}
break;
}
case 'i':
{
if (status.isUnlocked() && !status.isComplete() && prevChar == 'r')
{
// Add message about reward items
if (!level.getRewardItems().isEmpty())
{
result.add(this.user.getTranslation("challenges.gui.level-description.reward-items"));
for (ItemStack itemStack : level.getRewardItems())
{
result.add(this.user.getTranslation("challenges.gui.descriptions.item",
"[item]", itemStack.getType().name(),
"[count]", Integer.toString(itemStack.getAmount())));
if (itemStack.hasItemMeta() && itemStack.getEnchantments().isEmpty())
{
result.add(this.user.getTranslation("challenges.gui.descriptions.item-meta",
"[meta]", itemStack.getItemMeta().toString()));
}
for (Map.Entry<Enchantment, Integer> entry : itemStack.getEnchantments().entrySet())
{
result.add(this.user.getTranslation("challenges.gui.descriptions.item-enchant",
"[enchant]", entry.getKey().getKey().getKey(), "[level]", Integer.toString(entry.getValue())));
}
}
}
// Add message about reward commands
if (!level.getRewardCommands().isEmpty())
{
result.add(this.user.getTranslation("challenges.gui.level-description.reward-commands"));
for (String command : level.getRewardCommands())
{
result.add(this.user.getTranslation("challenges.gui.descriptions.command",
"[command]", command.replace("[player]", user.getName()).replace("[SELF]", "")));
}
}
}
break;
}
default:
{
break;
}
}
prevChar = c;
}
result.replaceAll(x -> x.replace("[label]", this.topLabel));
return result;
}
}

View File

@ -7,6 +7,11 @@ 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;
@ -24,7 +29,7 @@ public class CreateChallengeListener implements PanelListener {
@Override
public void onInventoryClose(InventoryCloseEvent event) {
addon.getChallengesManager().createInvChallenge(user, event.getInventory());
addon.getChallengesManager().createChallenge("uniqueID");
}
@Override

View File

@ -4,6 +4,11 @@ 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) {

View File

@ -12,7 +12,7 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.ItemStack;
import world.bentobox.challenges.database.object.Challenges;
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;
@ -25,11 +25,12 @@ 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 Challenges challenge;
private Challenge challenge;
private User user;
private Panel panel;
private Panel referringPanel;
@ -38,7 +39,7 @@ public class RequiredPanel implements ClickHandler, PanelListener {
* @param challenge
* @param user
*/
public RequiredPanel(Challenges challenge, User user, Panel referringPanel) {
public RequiredPanel(Challenge challenge, User user, Panel referringPanel) {
this.challenge = challenge;
this.user = user;
this.panel = openPanel();
@ -72,7 +73,7 @@ public class RequiredPanel implements ClickHandler, PanelListener {
.clickHandler(this)
.build()).forEach(pb::item);
return pb.user(user).build();
case LEVEL:
case OTHER:
break;
default:
@ -136,8 +137,6 @@ public class RequiredPanel implements ClickHandler, PanelListener {
}
// Save changes
switch (challenge.getChallengeType()) {
case ICON:
break;
case INVENTORY:
List<ItemStack> reqItems = new ArrayList<>();
// Skip first item
@ -153,7 +152,7 @@ public class RequiredPanel implements ClickHandler, PanelListener {
break;
case ISLAND:
break;
case LEVEL:
case OTHER:
break;
default:
break;

View File

@ -0,0 +1,431 @@
package world.bentobox.challenges.panel.admin;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
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.user.User;
import world.bentobox.bentobox.util.Util;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class contains Main
*/
public class AdminGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This boolean holds if import should overwrite existing challenges.
*/
private boolean overwriteMode;
/**
* This indicate if Reset Challenges must work as reset all.
*/
private boolean resetAllMode;
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum contains all button variations. Just for cleaner code.
*/
private enum Button
{
COMPLETE_USER_CHALLENGES,
RESET_USER_CHALLENGES,
ADD_CHALLENGE,
ADD_LEVEL,
EDIT_CHALLENGE,
EDIT_LEVEL,
DELETE_CHALLENGE,
DELETE_LEVEL,
IMPORT_CHALLENGES,
BACKWARD_CHALLENGES,
EDIT_SETTINGS
}
// ---------------------------------------------------------------------
// Section: Constructor
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
*/
public AdminGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
super(addon, world, user, topLabel, permissionPrefix);
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
*/
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.gui-title"));
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(10, this.createButton(Button.COMPLETE_USER_CHALLENGES));
panelBuilder.item(19, this.createButton(Button.RESET_USER_CHALLENGES));
// Add Challenges
panelBuilder.item(12, this.createButton(Button.ADD_CHALLENGE));
panelBuilder.item(13, this.createButton(Button.ADD_LEVEL));
// Edit Challenges
panelBuilder.item(21, this.createButton(Button.EDIT_CHALLENGE));
panelBuilder.item(22, this.createButton(Button.EDIT_LEVEL));
// Remove Challenges
panelBuilder.item(30, this.createButton(Button.DELETE_CHALLENGE));
panelBuilder.item(31, this.createButton(Button.DELETE_LEVEL));
// Import Challenges
panelBuilder.item(15, this.createButton(Button.IMPORT_CHALLENGES));
panelBuilder.item(24, this.createButton(Button.BACKWARD_CHALLENGES));
// Edit Addon Settings
panelBuilder.item(16, this.createButton(Button.EDIT_SETTINGS));
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
/**
* This method is used to create PanelItem for each button type.
* @param button Button which must be created.
* @return PanelItem with necessary functionality.
*/
private PanelItem createButton(Button button)
{
ItemStack icon;
String name;
String description;
boolean glow;
PanelItem.ClickHandler clickHandler;
String permissionSuffix;
switch (button)
{
case COMPLETE_USER_CHALLENGES:
permissionSuffix = COMPLETE;
name = this.user.getTranslation("challenges.gui.buttons.admin.complete");
description = this.user.getTranslation("challenges.gui.descriptions.admin.complete");
icon = new ItemStack(Material.WRITTEN_BOOK);
clickHandler = (panel, user, clickType, slot) -> {
new ListUsersGUI(this.addon,
this.world,
this.user,
ListUsersGUI.Mode.COMPLETE,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
case RESET_USER_CHALLENGES:
permissionSuffix = RESET;
name = this.user.getTranslation("challenges.gui.buttons.admin.reset");
description = this.user.getTranslation("challenges.gui.descriptions.admin.reset");
icon = new ItemStack(Material.WRITABLE_BOOK);
glow = this.resetAllMode;
clickHandler = (panel, user, clickType, slot) -> {
if (clickType.isRightClick())
{
this.resetAllMode = !this.resetAllMode;
this.build();
}
else
{
new ListUsersGUI(this.addon,
this.world,
this.user,
this.resetAllMode ? ListUsersGUI.Mode.RESET_ALL : ListUsersGUI.Mode.RESET,
this.topLabel,
this.permissionPrefix,
this).build();
}
return true;
};
break;
case ADD_CHALLENGE:
permissionSuffix = ADD;
name = this.user.getTranslation("challenges.gui.buttons.admin.create-challenge");
description = this.user.getTranslation("challenges.gui.descriptions.admin.create-challenge");
icon = new ItemStack(Material.BOOK);
clickHandler = (panel, user, clickType, slot) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
"unique_id",
(player, reply) -> {
String newName = Util.getWorld(this.world).getName() + "_" + reply;
if (!this.addon.getChallengesManager().containsChallenge(newName))
{
new EditChallengeGUI(this.addon,
this.world,
this.user,
this.addon.getChallengesManager().createChallenge(newName),
this.topLabel,
this.permissionPrefix,
this).build();
}
else
{
this.user.sendMessage("challenges.errors.unique-id", "[id]", reply);
}
return reply;
});
return true;
};
glow = false;
break;
case ADD_LEVEL:
permissionSuffix = ADD;
name = this.user.getTranslation("challenges.gui.buttons.admin.create-level");
description = this.user.getTranslation("challenges.gui.descriptions.admin.create-level");
icon = new ItemStack(Material.BOOK);
clickHandler = (panel, user, clickType, slot) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
"unique_id",
(player, reply) -> {
String newName = Util.getWorld(this.world).getName() + "_" + reply;
if (!this.addon.getChallengesManager().containsLevel(newName))
{
new EditLevelGUI(this.addon,
this.world,
this.user,
this.addon.getChallengesManager().createLevel(newName, this.world),
this.topLabel,
this.permissionPrefix,
this).build();
}
else
{
this.user.sendMessage("challenges.errors.unique-id", "[id]", reply);
}
return reply;
});
return true;
};
glow = false;
break;
case EDIT_CHALLENGE:
permissionSuffix = EDIT;
name = this.user.getTranslation("challenges.gui.buttons.admin.edit-challenge");
description = this.user.getTranslation("challenges.gui.descriptions.admin.edit-challenge");
icon = new ItemStack(Material.ANVIL);
clickHandler = (panel, user, clickType, slot) -> {
new ListChallengesGUI(this.addon,
this.world,
this.user,
ListChallengesGUI.Mode.EDIT,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
case EDIT_LEVEL:
{
permissionSuffix = EDIT;
name = this.user.getTranslation("challenges.gui.buttons.admin.edit-level");
description = this.user.getTranslation("challenges.gui.descriptions.admin.edit-level");
icon = new ItemStack(Material.ANVIL);
clickHandler = (panel, user, clickType, slot) -> {
new ListLevelsGUI(this.addon,
this.world,
this.user,
ListLevelsGUI.Mode.EDIT,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
}
case DELETE_CHALLENGE:
{
permissionSuffix = DELETE;
name = this.user.getTranslation("challenges.gui.buttons.admin.delete-challenge");
description = this.user.getTranslation("challenges.gui.descriptions.admin.delete-challenge");
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
new ListChallengesGUI(this.addon,
this.world,
this.user,
ListChallengesGUI.Mode.DELETE,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
}
case DELETE_LEVEL:
{
permissionSuffix = DELETE;
name = this.user.getTranslation("challenges.gui.buttons.admin.delete-level");
description = this.user.getTranslation("challenges.gui.descriptions.admin.delete-level");
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
new ListLevelsGUI(this.addon,
this.world,
this.user,
ListLevelsGUI.Mode.DELETE,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
}
case IMPORT_CHALLENGES:
{
permissionSuffix = IMPORT;
name = this.user.getTranslation("challenges.gui.buttons.admin.import");
description = this.user.getTranslation("challenges.gui.descriptions.admin.import");
icon = new ItemStack(Material.HOPPER);
clickHandler = (panel, user, clickType, slot) -> {
if (clickType.isRightClick())
{
this.overwriteMode = !this.overwriteMode;
this.build();
}
else
{
// Run import command.
this.user.performCommand(this.topLabel + " " + CHALLENGES + " " + IMPORT +
(this.overwriteMode ? " overwrite" : ""));
}
return true;
};
glow = this.overwriteMode;
break;
}
case BACKWARD_CHALLENGES:
{
permissionSuffix = IMPORT;
name = this.user.getTranslation("challenges.gui.buttons.admin.backward");
description = this.user.getTranslation("challenges.gui.descriptions.admin.backward");
icon = new ItemStack(Material.HOPPER);
clickHandler = (panel, user, clickType, slot) -> {
this.addon.getImportManager().
importPreviousChallenges(this.user, this.world, false);
return true;
};
glow = false;
break;
}
case EDIT_SETTINGS:
{
permissionSuffix = SETTINGS;
name = this.user.getTranslation("challenges.gui.buttons.admin.settings");
description = this.user.getTranslation("challenges.gui.descriptions.admin.settings");
icon = new ItemStack(Material.CRAFTING_TABLE);
clickHandler = (panel, user, clickType, slot) -> {
new EditSettingsGUI(this.addon,
this.world,
this.user,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
}
default:
// This should never happen.
return null;
}
// If user does not have permission to run command, then change icon and clickHandler.
final String actionPermission = this.permissionPrefix + ADMIN + "." + CHALLENGES + "." + permissionSuffix;
if (!this.user.hasPermission(actionPermission))
{
icon = new ItemStack(Material.BARRIER);
clickHandler = (panel, user, clickType, slot) -> {
this.user.sendMessage("general.errors.no-permission", "[permission]", actionPermission);
return true;
};
}
return new PanelItem(icon, name, GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength()), glow, clickHandler, false);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,705 @@
package world.bentobox.challenges.panel.admin;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import java.util.*;
import java.util.stream.Collectors;
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.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.ChallengesManager;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.database.object.ChallengeLevel;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.ItemSwitchGUI;
import world.bentobox.challenges.panel.util.NumberGUI;
import world.bentobox.challenges.panel.util.SelectChallengeGUI;
import world.bentobox.challenges.panel.util.StringListGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class contains all necessary elements to create Levels Edit GUI.
*/
public class EditLevelGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
* @param challengeLevel ChallengeLevel that must be edited.
*/
public EditLevelGUI(ChallengesAddon addon,
World world,
User user,
ChallengeLevel challengeLevel,
String topLabel,
String permissionPrefix)
{
this(addon, world, user, challengeLevel, topLabel, permissionPrefix, null);
}
/**
* {@inheritDoc}
* @param challengeLevel ChallengeLevel that must be edited.
*/
public EditLevelGUI(ChallengesAddon addon,
World world,
User user,
ChallengeLevel challengeLevel,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
this.challengeLevel = challengeLevel;
this.currentMenuType = MenuType.PROPERTIES;
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.edit-level-title"));
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(2, this.createMenuButton(MenuType.PROPERTIES));
panelBuilder.item(4, this.createMenuButton(MenuType.REWARDS));
panelBuilder.item(6, this.createMenuButton(MenuType.CHALLENGES));
if (this.currentMenuType.equals(MenuType.PROPERTIES))
{
this.buildMainPropertiesPanel(panelBuilder);
}
else if (this.currentMenuType.equals(MenuType.CHALLENGES))
{
this.buildChallengesPanel(panelBuilder);
}
else if (this.currentMenuType.equals(MenuType.REWARDS))
{
this.buildRewardsPanel(panelBuilder);
}
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
/**
* This class populate LevelsEditGUI with main level settings.
* @param panelBuilder PanelBuilder where icons must be added.
*/
private void buildMainPropertiesPanel(PanelBuilder panelBuilder)
{
panelBuilder.item(10, this.createButton(Button.NAME));
panelBuilder.item(19, this.createButton(Button.ICON));
panelBuilder.item(22, this.createButton(Button.UNLOCK_MESSAGE));
panelBuilder.item(25, this.createButton(Button.ORDER));
panelBuilder.item(31, this.createButton(Button.WAIVER_AMOUNT));
}
/**
* This class populate LevelsEditGUI with level rewards.
* @param panelBuilder PanelBuilder where icons must be added.
*/
private void buildRewardsPanel(PanelBuilder panelBuilder)
{
panelBuilder.item(12, this.createButton(Button.REWARD_DESCRIPTION));
panelBuilder.item(21, this.createButton(Button.REWARD_COMMANDS));
panelBuilder.item(13, this.createButton(Button.REWARD_ITEM));
panelBuilder.item(22, this.createButton(Button.REWARD_EXPERIENCE));
panelBuilder.item(31, this.createButton(Button.REWARD_MONEY));
}
/**
* This class populate LevelsEditGUI with level challenges.
* @param panelBuilder PanelBuilder where icons must be added.
*/
private void buildChallengesPanel(PanelBuilder panelBuilder)
{
List<Challenge> challengeList = this.addon.getChallengesManager().getLevelChallenges(this.challengeLevel);
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = challengeList.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (challengeList.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int challengeIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (challengeIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
challengeIndex < challengeList.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createChallengeIcon(challengeList.get(challengeIndex++)));
}
index++;
}
// Navigation buttons only if necessary
if (challengeList.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
panelBuilder.item(39, this.createButton(Button.ADD_CHALLENGE));
panelBuilder.item(41, this.createButton(Button.REMOVE_CHALLENGE));
}
// ---------------------------------------------------------------------
// Section: Other methods
// ---------------------------------------------------------------------
/**
* This method creates top menu buttons, that allows to switch "tabs".
* @param menuType Menu Type which button must be constructed.
* @return PanelItem that represents given menu type.
*/
private PanelItem createMenuButton(MenuType menuType)
{
ItemStack icon;
String name;
String description;
boolean glow;
PanelItem.ClickHandler clickHandler;
switch (menuType)
{
case PROPERTIES:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.properties");
description = this.user.getTranslation("challenges.gui.descriptions.admin.properties");
icon = new ItemStack(Material.CRAFTING_TABLE);
clickHandler = (panel, user, clickType, slot) -> {
this.currentMenuType = MenuType.PROPERTIES;
this.build();
return true;
};
glow = this.currentMenuType.equals(MenuType.PROPERTIES);
break;
}
case CHALLENGES:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.challenges");
description = this.user.getTranslation("challenges.gui.descriptions.admin.challenges");
icon = new ItemStack(Material.RAIL);
clickHandler = (panel, user, clickType, slot) -> {
this.currentMenuType = MenuType.CHALLENGES;
this.build();
return true;
};
glow = this.currentMenuType.equals(MenuType.CHALLENGES);
break;
}
case REWARDS:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.rewards");
description = this.user.getTranslation("challenges.gui.descriptions.admin.rewards");
icon = new ItemStack(Material.DROPPER);
clickHandler = (panel, user, clickType, slot) -> {
this.currentMenuType = MenuType.REWARDS;
this.build();
return true;
};
glow = this.currentMenuType.equals(MenuType.REWARDS);
break;
}
default:
return null;
}
return new PanelItem(icon, name, GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength()), glow, clickHandler, false);
}
/**
* This method creates given challenge icon. On click it should open Edit Challenge GUI.
* @param challenge Challenge which icon must be created.
* @return PanelItem that represents given challenge.
*/
private PanelItem createChallengeIcon(Challenge challenge)
{
return new PanelItemBuilder().
name(challenge.getFriendlyName()).
description(GuiUtils.stringSplit(
challenge.getDescription(),
this.addon.getChallengesSettings().getLoreLineLength())).
icon(challenge.getIcon()).
clickHandler((panel, user1, clickType, slot) -> {
// Open challenges edit screen.
new EditChallengeGUI(this.addon,
this.world,
this.user,
challenge,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
}).
glow(!challenge.isDeployed()).
build();
}
/**
* This method creates buttons for default main menu.
* @param button Button which panel item must be created.
* @return PanelItem that represents given button.
*/
private PanelItem createButton(Button button)
{
ItemStack icon;
String name;
List<String> description;
boolean glow;
PanelItem.ClickHandler clickHandler;
final int lineLength = this.addon.getChallengesSettings().getLoreLineLength();
switch (button)
{
case NAME:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.name");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.name-level"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", this.challengeLevel.getFriendlyName()));
icon = new ItemStack(Material.DROPPER);
clickHandler = (panel, user, clickType, slot) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
this.challengeLevel.getFriendlyName(),
(player, reply) -> {
this.challengeLevel.setFriendlyName(reply);
this.build();
return reply;
});
return true;
};
glow = false;
break;
}
case ICON:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.icon");
description = Collections.singletonList(this.user.getTranslation(
"challenges.gui.descriptions.admin.icon-challenge"));
icon = this.challengeLevel.getIcon();
clickHandler = (panel, user, clickType, slot) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
this.challengeLevel.getIcon().getType().name(),
(player, reply) -> {
Material material = Material.getMaterial(reply);
if (material != null)
{
this.challengeLevel.setIcon(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:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.description");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.description"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", "|" + this.challengeLevel.getUnlockMessage()));
icon = new ItemStack(Material.WRITABLE_BOOK);
clickHandler = (panel, user, clickType, slot) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
this.challengeLevel.getUnlockMessage(),
(player, reply) -> {
this.challengeLevel.setUnlockMessage(reply);
this.build();
return reply;
});
return true;
};
glow = false;
break;
}
case ORDER:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.order");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.order"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.challengeLevel.getOrder())));
icon = new ItemStack(Material.DROPPER);
clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getOrder(), -1, 54, (status, value) -> {
if (status)
{
this.challengeLevel.setOrder(value);
}
this.build();
});
return true;
};
glow = false;
break;
}
case WAIVER_AMOUNT:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.waiver-amount");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.waiver-amount"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.challengeLevel.getWaiverAmount())));
icon = new ItemStack(Material.REDSTONE_TORCH);
clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getWaiverAmount(), 0, (status, value) -> {
if (status)
{
this.challengeLevel.setWaiverAmount(value);
}
this.build();
});
return true;
};
glow = false;
break;
}
case REWARD_DESCRIPTION:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reward-text");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-text-level"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", "|" + this.challengeLevel.getRewardText()));
icon = new ItemStack(Material.WRITTEN_BOOK);
clickHandler = (panel, user, clickType, slot) -> {
new AnvilGUI(this.addon.getPlugin(),
this.user.getPlayer(),
this.challengeLevel.getRewardText(),
(player, reply) -> {
this.challengeLevel.setRewardText(reply);
this.build();
return reply;
});
return true;
};
glow = false;
break;
}
case REWARD_ITEM:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reward-items");
description = new ArrayList<>(this.challengeLevel.getRewardItems().size() + 1);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-items"));
for (ItemStack itemStack : this.challengeLevel.getRewardItems())
{
description.add(this.user.getTranslation("challenges.gui.descriptions.item",
"[item]", itemStack.getType().name(),
"[count]", Integer.toString(itemStack.getAmount())));
if (itemStack.hasItemMeta() && itemStack.getEnchantments().isEmpty())
{
description.add(this.user.getTranslation("challenges.gui.descriptions.item-meta",
"[meta]", itemStack.getItemMeta().toString()));
}
for (Map.Entry<Enchantment, Integer> entry : itemStack.getEnchantments().entrySet())
{
description.add(this.user.getTranslation("challenges.gui.descriptions.item-enchant",
"[enchant]", entry.getKey().getKey().getKey(), "[level]", Integer.toString(entry.getValue())));
}
}
icon = new ItemStack(Material.CHEST);
clickHandler = (panel, user, clickType, slot) -> {
new ItemSwitchGUI(this.user, this.challengeLevel.getRewardItems(), lineLength, (status, value) -> {
if (status)
{
this.challengeLevel.setRewardItems(value);
}
this.build();
});
return true;
};
glow = false;
break;
}
case REWARD_EXPERIENCE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reward-experience");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-experience"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.challengeLevel.getRewardExperience())));
icon = new ItemStack(Material.EXPERIENCE_BOTTLE);
clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getRewardExperience(), 0, (status, value) -> {
if (status)
{
this.challengeLevel.setRewardExperience(value);
}
this.build();
});
return true;
};
glow = false;
break;
}
case REWARD_MONEY:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reward-money");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-money"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.challengeLevel.getRewardMoney())));
if (this.addon.isEconomyProvided())
{
icon = new ItemStack(Material.GOLD_INGOT);
clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getRewardMoney(), 0, (status, value) -> {
if (status)
{
this.challengeLevel.setRewardMoney(value);
}
this.build();
});
return true;
};
}
else
{
icon = new ItemStack(Material.BARRIER);
clickHandler = null;
}
glow = false;
break;
}
case REWARD_COMMANDS:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reward-commands");
description = new ArrayList<>(this.challengeLevel.getRewardCommands().size() + 1);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-commands"));
for (String command : this.challengeLevel.getRewardCommands())
{
description.add(this.user.getTranslation("challenges.gui.descriptions.command",
"[command]", command));
}
icon = new ItemStack(Material.COMMAND_BLOCK);
clickHandler = (panel, user, clickType, slot) -> {
new StringListGUI(this.user, this.challengeLevel.getRewardCommands(), lineLength, (status, value) -> {
if (status)
{
this.challengeLevel.setRewardCommands(value);
}
this.build();
});
return true;
};
glow = false;
break;
}
case ADD_CHALLENGE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.add-challenge");
description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.add-challenge"));
icon = new ItemStack(Material.WATER_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
ChallengesManager manager = this.addon.getChallengesManager();
// Get all challenge that is not in current level.
List<Challenge> challengeList = manager.getAllChallenges(this.world);
challengeList.removeAll(manager.getLevelChallenges(this.challengeLevel));
// Generate descriptions for these challenges
Map<Challenge, List<String>> challengeDescriptionMap = challengeList.stream().
collect(Collectors.toMap(challenge -> challenge,
challenge -> this.generateChallengeDescription(challenge, this.user.getPlayer()),
(a, b) -> b,
() -> new LinkedHashMap<>(challengeList.size())));
// Open select gui
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, value) -> {
if (status)
{
manager.addChallengeToLevel(value, this.challengeLevel);
}
this.build();
});
return true;
};
glow = false;
break;
}
case REMOVE_CHALLENGE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.remove-challenge");
description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.remove-challenge"));
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
ChallengesManager manager = this.addon.getChallengesManager();
// Get all challenge that is in current level.
List<Challenge> challengeList = manager.getLevelChallenges(this.challengeLevel);
// Generate descriptions for these challenges
Map<Challenge, List<String>> challengeDescriptionMap = challengeList.stream().
collect(Collectors.toMap(challenge -> challenge,
challenge -> this.generateChallengeDescription(challenge, this.user.getPlayer()),
(a, b) -> b,
() -> new LinkedHashMap<>(challengeList.size())));
// Open select gui
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, value) -> {
if (status)
{
manager.removeChallengeFromLevel(value, this.challengeLevel);
}
this.build();
});
return true;
};
glow = false;
break;
}
default:
return null;
}
return new PanelItem(icon, name, GuiUtils.stringSplit(description, lineLength), glow, clickHandler, false);
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* Represents different buttons that could be in menus.
*/
private enum Button
{
NAME,
ICON,
UNLOCK_MESSAGE,
ORDER,
WAIVER_AMOUNT,
REWARD_DESCRIPTION,
REWARD_ITEM,
REWARD_EXPERIENCE,
REWARD_MONEY,
REWARD_COMMANDS,
ADD_CHALLENGE,
REMOVE_CHALLENGE
}
/**
* Represents different types of menus
*/
private enum MenuType
{
PROPERTIES,
CHALLENGES,
REWARDS
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable holds current challenge level that is in editing GUI.
*/
private ChallengeLevel challengeLevel;
/**
* Variable holds current active menu.
*/
private MenuType currentMenuType;
}

View File

@ -0,0 +1,263 @@
package world.bentobox.challenges.panel.admin;
import org.bukkit.Material;
import org.bukkit.World;
import java.util.ArrayList;
import java.util.List;
import net.wesjd.anvilgui.AnvilGUI;
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.panel.CommonGUI;
import world.bentobox.challenges.panel.util.NumberGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This Class creates GUI that allows to change Challenges Addon Settings via in-game
* menu.
*/
public class EditSettingsGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
*/
public EditSettingsGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
this(addon, world, user, topLabel, permissionPrefix, null);
}
/**
* {@inheritDoc}
*/
public EditSettingsGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.settings-title"));
final int lineLength = this.addon.getChallengesSettings().getLoreLineLength();
GuiUtils.fillBorder(panelBuilder);
// resetChallenges
List<String> 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.addon.getChallengesSettings().isResetChallenges() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
panelBuilder.item(19, new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin.reset-on-new")).
description(GuiUtils.stringSplit(description, lineLength)).
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
description.clear();
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.broadcast"));
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().
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
description.clear();
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-completed"));
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().
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
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
}

View File

@ -0,0 +1,197 @@
package world.bentobox.challenges.panel.admin;
import org.bukkit.Material;
import org.bukkit.World;
import java.util.List;
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.database.object.Challenge;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.ConfirmationGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class contains all necessary elements to create GUI that lists all challenges.
* It allows to edit them or remove, depending on given input mode.
*/
public class ListChallengesGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Constructor
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
* @param mode - mode that indicate what should do icon clicking.
*/
public ListChallengesGUI(ChallengesAddon addon,
World world,
User user,
Mode mode,
String topLabel,
String permissionPrefix)
{
this(addon, world, user, mode, topLabel, permissionPrefix, null);
}
/**
* {@inheritDoc}
* @param mode - mode that indicate what should do icon clicking.
*/
public ListChallengesGUI(ChallengesAddon addon,
World world,
User user,
Mode mode,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
this.currentMode = mode;
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.choose-challenge-title"));
if (this.currentMode.equals(Mode.DELETE))
{
GuiUtils.fillBorder(panelBuilder, Material.RED_STAINED_GLASS_PANE);
}
else
{
GuiUtils.fillBorder(panelBuilder);
}
List<Challenge> challengeList = this.addon.getChallengesManager().getAllChallenges(this.world);
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = challengeList.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (challengeList.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int challengeIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (challengeIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
challengeIndex < challengeList.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createChallengeIcon(challengeList.get(challengeIndex++)));
}
index++;
}
// Navigation buttons only if necessary
if (challengeList.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
/**
* This method creates button for given challenge.
* @param challenge Challenge which button must be created.
* @return Challenge button.
*/
private PanelItem createChallengeIcon(Challenge challenge)
{
PanelItemBuilder itemBuilder = new PanelItemBuilder().
name(challenge.getFriendlyName()).
description(GuiUtils.stringSplit(this.generateChallengeDescription(challenge, this.user.getPlayer()),
this.addon.getChallengesSettings().getLoreLineLength())).
icon(challenge.getIcon()).
glow(challenge.isDeployed());
if (this.currentMode.equals(Mode.EDIT))
{
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
new EditChallengeGUI(this.addon,
this.world,
this.user,
challenge,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
});
}
else if (this.currentMode.equals(Mode.DELETE))
{
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
new ConfirmationGUI(this.user, value -> {
if (value)
{
this.addon.getChallengesManager().deleteChallenge(challenge);
}
this.build();
});
return true;
});
}
return itemBuilder.build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* Mode in which gui icons should processed.
*/
public enum Mode
{
EDIT,
DELETE
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Current mode in which icons will act.
*/
private Mode currentMode;
}

View File

@ -0,0 +1,199 @@
package world.bentobox.challenges.panel.admin;
import org.bukkit.Material;
import org.bukkit.World;
import java.util.List;
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.database.object.ChallengeLevel;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.ConfirmationGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class creates GUI that lists all Levels. Clicking on Level icon will be processed
* by input mode.
*/
public class ListLevelsGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Constructor
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
* @param mode - mode that indicate what should do icon clicking.
*/
public ListLevelsGUI(ChallengesAddon addon,
World world,
User user,
Mode mode,
String topLabel,
String permissionPrefix)
{
this(addon, world, user, mode, topLabel, permissionPrefix, null);
}
/**
* {@inheritDoc}
* @param mode - mode that indicate what should do icon clicking.
*/
public ListLevelsGUI(ChallengesAddon addon,
World world,
User user,
Mode mode,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
this.currentMode = mode;
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.choose-level-title"));
if (this.currentMode.equals(Mode.DELETE))
{
GuiUtils.fillBorder(panelBuilder, Material.RED_STAINED_GLASS_PANE);
}
else
{
GuiUtils.fillBorder(panelBuilder);
}
List<ChallengeLevel> levelList = this.addon.getChallengesManager().getLevels(this.world);
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = levelList.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (levelList.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int levelIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (levelIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
levelIndex < levelList.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createLevelIcon(levelList.get(levelIndex++)));
}
index++;
}
// Navigation buttons only if necessary
if (levelList.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
/**
* This method creates button for given level
* @param challengeLevel Level which button must be created.
* @return Level button.
*/
private PanelItem createLevelIcon(ChallengeLevel challengeLevel)
{
PanelItemBuilder itemBuilder = new PanelItemBuilder().
name(challengeLevel.getFriendlyName()).
description(GuiUtils.stringSplit(
this.generateLevelDescription(challengeLevel, this.user.getPlayer()),
this.addon.getChallengesSettings().getLoreLineLength())).
icon(challengeLevel.getIcon()).
glow(false);
if (this.currentMode.equals(Mode.EDIT))
{
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
new EditLevelGUI(this.addon,
this.world,
this.user,
challengeLevel,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
});
}
else if (this.currentMode.equals(Mode.DELETE))
{
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
new ConfirmationGUI(this.user, value -> {
if (value)
{
this.addon.getChallengesManager().
deleteChallengeLevel(challengeLevel);
}
this.build();
});
return true;
});
}
return itemBuilder.build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* Mode in which gui icons should processed.
*/
public enum Mode
{
EDIT,
DELETE
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Current mode in which icons will act.
*/
private Mode currentMode;
}

View File

@ -0,0 +1,330 @@
package world.bentobox.challenges.panel.admin;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
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.bentobox.database.objects.Players;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.ChallengesManager;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.ConfirmationGUI;
import world.bentobox.challenges.panel.util.SelectChallengeGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class contains methods that allows to select specific user.
*/
public class ListUsersGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* List with players that should be in GUI.
*/
private List<Player> onlineUsers;
/**
* Current operation mode.
*/
private Mode operationMode;
/**
* Current index of view mode
*/
private int modeIndex = 2;
/**
* This allows to switch which users should be in the list.
*/
private enum ViewMode
{
ONLINE,
WITH_ISLAND,
IN_WORLD
}
/**
* This allows to decide what User Icon should do.
*/
public enum Mode
{
COMPLETE,
RESET,
RESET_ALL
}
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
* @param operationMode Indicate what should happen on player icon click.
*/
public ListUsersGUI(ChallengesAddon addon,
World world,
User user,
Mode operationMode,
String topLabel,
String permissionPrefix)
{
this(addon, world, user, operationMode, topLabel, permissionPrefix, null);
}
/**
* {@inheritDoc}
* @param operationMode Indicate what should happen on player icon click.
*/
public ListUsersGUI(ChallengesAddon addon,
World world,
User user,
Mode operationMode,
String topLabel,
String permissionPrefix,
CommonGUI parentPanel)
{
super(addon, world, user, topLabel, permissionPrefix, parentPanel);
this.onlineUsers = this.collectUsers(ViewMode.IN_WORLD);
this.operationMode = operationMode;
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.choose-user-title"));
GuiUtils.fillBorder(panelBuilder);
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = this.onlineUsers.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (this.onlineUsers.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int playerIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (playerIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
playerIndex < this.onlineUsers.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createPlayerIcon(this.onlineUsers.get(playerIndex++)));
}
index++;
}
// Add button that allows to toogle different player lists.
panelBuilder.item( 4, this.createToggleButton());
// Navigation buttons only if necessary
if (this.onlineUsers.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
/**
* This method creates button for given user. If user has island it will add valid click handler.
* @param player Player which button must be created.
* @return Player button.
*/
private PanelItem createPlayerIcon(Player player)
{
int lineLength = this.addon.getChallengesSettings().getLoreLineLength();
if (this.addon.getIslands().hasIsland(this.world, player.getUniqueId()) ||
this.addon.getIslands().inTeam(this.world, player.getUniqueId()))
{
return new PanelItemBuilder().name(player.getName()).icon(player.getName()).clickHandler(
(panel, user1, clickType, slot) -> {
ChallengesManager manager = this.addon.getChallengesManager();
Map<Challenge, List<String>> challengeDescriptionMap;
switch (this.operationMode)
{
case COMPLETE:
challengeDescriptionMap = new LinkedHashMap<>();
for (Challenge challenge : manager.getAllChallenges(this.world))
{
if (!manager.isChallengeComplete(player.getUniqueId(), challenge))
{
challengeDescriptionMap.put(challenge, this.generateChallengeDescription(challenge, player));
}
}
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, value) -> {
if (status)
{
manager.setChallengeComplete(User.getInstance(player), value);
}
else
{
this.build();
}
});
break;
case RESET:
challengeDescriptionMap = new LinkedHashMap<>();
for (Challenge challenge : manager.getAllChallenges(this.world))
{
if (manager.isChallengeComplete(player.getUniqueId(), challenge))
{
challengeDescriptionMap.put(challenge, this.generateChallengeDescription(challenge, player));
}
}
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, value) -> {
if (status)
{
manager.resetChallenge(User.getInstance(player), value);
}
else
{
this.build();
}
});
break;
case RESET_ALL:
new ConfirmationGUI(this.user, status -> {
if (status)
{
manager.resetAllChallenges(this.user, this.world);
}
this.build();
});
break;
}
return true;
}).build();
}
else
{
return new PanelItemBuilder().
name(player.getName()).
icon(Material.BARRIER).
description(GuiUtils.stringSplit(this.user.getTranslation("general.errors.player-has-no-island"), lineLength)).
clickHandler((panel, user1, clickType, slot) -> false).
build();
}
}
/**
* This method collects users based on view mode.
* @param mode Given view mode.
* @return List with players in necessary view mode.
*/
private List<Player> collectUsers(ViewMode mode)
{
if (mode.equals(ViewMode.ONLINE))
{
return new ArrayList<>(Bukkit.getOnlinePlayers());
}
else if (mode.equals(ViewMode.WITH_ISLAND))
{
return this.addon.getPlayers().getPlayers().stream().
filter(player -> this.addon.getIslands().getIsland(this.world, player.getPlayerUUID()) != null).
map(Players::getPlayer).
collect(Collectors.toList());
}
else
{
return new ArrayList<>(this.world.getPlayers());
}
}
/**
* This method creates Player List view Mode toggle button.
* @return Button that toggles through player view mode.
*/
private PanelItem createToggleButton()
{
List<String> description = new ArrayList<>(ViewMode.values().length + 1);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.toggle-user-list"));
description.add((ViewMode.ONLINE == ViewMode.values()[this.modeIndex] ? "&2" : "&c") +
this.user.getTranslation("challenges.gui.descriptions.admin.mode-online"));
description.add((ViewMode.WITH_ISLAND == ViewMode.values()[this.modeIndex] ? "&2" : "&c") +
this.user.getTranslation("challenges.gui.descriptions.admin.mode-in-world"));
description.add((ViewMode.IN_WORLD == ViewMode.values()[this.modeIndex] ? "&2" : "&c") +
this.user.getTranslation("challenges.gui.descriptions.admin.mode-with-island"));
return new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin.toggle-user-list")).
description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())).
icon(Material.STONE_BUTTON).
clickHandler(
(panel, user1, clickType, slot) -> {
if (clickType.isRightClick())
{
this.modeIndex--;
if (this.modeIndex < 0)
{
this.modeIndex = ViewMode.values().length - 1;
}
}
else
{
this.modeIndex++;
if (this.modeIndex >= ViewMode.values().length)
{
this.modeIndex = 0;
}
}
this.onlineUsers = this.collectUsers(ViewMode.values()[this.modeIndex]);
this.pageIndex = 0;
this.build();
return true;
}).build();
}
}

View File

@ -0,0 +1,228 @@
package world.bentobox.challenges.panel.admin;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Material;
import org.bukkit.World;
import java.util.*;
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.panel.CommonGUI;
import world.bentobox.challenges.panel.util.NumberGUI;
import world.bentobox.challenges.panel.util.SelectBlocksGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class allows to edit material that are in required material map.
*/
public class ManageBlocksGUI extends CommonGUI
{
public ManageBlocksGUI(ChallengesAddon addon,
World world,
User user,
Map<Material, Integer> materialMap,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
this.materialMap = materialMap;
this.materialList = new ArrayList<>(this.materialMap.keySet());
// Sort materials by their ordinal value.
this.materialList.sort(Comparator.comparing(Enum::ordinal));
this.selectedMaterials = new HashSet<>();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name(this.user.getTranslation("challenges.gui.title.admin.manage-blocks"));
// Create nice border.
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(3, this.createButton(Button.ADD));
panelBuilder.item(5, this.createButton(Button.REMOVE));
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = this.materialList.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (this.materialList.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int entitiesIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (entitiesIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
entitiesIndex < this.materialList.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createElementButton(this.materialList.get(entitiesIndex++)));
}
index++;
}
// Navigation buttons only if necessary
if (this.materialList.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
// Add return button.
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
/**
* This method creates PanelItem button of requested type.
* @param button Button which must be created.
* @return new PanelItem with requested functionality.
*/
private PanelItem createButton(Button button)
{
PanelItemBuilder builder = new PanelItemBuilder();
switch (button)
{
case ADD:
builder.name(this.user.getTranslation("challenges.gui.buttons.admin.add"));
builder.icon(Material.BUCKET);
builder.clickHandler((panel, user1, clickType, slot) -> {
new SelectBlocksGUI(this.user, new HashSet<>(this.materialList), (status, material) -> {
if (status)
{
this.materialMap.put(material, 1);
this.materialList.add(material);
}
this.build();
});
return true;
});
break;
case REMOVE:
builder.name(this.user.getTranslation("challenges.gui.buttons.admin.remove-selected"));
builder.description(this.user.getTranslation("challenges.gui.descriptions.admin.remove-selected"));
builder.icon(Material.LAVA_BUCKET);
builder.clickHandler((panel, user1, clickType, slot) -> {
this.materialMap.keySet().removeAll(this.selectedMaterials);
this.materialList.removeAll(this.selectedMaterials);
this.build();
return true;
});
break;
}
return builder.build();
}
/**
* This method creates button for given material.
* @param material material which button must be created.
* @return new Button for material.
*/
private PanelItem createElementButton(Material material)
{
return new PanelItemBuilder().
name(WordUtils.capitalize(material.name().toLowerCase().replace("_", " "))).
icon(GuiUtils.getMaterialItem(material, this.materialMap.get(material))).
description(this.selectedMaterials.contains(material) ?
this.user.getTranslation("challenges.gui.descriptions.admin.selected") : "").
clickHandler((panel, user1, clickType, slot) -> {
// On right click change which entities are selected for deletion.
if (clickType.isRightClick())
{
if (!this.selectedMaterials.add(material))
{
// Remove material if it is already selected
this.selectedMaterials.remove(material);
}
this.build();
}
else
{
new NumberGUI(this.user, this.materialMap.get(material), 1, (status, value) -> {
if (status)
{
// Update value only when something changes.
this.materialMap.put(material, value);
}
this.build();
});
}
return true;
}).
glow(this.selectedMaterials.contains(material)).
build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* Functional buttons in current GUI.
*/
private enum Button
{
ADD,
REMOVE
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Contains selected materials.
*/
private Set<Material> selectedMaterials;
/**
* List of materials to avoid order issues.
*/
private List<Material> materialList;
/**
* List of required materials.
*/
private Map<Material, Integer> materialMap;
}

View File

@ -0,0 +1,248 @@
package world.bentobox.challenges.panel.admin;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import java.util.*;
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.panel.CommonGUI;
import world.bentobox.challenges.panel.util.NumberGUI;
import world.bentobox.challenges.panel.util.SelectEntityGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class allows to edit entities that are in required entities map.
*/
public class ManageEntitiesGUI extends CommonGUI
{
public ManageEntitiesGUI(ChallengesAddon addon,
World world,
User user,
Map<EntityType, Integer> requiredEntities,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
this.requiredEntities = requiredEntities;
this.entityList = new ArrayList<>(this.requiredEntities.keySet());
this.entityList.sort(Comparator.comparing(Enum::name));
this.selectedEntities = new HashSet<>(EntityType.values().length);
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name(this.user.getTranslation("challenges.gui.title.admin.manage-entities"));
// create border
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(3, this.createButton(Button.ADD));
panelBuilder.item(5, this.createButton(Button.REMOVE));
panelBuilder.item(8, this.createButton(Button.SWITCH));
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = this.entityList.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (this.entityList.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int entitiesIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (entitiesIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
entitiesIndex < this.entityList.size() &&
index < 26)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createEntityButton(this.entityList.get(entitiesIndex++)));
}
index++;
}
// Navigation buttons only if necessary
if (this.entityList.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
// Add return button.
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
/**
* This method creates PanelItem button of requested type.
* @param button Button which must be created.
* @return new PanelItem with requested functionality.
*/
private PanelItem createButton(Button button)
{
PanelItemBuilder builder = new PanelItemBuilder();
switch (button)
{
case ADD:
builder.name(this.user.getTranslation("challenges.gui.buttons.admin.add"));
builder.icon(Material.BUCKET);
builder.clickHandler((panel, user1, clickType, slot) -> {
new SelectEntityGUI(this.user, Collections.emptySet(), this.asEggs, (status, entity) -> {
if (status)
{
if (!this.requiredEntities.containsKey(entity))
{
this.requiredEntities.put(entity, 1);
this.entityList.add(entity);
}
}
this.build();
});
return true;
});
break;
case REMOVE:
builder.name(this.user.getTranslation("challenges.gui.buttons.admin.remove-selected"));
builder.description(this.user.getTranslation("challenges.gui.descriptions.admin.remove-selected"));
builder.icon(Material.LAVA_BUCKET);
builder.clickHandler((panel, user1, clickType, slot) -> {
this.requiredEntities.keySet().removeAll(this.selectedEntities);
this.entityList.removeAll(this.selectedEntities);
this.build();
return true;
});
break;
case SWITCH:
builder.name(this.user.getTranslation("challenges.gui.buttons.admin.show-eggs"));
builder.description(this.user.getTranslation("challenges.gui.descriptions.admin.show-eggs"));
builder.icon(this.asEggs ? Material.EGG : Material.PLAYER_HEAD);
builder.clickHandler((panel, user1, clickType, slot) -> {
this.asEggs = !this.asEggs;
this.build();
return true;
});
break;
}
return builder.build();
}
/**
* This method creates button for given entity.
* @param entity Entity which button must be created.
* @return new Button for entity.
*/
private PanelItem createEntityButton(EntityType entity)
{
return new PanelItemBuilder().
name(WordUtils.capitalize(entity.name().toLowerCase().replace("_", " "))).
description(this.selectedEntities.contains(entity) ?
this.user.getTranslation("challenges.gui.descriptions.admin.selected") : "").
icon(this.asEggs ?
GuiUtils.getEntityEgg(entity, this.requiredEntities.get(entity)) :
GuiUtils.getEntityHead(entity, this.requiredEntities.get(entity))).
clickHandler((panel, user1, clickType, slot) -> {
// On right click change which entities are selected for deletion.
if (clickType.isRightClick())
{
if (!this.selectedEntities.add(entity))
{
// Remove entity if it is already selected
this.selectedEntities.remove(entity);
}
this.build();
}
else
{
new NumberGUI(this.user, this.requiredEntities.get(entity), 1, (status, value) -> {
if (status)
{
// Update value only when something changes.
this.requiredEntities.put(entity, value);
}
this.build();
});
}
return true;
}).
glow(this.selectedEntities.contains(entity)).
build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* Functional buttons in current GUI.
*/
private enum Button
{
ADD,
REMOVE,
SWITCH
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* List with entities to avoid list irregularities.
*/
private List<EntityType> entityList;
/**
* Set with entities that are selected.
*/
private Set<EntityType> selectedEntities;
/**
* Map that contains all entities and their cound.
*/
private Map<EntityType, Integer> requiredEntities;
/**
* Boolean indicate if entities should be displayed as eggs or mob heads.
*/
private boolean asEggs;
}

View File

@ -0,0 +1,464 @@
package world.bentobox.challenges.panel.user;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
import java.util.List;
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.database.object.Challenge;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.TryToComplete;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.LevelStatus;
/**
* This is UserGUI class. It contains everything necessary for user to use it.
*/
public class ChallengesGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* Default constructor that inits panels with minimal requirements, without parent panel.
*
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
*/
public ChallengesGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
super(addon, world, user, topLabel, permissionPrefix);
this.challengesManager = this.addon.getChallengesManager();
this.levelStatusList = this.challengesManager.getChallengeLevelStatus(this.user, this.world);
for (LevelStatus levelStatus : this.levelStatusList)
{
if (levelStatus.isUnlocked())
{
this.lastSelectedLevel = levelStatus;
}
else
{
break;
}
}
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
@Override
public void build()
{
// Do not open gui if there is no challenges.
if (this.challengesManager.getAllChallenges(this.world).isEmpty())
{
this.addon.getLogger().severe("There are no challenges set up!");
this.user.sendMessage("general.errors.general");
return;
}
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name(this.user.getTranslation("challenges.gui.title.challenges"));
// TODO: get last completed level.
int nextItemIndex = 0;
if (this.addon.getChallengesSettings().isFreeChallengesFirst())
{
this.addFreeChallenges(panelBuilder, nextItemIndex);
// Start new row for challenges.
if (panelBuilder.nextSlot() % 9 != 0)
{
nextItemIndex = panelBuilder.nextSlot() - panelBuilder.nextSlot() % 9 + 9;
}
else
{
nextItemIndex = panelBuilder.nextSlot();
}
}
this.addChallenges(panelBuilder, nextItemIndex);
// Start new row for levels.
// Start new row for challenges.
if (panelBuilder.nextSlot() % 9 != 0)
{
nextItemIndex = panelBuilder.nextSlot() - panelBuilder.nextSlot() % 9 + 9;
}
else
{
nextItemIndex = panelBuilder.nextSlot();
}
this.addChallengeLevels(panelBuilder, nextItemIndex);
if (!this.addon.getChallengesSettings().isFreeChallengesFirst())
{
// Start new row for free challenges.
if (panelBuilder.nextSlot() % 9 != 0)
{
nextItemIndex = panelBuilder.nextSlot() - panelBuilder.nextSlot() % 9 + 9;
}
else
{
nextItemIndex = panelBuilder.nextSlot();
}
this.addFreeChallenges(panelBuilder, nextItemIndex);
}
panelBuilder.build();
}
/**
* This method adds free challenges to panelBuilder.
* @param panelBuilder where free challenges must be added.
* @param firstItemIndex index of first element.
*/
private void addFreeChallenges(PanelBuilder panelBuilder, int firstItemIndex)
{
List<Challenge> freeChallenges = this.challengesManager.getFreeChallenges(this.world);
if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges())
{
freeChallenges.removeIf(challenge -> !challenge.isRepeatable() &&
this.challengesManager.isChallengeComplete(this.user, challenge));
}
final int freeChallengesCount = freeChallenges.size();
if (freeChallengesCount > 18)
{
int index = firstItemIndex;
if (this.freeChallengeIndex > 0)
{
panelBuilder.item(index++, new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.previous")).
clickHandler((panel, user1, clickType, slot) -> {
this.freeChallengeIndex--;
this.build();
return true;
}).build());
}
int currentIndex = this.freeChallengeIndex;
while (panelBuilder.nextSlot() != firstItemIndex + 18 && currentIndex < freeChallengesCount)
{
panelBuilder.item(index++, this.getChallengeButton(freeChallenges.get(currentIndex++)));
}
// Check if one challenge is left
if (currentIndex + 1 == freeChallengesCount)
{
panelBuilder.item(index, this.getChallengeButton(freeChallenges.get(currentIndex)));
}
else if (currentIndex < freeChallengesCount)
{
panelBuilder.item(index, new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.next")).
clickHandler((panel, user1, clickType, slot) -> {
this.freeChallengeIndex++;
this.build();
return true;
}).build());
}
}
else
{
for (Challenge challenge : freeChallenges)
{
// there are no limitations. Just bunch insert.
panelBuilder.item(firstItemIndex++, this.getChallengeButton(challenge));
}
}
}
/**
* This method adds last selected level challenges to panelBuilder.
* @param panelBuilder where last selected level challenges must be added.
* @param firstItemIndex index of first element.
*/
private void addChallenges(PanelBuilder panelBuilder, int firstItemIndex)
{
if (this.lastSelectedLevel != null)
{
List<Challenge> challenges = this.challengesManager.getLevelChallenges(this.lastSelectedLevel.getLevel());
if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges())
{
challenges.removeIf(challenge -> !challenge.isRepeatable() &&
this.challengesManager.isChallengeComplete(this.user, challenge));
}
final int challengesCount = challenges.size();
if (challengesCount > 18)
{
int index = firstItemIndex;
if (this.pageIndex > 0)
{
panelBuilder.item(index++, new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.previous")).
clickHandler((panel, user1, clickType, slot) -> {
this.pageIndex--;
this.build();
return true;
}).build());
}
int currentIndex = this.pageIndex;
while (panelBuilder.nextSlot() != firstItemIndex + 18 && currentIndex < challengesCount)
{
panelBuilder.item(index++, this.getChallengeButton(challenges.get(currentIndex++)));
}
// Check if one challenge is left
if (currentIndex + 1 == challengesCount)
{
panelBuilder.item(index, this.getChallengeButton(challenges.get(currentIndex)));
}
else if (currentIndex < challengesCount)
{
panelBuilder.item(index, new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.next")).
clickHandler((panel, user1, clickType, slot) -> {
this.pageIndex++;
this.build();
return true;
}).build());
}
}
else
{
for (Challenge challenge : challenges)
{
// there are no limitations. Just bunch insert.
panelBuilder.item(firstItemIndex++, this.getChallengeButton(challenge));
}
}
}
}
/**
* This method adds challenge levels to panelBuilder.
* @param panelBuilder where challenge levels must be added.
* @param firstItemIndex index of first element.
*/
private void addChallengeLevels(PanelBuilder panelBuilder, int firstItemIndex)
{
final int levelCounts = this.levelStatusList.size();
if (levelCounts > 9)
{
int index = firstItemIndex;
if (this.levelIndex > 0)
{
panelBuilder.item(index++, new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.previous")).
clickHandler((panel, user1, clickType, slot) -> {
this.levelIndex--;
this.build();
return true;
}).build());
}
int currentIndex = this.levelIndex;
while (panelBuilder.nextSlot() != firstItemIndex + 9 && currentIndex < levelCounts)
{
panelBuilder.item(index++, this.getLevelButton(this.levelStatusList.get(currentIndex++)));
}
// Check if one challenge is left
if (currentIndex + 1 == levelCounts)
{
panelBuilder.item(index, this.getLevelButton(this.levelStatusList.get(currentIndex)));
}
else if (currentIndex < levelCounts)
{
panelBuilder.item(index, new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.next")).
clickHandler((panel, user1, clickType, slot) -> {
this.levelIndex++;
this.build();
return true;
}).build());
}
}
else
{
for (LevelStatus level : this.levelStatusList)
{
// there are no limitations. Just bunch insert.
panelBuilder.item(firstItemIndex++, this.getLevelButton(level));
}
}
}
// ---------------------------------------------------------------------
// Section: Icon building
// ---------------------------------------------------------------------
/**
* This method creates given challenges icon that on press tries to complete it.
* @param challenge which icon must be constructed.
* @return PanelItem icon for challenge.
*/
private PanelItem getChallengeButton(Challenge challenge)
{
return new PanelItemBuilder().
icon(challenge.getIcon()).
name(challenge.getFriendlyName().isEmpty() ? challenge.getUniqueId() : challenge.getFriendlyName()).
description(GuiUtils.stringSplit(this.generateChallengeDescription(challenge, this.user.getPlayer()),
this.addon.getChallengesSettings().getLoreLineLength())).
clickHandler((panel, user1, clickType, slot) -> {
if (TryToComplete.complete(this.addon,
this.user,
challenge,
this.world,
this.topLabel,
this.permissionPrefix))
{
panel.getInventory().setItem(slot, this.getChallengeButton(challenge).getItem());
}
return true;
}).
glow(this.addon.getChallengesSettings().isAddCompletedGlow() &&
this.challengesManager.isChallengeComplete(this.user, challenge)).
build();
}
/**
* This method creates button for given level.
* @param level which button must be created.
* @return Button for given level.
*/
private PanelItem getLevelButton(LevelStatus level)
{
// Create a nice name for the level
String name = level.getLevel().getFriendlyName().isEmpty() ?
level.getLevel().getUniqueId() :
level.getLevel().getFriendlyName();
ItemStack icon;
List<String> description;
PanelItem.ClickHandler clickHandler;
boolean glow;
if (level == this.lastSelectedLevel)
{
icon = level.getLevel().getIcon();
description = GuiUtils.stringSplit(
this.generateLevelDescription(level.getLevel(), user.getPlayer()),
this.addon.getChallengesSettings().getLoreLineLength());
clickHandler = null;
glow = true;
}
else if (level.isUnlocked())
{
icon = level.getLevel().getIcon();
description = GuiUtils.stringSplit(
this.generateLevelDescription(level.getLevel(), user.getPlayer()),
this.addon.getChallengesSettings().getLoreLineLength());
clickHandler = (panel, user1, clickType, slot) -> {
this.lastSelectedLevel = level;
// Reset page index for challenges.
this.pageIndex = 0;
this.build();
return true;
};
glow = this.addon.getChallengesSettings().isAddCompletedGlow() &&
this.challengesManager.isLevelCompleted(this.user, level.getLevel());
}
else
{
icon = new ItemStack(Material.BOOK);
description = GuiUtils.stringSplit(
this.user.getTranslation("challenges.gui.descriptions.level-locked",
"[count]", Integer.toString(level.getNumberOfChallengesStillToDo()),
"[level]", level.getPreviousLevel().getFriendlyName()),
this.addon.getChallengesSettings().getLoreLineLength());
clickHandler = null;
glow = false;
}
return new PanelItem(icon, name, description, glow, clickHandler, false);
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This will be used if free challenges are more then 18.
*/
private int freeChallengeIndex = 0;
/**
* This will be used if levels are more then 9.
*/
private int levelIndex;
/**
* This list contains all information about level completion in current world.
*/
private List<LevelStatus> levelStatusList;
/**
* This indicate last selected level.
*/
private LevelStatus lastSelectedLevel;
/**
* Challenge Manager object.
*/
private ChallengesManager challengesManager;
}

View File

@ -0,0 +1,114 @@
package world.bentobox.challenges.panel.util;
import org.bukkit.Material;
import java.util.function.Consumer;
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.utils.GuiUtils;
/**
* This GUI is used to confirm that user wants to run command, that should be created from
* command string list.
*/
public class ConfirmationGUI
{
/**
* This constructor inits and opens ConfirmationGUI.
*
* @param user Gui Caller.
*/
public ConfirmationGUI(User user, Consumer<Boolean> consumer)
{
this.user = user;
this.consumer = consumer;
this.build();
}
/**
* This method builds confirmation panel with 2 buttons.
*/
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.confirm-title"));
GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE);
// Accept buttons
panelBuilder.item(10, this.getButton(true));
panelBuilder.item(11, this.getButton(true));
panelBuilder.item(12, this.getButton(true));
panelBuilder.item(19, this.getButton(true));
panelBuilder.item(20, this.getButton(true));
panelBuilder.item(21, this.getButton(true));
panelBuilder.item(28, this.getButton(true));
panelBuilder.item(29, this.getButton(true));
panelBuilder.item(30, this.getButton(true));
// Cancel Buttons
panelBuilder.item(14, this.getButton(false));
panelBuilder.item(15, this.getButton(false));
panelBuilder.item(16, this.getButton(false));
panelBuilder.item(23, this.getButton(false));
panelBuilder.item(24, this.getButton(false));
panelBuilder.item(25, this.getButton(false));
panelBuilder.item(32, this.getButton(false));
panelBuilder.item(33, this.getButton(false));
panelBuilder.item(34, this.getButton(false));
panelBuilder.item(44,
new PanelItemBuilder().
icon(Material.OAK_DOOR).
name(this.user.getTranslation("challenges.gui.buttons.return")).
clickHandler( (panel, user1, clickType, slot) -> {
this.consumer.accept(false);
return true;
}).build());
panelBuilder.build();
}
/**
* This method creates button with requested value.
* @param returnValue requested value
* @return PanelItem button.
*/
private PanelItem getButton(boolean returnValue)
{
return new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.admin.buttons." + (returnValue ? "accept" : "cancel"))).
icon(returnValue ? Material.GRAY_STAINED_GLASS_PANE : Material.RED_STAINED_GLASS_PANE).
clickHandler((panel, user1, clickType, i) -> {
this.consumer.accept(returnValue);
return true;
}).
build();
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* User who wants to run command.
*/
private User user;
/**
* Stores current Consumer
*/
private Consumer<Boolean> consumer;
}

View File

@ -0,0 +1,242 @@
package world.bentobox.challenges.panel.util;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.PanelListener;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class allows to change Input ItemStacks to different ItemStacks.
*/
public class ItemSwitchGUI
{
public ItemSwitchGUI(User user, List<ItemStack> itemStacks, int lineLength, BiConsumer<Boolean, List<ItemStack>> consumer)
{
this.consumer = consumer;
this.user = user;
this.itemStacks = itemStacks;
this.lineLength = lineLength;
this.build();
}
/**
* This method builds panel that allows to change given number value.
*/
private void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.manage-items"));
// Size of inventory that user can set via GUI.
panelBuilder.size(45);
panelBuilder.listener(new CustomPanelListener());
panelBuilder.item(0, this.getButton(Button.SAVE));
for (int i = 1; i < 8; i++)
{
panelBuilder.item(i, this.getButton(Button.EMPTY));
}
panelBuilder.item(8, this.getButton(Button.CANCEL));
for (ItemStack itemStack : this.itemStacks)
{
panelBuilder.item(new CustomPanelItem(itemStack));
}
panelBuilder.build().open(this.user);
}
/**
* This method create button that does some functionality in current gui.
* @param button Button functionality.
* @return PanelItem.
*/
private PanelItem getButton(Button button)
{
ItemStack icon;
String name;
List<String> description;
PanelItem.ClickHandler clickHandler;
switch (button)
{
case SAVE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.save");
description = Collections.emptyList();
icon = new ItemStack(Material.COMMAND_BLOCK);
clickHandler = (panel, user, clickType, slot) -> {
// Magic number 9 - second row. First row is for custom buttons.
// Magic number 45 - This GUI is initialed with 45 elements.
List<ItemStack> returnItems = new ArrayList<>(36);
for (int i = 9; i < 45; i++)
{
ItemStack itemStack = panel.getInventory().getItem(i);
if (itemStack != null)
{
returnItems.add(itemStack);
}
}
this.consumer.accept(true, returnItems);
return true;
};
break;
}
case CANCEL:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.cancel");
description = Collections.emptyList();
icon = new ItemStack(Material.IRON_DOOR);
clickHandler = (panel, user, clickType, slot) -> {
this.consumer.accept(false, Collections.emptyList());
return true;
};
break;
}
case EMPTY:
{
name = "";
description = Collections.emptyList();
icon = new ItemStack(Material.BARRIER);
clickHandler = (panel, user, clickType, slot) -> true;
break;
}
default:
return null;
}
return new PanelItem(icon, name, GuiUtils.stringSplit(description, this.lineLength), false, clickHandler, false);
}
// ---------------------------------------------------------------------
// Section: Private classes
// ---------------------------------------------------------------------
/**
* This CustomPanelItem does no lose Item original MetaData. After PanelItem has been
* created it restores original meta data. It also does not allow to change anything that
* could destroy meta data.
*/
private class CustomPanelItem extends PanelItem
{
CustomPanelItem(ItemStack item)
{
super(item.clone(), "", Collections.emptyList(), false, null, false);
this.getItem().setItemMeta(item.getItemMeta());
}
@Override
public void setGlow(boolean glow)
{
}
@Override
public void setDescription(List<String> description)
{
}
@Override
public void setName(String name)
{
}
@Override
public void setHead(ItemStack itemStack)
{
}
}
/**
* This CustomPanelListener allows to move items in current panel.
*/
private class CustomPanelListener implements PanelListener
{
@Override
public void setup()
{
}
@Override
public void onInventoryClose(InventoryCloseEvent inventoryCloseEvent)
{
}
@Override
public void onInventoryClick(User user, InventoryClickEvent event)
{
// First row of elements should be ignored, as it contains buttons and blocked slots.
event.setCancelled(event.getRawSlot() < 9);
}
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum holds all button values in current gui.
*/
private enum Button
{
CANCEL,
SAVE,
EMPTY
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* User who opens current gui.
*/
private User user;
/**
* List with original items.
*/
private List<ItemStack> itemStacks;
/**
* Consumer that returns item stacks on save action.
*/
private BiConsumer<Boolean, List<ItemStack>> consumer;
/**
* This variable stores how large line can be, before warp it.
*/
private int lineLength;
}

View File

@ -0,0 +1,426 @@
package world.bentobox.challenges.panel.util;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.Collections;
import java.util.function.BiConsumer;
import net.wesjd.anvilgui.AnvilGUI;
import world.bentobox.bentobox.BentoBox;
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.utils.GuiUtils;
/**
* This gui allows to change current number and returns it to previous GUI
*/
public class NumberGUI
{
public NumberGUI(User user, int value, int lineLength, BiConsumer<Boolean, Integer> consumer)
{
this(user, value, Integer.MIN_VALUE, Integer.MAX_VALUE, lineLength, consumer);
}
public NumberGUI(User user, int value, int minValue, int lineLength, BiConsumer<Boolean, Integer> consumer)
{
this(user, value, minValue, Integer.MAX_VALUE, lineLength, consumer);
}
public NumberGUI(User user, int value, int minValue, int maxValue, int lineLength, BiConsumer<Boolean, Integer> consumer)
{
this.user = user;
this.value = value;
this.consumer = consumer;
this.minValue = minValue;
this.maxValue = maxValue;
this.currentOperation = Button.SET;
this.lineLength = lineLength;
this.build();
}
/**
* This method builds panel that allows to change given number value.
*/
private void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.manage-numbers"));
GuiUtils.fillBorder(panelBuilder);
// Others
panelBuilder.item(1, this.getButton(Button.SAVE));
panelBuilder.item(19, this.getButton(Button.VALUE));
panelBuilder.item(44, this.getButton(Button.CANCEL));
panelBuilder.item(2, this.getButton(Button.INPUT));
// operations
panelBuilder.item(3, this.getButton(Button.SET));
panelBuilder.item(4, this.getButton(Button.INCREASE));
panelBuilder.item(5, this.getButton(Button.REDUCE));
panelBuilder.item(6, this.getButton(Button.MULTIPLY));
// Numbers
panelBuilder.item(11, this.createNumberButton(1));
panelBuilder.item(12, this.createNumberButton(10));
panelBuilder.item(13, this.createNumberButton(100));
panelBuilder.item(14, this.createNumberButton(1000));
panelBuilder.item(15, this.createNumberButton(10000));
panelBuilder.item(20, this.createNumberButton(2));
panelBuilder.item(21, this.createNumberButton(20));
panelBuilder.item(22, this.createNumberButton(200));
panelBuilder.item(23, this.createNumberButton(2000));
panelBuilder.item(24, this.createNumberButton(20000));
panelBuilder.item(29, this.createNumberButton(5));
panelBuilder.item(30, this.createNumberButton(50));
panelBuilder.item(31, this.createNumberButton(500));
panelBuilder.item(32, this.createNumberButton(5000));
panelBuilder.item(33, this.createNumberButton(50000));
panelBuilder.build();
}
/**
* This method creates PanelItem with required functionality.
* @param button Functionality requirement.
* @return PanelItem with functionality.
*/
private PanelItem getButton(Button button)
{
ItemStack icon;
String name;
String description;
PanelItem.ClickHandler clickHandler;
boolean glow;
switch (button)
{
case SAVE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.save");
description = this.user.getTranslation("challenges.gui.descriptions.admin.save");
icon = new ItemStack(Material.COMMAND_BLOCK);
clickHandler = (panel, user, clickType, slot) -> {
this.consumer.accept(true, this.value);
return true;
};
glow = false;
break;
}
case CANCEL:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.cancel");
description = this.user.getTranslation("challenges.gui.descriptions.admin.cancel");
icon = new ItemStack(Material.OAK_DOOR);
clickHandler = (panel, user, clickType, slot) -> {
this.consumer.accept(false, this.value);
return true;
};
glow = false;
break;
}
case INPUT:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.input");
description = this.user.getTranslation("challenges.gui.descriptions.admin.input");
icon = new ItemStack(Material.ANVIL);
clickHandler = (panel, user, clickType, slot) -> {
new AnvilGUI(BentoBox.getInstance(),
this.user.getPlayer(),
Integer.toString(this.value),
(player, reply) -> {
try
{
this.value = Integer.parseInt(reply);
if (this.value > this.maxValue || this.value < this.minValue)
{
this.user.sendMessage("challenges.errors.not-valid-integer",
"[value]", reply,
"[min]", Integer.toString(this.minValue),
"[max]", Integer.toString(this.maxValue));
}
else
{
this.build();
}
}
catch (Exception e)
{
reply = Integer.toString(this.value);
this.user.sendMessage("challenges.errors.not-a-integer", "[value]", reply);
}
return reply;
});
return true;
};
glow = false;
break;
}
case VALUE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.value");
description = this.user.getTranslation("challenges.gui.descriptions.current-value", "[value]", Integer.toString(this.value));
icon = new ItemStack(Material.PAPER);
clickHandler = (panel, user, clickType, slot) -> true;
glow = false;
break;
}
case SET:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.set");
description = this.user.getTranslation("challenges.gui.descriptions.admin.set");
icon = new ItemStack(Material.WHITE_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.currentOperation = Button.SET;
this.build();
return true;
};
glow = this.currentOperation.equals(Button.SET);
break;
}
case INCREASE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.increase");
description = this.user.getTranslation("challenges.gui.descriptions.admin.increase");
icon = new ItemStack(Material.GREEN_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.currentOperation = Button.INCREASE;
this.build();
return true;
};
glow = this.currentOperation.equals(Button.INCREASE);
break;
}
case REDUCE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reduce");
description = this.user.getTranslation("challenges.gui.descriptions.admin.reduce");
icon = new ItemStack(Material.RED_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.currentOperation = Button.REDUCE;
this.build();
return true;
};
glow = this.currentOperation.equals(Button.REDUCE);
break;
}
case MULTIPLY:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.multiply");
description = this.user.getTranslation("challenges.gui.descriptions.admin.multiply");
icon = new ItemStack(Material.BLUE_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.currentOperation = Button.MULTIPLY;
this.build();
return true;
};
glow = this.currentOperation.equals(Button.MULTIPLY);
break;
}
default:
return null;
}
return new PanelItem(icon, name, GuiUtils.stringSplit(description, this.lineLength), glow, clickHandler, false);
}
/**
* This method creates Number Button based on input number.
* @param number Number which button must be created.
* @return PanelItem that represents number button.
*/
private PanelItem createNumberButton(int number)
{
PanelItemBuilder itemBuilder = new PanelItemBuilder();
switch (this.currentOperation)
{
case SET:
{
itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number)));
itemBuilder.icon(Material.WHITE_STAINED_GLASS_PANE);
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
this.value = number;
if (this.value > this.maxValue)
{
this.user.sendMessage("challenges.errors.not-valid-integer",
"[value]", Integer.toString(this.value),
"[min]", Integer.toString(this.minValue),
"[max]", Integer.toString(this.maxValue));
this.value = this.maxValue;
}
if (this.value < this.minValue)
{
this.user.sendMessage("challenges.errors.not-valid-integer",
"[value]", Integer.toString(this.value),
"[min]", Integer.toString(this.minValue),
"[max]", Integer.toString(this.maxValue));
this.value = this.minValue;
}
this.build();
return true;
});
break;
}
case INCREASE:
{
itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number)));
itemBuilder.icon(Material.GREEN_STAINED_GLASS_PANE);
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
this.value += number;
if (this.value > this.maxValue)
{
this.user.sendMessage("challenges.errors.not-valid-integer",
"[value]", Integer.toString(this.value),
"[min]", Integer.toString(this.minValue),
"[max]", Integer.toString(this.maxValue));
this.value = this.maxValue;
}
this.build();
return true;
});
break;
}
case REDUCE:
{
itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number)));
itemBuilder.icon(Material.RED_STAINED_GLASS_PANE);
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
this.value -= number;
if (this.value < this.minValue)
{
this.user.sendMessage("challenges.errors.not-valid-integer",
"[value]", Integer.toString(this.value),
"[min]", Integer.toString(this.minValue),
"[max]", Integer.toString(this.maxValue));
this.value = this.minValue;
}
this.build();
return true;
});
break;
}
case MULTIPLY:
{
itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number)));
itemBuilder.icon(Material.BLUE_STAINED_GLASS_PANE);
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
this.value *= number;
if (this.value > this.maxValue)
{
this.user.sendMessage("challenges.errors.not-valid-integer",
"[value]", Integer.toString(this.value),
"[min]", Integer.toString(this.minValue),
"[max]", Integer.toString(this.maxValue));
this.value = this.maxValue;
}
this.build();
return true;
});
break;
}
}
return itemBuilder.build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum contains all button types.
*/
private enum Button
{
SAVE,
CANCEL,
INPUT,
VALUE,
SET,
INCREASE,
REDUCE,
MULTIPLY
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable stores current GUI consumer.
*/
private BiConsumer<Boolean, Integer> consumer;
/**
* User who runs GUI.
*/
private User user;
/**
* Current value.
*/
private int value;
/**
* Minimal value that is allowed to set.
*/
private int minValue;
/**
* Maximal value that is allowed to set.
*/
private int maxValue;
/**
* This variable holds which operation now is processed.
*/
private Button currentOperation;
/**
* This variable stores how large line can be, before warp it.
*/
private int lineLength;
}

View File

@ -0,0 +1,195 @@
package world.bentobox.challenges.panel.util;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
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.utils.GuiUtils;
/**
* This class contains all necessary things that allows to select single block from all ingame blocks. Selected
* block will be returned via BiConsumer.
*/
public class SelectBlocksGUI
{
public SelectBlocksGUI(User user, BiConsumer<Boolean, Material> consumer)
{
this(user, Collections.emptySet(), consumer);
}
public SelectBlocksGUI(User user, Set<Material> excludedMaterial, BiConsumer<Boolean, Material> consumer)
{
this.consumer = consumer;
this.user = user;
// Current GUI cannot display air blocks. It crashes with null-pointer
excludedMaterial.add(Material.AIR);
excludedMaterial.add(Material.CAVE_AIR);
excludedMaterial.add(Material.VOID_AIR);
// Piston head and moving piston is not necessary. useless.
excludedMaterial.add(Material.PISTON_HEAD);
excludedMaterial.add(Material.MOVING_PISTON);
// Barrier cannot be accessible to user.
excludedMaterial.add(Material.BARRIER);
this.elements = new ArrayList<>();
for (Material material : Material.values())
{
if (material.isBlock() && !material.isLegacy() && !excludedMaterial.contains(material))
{
this.elements.add(material);
}
}
this.build(0);
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
public void build(int pageIndex)
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name(this.user.getTranslation("challenges.gui.title.admin.select-block"));
GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE);
final int MAX_ELEMENTS = 21;
final int correctPage;
if (pageIndex < 0)
{
correctPage = this.elements.size() / MAX_ELEMENTS;
}
else if (pageIndex > (this.elements.size() / MAX_ELEMENTS))
{
correctPage = 0;
}
else
{
correctPage = pageIndex;
}
int entitiesIndex = MAX_ELEMENTS * correctPage;
// I want first row to be only for navigation and return button.
int index = 10;
while (entitiesIndex < ((correctPage + 1) * MAX_ELEMENTS) &&
entitiesIndex < this.elements.size())
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createMaterialButton(this.elements.get(entitiesIndex++)));
}
index++;
}
panelBuilder.item(4,
new PanelItemBuilder().
icon(Material.RED_STAINED_GLASS_PANE).
name(this.user.getTranslation("challenges.gui.buttons.admin.cancel")).
clickHandler( (panel, user1, clickType, slot) -> {
this.consumer.accept(false, null);
return true;
}).build());
if (this.elements.size() > MAX_ELEMENTS)
{
// Navigation buttons if necessary
panelBuilder.item(18,
new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.previous")).
clickHandler((panel, user1, clickType, slot) -> {
this.build(correctPage - 1);
return true;
}).build());
panelBuilder.item(26,
new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.next")).
clickHandler((panel, user1, clickType, slot) -> {
this.build(correctPage + 1);
return true;
}).build());
}
panelBuilder.item(44,
new PanelItemBuilder().
icon(Material.OAK_DOOR).
name(this.user.getTranslation("challenges.gui.buttons.return")).
clickHandler( (panel, user1, clickType, slot) -> {
this.consumer.accept(false, null);
return true;
}).build());
panelBuilder.build();
}
/**
* This method creates PanelItem that represents given material.
* Some materials is not displayable in Inventory GUI, so they are replaced with "placeholder" items.
* @param material Material which icon must be created.
* @return PanelItem that represents given material.
*/
private PanelItem createMaterialButton(Material material)
{
ItemStack itemStack = GuiUtils.getMaterialItem(material);
return new PanelItemBuilder().
name(WordUtils.capitalize(material.name().toLowerCase().replace("_", " "))).
icon(itemStack).
clickHandler((panel, user1, clickType, slot) -> {
this.consumer.accept(true, material);
return true;
}).
glow(!itemStack.getType().equals(material)).
build();
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* List with elements that will be displayed in current GUI.
*/
private List<Material> elements;
/**
* This variable stores consumer.
*/
private BiConsumer<Boolean, Material> consumer;
/**
* User who runs GUI.
*/
private User user;
}

View File

@ -0,0 +1,172 @@
package world.bentobox.challenges.panel.util;
import org.bukkit.Material;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
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.database.object.Challenge;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class creates new GUI that allows to select single challenge, which is returned via consumer.
*/
public class SelectChallengeGUI
{
public SelectChallengeGUI(User user, Map<Challenge, List<String>> challengesDescriptionMap, int lineLength, BiConsumer<Boolean, Challenge> consumer)
{
this.consumer = consumer;
this.user = user;
this.challengesList = new ArrayList<>(challengesDescriptionMap.keySet());
this.challengesDescriptionMap = challengesDescriptionMap;
this.lineLength = lineLength;
this.build(0);
}
/**
* This method builds panel that allows to select single challenge from input challenges.
*/
private void build(int pageIndex)
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.select-challenge"));
GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE);
// Maximal elements in page.
final int MAX_ELEMENTS = 21;
final int correctPage;
if (pageIndex < 0)
{
correctPage = this.challengesList.size() / MAX_ELEMENTS;
}
else if (pageIndex > (this.challengesList.size() / MAX_ELEMENTS))
{
correctPage = 0;
}
else
{
correctPage = pageIndex;
}
panelBuilder.item(4,
new PanelItemBuilder().
icon(Material.RED_STAINED_GLASS_PANE).
name(this.user.getTranslation("challenges.gui.buttons.return")).
clickHandler( (panel, user1, clickType, slot) -> {
this.consumer.accept(false, null);
return true;
}).build());
if (this.challengesList.size() > MAX_ELEMENTS)
{
// Navigation buttons if necessary
panelBuilder.item(18,
new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.previous")).
clickHandler((panel, user1, clickType, slot) -> {
this.build(correctPage - 1);
return true;
}).build());
panelBuilder.item(26,
new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.next")).
clickHandler((panel, user1, clickType, slot) -> {
this.build(correctPage + 1);
return true;
}).build());
}
int challengesIndex = MAX_ELEMENTS * correctPage;
// I want first row to be only for navigation and return button.
int index = 10;
while (challengesIndex < ((correctPage + 1) * MAX_ELEMENTS) &&
challengesIndex < this.challengesList.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index,
this.createChallengeButton(this.challengesList.get(challengesIndex++)));
}
index++;
}
panelBuilder.item(44,
new PanelItemBuilder().
icon(Material.OAK_DOOR).
name(this.user.getTranslation("challenges.gui.buttons.return")).
clickHandler( (panel, user1, clickType, slot) -> {
this.consumer.accept(false, null);
return true;
}).build());
panelBuilder.build();
}
/**
* This method builds PanelItem for given challenge.
* @param challenge Challenge which PanelItem must be created.
* @return new PanelItem for given Challenge.
*/
private PanelItem createChallengeButton(Challenge challenge)
{
return new PanelItemBuilder().
name(challenge.getFriendlyName()).
description(GuiUtils.stringSplit(this.challengesDescriptionMap.get(challenge), this.lineLength)).
icon(challenge.getIcon()).
clickHandler((panel, user1, clickType, slot) -> {
this.consumer.accept(true, challenge);
return true;
}).build();
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable stores consumer.
*/
private BiConsumer<Boolean, Challenge> consumer;
/**
* User who runs GUI.
*/
private User user;
/**
* Current value.
*/
private List<Challenge> challengesList;
/**
* Map that contains all challenge descriptions
*/
private Map<Challenge, List<String>> challengesDescriptionMap;
/**
* This variable stores how large line can be, before warp it.
*/
private int lineLength;
}

View File

@ -0,0 +1,190 @@
package world.bentobox.challenges.panel.util;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import java.util.*;
import java.util.function.BiConsumer;
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.utils.GuiUtils;
/**
* This GUI allows to select single entity and return it via Consumer.
*/
public class SelectEntityGUI
{
public SelectEntityGUI(User user, BiConsumer<Boolean, EntityType> consumer)
{
this(user, Collections.emptySet(), true, consumer);
}
public SelectEntityGUI(User user, Set<EntityType> excludedEntities, boolean asEggs, BiConsumer<Boolean, EntityType> consumer)
{
this.consumer = consumer;
this.user = user;
this.asEggs = asEggs;
this.entities = new ArrayList<>(EntityType.values().length);
for (EntityType entityType : EntityType.values())
{
if (entityType.isAlive() && !excludedEntities.contains(entityType))
{
this.entities.add(entityType);
}
}
// Sort mobs by their name for easier search.
this.entities.sort(Comparator.comparing(Enum::name));
this.build(0);
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds
*/
private void build(int pageIndex)
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.select-entity"));
GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE);
// Maximal elements in page.
final int MAX_ELEMENTS = 21;
final int correctPage;
if (pageIndex < 0)
{
correctPage = this.entities.size() / MAX_ELEMENTS;
}
else if (pageIndex > (this.entities.size() / MAX_ELEMENTS))
{
correctPage = 0;
}
else
{
correctPage = pageIndex;
}
panelBuilder.item(4,
new PanelItemBuilder().
icon(Material.RED_STAINED_GLASS_PANE).
name(this.user.getTranslation("challenges.gui.buttons.admin.cancel")).
clickHandler( (panel, user1, clickType, slot) -> {
this.consumer.accept(false, null);
return true;
}).build());
if (this.entities.size() > MAX_ELEMENTS)
{
// Navigation buttons if necessary
panelBuilder.item(18,
new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.previous")).
clickHandler((panel, user1, clickType, slot) -> {
this.build(correctPage - 1);
return true;
}).build());
panelBuilder.item(26,
new PanelItemBuilder().
icon(Material.SIGN).
name(this.user.getTranslation("challenges.gui.buttons.next")).
clickHandler((panel, user1, clickType, slot) -> {
this.build(correctPage + 1);
return true;
}).build());
}
int entitiesIndex = MAX_ELEMENTS * correctPage;
// I want first row to be only for navigation and return button.
int slot = 10;
while (entitiesIndex < ((correctPage + 1) * MAX_ELEMENTS) &&
entitiesIndex < this.entities.size() &&
slot < 36)
{
if (!panelBuilder.slotOccupied(slot))
{
panelBuilder.item(slot,
this.createEntityButton(this.entities.get(entitiesIndex++)));
}
slot++;
}
panelBuilder.item(44,
new PanelItemBuilder().
icon(Material.OAK_DOOR).
name(this.user.getTranslation("challenges.gui.buttons.return")).
clickHandler( (panel, user1, clickType, i) -> {
this.consumer.accept(false, null);
return true;
}).build());
panelBuilder.build();
}
/**
* This method builds PanelItem for given entity.
* @param entity Entity which PanelItem must be created.
* @return new PanelItem for given Entity.
*/
private PanelItem createEntityButton(EntityType entity)
{
ItemStack itemStack = this.asEggs ? GuiUtils.getEntityEgg(entity) : GuiUtils.getEntityHead(entity);
return new PanelItemBuilder().
name(WordUtils.capitalize(entity.name().toLowerCase().replace("_", " "))).
icon(itemStack).
clickHandler((panel, user1, clickType, slot) -> {
this.consumer.accept(true, entity);
return true;
}).build();
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable stores consumer.
*/
private BiConsumer<Boolean, EntityType> consumer;
/**
* User who runs GUI.
*/
private User user;
/**
* This variable stores if mobs must be displayed as Eggs "true" or Heads "false".
*/
private boolean asEggs;
/**
* Entities that must be in list.
*/
private List<EntityType> entities;
}

View File

@ -0,0 +1,147 @@
package world.bentobox.challenges.panel.util;
import org.bukkit.Material;
import org.bukkit.World;
import java.util.Collections;
import java.util.Set;
import java.util.function.BiConsumer;
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.utils.GuiUtils;
/**
* This class creates panel that allows to select and deselect World Environments. On save it runs
* input consumer with true and selected values.
*/
public class SelectEnvironmentGUI
{
public SelectEnvironmentGUI(User user, Set<World.Environment> values, BiConsumer<Boolean, Set<World.Environment>> consumer)
{
this.user = user;
this.values = values;
this.consumer = consumer;
this.build();
}
/**
* This method builds environment select panel.
*/
private void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.toggle-environment"));
GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE);
panelBuilder.item(3, new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin.save")).
icon(Material.GREEN_STAINED_GLASS_PANE).
clickHandler((panel, user1, clickType, index) -> {
this.consumer.accept(true, this.values);
return true;
}).
build());
panelBuilder.item(5, new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin.cancel")).
icon(Material.RED_STAINED_GLASS_PANE).
clickHandler((panel, user1, clickType, i) -> {
this.consumer.accept(false, Collections.emptySet());
return true;
}).
build());
panelBuilder.item(20, new PanelItemBuilder().
name(World.Environment.NETHER.name()).
icon(Material.NETHERRACK).
clickHandler((panel, user1, clickType, i) -> {
if (this.values.contains(World.Environment.NETHER))
{
this.values.remove(World.Environment.NETHER);
}
else
{
this.values.add(World.Environment.NETHER);
}
this.build();
return true;
}).
glow(this.values.contains(World.Environment.NETHER)).
build());
panelBuilder.item(22, new PanelItemBuilder().
name(World.Environment.NORMAL.name()).
icon(Material.DIRT).
clickHandler((panel, user1, clickType, i) -> {
if (this.values.contains(World.Environment.NORMAL))
{
this.values.remove(World.Environment.NORMAL);
}
else
{
this.values.add(World.Environment.NORMAL);
}
this.build();
return true;
}).
glow(this.values.contains(World.Environment.NORMAL)).
build());
panelBuilder.item(24, new PanelItemBuilder().
name(World.Environment.THE_END.name()).
icon(Material.END_STONE).
clickHandler((panel, user1, clickType, i) -> {
if (this.values.contains(World.Environment.THE_END))
{
this.values.remove(World.Environment.THE_END);
}
else
{
this.values.add(World.Environment.THE_END);
}
this.build();
return true;
}).
glow(this.values.contains(World.Environment.THE_END)).
build());
panelBuilder.item(44, new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.return")).
icon(Material.OAK_DOOR).
clickHandler((panel, user1, clickType, i) -> {
this.consumer.accept(false, Collections.emptySet());
return true;
}).
build());
panelBuilder.build();
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* User who wants to run command.
*/
private User user;
/**
* List with selected environments.
*/
private Set<World.Environment> values;
/**
* Stores current Consumer
*/
private BiConsumer<Boolean, Set<World.Environment>> consumer;
}

View File

@ -0,0 +1,254 @@
package world.bentobox.challenges.panel.util;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import net.wesjd.anvilgui.AnvilGUI;
import world.bentobox.bentobox.BentoBox;
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.utils.GuiUtils;
/**
* This GUI allows to edit List of strings. AnvilGUI has limited text space, so splitting
* text in multiple rows allows to edit each row separately.
*/
public class StringListGUI
{
public StringListGUI(User user, Collection<String> value, int lineLength, BiConsumer<Boolean, List<String>> consumer)
{
this(user, new ArrayList<>(value), lineLength, consumer);
}
public StringListGUI(User user, List<String> value, int lineLength, BiConsumer<Boolean, List<String>> consumer)
{
this.consumer = consumer;
this.user = user;
this.value = value;
this.lineLength = lineLength;
if (this.value.size() > 21)
{
// TODO: throw error that so large list cannot be edited.
this.consumer.accept(false, this.value);
}
else
{
this.build();
}
}
/**
* This method builds panel that allows to change given string value.
*/
private void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name(this.user.getTranslation("challenges.gui.title.admin.edit-text-fields"));
GuiUtils.fillBorder(panelBuilder, Material.BLACK_STAINED_GLASS_PANE);
panelBuilder.item(1, this.getButton(Button.SAVE));
panelBuilder.item(2, this.getButton(Button.VALUE));
panelBuilder.item(4, this.getButton(Button.ADD));
panelBuilder.item(5, this.getButton(Button.REMOVE));
panelBuilder.item(6, this.getButton(Button.CLEAR));
panelBuilder.item(44, this.getButton(Button.CANCEL));
int slot = 10;
for (int stringIndex = 0; stringIndex < this.value.size() && slot < 36; stringIndex++)
{
if (!panelBuilder.slotOccupied(slot))
{
panelBuilder.item(slot,
this.createStringElement(this.value.get(stringIndex), stringIndex));
}
slot++;
}
panelBuilder.build();
}
/**
* This method create button that does some functionality in current gui.
* @param button Button functionality.
* @return PanelItem.
*/
private PanelItem getButton(Button button)
{
ItemStack icon;
String name;
List<String> description;
PanelItem.ClickHandler clickHandler;
switch (button)
{
case SAVE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.save");
description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.save"));
icon = new ItemStack(Material.GREEN_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.consumer.accept(true, this.value);
return true;
};
break;
}
case CANCEL:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.cancel");
description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.cancel"));
icon = new ItemStack(Material.OAK_DOOR);
clickHandler = (panel, user, clickType, slot) -> {
this.consumer.accept(false, this.value);
return true;
};
break;
}
case VALUE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.value");
description = new ArrayList<>();
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", "[value]", ""));
description.addAll(this.value);
icon = new ItemStack(Material.PAPER);
clickHandler = (panel, user, clickType, slot) -> true;
break;
}
case ADD:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.add");
description = Collections.emptyList();
icon = new ItemStack(Material.WHITE_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
new AnvilGUI(BentoBox.getInstance(),
this.user.getPlayer(),
" ",
(player, reply) -> {
this.value.add(reply);
this.build();
return reply;
});
return true;
};
break;
}
case CLEAR:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.clear");
description = Collections.emptyList();
icon = new ItemStack(Material.RED_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.value.clear();
this.build();
return true;
};
break;
}
case REMOVE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.remove-empty");
description = Collections.emptyList();
icon = new ItemStack(Material.BLUE_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.value.removeIf(String::isEmpty);
this.build();
return true;
};
break;
}
default:
return null;
}
return new PanelItem(icon, name, GuiUtils.stringSplit(description, this.lineLength), false, clickHandler, false);
}
/**
* This method creates paper icon that represents single line from list.
* @param element Paper Icon name
* @return PanelItem.
*/
private PanelItem createStringElement(String element, int stringIndex)
{
return new PanelItemBuilder().
name(element).
icon(Material.PAPER).
clickHandler((panel, user1, clickType, i) -> {
new AnvilGUI(BentoBox.getInstance(),
this.user.getPlayer(),
element,
(player, reply) -> {
this.value.set(stringIndex, reply);
this.build();
return reply;
});
return true;
}).build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum holds all button values in current gui.
*/
private enum Button
{
VALUE,
ADD,
REMOVE,
CANCEL,
CLEAR,
SAVE
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable stores consumer.
*/
private BiConsumer<Boolean, List<String>> consumer;
/**
* User who runs GUI.
*/
private User user;
/**
* Current value.
*/
private List<String> value;
/**
* This variable stores how large line can be, before warp it.
*/
private int lineLength;
}

View File

@ -0,0 +1,420 @@
package world.bentobox.challenges.utils;
import org.apache.commons.lang.WordUtils;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
/**
* This class contains static methods that is used through multiple GUIs.
*/
public class GuiUtils
{
// ---------------------------------------------------------------------
// Section: Border around GUIs
// ---------------------------------------------------------------------
/**
* This method creates border of black panes around given panel with 5 rows.
* @param panelBuilder PanelBuilder which must be filled with border blocks.
*/
public static void fillBorder(PanelBuilder panelBuilder)
{
GuiUtils.fillBorder(panelBuilder, 5, Material.BLACK_STAINED_GLASS_PANE);
}
/**
* This method sets black stained glass pane around Panel with given row count.
* @param panelBuilder object that builds Panel.
* @param rowCount in Panel.
*/
public static void fillBorder(PanelBuilder panelBuilder, int rowCount)
{
GuiUtils.fillBorder(panelBuilder, rowCount, Material.BLACK_STAINED_GLASS_PANE);
}
/**
* This method sets blocks with given Material around Panel with 5 rows.
* @param panelBuilder object that builds Panel.
* @param material that will be around Panel.
*/
public static void fillBorder(PanelBuilder panelBuilder, Material material)
{
GuiUtils.fillBorder(panelBuilder, 5, material);
}
/**
* This method sets blocks with given Material around Panel with given row count.
* @param panelBuilder object that builds Panel.
* @param rowCount in Panel.
* @param material that will be around Panel.
*/
public static void fillBorder(PanelBuilder panelBuilder, int rowCount, Material material)
{
// Only for useful filling.
if (rowCount < 3)
{
return;
}
for (int i = 0; i < 9 * rowCount; i++)
{
// First (i < 9) and last (i > 35) rows must be filled
// First column (i % 9 == 0) and last column (i % 9 == 8) also must be filled.
if (i < 9 || i > 9 * (rowCount - 1) || i % 9 == 0 || i % 9 == 8)
{
panelBuilder.item(i, BorderBlock.getPanelBorder(material));
}
}
}
// ---------------------------------------------------------------------
// Section: ItemStack transformations
// ---------------------------------------------------------------------
/**
* This method transforms entity into egg or block that corresponds given entity.
* If entity egg is not found, then it is replaced by block that represents entity or
* barrier block.
* @param entity Entity which egg must be returned.
* @return ItemStack that may be egg for given entity.
*/
public static ItemStack getEntityEgg(EntityType entity)
{
return GuiUtils.getEntityEgg(entity, 1);
}
/**
* This method transforms entity into egg or block that corresponds given entity.
* If entity egg is not found, then it is replaced by block that represents entity or
* barrier block.
* @param entity Entity which egg must be returned.
* @param amount Amount of ItemStack elements.
* @return ItemStack that may be egg for given entity.
*/
public static ItemStack getEntityEgg(EntityType entity, int amount)
{
ItemStack itemStack;
switch (entity)
{
case PIG_ZOMBIE:
itemStack = new ItemStack(Material.ZOMBIE_PIGMAN_SPAWN_EGG);
break;
case ENDER_DRAGON:
itemStack = new ItemStack(Material.DRAGON_EGG);
break;
case WITHER:
itemStack = new ItemStack(Material.SOUL_SAND);
break;
case PLAYER:
itemStack = new ItemStack(Material.PLAYER_HEAD);
break;
case MUSHROOM_COW:
itemStack = new ItemStack(Material.MOOSHROOM_SPAWN_EGG);
break;
case SNOWMAN:
itemStack = new ItemStack(Material.CARVED_PUMPKIN);
break;
case IRON_GOLEM:
itemStack = new ItemStack(Material.IRON_BLOCK);
break;
case ARMOR_STAND:
itemStack = new ItemStack(Material.ARMOR_STAND);
break;
default:
Material material = Material.getMaterial(entity.name() + "_SPAWN_EGG");
if (material == null)
{
itemStack = new ItemStack(Material.BARRIER);
}
else
{
itemStack = new ItemStack(material);
}
break;
}
itemStack.setAmount(amount);
return itemStack;
}
/**
* This method transforms entity into player head with skin that corresponds given
* entity. If entity head is not found, then it is replaced by barrier block.
* @param entity Entity which head must be returned.
* @return ItemStack that may be head for given entity.
*/
public static ItemStack getEntityHead(EntityType entity)
{
return GuiUtils.getEntityHead(entity, 1);
}
/**
* This method transforms entity into player head with skin that corresponds given
* entity. If entity head is not found, then it is replaced by barrier block.
* @param entity Entity which head must be returned.
* @param amount Amount of ItemStack elements.
* @return ItemStack that may be head for given entity.
*/
public static ItemStack getEntityHead(EntityType entity, int amount)
{
ItemStack itemStack;
switch (entity)
{
case PLAYER:
itemStack = new ItemStack(Material.PLAYER_HEAD);
break;
case WITHER_SKELETON:
itemStack = new ItemStack(Material.WITHER_SKELETON_SKULL);
break;
case ARMOR_STAND:
itemStack = new ItemStack(Material.ARMOR_STAND);
break;
case SKELETON:
itemStack = new ItemStack(Material.SKELETON_SKULL);
break;
case GIANT:
case ZOMBIE:
itemStack = new ItemStack(Material.ZOMBIE_HEAD);
break;
case CREEPER:
itemStack = new ItemStack(Material.CREEPER_HEAD);
break;
case ENDER_DRAGON:
itemStack = new ItemStack(Material.DRAGON_HEAD);
break;
default:
HeadLib head = HeadLib.getHead(entity.name());
if (head == null)
{
itemStack = new ItemStack(Material.BARRIER);
}
else
{
itemStack = head.toItemStack();
}
break;
}
itemStack.setAmount(amount);
return itemStack;
}
/**
* This method transforms material into item stack that can be displayed in users
* inventory.
* @param material Material which item stack must be returned.
* @return ItemStack that represents given material.
*/
public static ItemStack getMaterialItem(Material material)
{
return GuiUtils.getMaterialItem(material, 1);
}
/**
* This method transforms material into item stack that can be displayed in users
* inventory.
* @param material Material which item stack must be returned.
* @param amount Amount of ItemStack elements.
* @return ItemStack that represents given material.
*/
public static ItemStack getMaterialItem(Material material, int amount)
{
ItemStack itemStack;
// Process items that cannot be item-stacks.
if (material.name().contains("WALL_"))
{
// Materials that is attached to wall cannot be showed in GUI. But they should be in list.
itemStack = new ItemStack(Material.getMaterial(material.name().replace("WALL_", "")));
}
else if (material.name().startsWith("POTTED_"))
{
// Materials Potted elements cannot be in inventory.
itemStack = new ItemStack(Material.getMaterial(material.name().replace("POTTED_", "")));
}
else if (material.equals(Material.MELON_STEM) || material.equals(Material.ATTACHED_MELON_STEM))
{
itemStack = new ItemStack(Material.MELON_SEEDS);
}
else if (material.equals(Material.PUMPKIN_STEM) || material.equals(Material.ATTACHED_PUMPKIN_STEM))
{
itemStack = new ItemStack(Material.PUMPKIN_SEEDS);
}
else if (material.equals(Material.TALL_SEAGRASS))
{
itemStack = new ItemStack(Material.SEAGRASS);
}
else if (material.equals(Material.CARROTS))
{
itemStack = new ItemStack(Material.CARROT);
}
else if (material.equals(Material.BEETROOTS))
{
itemStack = new ItemStack(Material.BEETROOT);
}
else if (material.equals(Material.POTATOES))
{
itemStack = new ItemStack(Material.POTATO);
}
else if (material.equals(Material.COCOA))
{
itemStack = new ItemStack(Material.COCOA_BEANS);
}
else if (material.equals(Material.KELP_PLANT))
{
itemStack = new ItemStack(Material.KELP);
}
else if (material.equals(Material.REDSTONE_WIRE))
{
itemStack = new ItemStack(Material.REDSTONE);
}
else if (material.equals(Material.TRIPWIRE))
{
itemStack = new ItemStack(Material.STRING);
}
else if (material.equals(Material.FROSTED_ICE))
{
itemStack = new ItemStack(Material.ICE);
}
else if (material.equals(Material.END_PORTAL) || material.equals(Material.END_GATEWAY) || material.equals(Material.NETHER_PORTAL))
{
itemStack = new ItemStack(Material.PAPER);
}
else if (material.equals(Material.BUBBLE_COLUMN) || material.equals(Material.WATER))
{
itemStack = new ItemStack(Material.WATER_BUCKET);
}
else if (material.equals(Material.LAVA))
{
itemStack = new ItemStack(Material.LAVA_BUCKET);
}
else if (material.equals(Material.FIRE))
{
itemStack = new ItemStack(Material.FIRE_CHARGE);
}
else if (material.equals(Material.AIR) || material.equals(Material.CAVE_AIR) || material.equals(Material.VOID_AIR))
{
itemStack = new ItemStack(Material.GLASS_BOTTLE);
}
else if (material.equals(Material.PISTON_HEAD) || material.equals(Material.MOVING_PISTON))
{
itemStack = new ItemStack(Material.PISTON);
}
else
{
itemStack = new ItemStack(material);
}
itemStack.setAmount(amount);
return itemStack;
}
/**
* This BorderBlock is simple PanelItem but without item meta data.
*/
private static class BorderBlock extends PanelItem
{
private BorderBlock(ItemStack icon)
{
super(icon.clone(), " ", Collections.emptyList(), false, null, false);
}
/**
* This method retunrs BorderBlock with requested item stack.
* @param material of which broder must be created.
* @return PanelItem that acts like border.
*/
private static BorderBlock getPanelBorder(Material material)
{
ItemStack itemStack = new ItemStack(material);
itemStack.getItemMeta().setDisplayName(" ");
return new BorderBlock(itemStack);
}
}
/**
* Simple splitter
*
* @param string - string to be split
* @param warpLength - whn warp should be affected.
* @return list of split strings
*/
public static List<String> stringSplit(String string, int warpLength)
{
// Remove all ending lines from string.
string = string.replaceAll("([\\r\\n])", "\\|");
string = ChatColor.translateAlternateColorCodes('&', string);
// Check length of lines
List<String> result = new ArrayList<>();
Arrays.stream(string.split("\\|")).
map(line -> Arrays.asList(WordUtils.wrap(line, warpLength).split(System.getProperty("line.separator")))).
forEach(result::addAll);
// Fix colors, as splitting my lost that information.
for (int i = 0, resultSize = result.size(); i < resultSize; i++)
{
if (i > 0)
{
String lastColor = ChatColor.getLastColors(result.get(i - 1));
result.set(i, lastColor + result.get(i));
}
}
return result;
}
/**
* Simple splitter for all strings in list.
* @param stringList - list of string to be split
* @param warpLength - whn warp should be affected.
* @return list of split strings
*/
public static List<String> stringSplit(List<String> stringList, int warpLength)
{
if (stringList.isEmpty())
{
return stringList;
}
List<String> newList = new ArrayList<>(stringList.size());
stringList.stream().map(string -> GuiUtils.stringSplit(string, warpLength)).forEach(newList::addAll);
return newList;
}
}

View File

@ -0,0 +1,298 @@
/*
* Written in 2018 by Daniel Saukel
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software
* to the public domain worldwide.
*
* This software is distributed without any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*
* @url https://github.com/DRE2N/HeadLib
*/
package world.bentobox.challenges.utils;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_13_R2.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.*;
import net.minecraft.server.v1_13_R2.NBTBase;
import net.minecraft.server.v1_13_R2.NBTTagCompound;
import net.minecraft.server.v1_13_R2.NBTTagList;
/**
* @author Daniel Saukel
*
* BONNe modified it for BentoBox by leaving only mob heads and removing unused code.
*/
public enum HeadLib
{
// ---------------------------------------------------------------------
// Section: Library of All Mob heads
// ---------------------------------------------------------------------
/**
* All enum values.
*/
SPIDER("8bdb71d0-4724-48b2-9344-e79480424798", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="),
CAVE_SPIDER("39173a7a-c957-4ec1-ac1a-43e5a64983df", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDE2NDVkZmQ3N2QwOTkyMzEwN2IzNDk2ZTk0ZWViNWMzMDMyOWY5N2VmYzk2ZWQ3NmUyMjZlOTgyMjQifX19"),
ENDERMAN("0de98464-1274-4dd6-bba8-370efa5d41a8", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2E1OWJiMGE3YTMyOTY1YjNkOTBkOGVhZmE4OTlkMTgzNWY0MjQ1MDllYWRkNGU2YjcwOWFkYTUwYjljZiJ9fX0="),
SLIME("7f0b0873-df6a-4a19-9bcd-f6c90ef804c7", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODk1YWVlYzZiODQyYWRhODY2OWY4NDZkNjViYzQ5NzYyNTk3ODI0YWI5NDRmMjJmNDViZjNiYmI5NDFhYmU2YyJ9fX0="),
GUARDIAN("f3898fe0-04fb-4f9c-8f8b-146a1d894007", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzI1YWY5NjZhMzI2ZjlkOTg0NjZhN2JmODU4MmNhNGRhNjQ1M2RlMjcxYjNiYzllNTlmNTdhOTliNjM1MTFjNiJ9fX0="),
GHAST("807f287f-6499-4e93-a887-0a298ab3091f", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGI2YTcyMTM4ZDY5ZmJiZDJmZWEzZmEyNTFjYWJkODcxNTJlNGYxYzk3ZTVmOTg2YmY2ODU1NzFkYjNjYzAifX19"),
BLAZE("7ceb88b2-7f5f-4399-abb9-7068251baa9d", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjc4ZWYyZTRjZjJjNDFhMmQxNGJmZGU5Y2FmZjEwMjE5ZjViMWJmNWIzNWE0OWViNTFjNjQ2Nzg4MmNiNWYwIn19fQ=="),
MAGMA_CUBE("96aced64-5b85-4b99-b825-53cd7a9f9726", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzg5NTdkNTAyM2M5MzdjNGM0MWFhMjQxMmQ0MzQxMGJkYTIzY2Y3OWE5ZjZhYjM2Yjc2ZmVmMmQ3YzQyOSJ9fX0="),
WITHER("119c371b-ea16-47c9-ad7f-23b3d894520a", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2RmNzRlMzIzZWQ0MTQzNjk2NWY1YzU3ZGRmMjgxNWQ1MzMyZmU5OTllNjhmYmI5ZDZjZjVjOGJkNDEzOWYifX19"),
ENDER_DRAGON("433562fa-9e23-443e-93b0-d67228435e77", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzRlY2MwNDA3ODVlNTQ2NjNlODU1ZWYwNDg2ZGE3MjE1NGQ2OWJiNGI3NDI0YjczODFjY2Y5NWIwOTVhIn19fQ=="),
SHULKER("d700b0b9-be74-4630-8cb5-62c979828ef6", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjFkMzUzNGQyMWZlODQ5OTI2MmRlODdhZmZiZWFjNGQyNWZmZGUzNWM4YmRjYTA2OWU2MWUxNzg3ZmYyZiJ9fX0="),
CREEPER("eed2d903-ca32-4cc7-b33b-ca3bdbe18da4", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjQyNTQ4MzhjMzNlYTIyN2ZmY2EyMjNkZGRhYWJmZTBiMDIxNWY3MGRhNjQ5ZTk0NDQ3N2Y0NDM3MGNhNjk1MiJ9fX0="),
ZOMBIE("9959dd98-efb3-4ee9-a8fb-2fda0218cda0", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTZmYzg1NGJiODRjZjRiNzY5NzI5Nzk3M2UwMmI3OWJjMTA2OTg0NjBiNTFhNjM5YzYwZTVlNDE3NzM0ZTExIn19fQ=="),
ZOMBIE_VILLAGER("bcaf2b85-d421-47cc-a40a-455e77bfb60b", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzdlODM4Y2NjMjY3NzZhMjE3YzY3ODM4NmY2YTY1NzkxZmU4Y2RhYjhjZTljYTRhYzZiMjgzOTdhNGQ4MWMyMiJ9fX0="),
ZOMBIE_PIGMAN("6540c046-d6ea-4aff-9766-32a54ebe6958", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzRlOWM2ZTk4NTgyZmZkOGZmOGZlYjMzMjJjZDE4NDljNDNmYjE2YjE1OGFiYjExY2E3YjQyZWRhNzc0M2ViIn19fQ=="),
DOG("9655594c-5b1c-48a5-8e12-ffd7e0c735f2", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDk1MTgzY2E0Y2RkMjk2MjhmZTZjNzIyZjc3OTA4N2I4M2MyMWJhOTdmNDIyNWU0YWQ5YjNlNjE4ZWNjZDMwIn19fQ=="),
HORSE("c6abc94e-a5ff-45fe-a0d7-4e479f290a6f", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDJlYjk2N2FiOTRmZGQ0MWE2MzI1ZjEyNzdkNmRjMDE5MjI2ZTVjZjM0OTc3ZWVlNjk1OTdmYWZjZjVlIn19fQ=="),
TURTLE("ef56c7a3-a5e7-4a7f-9786-a4b6273a591d", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTJlNTQ4NDA4YWI3NWQ3ZGY4ZTZkNWQyNDQ2ZDkwYjZlYzYyYWE0ZjdmZWI3OTMwZDFlZTcxZWVmZGRmNjE4OSJ9fX0="),
OCELOT("664dd492-3fcd-443b-9e61-4c7ebd9e4e10", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTY1N2NkNWMyOTg5ZmY5NzU3MGZlYzRkZGNkYzY5MjZhNjhhMzM5MzI1MGMxYmUxZjBiMTE0YTFkYjEifX19"),
SHEEP("fa234925-9dbe-4b8f-a544-7c70fb6b6ac5", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjMxZjljY2M2YjNlMzJlY2YxM2I4YTExYWMyOWNkMzNkMThjOTVmYzczZGI4YTY2YzVkNjU3Y2NiOGJlNzAifX19"),
COW("97ddf3b3-9dbe-4a3b-8a0f-1b19ddeac0bd", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWQ2YzZlZGE5NDJmN2Y1ZjcxYzMxNjFjNzMwNmY0YWVkMzA3ZDgyODk1ZjlkMmIwN2FiNDUyNTcxOGVkYzUifX19"),
CHICKEN("7d3a8ace-e045-4eba-ab71-71dbf525daf1", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTYzODQ2OWE1OTljZWVmNzIwNzUzNzYwMzI0OGE5YWIxMWZmNTkxZmQzNzhiZWE0NzM1YjM0NmE3ZmFlODkzIn19fQ=="),
PIG("e1e1c2e4-1ed2-473d-bde2-3ec718535399", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjIxNjY4ZWY3Y2I3OWRkOWMyMmNlM2QxZjNmNGNiNmUyNTU5ODkzYjZkZjRhNDY5NTE0ZTY2N2MxNmFhNCJ9fX0="),
SQUID("f95d9504-ea2b-4b89-b2d0-d400654a7010", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMDE0MzNiZTI0MjM2NmFmMTI2ZGE0MzRiODczNWRmMWViNWIzY2IyY2VkZTM5MTQ1OTc0ZTljNDgzNjA3YmFjIn19fQ=="),
MUSHROOM_COW("e206ac29-ae69-475b-909a-fb523d894336", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDBiYzYxYjk3NTdhN2I4M2UwM2NkMjUwN2EyMTU3OTEzYzJjZjAxNmU3YzA5NmE0ZDZjZjFmZTFiOGRiIn19fQ=="),
ELDER_GUARDIAN("f2e933a7-614f-44e0-bf18-289b102104ab", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWM3OTc0ODJhMTRiZmNiODc3MjU3Y2IyY2ZmMWI2ZTZhOGI4NDEzMzM2ZmZiNGMyOWE2MTM5Mjc4YjQzNmIifX19"),
STRAY("644c9bad-958b-43ce-9d2f-199d85be607c", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzhkZGY3NmU1NTVkZDVjNGFhOGEwYTVmYzU4NDUyMGNkNjNkNDg5YzI1M2RlOTY5ZjdmMjJmODVhOWEyZDU2In19fQ=="),
HUSK("2e387bc6-774b-4fda-ba22-eb54a26dfd9e", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzc3MDY4MWQxYTI1NWZiNGY3NTQ3OTNhYTA1NWIyMjA0NDFjZGFiOWUxMTQxZGZhNTIzN2I0OTkzMWQ5YjkxYyJ9fX0="),
SKELETON_HORSE("bcbce5bf-86c4-4e62-9fc5-0cc90de94b6d", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDdlZmZjZTM1MTMyYzg2ZmY3MmJjYWU3N2RmYmIxZDIyNTg3ZTk0ZGYzY2JjMjU3MGVkMTdjZjg5NzNhIn19fQ=="),
ZOMBIE_HORSE("506ced1a-dac8-4d84-b341-645fbb297335", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q2YjllZjhkZDEwYmE2NDE0MjJiNDQ5ZWQxNWFkYzI5MmQ3M2Y1NzI5ODRkNDdlMjhhMjI2YWE2ZWRkODcifX19"),
DONKEY("3da7917b-cb95-40b3-a516-9befa4f4d71d", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjEyNTJjMjI1MGM0NjhkOWZkZTUzODY3Nzg1NWJjOWYyODQzM2RmNjkyNDdkNzEzODY4NzgxYjgyZDE0YjU1In19fQ=="),
MULE("fac6815e-02d5-4776-a5d6-f6d6535b7831", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzY5Y2E0YzI5NTZhNTY3Yzk2ZWUwNGM1MzE0OWYxODY0NjIxODM5M2JjN2IyMWVkNDVmZGFhMTNiZWJjZGFkIn19fQ=="),
EVOKER("36ee7e5b-c092-48ad-9673-2a73b0a44b4f", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTAwZDNmZmYxNmMyZGNhNTliOWM1OGYwOTY1MjVjODY5NzExNjZkYmFlMTMzYjFiMDUwZTVlZTcxNjQ0MyJ9fX0="),
VEX("f83bcfc1-0213-4957-888e-d3e2fae71203", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWU3MzMwYzdkNWNkOGEwYTU1YWI5ZTk1MzIxNTM1YWM3YWUzMGZlODM3YzM3ZWE5ZTUzYmVhN2JhMmRlODZiIn19fQ=="),
VINDICATOR("5f958e1c-91ea-42d3-9d26-09e5925f2d9c", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2RhNTg1ZWJkZGNjNDhmMzA3YmU2YTgzOTE2Zjg3OGVkNGEwMTRlYzNkNGYyODZhMmNmZDk1MzI4MTk2OSJ9fX0="),
ILLUSIONER("ccb79aa9-1764-4e5b-8ff3-e7be661ac7e2", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjYxNWUxMjQ1ZDBkODJkODFkZmEzNzUzMDYzZDhhYWQwZmE2NjU3NTk5ODcxY2Y0YzY5YmFiNzNjNjk5MDU1In19fQ=="),
PIG_ZOMBIE("6540c046-d6ea-4aff-9766-32a54ebe6958", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzRlOWM2ZTk4NTgyZmZkOGZmOGZlYjMzMjJjZDE4NDljNDNmYjE2YjE1OGFiYjExY2E3YjQyZWRhNzc0M2ViIn19fQ=="),
SILVERFISH("30a4cd5c-5754-4db8-8960-18022a74627d", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGE5MWRhYjgzOTFhZjVmZGE1NGFjZDJjMGIxOGZiZDgxOWI4NjVlMWE4ZjFkNjIzODEzZmE3NjFlOTI0NTQwIn19fQ=="),
BAT("cfdaf903-18cf-4a92-acf2-efa8626cf0b2", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWU5OWRlZWY5MTlkYjY2YWMyYmQyOGQ2MzAyNzU2Y2NkNTdjN2Y4YjEyYjlkY2E4ZjQxYzNlMGEwNGFjMWNjIn19fQ=="),
WITCH("7f92b3d6-5ee0-4ab6-afae-2206b9514a63", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjBlMTNkMTg0NzRmYzk0ZWQ1NWFlYjcwNjk1NjZlNDY4N2Q3NzNkYWMxNmY0YzNmODcyMmZjOTViZjlmMmRmYSJ9fX0="),
ENDERMITE("33c425bb-a294-4e01-9b5b-a8ad652bb5cf", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODRhYWZmYTRjMDllMmVhZmI4NWQzNTIyMTIyZGIwYWE0NTg3NGJlYTRlM2Y1ZTc1NjZiNGQxNjZjN2RmOCJ9fX0="),
WOLF("4aabc2be-340a-46ad-a42b-0c348344750a", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdhZGU0OWY1MDEzMTExNTExZGM1MWJhYjc2OWMxYWQ2OTUzMTlhNWQzNTViMzZhZTkyMzRlYTlkMWZmOGUifX19"),
SNOWMAN("d71e165b-b49d-4180-9ccf-8ad3084df1dc", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTdlOTgzMWRhZjY4MWY4YzRjNDc3NWNiNDY1M2MzNGJlMjg5OGY4N2VmZDNiNTk4ZDU1NTUxOGYyZmFjNiJ9fX0="),
IRON_GOLEM("7cb6e9a5-994f-40d5-9bfc-4ba5d796d21e", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODkwOTFkNzllYTBmNTllZjdlZjk0ZDdiYmE2ZTVmMTdmMmY3ZDQ1NzJjNDRmOTBmNzZjNDgxOWE3MTQifX19"),
RABBIT("2186bdc6-55b1-4b44-8a46-3c8a11d40f3d", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2QxMTY5YjI2OTRhNmFiYTgyNjM2MDk5MjM2NWJjZGE1YTEwYzg5YTNhYTJiNDhjNDM4NTMxZGQ4Njg1YzNhNyJ9fX0="),
POLAR_BEAR("87324464-1700-468f-8333-e7779ec8c21e", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDQ2ZDIzZjA0ODQ2MzY5ZmEyYTM3MDJjMTBmNzU5MTAxYWY3YmZlODQxOTk2NjQyOTUzM2NkODFhMTFkMmIifX19"),
LLAMA("75fb08e5-2419-46fa-bf09-57362138f234", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzJiMWVjZmY3N2ZmZTNiNTAzYzMwYTU0OGViMjNhMWEwOGZhMjZmZDY3Y2RmZjM4OTg1NWQ3NDkyMTM2OCJ9fX0="),
PARROT("da0cac14-3763-45df-b884-c99a567882ac", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTZkZTFlYjllMzI1ZTYyZjI4ZjJjMTgzZDM5YTY4MzExMzY0NDYzNjU3MjY0Njc1YThiNDYxY2QyOGM5In19fQ=="),
VILLAGER("b3ed4a1b-dfff-464c-87c0-c8029e1de47b", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzZhYjYxYWNlMTM2MDE3YTg3YjFiODFiMTQ1ZWJjNjNlMmU2ZGE5ZDM2NGM4MTE5NGIzM2VlODY2ZmU0ZCJ9fX0="),
PHANTOM("9290add8-c291-4a5a-8f8a-594f165406a3", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2U5NTE1M2VjMjMyODRiMjgzZjAwZDE5ZDI5NzU2ZjI0NDMxM2EwNjFiNzBhYzAzYjk3ZDIzNmVlNTdiZDk4MiJ9fX0="),
COD("d6d4c744-06b4-4a8a-bc7a-bdb0770bb1cf", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MmQ3ZGQ2YWFkZjM1Zjg2ZGEyN2ZiNjNkYTRlZGRhMjExZGY5NmQyODI5ZjY5MTQ2MmE0ZmIxY2FiMCJ9fX0="),
SALMON("0354c430-3979-4b6e-8e65-a99eb3ea8818", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGFlYjIxYTI1ZTQ2ODA2Y2U4NTM3ZmJkNjY2ODI4MWNmMTc2Y2VhZmU5NWFmOTBlOTRhNWZkODQ5MjQ4NzgifX19"),
PUFFERFISH("258e3114-368c-48a1-85fd-be580912f0df", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTcxNTI4NzZiYzNhOTZkZDJhMjI5OTI0NWVkYjNiZWVmNjQ3YzhhNTZhYzg4NTNhNjg3YzNlN2I1ZDhiYiJ9fX0="),
TROPICAL_FISH("d93c1bf6-616f-401a-af6e-f9b9803a0024", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTc5ZTQ4ZDgxNGFhM2JjOTg0ZThhNmZkNGZiMTcwYmEwYmI0ODkzZjRiYmViZGU1ZmRmM2Y4Zjg3MWNiMjkyZiJ9fX0="),
DROWNED("2f169660-61be-46bd-acb5-1abef9fe5731", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzNmN2NjZjYxZGJjM2Y5ZmU5YTYzMzNjZGUwYzBlMTQzOTllYjJlZWE3MWQzNGNmMjIzYjNhY2UyMjA1MSJ9fX0="),
DOLPHIN("8b7ccd6d-36de-47e0-8d5a-6f6799c6feb8", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGU5Njg4Yjk1MGQ4ODBiNTViN2FhMmNmY2Q3NmU1YTBmYTk0YWFjNmQxNmY3OGU4MzNmNzQ0M2VhMjlmZWQzIn19fQ==");
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* User UUID that has given skin.
*/
private String uuid;
/**
* Base64 Encoded link to Minecraft texture.
*/
private String textureValue;
/**
* Skull owner.
*/
private Object skullOwner;
/**
* This map allows to access all enum values via their string.
*/
private final static Map<String, HeadLib> BY_NAME = new HashMap<>();
// ---------------------------------------------------------------------
// Section: Constructor
// ---------------------------------------------------------------------
/**
* This inits new enum value by given UUID and textureValue that is encoded in Base64.
* @param uuid User UUID String which skin must be loaded.
* @param textureValue Texture link encoded in Base64.
*/
HeadLib(String uuid, String textureValue)
{
this.uuid = uuid;
this.textureValue = textureValue;
}
// ---------------------------------------------------------------------
// Section: Methods that returns ItemStacks
// ---------------------------------------------------------------------
/**
* Returns an ItemStack of the size 1 of the custom head.
*
* @return an ItemStack of the custom head.
*/
public ItemStack toItemStack()
{
return this.toItemStack(1);
}
/**
* Returns an ItemStack of the custom head.
*
* @param amount the amount of items in the stack
* @return an ItemStack of the custom head.
*/
public ItemStack toItemStack(int amount)
{
return this.toItemStack(amount, null);
}
/**
* Returns an ItemStack of the size 1 of the custom head.
*
* @param displayName the name to display. Supports "&amp;" color codes
* @param loreLines optional lore lines. Supports "&amp;" color codes
* @return an ItemStack of the custom head.
*/
public ItemStack toItemStack(String displayName, String... loreLines)
{
return this.toItemStack(1, displayName, loreLines);
}
/**
* Returns an ItemStack of the custom head.
*
* @param amount the amount of items in the stack
* @param displayName the name to display. Supports "&amp;" color codes
* @param loreLines optional lore lines. Supports "&amp;" color codes
* @return an ItemStack of the custom head.
*/
public ItemStack toItemStack(int amount, String displayName, String... loreLines)
{
ItemStack item = new ItemStack(Material.PLAYER_HEAD, amount);
if (displayName != null)
{
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(ChatColor.translateAlternateColorCodes('&', displayName));
if (loreLines.length != 0)
{
List<String> loreCC = new ArrayList<>();
Arrays.stream(loreLines).forEach(l -> loreCC.add(ChatColor.translateAlternateColorCodes('&', l)));
meta.setLore(loreCC);
}
item.setItemMeta(meta);
}
return this.setSkullOwner(item, this.getSkullOwner());
}
// ---------------------------------------------------------------------
// Section: Private inner methods
// ---------------------------------------------------------------------
/**
* This method returns SkullOwner or create new one if it is not created yet.
* SkullOwner is NBTTagCompound object that contains information about player_head skin.
* @return skullOwner object.
*/
private Object getSkullOwner()
{
if (this.skullOwner == null)
{
this.skullOwner = this.createOwnerCompound(this.uuid, this.textureValue);
}
return this.skullOwner;
}
/**
* This method creates new NBTTagCompound object that contains UUID and texture link.
* @param id - UUID of user.
* @param textureValue - Encoded texture string.
* @return NBTTagCompound object that contains all necessary information about player_head skin.
*/
private NBTTagCompound createOwnerCompound(String id, String textureValue)
{
NBTTagCompound skullOwner = new NBTTagCompound();
skullOwner.setString("Id", id);
NBTTagCompound properties = new NBTTagCompound();
NBTTagList textures = new NBTTagList();
NBTTagCompound value = new NBTTagCompound();
value.setString("Value", textureValue);
textures.add(value);
properties.set("textures", textures);
skullOwner.set("Properties", properties);
return skullOwner;
}
/**
* This method adds SkullOwner tag to given item.
* @param item Item whom SkullOwner tag must be added.
* @param compound NBTTagCompound object that contains UUID and texture link.
* @return new copy of given item with SkullOwner tag.
*/
private ItemStack setSkullOwner(ItemStack item, Object compound)
{
net.minecraft.server.v1_13_R2.ItemStack nmsStack = CraftItemStack.asNMSCopy(item);
nmsStack.getOrCreateTag().set("SkullOwner", (NBTBase) compound);
return CraftItemStack.asBukkitCopy(nmsStack);
}
// ---------------------------------------------------------------------
// Section: Other methods
// ---------------------------------------------------------------------
/**
* This method returns HeadLib enum object with given name. If enum value with given name does not exist,
* then return null.
* @param name Name of object that must be returned.
* @return HeadLib with given name or null.
*/
public static HeadLib getHead(String name)
{
return BY_NAME.get(name.toUpperCase());
}
//
// This static call populates all existing enum values into static map.
//
static
{
for (HeadLib head : values())
{
BY_NAME.put(head.name(), head);
}
}
}

View File

@ -1,6 +1,6 @@
package world.bentobox.challenges;
package world.bentobox.challenges.utils;
import world.bentobox.challenges.database.object.ChallengeLevels;
import world.bentobox.challenges.database.object.ChallengeLevel;
/**
* Level status class
@ -8,8 +8,8 @@ import world.bentobox.challenges.database.object.ChallengeLevels;
*
*/
public class LevelStatus {
private final ChallengeLevels level;
private final ChallengeLevels previousLevel;
private final ChallengeLevel level;
private final ChallengeLevel previousLevel;
private final int numberOfChallengesStillToDo;
private final boolean complete;
private final boolean isUnlocked;
@ -21,7 +21,7 @@ public class LevelStatus {
* @param complete - whether complete or not
* @param isUnlocked
*/
public LevelStatus(ChallengeLevels level, ChallengeLevels previousLevel, int numberOfChallengesStillToDo, boolean complete, boolean isUnlocked) {
public LevelStatus(ChallengeLevel level, ChallengeLevel previousLevel, int numberOfChallengesStillToDo, boolean complete, boolean isUnlocked) {
super();
this.level = level;
this.previousLevel = previousLevel;
@ -32,7 +32,7 @@ public class LevelStatus {
/**
* @return the level
*/
public ChallengeLevels getLevel() {
public ChallengeLevel getLevel() {
return level;
}
/**
@ -44,7 +44,7 @@ public class LevelStatus {
/**
* @return the previousLevel
*/
public ChallengeLevels getPreviousLevel() {
public ChallengeLevel getPreviousLevel() {
return previousLevel;
}
/**

View File

@ -4,18 +4,30 @@ version: ${version}
authors: tastybento
softdepend: AcidIsland, BSkyBlock, Level
softdepend: AcidIsland, BSkyBlock, CaveBlock, SkyGrid, Level
permissions:
bskyblock.challenges:
description: Let the player use the /challenges command
description: Let the player use the '/island challenges' command
default: true
bskyblock.admin.challenges:
description: Access challenge admin commands
default: op
acidisland.challenges:
description: Let the player use the /challenges command
description: Let the player use the '/ai challenges' command
default: true
acidisland.admin.challenges:
description: Access challenge admin commands
default: op
caveblock.challenges:
description: Let the player use the '/cave challenges' command
default: true
caveblock.admin.challenges:
description: Access challenge admin commands
default: op
skygrid.challenges:
description: Let the player use the '/skygrid challenges' command
default: true
skygrid.admin.challenges:
description: Access challenge admin commands
default: op

View File

@ -1,16 +1,68 @@
# Challenges Config
# Challenges Configuration ${project.version}
# This config file is dynamic and saved when the server is shutdown.
# 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.
#
#
# Reset Challenges - if this is true, player's challenges will reset when they
# reset an island or if they are kicked or leave a team. Prevents exploiting the
# challenges by doing them repeatedly.
resetchallenges: true
reset-challenges: true
#
# Broadcast 1st time challenge completion messages to all players.
# Change to false if the spam becomes too much.
broadcastmessages: true
# Remove non-repeatable challenges from the challenge GUI when complete
removecompleteonetimechallenges: false
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
addcompletedglow: true
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.
# To disable addon it is necessary to write its name in new line that starts with -. Example:
# disabled-gamemodes:
# - BSkyBlock
disabled-gamemodes: []
#
uniqueId: config
#
configVersion: v1.1

View File

@ -6,98 +6,303 @@
### Credits ###
# Tastybento: maintainer
challenges:
admin:
challenge-created: "[challenge] created!"
complete:
description: "Mark challenge complete"
parameters: "<player> <unique challenge name>"
unknown-challenge: "&cUnknown challenge"
create:
description: "&6Collect:"
description-item-color: "&B"
inventory:
description: "create an inventory challenge"
parameters: "[challenge name]"
surrounding:
description: "create a surrounding challenge"
hit-things: "Hit things to add them to the list of things required. Right click when done."
parameters: "[challenge name]"
description: "challenges admin"
error:
no-name: "You must include a challenge name"
gui-title: "&aChallenges Admin"
import:
description: "import challenges from challenges.yml"
imported: "Imported '[challenge]'"
levels: "Importing levels: [levels]"
no-file: "&cCould not find challenges.yml file to import!"
no-levels: "Warning: No levels defined in challenges.yml"
no-load: "&cError: Could not load challenges.yml. [message]"
number: "Imported [number] challenges"
overwriting: "Overwriting '[challenge]'"
parameters: "[overwrite]"
skipping: "'[challenge]' already exists - skipping"
parameters: ""
reload:
description: "reload challenges from the database"
parameters: ""
reset:
description: "Reset challenge to 0 times / incomplete"
parameters: "<player> <unique challenge name>"
seticon:
description: "sets the challenge icon to inhand item"
error:
no-such-challenge: "&cNo such challenge name"
parameters: "[challenge name]"
you-added: "You added one [thing] to the challenge"
challenge:
format: "[description]"
complete: "&BComplete"
completechallenge:
challange-completed: "Challenge: [challengename] has been completed for [name]"
completed-times: "Completed [donetimes] out of [maxtimes]"
description: "Open the challenges menu"
error:
could-not-save: "&cCould not save the challenge!"
island-level: "&cYour island must be level [number] to complete this challenge!"
items-not-there: "&cAll required items must be close to you on your island!"
no-items-clicked: "&cYou did not click on anything. Cancelling."
not-close-enough: "&cYou must be standing within [number] blocks of all required items."
not-enough-items: "&cYou do not have enough [items] to complete this challenge!"
not-on-island: "&cYou must be on your island to do that!"
reward-problem: "&cThere was a problem giving your reward. Ask Admin to check log!"
you-still-need: "&cYou still need [amount] x [item]"
exp-reward: "&6Exp reward: [reward]"
first-time-rewards: "&6First time reward(s)"
gui-title: "&aChallenges"
help:
command: "/challenges: &fshow challenges"
config-reloaded: "Configuration reloaded from file."
reset-all-challenges: "resets all of the player's challenges"
reset-challenge: "marks a challenge as incomplete"
reset-challenge-for-all: "globally resets a challenge for every player with an optional repetition"
incomplete: Incomplete
item-take-warning: "&cAll required items are|&ctaken when you complete|&cthis challenge!"
items-closeby: "&cAll required items|&cmust be close to you|&con your island!"
level: "&FLevel: [level]"
max-reached: "Max reached [donetimes] out of [maxtimes]"
money-reward: "&6Money reward: $[reward]"
name: "Challenge Name"
name-has-completed: "[name] has completed the [challenge] challenge!"
navigation: "Click to see [level] challenges!"
not-repeatable: "This challenge is not repeatable!"
parameters: "[Level]"
repeat-rewards: "&6Repeat reward(s)"
repeatable: "This challenge can be repeated [maxtimes] times"
resetallchallenges:
success: "[name] has had all challenges reset."
resetchallenge:
challenge-reset: "Challenge: [challengename] has been reset for [name]"
error-challenge-does-not-exist: "Challenge doesn't exist or isn't yet completed"
rewards: "&FReward(s)"
to-complete: "Complete [challengesToDo] more [thisLevel] challenges to unlock this level!"
you-completed: "You completed the [challenge] challenge!"
you-repeated: "You repeated the [challenge] challenge!"
not-enough-money: "It is necessary to have [money] on your account to complete the challenge."
not-enough-exp: "It is necessary to have [xp] EXP to complete challenge."
challenges:
commands:
admin:
main:
parameters: ''
description: 'Main admin command. Opens GUI.'
complete:
description: 'Mark challenge complete'
parameters: '<player> <unique challenge name>'
create:
description: 'Opens GUI that allows to create challenge.'
parameters: '<unique challenge name>'
surrounding:
description: 'Create a surrounding challenge.'
parameters: '<challenge name>'
import:
description: 'Import challenges from challenges.yml'
parameters: '<overwrite>'
reload:
description: 'Reload challenges from the database'
parameters: ''
reset:
description: 'Reset challenge to 0 times / incomplete'
parameters: '<player> <unique challenge name>'
show:
description: 'This method prints in chat all challenges that exist in world.'
parameters: ''
user:
description: 'This method opens Challenges GUI.'
parameters: ''
gui:
title:
admin:
gui-title: '&aChallenges Admin'
edit-challenge-title: '&aEdit Challenge'
edit-level-title: '&aEdit Level'
settings-title: '&aEdit Settings'
choose-challenge-title: '&aChoose Challenge'
choose-level-title: '&aChoose Level'
choose-user-title: '&aChoose Player'
manage-blocks: '&aManage Blocks'
manage-entities: '&aManage Entities'
confirm-title: '&aConfirmation'
manage-items: '&aManage Items'
manage-numbers: '&aNumber Pad'
select-block: '&aSelect Block'
select-challenge: '&aSelect Challenge'
select-entity: '&aSelect Entity'
toggle-environment: '&aToggle Environment'
edit-text-fields: '&aEdit Text Fields'
challenges: '&aChallenges'
buttons:
admin:
complete: 'Complete user challenge'
reset: 'Reset user challenge'
create-challenge: 'Add new challenge'
create-level: 'Add new level'
edit-challenge: 'Edit challenge'
edit-level: 'Edit level'
delete-challenge: 'Remove challenge'
delete-level: 'Remove level'
import: 'Import ASkyblock Challenges'
backward: 'Import 0.3.0 Challenges'
settings: 'Edit Settings'
properties: 'Properties'
requirements: 'Requirements'
rewards: 'Rewards'
challenges: 'Challenges'
type: 'Challenge Type'
deployment: 'Deployment'
icon: 'Icon'
description: 'Description'
order: 'Order'
environment: 'Environment'
remove-on-complete: 'Remove after completion'
name: 'Friendly Name'
required-entities: 'Required Entities'
remove-entities: 'Remove Entities'
required-blocks: 'Required Blocks'
remove-blocks: 'Remove Blocks'
search-radius: 'Search Radius'
required-permissions: 'Required Permissions'
required-items: 'Required Items'
remove-items: 'Remove Items'
required-experience: 'Required experience'
remove-experience: 'Remove experience'
required-level: 'Required island level'
required-money: 'Required money'
remove-money: 'Remove money'
reward-text: 'Reward message'
reward-items: 'Reward items'
reward-experience: 'Reward experience'
reward-money: 'Reward money'
reward-commands: 'Reward commands'
repeatable: 'Repeatable'
repeat-count: 'Max Times'
repeat-reward-text: 'Repeat reward message'
repeat-reward-items: 'Repeat reward items'
repeat-reward-experience: 'Repeat reward experience'
repeat-reward-money: 'Repeat reward money'
repeat-reward-commands: 'Repeat reward commands'
waiver-amount: 'Waiver Amount'
add-challenge: 'Add Challenge'
remove-challenge: 'Remove Challenge'
reset-on-new: 'Reset On New Island'
broadcast: 'Broadcast Completion'
remove-completed: 'Remove after complete'
glow: 'Glow when completed'
free-at-top: 'Free challenges first'
line-length: 'Lore line length'
toggle-user-list: 'User List'
remove-selected: 'Remove Selected'
add: 'Add'
show-eggs: 'Switch View mode'
accept: 'Accept'
decline: 'Decline'
save: 'Save'
cancel: 'Cancel'
input: 'Input'
value: 'Value'
set: '='
increase: '+'
reduce: '-'
multiply: '*'
clear: 'Clear'
remove-empty: 'Remove empty'
number: '[number]'
level-lore: 'Level Description'
challenge-lore: 'Challenge Description'
next: 'Next'
previous: 'Previous'
return: 'Return'
descriptions:
admin:
save: 'Save and return to previous GUI.'
cancel: 'Return to previous GUI. Changes will not be saved.'
input: 'Open text field input.'
set: 'Set operation. Clicking on numbers will change value to selected number.'
increase: 'Increase operation. Clicking on numbers will increase value by selected number.'
reduce: 'Reduce operation. Clicking on numbers will reduce value by selected number.'
multiply: 'Multiply operation. Clicking on numbers will multiply value by selected number.'
import: 'Allows to import ASkyblock Challenges.|On right click it enables/disables overwrite mode.'
complete: 'Allows to complete challenges for any user.|User will not get reward for completion.'
reset: 'Allows to reset completed user challenges.|Right click enables/disables Reset all functionality.'
create-challenge: 'Allows to add new Challenge.|By default it will be in free challenges list.'
create-level: 'Allows to add new Level.'
edit-challenge: 'Allows to edit any Challenge settings.'
edit-level: 'Allows to edit any Level settings.'
delete-challenge: 'Allows remove any Challenge.'
delete-level: 'Allows remove any Level.'
backward: 'Allows to import challenges from 0.3.0 and below addon version.'
settings: 'Allows to change addon settings.'
properties: 'Allows to change general properties'
requirements: 'Allows to manage requirements'
rewards: 'Allows to manage rewards'
challenges: 'Allows to manage level challenges (add / remove).'
deployment: 'Allows users to complete (view) 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.'
description: 'Allows to edit description.'
order: 'Allows to change order number.'
environment: 'Allows to change environment where challenge operates.'
type: 'Allows change challenge type. Each type has their own requirements.'
remove-on-complete: 'Allows to remove challenge from player GUI after it is completed.'
name-challenge: 'Allows to change challenge display name.'
name-level: 'Allows to change level display name.'
required-entities: 'Allows to add/edit/remove required entities.|Entities:|'
remove-entities: 'Allows to remove (kill) entities on challenge completion.'
required-blocks: 'Allows to add/edit/remove required blocks.|Blocks:|'
remove-blocks: 'Allows to remove (replace with air) blocks on challenge completion.'
search-radius: 'Radius around player location where required entities and blocks will be searched.'
required-permissions: 'Required permissions for player to be able to complete challenge.|Permission:'
required-items: 'Required items in player"s inventory.|Items:'
remove-items: 'Allows to remove items from player inventory after challenge completion.'
required-experience: 'Allows to define required experience for user to complete challenge.'
remove-experience: 'Allows to remove remove required experience.'
required-level: 'Allows to define required island level for this challenge.|&cRequires Level addon.'
required-money: 'Allows to define required money in player"s account.|&cRequires Vault and Economy plugin.'
remove-money: 'Allows to remove required money from player"s account.|&cRequires Vault and Economy plugin.'
reward-text: 'Allows to change message that will be sent to player after challenges completion.'
reward-items: 'Allows to change first time completion reward items.|Items:'
reward-experience: 'Allows to change first time completion reward Experience.'
reward-money: 'Allows to change first time completion reward Money.|&cRequires Vault and Economy plugin.'
reward-commands: 'Allows to define reward commands that will be called after first time completion.|***Adding "[SELF]" at the start means that command will be run by player, f.e. "/kill"|***String "[player]" will be replaced with player name, f.e. "/kill [player]" will be transformed to "/kill BONNe1704"|Commands:'
repeatable: 'Allows to define if challenge is repeatable or not.'
repeat-count: 'Allows to define maximal repeat count. If value is set 0 or smaller, then there are no limitations.'
repeat-reward-text: 'Allows to change message that will be sent to player after challenge repeated completion.'
repeat-reward-items: 'Allows to change repeated completion reward items.|Items:'
repeat-reward-experience: 'Allows to change repeated completion reward Experience.'
repeat-reward-money: 'Allows to change repeated completion reward Money.|&cRequires Vault and Economy plugin.'
repeat-reward-commands: 'Allows to define reward commands that will be called after challenge repeated completion.|***Adding "[SELF]" at the start means that command will be run by player, f.e. "/kill"|***String "[player]" will be replaced with player name, f.e. "/kill [player]" will be transformed to "/kill BONNe1704"|Commands:'
waiver-amount: 'Allows to set how many challenges can be left undone to unlock next level.'
reward-text-level: 'Allows to change message that will be sent to player after completing all challenges in level.'
add-challenge: 'Allows to add existing challenge to current level.'
remove-challenge: 'Allows remove any challenge from current level.'
reset-on-new: 'Enables/Disables option, that resets all player challenges if player restarts island, leave island or was kicked out.'
broadcast: 'Enables/Disables broadcast to online players about first time challenge completion.'
remove-completed: 'Enables/Disables hiding challenges that are completed and cannot be repeated.'
glow: 'Enables/Disables glowing effect for completed challenges.'
free-at-top: 'Allows to change free challenges location. True mean that challenges will be first, otherwise they will be last.'
line-length: 'Allows to modify maximal line length in lore box. Will not affect stored objects.'
toggle-user-list: 'Switch to different player list.'
mode-online: 'Players which currently are online.'
mode-in-world: 'Players which is in GameMode world.'
mode-with-island: 'Players which has island in GameMode.'
selected: 'Selected'
remove-selected: 'Remove selected elements.|You can select elements with right mouse button.'
show-eggs: 'Switch entity view between Egg mode or Head mode.'
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.'
current-value: '|&6Current value: [value].'
enabled: 'Active'
disabled: 'Disabled'
type:
island: '- Island Type:| (allows to require blocks or mobs around player)'
inventory: '- Inventory Type:| (allows to require items in players inventory)'
other: '- Other Type:| (allows to require things from other plugins/addons)'
the-end: '- The End'
nether: '- Nether'
normal: '- Overworld'
entity: '- [entity] : [count]'
block: '- [block] : [count]'
permission: '- [permission]'
item: '- [count] x [item]'
item-meta: ' ([meta])'
item-enchant: ' - [enchant] [level]'
command: '- [command]'
level-unlocked: 'Click to see [level] challenges!'
level-locked: 'Complete [count] more [level] challenges to unlock this level!'
challenge-description:
level: '&FLevel: [level]'
completed: '&BCompleted'
completed-times-of: 'Completed [donetimes] out of [maxtimes]'
maxed-reached: 'Completed [donetimes] out of [maxtimes]'
completed-times: 'Completed [donetimes]'
warning-items-take: '&cAll required items are taken when you complete this challenge!'
objects-close-by: '&cAll required blocks and entities must be close to you on your island!'
warning-entities-kill: '&cAll required entities will be killed when you complete this challenge!'
warning-blocks-remove: '&cAll required blocks will be removed when you complete this challenge!'
not-repeatable: '&cThis challenge is not repeatable!'
experience-reward: '&6Exp reward: [value]'
money-reward: '&6Money reward: $[value]'
required-experience: '&6Required exp: [value]'
required-money: '&6Required money: $[value]'
required-island-level: '&6Required island level: [value]'
environment: 'Required Environments:'
reward-items: '&6Reward Items:'
reward-commands: '&6Reward Commands:'
required-items: 'Required Items:'
required-entities: 'Required Entities:'
required-blocks: 'Required Blocks:'
level-description:
completed: '&BCompleted'
completed-challenges-of: '&3You have completed [number] of [max] challenges in this level.'
waver-amount: '&6Can skip [value] challenges to unlock next level.'
experience-reward: '&6Exp reward: [value]'
money-reward: '&6Money reward: $[value]'
reward-items: '&6Reward Items:'
reward-commands: '&6Reward Commands:'
messages:
admin:
hit-things: 'Hit things to add them to the list of things required. Right click when done.'
you-added: 'You added one [thing] to the challenge'
challenge-created: '[challenge] created!'
you-completed-challenge: '&2You completed the [value] challenge!'
you-repeated-challenge: '&2You repeated the [value] challenge!'
you-completed-level: '&2You completed the [value] level!'
name-has-completed-challenge: '&5[name] has completed the [value] challenge!'
name-has-completed-level: '&5[name] has completed the [value] level!'
import-levels: 'Start importing Levels'
import-challenges: 'Start importing Challenges'
no-levels: 'Warning: No levels defined in challenges.yml'
import-number: 'Imported [number] challenges'
load-skipping: '"[value]" already exists - skipping'
load-overwriting: 'Overwriting "[value]"'
load-add: 'Adding new object: [value]'
errors:
no-name: '&cMissing challenge name'
unknown-challenge: '&cUnknown challenge'
unique-id: '&cUniqueID "[id]" is not valid.'
wrong-icon: '&cGiven material "[value]" is not valid and cannot be used as icon.'
not-valid-integer: '&cGiven integer "[value]" is not valid!|Value should be between [min] and [max].'
not-a-integer: '&cGiven value "[value]" is not integer!'
not-deployed: '&cChallenge is not deployed!'
not-on-island: '&cYou must be on your island to do that!'
challenge-level-not-available: '&cYou have not unlocked level to complete this challenge.'
not-repeatable: '&cThis challenge is not repeatable!'
wrong-environment: '&cYou are in wrong environment!'
not-enough-items: '&cYou do not have enough [items] to complete this challenge!'
not-close-enough: '&cYou must be standing within [number] blocks of all required items.'
you-still-need: '&cYou still need [amount] x [item]'
missing-addon: '&cCannot complete challenge. Required addon or plugin is missing.'
incorrect: '&cCannot complete challenge. Requirements are incorrect.'
not-enough-money: '&cIt is necessary to have [value] on your account to complete the challenge.'
not-enough-experience: '&cIt is necessary to have [value] EXP to complete challenge.'
island-level: '&cYour island must be level [number] to complete this challenge!'
import-no-file: '&cCould not find challenges.yml file to import!'
no-load: '&cError: Could not load challenges.yml. [message]'
load-error: '&cError: Cannot load [value].'
version: 5

View File

@ -35,8 +35,8 @@ import org.powermock.modules.junit4.PowerMockRunner;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import world.bentobox.challenges.database.object.Challenges;
import world.bentobox.challenges.database.object.Challenges.ChallengeType;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.database.object.Challenge.ChallengeType;
/**
* @author tastybento
@ -81,7 +81,7 @@ public class ChallengesAddonTest {
public void test() {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Challenges challenges = new Challenges();
Challenge challenges = new Challenge();
challenges.setChallengeType(ChallengeType.ISLAND);
Map<Material, Integer> map = new HashMap<>();
map.put(Material.DIRT, 5);

View File

@ -26,6 +26,7 @@ import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.ParseItem;
@RunWith(PowerMockRunner.class)
@Deprecated
public class ParseItemTest {
private static ChallengesAddon addon;