Merge branch 'develop' into master

# Conflicts:
#	pom.xml
#	src/main/java/world/bentobox/challenges/commands/admin/ChallengesGlobalAdminCommand.java
#	src/main/java/world/bentobox/challenges/managers/ChallengesImportManager.java
#	src/main/java/world/bentobox/challenges/managers/ChallengesManager.java
#	src/main/java/world/bentobox/challenges/panel/CommonPanel.java
#	src/main/java/world/bentobox/challenges/panel/user/ChallengesPanel.java
#	src/main/java/world/bentobox/challenges/tasks/TryToComplete.java
#	src/main/resources/locales/en-US.yml
#	src/main/resources/locales/pl.yml
#	src/main/resources/locales/zh-CN.yml
#	src/main/resources/template.yml
This commit is contained in:
BONNe 2023-01-05 21:40:14 +02:00
commit 7f58af7588
14 changed files with 3306 additions and 1239 deletions

View File

@ -1,6 +0,0 @@
Contributions are welcome but acceptance is completely up to tastybento. Do not be offended if your contribution is rejected.
I will not accept any contributions that are formatting only, or mostly formatting.
Automated code cleanup is also not a valid contribution as a first Pull Request. If a tool is doing your job,
the submit an issue that recommends we use a specific tool.
Contributions are accepted under the license terms and conditions. Note that this means we may use them elsewhere.
Thank you!

View File

@ -1,5 +0,0 @@
Thanks for submitting a pull request. Do not use this form for bug reports!
Your submission must meet the minimum requirements of a contribution, i.e., add code, refactor code or fix code.
It takes time and effort to review submissions, so please do not waste our time.
Note: formatting/spacing-only submissions will be rejected!
For submissions, we want you to use spaces, not tabs (4 spaces) - thank you.

View File

@ -37,14 +37,14 @@
<!-- More visible way how to change dependency versions -->
<spigot.version>1.17.1-R0.1-SNAPSHOT</spigot.version>
<spigot-annotations.version>1.2.3-SNAPSHOT</spigot-annotations.version>
<bentobox.version>1.20.0</bentobox.version>
<bentobox.version>1.21.0</bentobox.version>
<level.version>2.6.3</level.version>
<vault.version>1.7</vault.version>
<panelutils.version>1.0.0</panelutils.version>
<panelutils.version>1.1.0</panelutils.version>
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- This allows to change between versions and snapshots. -->
<build.version>1.0.0</build.version>
<build.version>1.1.0</build.version>
<build.number>-LOCAL</build.number>
<!-- Sonar Cloud -->
<sonar.projectKey>BentoBoxWorld_Challenges</sonar.projectKey>

View File

@ -37,7 +37,7 @@ public class ChallengesGlobalAdminCommand extends CompositeCommand
@Override
public void setup()
{
this.setPermission("addon.admin.challenges");
this.setPermission("admin.challenges");
this.setParametersHelp("challenges.commands.admin.main.parameters");
this.setDescription("challenges.commands.admin.main.description");
}

View File

@ -101,10 +101,8 @@ public class ChallengesImportManager
Utils.sendMessage(user, user.getTranslation(Constants.ERRORS + "no-load",
Constants.PARAMETER_FILE, file, TextVariables.DESCRIPTION, e.getMessage()));
}
else
{
this.addon.logError("Exception when loading file. " + e.getMessage());
}
this.addon.logError("Exception when loading file. " + e.getMessage());
return;
}
@ -119,10 +117,8 @@ public class ChallengesImportManager
user.getTranslation(Constants.ERRORS + "not-a-gamemode-world",
Constants.PARAMETER_WORLD, world.getName()));
}
else
{
this.addon.logWarning("Given world is not a gamemode world.");
}
this.addon.logWarning("Given world is not a gamemode world.");
return;
}

View File

