Release 1.2.0 (#317)

* Init 1.2.0 version

* Fixes #311 localization errors in zn-CN.

Original translation author translated `[]` placeholders which broke locale

* Init 1.2.0 version

* Edit some unfit translation (#312)

Edit some unfit translation

* Fixes a regex bug that replaced every [player] char instead of whole word.

* Fixes a crash that prevented STATISTICS entity and material/item challenges to be completed.

* Add requirement-not-met-material and requirement-not-met-entity to display statistic required item on error.

* Add locale of Chinese-Hong Kong (zh-HK) (#313)

Addition of locale updated to latest version

* Add ${argLine} to get jacoco coverage

* Updated Jacoco POM section

* Update build.yml

Java 17 for Surefire

* Updated pladdon annotations

* Add support for gamemode-specific translations.

This was a request from Floris

* Update ChallengesManagerTest methods with world parameter.

* Implement option that excludes undeployed challenges

The new option allows to toggle if undeployed challenges should be included in level completion count. Disabling option will not include these challenges for level completion.

Fixes #315

* Create plugin.yml (#316)

* Create plugin.yml

* Update pom.xml

* Update ChallengesPladdon.java

* Remove dependency to org.apache.commons

Replace org.apache.commons.lang.ArrayUtils to a default Java implementation.

---------

Co-authored-by: EpicMo <1982742309@qq.com>
Co-authored-by: JamesMCL44 <epicquarters@gmail.com>
Co-authored-by: tastybento <tastybento@users.noreply.github.com>
Co-authored-by: tastybento <tastybento@wasteofplastic.com>
This commit is contained in:
BONNe 2023-04-15 22:55:34 +03:00 committed by GitHub
parent 7f58af7588
commit b1fa9a9da7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1869 additions and 504 deletions

View File

@ -14,10 +14,10 @@ jobs:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Set up JDK 16
- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 16
java-version: 17
- name: Cache SonarCloud packages
uses: actions/cache@v1
with:

55
pom.xml
View File

@ -32,7 +32,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>16</java.version>
<java.version>17</java.version>
<powermock.version>2.0.9</powermock.version>
<!-- More visible way how to change dependency versions -->
<spigot.version>1.17.1-R0.1-SNAPSHOT</spigot.version>
@ -44,7 +44,7 @@
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- This allows to change between versions and snapshots. -->
<build.version>1.1.0</build.version>
<build.version>1.2.0</build.version>
<build.number>-LOCAL</build.number>
<!-- Sonar Cloud -->
<sonar.projectKey>BentoBoxWorld_Challenges</sonar.projectKey>
@ -127,12 +127,6 @@
<version>${spigot.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>plugin-annotations</artifactId>
<version>1.2.3-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Vault API -->
<dependency>
<groupId>net.milkbowl.vault</groupId>
@ -249,6 +243,7 @@
<version>3.0.0-M5</version>
<configuration>
<argLine>
${argLine}
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.math=ALL-UNNAMED
--add-opens java.base/java.io=ALL-UNNAMED
@ -355,35 +350,35 @@
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.1-SNAPSHOT</version>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<configuration>
<minimizeJar>true</minimizeJar>
<artifactSet>
<includes>
<include>lv.id.bonne:panelutils:*</include>
</includes>
</artifactSet>
<transformers>
<!-- Add a transformer to exclude any other manifest files (possibly from dependencies). -->
<transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
<resource>MANIFEST.MF</resource>
</transformer>
<!-- Add a transformer to include your custom manifest file. -->
<transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
<resource>META-INF/MANIFEST.MF</resource>
<file>src/main/resources/META-INF/MANIFEST.MF</file>
</transformer>
</transformers>
<append>true</append>
<excludes>
<!-- This is required to prevent Jacoco from adding
synthetic fields to a JavaBean class (causes errors in testing) -->
<exclude>**/*Names*</exclude>
</excludes>
</configuration>
<executions>
<execution>
<phase>package</phase>
<id>prepare-agent</id>
<goals>
<goal>shade</goal>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<goals>
<goal>report</goal>
</goals>
<configuration>
<formats>
<format>XML</format>
</formats>
</configuration>
</execution>
</executions>
</plugin>
</plugins>

View File

@ -408,8 +408,18 @@ public class ChallengesAddon extends Addon {
addonName + "_latest_level_uncompleted_count",
user -> {
ChallengeLevel level = this.challengesManager.getLatestUnlockedLevel(user, world);
return String.valueOf(level != null ?
level.getChallenges().size() - this.challengesManager.getLevelCompletedChallengeCount(user, world, level) : 0);
if (level == null)
{
return "0";
}
int challengeCount = this.getChallengesSettings().isIncludeUndeployed() ?
level.getChallenges().size() :
this.challengesManager.getLevelChallenges(level, false).size();
return String.valueOf(challengeCount -
this.challengesManager.getLevelCompletedChallengeCount(user, world, level));
});
}

View File

@ -7,19 +7,12 @@
package world.bentobox.challenges;
import org.bukkit.plugin.java.annotation.dependency.Dependency;
import org.bukkit.plugin.java.annotation.plugin.ApiVersion;
import org.bukkit.plugin.java.annotation.plugin.Plugin;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.Pladdon;
/**
* @author tastybento
*/
@Plugin(name="Pladdon", version="1.0")
@ApiVersion(ApiVersion.Target.v1_17)
@Dependency(value = "BentoBox")
public class ChallengesPladdon extends Pladdon
{
@Override

View File

@ -55,7 +55,7 @@ public class ChallengesGlobalPlayerCommand extends CompositeCommand
if (this.gameModeAddons.isEmpty())
{
Utils.sendMessage(user, user.getTranslation(Constants.ERRORS + "not-hooked"));
Utils.sendMessage(user, user.getWorld(), Constants.ERRORS + "not-hooked");
return false;
}
else if (this.gameModeAddons.size() == 1)
@ -80,7 +80,7 @@ public class ChallengesGlobalPlayerCommand extends CompositeCommand
}
}
Utils.sendMessage(user, user.getTranslation("general.errors.wrong-world"));
Utils.sendMessage(user, user.getWorld(), "general.errors.wrong-world");
}
else if (this.<ChallengesAddon>getAddon().getChallengesSettings().getUserGuiMode() == GuiMode.GAMEMODE_LIST)
{

View File

@ -8,6 +8,7 @@ import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.panel.user.ChallengesPanel;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.Utils;
@ -31,7 +32,7 @@ public class ChallengesPlayerCommand extends CompositeCommand
if (!this.getIWM().inWorld(user.getWorld()) ||
!Util.sameWorld(this.getWorld(), user.getWorld())) {
// Not a GameMode world.
Utils.sendMessage(user, user.getTranslation("general.errors.wrong-world"));
Utils.sendMessage(user, user.getWorld(), "general.errors.wrong-world");
return false;
}
@ -47,13 +48,13 @@ public class ChallengesPlayerCommand extends CompositeCommand
map(GameModeAddon::getAdminCommand).
map(optionalAdminCommand -> optionalAdminCommand.map(CompositeCommand::getTopLabel).orElse(this.getTopLabel())).
orElse(this.getTopLabel());
Utils.sendMessage(user, user.getTranslation("challenges.errors.no-challenges-admin",
Utils.sendMessage(user, this.getWorld(), Constants.ERRORS + "no-challenges-admin",
"[command]",
topLabel + " " + this.<ChallengesAddon>getAddon().getChallengesSettings().getAdminMainCommand().split(" ")[0]));
topLabel + " " + this.<ChallengesAddon>getAddon().getChallengesSettings().getAdminMainCommand().split(" ")[0]);
}
else
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.no-challenges"));
Utils.sendMessage(user, this.getWorld(), Constants.ERRORS + "no-challenges");
}
return false;
@ -62,14 +63,14 @@ public class ChallengesPlayerCommand extends CompositeCommand
if (this.getIslands().getIsland(this.getWorld(), user) == null)
{
// Do not open gui if there is no island for this player.
Utils.sendMessage(user, user.getTranslation("general.errors.no-island"));
Utils.sendMessage(user, this.getWorld(), "general.errors.no-island");
return false;
} else if (ChallengesAddon.CHALLENGES_WORLD_PROTECTION.isSetForWorld(this.getWorld()) &&
!this.getIslands().locationIsOnIsland(user.getPlayer(), user.getLocation()))
{
// Do not open gui if player is not on the island, but challenges requires island for
// completion.
Utils.sendMessage(user, user.getTranslation("challenges.errors.not-on-island"));
Utils.sendMessage(user, this.getWorld(), Constants.ERRORS + "not-on-island");
return false;
}

View File

@ -11,6 +11,7 @@ import world.bentobox.bentobox.util.Util;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.tasks.TryToComplete;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.Utils;
@ -54,7 +55,7 @@ public class CompleteChallengeCommand extends CompositeCommand
{
if (args.isEmpty())
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.no-name"));
Utils.sendMessage(user, this.getWorld(), Constants.ERRORS + "no-name");
this.showHelp(this, user);
return false;
}
@ -73,7 +74,7 @@ public class CompleteChallengeCommand extends CompositeCommand
if (!canMultipleTimes && count > 1)
{
Utils.sendMessage(user, user.getTranslation("challenges.error.no-multiple-permission"));
Utils.sendMessage(user, this.getWorld(), Constants.ERRORS + "no-multiple-permission");
count = 1;
}
@ -87,7 +88,7 @@ public class CompleteChallengeCommand extends CompositeCommand
}
else
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.unknown-challenge"));
Utils.sendMessage(user, this.getWorld(), Constants.ERRORS + "unknown-challenge");
this.showHelp(this, user);
return false;
}

View File

@ -53,7 +53,7 @@ public class ChallengesGlobalAdminCommand extends CompositeCommand
if (this.gameModeAddons.isEmpty())
{
Utils.sendMessage(user, user.getTranslation(Constants.ERRORS + "not-hooked"));
Utils.sendMessage(user, this.getWorld(), Constants.ERRORS + "not-hooked");
return false;
}
else if (this.gameModeAddons.size() == 1)

View File

