mirror of
https://github.com/BentoBoxWorld/Challenges.git
synced 2025-02-22 23:31:21 +01:00
Merge pull request #376 from BentoBoxWorld/papi
Added a PAPI formula option to Other challenge types.
This commit is contained in:
commit
39addcabf6
12
pom.xml
12
pom.xml
@ -117,6 +117,11 @@
|
|||||||
<id>minecraft-repo</id>
|
<id>minecraft-repo</id>
|
||||||
<url>https://libraries.minecraft.net/</url>
|
<url>https://libraries.minecraft.net/</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<!-- Placeholder API -->
|
||||||
|
<repository>
|
||||||
|
<id>placeholderapi</id>
|
||||||
|
<url>https://repo.extendedclip.com/releases/</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -198,6 +203,13 @@
|
|||||||
<artifactId>commons-math3</artifactId>
|
<artifactId>commons-math3</artifactId>
|
||||||
<version>3.6.1</version>
|
<version>3.6.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Placeholder API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>me.clip</groupId>
|
||||||
|
<artifactId>placeholderapi</artifactId>
|
||||||
|
<version>2.11.6</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -0,0 +1,183 @@
|
|||||||
|
package world.bentobox.challenges.database.object.requirements;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.PlaceholderAPI;
|
||||||
|
|
||||||
|
public class CheckPapi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the formula by first replacing PAPI placeholders (using the provided Player)
|
||||||
|
* and then evaluating the resulting expression. The expression is expected to be a series
|
||||||
|
* of numeric comparisons (using =, <>, <=, >=, <, >) joined by Boolean operators AND and OR.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* "%aoneblock_my_island_lifetime_count% >= 1000 AND %Level_aoneblock_island_level% >= 100"
|
||||||
|
*
|
||||||
|
* If any placeholder evaluates to a non-numeric value or the formula is malformed, false is returned.
|
||||||
|
*
|
||||||
|
* @param player the Player used for placeholder replacement.
|
||||||
|
* @param formula the formula to evaluate.
|
||||||
|
* @return true if the formula evaluates to true, false otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean evaluate(Player player, String formula) {
|
||||||
|
// Replace PAPI placeholders with actual values using the provided Player.
|
||||||
|
String parsedFormula = PlaceholderAPI.setPlaceholders(player, formula);
|
||||||
|
|
||||||
|
// Tokenize the parsed formula (tokens are assumed to be separated by whitespace).
|
||||||
|
List<String> tokens = tokenize(parsedFormula);
|
||||||
|
if (tokens.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Parser parser = new Parser(tokens);
|
||||||
|
boolean result = parser.parseExpression();
|
||||||
|
// If there are leftover tokens, the expression is malformed.
|
||||||
|
if (parser.hasNext()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Any error in parsing or evaluation results in false.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits the given string into tokens using whitespace as the delimiter.
|
||||||
|
*
|
||||||
|
* @param s the string to tokenize.
|
||||||
|
* @return a list of tokens.
|
||||||
|
*/
|
||||||
|
private static List<String> tokenize(String s) {
|
||||||
|
return new ArrayList<>(Arrays.asList(s.split("\\s+")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple recursive descent parser that evaluates expressions according to the following grammar:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Expression -> Term { OR Term }
|
||||||
|
* Term -> Factor { AND Factor }
|
||||||
|
* Factor -> operand operator operand
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* A Factor is expected to be a numeric condition in the form:
|
||||||
|
* number operator number
|
||||||
|
* where operator is one of: =, <>, <=, >=, <, or >.
|
||||||
|
*/
|
||||||
|
private static class Parser {
|
||||||
|
private final List<String> tokens;
|
||||||
|
private int pos = 0;
|
||||||
|
|
||||||
|
public Parser(List<String> tokens) {
|
||||||
|
this.tokens = tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if there are more tokens to process.
|
||||||
|
*/
|
||||||
|
public boolean hasNext() {
|
||||||
|
return pos < tokens.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next token without advancing.
|
||||||
|
*/
|
||||||
|
public String peek() {
|
||||||
|
return tokens.get(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next token and advances the position.
|
||||||
|
*/
|
||||||
|
public String next() {
|
||||||
|
return tokens.get(pos++);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an Expression:
|
||||||
|
* Expression -> Term { OR Term }
|
||||||
|
*/
|
||||||
|
public boolean parseExpression() {
|
||||||
|
boolean value = parseTerm();
|
||||||
|
while (hasNext() && peek().equalsIgnoreCase("OR")) {
|
||||||
|
next(); // consume "OR"
|
||||||
|
boolean termValue = parseTerm();
|
||||||
|
value = value || termValue;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a Term:
|
||||||
|
* Term -> Factor { AND Factor }
|
||||||
|
*/
|
||||||
|
public boolean parseTerm() {
|
||||||
|
boolean value = parseFactor();
|
||||||
|
while (hasNext() && peek().equalsIgnoreCase("AND")) {
|
||||||
|
next(); // consume "AND"
|
||||||
|
boolean factorValue = parseFactor();
|
||||||
|
value = value && factorValue;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a Factor, which is a single condition in the form:
|
||||||
|
* operand operator operand
|
||||||
|
*
|
||||||
|
* For example: "1234 >= 1000"
|
||||||
|
*
|
||||||
|
* @return the boolean result of the condition.
|
||||||
|
*/
|
||||||
|
public boolean parseFactor() {
|
||||||
|
// There must be at least three tokens remaining.
|
||||||
|
if (pos + 2 >= tokens.size()) {
|
||||||
|
throw new RuntimeException("Incomplete condition");
|
||||||
|
}
|
||||||
|
|
||||||
|
String leftOperand = next();
|
||||||
|
String operator = next();
|
||||||
|
String rightOperand = next();
|
||||||
|
|
||||||
|
// Validate operator.
|
||||||
|
if (!operator.equals("=") && !operator.equals("<>") && !operator.equals("<=") && !operator.equals(">=")
|
||||||
|
&& !operator.equals("<") && !operator.equals(">")) {
|
||||||
|
throw new RuntimeException("Invalid operator: " + operator);
|
||||||
|
}
|
||||||
|
|
||||||
|
double leftVal, rightVal;
|
||||||
|
try {
|
||||||
|
leftVal = Double.parseDouble(leftOperand);
|
||||||
|
rightVal = Double.parseDouble(rightOperand);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// If either operand is not numeric, return false.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Evaluate the condition.
|
||||||
|
switch (operator) {
|
||||||
|
case "=":
|
||||||
|
return Double.compare(leftVal, rightVal) == 0;
|
||||||
|
case "<>":
|
||||||
|
return Double.compare(leftVal, rightVal) != 0;
|
||||||
|
case "<=":
|
||||||
|
return leftVal <= rightVal;
|
||||||
|
case ">=":
|
||||||
|
return leftVal >= rightVal;
|
||||||
|
case "<":
|
||||||
|
return leftVal < rightVal;
|
||||||
|
case ">":
|
||||||
|
return leftVal > rightVal;
|
||||||
|
default:
|
||||||
|
// This case is never reached.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -139,6 +139,20 @@ public class OtherRequirements extends Requirements
|
|||||||
{
|
{
|
||||||
this.requiredIslandLevel = requiredIslandLevel;
|
this.requiredIslandLevel = requiredIslandLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the papiString
|
||||||
|
*/
|
||||||
|
public String getPapiString() {
|
||||||
|
return papiString == null ? "" : papiString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param papiString the papiString to set
|
||||||
|
*/
|
||||||
|
public void setPapiString(String papiString) {
|
||||||
|
this.papiString = papiString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
@ -162,6 +176,7 @@ public class OtherRequirements extends Requirements
|
|||||||
clone.setRequiredMoney(this.requiredMoney);
|
clone.setRequiredMoney(this.requiredMoney);
|
||||||
clone.setTakeMoney(this.takeMoney);
|
clone.setTakeMoney(this.takeMoney);
|
||||||
clone.setRequiredIslandLevel(this.requiredIslandLevel);
|
clone.setRequiredIslandLevel(this.requiredIslandLevel);
|
||||||
|
clone.setPapiString(this.papiString);
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
@ -201,4 +216,12 @@ public class OtherRequirements extends Requirements
|
|||||||
*/
|
*/
|
||||||
@Expose
|
@Expose
|
||||||
private long requiredIslandLevel;
|
private long requiredIslandLevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formulas that include math symbols and PAPI placeholders
|
||||||
|
*/
|
||||||
|
@Expose
|
||||||
|
private String papiString;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -215,6 +215,7 @@ public class EditChallengePanel extends CommonPanel {
|
|||||||
panelBuilder.item(12, this.createRequirementButton(RequirementButton.REQUIRED_MONEY));
|
panelBuilder.item(12, this.createRequirementButton(RequirementButton.REQUIRED_MONEY));
|
||||||
panelBuilder.item(21, this.createRequirementButton(RequirementButton.REMOVE_MONEY));
|
panelBuilder.item(21, this.createRequirementButton(RequirementButton.REMOVE_MONEY));
|
||||||
|
|
||||||
|
panelBuilder.item(14, this.createRequirementButton(RequirementButton.REQUIRED_PAPI));
|
||||||
panelBuilder.item(23, this.createRequirementButton(RequirementButton.REQUIRED_LEVEL));
|
panelBuilder.item(23, this.createRequirementButton(RequirementButton.REQUIRED_LEVEL));
|
||||||
|
|
||||||
panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS));
|
panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS));
|
||||||
@ -630,7 +631,7 @@ public class EditChallengePanel extends CommonPanel {
|
|||||||
return this.createInventoryRequirementButton(button);
|
return this.createInventoryRequirementButton(button);
|
||||||
}
|
}
|
||||||
// Buttons for Other Requirements
|
// Buttons for Other Requirements
|
||||||
case REQUIRED_EXPERIENCE, REMOVE_EXPERIENCE, REQUIRED_LEVEL, REQUIRED_MONEY, REMOVE_MONEY -> {
|
case REQUIRED_EXPERIENCE, REMOVE_EXPERIENCE, REQUIRED_LEVEL, REQUIRED_MONEY, REMOVE_MONEY, REQUIRED_PAPI -> {
|
||||||
return this.createOtherRequirementButton(button);
|
return this.createOtherRequirementButton(button);
|
||||||
}
|
}
|
||||||
// Statistics
|
// Statistics
|
||||||
@ -1098,6 +1099,33 @@ public class EditChallengePanel extends CommonPanel {
|
|||||||
description.add("");
|
description.add("");
|
||||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
|
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
|
||||||
}
|
}
|
||||||
|
case REQUIRED_PAPI -> {
|
||||||
|
if (!requirements.getPapiString().isEmpty()) {
|
||||||
|
description
|
||||||
|
.add(this.user.getTranslation(reference + "value", "[formula]", requirements.getPapiString()));
|
||||||
|
}
|
||||||
|
icon = new ItemStack(
|
||||||
|
this.addon.getPlugin().getHooks().getHook("PlaceholderAPI").isPresent() ? Material.PAPER
|
||||||
|
: Material.BARRIER);
|
||||||
|
clickHandler = (panel, user, clickType, i) -> {
|
||||||
|
Consumer<String> stringConsumer = string -> {
|
||||||
|
if (string != null) {
|
||||||
|
requirements.setPapiString(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reopen panel
|
||||||
|
this.build();
|
||||||
|
};
|
||||||
|
ConversationUtils.createStringInput(stringConsumer, user,
|
||||||
|
this.user.getTranslation(Constants.CONVERSATIONS + "enter-formula"), "");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
glow = false;
|
||||||
|
|
||||||
|
description.add("");
|
||||||
|
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
|
||||||
|
}
|
||||||
case REQUIRED_MONEY -> {
|
case REQUIRED_MONEY -> {
|
||||||
description.add(this.user.getTranslation(reference + "value", Constants.PARAMETER_NUMBER,
|
description.add(this.user.getTranslation(reference + "value", Constants.PARAMETER_NUMBER,
|
||||||
String.valueOf(requirements.getRequiredMoney())));
|
String.valueOf(requirements.getRequiredMoney())));
|
||||||
@ -1701,7 +1729,7 @@ public class EditChallengePanel extends CommonPanel {
|
|||||||
REQUIRED_LEVEL, REQUIRED_MONEY, REMOVE_MONEY, STATISTIC, STATISTIC_BLOCKS, STATISTIC_ITEMS,
|
REQUIRED_LEVEL, REQUIRED_MONEY, REMOVE_MONEY, STATISTIC, STATISTIC_BLOCKS, STATISTIC_ITEMS,
|
||||||
STATISTIC_ENTITIES,
|
STATISTIC_ENTITIES,
|
||||||
STATISTIC_AMOUNT, REMOVE_STATISTIC, REQUIRED_MATERIALTAGS, REQUIRED_ENTITYTAGS, REQUIRED_STATISTICS,
|
STATISTIC_AMOUNT, REMOVE_STATISTIC, REQUIRED_MATERIALTAGS, REQUIRED_ENTITYTAGS, REQUIRED_STATISTICS,
|
||||||
REMOVE_STATISTICS,
|
REMOVE_STATISTICS, REQUIRED_PAPI,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
@ -37,6 +37,7 @@ import org.bukkit.util.BoundingBox;
|
|||||||
|
|
||||||
import com.google.common.collect.UnmodifiableIterator;
|
import com.google.common.collect.UnmodifiableIterator;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.BentoBox;
|
||||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
import world.bentobox.bentobox.database.objects.Island;
|
import world.bentobox.bentobox.database.objects.Island;
|
||||||
@ -45,6 +46,7 @@ import world.bentobox.challenges.ChallengesAddon;
|
|||||||
import world.bentobox.challenges.database.object.Challenge;
|
import world.bentobox.challenges.database.object.Challenge;
|
||||||
import world.bentobox.challenges.database.object.Challenge.ChallengeType;
|
import world.bentobox.challenges.database.object.Challenge.ChallengeType;
|
||||||
import world.bentobox.challenges.database.object.ChallengeLevel;
|
import world.bentobox.challenges.database.object.ChallengeLevel;
|
||||||
|
import world.bentobox.challenges.database.object.requirements.CheckPapi;
|
||||||
import world.bentobox.challenges.database.object.requirements.InventoryRequirements;
|
import world.bentobox.challenges.database.object.requirements.InventoryRequirements;
|
||||||
import world.bentobox.challenges.database.object.requirements.IslandRequirements;
|
import world.bentobox.challenges.database.object.requirements.IslandRequirements;
|
||||||
import world.bentobox.challenges.database.object.requirements.OtherRequirements;
|
import world.bentobox.challenges.database.object.requirements.OtherRequirements;
|
||||||
@ -530,91 +532,79 @@ public class TryToComplete
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If challenges are in sync with all island members, then punish others too.
|
// If challenges are in sync with all island members, then punish others too.
|
||||||
if (this.addon.getChallengesSettings().isStoreAsIslandData())
|
if (this.addon.getChallengesSettings().isStoreAsIslandData())
|
||||||
{
|
|
||||||
Island island = this.addon.getIslands().getIsland(this.world, this.user);
|
|
||||||
|
|
||||||
if (island == null) {
|
|
||||||
// hmm
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (UnmodifiableIterator<UUID> iterator = island.getMemberSet().iterator(); iterator.hasNext()
|
|
||||||
&& removeAmount > 0;)
|
|
||||||
{
|
{
|
||||||
Player player = Bukkit.getPlayer(iterator.next());
|
Island island = this.addon.getIslands().getIsland(this.world, this.user);
|
||||||
|
|
||||||
if (player == null || player == this.user.getPlayer()) {
|
if (island == null) {
|
||||||
// cannot punish null or player who already was punished.
|
// hmm
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Objects.requireNonNull(s.statistic()).getType()) {
|
for (UnmodifiableIterator<UUID> iterator = island.getMemberSet().iterator(); iterator.hasNext()
|
||||||
case UNTYPED -> {
|
&& removeAmount > 0;) {
|
||||||
int statistic = player.getStatistic(s.statistic());
|
Player player = Bukkit.getPlayer(iterator.next());
|
||||||
|
|
||||||
if (removeAmount >= statistic)
|
if (player == null || player == this.user.getPlayer()) {
|
||||||
{
|
// cannot punish null or player who already was punished.
|
||||||
removeAmount -= statistic;
|
continue;
|
||||||
player.setStatistic(s.statistic(), 0);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
switch (Objects.requireNonNull(s.statistic()).getType()) {
|
||||||
player.setStatistic(s.statistic(), statistic - removeAmount);
|
case UNTYPED -> {
|
||||||
removeAmount = 0;
|
int statistic = player.getStatistic(s.statistic());
|
||||||
}
|
|
||||||
}
|
|
||||||
case ITEM, BLOCK -> {
|
|
||||||
if (s.material() == null)
|
|
||||||
{
|
|
||||||
// Just a sanity check. Entity cannot be null at this point of code.
|
|
||||||
removeAmount = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int statistic = player.getStatistic(s.statistic(), s.material());
|
|
||||||
|
|
||||||
if (removeAmount >= statistic)
|
if (removeAmount >= statistic)
|
||||||
{
|
{
|
||||||
removeAmount -= statistic;
|
removeAmount -= statistic;
|
||||||
player.setStatistic(s.statistic(), s.material(), 0);
|
player.setStatistic(s.statistic(), 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
player.setStatistic(s.statistic(), s.material(),
|
player.setStatistic(s.statistic(), statistic - removeAmount);
|
||||||
statistic - removeAmount);
|
|
||||||
removeAmount = 0;
|
removeAmount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
case ITEM, BLOCK -> {
|
||||||
case ENTITY -> {
|
if (s.material() == null) {
|
||||||
if (s.entity() == null)
|
// Just a sanity check. Entity cannot be null at this point of code.
|
||||||
{
|
removeAmount = 0;
|
||||||
// Just a sanity check. Entity cannot be null at this point of code.
|
} else {
|
||||||
removeAmount = 0;
|
int statistic = player.getStatistic(s.statistic(), s.material());
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int statistic = player.getStatistic(s.statistic(), s.entity());
|
|
||||||
|
|
||||||
if (removeAmount >= statistic)
|
if (removeAmount >= statistic) {
|
||||||
|
removeAmount -= statistic;
|
||||||
|
player.setStatistic(s.statistic(), s.material(), 0);
|
||||||
|
} else {
|
||||||
|
player.setStatistic(s.statistic(), s.material(), statistic - removeAmount);
|
||||||
|
removeAmount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case ENTITY -> {
|
||||||
|
if (s.entity() == null)
|
||||||
{
|
{
|
||||||
removeAmount -= statistic;
|
// Just a sanity check. Entity cannot be null at this point of code.
|
||||||
player.setStatistic(s.statistic(), s.entity(), 0);
|
removeAmount = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
player.setStatistic(s.statistic(), s.entity(),
|
int statistic = player.getStatistic(s.statistic(), s.entity());
|
||||||
statistic - removeAmount);
|
|
||||||
removeAmount = 0;
|
if (removeAmount >= statistic) {
|
||||||
|
removeAmount -= statistic;
|
||||||
|
player.setStatistic(s.statistic(), s.entity(), 0);
|
||||||
|
} else {
|
||||||
|
player.setStatistic(s.statistic(), s.entity(), statistic - removeAmount);
|
||||||
|
removeAmount = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1426,6 +1416,15 @@ public class TryToComplete
|
|||||||
Utils.sendMessage(this.user,
|
Utils.sendMessage(this.user,
|
||||||
this.world, Constants.ERRORS + "island-level", TextVariables.NUMBER,
|
this.world, Constants.ERRORS + "island-level", TextVariables.NUMBER,
|
||||||
String.valueOf(requirements.getRequiredIslandLevel()));
|
String.valueOf(requirements.getRequiredIslandLevel()));
|
||||||
|
} else if (this.addon.getPlugin().getHooks().getHook("PlaceholderAPI").isPresent()
|
||||||
|
&& !requirements.getPapiString().isEmpty()
|
||||||
|
&& !CheckPapi.evaluate(user.getPlayer(), requirements.getPapiString())) {
|
||||||
|
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "incorrect");
|
||||||
|
if (!requirements.getPapiString().isEmpty()) {
|
||||||
|
addon.log("FYI:.Challenge failed for " + user.getName() + ". PAPI formula: "
|
||||||
|
+ requirements.getPapiString() + " = "
|
||||||
|
+ CheckPapi.evaluate(user.getPlayer(), requirements.getPapiString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1451,7 +1450,6 @@ public class TryToComplete
|
|||||||
// Section: Statistic Challenge
|
// Section: Statistic Challenge
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a statistic challenge can be completed or not
|
* Checks if a statistic challenge can be completed or not
|
||||||
* It returns ChallengeResult.
|
* It returns ChallengeResult.
|
||||||
|
@ -415,6 +415,13 @@ challenges:
|
|||||||
&7 money on the player's
|
&7 money on the player's
|
||||||
&7 account for the challenge.
|
&7 account for the challenge.
|
||||||
value: "&7 Current value: &e [number]"
|
value: "&7 Current value: &e [number]"
|
||||||
|
required_papi:
|
||||||
|
name: "&f&l Required PAPI"
|
||||||
|
description: |-
|
||||||
|
&7 Checks a formula that can
|
||||||
|
&7 include PAPI placeholders
|
||||||
|
&7 and math and logical elements.
|
||||||
|
value: "&7 Formula: &e [formula]"
|
||||||
statistic:
|
statistic:
|
||||||
name: "&f&l Statistic"
|
name: "&f&l Statistic"
|
||||||
description: |-
|
description: |-
|
||||||
@ -1130,6 +1137,7 @@ challenges:
|
|||||||
file-name-exist: "&c A file named '[id]' already exists. Cannot overwrite."
|
file-name-exist: "&c A file named '[id]' already exists. Cannot overwrite."
|
||||||
write-search: "&e Please enter a search value. (Type 'cancel' to exit)"
|
write-search: "&e Please enter a search value. (Type 'cancel' to exit)"
|
||||||
search-updated: "&a Search value updated."
|
search-updated: "&a Search value updated."
|
||||||
|
enter-formula: "&a Enter a formula that uses PAPI number placeholders and symbols =,<>,<+,>=, AND, OR only.\n&a Example: &7 %aoneblock_my_island_lifetime_count% >= 1000 AND %Level_aoneblock_island_level% >= 100"
|
||||||
titles:
|
titles:
|
||||||
challenge-title: "Success!"
|
challenge-title: "Success!"
|
||||||
challenge-subtitle: "[friendlyName]"
|
challenge-subtitle: "[friendlyName]"
|
||||||
|
Loading…
Reference in New Issue
Block a user