Address some code quality reports from SonarCloud.

Most of the errors are just sanity checks, as the most of null-pointers were already checked in other ways.
This commit is contained in:
BONNe 2021-12-01 11:30:02 +02:00
parent e7b84768aa
commit 7fbffbb6d2
38 changed files with 336 additions and 343 deletions

View File

@ -19,7 +19,7 @@ import world.bentobox.challenges.utils.Utils;
public class ChallengesGlobalPlayerCommand extends CompositeCommand
{
/**
* Constructor that inits command with given string.
* Constructor that init command with given string.
* @param addon Challenges Addon
* @param gameModeAddons List with GameModes where challenges addon operates.
*/

View File

@ -16,7 +16,7 @@ import world.bentobox.challenges.utils.Utils;
/**
* This command allows to complete challenges without a gui.
* This command allows completing challenges without a gui.
*/
public class CompleteChallengeCommand extends CompositeCommand
{

View File

@ -10,11 +10,11 @@ import world.bentobox.challenges.panel.admin.AdminPanel;
public class ChallengesAdminCommand extends CompositeCommand
{
/**
* Admin command for challenges
* Instantiates a new Challenges' admin command.
*
* @param parent
* @param addon the addon
* @param parent the parent
*/
public ChallengesAdminCommand(ChallengesAddon addon, CompositeCommand parent)
{

View File

@ -6,7 +6,6 @@ import java.util.List;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.panel.user.GameModePanel;
import world.bentobox.challenges.utils.Constants;
@ -19,7 +18,7 @@ import world.bentobox.challenges.utils.Utils;
public class ChallengesGlobalAdminCommand extends CompositeCommand
{
/**
* Constructor that inits command with given string.
* Constructor that init command with given string.
* @param addon Challenges Addon
* @param gameModeAddons List with GameModes where challenges addon operates.
*/

View File

@ -20,7 +20,7 @@ import world.bentobox.challenges.utils.Utils;
/**
* This command allows to complete challenges without a gui.
* This command allows completing challenges without a gui.
*/
public class CompleteCommand extends CompositeCommand
{
@ -99,24 +99,26 @@ public class CompleteCommand extends CompositeCommand
// Add world name back at the start
String challengeName = Utils.getGameMode(this.getWorld()) + "_" + args.get(1);
Challenge challenge = this.addon.getChallengesManager().getChallenge(challengeName);
User target = User.getInstance(targetUUID);
if (challenge != null)
if (challenge != null && target != null)
{
if (!this.addon.getChallengesManager().isChallengeComplete(targetUUID, this.getWorld(), challenge))
{
this.addon.getChallengesManager().setChallengeComplete(
targetUUID, this.getWorld(), challenge, user.getUniqueId());
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.completed",
Constants.PARAMETER_NAME, challenge.getFriendlyName(),
Constants.PARAMETER_PLAYER, User.getInstance(targetUUID).getName()));
Constants.PARAMETER_PLAYER, target.getName()));
}
else
{
this.addon.log("Challenge " + challenge.getFriendlyName() + " completed for player " +
User.getInstance(targetUUID).getName());
target.getName());
}
}
else
@ -166,23 +168,16 @@ public class CompleteCommand extends CompositeCommand
switch (size)
{
case 3:
case 3 ->
// Create suggestions with all challenges that is available for users.
returnList.addAll(Util.getOnlinePlayerList(user));
break;
case 4:
case 4 ->
// Create suggestions with all challenges that is available for users.
returnList.addAll(this.addon.getChallengesManager().getAllChallengesNames(this.getWorld()).stream().
map(challenge -> challenge.substring(Utils.getGameMode(this.getWorld()).length() + 1)).
collect(Collectors.toList()));
break;
default:
{
default ->
returnList.addAll(Collections.singletonList("help"));
break;
}
}
return Optional.of(Util.tabLimit(returnList, lastString));

View File

@ -9,27 +9,32 @@ import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon;
public class MigrateCommand extends CompositeCommand {
public class MigrateCommand extends CompositeCommand
{
/**
* Migrates challenges
* @param addon
* @param cmd
* Instantiates a new Migrate command command.
*
* @param addon the addon
* @param cmd the cmd
*/
public MigrateCommand(Addon addon, CompositeCommand cmd) {
public MigrateCommand(Addon addon, CompositeCommand cmd)
{
super(addon, cmd, "migrate");
}
@Override
public boolean execute(User user, String label, List<String> args) {
((ChallengesAddon)getAddon()).getChallengesManager().migrateDatabase(user, getWorld());
public boolean execute(User user, String label, List<String> args)
{
((ChallengesAddon) getAddon()).getChallengesManager().migrateDatabase(user, getWorld());
return true;
}
@Override
public void setup() {
public void setup()
{
this.setPermission("challenges.admin");
this.setParametersHelp("challenges.commands.admin.migrate.parameters");
this.setDescription("challenges.commands.admin.migrate.description");

View File

@ -11,13 +11,15 @@ import world.bentobox.challenges.utils.Utils;
/**
* This class allows to reload challenges addon.
* This class allows reloading challenges addon.
*/
public class ReloadChallenges extends CompositeCommand
{
/**
* Admin command to reloads challenges addon.
* @param parent
* Instantiates a new Reload challenges command.
*
* @param addon the addon
* @param parent the parent
*/
public ReloadChallenges(Addon addon, CompositeCommand parent)
{
@ -69,5 +71,8 @@ public class ReloadChallenges extends CompositeCommand
// ---------------------------------------------------------------------
private ChallengesManager manager;
/**
* Addon Manager instance.
*/
private final ChallengesManager manager;
}

View File

@ -20,7 +20,7 @@ import world.bentobox.challenges.utils.Utils;
/**
* This command allows to reset challenges without a gui.
* This command allows resetting challenges without a gui.
*/
public class ResetCommand extends CompositeCommand
{
@ -79,8 +79,9 @@ public class ResetCommand extends CompositeCommand
else if (!args.get(1).isEmpty())
{
UUID targetUUID = this.getPlayers().getUUID(args.get(0));
User target = User.getInstance(targetUUID);
if (targetUUID == null)
if (targetUUID == null || target == null)
{
if (user.isPlayer())
{
@ -104,12 +105,11 @@ public class ResetCommand extends CompositeCommand
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.reset-all",
Constants.PARAMETER_PLAYER, User.getInstance(targetUUID).getName()));
Constants.PARAMETER_PLAYER, target.getName()));
}
else
{
this.addon.log("All challenges for user " +
User.getInstance(targetUUID).getName() + " was reset!");
this.addon.log("All challenges for user " + target.getName() + " was reset!");
}
return true;
@ -129,12 +129,12 @@ public class ResetCommand extends CompositeCommand
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.reset",
Constants.PARAMETER_NAME, challenge.getFriendlyName(),
Constants.PARAMETER_PLAYER, User.getInstance(targetUUID).getName()));
Constants.PARAMETER_PLAYER, target.getName()));
}
else
{
this.addon.log("Challenge " + challenge.getFriendlyName() + " was reset for player " +
User.getInstance(targetUUID).getName());
target.getName());
}
}
else
@ -185,25 +185,18 @@ public class ResetCommand extends CompositeCommand
switch (size)
{
case 3:
case 3 ->
// Create suggestions with all challenges that is available for users.
returnList.addAll(Util.getOnlinePlayerList(user));
break;
case 4:
case 4 -> {
// Create suggestions with all challenges that is available for users.
returnList.addAll(this.addon.getChallengesManager().getAllChallengesNames(this.getWorld()).stream().
map(challenge -> challenge.substring(Utils.getGameMode(this.getWorld()).length() + 1)).
collect(Collectors.toList()));
returnList.add("all");
break;
default:
{
returnList.addAll(Collections.singletonList("help"));
break;
}
default ->
returnList.addAll(Collections.singletonList("help"));
}
return Optional.of(Util.tabLimit(returnList, lastString));
@ -217,5 +210,5 @@ public class ResetCommand extends CompositeCommand
/**
* Variable that holds challenge addon. Single casting.
*/
private ChallengesAddon addon;
private final ChallengesAddon addon;
}