@ -56,7 +56,7 @@ public class CompleteCommand extends CompositeCommand
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.no-name"));
Utils.sendMessage(user, this.getWorld(), Constants.ERRORS + "no-name");
}
else
{
@ -67,7 +67,7 @@ public class CompleteCommand extends CompositeCommand
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.missing-arguments"));
Utils.sendMessage(user, this.getWorld(), Constants.ERRORS + "missing-arguments");
}
else
{
@ -82,9 +82,11 @@ public class CompleteCommand extends CompositeCommand
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("general.errors.unknown-player",
Utils.sendMessage(user,
this.getWorld(),
"general.errors.unknown-player",
TextVariables.NAME,
args.get(0)));
args.get(0));
}
else
{
@ -109,9 +111,11 @@ public class CompleteCommand extends CompositeCommand
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.completed",
Utils.sendMessage(user,
this.getWorld(),
Constants.MESSAGES + "completed",
Constants.PARAMETER_NAME, challenge.getFriendlyName(),
Constants.PARAMETER_PLAYER, target.getName()));
Constants.PARAMETER_PLAYER, target.getName());
}
else
{
@ -123,7 +127,9 @@ public class CompleteCommand extends CompositeCommand
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.already-completed"));
Utils.sendMessage(user,
this.getWorld(),
Constants.MESSAGES + "already-completed");
}
else
{
@ -137,7 +143,9 @@ public class CompleteCommand extends CompositeCommand
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.unknown-challenge"));
Utils.sendMessage(user,
this.getWorld(),
Constants.ERRORS + "unknown-challenge");
}
else
{

View File

@ -49,13 +49,13 @@ public class ReloadChallenges extends CompositeCommand
if (args.isEmpty())
{
this.manager.load();
Utils.sendMessage(user, user.getTranslation("general.success"));
Utils.sendMessage(user, this.getWorld(), "general.success");
return true;
}
else if (args.get(0).equalsIgnoreCase("hard"))
{
this.manager.reload();
Utils.sendMessage(user, user.getTranslation("general.success"));
Utils.sendMessage(user, this.getWorld(), "general.success");
return true;
}
else

View File

@ -56,7 +56,7 @@ public class ResetCommand extends CompositeCommand
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.no-name"));
Utils.sendMessage(user, this.getWorld(), Constants.ERRORS + "no-name");
}
else
{
@ -67,7 +67,7 @@ public class ResetCommand extends CompositeCommand
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.missing-arguments"));
Utils.sendMessage(user, this.getWorld(), Constants.ERRORS + "missing-arguments");
}
else
{
@ -82,8 +82,11 @@ public class ResetCommand extends CompositeCommand
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("general.errors.unknown-player",
TextVariables.NAME, args.get(0)));
Utils.sendMessage(user,
this.getWorld(),
Constants.ERRORS + "unknown-player",
TextVariables.NAME,
args.get(0));
}
else
{
@ -102,8 +105,11 @@ public class ResetCommand extends CompositeCommand
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.reset-all",
Constants.PARAMETER_PLAYER, target.getName()));
Utils.sendMessage(user,
this.getWorld(),
Constants.MESSAGES + "reset-all",
Constants.PARAMETER_PLAYER,
target.getName());
}
else
{
@ -125,9 +131,11 @@ public class ResetCommand extends CompositeCommand
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.reset",
Utils.sendMessage(user,
this.getWorld(),
Constants.MESSAGES + "reset",
Constants.PARAMETER_NAME, challenge.getFriendlyName(),
Constants.PARAMETER_PLAYER, target.getName()));
Constants.PARAMETER_PLAYER, target.getName());
}
else
{
@ -139,7 +147,9 @@ public class ResetCommand extends CompositeCommand
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.not-completed"));
Utils.sendMessage(user,
this.getWorld(),
Constants.MESSAGES + "not-completed");
}
else
{
@ -153,7 +163,9 @@ public class ResetCommand extends CompositeCommand
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.unknown-challenge"));
Utils.sendMessage(user,
this.getWorld(),
Constants.ERRORS + "unknown-challenge");
}
else
{

View File

@ -106,11 +106,10 @@ public class Settings implements ConfigObject
@ConfigComment("Valid values are:")
@ConfigComment(" 'VISIBLE' - there will be no hidden challenges. All challenges will be viewable in GUI.")
@ConfigComment(" 'HIDDEN' - shows only deployed challenges.")
@ConfigComment(" 'TOGGLEABLE' - there will be button in GUI that allows users to switch from ALL modes.")
@ConfigComment("TOGGLEABLE - Currently not implemented.")
@ConfigEntry(path = "gui-settings.undeployed-view-mode")
private VisibilityMode visibilityMode = VisibilityMode.VISIBLE;
@ConfigComment("")
@ConfigComment("This allows to change default locked level icon. This option may be")
@ConfigComment("overwritten by each challenge level. If challenge level has specified")
@ -130,6 +129,13 @@ public class Settings implements ConfigObject
@ConfigEntry(path = "reset-challenges")
private boolean resetChallenges = true;
@ConfigComment("")
@ConfigComment("This option indicates if undepolyed challenges should be counted to level completion.")
@ConfigComment("Disabling this option will make it so that only deployed challenges will be counted.")
@ConfigComment("Default: true")
@ConfigEntry(path = "include-undeployed")
private boolean includeUndeployed = true;
@ConfigComment("")
@ConfigComment("Broadcast 1st time challenge completion messages to all players.")
@ConfigComment("Change to false if the spam becomes too much.")
@ -165,7 +171,7 @@ public class Settings implements ConfigObject
* Configuration version
*/
@ConfigComment("")
private String configVersion = "v3";
private String configVersion = "v4";
// ---------------------------------------------------------------------
@ -597,4 +603,26 @@ public class Settings implements ConfigObject
{
this.visibilityMode = visibilityMode;
}
/**
* Is count undeployed to completion boolean.
*
* @return the boolean
*/
public boolean isIncludeUndeployed()
{
return includeUndeployed;
}
/**
* Sets count undeployed to completion.
*
* @param includeUndeployed the count undeployed to completion
*/
public void setIncludeUndeployed(boolean includeUndeployed)
{
this.includeUndeployed = includeUndeployed;
}
}

View File