@ -113,41 +113,28 @@ public class ChallengesManager
* This comparator orders challenges by their level, order and name.
*/
private final Comparator<Challenge> challengeComparator = (o1, o2) -> {
if (o1.getLevel().equals(o2.getLevel()))
ChallengeLevel o1Level = this.getLevel(o1.getLevel());
ChallengeLevel o2Level = this.getLevel(o2.getLevel());
if (o1Level == null && o2Level == null)
{
if (o1.getOrder() == o2.getOrder())
{
// If orders are equal, sort by unique id
return o1.getUniqueId().compareToIgnoreCase(o2.getUniqueId());
}
else
{
// If levels are equal, sort them by order numbers.
return Integer.compare(o1.getOrder(), o2.getOrder());
}
return Integer.compare(o1.getOrder(), o2.getOrder());
}
else if (o1Level == null)
{
return -1;
}
else if (o2Level == null)
{
return 1;
}
else if (o1Level.equals(o2Level))
{
return Integer.compare(o1.getOrder(), o2.getOrder());
}
else
{
if (o1.getLevel().isEmpty() || o2.getLevel().isEmpty())
{
// If exist free level challenge, then it should be at the start.
return Boolean.compare(o2.getLevel().isEmpty(), o1.getLevel().isEmpty());
}
else
{
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());
}
}
return Integer.compare(o1Level.getOrder(), o2Level.getOrder());
}
};

View File

