Compare commits

...

172 Commits

Author SHA1 Message Date
tastybento ec6b950304 Fix tests. 2024-03-10 18:44:57 -07:00
tastybento d0588303c0 Reference latest BentoBox release version 2024-03-10 16:11:22 -07:00
BONNe 7483ff0e0f
Update en-US.yml 2024-02-11 17:13:24 +02:00
tastybento 005d49a756 Update TIPPED_ARROW to latest API in panels 2024-01-21 09:02:19 -08:00
tastybento fe9e63f1c7 Fix tests for creative user inventory challenge completion 2024-01-13 08:23:41 -08:00
BONNe 8a8124f36e Fixes crash when player in CREATIVE shift+clicks on INVENTORY challenge.
Limit completion time to 2, if player is in creative instead of Integer.MAX_VALUE

Fixes #330
2024-01-11 09:40:20 +02:00
BONNe 74cd97fb80 Upgrade PanelUtils to 1.2.0 2024-01-03 14:11:22 +02:00
BONNe c351225e9a
Fixes enchanted book meta not displayed (#328)
Apparently in Spigot EnchantmentStorage has a map that is not used for enchantment storing. Nice.

Fixes #327
2023-12-20 11:06:16 +02:00
tastybento a90d17d70d
Update README.md 2023-11-26 19:06:04 -08:00
tastybento b6bd3d3a2e
Update README.md 2023-11-26 19:04:43 -08:00
tastybento b82defe3b5 Show money as formatted. Addresses #324 2023-11-26 18:52:39 -08:00
gitlocalize-app[bot] a6a3a3e12d
Translate uk.yml via GitLocalize (#325)
Co-authored-by: GIGABAIT <freebitcoin93@gmail.com>
Co-authored-by: tastybento <tastybento@users.noreply.github.com>
2023-11-26 10:09:27 -08:00
gitlocalize-app[bot] 48f388c7f6
Add Ukrainian locale (#326)
* Translate uk.yml via GitLocalize

* Translate uk.yml via GitLocalize

---------

Co-authored-by: mt-gitlocalize <mt@gitlocalize.com>
Co-authored-by: GIGABAIT <freebitcoin93@gmail.com>
2023-11-26 10:00:06 -08:00
tastybento 56d7eb4259 Update to BentoBox 2.0.0
Had to ignore some tests because PowerMockito can't mock them for some
reason.
2023-11-12 13:23:22 -08:00
tastybento 34d280d5bf
Update pom.xml 2023-07-10 21:41:20 -07:00
tastybento 9e34910f07 Update Jacoco 2023-07-10 21:22:34 -07:00
tastybento 1fdcfdd7ef Remove offending test. Was not that useful anyway. 2023-07-08 11:42:52 -07:00
tastybento 1759ef7123 Try adding maven dependency to fix test issue 2023-07-08 11:37:45 -07:00
tastybento bba54aa08b Remove duplicate plugin reference in POM 2023-07-08 11:28:40 -07:00
tastybento ebd0b46656 Update POM versions to use latest API 2023-07-08 10:50:47 -07:00
gitlocalize-app[bot] 98052d1797
Update Hungarian translation (#301)
* Translate hu.yml via GitLocalize

* Translate hu.yml via GitLocalize

* Translate hu.yml via GitLocalize

* Translate hu.yml via GitLocalize

* Update hu.yml

Fix color codes and placeholders

---------

Co-authored-by: driverdakid <tamascsiszar99@icloud.com>
Co-authored-by: mt-gitlocalize <mt@gitlocalize.com>
Co-authored-by: BONNe <bonne@bonne.id.lv>
Co-authored-by: slimcraft <davidelek12@gmail.com>
Co-authored-by: tastybento <tastybento@users.noreply.github.com>
2023-07-08 10:43:57 -07:00
BONNe d74cfbfe96 Merge remote-tracking branch 'origin/develop' into develop 2023-07-03 12:36:59 +03:00
BONNe 3b36f38b7c Fixes the admin GUI crash.
Add shade plugin that was missing for dependencies.
2023-07-03 12:35:55 +03:00
tastybento 125a3249ac Add required distribution 2023-06-24 13:52:45 -07:00
tastybento 9da197de21 Update Github Action build script 2023-06-24 13:02:26 -07:00
tastybento 480ffd8eb4 Fixed ChallengesManagerTest 2023-06-04 10:49:16 -07:00
tastybento ddebdf0e62 Fixed ChallengesCommandTest 2023-06-04 10:41:18 -07:00
tastybento 82ba144038 Fixed CompleteChallengeCommandTest 2023-06-04 10:38:45 -07:00
tastybento 53f0a0cb37 Fixed TryToComplete test class 2023-06-04 10:31:52 -07:00
BONNe 550e348428 Fixes a crash with written/writable books.
The issue was with generating description message for written books without title or author.

Fixes #318
2023-04-24 15:01:56 +03:00
BONNe b1fa9a9da7
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>
2023-04-15 22:55:34 +03:00
BONNe 01bd7b82bb
Remove dependency to org.apache.commons
Replace org.apache.commons.lang.ArrayUtils to a default Java implementation.
2023-04-13 18:56:17 +03:00
BONNe a608c8b765
Create plugin.yml (#316)
* Create plugin.yml

* Update pom.xml

* Update ChallengesPladdon.java
2023-04-08 18:30:40 +03:00
BONNe 5ab4237df4 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
2023-04-02 14:47:10 +03:00
BONNe de7172ef75 Update ChallengesManagerTest methods with world parameter. 2023-03-31 11:26:54 +03:00
BONNe 9953459e50 Add support for gamemode-specific translations.
This was a request from Floris
2023-03-31 11:12:08 +03:00
tastybento e0377fd352 Updated pladdon annotations 2023-03-25 10:05:36 -07:00
tastybento 09adbde004
Update build.yml
Java 17 for Surefire
2023-02-10 15:36:55 -08:00
tastybento 84a38f4d8c Updated Jacoco POM section 2023-02-10 10:50:41 -08:00
tastybento 1b585a22c8
Add ${argLine} to get jacoco coverage 2023-02-09 15:14:35 -08:00
JamesMCL44 9ed92733c7
Add locale of Chinese-Hong Kong (zh-HK) (#313)
Addition of locale updated to latest version
2023-02-05 18:36:33 +02:00
BONNe 431aaf46fc Add requirement-not-met-material and requirement-not-met-entity to display statistic required item on error. 2023-02-02 23:29:06 +02:00
BONNe ee8eaf8e84 Fixes a crash that prevented STATISTICS entity and material/item challenges to be completed. 2023-02-02 23:24:22 +02:00
BONNe 5ba7c681de Merge remote-tracking branch 'origin/develop' into develop 2023-01-30 23:54:36 +02:00
BONNe 468232cabc Fixes a regex bug that replaced every [player] char instead of whole word. 2023-01-30 23:54:29 +02:00
EpicMo 1faf3b55be
Edit some unfit translation (#312)
Edit some unfit translation
2023-01-20 04:44:29 +02:00
BONNe 0d69459738 Merge remote-tracking branch 'origin/develop' into develop 2023-01-19 12:47:29 +02:00
BONNe e94d2349c3 Init 1.2.0 version 2023-01-19 12:47:21 +02:00
BONNe 8b81101ef0 Fixes #311 localization errors in zn-CN.
Original translation author translated `[]` placeholders which broke locale
2023-01-19 12:47:20 +02:00
BONNe 1da624002d
Init 1.2.0 version 2023-01-05 21:49:39 +02:00
BONNe 7f58af7588 Merge branch 'develop' into master
# Conflicts:
#	pom.xml
#	src/main/java/world/bentobox/challenges/commands/admin/ChallengesGlobalAdminCommand.java
#	src/main/java/world/bentobox/challenges/managers/ChallengesImportManager.java
#	src/main/java/world/bentobox/challenges/managers/ChallengesManager.java
#	src/main/java/world/bentobox/challenges/panel/CommonPanel.java
#	src/main/java/world/bentobox/challenges/panel/user/ChallengesPanel.java
#	src/main/java/world/bentobox/challenges/tasks/TryToComplete.java
#	src/main/resources/locales/en-US.yml
#	src/main/resources/locales/pl.yml
#	src/main/resources/locales/zh-CN.yml
#	src/main/resources/template.yml
2023-01-05 21:40:14 +02:00
BONNe 4c4ec57562 Update to BentoBox 1.21 and PanelUtils 1.1.0 2023-01-05 21:39:03 +02:00
BONNe da46a31add Remove unnecessary md files. 2023-01-05 21:34:02 +02:00
BONNe b7e2bc7719 Merge remote-tracking branch 'origin/develop' into develop 2023-01-05 21:32:30 +02:00
BONNe c8edfe3b51 Adds potion names to the default locale.
The potion names will not be displayed, but it will add all of them in the locale.
2023-01-05 21:32:03 +02:00
BONNe cfabb28daf
Add extra parameters for completion commands. (#309)
The 2 new parameters are:
   - [owner] - the owner of island.
   - [name] - the name of the island.

Fixes #304
2022-11-21 08:16:42 +02:00
BONNe e55503a9cf Add extra parameters for completion commands.
The 2 new parameters are:
   - [owner] - the owner of island.
   - [name] - the name of the island.

Fixes #304
2022-11-21 08:15:38 +02:00
BONNe 57a4c08c0c
Rewrite action display logic. (#308)
There were no filters for action displaying. All actions were active from the start, even if they are not possible.
I added action filter that will remove impossible actions:
    - COMPLETE_MAX and MULTIPLE_PANEL for non-repeatable challenge,
    - already completely finished challenge.
Fixes #307
2022-11-21 08:01:13 +02:00
BONNe 31bd9238d4 Merge remote-tracking branch 'origin/develop' into develop 2022-11-05 04:09:56 +02:00
BONNe 0475c798e1 Fixes missing error translation for not meeting statistics challenge value. 2022-11-05 04:09:43 +02:00
gitlocalize-app[bot] 9b83b5cd06
Update PT (#306)
* Translate pt.yml via GitLocalize

* Translate pt.yml via GitLocalize

Co-authored-by: Mario-Leal <henriquedosgrilo@gmail.com>
Co-authored-by: mt-gitlocalize <mt@gitlocalize.com>
2022-10-31 08:24:18 +02:00
gitlocalize-app[bot] d2c8cb2925
Translate pl.yml via GitLocalize (#305)
Co-authored-by: wiktorm12 <wiktorm12@gmail.com>
2022-10-31 08:24:09 +02:00
gitlocalize-app[bot] e6fdc81937
Translate pl.yml via GitLocalize (#302)
Co-authored-by: wiktorm12 <wiktorm12@gmail.com>
2022-08-27 15:14:59 +03:00
gitlocalize-app[bot] 57d1f9f4cc
Update zh-CN (#300)
* Translate zh-CN.yml via GitLocalize

* Translate zh-CN.yml via GitLocalize

* Translate zh-CN.yml via GitLocalize

Co-authored-by: DuckSoft <realducksoft@gmail.com>
Co-authored-by: mt-gitlocalize <mt@gitlocalize.com>
Co-authored-by: Yanhanr <me.yanhan@outlook.com>
2022-08-23 10:54:44 +03:00
gitlocalize-app[bot] 3ca2fbe7eb
Update PL translation (#299)
* Translate pl.yml via GitLocalize

* Translate pl.yml via GitLocalize

* Translate pl.yml via GitLocalize

Co-authored-by: wiktorm12 <wiktorm12@gmail.com>
Co-authored-by: LISU <lisudef@gmail.com>
Co-authored-by: mt-gitlocalize <mt@gitlocalize.com>
2022-08-23 10:54:28 +03:00
BONNe c933caebe0 Fixes an issue when error message about file loading was not logged. 2022-07-26 01:02:09 +03:00
BONNe d59b047555 Fixes missing "required level" string.
I forgot to add correct reference text to the level.

Fixes #298
2022-07-25 11:00:05 +03:00
BONNe 26fb55748f Solves "Comparison method violates its general contract!" crash.
I reworked a comparator for challenges a bit. I did not find the reason why previous was wrong, as it should return the same result as the new one, but for some reason this works, and previous do not.

Fixes #296
2022-07-07 11:27:11 +03:00
BONNe 218e5fc6c4 Fixes an incorrect permission assignment for global admin and global player command.
Reported via discord.
2022-05-13 18:02:42 +03:00
BONNe 629159b52d
Update pom.xml 2022-05-06 23:18:38 +03:00
tastybento 9cccfa02ba Remove various code smells. 2022-04-16 15:54:49 -07:00
tastybento 6c0915544e Require non-nulls.
getInventory never returns null.
2022-04-16 15:27:35 -07:00
tastybento 37d2039a67 Added null check 2022-04-16 15:21:29 -07:00
tastybento 44ad32df50 Null check 2022-04-16 15:15:26 -07:00
tastybento e8b4129c3a Check for null world 2022-04-16 15:13:55 -07:00
tastybento 5c2f2ecfc7 Avoid potential call with a null parameter to User.getInstance 2022-04-16 15:12:19 -07:00
tastybento 10d8352f1c Fixed test failures. 2022-04-16 15:03:11 -07:00
tastybento aff6fcec22 Fix failing test. Make player default to being on island. 2022-04-16 14:49:17 -07:00
tastybento 80f748070e Fix error in test class.
Note this does not fix the failing assertion.
2022-04-16 14:42:52 -07:00
tastybento 2263dae70c Fix NPEs when running tests.
Note that there are still test failures, but these are assertions and
not errors.
2022-04-16 14:36:05 -07:00
gitlocalize-app[bot] f851a96c9b
Update German translation (#295)
* Translate de.yml via GitLocalize

* Translate de.yml via GitLocalize

* Translate de.yml via GitLocalize

Co-authored-by: Patrick <patrick.wassmuth@gmx.de>
Co-authored-by: Michael F <unhappyangel83@googlemail.com>
Co-authored-by: DAge030 <dage030@web.de>
2022-04-16 18:34:54 +03:00
BONNe 36ad61b4b9
Improve equal item listing.
Change when items should be grouped.
Instead of relaying strictly from ignoreMetaData set, now try to group equal elements without durability check, and use set only if that fails.
2022-03-22 12:49:57 +02:00
BONNe e96e2c7e72
Fixes a bug with `-1` repeat-times
There was a bug that prevented the challenge to be completed if negative numbers were set in the "max-repeats" value.
2022-03-22 12:41:27 +02:00
BONNe 48c47f086d
Update pom.xml 2022-03-03 18:33:56 +02:00
BONNe 6bffb2088b
Fix a bug with completion broadcasting
Reported via Discord.
2022-02-20 12:08:58 +02:00
BONNe b9e57fdebb Fixes some small bugs with translation potion base effect.
There was an issue that it tried to translate extra effects and ignored main one.

Relates to #290
2022-01-08 13:23:48 +02:00
BONNe fc1d4fcf06 Update lv translation. 2022-01-04 21:48:36 +02:00
BONNe 23778ffca2 Fix an issue when edit menu did not display item amount. 2022-01-04 21:47:20 +02:00
BONNe 88215b6f0c Implement MetaData ignoring for rewards.
While required items had a metadata grouping, reward items did not have it. This will fix that.

Fixes #289
2022-01-04 21:45:34 +02:00
BONNe 71e0029d46 Fixes incorrect NEXT and PREVIOUS button descriptions.
Fixes #289
2022-01-04 21:38:52 +02:00
BONNe 7fbffbb6d2 Address some code quality reports from SonarCloud.
Most of the errors are just sanity checks, as the most of null-pointers were already checked in other ways.
2021-12-01 11:30:02 +02:00
BONNe e7b84768aa Remove unnecessary NMS dependency.
NMS code was used for Player Heads, but instead of NMS now it uses public mojang lib.
2021-12-01 10:16:34 +02:00
BONNe 8f6abf2434 Link templates to the docs. 2021-11-22 13:55:51 +02:00
BONNe e9f37e8dee Replace GuiUtils and HeadLib to the PanelUtils library. 2021-10-02 14:04:30 +03:00
tastybento e4f93615ce Removed shade plugin from POM 2021-09-24 19:58:04 -07:00
BONNe 13924a3011 Fixes failing unit-test 2021-09-24 17:19:58 +03:00
BONNe 08d1561138 Implement an option to set which item type will ignore metadata per challenge.
Fixes #261
Fixes #252
2021-09-24 17:16:33 +03:00
BONNe 99a3e3f165 Implement changing Timeout in the Challenge Edit GUI.
Relates #71
2021-09-24 16:16:48 +03:00
BONNe bb5e861b30 Implement timeout respecting in challenges completion.
Implement timeout in GUI's.

Relates #71
2021-09-24 16:03:02 +03:00
BONNe 1b01995546 Add timeout for repeatable challenges.
Relates #71
2021-09-24 13:08:33 +03:00
BONNe 644c7d6ba5 Fixes #269
Disable waiver amount message for last challenge level.
2021-09-24 12:55:41 +03:00
BONNe aa0336d62a Fixes #187
Add a new method that updates unlocked level list without changing active level. This method returns if last unlocked level was changed, and in that case it triggers whole gui rebuilding.
2021-09-24 12:26:44 +03:00
BONNe adf4e7c58b Fixes #253
Adds TeamKick and TeamLeave events to the reset check.
Do not reset challenges if data is stored per island. As in that case, they will already lose their data.
2021-09-24 11:14:07 +03:00
tastybento 41d574a859 Excluded unnecessary files from shading. 2021-09-23 22:22:23 -07:00
tastybento 070a7190a4 Remove Vault repo because it is not needed. 2021-09-23 22:09:34 -07:00
tastybento f9e1b15b9f Try different spigot API version 2021-09-23 21:59:14 -07:00
tastybento e110202a2a Updated .gitignore 2021-09-23 19:39:54 -07:00
tastybento 50d5687aef Fix JavaDoc, Shade plugin settings 2021-09-23 19:39:33 -07:00
tastybento 877c8d2eff Fixes tests 2021-09-23 19:38:10 -07:00
tastybento 7b8cab3689 Fixed ChallengesCommandTest tests 2021-09-23 17:35:26 -07:00
tastybento c21cae91e1 Fixed errors and tests for CompleteChallengeCommandTest 2021-09-23 17:22:16 -07:00
tastybento 018455f8f6 Prevent errors in TryToCompleteTest
Note - tests still fail.
2021-09-23 17:12:59 -07:00
tastybento 7126acfcfa Reorder dependencies
The Mojang dependency was blocking out the needed Google common
packages.
2021-09-23 17:08:12 -07:00
BONNe ff231fae49 Add missing strings into locale. 2021-09-20 15:19:08 +03:00
BONNe 09d5bfc8cf Add search button to the CommonPagedPanel.
Search button will allow to search elements if there are more than displayed elements.
2021-09-20 15:14:42 +03:00
BONNe 8c9ddb189d Add missing tooltips to the CommonPagedPanel 2021-09-20 14:41:09 +03:00
BONNe 23fc5310b3 Change download icon from hopper to cobweb. 2021-09-20 14:40:47 +03:00
BONNe a75c243762 Add search field to the PagedSelectors.
Add missing tooltips.
2021-09-20 14:39:21 +03:00
BONNe b138e50376 Change from click-to-select to a proper next/previous page tooltip 2021-09-20 14:38:29 +03:00
BONNe 7f53283f78 Fixes illegal stack issues in default challenges.
#249
2021-09-20 12:23:19 +03:00
BONNe 5e94aa71da Add missing mob heads. 2021-09-20 12:16:30 +03:00
BONNe aa4bb3d8e4 Update missing icons for blocks.
Some blocks cannot be displayed in GUI's, and were leaving empty spaces.
This replaces their icon with a close representative.

Fixes #286
2021-09-20 11:49:39 +03:00
BONNe 7f3a1f3e5e Update BentoBox version 2021-09-20 11:17:23 +03:00
BONNe 4e0177772e Comment out showcase translation. 2021-09-20 11:16:03 +03:00
BONNe 01e6306ef2 Implement multi-linguistic server support.
Now server owners can specify different name, description and reward text for each challenge and level via locales file.

Add showcase example.
2021-09-20 11:15:24 +03:00
BONNe 477766c8f0 Update latvian locale to the latest version. 2021-09-20 10:22:43 +03:00
BONNe 25c6d0d403 Update default locale. 2021-09-20 10:22:27 +03:00
BONNe dfd0a53fb5 Remove unnecessary "admin" tag. 2021-09-20 10:22:07 +03:00
BONNe 56fb5388c5 Fixes small bugs in translation. 2021-09-20 09:28:23 +03:00
BONNe 24828a3a1b Fixes a bug when global commands does not displays in tab-complete.
Remove DefaultsCommand.java as it is not used anymore.
2021-09-20 09:27:58 +03:00
BONNe c1a0eaa2bf Translates color codes for database texts. 2021-09-19 22:56:50 +03:00
BONNe 5f4fc315e6 Fix permission link. 2021-09-19 21:48:19 +03:00
BONNe 54696ce8e7 Add meta for items translations. 2021-09-19 21:04:54 +03:00
BONNe 2bc71b5f52 Clean up Constants a bit. 2021-09-19 21:04:09 +03:00
BONNe 89c51211cd Separate singe and multiple listings. 2021-09-19 18:41:41 +03:00
BONNe 6fbc9d0676 Changes User#sendMessage to Utils#sendMessage
This allows add "prefix" to all messages send from Challenges addon.
2021-09-19 15:36:52 +03:00
BONNe 99c920fe8f Fixes #264
Challenges Menu will be opened only if player is in correct world.
2021-09-19 15:14:28 +03:00
BONNe 220cc20726 Update default config value. 2021-09-19 15:02:28 +03:00
BONNe 670513e37a Update all commands.
Commands now will have an option to change their call values.
2021-09-19 15:02:15 +03:00
BONNe 5da823c7e5 Update Main addon class.
Move vault and level detection after everything is loaded.
Update command names.
2021-09-19 14:21:29 +03:00
BONNe 4826b5fec7 Change settings file.
Add ability to change commands for addon.
Change default mode from player challenges to island challenges.
2021-09-19 14:20:11 +03:00
BONNe af3a42e136 Improve coloring scheme a bit. 2021-09-19 13:11:41 +03:00
BONNe 29565538c3 Implements Template reading.
Add template loading via Admin Panel.
Improve LibraryPanel so it could find json and yml files.
2021-09-18 21:37:30 +03:00
BONNe 535cde825e Create template YAML file.
This file format is for people who has an alergy with ingame GUI.
2021-09-18 21:35:54 +03:00
BONNe 5687f1a125 Update default.json
Split text into multiple lines.
2021-09-18 21:34:18 +03:00
BONNe 3a3af0e2c8 Updates tests.
ChallengesGUITest is removed because GUI is removed.
2021-09-18 13:04:43 +03:00
BONNe 09e25dc2a7 Updates pom.xml 2021-09-18 13:04:14 +03:00
BONNe d44298cb3f Updates locales file.
Complete rework of the locales file.
Very sorry translators :( no migration.
2021-09-18 13:03:27 +03:00
BONNe dae779ea1a Adds panel saving to the `/challenges/panels` directory. 2021-09-18 13:02:22 +03:00
BONNe edc6d1a5b6 Fixes ChallengesManager and Completer. 2021-09-18 13:01:35 +03:00
BONNe c8177adb9e Update Settings file.
Remove unused parts.
2021-09-18 13:01:04 +03:00
BONNe bfc5cefd69 Update commands.
Commands will now call correct GUI.
2021-09-18 13:00:31 +03:00
BONNe d1f15aed8b Remove unused adapters.
Updates Challenges and ChallengesLevel objects.
Add TypeMigrationAdapter that will fix issue with renamed challenge type.
2021-09-18 12:58:52 +03:00
BONNe 3ee89af5df Update all admin panels.
Admin panels will not contain better locales codding and easier-to-improve design.

Remove old and unused GUIs.
2021-09-18 12:56:44 +03:00
BONNe 09a30f00db Implement customizable user panels.
Server owners can customize 3 panels:
- main panel
- gamemode selector
- multiple completions

Panel functions will be explained in docs later.
2021-09-18 12:54:17 +03:00
BONNe 3bb0a30657 Rename classes to Selectors.
Split single and multiple item selectors for easier implementation.
Update proper locales.
2021-09-18 12:51:00 +03:00
BONNe 5d88c7b1d8 Add mojang authLib instead of NMS. 2021-08-14 21:48:20 +03:00
BONNe 703658eccc Move managers to a separate directory. 2021-08-14 21:43:42 +03:00
BONNe 7c2be91be9 Switch to annotations instead of plugin.yml file. 2021-08-14 21:42:45 +03:00
BONNe 834078e99f Merge remote-tracking branch 'origin/develop' into develop 2021-08-14 19:37:23 +03:00
BONNe c63087c5af Create Statistic Requirement for Challenges addon.
Statistic requirement is a new type of challenge that is based on Statistic page for clients.
2021-08-14 19:25:04 +03:00
BONNe 0b87bf6569
Update pom.xml 2021-06-28 03:26:16 +03:00
tastybento 66a4730ca0 Use BentoBox 1.17.0 2021-06-27 17:09:06 -07:00
tastybento 015b5d3afb Fix Java 16 compilation. 2021-06-27 11:10:49 -07:00
BONNe f75cfa9e7a Merge remote-tracking branch 'origin/develop' into develop 2021-06-23 19:51:12 +03:00
BONNe 9ca674d2b9 Upgrade to BentoBox 1.17 API changes.
Implement Pladdon functionality.
Compile against java 16 and Spigot 1.17
2021-06-23 19:50:58 +03:00
tastybento 95edafd04f
Update CompleteChallengeCommandTest.java 2021-05-12 17:57:44 -07:00
BONNe 93c98e0c35 Fixes translated placeholders in PL translation.
Note: translation looks bad.
2021-04-28 10:38:30 +03:00
BONNe 227138a689 Fixes a mistaken permission for completing multiple challenges at once. 2021-04-16 20:38:32 +03:00
Qumoo 66779a75f7
Updated german language file (#278)
fixed double & and double whitespace
2021-03-24 20:55:23 +02:00
apachezy cdfa68c942
Retranslated zh-CN.yml (#273)
* 50% completed.

* 60% completed.

* 63% completed.

* Completed.

* Change the indentation, some improvements.

Co-authored-by: zhangYi <apachezy@hotmail.com>
2021-03-14 01:47:35 +02:00
tastybento 3301554822 Version 0.8.5 2021-03-07 13:38:39 -08:00
42 changed files with 9614 additions and 4451 deletions

View File

@ -11,21 +11,22 @@ jobs:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Set up JDK 16
uses: actions/setup-java@v1
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: 16
distribution: 'adopt'
java-version: 17
- name: Cache SonarCloud packages
uses: actions/cache@v1
uses: actions/cache@v3
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Maven packages
uses: actions/cache@v1
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
@ -34,4 +35,4 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar

View File

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

View File

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

View File

@ -2,24 +2,9 @@
[![Discord](https://img.shields.io/discord/272499714048524288.svg?logo=discord)](https://discord.bentobox.world)
[![Build Status](https://ci.codemc.org/buildStatus/icon?job=BentoBoxWorld/Challenges)](https://ci.codemc.org/job/BentoBoxWorld/job/Challenges/)
Add-on for BentoBox to provide challenges for any BentoBox GameMode.
Add-on for BentoBox to provide challenges for any BentoBox GameMode. Challenges can be to collect items, to have items or blocks nearby, to amass an amount of money or island levels, or to have accomplished some player statistic. Each challenge can reward the player with money, experience points, blocks, items, or other things, like permissions, Pre-built challenges are available and there is also a Web Library of pre-built ones. Customize them to fit your needs!
## Where to find
Currently Challenges Addon is in **Beta stage**, so it may or may not contain bugs... a lot of bugs. Also it means, that some features are not working or implemented.
Latest official **Beta Release is 0.8.3**, and you can download it from [Release tab](https://github.com/BentoBoxWorld/Challenges/releases)
But it will work with BentoBox 1.14.
Latest development builds will be based on **Minecraft 1.16.1** and **BentoBox 1.14.0**.
**Nightly builds** are available in [Jenkins Server](https://ci.codemc.org/job/BentoBoxWorld/job/Challenges/lastStableBuild/).
If you like this addon but something is missing or is not working as you want, you can always submit an [Issue request](https://github.com/BentoBoxWorld/Challenges/issues) or get a support in Discord [BentoBox ![icon](https://avatars2.githubusercontent.com/u/41555324?s=15&v=4)](https://discord.bentobox.world)
## Translations
As most of BentoBox projects, Challenges Addon is translatable in any language. Everyone can contribute, and translate some parts of the addon in their language via [GitLocalize](https://gitlocalize.com/repo/2896).
If your language is not in the list, please contact to developers via Discord and it will be added there.
Unfortunately, default challenges come only in English translation. But with version 0.8.0 there will be access to different challenges libraries, where everyone could share their challenges with their translations. More information will come soon.
![Challenges](https://github.com/BentoBoxWorld/Challenges/assets/4407265/9b3c5278-3a9d-45f2-9ee1-2c1fc1199a8d)
## How to use
@ -27,21 +12,32 @@ Unfortunately, default challenges come only in English translation. But with ver
2. Restart the server
3. Edit the config.yml how you want.
4. Restart the server
5. Run the Admin challenges command to set up challenges for your game mode.
#### Challenges
#### Installation
By default, challenges addon comes without any challenge or level. On first runtime only Admin GUI will be accessible.
Admins can create their own challenges or import some default challenges, which importing also are available via Admin GUI. Default challenges contains 5 levels and 57 challenges.
There exist also Web Library, where users can download public challenges. It is accessible with Admin GUI by clicking on Web icon.
By default, challenges addon comes without any challenge or level. On first run time only Admin GUI will be accessible.
Admins can create their own challenges or import some default challenges. Default challenges contains 5 levels and 57 challenges.
There also exists a Web Library, where admins can download public challenges. It is accessible from the Admin GUI by clicking on the Web icon.
## Compatibility
- [x] BentoBox - 1.14 versions
- [x] BentoBok
- [x] BSkyBlock
- [x] AcidIsland
- [x] SkyGrid
- [x] CaveBlock
## Information
## Translations
As with most of BentoBox projects, Challenges Addon is translatable into any language. Everyone can contribute, and translate some parts of the addon in their language via [GitLocalize](https://gitlocalize.com/repo/2896).
If your language is not in the list, please contact the developers via Discord and it will be added there.
Unfortunately, default challenges come only be in English, but there are different challenges libraries where everyone can share their challenges with their translations.
## Documentation
More information can be found in the docs: https://docs.bentobox.world/en/latest/addons/Challenges/
## Bugs or feature requests
If you like this addon but something is missing or is not working as you want, you can always submit an [Issue request](https://github.com/BentoBoxWorld/Challenges/issues) or get a support in Discord [BentoBox ![icon](https://avatars2.githubusercontent.com/u/41555324?s=15&v=4)](https://discord.bentobox.world)
More information can be found in [Wiki Pages](https://docs.bentobox.world/en/latest/addons/Challenges/).

106
pom.xml
View File

@ -32,19 +32,19 @@
<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>
<spigot.version>1.20.4-R0.1-SNAPSHOT</spigot.version>
<spigot-annotations.version>1.2.3-SNAPSHOT</spigot-annotations.version>
<bentobox.version>1.20.0</bentobox.version>
<bentobox.version>2.1.0</bentobox.version>
<level.version>2.6.3</level.version>
<vault.version>1.7</vault.version>
<panelutils.version>1.0.0</panelutils.version>
<panelutils.version>1.2.0</panelutils.version>
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- This allows to change between versions and snapshots. -->
<build.version>1.0.0</build.version>
<build.version>1.3.0</build.version>
<build.number>-LOCAL</build.number>
<!-- Sonar Cloud -->
<sonar.projectKey>BentoBoxWorld_Challenges</sonar.projectKey>
@ -120,6 +120,12 @@
</repositories>
<dependencies>
<!-- This is required for PowerMockito to work and must be placed before it -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.30.2-GA</version>
</dependency>
<!-- Spigot API -->
<dependency>
<groupId>org.spigotmc</groupId>
@ -127,12 +133,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>
@ -193,6 +193,11 @@
<version>1.5.21</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
</dependencies>
<build>
@ -223,6 +228,38 @@
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.1-SNAPSHOT</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>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
@ -249,6 +286,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
@ -330,59 +368,35 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.4</version>
<version>0.8.10</version>
<configuration>
<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>
<!-- Prevents the Material is too large to mock error -->
<exclude>org/bukkit/Material*</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>pre-unit-test</id>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<id>report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.1-SNAPSHOT</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>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<formats>
<format>XML</format>
</formats>
</configuration>
</execution>
</executions>
</plugin>

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
@ -27,4 +20,4 @@ public class ChallengesPladdon extends Pladdon
{
return new ChallengesAddon();
}
}
}

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

@ -37,7 +37,7 @@ public class ChallengesGlobalAdminCommand extends CompositeCommand
@Override
public void setup()
{
this.setPermission("addon.admin.challenges");
this.setPermission("admin.challenges");
this.setParametersHelp("challenges.commands.admin.main.parameters");
this.setDescription("challenges.commands.admin.main.description");
}
@ -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,14 +102,15 @@ public class ChallengesImportManager
{
if (user != null)
{
Utils.sendMessage(user, user.getTranslation(Constants.ERRORS + "no-load",
Constants.PARAMETER_FILE, file, TextVariables.DESCRIPTION, e.getMessage()));
}
else
{
this.addon.logError("Exception when loading file. " + e.getMessage());
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());
return;
}
@ -116,14 +121,13 @@ public class ChallengesImportManager
if (user != null)
{
Utils.sendMessage(user,
user.getTranslation(Constants.ERRORS + "not-a-gamemode-world",
Constants.PARAMETER_WORLD, world.getName()));
}
else
{
this.addon.logWarning("Given world is not a gamemode world.");
world,
Constants.ERRORS + "not-a-gamemode-world",
Constants.PARAMETER_WORLD, world.getName());
}
this.addon.logWarning("Given world is not a gamemode world.");
return;
}
@ -155,6 +159,7 @@ public class ChallengesImportManager
challengeCount = reader.getKeys(false).stream().
mapToInt(challengeId -> this.createChallenge(challengeId,
prefix,
world,
reader.getConfigurationSection(challengeId))).
sum();
}
@ -178,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 " +
@ -192,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)
@ -270,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)
{
@ -636,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)
{
@ -700,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 -> {
@ -713,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)
@ -750,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
{
@ -777,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 -> {
@ -790,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)
@ -819,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
{
@ -886,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());
@ -898,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";
@ -113,41 +113,28 @@ public class ChallengesManager
* This comparator orders challenges by their level, order and name.
*/
private final Comparator<Challenge> challengeComparator = (o1, o2) -> {
if (o1.getLevel().equals(o2.getLevel()))
ChallengeLevel o1Level = this.getLevel(o1.getLevel());
ChallengeLevel o2Level = this.getLevel(o2.getLevel());
if (o1Level == null && o2Level == null)
{
if (o1.getOrder() == o2.getOrder())
{
// If orders are equal, sort by unique id
return o1.getUniqueId().compareToIgnoreCase(o2.getUniqueId());
}
else
{
// If levels are equal, sort them by order numbers.
return Integer.compare(o1.getOrder(), o2.getOrder());
}
return Integer.compare(o1.getOrder(), o2.getOrder());
}
else if (o1Level == null)
{
return -1;
}
else if (o2Level == null)
{
return 1;
}
else if (o1Level.equals(o2Level))
{
return Integer.compare(o1.getOrder(), o2.getOrder());
}
else
{
if (o1.getLevel().isEmpty() || o2.getLevel().isEmpty())
{
// If exist free level challenge, then it should be at the start.
return Boolean.compare(o2.getLevel().isEmpty(), o1.getLevel().isEmpty());
}
else
{
ChallengeLevel o1Level = this.getLevel(o1.getLevel());
ChallengeLevel o2Level = this.getLevel(o2.getLevel());
if (o1Level == null || o2Level == null)
{
return Boolean.compare(o1Level == null, o2Level == null);
}
else
{
// Sort by challenges level order numbers
return Integer.compare(o1Level.getOrder(), o2Level.getOrder());
}
}
return Integer.compare(o1Level.getOrder(), o2Level.getOrder());
}
};
@ -243,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);
}
@ -257,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.
@ -267,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;
@ -277,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!");
@ -293,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;
@ -303,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());
}
}
}
@ -312,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());
}
}
@ -329,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);
}
@ -344,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)
@ -354,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;
@ -364,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!");
@ -376,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
{
@ -393,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;
@ -403,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());
}
}
}
@ -412,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());
}
}
@ -499,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;
@ -653,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
{
@ -669,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
{
@ -680,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
{
@ -1107,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;
@ -1120,7 +1148,7 @@ public class ChallengesManager
level,
previousLevel,
challengesToDo,
level.getChallenges().size() == doneChallengeCount,
challengeList.size() == doneChallengeCount,
unlocked));
previousLevel = level;
@ -1156,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);
}
}
@ -1195,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;
}
@ -1756,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());
}
@ -1771,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());
}
@ -1893,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