@ -82,7 +82,11 @@ public class ChallengesImportManager
{
if (user != null)
{
Utils.sendMessage(user, user.getTranslation(Constants.ERRORS + "no-file", Constants.PARAMETER_FILE, file));
Utils.sendMessage(user,
world,
Constants.ERRORS + "no-file",
Constants.PARAMETER_FILE,
file);
}
return;
@ -98,8 +102,11 @@ public class ChallengesImportManager
{
if (user != null)
{
Utils.sendMessage(user, user.getTranslation(Constants.ERRORS + "no-load",
Constants.PARAMETER_FILE, file, TextVariables.DESCRIPTION, e.getMessage()));
Utils.sendMessage(user,
world,
Constants.ERRORS + "no-load",
Constants.PARAMETER_FILE, file,
TextVariables.DESCRIPTION, e.getMessage());
}
this.addon.logError("Exception when loading file. " + e.getMessage());
@ -114,8 +121,9 @@ public class ChallengesImportManager
if (user != null)
{
Utils.sendMessage(user,
user.getTranslation(Constants.ERRORS + "not-a-gamemode-world",
Constants.PARAMETER_WORLD, world.getName()));
world,
Constants.ERRORS + "not-a-gamemode-world",
Constants.PARAMETER_WORLD, world.getName());
}
this.addon.logWarning("Given world is not a gamemode world.");
@ -151,6 +159,7 @@ public class ChallengesImportManager
challengeCount = reader.getKeys(false).stream().
mapToInt(challengeId -> this.createChallenge(challengeId,
prefix,
world,
reader.getConfigurationSection(challengeId))).
sum();
}
@ -174,9 +183,10 @@ public class ChallengesImportManager
if (user != null)
{
Utils.sendMessage(user,
user.getTranslation(Constants.MESSAGES + "import-count",
"[levels]", String.valueOf(levelCount),
"[challenges]", String.valueOf(challengeCount)));
world,
Constants.MESSAGES + "import-count",
"[levels]", String.valueOf(levelCount),
"[challenges]", String.valueOf(challengeCount));
}
this.addon.log("Imported " + challengeCount + " challenges and " +
@ -188,11 +198,13 @@ public class ChallengesImportManager
* This method creates challenge from given config section.
* @param challengeId Challenge ID.
* @param prefix GameMode prefix.
* @param world world where challenge is created.
* @param section Configuration Section that contains information.
* @return 1 if challenge is created, otherwise 0.
*/
private int createChallenge(String challengeId,
String prefix,
World world,
@Nullable ConfigurationSection section)
{
if (section == null)
@ -266,7 +278,7 @@ public class ChallengesImportManager
}
this.addon.getChallengesManager().saveChallenge(challenge);
this.addon.getChallengesManager().loadChallenge(challenge, true, null, true);
this.addon.getChallengesManager().loadChallenge(challenge, world, true, null, true);
}
catch (Exception e)
{
@ -632,7 +644,7 @@ public class ChallengesImportManager
}
this.addon.getChallengesManager().saveLevel(level);
this.addon.getChallengesManager().loadLevel(level, true, null, true);
this.addon.getChallengesManager().loadLevel(level, world,true, null, true);
}
catch (Exception ignored)
{
@ -696,7 +708,7 @@ public class ChallengesImportManager
challenge.setLevel(uniqueIDPrefix + challenge.getLevel());
}
// Load challenge in memory
manager.loadChallenge(challenge, false, user, user == null);
manager.loadChallenge(challenge, world, false, user, user == null);
});
downloadedChallenges.getLevelList().forEach(challengeLevel -> {
@ -709,7 +721,7 @@ public class ChallengesImportManager
map(challenge -> uniqueIDPrefix + challenge).
collect(Collectors.toSet()));
// Load level in memory
manager.loadLevel(challengeLevel, false, user, user == null);
manager.loadLevel(challengeLevel, world, false, user, user == null);
});
}
catch (Exception e)
@ -746,7 +758,7 @@ public class ChallengesImportManager
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.exist-challenges-or-levels"));
Utils.sendMessage(user, world, Constants.ERRORS + "exist-challenges-or-levels");
}
else
{
@ -773,7 +785,7 @@ public class ChallengesImportManager
challenge.setLevel(uniqueIDPrefix + challenge.getLevel());
}
// Load challenge in memory
manager.loadChallenge(challenge, false, user, user == null);
manager.loadChallenge(challenge, world, false, user, user == null);
});
downloadedChallenges.getLevelList().forEach(challengeLevel -> {
@ -786,7 +798,7 @@ public class ChallengesImportManager
map(challenge -> uniqueIDPrefix + challenge).
collect(Collectors.toSet()));
// Load level in memory
manager.loadLevel(challengeLevel, false, user, user == null);
manager.loadLevel(challengeLevel, world, false, user, user == null);
});
}
catch (Exception e)
@ -815,8 +827,9 @@ public class ChallengesImportManager
if (user.isPlayer())
{
Utils.sendMessage(user,
user.getTranslation(Constants.ERRORS + "file-exist",
Constants.PARAMETER_FILE, fileName));
world,
Constants.ERRORS + "file-exist",
Constants.PARAMETER_FILE, fileName);
}
else
{
@ -882,9 +895,10 @@ public class ChallengesImportManager
if (user.isPlayer())
{
Utils.sendMessage(user,
user.getTranslation(Constants.ERRORS + "no-load",
Constants.PARAMETER_FILE, fileName,
TextVariables.DESCRIPTION, e.getMessage()));
world,
Constants.ERRORS + "no-load",
Constants.PARAMETER_FILE, fileName,
TextVariables.DESCRIPTION, e.getMessage());
}
this.addon.logError("Could not save json file: " + e.getMessage());
@ -894,9 +908,10 @@ public class ChallengesImportManager
if (user.isPlayer())
{
Utils.sendMessage(user,
user.getTranslation(Constants.CONVERSATIONS + "database-export-completed",
Constants.PARAMETER_WORLD, world.getName(),
Constants.PARAMETER_FILE, fileName));
world,
Constants.CONVERSATIONS + "database-export-completed",
Constants.PARAMETER_WORLD, world.getName(),
Constants.PARAMETER_FILE, fileName);
}
else
{

View File

@ -28,6 +28,7 @@ import world.bentobox.challenges.events.ChallengeCompletedEvent;
import world.bentobox.challenges.events.ChallengeResetAllEvent;
import world.bentobox.challenges.events.ChallengeResetEvent;
import world.bentobox.challenges.events.LevelCompletedEvent;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.LevelStatus;
import world.bentobox.challenges.utils.Utils;
@ -97,7 +98,6 @@ public class ChallengesManager
* String for free Challenge Level.
*/
public static final String FREE = "";
public static final String VALUE = "[value]";
public static final String USER_ID = "user-id";
public static final String CHALLENGE_ID = "challenge-id";
public static final String ADMIN_ID = "admin-id";
@ -230,7 +230,7 @@ public class ChallengesManager
*/
private void loadChallenge(@NonNull Challenge challenge)
{
this.loadChallenge(challenge, true, null, true);
this.loadChallenge(challenge, null, true, null, true);
}
@ -244,9 +244,10 @@ public class ChallengesManager
* @return - true if imported
*/
public boolean loadChallenge(@Nullable Challenge challenge,
boolean overwrite,
User user,
boolean silent)
World world,
boolean overwrite,
User user,
boolean silent)
{
// This may happen if database somehow failed to load challenge and return
// null as input.
@ -254,7 +255,10 @@ public class ChallengesManager
{
if (!silent)
{
Utils.sendMessage(user, user.getTranslation("load-error", "[value]", "NULL"));
Utils.sendMessage(user,
world,
Constants.ERRORS + "load-error",
Constants.PARAMETER_VALUE, "NULL");
}
return false;
@ -264,8 +268,10 @@ public class ChallengesManager
{
if (!silent)
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.invalid-challenge",
"[challenge]", challenge.getUniqueId()));
Utils.sendMessage(user,
world,
Constants.ERRORS + "invalid-challenge",
Constants.PARAMETER_CHALLENGE, challenge.getUniqueId());
}
this.addon.logWarning("Data for challenge `" + challenge.getUniqueId() + "` is not valid. It could be NULL element in item-stack!");
@ -280,8 +286,10 @@ public class ChallengesManager
{
if (!silent)
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.load-skipping",
VALUE, challenge.getFriendlyName()));
Utils.sendMessage(user,
world,
Constants.MESSAGES + "load-skipping",
Constants.PARAMETER_VALUE, challenge.getFriendlyName());
}
return false;
@ -290,8 +298,10 @@ public class ChallengesManager
{
if (!silent)
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.load-overwriting",
VALUE, challenge.getFriendlyName()));
Utils.sendMessage(user,
world,
Constants.MESSAGES + "load-overwriting",
Constants.PARAMETER_VALUE, challenge.getFriendlyName());
}
}
}
@ -299,8 +309,10 @@ public class ChallengesManager
{
if (!silent)
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.load-add",
VALUE, challenge.getFriendlyName()));
Utils.sendMessage(user,
world,
Constants.MESSAGES + "load-add",
Constants.PARAMETER_VALUE, challenge.getFriendlyName());
}
}
@ -316,7 +328,7 @@ public class ChallengesManager
*/
private void loadLevel(@NonNull ChallengeLevel level)
{
this.loadLevel(level, true, null, true);
this.loadLevel(level, null, true, null, true);
}
@ -331,6 +343,7 @@ public class ChallengesManager
* @return boolean that indicate about load status.
*/
public boolean loadLevel(@Nullable ChallengeLevel level,
World world,
boolean overwrite,
User user,
boolean silent)
@ -341,7 +354,10 @@ public class ChallengesManager
{
if (!silent)
{
Utils.sendMessage(user, user.getTranslation("load-error", "[value]", "NULL"));
Utils.sendMessage(user,
world,
Constants.ERRORS + "load-error",
Constants.PARAMETER_VALUE, "NULL");
}
return false;
@ -351,8 +367,10 @@ public class ChallengesManager
{
if (!silent)
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.invalid-level",
"[level]", level.getUniqueId()));
Utils.sendMessage(user,
world,
Constants.ERRORS + "invalid-level",
"[level]", level.getUniqueId());
}
this.addon.logWarning("Data for level `" + level.getUniqueId() + "` is not valid. It could be NULL element in item-stack!");
@ -363,8 +381,10 @@ public class ChallengesManager
{
if (user != null)
{
Utils.sendMessage(user, user.getTranslation("challenges.errors.load-error",
VALUE, level.getFriendlyName()));
Utils.sendMessage(user,
world,
Constants.ERRORS + "load-error",
Constants.PARAMETER_VALUE, level.getFriendlyName());
}
else
{
@ -380,8 +400,10 @@ public class ChallengesManager
{
if (!silent)
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.load-skipping",
VALUE, level.getFriendlyName()));
Utils.sendMessage(user,
world,
Constants.MESSAGES + "load-skipping",
Constants.PARAMETER_VALUE, level.getFriendlyName());
}
return false;
@ -390,8 +412,10 @@ public class ChallengesManager
{
if (!silent)
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.load-overwriting",
VALUE, level.getFriendlyName()));
Utils.sendMessage(user,
world,
Constants.MESSAGES + "load-overwriting",
Constants.PARAMETER_VALUE, level.getFriendlyName());
}
}
}
@ -399,8 +423,10 @@ public class ChallengesManager
{
if (!silent)
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.load-add",
VALUE, level.getFriendlyName()));
Utils.sendMessage(user,
world,
Constants.MESSAGES + "load-add",
Constants.PARAMETER_VALUE, level.getFriendlyName());
}
}
@ -486,7 +512,7 @@ public class ChallengesManager
if (!this.challengeCacheData.containsKey(uniqueID))
{
if (!this.challengeDatabase.objectExists(uniqueID) ||
!this.loadChallenge(this.challengeDatabase.loadObject(uniqueID), false, null, true))
!this.loadChallenge(this.challengeDatabase.loadObject(uniqueID), Bukkit.getWorld(level.getWorld()), false, null, true))
{
this.addon.logError("Cannot find " + uniqueID + " challenge for " + level.getUniqueId());
return false;
@ -640,7 +666,9 @@ public class ChallengesManager
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.migrate-start"));
Utils.sendMessage(user,
world,
Constants.MESSAGES + "migrate-start");
}
else
{
@ -656,7 +684,9 @@ public class ChallengesManager
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.migrate-end"));
Utils.sendMessage(user,
world,
Constants.MESSAGES + "migrate-end");
}
else
{
@ -667,7 +697,9 @@ public class ChallengesManager
{
if (user.isPlayer())
{
Utils.sendMessage(user, user.getTranslation("challenges.messages.migrate-not"));
Utils.sendMessage(user,
world,
Constants.MESSAGES + "migrate-not");
}
else
{
@ -1094,11 +1126,20 @@ public class ChallengesManager
// know how many challenges there were and how many has been done. Then
// remove waiver amount to get count of challenges that still necessary to do.
List<Challenge> previousChallengeList = previousLevel == null ?
Collections.emptyList() :
this.getLevelChallenges(previousLevel);
int challengesToDo = previousLevel == null ? 0 :
(previousLevel.getChallenges().size() - doneChallengeCount - previousLevel.getWaiverAmount());
(previousChallengeList.size() - doneChallengeCount - previousLevel.getWaiverAmount());
List<Challenge> challengeList = this.getLevelChallenges(level);
// As level already contains unique ids of challenges, just iterate through them.
doneChallengeCount = (int) level.getChallenges().stream().filter(playerData::isChallengeDone).count();
doneChallengeCount = (int) challengeList.stream().
map(Challenge::getUniqueId).
filter(playerData::isChallengeDone).
count();
// Mark if level is unlocked
boolean unlocked = previousUnlocked && challengesToDo <= 0;
@ -1107,7 +1148,7 @@ public class ChallengesManager
level,
previousLevel,
challengesToDo,
level.getChallenges().size() == doneChallengeCount,
challengeList.size() == doneChallengeCount,
unlocked));
previousLevel = level;
@ -1143,18 +1184,27 @@ public class ChallengesManager
{
ChallengeLevel previousLevel = levelIndex < 1 ? null : challengeLevelList.get(levelIndex - 1);
List<Challenge> previousChallengeList = previousLevel == null ? Collections.emptyList() :
this.getLevelChallenges(previousLevel);
int challengesToDo = previousLevel == null ? 0 :
(previousLevel.getChallenges().size() - previousLevel.getWaiverAmount()) -
(int) previousLevel.getChallenges().stream().filter(playerData::isChallengeDone).count();
(previousChallengeList.size() - previousLevel.getWaiverAmount()) -
(int) previousChallengeList.stream().map(Challenge::getUniqueId).
filter(playerData::isChallengeDone).count();
List<Challenge> challengeList = this.getLevelChallenges(level);
// As level already contains unique ids of challenges, just iterate through them.
int doneChallengeCount = (int) level.getChallenges().stream().filter(playerData::isChallengeDone).count();
int doneChallengeCount = (int) challengeList.stream().
map(Challenge::getUniqueId).
filter(playerData::isChallengeDone).
count();
return new LevelStatus(
level,
previousLevel,
challengesToDo,
level.getChallenges().size() == doneChallengeCount,
challengeList.size() == doneChallengeCount,
challengesToDo <= 0);
}
}
@ -1182,9 +1232,15 @@ public class ChallengesManager
{
this.addPlayerData(storageDataID);
ChallengesPlayerData playerData = this.playerCacheData.get(storageDataID);
long doneChallengeCount = level.getChallenges().stream().filter(playerData::isChallengeDone).count();
return level.getChallenges().size() == doneChallengeCount;
List<Challenge> challengeList = this.getLevelChallenges(level);
long doneChallengeCount = challengeList.stream().
map(Challenge::getUniqueId).
filter(playerData::isChallengeDone).
count();
return challengeList.size() == doneChallengeCount;
}
@ -1743,11 +1799,11 @@ public class ChallengesManager
{
// Free Challenges hides under FREE level.
return this.islandWorldManager.getAddon(world).map(gameMode ->
this.challengeCacheData.values().stream().
filter(challenge -> challenge.getLevel().equals(FREE) &&
challenge.matchGameMode(gameMode.getDescription().getName())).
sorted(Comparator.comparing(Challenge::getOrder)).
collect(Collectors.toList())).
this.challengeCacheData.values().stream().
filter(challenge -> challenge.getLevel().equals(FREE) &&
challenge.matchGameMode(gameMode.getDescription().getName())).
sorted(Comparator.comparing(Challenge::getOrder)).
collect(Collectors.toList())).
orElse(Collections.emptyList());
}
@ -1758,10 +1814,24 @@ public class ChallengesManager
* @return List with challenges in given level.
*/
public List<Challenge> getLevelChallenges(ChallengeLevel level)
{
return this.getLevelChallenges(level,
this.addon.getChallengesSettings().isIncludeUndeployed());
}
/**
* Level which challenges must be received
* @param level Challenge level.
* @param includeUndeployed if true, then include challenges that are not deployed.
* @return List with challenges in given level.
*/
public List<Challenge> getLevelChallenges(ChallengeLevel level, boolean includeUndeployed)
{
return level.getChallenges().stream().
map(this::getChallenge).
filter(Objects::nonNull).
filter(challenge -> includeUndeployed || challenge.isDeployed()).
sorted(Comparator.comparing(Challenge::getOrder)).
collect(Collectors.toList());
}
@ -1880,7 +1950,9 @@ public class ChallengesManager
*/
public int getChallengeCount(World world)
{
return this.getAllChallenges(world).size();
return (int) this.getAllChallenges(world).stream().
filter(challenge -> this.settings.isIncludeUndeployed() || challenge.isDeployed()).
count();
}

View File

@ -942,14 +942,17 @@ public abstract class CommonPanel
else
{
ChallengeLevel level = levelStatus.getLevel();
List<Challenge> challengeList = this.addon.getChallengesManager().getLevelChallenges(level);
// Check if unlock message should appear.
int doneChallenges = (int) level.getChallenges().stream().
int doneChallenges = (int) challengeList.
stream().
filter(challenge -> this.addon.getChallengesManager().isChallengeComplete(user.getUniqueId(), world, challenge)).
count();
return this.user.getTranslation(reference + "completed-challenges-of",
"[number]", String.valueOf(doneChallenges),
"[max]", String.valueOf(level.getChallenges().size()));
"[max]", String.valueOf(challengeList.size()));
}
}

View File

@ -7,12 +7,12 @@
package world.bentobox.challenges.panel;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.ChatColor;
import org.bukkit.conversations.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
@ -65,7 +65,7 @@ public class ConversationUtils
// Split and check if they exist in valid entries.
String[] accepted = validEntry.toLowerCase().replaceAll("\\s", "").split(",");
return ArrayUtils.contains(accepted, input.toLowerCase());
return Arrays.asList(accepted).contains(input.toLowerCase());
}
@ -81,7 +81,7 @@ public class ConversationUtils
{
String validEntry = user.getTranslation(Constants.CONVERSATIONS + "confirm-string").toLowerCase();
if (ArrayUtils.contains(validEntry.replaceAll("\\s", "").split(","), input.toLowerCase()))
if (Arrays.asList(validEntry.replaceAll("\\s", "").split(",")).contains(input.toLowerCase()))
{
// Add answer to consumer.
consumer.accept(true);
@ -432,7 +432,7 @@ public class ConversationUtils
toLowerCase().replaceAll("\\s", "").
split(",");
if (input != null && ArrayUtils.contains(exit, input.toLowerCase()))
if (input != null && Arrays.asList(exit).contains(input.toLowerCase()))
{
return messagePrompt;
}

View File

@ -156,7 +156,7 @@ public class EditChallengePanel extends CommonPanel
// This will ensure that all main things will be always stored
this.addon.getChallengesManager().saveChallenge(this.challenge);
// If for some reason challenge is not loaded, do it.
this.addon.getChallengesManager().loadChallenge(this.challenge, false, null, true);
this.addon.getChallengesManager().loadChallenge(this.challenge, this.world,false, null, true);
panelBuilder.build();
}
@ -445,8 +445,10 @@ public class EditChallengePanel extends CommonPanel
else
{
Utils.sendMessage(this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "invalid-challenge",
"[challenge]", this.challenge.getFriendlyName()));
this.world,
Constants.CONVERSATIONS + "invalid-challenge",
Constants.PARAMETER_CHALLENGE,
this.challenge.getFriendlyName());
this.challenge.setDeployed(false);
}