View File

@ -7,27 +7,32 @@ import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon;
public class ShowChallenges extends CompositeCommand {
public class ShowChallenges extends CompositeCommand
{
/**
* Admin command to show challenges and manage them
* @param parent
* Instantiates a new Show challenges command.
*
* @param addon the addon
* @param parent the parent
*/
public ShowChallenges(Addon addon, CompositeCommand parent) {
public ShowChallenges(Addon addon, CompositeCommand parent)
{
super(addon, parent, "show");
}
@Override
public void setup() {
public void setup()
{
this.setPermission("admin.challenges");
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) {
public boolean execute(User user, String label, List<String> args)
{
if (user.isPlayer())
{
((ChallengesAddon) getAddon()).getChallengesManager().
@ -40,7 +45,5 @@ public class ShowChallenges extends CompositeCommand {
}
return true;
}
}

View File

@ -6,7 +6,6 @@ import java.util.stream.Collectors;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.NonNull;
@ -16,7 +15,6 @@ import com.google.gson.annotations.JsonAdapter;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.database.objects.DataObject;
import world.bentobox.bentobox.database.objects.Table;
import world.bentobox.challenges.database.object.adapters.EntityCompatibilityAdapter;
import world.bentobox.challenges.database.object.adapters.RequirementsAdapter;
import world.bentobox.challenges.database.object.adapters.TypeMigrationAdapter;
import world.bentobox.challenges.database.object.requirements.Requirements;
@ -838,7 +836,7 @@ public class Challenge implements DataObject
clone.setEnvironment(new HashSet<>(this.environment));
clone.setLevel(this.level);
clone.setRemoveWhenCompleted(this.removeWhenCompleted);
clone.setRequirements(this.requirements.clone());
clone.setRequirements(this.requirements.copy());
clone.setRewardText(this.rewardText);
clone.setRewardItems(
this.rewardItems.stream().

View File

@ -6,6 +6,7 @@ import java.util.stream.Collectors;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import com.google.gson.annotations.Expose;
@ -449,7 +450,7 @@ public class ChallengeLevel implements DataObject, Comparable<ChallengeLevel>
* {@inheritDoc}
*/
@Override
public int compareTo(ChallengeLevel o)
public int compareTo(@NotNull ChallengeLevel o)
{
if (this.equals(o))
{
@ -501,13 +502,11 @@ public class ChallengeLevel implements DataObject, Comparable<ChallengeLevel>
return true;
}
if (!(obj instanceof ChallengeLevel))
if (!(obj instanceof ChallengeLevel other))
{
return false;
}
ChallengeLevel other = (ChallengeLevel) obj;
if (uniqueId == null)
{
return other.uniqueId == null;
@ -542,8 +541,7 @@ public class ChallengeLevel implements DataObject, Comparable<ChallengeLevel>
* Clone method that returns clone of current challengeLevel.
* @return ChallengeLevel that is cloned from current object.
*/
@Override
public ChallengeLevel clone()
public ChallengeLevel copy()
{
ChallengeLevel clone = new ChallengeLevel();

View File

@ -65,7 +65,7 @@ public class ChallengesPlayerData implements DataObject
private Map<String, Integer> challengeStatus = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
/**
* Map of challenges completion time where key is challenges unique id and value is
* Map of challenges completion time when key is challenges unique id and value is
* timestamp when challenge was completed last time.
*/
@Expose
@ -353,13 +353,11 @@ public class ChallengesPlayerData implements DataObject
return true;
}
if (!(obj instanceof ChallengesPlayerData))
if (!(obj instanceof ChallengesPlayerData other))
{
return false;
}
ChallengesPlayerData other = (ChallengesPlayerData) obj;
if (uniqueId == null)
{
return other.uniqueId == null;

View File

@ -33,10 +33,7 @@ public class EntityCompatibilityAdapter implements
{
JsonObject jsonArray = new JsonObject();
src.forEach((entity, number) ->
{
jsonArray.addProperty(entity.name(), number);
});
src.forEach((entity, number) -> jsonArray.addProperty(entity.name(), number));
return jsonArray;
}
@ -46,7 +43,6 @@ public class EntityCompatibilityAdapter implements
* This method deserializes json object that stores Entity Name and amount as integer.
* @param json Json element that must be parsed.
* @return EnumMap that contains EntityType as key and Integer as value.
* @throws JsonParseException
*/
@Override
public Map<EntityType, Integer> deserialize(JsonElement json,

View File

@ -42,7 +42,6 @@ public class TypeMigrationAdapter implements JsonSerializer<Challenge.ChallengeT
return switch (primitive.getAsString())
{
case "ISLAND", "ISLAND_TYPE" -> Challenge.ChallengeType.ISLAND_TYPE;
case "INVENTORY", "INVENTORY_TYPE" -> Challenge.ChallengeType.INVENTORY_TYPE;
case "OTHER", "OTHER_TYPE" -> Challenge.ChallengeType.OTHER_TYPE;
case "STATISTIC", "STATISTIC_TYPE" -> Challenge.ChallengeType.STATISTIC_TYPE;

View File

@ -126,12 +126,12 @@ public class InventoryRequirements extends Requirements
/**
* Method Requirements#clone allows to clone Requirements object, to avoid changing content when it is necessary
* Method Requirements#copy allows copies Requirements object, to avoid changing content when it is necessary
* to use it.
* @return InventoryRequirements clone
* @return InventoryRequirements copy
*/
@Override
public Requirements clone()
public Requirements copy()
{
InventoryRequirements clone = new InventoryRequirements();
clone.setRequiredPermissions(new HashSet<>(this.getRequiredPermissions()));

View File

@ -165,12 +165,12 @@ public class IslandRequirements extends Requirements
/**
* Method Requirements#clone allows to clone Requirements object, to avoid changing content when it is necessary
* Method Requirements#copy allows copies Requirements object, to avoid changing content when it is necessary
* to use it.
* @return IslandRequirements clone
* @return IslandRequirements copy
*/
@Override
public Requirements clone()
public Requirements copy()
{
IslandRequirements clone = new IslandRequirements();
clone.setRequiredPermissions(new HashSet<>(this.getRequiredPermissions()));

View File

@ -147,12 +147,12 @@ public class OtherRequirements extends Requirements
/**
* Method Requirements#clone allows to clone Requirements object, to avoid changing content when it is necessary
* Method Requirements#copy allows copies Requirements object, to avoid changing content when it is necessary
* to use it.
* @return OtherRequirements clone
* @return OtherRequirements copy
*/
@Override
public Requirements clone()
public Requirements copy()
{
OtherRequirements clone = new OtherRequirements();
clone.setRequiredPermissions(new HashSet<>(this.getRequiredPermissions()));

View File

@ -70,12 +70,11 @@ public abstract class Requirements
/**
* Method Requirements#clone allows to clone Requirements object, to avoid changing content when it is necessary
* Method Requirements#copy allows to copy Requirements object, to avoid changing content when it is necessary
* to use it.
* @return Requirements clone
* @return Requirements copy
*/
@Override
public abstract Requirements clone();
public abstract Requirements copy();
// ---------------------------------------------------------------------

View File

@ -11,7 +11,6 @@ import com.google.gson.annotations.Expose;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.entity.EntityType;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
@ -27,11 +26,11 @@ public class StatisticRequirements extends Requirements
/**
* This method clones given statistic object.
* @return Clone of this object.
* This method copies given statistic object.
* @return Copy of this object.
*/
@Override
public Requirements clone()
public Requirements copy()
{
StatisticRequirements requirements = new StatisticRequirements();
requirements.setStatistic(this.statistic);
@ -96,7 +95,7 @@ public class StatisticRequirements extends Requirements
*
* @param statistic the statistic
*/
public void setStatistic(@NonNull Statistic statistic)
public void setStatistic(@Nullable Statistic statistic)
{
this.statistic = statistic;
}

View File

@ -101,5 +101,5 @@ public class ChallengeDataRequestHandler extends AddonRequestHandler
/**
* Variable stores challenges addon.
*/
private ChallengesAddon addon;
private final ChallengesAddon addon;
}

View File

@ -5,6 +5,7 @@ import java.util.Collections;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.World;
import world.bentobox.bentobox.api.addons.request.AddonRequestHandler;
import world.bentobox.challenges.ChallengesAddon;
@ -43,15 +44,21 @@ public class ChallengeListRequestHandler extends AddonRequestHandler
*/
if (metaData == null ||
metaData.isEmpty() ||
metaData.get("world-name") == null ||
!(metaData.get("world-name") instanceof String) ||
Bukkit.getWorld((String) metaData.get("world-name")) == null)
metaData.isEmpty() ||
metaData.get("world-name") == null ||
!(metaData.get("world-name") instanceof String))
{
return Collections.emptyList();
}
return this.addon.getChallengesManager().getAllChallengesNames(Bukkit.getWorld((String) metaData.get("world-name")));
World world = Bukkit.getWorld((String) metaData.get("world-name"));
if (world == null)
{
return Collections.emptyList();
}
return this.addon.getChallengesManager().getAllChallengesNames(world);
}
@ -63,5 +70,5 @@ public class ChallengeListRequestHandler extends AddonRequestHandler
/**
* Variable stores challenges addon.
*/
private ChallengesAddon addon;
private final ChallengesAddon addon;
}

View File

@ -50,24 +50,27 @@ public class CompletedChallengesRequestHandler extends AddonRequestHandler
*/
if (metaData == null ||
metaData.isEmpty() ||
metaData.get("world-name") == null ||
!(metaData.get("world-name") instanceof String) ||
metaData.get("player") == null ||
!(metaData.get("player") instanceof UUID) ||
Bukkit.getWorld((String) metaData.get("world-name")) == null)
metaData.isEmpty() ||
metaData.get("world-name") == null ||
!(metaData.get("world-name") instanceof String) ||
metaData.get("player") == null ||
!(metaData.get("player") instanceof UUID player))
{
return Collections.emptySet();
}
World world = Bukkit.getWorld((String) metaData.get("world-name"));
UUID player = (UUID) metaData.get("player");
if (world == null)
{
return Collections.emptySet();
}
ChallengesManager manager = this.addon.getChallengesManager();
return manager.getAllChallengesNames(world).stream().
filter(challenge -> manager.isChallengeComplete(player, world, challenge)).
collect(Collectors.toSet());
filter(challenge -> manager.isChallengeComplete(player, world, challenge)).
collect(Collectors.toSet());
}
@ -79,5 +82,5 @@ public class CompletedChallengesRequestHandler extends AddonRequestHandler
/**
* Variable stores challenges addon.
*/
private ChallengesAddon addon;
private final ChallengesAddon addon;
}

View File

@ -94,5 +94,5 @@ public class LevelDataRequestHandler extends AddonRequestHandler
/**
* Variable stores challenges addon.
*/
private ChallengesAddon addon;
private final ChallengesAddon addon;
}

View File

@ -5,6 +5,7 @@ import java.util.Collections;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.World;
import world.bentobox.bentobox.api.addons.request.AddonRequestHandler;
import world.bentobox.challenges.ChallengesAddon;
@ -44,16 +45,21 @@ public class LevelListRequestHandler extends AddonRequestHandler
*/
if (metaData == null ||
metaData.isEmpty() ||
metaData.get("world-name") == null ||
!(metaData.get("world-name") instanceof String) ||
Bukkit.getWorld((String) metaData.get("world-name")) == null)
metaData.isEmpty() ||
metaData.get("world-name") == null ||
!(metaData.get("world-name") instanceof String))
{
return Collections.emptyList();
}
return this.addon.getChallengesManager().getLevelNames(
Bukkit.getWorld((String) metaData.get("world-name")));
World world = Bukkit.getWorld((String) metaData.get("world-name"));
if (world == null)
{
return Collections.emptyList();
}
return this.addon.getChallengesManager().getLevelNames(world);
}
@ -65,5 +71,5 @@ public class LevelListRequestHandler extends AddonRequestHandler
/**
* Variable stores challenges addon.
*/
private ChallengesAddon addon;
private final ChallengesAddon addon;
}

View File

@ -50,5 +50,5 @@ public class SaveListener implements Listener
// ---------------------------------------------------------------------
private ChallengesAddon addon;
private final ChallengesAddon addon;
}

View File

@ -27,6 +27,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import lv.id.bonne.panelutils.PanelUtils;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
@ -661,14 +662,21 @@ public class ChallengesImportManager
*/
public void importDatabaseFile(User user, World world, String fileName)
{
World correctWorld = Util.getWorld(world);
if (correctWorld == null)
{
this.addon.logError("Given world is not part of BentoBox");
return;
}
ChallengesManager manager = this.addon.getChallengesManager();
// If exist any generator that is bound to current world, then do not load generators.
if (manager.hasAnyChallengeData(world.getName()))
{
this.addon.getPlugin().getIWM().getAddon(world).ifPresent(gameModeAddon -> {
manager.wipeDatabase(gameModeAddon.getDescription().getName().toLowerCase());
});
this.addon.getPlugin().getIWM().getAddon(world).ifPresent(gameModeAddon ->
manager.wipeDatabase(gameModeAddon.getDescription().getName().toLowerCase()));
}
try
@ -700,7 +708,7 @@ public class ChallengesImportManager
// Set correct level ID
challengeLevel.setUniqueId(uniqueIDPrefix + challengeLevel.getUniqueId());
// Set correct world name
challengeLevel.setWorld(Util.getWorld(world).getName());
challengeLevel.setWorld(correctWorld.getName());
// Reset names for all challenges.
challengeLevel.setChallenges(challengeLevel.getChallenges().stream().
map(challenge -> uniqueIDPrefix + challenge).
@ -728,6 +736,14 @@ public class ChallengesImportManager
*/
public void loadDownloadedChallenges(User user, World world, String downloadString)
{
World correctWorld = Util.getWorld(world);
if (correctWorld == null)
{
this.addon.logError("Given world is not part of BentoBox");
return;
}
ChallengesManager manager = this.addon.getChallengesManager();
// If exist any challenge or level that is bound to current world, then do not load default challenges.
@ -769,7 +785,7 @@ public class ChallengesImportManager
// Set correct level ID
challengeLevel.setUniqueId(uniqueIDPrefix + challengeLevel.getUniqueId());
// Set correct world name
challengeLevel.setWorld(Util.getWorld(world).getName());
challengeLevel.setWorld(correctWorld.getName());
// Reset names for all challenges.
challengeLevel.setChallenges(challengeLevel.getChallenges().stream().
map(challenge -> uniqueIDPrefix + challenge).
@ -840,7 +856,7 @@ public class ChallengesImportManager
stream().
map(challengeLevel -> {
// Use clone to avoid any changes in existing levels.
ChallengeLevel clone = challengeLevel.clone();
ChallengeLevel clone = challengeLevel.copy();
// Remove world name from level ID.
clone.setUniqueId(challengeLevel.getUniqueId().replaceFirst(replacementString, ""));
// Remove world name.

View File

@ -12,7 +12,6 @@ import org.bukkit.entity.EntityType;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.Database;
@ -24,9 +23,6 @@ import world.bentobox.challenges.config.Settings;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.database.object.ChallengeLevel;
import world.bentobox.challenges.database.object.ChallengesPlayerData;
import world.bentobox.challenges.database.object.requirements.InventoryRequirements;
import world.bentobox.challenges.database.object.requirements.IslandRequirements;
import world.bentobox.challenges.database.object.requirements.OtherRequirements;
import world.bentobox.challenges.database.object.requirements.Requirements;
import world.bentobox.challenges.events.ChallengeCompletedEvent;
import world.bentobox.challenges.events.ChallengeResetAllEvent;
@ -57,7 +53,7 @@ public class ChallengesManager
private final Database<ChallengeLevel> levelDatabase;
/**
* This database allows to access player challenge data.
* This database allows accessing player challenge data.
*/
private final Database<ChallengesPlayerData> playersDatabase;
@ -77,17 +73,17 @@ public class ChallengesManager
private final Map<String, ChallengesPlayerData> playerCacheData;
/**
* This variable allows to access ChallengesAddon.
* This variable allows accessing ChallengesAddon.
*/
private final ChallengesAddon addon;
/**
* This variable allows to access ChallengesAddon settings.
* This variable allows accessing ChallengesAddon settings.
*/
private final Settings settings;
/**
* Island world manager allows to detect which world refferes to which gamemode addon.
* Island world manager allows detecting which world refers to which gamemode addon.
*/
private final IslandWorldManager islandWorldManager;
@ -121,7 +117,7 @@ public class ChallengesManager
{
if (o1.getOrder() == o2.getOrder())
{
// If orders are equal, sort by unique Id
// If orders are equal, sort by unique id
return o1.getUniqueId().compareToIgnoreCase(o2.getUniqueId());
}
else
@ -139,9 +135,18 @@ public class ChallengesManager
}
else
{
// Sort by challenges level order numbers
return Integer.compare(this.getLevel(o1.getLevel()).getOrder(),
this.getLevel(o2.getLevel()).getOrder());
ChallengeLevel o1Level = this.getLevel(o1.getLevel());
ChallengeLevel o2Level = this.getLevel(o2.getLevel());
if (o1Level == null || o2Level == null)
{
return Boolean.compare(o1Level == null, o2Level == null);
}
else
{
// Sort by challenges level order numbers
return Integer.compare(o1Level.getOrder(), o2Level.getOrder());
}
}
}
};
@ -166,7 +171,7 @@ public class ChallengesManager
// Set up the configs
this.challengeDatabase = new Database<>(addon, Challenge.class);
this.levelDatabase = new Database<>(addon, ChallengeLevel.class);
// Players is where all the player history will be stored
// playersDatabase is where all the player history will be stored
this.playersDatabase = new Database<>(addon, ChallengesPlayerData.class);
// Init all cache objects.
@ -226,9 +231,10 @@ public class ChallengesManager
// store player data before cleaning.
this.savePlayersData();
}
//this.challengeDatabase = new Database<>(addon, Challenge.class);
//this.levelDatabase = new Database<>(addon, ChallengeLevel.class);
//this.playersDatabase = new Database<>(addon, ChallengesPlayerData.class);
// this.challengeDatabase = new Database<>(addon, Challenge.class);
// this.levelDatabase = new Database<>(addon, ChallengeLevel.class);
// this.playersDatabase = new Database<>(addon, ChallengesPlayerData.class);
this.loadAndValidate();
}
@ -420,26 +426,6 @@ public class ChallengesManager
}
/**
* This method stores PlayerData into local cache.
*
* @param playerData ChallengesPlayerData that must be loaded.
*
* TODO: Remove this unused method?
*/
private void loadPlayerData(@NonNull ChallengesPlayerData playerData)
{
try
{
this.playerCacheData.put(playerData.getUniqueId(), playerData);
}
catch (Exception e)
{
this.addon.getLogger().severe("UUID for player in challenge data file is invalid!");
}
}
/**
* This method removes given player from cache data.
*

View File

@ -528,11 +528,9 @@ public abstract class CommonPanel
switch (requirement.getStatistic().getType())
{
case UNTYPED -> {
statistic = this.user.getTranslationOrNothing(reference + "statistic",
"[statistic]", Utils.prettifyObject(requirement.getStatistic(), this.user),
"[number]", String.valueOf(requirement.getAmount()));
}
case UNTYPED -> statistic = this.user.getTranslationOrNothing(reference + "statistic",
"[statistic]", Utils.prettifyObject(requirement.getStatistic(), this.user),
"[number]", String.valueOf(requirement.getAmount()));
case ITEM, BLOCK -> {
if (requirement.getAmount() > 1)
{
@ -563,9 +561,7 @@ public abstract class CommonPanel
"[target]", Utils.prettifyObject(requirement.getEntity(), this.user));
}
}
default -> {
statistic = "";
}
default -> statistic = "";
}
String warning = requirement.isReduceStatistic() ?

View File

@ -41,9 +41,9 @@ public class ConversationUtils
* @param user User who is targeted with current confirmation.
*/
public static void createConfirmation(Consumer<Boolean> consumer,
User user,
@NotNull String question,
@Nullable String successMessage)
User user,
@NotNull String question,
@Nullable String successMessage)
{
ValidatingPrompt confirmationPrompt = new ValidatingPrompt()
{
@ -77,7 +77,6 @@ public class ConversationUtils
* @return the prompt
*/
@Override
@Nullable
protected Prompt acceptValidatedInput(@NotNull ConversationContext context, @NotNull String input)
{
String validEntry = user.getTranslation(Constants.CONVERSATIONS + "confirm-string").toLowerCase();
@ -105,7 +104,8 @@ public class ConversationUtils
* @see Prompt#getPromptText(ConversationContext)
*/
@Override
public @NotNull String getPromptText(@NotNull ConversationContext conversationContext)
@NotNull
public String getPromptText(@NotNull ConversationContext conversationContext)
{
// Close input GUI.
user.closeInventory();
@ -137,11 +137,11 @@ public class ConversationUtils
* @param user User who is targeted with current confirmation.
*/
public static void createIDStringInput(Consumer<String> consumer,
Function<String, Boolean> validation,
User user,
@NotNull String question,
@Nullable String successMessage,
@Nullable String failTranslationLocation)
Function<String, Boolean> validation,
User user,
@NotNull String question,
@Nullable String successMessage,
@Nullable String failTranslationLocation)
{
ValidatingPrompt validatingPrompt = new ValidatingPrompt()
{
@ -154,7 +154,8 @@ public class ConversationUtils
* @return The text to display.
*/
@Override
public String getPromptText(ConversationContext context)
@NotNull
public String getPromptText(@NotNull ConversationContext context)
{
// Close input GUI.
user.closeInventory();
@ -175,7 +176,7 @@ public class ConversationUtils
* validity of the input.
*/
@Override
protected boolean isInputValid(ConversationContext context, String input)
protected boolean isInputValid(@NotNull ConversationContext context, @NotNull String input)
{
return validation.apply(input);
}
@ -194,8 +195,8 @@ public class ConversationUtils
* correct the input.
*/
@Override
protected String getFailedValidationText(ConversationContext context,
String invalidInput)
protected String getFailedValidationText(@NotNull ConversationContext context,
@NotNull String invalidInput)
{
return user.getTranslation(failTranslationLocation,
Constants.PARAMETER_ID,
@ -216,7 +217,7 @@ public class ConversationUtils
* @return The next Prompt in the prompt graph.
*/
@Override
protected Prompt acceptValidatedInput(ConversationContext context, String input)
protected Prompt acceptValidatedInput(@NotNull ConversationContext context, @NotNull String input)
{
// Add answer to consumer.
consumer.accept(input);
@ -247,10 +248,10 @@ public class ConversationUtils
* @param question Message that will be displayed in chat when player triggers conversion.
*/
public static void createNumericInput(Consumer<Number> consumer,
@NotNull User user,
@NotNull String question,
Number minValue,
Number maxValue)
@NotNull User user,
@NotNull String question,
Number minValue,
Number maxValue)
{
// Create NumericPromt instance that will validate and process input.
NumericPrompt numberPrompt = new NumericPrompt()
@ -267,7 +268,7 @@ public class ConversationUtils
* graph.
*/
@Override
protected Prompt acceptValidatedInput(ConversationContext context, Number input)
protected Prompt acceptValidatedInput(@NotNull ConversationContext context, @NotNull Number input)
{
// Add answer to consumer.
consumer.accept(input);
@ -285,7 +286,7 @@ public class ConversationUtils
* @return The validity of the player's input.
*/
@Override
protected boolean isNumberValid(ConversationContext context, Number input)
protected boolean isNumberValid(@NotNull ConversationContext context, Number input)
{
return input.doubleValue() >= minValue.doubleValue() &&
input.doubleValue() <= maxValue.doubleValue();
@ -301,7 +302,7 @@ public class ConversationUtils
* @return A message explaining how to correct the input.
*/
@Override
protected String getInputNotNumericText(ConversationContext context, String invalidInput)
protected String getInputNotNumericText(@NotNull ConversationContext context, @NotNull String invalidInput)
{
return user.getTranslation(Constants.CONVERSATIONS + "numeric-only", Constants.PARAMETER_VALUE, invalidInput);
}
@ -316,7 +317,7 @@ public class ConversationUtils
* @return A message explaining how to correct the input.
*/
@Override
protected String getFailedValidationText(ConversationContext context, Number invalidInput)
protected String getFailedValidationText(@NotNull ConversationContext context, Number invalidInput)
{
return user.getTranslation(Constants.CONVERSATIONS + "not-valid-value",
Constants.PARAMETER_VALUE, invalidInput.toString(),
@ -329,7 +330,8 @@ public class ConversationUtils
* @see Prompt#getPromptText(ConversationContext)
*/
@Override
public String getPromptText(ConversationContext conversationContext)
@NotNull
public String getPromptText(@NotNull ConversationContext conversationContext)
{
// Close input GUI.
user.closeInventory();
@ -363,9 +365,9 @@ public class ConversationUtils
* @param user User who is targeted with current confirmation.
*/
public static void createStringListInput(Consumer<List<String>> consumer,
User user,
@NotNull String question,
@NotNull String successMessage)
User user,
@NotNull String question,
@NotNull String successMessage)
{
final String SESSION_CONSTANT = Constants.CONVERSATIONS + user.getUniqueId();
@ -373,13 +375,12 @@ public class ConversationUtils
MessagePrompt messagePrompt = new MessagePrompt()
{
@Override
public @NotNull String getPromptText(@NotNull ConversationContext context)
@NotNull
public String getPromptText(@NotNull ConversationContext context)
{
List<String> description = (List<String>) context.getSessionData(SESSION_CONSTANT);
if (description != null)
if (context.getSessionData(SESSION_CONSTANT) instanceof List description)
{
consumer.accept(description);
consumer.accept((List<String>) description);
return successMessage;
}
else
@ -400,7 +401,8 @@ public class ConversationUtils
StringPrompt stringPrompt = new StringPrompt()
{
@Override
public @NotNull String getPromptText(@NotNull ConversationContext context)
@NotNull
public String getPromptText(@NotNull ConversationContext context)
{
user.closeInventory();
@ -424,7 +426,7 @@ public class ConversationUtils
@Override
public @Nullable Prompt acceptInput(@NotNull ConversationContext context, @Nullable String input)
public Prompt acceptInput(@NotNull ConversationContext context, @Nullable String input)
{
String[] exit = user.getTranslation(Constants.CONVERSATIONS + "exit-string").
toLowerCase().replaceAll("\\s", "").
@ -437,9 +439,9 @@ public class ConversationUtils
List<String> desc = new ArrayList<>();
if (context.getSessionData(SESSION_CONSTANT) != null)
if (context.getSessionData(SESSION_CONSTANT) instanceof List list)
{
desc = ((List<String>) context.getSessionData(SESSION_CONSTANT));
desc = (List<String>) list;
}
if (input != null) {
desc.add(ChatColor.translateAlternateColorCodes('&', input));
@ -471,15 +473,16 @@ public class ConversationUtils
* @param user User who is targeted with current confirmation.
*/
public static void createStringInput(Consumer<String> consumer,
User user,
@NotNull String question,
@Nullable String successMessage)
User user,
@NotNull String question,
@Nullable String successMessage)
{
// Text input message.
StringPrompt stringPrompt = new StringPrompt()
{
@Override
public @NotNull String getPromptText(@NotNull ConversationContext context)
@NotNull
public String getPromptText(@NotNull ConversationContext context)
{
user.closeInventory();
return question;
@ -487,7 +490,8 @@ public class ConversationUtils
@Override
public @NotNull Prompt acceptInput(@NotNull ConversationContext context, @Nullable String input)
@NotNull
public Prompt acceptInput(@NotNull ConversationContext context, @Nullable String input)
{
consumer.accept(input);
return ConversationUtils.endMessagePrompt(successMessage);
@ -519,14 +523,16 @@ public class ConversationUtils
return new MessagePrompt()
{
@Override
public @NotNull String getPromptText(@NotNull ConversationContext context)
@NotNull
public String getPromptText(@NotNull ConversationContext context)
{
return message == null ? "" : message;
}
@Override
protected @Nullable Prompt getNextPrompt(@NotNull ConversationContext context)
@Nullable
protected Prompt getNextPrompt(@NotNull ConversationContext context)
{
return Prompt.END_OF_CONVERSATION;
}

View File

@ -158,10 +158,9 @@ public class ManageBlocksPanel extends CommonPagedPanel<Material>
if (!this.selectedMaterials.isEmpty())
{
description.add(this.user.getTranslation(reference + "title"));
this.selectedMaterials.forEach(material -> {
this.selectedMaterials.forEach(material ->
description.add(this.user.getTranslation(reference + "material",
"[material]", Utils.prettifyObject(material, this.user)));
});
"[material]", Utils.prettifyObject(material, this.user))));
}
icon = new ItemStack(Material.LAVA_BUCKET);

View File

@ -155,10 +155,9 @@ public class ManageEntitiesPanel extends CommonPagedPanel<EntityType>
if (!this.selectedEntities.isEmpty())
{
description.add(this.user.getTranslation(reference + "title"));
this.selectedEntities.forEach(entity -> {
this.selectedEntities.forEach(entity ->
description.add(this.user.getTranslation(reference + "entity",
"[entity]", Utils.prettifyObject(entity, this.user)));
});
"[entity]", Utils.prettifyObject(entity, this.user))));
}
icon = new ItemStack(Material.LAVA_BUCKET);

View File

@ -120,10 +120,9 @@ public class ChallengeSelector extends PagedSelector<Challenge>
if (!this.selectedElements.isEmpty())
{
description.add(this.user.getTranslation(reference + "title"));
this.selectedElements.forEach(challenge -> {
this.selectedElements.forEach(challenge ->
description.add(this.user.getTranslation(reference + "element",
"[element]", challenge.getFriendlyName()));
});
"[element]", challenge.getFriendlyName())));
}
icon = new ItemStack(Material.COMMAND_BLOCK);

View File

@ -143,10 +143,9 @@ public record EnvironmentSelector(User user, Set<World.Environment> values, BiCo
if (!this.values.isEmpty())
{
description.add(this.user.getTranslation(reference + "title"));
this.values.forEach(element -> {
this.values.forEach(element ->
description.add(this.user.getTranslation(reference + "element",
"[element]", Utils.prettifyObject(element, this.user)));
});
"[element]", Utils.prettifyObject(element, this.user))));
}
icon = new ItemStack(Material.COMMAND_BLOCK);

View File

@ -160,10 +160,9 @@ public class MultiBlockSelector extends PagedSelector<Material>
if (!this.selectedElements.isEmpty())
{
description.add(this.user.getTranslation(reference + "title"));
this.selectedElements.forEach(material -> {
this.selectedElements.forEach(material ->
description.add(this.user.getTranslation(reference + "element",
"[element]", Utils.prettifyObject(material, this.user)));
});
"[element]", Utils.prettifyObject(material, this.user))));
}
icon = new ItemStack(Material.COMMAND_BLOCK);

View File

@ -144,10 +144,9 @@ public class MultiEntitySelector extends PagedSelector<EntityType>
if (!this.selectedElements.isEmpty())
{
description.add(this.user.getTranslation(reference + "title"));
this.selectedElements.forEach(material -> {
this.selectedElements.forEach(material ->
description.add(this.user.getTranslation(reference + "element",
"[element]", Utils.prettifyObject(material, this.user)));
});
"[element]", Utils.prettifyObject(material, this.user))));
}
icon = new ItemStack(Material.COMMAND_BLOCK);

View File

@ -4,7 +4,6 @@ package world.bentobox.challenges.tasks;
import com.google.common.collect.UnmodifiableIterator;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
@ -61,7 +60,7 @@ public class TryToComplete
/**
* Challenges addon variable.
*/
private ChallengesAddon addon;
private final ChallengesAddon addon;
/**
* Challenges manager for addon.
@ -83,11 +82,6 @@ public class TryToComplete
*/
private String permissionPrefix;
/**
* Top command first label.
*/
private String topLabel;
/**
* Challenge that should be completed.
*/
@ -102,13 +96,6 @@ public class TryToComplete
// Section: Builder
// ---------------------------------------------------------------------
@Deprecated
public TryToComplete label(String label)
{
this.topLabel = label;
return this;
}
@Deprecated
public TryToComplete user(User user)
@ -118,38 +105,6 @@ public class TryToComplete
}
@Deprecated
public TryToComplete manager(ChallengesManager manager)
{
this.manager = manager;
return this;
}
@Deprecated
public TryToComplete challenge(Challenge challenge)
{
this.challenge = challenge;
return this;
}
@Deprecated
public TryToComplete world(World world)
{
this.world = world;
return this;
}
@Deprecated
public TryToComplete permPrefix(String prefix)
{
this.permissionPrefix = prefix;
return this;
}
@Deprecated
public TryToComplete(ChallengesAddon addon)
{
@ -185,7 +140,6 @@ public class TryToComplete
// To avoid any modifications that may occur to challenges in current completion
// just clone it.
this.challenge = challenge.clone();
this.topLabel = topLabel;
}
@ -254,6 +208,13 @@ public class TryToComplete
return result;
}
if (this.user.getLocation() == null || this.user.getInventory() == null)
{
// This is just a cleaning check. There is no situations where location or inventory
// could be null at this point of code.
return result;
}
this.fullFillRequirements(result);
// Validation to avoid rewarding if something goes wrong in removing requirements.
@ -314,23 +275,21 @@ public class TryToComplete
filter(player -> this.user.getUniqueId().equals(player.getUniqueId())).
map(User::getInstance).
filter(Objects::nonNull).
forEach(user -> {
Utils.sendMessage(user, user.getTranslation(
"challenges.messages.name-has-completed-challenge",
Constants.PARAMETER_NAME, this.user.getName(),
"[value]", this.challenge.getFriendlyName()));
});
forEach(user -> Utils.sendMessage(user, user.getTranslation(
"challenges.messages.name-has-completed-challenge",
Constants.PARAMETER_NAME, this.user.getName(),
"[value]", this.challenge.getFriendlyName())));
}
// sends title to player on challenge completion
if (this.addon.getChallengesSettings().isShowCompletionTitle())
{
this.user.getPlayer().sendTitle(
this.parseChallenge(this.user.getTranslation("challenges.titles.challenge-title"), this.challenge),
this.parseChallenge(this.user.getTranslation("challenges.titles.challenge-subtitle"), this.challenge),
10,
this.addon.getChallengesSettings().getTitleShowtime(),
20);
this.parseChallenge(this.user.getTranslation("challenges.titles.challenge-title"), this.challenge),
this.parseChallenge(this.user.getTranslation("challenges.titles.challenge-subtitle"), this.challenge),
10,
this.addon.getChallengesSettings().getTitleShowtime(),
20);
}
}
@ -355,7 +314,7 @@ public class TryToComplete
if (this.addon.isEconomyProvided())
{
this.addon.getEconomyProvider().deposit(this.user,
(double)this.challenge.getRepeatMoneyReward() * rewardFactor);
this.challenge.getRepeatMoneyReward() * rewardFactor);
}
// Experience Repeat Reward
@ -424,12 +383,10 @@ public class TryToComplete
filter(player -> this.user.getUniqueId().equals(player.getUniqueId())).
map(User::getInstance).
filter(Objects::nonNull).
forEach(user -> {
Utils.sendMessage(user, user.getTranslation(
"challenges.messages.name-has-completed-level",
Constants.PARAMETER_NAME, this.user.getName(),
"[value]", level.getFriendlyName()));
});
forEach(user -> Utils.sendMessage(user, user.getTranslation(
"challenges.messages.name-has-completed-level",
Constants.PARAMETER_NAME, this.user.getName(),
"[value]", level.getFriendlyName())));
}
this.manager.setLevelComplete(this.user, this.world, level);
@ -453,7 +410,7 @@ public class TryToComplete
/**
* This method full fills all challenge type requirements, that is not full filled yet.
* This method fulfills all challenge type requirements, that is not fulfilled yet.
* @param result Challenge Results
*/
private void fullFillRequirements(ChallengeResult result)
@ -520,7 +477,7 @@ public class TryToComplete
case STATISTIC_TYPE -> {
StatisticRequirements requirements = this.challenge.getRequirements();
if (requirements.isReduceStatistic())
if (requirements.isReduceStatistic() && requirements.getStatistic() != null)
{
int removeAmount = result.getFactor() * requirements.getAmount();
@ -544,7 +501,12 @@ public class TryToComplete
case ITEM, BLOCK -> {
int statistic = this.user.getPlayer().getStatistic(requirements.getStatistic());
if (removeAmount >= statistic)
if (requirements.getMaterial() == null)
{
// Just a sanity check. Material cannot be null at this point of code.
removeAmount = 0;
}
else if (removeAmount >= statistic)
{
this.user.getPlayer().setStatistic(requirements.getStatistic(), requirements.getMaterial(), 0);
removeAmount -= statistic;
@ -560,7 +522,12 @@ public class TryToComplete
case ENTITY -> {
int statistic = this.user.getPlayer().getStatistic(requirements.getStatistic());
if (removeAmount >= statistic)
if (requirements.getEntity() == null)
{
// Just a sanity check. Entity cannot be null at this point of code.
removeAmount = 0;
}
else if (removeAmount >= statistic)
{
this.user.getPlayer().setStatistic(requirements.getStatistic(), requirements.getEntity(), 0);
removeAmount -= statistic;
@ -616,7 +583,12 @@ public class TryToComplete
case ITEM, BLOCK -> {
int statistic = player.getStatistic(requirements.getStatistic());
if (removeAmount >= statistic)
if (requirements.getMaterial() == null)
{
// Just a sanity check. Entity cannot be null at this point of code.
removeAmount = 0;
}
else if (removeAmount >= statistic)
{
removeAmount -= statistic;
player.setStatistic(requirements.getStatistic(), requirements.getMaterial(), 0);
@ -632,7 +604,12 @@ public class TryToComplete
case ENTITY -> {
int statistic = player.getStatistic(requirements.getStatistic());
if (removeAmount >= statistic)
if (requirements.getEntity() == null)
{
// Just a sanity check. Entity cannot be null at this point of code.
removeAmount = 0;
}
else if (removeAmount >= statistic)
{
removeAmount -= statistic;
player.setStatistic(requirements.getStatistic(), requirements.getEntity(), 0);
@ -676,13 +653,14 @@ public class TryToComplete
result = EMPTY_RESULT;
}
else if (Util.getWorld(this.world) != Util.getWorld(this.user.getWorld()) ||
!this.challenge.matchGameMode(Utils.getGameMode(this.world)))
!this.challenge.matchGameMode(Utils.getGameMode(this.world)))
{
Utils.sendMessage(this.user, this.user.getTranslation("general.errors.wrong-world"));
result = EMPTY_RESULT;
}
// Player is not on island
else if (ChallengesAddon.CHALLENGES_WORLD_PROTECTION.isSetForWorld(this.world) &&
else if (this.user.getLocation() == null ||
ChallengesAddon.CHALLENGES_WORLD_PROTECTION.isSetForWorld(this.world) &&
!this.addon.getIslands().locationIsOnIsland(this.user.getPlayer(), this.user.getLocation()))
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.not-on-island"));
@ -690,22 +668,22 @@ public class TryToComplete
}
// Check player permission
else if (!this.addon.getIslands().getIslandAt(this.user.getLocation()).
map(i -> i.isAllowed(this.user, ChallengesAddon.CHALLENGES_ISLAND_PROTECTION)).
orElse(false))
map(i -> i.isAllowed(this.user, ChallengesAddon.CHALLENGES_ISLAND_PROTECTION)).
orElse(false))
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.no-rank"));
result = EMPTY_RESULT;
}
// Check if user has unlocked challenges level.
else if (!this.challenge.getLevel().equals(ChallengesManager.FREE) &&
!this.manager.isLevelUnlocked(this.user, this.world, this.manager.getLevel(this.challenge.getLevel())))
!this.manager.isLevelUnlocked(this.user, this.world, this.manager.getLevel(this.challenge.getLevel())))
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.challenge-level-not-available"));
result = EMPTY_RESULT;
}
// Check max times
else if (this.challenge.isRepeatable() && this.challenge.getMaxTimes() > 0 &&
this.manager.getChallengeTimes(this.user, this.world, this.challenge) >= this.challenge.getMaxTimes())
this.manager.getChallengeTimes(this.user, this.world, this.challenge) >= this.challenge.getMaxTimes())
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.not-repeatable"));
result = EMPTY_RESULT;
@ -729,7 +707,7 @@ public class TryToComplete
}
// Check environment
else if (!this.challenge.getEnvironment().isEmpty() &&
!this.challenge.getEnvironment().contains(this.user.getWorld().getEnvironment()))
!this.challenge.getEnvironment().contains(this.user.getWorld().getEnvironment()))
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.wrong-environment"));
result = EMPTY_RESULT;
@ -827,7 +805,7 @@ public class TryToComplete
{
String alert = "Running command '" + cmd + "' as " + this.user.getName();
this.addon.getLogger().info(alert);
cmd = cmd.substring(6, cmd.length()).replace(Constants.PARAMETER_PLAYER, this.user.getName()).trim();
cmd = cmd.substring(6).replace(Constants.PARAMETER_PLAYER, this.user.getName()).trim();
try
{
if (!user.performCommand(cmd))
@ -896,7 +874,12 @@ public class TryToComplete
{
int numInInventory;
if (this.getInventoryRequirements().getIgnoreMetaData().contains(required.getType()))
if (this.user.getInventory() == null)
{
// Sanity check. User always has inventory at this point of code.
numInInventory = 0;
}
else if (this.getInventoryRequirements().getIgnoreMetaData().contains(required.getType()))
{
numInInventory = Arrays.stream(this.user.getInventory().getContents()).
filter(Objects::nonNull).
@ -951,7 +934,12 @@ public class TryToComplete
int amountToBeRemoved = required.getAmount() * factor;
List<ItemStack> itemsInInventory;
if (this.getInventoryRequirements().getIgnoreMetaData().contains(required.getType()))
if (this.user.getInventory() == null)
{
// Sanity check. User always has inventory at this point of code.
itemsInInventory = Collections.emptyList();
}
else if (this.getInventoryRequirements().getIgnoreMetaData().contains(required.getType()))
{
// Use collecting method that ignores item meta.
itemsInInventory = Arrays.stream(user.getInventory().getContents()).
@ -1065,14 +1053,14 @@ public class TryToComplete
// Protection code. Do not allow to select too large region for completing challenge.
if (boundingBox.getWidthX() > distance * 2 + 3 ||
boundingBox.getWidthZ() > distance * 2 + 3 ||
boundingBox.getHeight() > distance * 2 + 3)
boundingBox.getWidthZ() > distance * 2 + 3 ||
boundingBox.getHeight() > distance * 2 + 3)
{
this.addon.logError("BoundingBox is larger than SearchRadius. " +
" | BoundingBox: " + boundingBox.toString() +
" | BoundingBox: " + boundingBox +
" | Search Distance: " + requirements.getSearchRadius() +
" | Location: " + this.user.getLocation().toString() +
" | Center: " + island.getCenter().toString() +
" | Location: " + this.user.getLocation() +
" | Center: " + island.getCenter() +
" | Range: " + range);
return EMPTY_RESULT;
@ -1110,10 +1098,10 @@ public class TryToComplete
// This queue will contain only blocks whit required type ordered by distance till player.
Queue<Block> blockFromWorld = new PriorityQueue<>((o1, o2) -> {
if (o1.getType().equals(o2.getType()))
if (o1.getType().equals(o2.getType()) && this.user.getLocation() != null)
{
return Double.compare(o1.getLocation().distance(this.user.getLocation()),
o2.getLocation().distance(this.user.getLocation()));
o2.getLocation().distance(this.user.getLocation()));
}
else
{
@ -1210,10 +1198,10 @@ public class TryToComplete
// Create queue that contains all required entities ordered by distance till player.
Queue<Entity> entityQueue = new PriorityQueue<>((o1, o2) -> {
if (o1.getType().equals(o2.getType()))
if (o1.getType().equals(o2.getType()) && this.user.getLocation() != null)
{
return Double.compare(o1.getLocation().distance(this.user.getLocation()),
o2.getLocation().distance(this.user.getLocation()));
o2.getLocation().distance(this.user.getLocation()));
}
else
{
@ -1408,6 +1396,12 @@ public class TryToComplete
int currentValue;
if (requirements.getStatistic() == null)
{
// Sanity check.
return EMPTY_RESULT;
}
switch (requirements.getStatistic().getType())
{
case UNTYPED -> currentValue =
@ -1454,7 +1448,10 @@ public class TryToComplete
if (inputMessage.contains("[") && inputMessage.contains("]"))
{
outputMessage = outputMessage.replace("[friendlyName]", challenge.getFriendlyName());
outputMessage = outputMessage.replace("[level]", challenge.getLevel().isEmpty() ? "" : this.manager.getLevel(challenge.getLevel()).getFriendlyName());
ChallengeLevel level = challenge.getLevel().isEmpty() ? null : this.manager.getLevel(challenge.getLevel());
outputMessage = outputMessage.replace("[level]", level == null ? "" : level.getFriendlyName());
outputMessage = outputMessage.replace("[rewardText]", challenge.getRewardText());
}

View File

@ -19,7 +19,7 @@ public class LevelStatus {
* @param previousLevel - previous level
* @param numberOfChallengesStillToDo - number of challenges still to do on this level
* @param complete - whether complete or not
* @param isUnlocked
* @param isUnlocked - if level is unlocked or not.
*/
public LevelStatus(ChallengeLevel level, ChallengeLevel previousLevel, int numberOfChallengesStillToDo, boolean complete, boolean isUnlocked) {
super();

View File

@ -63,7 +63,7 @@ public class Utils
i++;
}
if (isUnique && item != null)
if (isUnique)
{
// The same issue as in other places. Clone prevents from changing original item.
returnItems.add(item.clone());
@ -95,7 +95,7 @@ public class Utils
* @param <T> Instance of given object.
* @return Next value after currentValue in values array.
*/
public static <T extends Object> T getNextValue(T[] values, T currentValue)
public static <T> T getNextValue(T[] values, T currentValue)
{
for (int i = 0; i < values.length; i++)
{
@ -123,7 +123,7 @@ public class Utils
* @param <T> Instance of given object.
* @return Previous value before currentValue in values array.
*/
public static <T extends Object> T getPreviousValue(T[] values, T currentValue)
public static <T> T getPreviousValue(T[] values, T currentValue)
{
for (int i = 0; i < values.length; i++)
{
@ -544,19 +544,15 @@ public class Utils
String translation;
switch (object.getType())
{
case POTION, SPLASH_POTION, LINGERING_POTION, TIPPED_ARROW -> {
case POTION, SPLASH_POTION, LINGERING_POTION, TIPPED_ARROW ->
// Get Potion Meta
translation = prettifyObject(object, (PotionMeta) object.getItemMeta(), user);
}
case PLAYER_HEAD, PLAYER_WALL_HEAD -> {
case PLAYER_HEAD, PLAYER_WALL_HEAD ->
translation = prettifyObject(object, (SkullMeta) object.getItemMeta(), user);
}
case ENCHANTED_BOOK -> {
case ENCHANTED_BOOK ->
translation = prettifyObject(object, (EnchantmentStorageMeta) object.getItemMeta(), user);
}
case WRITTEN_BOOK, WRITABLE_BOOK -> {
case WRITTEN_BOOK, WRITABLE_BOOK ->
translation = prettifyObject(object, (BookMeta) object.getItemMeta(), user);
}
case LEATHER_BOOTS,LEATHER_CHESTPLATE,LEATHER_HELMET,LEATHER_LEGGINGS,LEATHER_HORSE_ARMOR,
TRIDENT,CROSSBOW,CHAINMAIL_HELMET,CHAINMAIL_CHESTPLATE,CHAINMAIL_LEGGINGS,CHAINMAIL_BOOTS,IRON_HELMET,
IRON_CHESTPLATE,IRON_LEGGINGS,IRON_BOOTS,DIAMOND_HELMET,DIAMOND_CHESTPLATE,DIAMOND_LEGGINGS,DIAMOND_BOOTS,
@ -565,9 +561,8 @@ public class Utils
STONE_SWORD,STONE_SHOVEL,STONE_PICKAXE,STONE_AXE,STONE_HOE,GOLDEN_SWORD,GOLDEN_SHOVEL,GOLDEN_PICKAXE,
GOLDEN_AXE,GOLDEN_HOE,IRON_SWORD,IRON_SHOVEL,IRON_PICKAXE,IRON_AXE,IRON_HOE,DIAMOND_SWORD,DIAMOND_SHOVEL,
DIAMOND_PICKAXE,DIAMOND_AXE,DIAMOND_HOE,NETHERITE_SWORD,NETHERITE_SHOVEL,NETHERITE_PICKAXE,NETHERITE_AXE,
NETHERITE_HOE,TURTLE_HELMET,SHEARS,SHIELD,FLINT_AND_STEEL,BOW -> {
NETHERITE_HOE,TURTLE_HELMET,SHEARS,SHIELD,FLINT_AND_STEEL,BOW ->
translation = prettifyObject(object, object.getItemMeta(), user);
}
default ->
translation = "";
}