@ -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

@ -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

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

View File

@ -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))
@ -791,17 +823,25 @@ public class TryToComplete
private void runCommands(List<String> commands)
{
// Ignore commands with this perm
if (user.hasPermission(this.permissionPrefix + "command.challengeexempt") && !user.isOp())
if (this.user.hasPermission(this.permissionPrefix + "command.challengeexempt") && !this.user.isOp())
{
return;
}
final Island island = this.addon.getIslandsManager().getIsland(this.world, this.user);
final String owner = island == null ? "" : this.addon.getPlayers().getName(island.getOwner());
for (String cmd : commands)
{
if (cmd.startsWith("[SELF]"))
{
String alert = "Running command '" + cmd + "' as " + this.user.getName();
this.addon.getLogger().info(alert);
cmd = cmd.substring(6).replace(Constants.PARAMETER_PLAYER, this.user.getName()).trim();
cmd = cmd.substring(6).
replaceAll(Constants.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
{
if (!user.performCommand(cmd))
@ -816,11 +856,17 @@ public class TryToComplete
continue;
}
// Substitute in any references to player
try
{
if (!this.addon.getServer().dispatchCommand(this.addon.getServer().getConsoleSender(),
cmd.replace(Constants.PARAMETER_PLAYER, this.user.getName())))
cmd = cmd.replaceAll(Constants.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))
{
this.showError(cmd);
}
@ -894,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;
}
@ -906,6 +952,8 @@ public class TryToComplete
else
{
requiredItems = Collections.emptyList();
// Set maxTime to 2, to not crash client when completing 2147483647 times.
maxTimes = 2;
}
// Return the result
@ -1159,13 +1207,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
@ -1245,9 +1296,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();
@ -1328,42 +1381,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
{
@ -1426,9 +1484,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()),
"[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

@ -7,11 +7,19 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.bukkit.*;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.World;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.*;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionType;
import org.eclipse.jdt.annotation.Nullable;
@ -186,11 +194,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));
}
@ -820,7 +831,7 @@ public class Utils
StringBuilder builder = new StringBuilder();
enchantmentMeta.getEnchants().forEach((enchantment, level) -> {
enchantmentMeta.getStoredEnchants().forEach((enchantment, level) -> {
builder.append("\n");
builder.append(user.getTranslationOrNothing(Constants.ITEM_STACKS + "meta.enchant-meta",
"[type]", prettifyObject(enchantment, user),
@ -865,8 +876,8 @@ public class Utils
final String metaReference = Constants.ITEM_STACKS + "meta.";
String meta = user.getTranslationOrNothing(metaReference + "book-meta",
"[title]", bookMeta.getTitle(),
"[author]", bookMeta.getAuthor());
"[title]", bookMeta.hasTitle() ? bookMeta.getTitle() : "",
"[author]", bookMeta.hasAuthor() ? bookMeta.getAuthor() : "");
return user.getTranslationOrNothing(Constants.ITEM_STACKS + "generic",
"[type]", prettifyObject(itemType, user),

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: |-
@ -898,7 +907,7 @@ challenges:
# Message that will be added after environment-title-multiple.
environment-list: " &7 - &e [environment]"
# Message that will replace [permissions] placeholder if there is just a single permission.
permission-single: "&c Requires [permissions] permission"
permission-single: "&c Requires [permission] permission"
# Message that will replace [permissions] placeholder if there are multiple permissions.
permissions-title: "&c Requires permissions: "
# Message that will be added after permissions-title-multiple.
@ -1189,7 +1198,7 @@ challenges:
not-enough-money: '&c It is necessary to have [value] on your account to complete the challenge.'
not-enough-experience: '&c It is necessary to have [value] EXP to complete this challenge.'
island-level: '&c Your island must be level [number] or greater to complete this challenge!'
no-load: '&c Error: Could not load file. [message]'
no-load: '&c Error: Could not load [file]. Error [message]'
load-error: '&c Error: Cannot load [value].'
no-rank: "&c You do not have rank that is high enough to do that."
cannot-remove-items: '&c Some items cannot be removed from your inventory!'
@ -1203,6 +1212,9 @@ challenges:
no-library-entries: "&c Cannot find any library entries. Nothing to show."
not-hooked: "&c Challenges Addon could not find any GameMode."
timeout: "&c This challenge requires to wait [timeout] between completions. You must wait [wait-time] till complete it again."
requirement-not-met: "&c This challenge requires [statistic] to have [number]. You have only [value]. "
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.
@ -1238,7 +1250,27 @@ challenges:
# # This will overwrite generic translation.
# name: "[type] [upgraded] [extended]"
# # Type is either specific translation or potion effect.
# uncraftable: "Uncraftable"
# water: "Water"
# mundane: "Mundane"
# thick: "Thick"
# awkward: "Awkward"
# night_vision: "Potion of Night Vision"
# invisibility: "Potion of Invisibility"
# jump: "Potion of Leaping"
# fire_resistance: "Potion of Fire Resistance"
# speed: "Potion of Swiftness"
# slowness: "Potion of Slowness"
# water_breathing: "Potion of Water Breathing"
# instant_heal: "Potion of Healing"
# instant_damage: "Potion of Harming"
# poison: "Potion of Poison"
# regen: "Potion of Regeneration"
# strength: "Potion of Strength"
# weakness: "Potion of Weakness"
# luck: "Potion of Luck"
# turtle_master: "Potion of Turtle Master"
# slow_falling: "Potion of Slow Falling"
# stone_shovel:
# # This will mean that only stone shovels will not show
# # meta information.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@ gamemode_panel:
content:
2:
1:
icon: TIPPED_ARROW:INSTANT_HEAL::::1
icon: tipped_arrow{CustomPotionColor:11546150}
title: challenges.gui.buttons.previous.name
description: challenges.gui.buttons.previous.description
data:
@ -33,7 +33,7 @@ gamemode_panel:
7: gamemode
8: gamemode
9:
icon: TIPPED_ARROW:JUMP::::1
icon: tipped_arrow{CustomPotionColor:8439583}
title: challenges.gui.buttons.next.name
description: challenges.gui.buttons.next.description
data:

View File

@ -23,7 +23,7 @@ main_panel:
8: challenge_button
3:
1:
icon: TIPPED_ARROW:INSTANT_HEAL::::1
icon: tipped_arrow{CustomPotionColor:11546150}
title: challenges.gui.buttons.previous.name
description: challenges.gui.buttons.previous.description
data:
@ -41,7 +41,7 @@ main_panel:
7: challenge_button
8: challenge_button
9:
icon: TIPPED_ARROW:JUMP::::1
icon: tipped_arrow{CustomPotionColor:8439583}
title: challenges.gui.buttons.next.name
description: challenges.gui.buttons.next.description
data:
@ -53,7 +53,7 @@ main_panel:
tooltip: challenges.gui.tips.click-to-next
5:
1:
icon: TIPPED_ARROW:INSTANT_HEAL::::1
icon: tipped_arrow{CustomPotionColor:11546150}
title: challenges.gui.buttons.previous.name
description: challenges.gui.buttons.previous.description
data:
@ -71,7 +71,7 @@ main_panel:
7: level_button
8: level_button
9:
icon: TIPPED_ARROW:JUMP::::1
icon: tipped_arrow{CustomPotionColor:8439583}
title: challenges.gui.buttons.next.name
description: challenges.gui.buttons.next.description
data:

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

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

View File

@ -82,7 +82,7 @@ public class ChallengesManagerTest {
// Mocks
@Mock
private ChallengesAddon addon;
@Mock
private Settings settings;
@Mock
private IslandWorldManager iwm;
@ -134,9 +134,11 @@ public class ChallengesManagerTest {
when(s.getDatabaseType()).thenReturn(DatabaseType.JSON);
// Addon Settings
settings = new Settings();
when(addon.getChallengesSettings()).thenReturn(settings);
when(settings.isStoreHistory()).thenReturn(true);
when(settings.getLifeSpan()).thenReturn(10);
settings.setStoreAsIslandData(false);
settings.setStoreHistory(true);
settings.setLifeSpan(10);
// Database
database = new File("database");
@ -245,97 +247,97 @@ 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));
verify(user).getTranslation("challenges.messages.load-skipping", "[value]", "name");
assertFalse(cm.loadChallenge(challenge, world, false, user, false));
verify(user).getTranslation(world, "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));
verify(user, never()).getTranslation(anyString(), anyString(), anyString());
assertTrue(cm.loadChallenge(challenge, world, true, user, true));
verify(user, never()).getTranslation(any(World.class), 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));
verify(user).getTranslation("challenges.messages.load-overwriting", "[value]", "name");
assertTrue(cm.loadChallenge(challenge, world, true, user, false));
verify(user).getTranslation(world, "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));
verify(user).getTranslation("challenges.messages.load-skipping", "[value]", "Novice");
assertFalse(cm.loadLevel(level, world, false, user, false));
verify(user).getTranslation(world, "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));
verify(user, never()).getTranslation(anyString(), anyString(), anyString());
assertTrue(cm.loadLevel(level, world, true, user, true));
verify(user, never()).getTranslation(any(World.class), 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));
verify(user).getTranslation("challenges.messages.load-overwriting", "[value]", "Novice");
assertTrue(cm.loadLevel(level, world, true, user, false));
verify(user).getTranslation(world, "challenges.messages.load-overwriting", "[value]", "Novice");
}
/**
@ -660,7 +662,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 +675,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 +690,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 +794,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));
}

View File

@ -6,7 +6,6 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@ -17,7 +16,6 @@ import java.util.Optional;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFactory;
@ -38,7 +36,6 @@ import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.configuration.WorldSettings;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.CommandsManager;
@ -46,16 +43,16 @@ import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.util.Util;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.managers.ChallengesManager;
import world.bentobox.challenges.config.Settings;
import world.bentobox.challenges.config.SettingsUtils.VisibilityMode;
import world.bentobox.challenges.managers.ChallengesManager;
/**
* @author tastybento
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({Bukkit.class, BentoBox.class, ChatColor.class, Util.class})
@PrepareForTest({ Bukkit.class, BentoBox.class, Util.class })
public class ChallengesCommandTest {
@Mock
@ -104,7 +101,7 @@ public class ChallengesCommandTest {
Optional<GameModeAddon> optionalAddon = Optional.of(gameModeAddon);
when(iwm.getAddon(any())).thenReturn(optionalAddon);
when(plugin.getIWM()).thenReturn(iwm);
@NonNull
WorldSettings ws = new TestWorldSetting();
when(iwm.getWorldSettings(any())).thenReturn(ws);
@ -143,10 +140,6 @@ public class ChallengesCommandTest {
// Challenges exist
when(chm.hasAnyChallengeData(any(World.class))).thenReturn(true);
// ChatColor
PowerMockito.mockStatic(ChatColor.class);
when(ChatColor.translateAlternateColorCodes(any(char.class), anyString())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(1, String.class));
// Settings
Settings settings = new Settings();
when(addon.getChallengesSettings()).thenReturn(settings);
@ -161,6 +154,9 @@ public class ChallengesCommandTest {
// Util
PowerMockito.mockStatic(Util.class, Mockito.RETURNS_MOCKS);
when(Util.sameWorld(any(), any())).thenReturn(true);
when(Util.translateColorCodes(anyString()))
.thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
// Command under test
cc = new ChallengesPlayerCommand(addon, ic);
}
@ -172,7 +168,7 @@ public class ChallengesCommandTest {
public void testCanExecuteWrongWorld() {
when(iwm.inWorld(any(World.class))).thenReturn(false);
assertFalse(cc.canExecute(user, "challenges", Collections.emptyList()));
verify(user).getTranslation("general.errors.wrong-world");
verify(user).getTranslation(world, "general.errors.wrong-world");
}
/**
@ -184,7 +180,7 @@ public class ChallengesCommandTest {
when(chm.hasAnyChallengeData(any(World.class))).thenReturn(false);
assertFalse(cc.canExecute(user, "challenges", Collections.emptyList()));
verify(addon).logError("There are no challenges set up in world!");
verify(user).getTranslation("challenges.errors.no-challenges");
verify(user).getTranslation(world, "challenges.errors.no-challenges");
}
/**
@ -196,8 +192,8 @@ public class ChallengesCommandTest {
when(chm.hasAnyChallengeData(any(World.class))).thenReturn(false);
assertFalse(cc.canExecute(user, "challenges", Collections.emptyList()));
verify(addon).logError("There are no challenges set up in world!");
verify(user).getTranslation("challenges.errors.no-challenges-admin", "[command]", "bsb challenges");
verify(user, never()).getTranslation("challenges.errors.no-challenges");
verify(user).getTranslation(world, "challenges.errors.no-challenges-admin", "[command]", "bsb challenges");
verify(user, never()).getTranslation(world, "challenges.errors.no-challenges");
}
/**
@ -209,8 +205,8 @@ public class ChallengesCommandTest {
when(chm.hasAnyChallengeData(any(World.class))).thenReturn(false);
assertFalse(cc.canExecute(user, "challenges", Collections.emptyList()));
verify(addon).logError("There are no challenges set up in world!");
verify(user).getTranslation("challenges.errors.no-challenges-admin", "[command]", "bsb challenges");
verify(user, never()).getTranslation("challenges.errors.no-challenges");
verify(user).getTranslation(world, "challenges.errors.no-challenges-admin", "[command]", "bsb challenges");
verify(user, never()).getTranslation(world, "challenges.errors.no-challenges");
}
/**
@ -223,8 +219,8 @@ public class ChallengesCommandTest {
when(chm.hasAnyChallengeData(any(World.class))).thenReturn(false);
assertFalse(cc.canExecute(user, "challenges", Collections.emptyList()));
verify(addon).logError("There are no challenges set up in world!");
verify(user).getTranslation("challenges.errors.no-challenges-admin", "[command]", "bsb challenges");
verify(user, never()).getTranslation("challenges.errors.no-challenges");
verify(user).getTranslation(world, "challenges.errors.no-challenges-admin", "[command]", "bsb challenges");
verify(user, never()).getTranslation(world, "challenges.errors.no-challenges");
}
/**
@ -234,7 +230,7 @@ public class ChallengesCommandTest {
public void testCanExecuteNoIsland() {
when(im.getIsland(any(), any(User.class))).thenReturn(null);
assertFalse(cc.canExecute(user, "challenges", Collections.emptyList()));
verify(user).getTranslation("general.errors.no-island");
verify(user).getTranslation(world, "general.errors.no-island");
}
/**
@ -246,16 +242,6 @@ public class ChallengesCommandTest {
verify(user, never()).sendMessage(anyString());
}
/**
* Test method for {@link ChallengesPlayerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testExecuteUserStringListOfStringConsole() {
User console = mock(User.class);
assertFalse(cc.execute(console, "challenges", Collections.emptyList()));
verify(console).sendMessage(eq("commands.help.header"), eq(TextVariables.LABEL), eq("BSkyBlock"));
}
/**
* Test method for {@link ChallengesPlayerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/

View File

@ -19,7 +19,6 @@ import java.util.Optional;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFactory;
@ -46,11 +45,12 @@ import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.util.Util;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.managers.ChallengesManager;
import world.bentobox.challenges.config.Settings;
import world.bentobox.challenges.config.SettingsUtils.VisibilityMode;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.managers.ChallengesManager;
import world.bentobox.challenges.tasks.TryToComplete;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.Utils;
/**
@ -58,7 +58,7 @@ import world.bentobox.challenges.utils.Utils;
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({Bukkit.class, BentoBox.class, ChatColor.class, Utils.class, TryToComplete.class, Util.class})
@PrepareForTest({ Bukkit.class, BentoBox.class, Utils.class, TryToComplete.class, Util.class })
public class CompleteChallengeCommandTest {
@Mock
@ -149,11 +149,6 @@ public class CompleteChallengeCommandTest {
List<String> nameList = Arrays.asList("world_maker", "world_placer", "bad_challenge_name", "world_breaker");
when(chm.getAllChallengesNames(any())).thenReturn(nameList);
// ChatColor
PowerMockito.mockStatic(ChatColor.class);
when(ChatColor.translateAlternateColorCodes(any(char.class), anyString())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(1, String.class));
// Settings
Settings settings = new Settings();
when(addon.getChallengesSettings()).thenReturn(settings);
@ -175,6 +170,8 @@ public class CompleteChallengeCommandTest {
// Util
PowerMockito.mockStatic(Util.class);
when(Util.tabLimit(any(), any())).thenAnswer((Answer<List<String>>) invocation -> (List<String>)invocation.getArgument(0, List.class));
when(Util.translateColorCodes(anyString()))
.thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
// Command under test
cc = new CompleteChallengeCommand(addon, ic);
@ -207,7 +204,8 @@ public class CompleteChallengeCommandTest {
@Test
public void testExecuteUserStringListOfStringNoArgs() {
assertFalse(cc.execute(user, "complete", Collections.emptyList()));
verify(user).getTranslation(eq("challenges.errors.no-name"));
PowerMockito.verifyStatic(Utils.class);
Utils.sendMessage(user, world, Constants.ERRORS + "no-name");
verify(user).sendMessage(eq("commands.help.header"), eq(TextVariables.LABEL), eq("BSkyBlock"));
}
@ -218,7 +216,8 @@ public class CompleteChallengeCommandTest {
public void testExecuteUserStringListOfStringUnknownChallenge() {
when(chm.getChallenge(anyString())).thenReturn(null);
assertFalse(cc.execute(user, "complete", Collections.singletonList("mychal")));
verify(user).getTranslation(eq("challenges.errors.unknown-challenge"));
PowerMockito.verifyStatic(Utils.class);
Utils.sendMessage(user, world, Constants.ERRORS + "unknown-challenge");
verify(user).sendMessage(eq("commands.help.header"), eq(TextVariables.LABEL), eq("BSkyBlock"));
}
@ -247,7 +246,8 @@ public class CompleteChallengeCommandTest {
@Test
public void testExecuteUserStringListOfStringKnownChallengeSuccessMultipleTimesNoPerm() {
assertTrue(cc.execute(user, "complete", Arrays.asList("mychal", "5")));
verify(user).getTranslation(eq("challenges.error.no-multiple-permission"));
PowerMockito.verifyStatic(Utils.class);
Utils.sendMessage(user, world, Constants.ERRORS + "no-multiple-permission");
}
/**