View File

@ -212,7 +212,7 @@ public class EditLevelPanel extends CommonPagedPanel<Challenge>
private void buildChallengesPanel(PanelBuilder panelBuilder)
{
List<Challenge> challengeList = this.addon.getChallengesManager().
getLevelChallenges(this.challengeLevel).stream().
getLevelChallenges(this.challengeLevel, true).stream().
filter(challenge -> this.searchString.isBlank() ||
challenge.getFriendlyName().toLowerCase().contains(this.searchString.toLowerCase()) ||
challenge.getUniqueId().toLowerCase().contains(this.searchString.toLowerCase()) ||
@ -784,7 +784,7 @@ public class EditLevelPanel extends CommonPagedPanel<Challenge>
// Get all challenge that is not in current level.
List<Challenge> challengeList = manager.getAllChallenges(this.world);
challengeList.removeAll(manager.getLevelChallenges(this.challengeLevel));
challengeList.removeAll(manager.getLevelChallenges(this.challengeLevel, true));
// Generate descriptions for these challenges
Map<Challenge, List<String>> challengeDescriptionMap = challengeList.stream().
@ -820,7 +820,7 @@ public class EditLevelPanel extends CommonPagedPanel<Challenge>
ChallengesManager manager = this.addon.getChallengesManager();
// Get all challenge that is in current level.
List<Challenge> challengeList = manager.getLevelChallenges(this.challengeLevel);
List<Challenge> challengeList = manager.getLevelChallenges(this.challengeLevel, true);
// Generate descriptions for these challenges
Map<Challenge, List<String>> challengeDescriptionMap = challengeList.stream().

View File

@ -119,6 +119,7 @@ public class EditSettingsPanel extends CommonPanel
panelBuilder.item(11, this.getSettingsButton(Button.GLOW_COMPLETED));
panelBuilder.item(20, this.getSettingsButton(Button.REMOVE_COMPLETED));
panelBuilder.item(29, this.getSettingsButton(Button.VISIBILITY_MODE));
panelBuilder.item(30, this.getSettingsButton(Button.INCLUDE_UNDEPLOYED));
panelBuilder.item(21, this.getSettingsButton(Button.LOCKED_LEVEL_ICON));
@ -414,9 +415,6 @@ public class EditSettingsPanel extends CommonPanel
description.add(this.user.getTranslation(reference +
(this.settings.getVisibilityMode().equals(VisibilityMode.HIDDEN) ? "enabled" : "disabled")) +
this.user.getTranslation(reference + "hidden"));
description.add(this.user.getTranslation(reference +
(this.settings.getVisibilityMode().equals(VisibilityMode.TOGGLEABLE) ? "enabled" : "disabled")) +
this.user.getTranslation(reference + "toggleable"));
if (this.settings.getVisibilityMode().equals(VisibilityMode.VISIBLE))
{
@ -454,6 +452,22 @@ public class EditSettingsPanel extends CommonPanel
description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-cycle"));
description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-cycle"));
}
case INCLUDE_UNDEPLOYED -> {
description.add(this.user.getTranslation(reference +
(this.settings.isIncludeUndeployed() ? "enabled" : "disabled")));
icon = new ItemStack(Material.BARREL);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setIncludeUndeployed(!this.settings.isIncludeUndeployed());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
this.addon.saveSettings();
return true;
};
glow = this.settings.isIncludeUndeployed();
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
}
default -> {
icon = new ItemStack(Material.PAPER);
clickHandler = null;
@ -557,6 +571,10 @@ public class EditSettingsPanel extends CommonPanel
LOCKED_LEVEL_ICON,
SHOW_TITLE,
TITLE_SHOWTIME,
/**
* This allows to switch between counting/not couting undeployed challenges.
*/
INCLUDE_UNDEPLOYED,
/**
* This allows to switch between different challenges visibility modes.
*/

View File

@ -166,8 +166,9 @@ public class LibraryPanel extends CommonPagedPanel<LibraryEntry>
{
if (this.libraryEntries.isEmpty())
{
Utils.sendMessage(this.user, this.user.getTranslation(
Constants.ERRORS + "no-library-entries"));
Utils.sendMessage(this.user,
this.world,
Constants.ERRORS + "no-library-entries");
return;
}
@ -311,8 +312,9 @@ public class LibraryPanel extends CommonPagedPanel<LibraryEntry>
{
this.blockedForDownland = true;
Utils.sendMessage(this.user, this.user.getTranslation(
Constants.MESSAGES + "start-downloading"));
Utils.sendMessage(this.user,
this.world,
Constants.MESSAGES + "start-downloading");
// Run download task after 5 ticks.
this.updateTask = this.addon.getPlugin().getServer().getScheduler().

View File

@ -77,7 +77,7 @@ public class ChallengesPanel extends CommonPanel
if (!this.containsChallenges)
{
this.addon.logError("There are no challenges set up!");
Utils.sendMessage(user, user.getTranslation(Constants.ERRORS + "no-challenges"));
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "no-challenges");
return;
}
@ -130,7 +130,7 @@ public class ChallengesPanel extends CommonPanel
{
if (this.lastSelectedLevel != null)
{
this.challengeList = this.manager.getLevelChallenges(this.lastSelectedLevel.getLevel());
this.challengeList = this.manager.getLevelChallenges(this.lastSelectedLevel.getLevel(), true);
if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges())
{

View File

@ -265,18 +265,21 @@ public class TryToComplete
// Send message about first completion only if it is completed only once.
if (result.getFactor() == 1)
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.messages.you-completed-challenge",
"[value]", this.challenge.getFriendlyName()));
Utils.sendMessage(this.user,
this.world,
Constants.MESSAGES + "you-completed-challenge",
Constants.PARAMETER_VALUE, this.challenge.getFriendlyName());
}
if (this.addon.getChallengesSettings().isBroadcastMessages())
{
Bukkit.getOnlinePlayers().stream().
map(User::getInstance).
forEach(user -> Utils.sendMessage(user, user.getTranslation(
"challenges.messages.name-has-completed-challenge",
forEach(user -> Utils.sendMessage(user,
this.world,
Constants.MESSAGES + "name-has-completed-challenge",
Constants.PARAMETER_NAME, this.user.getName(),
"[value]", this.challenge.getFriendlyName())));
Constants.PARAMETER_VALUE, this.challenge.getFriendlyName()));
}
// sends title to player on challenge completion
@ -327,14 +330,18 @@ public class TryToComplete
if (result.getFactor() > 1)
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.messages.you-repeated-challenge-multiple",
"[value]", this.challenge.getFriendlyName(),
"[count]", Integer.toString(result.getFactor())));
Utils.sendMessage(this.user,
this.world,
Constants.MESSAGES + "you-repeated-challenge-multiple",
Constants.PARAMETER_VALUE, this.challenge.getFriendlyName(),
"[count]", Integer.toString(result.getFactor()));
}
else
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.messages.you-repeated-challenge",
"[value]", this.challenge.getFriendlyName()));
Utils.sendMessage(this.user,
this.world,
Constants.MESSAGES + "you-repeated-challenge",
Constants.PARAMETER_VALUE, this.challenge.getFriendlyName());
}
}
@ -372,17 +379,20 @@ public class TryToComplete
// Run commands
this.runCommands(level.getRewardCommands());
Utils.sendMessage(this.user, this.user.getTranslation("challenges.messages.you-completed-level",
"[value]", level.getFriendlyName()));
Utils.sendMessage(this.user,
this.world,
Constants.MESSAGES + "you-completed-level",
Constants.PARAMETER_VALUE, level.getFriendlyName());
if (this.addon.getChallengesSettings().isBroadcastMessages())
{
Bukkit.getOnlinePlayers().stream().
map(User::getInstance).
forEach(user -> Utils.sendMessage(user, user.getTranslation(
"challenges.messages.name-has-completed-level",
forEach(user -> Utils.sendMessage(user,
this.world,
Constants.MESSAGES + "name-has-completed-level",
Constants.PARAMETER_NAME, this.user.getName(),
"[value]", level.getFriendlyName())));
Constants.PARAMETER_VALUE, level.getFriendlyName()));
}
this.manager.setLevelComplete(this.user, this.world, level);
@ -447,7 +457,8 @@ public class TryToComplete
if (sumEverything != removedAmount)
{
Utils.sendMessage(this.user,
this.user.getTranslation("challenges.errors.cannot-remove-items"));
this.world,
Constants.ERRORS + "cannot-remove-items");
result.removedItems = removedItems;
result.meetsRequirements = false;
@ -495,45 +506,54 @@ public class TryToComplete
}
}
case ITEM, BLOCK -> {
int statistic = this.user.getPlayer().getStatistic(requirements.getStatistic());
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;
}
else
{
this.user.getPlayer().setStatistic(requirements.getStatistic(),
requirements.getMaterial(),
statistic - removeAmount);
removeAmount = 0;
int statistic = this.user.getPlayer().getStatistic(requirements.getStatistic(),
requirements.getMaterial());
if (removeAmount >= statistic)
{
this.user.getPlayer()
.setStatistic(requirements.getStatistic(), requirements.getMaterial(), 0);
removeAmount -= statistic;
}
else
{
this.user.getPlayer().setStatistic(requirements.getStatistic(),
requirements.getMaterial(),
statistic - removeAmount);
removeAmount = 0;
}
}
}
case ENTITY -> {
int statistic = this.user.getPlayer().getStatistic(requirements.getStatistic());
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;
}
else
{
this.user.getPlayer().setStatistic(requirements.getStatistic(),
requirements.getEntity(),
statistic - removeAmount);
removeAmount = 0;
int statistic = this.user.getPlayer().getStatistic(requirements.getStatistic(),
requirements.getEntity());
if (removeAmount >= statistic)
{
this.user.getPlayer().setStatistic(requirements.getStatistic(), requirements.getEntity(), 0);
removeAmount -= statistic;
}
else
{
this.user.getPlayer().setStatistic(requirements.getStatistic(),
requirements.getEntity(),
statistic - removeAmount);
removeAmount = 0;
}
}
}
}
@ -577,45 +597,57 @@ public class TryToComplete
}
}
case ITEM, BLOCK -> {
int statistic = player.getStatistic(requirements.getStatistic());
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);
}
else
{
player.setStatistic(requirements.getStatistic(),
requirements.getMaterial(),
statistic - removeAmount);
removeAmount = 0;
int statistic = player.getStatistic(requirements.getStatistic(),
requirements.getMaterial());
if (removeAmount >= statistic)
{
removeAmount -= statistic;
player.setStatistic(requirements.getStatistic(),
requirements.getMaterial(),
0);
}
else
{
player.setStatistic(requirements.getStatistic(),
requirements.getMaterial(),
statistic - removeAmount);
removeAmount = 0;
}
}
}
case ENTITY -> {
int statistic = player.getStatistic(requirements.getStatistic());
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);
}
else
{
player.setStatistic(requirements.getStatistic(),
requirements.getEntity(),
statistic - removeAmount);
removeAmount = 0;
int statistic = player.getStatistic(requirements.getStatistic(),
requirements.getEntity());
if (removeAmount >= statistic)
{
removeAmount -= statistic;
player.setStatistic(requirements.getStatistic(),
requirements.getEntity(),
0);
}
else
{
player.setStatistic(requirements.getStatistic(),
requirements.getEntity(),
statistic - removeAmount);
removeAmount = 0;
}
}
}
}
@ -640,18 +672,18 @@ public class TryToComplete
// Check the world
if (!this.challenge.isDeployed())
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.not-deployed"));
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "not-deployed");
result = EMPTY_RESULT;
}
else if (maxTimes < 1)
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.not-valid-integer"));
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "not-valid-integer");
result = EMPTY_RESULT;
}
else if (Util.getWorld(this.world) != Util.getWorld(this.user.getWorld()) ||
!this.challenge.matchGameMode(Utils.getGameMode(this.world)))
{
Utils.sendMessage(this.user, this.user.getTranslation("general.errors.wrong-world"));
Utils.sendMessage(this.user, this.world, "general.errors.wrong-world");
result = EMPTY_RESULT;
}
// Player is not on island
@ -659,7 +691,7 @@ public class TryToComplete
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"));
Utils.sendMessage(this.user, this.world, Constants.MESSAGES + "not-on-island");
result = EMPTY_RESULT;
}
// Check player permission
@ -667,27 +699,27 @@ public class TryToComplete
map(i -> i.isAllowed(this.user, ChallengesAddon.CHALLENGES_ISLAND_PROTECTION)).
orElse(false))
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.no-rank"));
Utils.sendMessage(this.user, this.world, Constants.MESSAGES + "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())))
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.challenge-level-not-available"));
Utils.sendMessage(this.user, this.world, Constants.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())
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.not-repeatable"));
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "not-repeatable");
result = EMPTY_RESULT;
}
// Check repeatability
else if (!this.challenge.isRepeatable() && this.manager.isChallengeComplete(this.user, this.world, this.challenge))
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.not-repeatable"));
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "not-repeatable");
result = EMPTY_RESULT;
}
// Check if timeout is not broken
@ -696,22 +728,22 @@ public class TryToComplete
long missing = this.manager.getLastCompletionDate(this.user, this.world, challenge) +
this.challenge.getTimeout() - System.currentTimeMillis();
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.timeout",
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "timeout",
"[timeout]", Utils.parseDuration(Duration.ofMillis(this.challenge.getTimeout()), this.user),
"[wait-time]", Utils.parseDuration(Duration.ofMillis(missing), this.user)));
"[wait-time]", Utils.parseDuration(Duration.ofMillis(missing), this.user));
result = EMPTY_RESULT;
}
// Check environment
else if (!this.challenge.getEnvironment().isEmpty() &&
!this.challenge.getEnvironment().contains(this.user.getWorld().getEnvironment()))
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.wrong-environment"));
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "wrong-environment");
result = EMPTY_RESULT;
}
// Check permission
else if (!this.checkPermissions())
{
Utils.sendMessage(this.user, this.user.getTranslation("general.errors.no-permission"));
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "no-permission");
result = EMPTY_RESULT;
}
else if (type.equals(ChallengeType.INVENTORY_TYPE))
@ -806,9 +838,9 @@ public class TryToComplete
String alert = "Running command '" + cmd + "' as " + this.user.getName();
this.addon.getLogger().info(alert);
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()).
replaceAll(Constants.ESC + Constants.PARAMETER_PLAYER, this.user.getName()).
replaceAll(Constants.ESC + Constants.PARAMETER_OWNER, owner).
replaceAll(Constants.ESC + Constants.PARAMETER_NAME, island == null || island.getName() == null ? "" : island.getName()).
trim();
try
{
@ -829,9 +861,9 @@ public class TryToComplete
try
{
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()).
cmd = cmd.replaceAll(Constants.ESC + Constants.PARAMETER_PLAYER, this.user.getName()).
replaceAll(Constants.ESC + Constants.PARAMETER_OWNER, owner).
replaceAll(Constants.ESC + Constants.PARAMETER_NAME, island == null || island.getName() == null ? "" : island.getName()).
trim();
if (!this.addon.getServer().dispatchCommand(this.addon.getServer().getConsoleSender(), cmd))
@ -908,9 +940,9 @@ public class TryToComplete
if (numInInventory < required.getAmount())
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.not-enough-items",
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "not-enough-items",
"[items]",
Utils.prettifyObject(required, this.user)));
Utils.prettifyObject(required, this.user));
return EMPTY_RESULT;
}
@ -1173,13 +1205,16 @@ public class TryToComplete
return new ChallengeResult().setMeetsRequirements().setCompleteFactor(factor).setBlockQueue(blockFromWorld);
}
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.not-close-enough",
"[number]", String.valueOf(this.getIslandRequirements().getSearchRadius())));
Utils.sendMessage(this.user,
this.world,
Constants.ERRORS + "not-close-enough",
Constants.PARAMETER_NUMBER, String.valueOf(this.getIslandRequirements().getSearchRadius()));
blocks.forEach((k, v) -> Utils.sendMessage(this.user,
this.user.getTranslation("challenges.errors.you-still-need",
"[amount]", String.valueOf(v),
"[item]", Utils.prettifyObject(k, this.user))));
this.world,
Constants.ERRORS + "you-still-need",
"[amount]", String.valueOf(v),
"[item]", Utils.prettifyObject(k, this.user)));
// kick garbage collector
@ -1259,9 +1294,11 @@ public class TryToComplete
}
minimalRequirements.forEach((reqEnt, amount) ->
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.you-still-need",
Utils.sendMessage(this.user,
this.world,
Constants.ERRORS + "you-still-need",
"[amount]", String.valueOf(amount),
"[item]", Utils.prettifyObject(reqEnt, this.user))));
"[item]", Utils.prettifyObject(reqEnt, this.user)));
// Kick garbage collector
entitiesFound.clear();
@ -1342,42 +1379,47 @@ public class TryToComplete
if (!this.addon.isLevelProvided() && requirements.getRequiredIslandLevel() != 0)
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.missing-addon"));
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "missing-addon");
}
else if (!this.addon.isEconomyProvided() &&
requirements.getRequiredMoney() != 0)
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.missing-addon"));
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "missing-addon");
}
else if (this.addon.isEconomyProvided() && requirements.getRequiredMoney() < 0)
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.incorrect"));
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "incorrect");
}
else if (this.addon.isEconomyProvided() &&
!this.addon.getEconomyProvider().has(this.user, requirements.getRequiredMoney()))
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.not-enough-money",
"[value]",
Double.toString(requirements.getRequiredMoney())));
Utils.sendMessage(this.user,
this.world,
Constants.ERRORS + "not-enough-money",
Constants.PARAMETER_VALUE, Double.toString(requirements.getRequiredMoney()));
}
else if (requirements.getRequiredExperience() < 0)
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.incorrect"));
Utils.sendMessage(this.user, this.world, Constants.ERRORS + "incorrect");
}
else if (this.user.getPlayer().getTotalExperience() < requirements.getRequiredExperience() &&
this.user.getPlayer().getGameMode() != GameMode.CREATIVE)
{
// Players in creative gamemode has infinite amount of EXP.
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.not-enough-experience",
"[value]",
Integer.toString(requirements.getRequiredExperience())));
Utils.sendMessage(this.user,
this.world,
Constants.ERRORS + "not-enough-experience",
Constants.PARAMETER_VALUE,
Integer.toString(requirements.getRequiredExperience()));
}
else if (this.addon.isLevelProvided() &&
this.addon.getLevelAddon().getIslandLevel(this.world, this.user.getUniqueId()) < requirements.getRequiredIslandLevel())
{
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.island-level",
Utils.sendMessage(this.user,
this.world,
Constants.ERRORS + "island-level",
TextVariables.NUMBER,
String.valueOf(requirements.getRequiredIslandLevel())));
String.valueOf(requirements.getRequiredIslandLevel()));
}
else
{
@ -1440,10 +1482,35 @@ public class TryToComplete
if (currentValue < requirements.getAmount())
{
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)));
switch (Objects.requireNonNull(requirements.getStatistic()).getType())
{
case ITEM, BLOCK -> {
Utils.sendMessage(this.user,
this.world,
Constants.ERRORS + "requirement-not-met-material",
TextVariables.NUMBER, String.valueOf(requirements.getAmount()),
"[statistic]", Utils.prettifyObject(requirements.getStatistic(), this.user),
"[material]", Utils.prettifyObject(requirements.getMaterial(), this.user),
Constants.PARAMETER_VALUE, String.valueOf(currentValue));
}
case ENTITY -> {
Utils.sendMessage(this.user,
this.world,
Constants.ERRORS + "requirement-not-met-entity",
TextVariables.NUMBER, String.valueOf(requirements.getAmount()),
"[statistic]", Utils.prettifyObject(requirements.getStatistic(), this.user),
"[entity]", Utils.prettifyObject(requirements.getEntity(), this.user),
Constants.PARAMETER_VALUE, String.valueOf(currentValue));
}
default -> {
Utils.sendMessage(this.user,
this.world,
Constants.ERRORS + "requirement-not-met",
TextVariables.NUMBER, String.valueOf(requirements.getAmount()),
"[statistic]", Utils.prettifyObject(requirements.getStatistic(), this.user),
Constants.PARAMETER_VALUE, String.valueOf(currentValue));
}
}
}
else
{

View File

@ -223,4 +223,9 @@ public class Constants
* Reference string to challenge parameter in translations.
*/
public static final String PARAMETER_CHALLENGE = "[challenge]";
/**
* Regex escape chars.
*/
public static final String ESC = "\\";
}