@ -496,7 +496,7 @@ public abstract class CommonPanel
this.user.getTranslationOrNothing(reference + "money-warning") : "";
String level = !this.addon.isLevelProvided() || requirement.getRequiredIslandLevel() <= 0 ? "" :
this.user.getTranslationOrNothing(reference,
this.user.getTranslationOrNothing(reference + "level",
"[number]", String.valueOf(requirement.getRequiredIslandLevel()));
return this.user.getTranslationOrNothing(reference + "lore",

View File

@ -8,6 +8,7 @@ package world.bentobox.challenges.panel.user;
import org.bukkit.World;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
@ -274,11 +275,43 @@ public class ChallengesPanel extends CommonPanel
builder.description(this.generateChallengeDescription(challenge, this.user));
}
// If challenge is not repeatable, remove all other actions beside "COMPLETE".
// If challenge is completed all possible times, remove action.
List<ItemTemplateRecord.ActionRecords> actions = template.actions().stream().
filter(action -> challenge.isRepeatable() || "COMPLETE".equalsIgnoreCase(action.actionType())).
filter(action ->
{
boolean isCompletedOnce =
this.manager.isChallengeComplete(this.user.getUniqueId(), this.world, challenge);
if (!isCompletedOnce)
{
// Is not completed once, then it must appear.
return true;
}
else if (challenge.isRepeatable() && challenge.getMaxTimes() <= 0)
{
// Challenge is unlimited. Must appear in the list.
return true;
}
else
{
// Challenge still have some opened slots.
long doneTimes = challenge.isRepeatable() ?
this.manager.getChallengeTimes(this.user, this.world, challenge) : 1;
return challenge.isRepeatable() && doneTimes < challenge.getMaxTimes();
}
}).
toList();
// Add Click handler
builder.clickHandler((panel, user, clickType, i) -> {
for (ItemTemplateRecord.ActionRecords action : template.actions())
for (ItemTemplateRecord.ActionRecords action : actions)
{
if (clickType == action.clickType())
if (clickType == action.clickType() || clickType.equals(ClickType.UNKNOWN))
{
switch (action.actionType().toUpperCase())
{
@ -368,9 +401,8 @@ public class ChallengesPanel extends CommonPanel
});
// Collect tooltips.
List<String> tooltips = template.actions().stream().
List<String> tooltips = actions.stream().
filter(action -> action.tooltip() != null).
filter(action -> challenge.isRepeatable() || "COMPLETE".equalsIgnoreCase(action.actionType())).
map(action -> this.user.getTranslation(this.world, action.tooltip())).
filter(text -> !text.isBlank()).
collect(Collectors.toCollection(() -> new ArrayList<>(template.actions().size())));

View File

@ -791,17 +791,25 @@ public class TryToComplete
private void runCommands(List<String> commands)
{
// Ignore commands with this perm
if (user.hasPermission(this.permissionPrefix + "command.challengeexempt") && !user.isOp())
if (this.user.hasPermission(this.permissionPrefix + "command.challengeexempt") && !this.user.isOp())
{
return;
}
final Island island = this.addon.getIslandsManager().getIsland(this.world, this.user);
final String owner = island == null ? "" : this.addon.getPlayers().getName(island.getOwner());
for (String cmd : commands)
{
if (cmd.startsWith("[SELF]"))
{
String alert = "Running command '" + cmd + "' as " + this.user.getName();
this.addon.getLogger().info(alert);
cmd = cmd.substring(6).replace(Constants.PARAMETER_PLAYER, this.user.getName()).trim();
cmd = cmd.substring(6).
replaceAll(Constants.PARAMETER_PLAYER, this.user.getName()).
replaceAll(Constants.PARAMETER_OWNER, owner).
replaceAll(Constants.PARAMETER_NAME, island == null || island.getName() == null ? "" : island.getName()).
trim();
try
{
if (!user.performCommand(cmd))
@ -816,11 +824,17 @@ public class TryToComplete
continue;
}
// Substitute in any references to player
try
{
if (!this.addon.getServer().dispatchCommand(this.addon.getServer().getConsoleSender(),
cmd.replace(Constants.PARAMETER_PLAYER, this.user.getName())))
cmd = cmd.replaceAll(Constants.PARAMETER_PLAYER, this.user.getName()).
replaceAll(Constants.PARAMETER_OWNER, owner).
replaceAll(Constants.PARAMETER_NAME, island == null || island.getName() == null ? "" : island.getName()).
trim();
if (!this.addon.getServer().dispatchCommand(this.addon.getServer().getConsoleSender(), cmd))
{
this.showError(cmd);
}
@ -1428,6 +1442,7 @@ public class TryToComplete
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.requirement-not-met",
TextVariables.NUMBER, String.valueOf(requirements.getAmount()),
"[statistic]", Utils.prettifyObject(requirements.getStatistic(), this.user),
"[value]", String.valueOf(currentValue)));
}
else

View File

@ -1189,7 +1189,7 @@ challenges:
not-enough-money: '&c It is necessary to have [value] on your account to complete the challenge.'
not-enough-experience: '&c It is necessary to have [value] EXP to complete this challenge.'
island-level: '&c Your island must be level [number] or greater to complete this challenge!'
no-load: '&c Error: Could not load file. [message]'
no-load: '&c Error: Could not load [file]. Error [message]'
load-error: '&c Error: Cannot load [value].'
no-rank: "&c You do not have rank that is high enough to do that."
cannot-remove-items: '&c Some items cannot be removed from your inventory!'
@ -1203,6 +1203,7 @@ challenges:
no-library-entries: "&c Cannot find any library entries. Nothing to show."
not-hooked: "&c Challenges Addon could not find any GameMode."
timeout: "&c This challenge requires to wait [timeout] between completions. You must wait [wait-time] till complete it again."
requirement-not-met: "&c This challenge requires [statistic] to have [number]. You have only [value]. "
# # Showcase for manual material translation
# materials:
# # Names should be lowercase.
@ -1238,7 +1239,27 @@ challenges:
# # This will overwrite generic translation.
# name: "[type] [upgraded] [extended]"
# # Type is either specific translation or potion effect.
# uncraftable: "Uncraftable"
# water: "Water"
# mundane: "Mundane"
# thick: "Thick"
# awkward: "Awkward"
# night_vision: "Potion of Night Vision"
# invisibility: "Potion of Invisibility"
# jump: "Potion of Leaping"
# fire_resistance: "Potion of Fire Resistance"
# speed: "Potion of Swiftness"
# slowness: "Potion of Slowness"
# water_breathing: "Potion of Water Breathing"
# instant_heal: "Potion of Healing"
# instant_damage: "Potion of Harming"
# poison: "Potion of Poison"
# regen: "Potion of Regeneration"
# strength: "Potion of Strength"
# weakness: "Potion of Weakness"
# luck: "Potion of Luck"
# turtle_master: "Potion of Turtle Master"
# slow_falling: "Potion of Slow Falling"
# stone_shovel:
# # This will mean that only stone shovels will not show
# # meta information.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -88,6 +88,10 @@ challenges:
# It is not necessary to writhe `/`.
# This examples first command will force player to execute `/island` command,
# While second command will run `/kill [player]` from the server console.
# There are 3 available parameters for commands:
# - [player] - player who completed the challenge
# - [owner] - the island owner
# - [name] - the name of the island.
commands:
- island
- kill [player]
@ -122,6 +126,10 @@ challenges:
# It is not necessary to writhe `/`.
# This examples first command will force player to execute `/island` command,
# While second command will run `/kill [player]` from the server console.
# There are 3 available parameters for commands:
# - [player] - player who completed the challenge
# - [owner] - the island owner
# - [name] - the name of the island.
commands:
- island
- kill [player]
@ -220,6 +228,10 @@ challenges:
# It is not necessary to writhe `/`.
# This examples first command will force player to execute `/island` command,
# While second command will run `/kill [player]` from the server console.
# There are 3 available parameters for commands:
# - [player] - player who completed the challenge
# - [owner] - the island owner
# - [name] - the name of the island.
commands:
- island
- kill [player]
@ -254,6 +266,10 @@ challenges:
# It is not necessary to writhe `/`.
# This examples first command will force player to execute `/island` command,
# While second command will run `/kill [player]` from the server console.
# There are 3 available parameters for commands:
# - [player] - player who completed the challenge
# - [owner] - the island owner
# - [name] - the name of the island.
commands:
- island
- kill [player]
@ -339,6 +355,10 @@ challenges:
# It is not necessary to writhe `/`.
# This examples first command will force player to execute `/island` command,
# While second command will run `/kill [player]` from the server console.
# There are 3 available parameters for commands:
# - [player] - player who completed the challenge
# - [owner] - the island owner
# - [name] - the name of the island.
commands:
- island
- kill [player]
@ -373,6 +393,10 @@ challenges:
# It is not necessary to writhe `/`.
# This examples first command will force player to execute `/island` command,
# While second command will run `/kill [player]` from the server console.
# There are 3 available parameters for commands:
# - [player] - player who completed the challenge
# - [owner] - the island owner
# - [name] - the name of the island.
commands:
- island
- kill [player]
@ -464,6 +488,10 @@ challenges:
# It is not necessary to writhe `/`.
# This examples first command will force player to execute `/island` command,
# While second command will run `/kill [player]` from the server console.
# There are 3 available parameters for commands:
# - [player] - player who completed the challenge
# - [owner] - the island owner
# - [name] - the name of the island.
commands:
- island
- kill [player]
@ -498,6 +526,10 @@ challenges:
# It is not necessary to writhe `/`.
# This examples first command will force player to execute `/island` command,
# While second command will run `/kill [player]` from the server console.
# There are 3 available parameters for commands:
# - [player] - player who completed the challenge
# - [owner] - the island owner
# - [name] - the name of the island.
commands:
- island
- kill [player]
@ -551,6 +583,10 @@ levels:
# It is not necessary to writhe `/`.
# This examples first command will force player to execute `/island` command,
# While second command will run `/kill [player]` from the server console.
# There are 3 available parameters for commands:
# - [player] - player who completed the challenge
# - [owner] - the island owner
# - [name] - the name of the island.
commands:
- island
- kill [player]