View File

@ -186,11 +186,14 @@ public class Utils
* Send given message to user and add prefix to the start of the message.
*
* @param user User who need to receive message.
* @param message String of message that must be send.
* @param world Reference to world where message must be send.
* @param translation String of message that must be send.
* @param parameters Parameters that must be added to translation.
*/
public static void sendMessage(User user, String message)
public static void sendMessage(User user, World world, String translation, String... parameters)
{
user.sendMessage(user.getTranslation(Constants.CONVERSATIONS + "prefix") + message);
user.sendMessage(user.getTranslation(world, Constants.CONVERSATIONS + "prefix") +
user.getTranslation(world, translation, parameters));
}

View File

@ -683,6 +683,15 @@ challenges:
visible: "Show visible challenges"
hidden: "Show all challenges"
toggleable: "Allow toggling"
include_undeployed:
name: "&f&l Include Undeployed Challenges"
description: |-
&7 Indicates if undeployed
&7 challenges should be
&7 counted towards level
&7 completion.
enabled: "&2 Enabled"
disabled: "&c Disabled"
download:
name: "&f&l Download Libraries"
description: |-
@ -1204,6 +1213,8 @@ challenges:
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]. "
requirement-not-met-entity: "&c This challenge requires [statistic] [entity] to have [number]. You have only [value]. "
requirement-not-met-material: "&c This challenge requires [statistic] [material] to have [number]. You have only [value]. "
# # Showcase for manual material translation
# materials:
# # Names should be lowercase.

View File

@ -2,6 +2,9 @@
meta:
authors:
- BONNe
# Attention for Chinese translation
# 中文翻译须知在本人2023年1月19日接手前上一位翻译者疑似用机翻软件翻译了全文包括变量在内的所有文字。
# 感谢原作者BONNe进行了修改同时笔者对管理员部分的翻译和玩家全部的翻译进行了订正。时间仓促请君斧正。
challenges:
commands:
admin:
@ -33,14 +36,14 @@ challenges:
gamemode-gui: "&0&l 选择游戏模式"
multiple-gui: "&0&l 多少次?"
admin-gui: "&0&l 挑战管理菜单"
edit-challenge: "&0&l 编辑 [挑战]"
edit-level: "&0&l 编辑 [等级]"
edit-challenge: "&0&l 编辑 [challenge]"
edit-level: "&0&l 编辑 [level]"
settings: "&0&l 设置"
choose-challenge: "&0&l 选择挑战"
choose-level: "&0&l 选择级别"
choose-player: "&0&l 选择播放器"
choose-player: "&0&l 选择玩家"
library: "&0&l 库"
manage-blocks: "&0&l 管理块"
manage-blocks: "&0&l 管理块"
manage-entities: "&0&l 管理实体"
type-selector: "&0&l 挑战类型选择器"
item-selector: "&0&l 项目选择器"
@ -51,10 +54,10 @@ challenges:
environment-selector: "&0&l 环境选择器"
buttons:
free-challenges:
name: "&f&l 免费挑战"
name: "&f&l 自由挑战"
description: |-
&7 显示列表
&7 免费挑战
&7 自由挑战
return:
name: "&f&l 返回"
description: |-
@ -62,20 +65,20 @@ challenges:
&7 或退出 GUI
previous:
name: "&f&l 上一页"
description: "&7 切换到 &e [数字] &7 页面"
description: "&7 切换到 &e [number] &7 页"
next:
name: "&f&l 下一页"
description: "&7 切换到 &e [数字] &7 页面"
description: "&7 切换到 &e [number] &7 页"
reduce:
name: "&f&l 减少"
description: "&7 减少 &e [数字]"
description: "&7 减少 &e [number]"
increase:
name: "&f&l 增加"
description: "&7 增加 &e [数字]"
description: "&7 增加 &e [number]"
accept:
name: "&f&l 完成"
description: |-
&7 完成挑战 &e [数字]
&7 完成挑战 &e [number]
&7次(-s)
quit:
name: "&f&l 退出"
@ -97,10 +100,10 @@ challenges:
&7 启动一个进程
&7 创造了一个新的挑战。
add_level:
name: "&f&l 创建关卡"
name: "&f&l 创建级别"
description: |-
&7 启动一个进程
&7 创造了一个新的水平
&7 创造了一个新的级别
edit_challenge:
name: "&f&l 编辑挑战"
description: |-
@ -117,7 +120,7 @@ challenges:
&7 允许选择和删除
&7 挑战。
delete_level:
name: "&f&l 删除级"
name: "&f&l 删除"
description: |-
&7 允许选择和删除
&7 一个级别。
@ -146,7 +149,7 @@ challenges:
name: "&f&l 库"
description: |-
&7 打开公共
&7 挑战图书馆
&7 挑战
import_database:
name: "&f&l 导入数据库"
description: |-
@ -158,7 +161,7 @@ challenges:
&7 允许导入模板
&7 文件有挑战。
export_challenges:
name: "&f&l 挑战"
name: "&f&l 出挑战"
description: |-
&7 允许导出数据库
&7 到本地文件。
@ -184,7 +187,7 @@ challenges:
description: |-
&7 允许更改
&7 显示名称。
value: "&7 当前:&r [名称]"
value: "&7 当前:&r [name]"
remove_on_complete:
name: "&f&l 完成后隐藏"
description: |-
@ -209,14 +212,14 @@ challenges:
enabled: "&2"
disabled: "C"
order:
name: "&f&l 订单"
name: "&f&l 顺序"
description: |-
&7 允许改变顺序
&7 个对象。
&7 相同数量的对象
&7 将由他们订购
&7 唯一 ID 名称。
value: "&7 当前订单:&e [数字]"
value: "&7 当前顺序:&e [number]"
icon:
name: "&f&l 图标"
description: |-
@ -234,82 +237,83 @@ challenges:
&7 权限
&7 挑战是可完成的。
title: "&7 权限:"
permission: " &8 - [权限]"
permission: " &8 - [permission]"
none: "&7 权限未设置。"
remove_entities:
name: "&f&l 删除实体"
description: |-
&7 允许切换
&7 所需实体将
&7 从世界中移除
&7 完成
&7 挑战。
&7 所需要的
&7 在完成挑战
&7
&7 从世界中移除的实体
enabled: "&2 已启用"
disabled: "&c 已禁用"
required_entities:
name: "&f&l 必需的实体"
description: |-
&7 允许根据需要进行更改
&7 实体为此
&7 挑战是可完成的。
&7 允许
&7 为完成这个挑战。
&7 所需要的实体进行更改
title: "&7 实体:"
list: " &8 - [数字] x [实体]"
list: " &8 - [number] x [entity]"
none: "&7 不添加实体。"
remove_blocks:
name: "&f&l 移除方块"
description: |-
&7 允许切换
&7 所需块将
&7 从世界中移除
&7 完成
&7 挑战。
&7 所需
&7 在完成挑战
&7
&7 从世界中移除的方块
enabled: "&2 已启用"
disabled: "&c 已禁用"
required_blocks:
name: "&f&l 所需块"
name: "&f&l 所需块"
description: |-
&7 允许根据需要进行更改
&7 块为此
&7 挑战是可完成的。
&7 允许更改
&7 为完成挑战所需要的
&7 方块
title: "&7 块:"
list: " &8 - [数量] x [块]"
list: " &8 - [number] x [block]"
none: "&7 块不被添加。"
search_radius:
name: "&f&l 搜索半径"
description: |-
&7 允许改变半径
&7 周围的玩家
&7 块和/或实体是
&7 检测到。
value: "&7 当前距离:&e [数字]"
&7 允许更改任务所需的方块
&7 或实体的检测半径。
&7 (部分任务需要玩家周围
&7 有一定数量的方块/实体)
value: "&7 当前距离:&e [number]"
remove_items:
name: "&f&l 删除项目"
name: "&f&l 删除道具"
description: |-
&7 允许切换
&7 项必填项
&7 从库存中移除
&7 完成后
&7 挑战
&7 挑战所需道具
&7 在挑战完成后
&7 是否从背包中
&7 移除
enabled: "&2 已启用"
disabled: "&c 已禁用"
required_items:
name: "&f&l 必填项目"
name: "&f&l 需求道具"
description: |-
&7 允许根据需要进行更改
&7 项为此
&7 挑战是可完成的。
title: "&7 项:"
list: " &8 - [数量] x [项目]"
list: " &8 - [number] x [item]"
none: "&7 项目未添加。"
add_ignored_meta:
name: "&f&l 添加忽略元数据"
#翻译到这了下面的都是没有人工翻译的cirno看了也无语
description: |-
&7 允许添加哪个
&7 项应忽略
&7 任何元数据
&7 分配给他们。
title: "&7 项:"
list: " &8 - [数量] x [项目]"
list: " &8 - [number] x [item]"
none: "&7 项目未添加。"
remove_ignored_meta:
name: "&f&l 删除忽略元数据"
@ -323,7 +327,7 @@ challenges:
description: |-
&7 允许切换
&7 所需经验将
&7 播放器中移除
&7 玩家中移除
&7 完成后
&7 挑战。
enabled: "&2 已启用"
@ -333,21 +337,21 @@ challenges:
description: |-
&7 允许更改
&7 所需经验
&7 播放器
value: "&7 当前经验:&e [数字]"
&7 玩家
value: "&7 当前经验:&e [number]"
required_level:
name: "&f&l 所需岛屿等级"
description: |-
&7 允许更改
&7 所需岛屿等级
&7 挑战。
value: "&7 当前级别:&e [数字]"
value: "&7 当前级别:&e [number]"
remove_money:
name: "&f&l 移除金钱"
description: |-
&7 允许切换
&7 所需资金将
&7 播放器中移除
&7 玩家中移除
&7 帐号完成后
&7 挑战。
enabled: "&2 已启用"
@ -358,21 +362,21 @@ challenges:
&7 允许更改
&7 玩家需要的钱
&7 说明了挑战。
value: "&7 当前值:&e [数字]"
value: "&7 当前值:&e [number]"
statistic:
name: "&f&l 统计"
description: |-
&7 允许更改
&7 统计类型是
&7 签入了这个挑战。
value: "&7 当前值:&e [统计]"
value: "&7 当前值:&e [statistic]"
statistic_amount:
name: "&f&l 目标值"
description: |-
&7 允许更改
&7 统计目标值
&7 必须满足。
value: "&7 当前值:&e [数字]"
value: "&7 当前值:&e [number]"
remove_statistic:
name: "&f&l 减少统计量"
description: |-
@ -387,19 +391,19 @@ challenges:
description: |-
&7 允许更改
&7 统计目标块。
value: "&7 当前块:&e []"
value: "&7 当前块:&e [block]"
statistic_items:
name: "&f&l 目标项目"
description: |-
&7 允许更改
&7 统计目标项。
value: "&7 当前项目:&e [项目]"
value: "&7 当前项目:&e [item]"
statistic_entities:
name: "&f&l 目标实体"
description: |-
&7 允许更改
&7 统计目标实体。
value: "&7 当前实体:&e [实体]"
value: "&7 当前实体:&e [entity]"
reward_text:
name: "&f&l 奖励文本"
description: |-
@ -420,7 +424,7 @@ challenges:
&7 允许更改奖励
&7 项。
title: "&7 项:"
list: " &8 - [数量] x [项目]"
list: " &8 - [number] x [item]"
none: "&7 项目未添加。"
repeat_reward_items:
name: "&f&l 重复奖励项目"
@ -429,35 +433,35 @@ challenges:
&7 奖励物品
&7 挑战。
title: "&7 项:"
list: " &8 - [数量] x [项目]"
list: " &8 - [number] x [item]"
none: "&7 项目未添加。"
reward_experience:
name: "&f&l 奖励体验"
description: |-
&7 允许更改
&7 奖励经验
&7 播放器
value: "&7 奖励经验:&e [数字]"
&7 玩家
value: "&7 奖励经验:&e [number]"
repeat_reward_experience:
name: "&f&l 重复奖励体验"
description: |-
&7 允许更改
&7 重复奖励经验
&7 播放器
value: "&7 奖励经验:&e [数字]"
&7 玩家
value: "&7 奖励经验:&e [number]"
reward_money:
name: "&f&l 奖励金"
description: |-
&7 允许更改
&7 奖励金钱。
value: "&7 当前值:&e [数字]"
value: "&7 当前值:&e [number]"
repeat_reward_money:
name: "&f&l 重复奖励金"
description: |-
&7 允许更改
&7 重复奖励金
&7 挑战。
value: "&7 当前值:&e [数字]"
value: "&7 当前值:&e [number]"
reward_commands:
name: "&f&l 奖励命令"
description: |-
@ -509,7 +513,7 @@ challenges:
&7 允许更改
&7 重复次数
&7 挑战。
value: "&7 当前值:&e [数字]"
value: "&7 当前值:&e [number]"
cool_down:
name: "&f&l 冷却"
description: |-
@ -518,7 +522,7 @@ challenges:
&7 之间必须等待
&7 可重复挑战
&7 完成。
value: "&7 当前值:&e [时间]"
value: "&7 当前值:&e [time]"
challenges:
name: "&f&l 挑战"
description: |-
@ -531,7 +535,7 @@ challenges:
&7 的挑战
&7 未完成
&7 解锁下一个级别。
value: "&7 当前值:&e [数字]"
value: "&7 当前值:&e [number]"
add_challenges:
name: "&f&l 添加挑战(-s)"
description: |-
@ -626,13 +630,13 @@ challenges:
&7 在用户数据中。
&7 0 表示数据将
&7 不会被删除。
value: "&7 当前值:&e [数字]"
value: "&7 当前值:&e [number]"
title_showtime:
name: "&f&l 标题放映时间"
description: |-
&7 该标题的刻度数
&7 将显示给玩家。
value: "&7 当前值:&e [数字]"
value: "&7 当前值:&e [number]"
active_world_list:
name: "&f&l 仅显示活跃世界"
description: |-
@ -658,16 +662,16 @@ challenges:
name: "&f&l 下载库"
description: |-
&7 可手动更新
&7 挑战图书馆
&7 挑战
enabled: "&2 清除缓存"
disabled: "&c 不清除缓存"
player:
name: "&f&l [名称]"
description: "&7 岛主:[所有者]"
name: "&f&l [name]"
description: "&7 岛主:[owner]"
members: "&7 岛成员:"
member: "&8 - [名称]"
member: "&8 - [name]"
no-island: |-
&c 播放器没有
&c 玩家没有
&c 一个岛屿。
player_list:
name: "&f&l 选择用户列表"
@ -691,9 +695,9 @@ challenges:
&7 个选定的块
&7 来自列表。
title: "&7 精选材料:"
material: "&8 - [材质]"
material: "&8 - [material]"
material:
name: "&f&l [材质]"
name: "&f&l [material]"
description: "&7 材质 ID[id]"
selected: "&2 已选择"
add_entity:
@ -705,7 +709,7 @@ challenges:
name: "&f&l 换鸡蛋"
description: |-
&7 允许从
&7 鸡蛋给暴徒头。
&7 鸡蛋给怪物头。
remove_entity:
name: "&f&l 删除实体"
description: |-
@ -713,9 +717,9 @@ challenges:
&7 个选定的实体
&7 来自列表。
title: "&7 选定实体:"
entity: "&8 - [实体]"
entity: "&8 - [entity]"
entity:
name: "&f&l [实体]"
name: "&f&l [entity]"
description: "&7 实体 ID[id]"
selected: "&2 已选择"
inventory_type:
@ -728,7 +732,7 @@ challenges:
description: |-
&7 检查的挑战
&7 周围的方块或实体
&7 播放器
&7 玩家
other_type:
name: "&f&l 其他类型"
description: |-
@ -756,40 +760,41 @@ challenges:
&7 返回选中的元素
&7 并打开以前的 GUI。
title: "&7 已选择:"
element: "&8 - [元素]"
element: "&8 - [element]"
statistic_element:
name: "&f&l [统计]"
description: "[描述]"
name: "&f&l [statistic]"
description: "[description]"
environment_element:
name: "&f&l [环境]"
description: "[描述]"
name: "&f&l [environment]"
description: "[description]"
search:
name: "&f&l 搜索"
description: |-
&7 允许搜索
&7 元素与输入
&7 文本值。
search: "&b 值:[值]"
search: "&b 值:[value]"
#上面的都是没有翻译的,cirno看了直摇头
tips:
click-to-select: "&e 单击 &7 进行选择。"
click-to-choose: "&e 单击 &7 进行选择。"
click-to-complete: "&e 击 &7 完成。"
right-click-multiple-open: "&e 右击 &7 选择完成数。"
shift-left-click-to-complete-all: "&e Shift 单击 &7 完成所有操作。"
left-click-to-accept: "&e 左键单击 &7 完成。"
click-to-complete: "&e 击 &7 完成。"
right-click-multiple-open: "&e 右击 &7 选择完成挑战的次数。"
shift-left-click-to-complete-all: "&e 按住Shift并左击 &7 一键完成(根据背包中所需道具数量)。"
left-click-to-accept: "&e 左击 &7 接受。"
right-click-to-write: "&e 右击 &7 写入。"
click-to-reduce: "&e 点击 &7 减少。"
click-to-increase: "&e 点击 &7 增加。"
click-to-return: "&e 单击 &7 返回。"
click-to-quit: "&e 点击 &7 退出。"
click-to-wipe: "&e 单击 &7 除。"
left-click-to-wipe: "&e 左键单击 &7 除。"
click-to-wipe: "&e 单击 &7 除。"
left-click-to-wipe: "&e 左键单击 &7 除。"
right-click-to-switch: "&e 右键 &7 切换。"
click-to-open: "&e 点击 &7 打开。"
click-to-export: "&e 点击 &7 导出。"
click-to-create: "&e 点击 &7 创建。"
left-click-to-open: "&e 左键单击 &7 打开。"
right-click-to-reset-all: "&e 右键单击 &7 擦除所有内容。"
right-click-to-reset-all: "&e 右键单击 &7 重置所有内容。"
click-to-toggle: "&e 单击 &7 进行切换。"
click-to-change: "&e 单击 &7 进行更改。"
shift-click-to-reset: "&e Shift 单击 &7 进行重置。"
@ -818,110 +823,111 @@ challenges:
descriptions:
challenge:
lore: |-
[描述]
[地位]
[冷却]
[要求]
[奖励]
[description]
[status]
[cooldown]
[requirements]
[rewards]
status:
completed: "&2&l 已完成"
completed-times: "&2 完成 &7&l [数字] &r&2 时间(-s)"
completed-times-of: "&2 已完成 &7&l [次数] &r&2 共 &7&l [最多] &r&2 次"
completed-times-reached: "&2&l 全部完成 &7 [最多] &2 次"
#原来的time(-s)意思是如果完成复数次就是times不是时间里秒的含义
completed-times: "&2 完成 &7&l [number] &r&2 次"
completed-times-of: "&2 已完成 &7&l [number] &r&2 共 &7&l [max] &r&2 次"
completed-times-reached: "&2&l 全部完成 &7 [max] &2 次"
cooldown:
lore: |-
[超时]
[等待时间]
timeout: "&7&l 冷却时间:&r&7 [时间]"
wait-time: "&c&l 可用时间:&r&c [时间]"
in-days: "[数量] d"
in-hours: "[数量]小时"
in-minutes: "[数量] 分钟"
in-seconds: "[数字] s"
[timeout]
[wait-time]
timeout: "&7&l 冷却时间:&r&7 [time]"
wait-time: "&c&l 等待时间:&r&c [time]"
in-days: "[number] d"
in-hours: "[number]小时"
in-minutes: "[number] 分钟"
in-seconds: "[number] s"
requirements:
lore: |-
[环境]
[类型要求]
[权限]
environment-single: "&7 限于 [环境]"
[environment]
[type-requirement]
[permission]
environment-single: "&7 限于 [environment]"
environment-title: "&7 限于:"
environment-list: " &7 - &e [环境]"
environment-list: " &7 - &e [environment]"
permission-single: "&c 需要 [permissions] 权限"
permissions-title: "&c 需要权限:"
permissions-list: " &c - [权限]"
permissions-list: " &c - [permission]"
island:
lore: |-
[]
[实体]
[搜索半径]
[警告块]
[警告实体]
blocks-title: "&7&l 所需块:"
block-value: " &7 - &e [材质]"
blocks-value: " &7 - &e [数量] x [材料]"
[blocks]
[entities]
[search-radius]
[warning-block]
[warning-entity]
blocks-title: "&7&l 所需块:"
block-value: " &7 - &e [material]"
blocks-value: " &7 - &e [number] x [material]"
entities-title: "&7&l 所需实体:"
entity-value: " &7 - &e [实体]"
entities-value: " &7 - &e [数字] x [实体]"
search-radius: "&7 不超过 &e [数字] &7 米"
warning-block: "&e 块将被 &c 删除"
entity-value: " &7 - &e [entity]"
entities-value: " &7 - &e [number] x [entity]"
search-radius: "&7 不超过 &e [number] &7 米"
warning-block: "&e 块将被 &c 删除"
warning-entity: "&e 实体将被 &c 删除"
inventory:
lore: |-
[项目]
[警告]
[items]
[warning]
item-title: "&7&l 必填项目:"
item-value: " &7 - &e [项目]"
items-value: " &7 - &e [数字] x [项目]"
item-value: " &7 - &e [item]"
items-value: " &7 - &e [number] x [item]"
warning: "&e 项目(-s将被 &c 删除"
other:
lore: |-
[经验]
[经验警告]
[]
[金钱警告]
[等级]
experience: "&7&l 所需经验:&r&e [数量]"
[experience]
[experience-warning]
[money]
[money-warning]
[level]
experience: "&7&l 所需经验:&r&e [number]"
experience-warning: "&e 经验将被 &c 移除"
money: "&7&l 所需资金:&r&e [数字]"
money: "&7&l 所需资金:&r&e [number]"
money-warning: "&e 钱将被 &c 移除"
level: "&7&l 所需岛屿等级:&r&e [数字]"
level: "&7&l 所需岛屿等级:&r&e [number]"
statistic:
lore: |-
[统计]
[警告]
multiple-target: "&7&l [统计]: &r&e [数字] x [目标]"
single-target: "&7&l [统计]: &r&e [目标]"
statistic: "&7&l [统计] &r&e [数字]"
[statistic]
[warning]
multiple-target: "&7&l [statistic]: &r&e [number] x [target]"
single-target: "&7&l [statistic]: &r&e [target]"
statistic: "&7&l [statistic] &r&e [number]"
warning: "&e 统计数据将 &c 减少"
rewards:
lore: |-
&7&l 奖励:
[文本]
[项目]
[经验]
[]
[命令]
[text]
[items]
[experience]
[money]
[commands]
item-title: "&7 项:"
item-value: " &7 - &e [项目]"
items-value: " &7 - &e [数字] x [项目]"
experience: "&7 经验:&r&e [数字]"
money: "&7 金钱:&r&e [数字]"
item-value: " &7 - &e [item]"
items-value: " &7 - &e [number] x [item]"
experience: "&7 经验:&r&e [number]"
money: "&7 金钱:&r&e [number]"
commands-title: "&7 命令:"
command: " &7 - &e [命令]"
command: " &7 - &e [command]"
level:
lore: |-
[文本]
[地位]
[放弃]
[奖励]
[text]
[status]
[waiver]
[rewards]
status:
completed: "&2&l 已完成"
completed-challenges-of: |-
&2 已完成 &7&l [数量] &r&2 出
&2 已完成 &7&l [number] &r&2 出
&7&l [max] &r&2 挑战。
locked: "&c&l 锁定"
missing-challenges: |-
&7 [数字] 更多的挑战必须是
&7 [number] 更多的挑战必须是
&7 完成以解锁此级别。
waiver: |-
&7&l [number] 挑战(-s) &r&7 可以
@ -929,25 +935,26 @@ challenges:
rewards:
lore: |-
&7&l 奖励:
[文本]
[项目]
[经验]
[]
[命令]
[text]
[items]
[experience]
[money]
[commands]
item-title: "&7 项:"
item-value: " &7 - &e [项目]"
items-value: " &7 - &e [数字] x [项目]"
experience: "&7 经验:&r&e [数字]"
money: "&7 金钱:&r&e [数字]"
item-value: " &7 - &e [item]"
items-value: " &7 - &e [number] x [item]"
experience: "&7 经验:&r&e [number]"
money: "&7 金钱:&r&e [number]"
commands-title: "&7 命令:"
command: " &7 - &e [命令]"
command: " &7 - &e [command]"
library:
author: "&7 作者 &e [作者]"
version: "&7 Made with Challenges &e [版本]"
author: "&7 作者 &e [author]"
version: "&7 Made with Challenges &e [version]"
lang: "&7 语言:&e [lang]"
gamemode: "&7 主要用于 &e [游戏模式]"
gamemode: "&7 主要用于 &e [gamemode]"
#后面没人工翻译了
conversations:
prefix: "&l&6 [便当盒]: &r"
prefix: "&l&6 [BentoBox]: &r"
confirm-string: true, on, yes, 确认, y, 有效, 正确
deny-string: 关闭拒绝n无效不正确
cancel-string: 取消
@ -956,17 +963,17 @@ challenges:
input-number: "&e 请在聊天中输入一个号码。"
input-seconds: "&e 请在聊天中输入秒。"
numeric-only: "&c 给定的 [value] 不是数字!"
not-valid-value: "&c 给定的数字 [] 无效。它必须大于 [min] 并且小于 [max]"
user-data-removed: "&a [游戏模式] 的所有用户数据都从数据库中清除。"
confirm-user-data-deletion: "&e 请确认您要清除 [游戏模式] 的用户数据库。"
challenge-data-removed: "&a [游戏模式] 的所有挑战数据都从数据库中清除。"
confirm-challenge-data-deletion: "&e 请确认您要清除 [游戏模式] 的挑战数据库。"
all-data-removed: "&a [游戏模式] 的所有插件数据都从数据库中清除。"
confirm-all-data-deletion: "&e 请确认您要清除 [游戏模式] 的插件数据。"
write-name: "&e 请在聊天中一个名字。"
not-valid-value: "&c 给定的数字 [value] 无效。它必须大于 [min] 并且小于 [max]"
user-data-removed: "&a [gamemode] 的所有用户数据都从数据库中清除。"
confirm-user-data-deletion: "&e 请确认您要清除 [gamemode] 的用户数据库。"
challenge-data-removed: "&a [gamemode] 的所有挑战数据都从数据库中清除。"
confirm-challenge-data-deletion: "&e 请确认您要清除 [gamemode] 的挑战数据库。"
all-data-removed: "&a [gamemode] 的所有插件数据都从数据库中清除。"
confirm-all-data-deletion: "&e 请确认您要清除 [gamemode] 的插件数据。"
write-name: "&e 请在聊天中输入一个名字。"
new-object-created: "&a 为 [gamemode] 创建了一个新对象。"
object-already-exists: "&c 对象 &7 [id] &c 已经存在。选择不同的名称。"
invalid-challenge: "&c 挑战 [挑战] 包含无效数据。无法部署!"
invalid-challenge: "&c 挑战 [challenge] 包含无效数据。无法部署!"
name-changed: "&a 成功,名称已更新。"
write-description: "&e 请在聊天中输入新的描述,然后在一行中自行“退出”以完成。"
description-changed: "&a 成功,说明已更新。"
@ -987,7 +994,7 @@ challenges:
start-downloading: "&a 开始下载和导入挑战库。"
written-text: "&a 输入文本:"
confirm-data-replacement: "&e 请确认您想用新的挑战替换当前的挑战。"
new-challenges-imported: "&a 成功,[游戏模式] 的新挑战已导入。"
new-challenges-imported: "&a 成功,[gamemode] 的新挑战已导入。"
exported-file-name: "&e 请输入导出的数据库文件的文件名。 (写“取消”退出)"
database-export-completed: "&a 成功,[world] 的数据库导出完成。文件[文件]生成。"
file-name-exist: "&c 名称为“[id]”的文件存在。无法覆盖。"
@ -998,11 +1005,12 @@ challenges:
challenge-subtitle: "[friendlyName]"
level-title: "&a已完成"
level-subtitle: "[friendlyName]"
#上面没翻译了
messages:
completed: "&2 你为[玩家]完成了挑战[名字]"
completed: "&2 你为[player]完成了挑战[name]"
already-completed: "&2 这个挑战已经完成了!"
reset: "&2 你为 [玩家] 重置挑战 [名称]"
reset-all: "&2 所有[玩家]挑战均已重置!"
reset: "&2 你为 [player] 重置挑战 [name]"
reset-all: "&2 所有[player]挑战均已重置!"
not-completed: "&2 此挑战尚未完成!"
migrate-start: "&2 开始迁移挑战插件数据。"
migrate-end: "&2 挑战插件数据更新为新格式。"
@ -1031,7 +1039,7 @@ challenges:
you-still-need: "&c你还差 &f[amount] &c个 &f[item] &c才能完成挑战。"
missing-addon: "&c无法完成挑战缺少必需的组件或插件。"
incorrect: "&c无法完成挑战必要条件设定错误。"
not-enough-money: "&c你必须有 &f[value] &c游戏币才能完成任务。"
not-enough-money: "&c你必须有 &f[value] &c金钱才能完成任务。"
not-enough-experience: "&c你必须有 &f[value] &c经验值才能完成任务。"
island-level: "&c你的岛屿等级必须达到 &flv[number] &c才能完成任务"
no-load: "&c错误 无法载入 &fchallenges.yml&c. [message]"
@ -1047,18 +1055,106 @@ challenges:
invalid-challenge: "&c挑战项 [challenge] &c包含错误它不会从数据库中加载"
no-library-entries: "&c 找不到任何库条目。没什么可显示的。"
not-hooked: "&c Challenges Addon 找不到任何游戏模式。"
timeout: "&c 此挑战需要在完成之间等待 [超时]。您必须等待 [wait-time] 才能再次完成。"
timeout: "&c 此挑战需要在完成之间等待 [timeout]。您必须等待 [wait-time] 才能再次完成。"
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.
# cobblestone: "Cobblestone"
# # Also supports descriptions.
# stone:
# name: "Stone"
# description: ""
# item-stacks:
# # Non-specific item meta translations.
# # TYPE is the item type
# # META is a content of item meta.
# generic: "[type] [meta]"
# # Non-specific meta translations. Will replace [meta]
# meta:
# upgraded: "Upgraded"
# extended: "Extended"
# potion-meta: "&e [type] [upgraded] [extended]"
# # Be aware, enchants are always listed below item in separate line.
# enchant-meta: " &7 - &e [type] [level]"
# skull-meta: ": &e [player-name]"
# book-meta: "&e [title] [author]"
# # Custom Enchantment Translation.
# enchant:
# menting: "Mending"
# unbreaking: "Unbreaking"
# # Custom Potion Translation.
# potion-type:
# water_breathing: "Water Breathing"
# # You can also create specific item translations
# # Like translate all potions.
# potion:
# # 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.
# name: "[type]"
#
# # Showcase how to support multi-linguistic challenges
# challenges:
# # Database ID name.
# example_challenge_id:
# name: "&2 Translated Name"
# description: |-
# &7 Translated Custom
# &7 description
# reward-text: |-
# &7 Translated Reward
# &7 text
# repeat-reward-text: |-
# &7 Translated Repeat
# &7 Reward text
# levels:
# # Database ID name.
# example_level_id:
# name: "&2 Translated Name"
# description: |-
# &7 Translated Custom
# &7 description
# reward-text: |-
# &7 Translated Reward
# &7 text
protection:
flags:
CHALLENGES_ISLAND_PROTECTION:
description: 允许/禁止 在岛屿上完成挑战
name: 挑战权限
description: |-
&5 &o 切换谁可以
&5 &o 完成挑战
name: 挑战保护
CHALLENGES_WORLD_PROTECTION:
description: |-
&7允许/禁止 限制玩家只能在自己岛
&7上才能完成挑战。
&c允许时玩家只能在自己岛上进行
&c和完成挑战。
name: 挑战岛屿限制
hint: "&c已被禁止在岛屿范围外进行挑战"
&5 &o 启用 / 禁用
&5 &o 玩家们在自己
&5 &o 岛屿中完成挑
&5 &o 战的需求
name: 岛屿挑战限制
hint: 岛屿外无挑战
version: 11

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
name: BentoBox-Challenges
main: world.bentobox.challenges.ChallengesPladdon
version: ${project.version}${build.number}
api-version: "1.17"
authors: [tastybento, BONNe]
contributors: ["The BentoBoxWorld Community"]
website: https://bentobox.world
description: ${project.description}

View File

@ -245,96 +245,96 @@ public class ChallengesManagerTest {
}
/**
* Test method for {@link ChallengesManager#loadChallenge(world.bentobox.challenges.database.object.Challenge, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
* Test method for {@link ChallengesManager#loadChallenge(world.bentobox.challenges.database.object.Challenge, World, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
*/
@Test
public void testLoadChallengeNoOverwriteSilent() {
// load once
assertTrue(cm.loadChallenge(challenge, false, user, true));
assertTrue(cm.loadChallenge(challenge, world, false, user, true));
// load twice - no overwrite
assertFalse(cm.loadChallenge(challenge, false, user, true));
assertFalse(cm.loadChallenge(challenge, world, false, user, true));
}
/**
* Test method for {@link ChallengesManager#loadChallenge(world.bentobox.challenges.database.object.Challenge, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
* Test method for {@link ChallengesManager#loadChallenge(world.bentobox.challenges.database.object.Challenge, World, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
*/
@Test
public void testLoadChallengeNoOverwriteNotSilent() {
// load once
assertTrue(cm.loadChallenge(challenge, false, user, true));
assertTrue(cm.loadChallenge(challenge, world, false, user, true));
// load twice - no overwrite, not silent
assertFalse(cm.loadChallenge(challenge, false, user, false));
assertFalse(cm.loadChallenge(challenge, world, false, user, false));
verify(user).getTranslation("challenges.messages.load-skipping", "[value]", "name");
}
/**
* Test method for {@link ChallengesManager#loadChallenge(world.bentobox.challenges.database.object.Challenge, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
* Test method for {@link ChallengesManager#loadChallenge(world.bentobox.challenges.database.object.Challenge, World, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
*/
@Test
public void testLoadChallengeOverwriteSilent() {
// load once
assertTrue(cm.loadChallenge(challenge, false, user, true));
assertTrue(cm.loadChallenge(challenge, world, false, user, true));
// overwrite
assertTrue(cm.loadChallenge(challenge, true, user, true));
assertTrue(cm.loadChallenge(challenge, world, true, user, true));
verify(user, never()).getTranslation(anyString(), anyString(), anyString());
}
/**
* Test method for {@link ChallengesManager#loadChallenge(world.bentobox.challenges.database.object.Challenge, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
* Test method for {@link ChallengesManager#loadChallenge(world.bentobox.challenges.database.object.Challenge, World, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
*/
@Test
public void testLoadChallengeOverwriteNotSilent() {
// load once
assertTrue(cm.loadChallenge(challenge, false, user, true));
assertTrue(cm.loadChallenge(challenge, world, false, user, true));
// overwrite not silent
assertTrue(cm.loadChallenge(challenge, true, user, false));
assertTrue(cm.loadChallenge(challenge, world, true, user, false));
verify(user).getTranslation("challenges.messages.load-overwriting", "[value]", "name");
}
/**
* Test method for {@link ChallengesManager#loadLevel(world.bentobox.challenges.database.object.ChallengeLevel, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
* Test method for {@link ChallengesManager#loadLevel(world.bentobox.challenges.database.object.ChallengeLevel, World, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
*/
@Test
public void testLoadLevelNoOverwriteSilent() {
// load once
assertTrue(cm.loadLevel(level, false, user, true));
assertTrue(cm.loadLevel(level, world, false, user, true));
// load twice - no overwrite
assertFalse(cm.loadLevel(level, false, user, true));
assertFalse(cm.loadLevel(level, world, false, user, true));
}
/**
* Test method for {@link ChallengesManager#loadLevel(world.bentobox.challenges.database.object.ChallengeLevel, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
* Test method for {@link ChallengesManager#loadLevel(world.bentobox.challenges.database.object.ChallengeLevel, World, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
*/
@Test
public void testLoadLevelNoOverwriteNotSilent() {
// load once
assertTrue(cm.loadLevel(level, false, user, true));
assertTrue(cm.loadLevel(level, world, false, user, true));
// load twice - no overwrite, not silent
assertFalse(cm.loadLevel(level, false, user, false));
assertFalse(cm.loadLevel(level, world, false, user, false));
verify(user).getTranslation("challenges.messages.load-skipping", "[value]", "Novice");
}
/**
* Test method for {@link ChallengesManager#loadLevel(world.bentobox.challenges.database.object.ChallengeLevel, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
* Test method for {@link ChallengesManager#loadLevel(world.bentobox.challenges.database.object.ChallengeLevel, World, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
*/
@Test
public void testLoadLevelOverwriteSilent() {
// load once
assertTrue(cm.loadLevel(level, false, user, true));
assertTrue(cm.loadLevel(level, world, false, user, true));
// overwrite
assertTrue(cm.loadLevel(level, true, user, true));
assertTrue(cm.loadLevel(level, world, true, user, true));
verify(user, never()).getTranslation(anyString(), anyString(), anyString());
}
/**
* Test method for {@link ChallengesManager#loadLevel(world.bentobox.challenges.database.object.ChallengeLevel, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
* Test method for {@link ChallengesManager#loadLevel(world.bentobox.challenges.database.object.ChallengeLevel, World, boolean, world.bentobox.bentobox.api.user.User, boolean)}.
*/
@Test
public void testLoadLevelOverwriteNotSilent() {
// load once
assertTrue(cm.loadLevel(level, false, user, true));
assertTrue(cm.loadLevel(level, world, false, user, true));
// overwrite not silent
assertTrue(cm.loadLevel(level, true, user, false));
assertTrue(cm.loadLevel(level, world, true, user, false));
verify(user).getTranslation("challenges.messages.load-overwriting", "[value]", "Novice");
}
@ -660,7 +660,7 @@ public class ChallengesManagerTest {
public void testGetAllChallengesNames() {
assertTrue(cm.getAllChallengesNames(world).isEmpty());
cm.saveChallenge(challenge);
cm.loadChallenge(challenge, false, user, true);
cm.loadChallenge(challenge, world, false, user, true);
List<String> list = cm.getAllChallengesNames(world);
assertFalse(list.isEmpty());
assertEquals(cName, list.get(0));
@ -673,7 +673,7 @@ public class ChallengesManagerTest {
public void testGetAllChallenges() {
assertTrue(cm.getAllChallenges(world).isEmpty());
cm.saveChallenge(challenge);
cm.loadChallenge(challenge, false, user, true);
cm.loadChallenge(challenge, world, false, user, true);
List<Challenge> list = cm.getAllChallenges(world);
assertFalse(list.isEmpty());
assertEquals(challenge, list.get(0));
@ -688,12 +688,12 @@ public class ChallengesManagerTest {
assertTrue(cm.getFreeChallenges(world).isEmpty());
// One normal
cm.saveChallenge(challenge);
cm.loadChallenge(challenge, false, user, true);
cm.loadChallenge(challenge, world, false, user, true);
assertTrue(cm.getFreeChallenges(world).isEmpty());
// One free
challenge.setLevel("");
cm.saveChallenge(challenge);
cm.loadChallenge(challenge, false, user, true);
cm.loadChallenge(challenge, world, false, user, true);
List<Challenge> list = cm.getFreeChallenges(world);
assertFalse(list.isEmpty());
assertEquals(challenge, list.get(0));
@ -792,7 +792,7 @@ public class ChallengesManagerTest {
public void testGetLevelString() {
assertNull(cm.getLevel("dss"));
cm.saveLevel(level);
cm.loadLevel(level, false, user, true);
cm.loadLevel(level, world, false, user, true);
assertEquals(level, cm.getLevel(levelName));
}