Compare commits

...
433 Commits
Author SHA1 Message Date
Ben Woo 278c51d056 Merge pull request #3056 from Multiverse/zax71MV5/versionCommand
Add `/mv version`
2024-03-12 10:38:12 +08:00
Zax71 caed081f82 Update Ben's name 2024-03-08 18:03:42 +00:00
Zax71 7276da7665 Implement i18n 2024-02-24 13:48:57 +00:00
Zax71 90b8729129 Add Ben and Zax71 to authors 2024-02-24 13:37:23 +00:00
Zax71 c24f198ed0 Add /mv version 2024-02-24 13:36:13 +00:00
Ben Woo 0c37c9e934 Merge pull request #3033 from Multiverse/ben/mv5/list-value-node
Implement ListValueNode and modify actions
2023-09-25 22:24:42 +08:00
Ben Woo 454bcd36e5 Refactor and fix checkstyles for some listeners 2023-09-25 14:09:09 +08:00
Ben Woo af7d5a8cb0 Remove useless MultiverseCoreListener 2023-09-25 14:08:51 +08:00
Ben Woo a44361f5e4 Merge pull request #3034 from Multiverse/zax71/MV5/gameruleCommandMerge
Zax71/mv5/gamerule command merge
2023-09-25 13:31:20 +08:00
Ben Woo 8d508358f7 Implement gamerule reset 2023-09-25 12:29:29 +08:00
Zax71 7c6d7d5883 Merge /mv gamerule and /mv gamerules 2023-09-24 10:34:11 +01:00
Ben Woo c78dbcd395 Implement ListValueNode and modify actions 2023-09-24 11:11:48 +08:00
Ben Woo b2c1aafb62 Make sure nodes is not null and fix some checkstyles 2023-09-23 10:14:10 +08:00
Ben Woo d08e6fae38 Merge pull request #3032 from Multiverse/zax71/MV5/GeneratorsCommand
Add `/mv generators` command
2023-09-23 09:52:17 +08:00
Ben Woo d6ccbd9eee Fix some checkstyles for generator command 2023-09-23 09:50:22 +08:00
Ben Woo d880ea95ed Merge pull request #3031 from Multiverse/ben/mv5/issuer-methods
Support more variety of message payload for MVCommandIssuer
2023-09-23 09:41:07 +08:00
Ben Woo 38aa2acf8e Merge pull request #3030 from Multiverse/zax71/MV5/InfoCommand
Add `/mv info`
2023-09-23 09:40:41 +08:00
Ben Woo 5845fdd541 Merge pull request #3027 from Multiverse/ben/mv5/config-suggest-parser
Implement autocomplete and string parsing for config handling
2023-09-23 09:39:15 +08:00
Ben Woo 01cfcc5684 Merge pull request #3019 from Multiverse/ben/mv5/teleporter
Ben/mv5/teleporter
2023-09-23 09:38:55 +08:00
Ben Woo 62a4e7e27d Merge pull request #3028 from Multiverse/ben/mv5/remove-unsafecallwrapper
Remove UnsafeCallWrapper as now we use varv Try
2023-09-23 09:38:39 +08:00
Zax71 ac174dcf66 Add /mv generators 2023-09-22 19:03:19 +01:00
Ben Woo 4095829eca Replace properties method in MVConfig to StringPropertyHandle 2023-09-22 23:09:31 +08:00
Ben Woo 13dc1bd0d0 Support more variety of message payload for MVCommandIssuer 2023-09-22 17:44:44 +08:00
Ben Woo 3a6c52337f Add more properties to info command and refactor 2023-09-22 17:20:41 +08:00
Ben Woo 61e3ffb7e5 Add null value formatting for MapContentProvider 2023-09-22 17:20:13 +08:00
Ben Woo 41f9989eef Fix more checkstyles and use LinkedHashMap for info command 2023-09-22 16:09:04 +08:00
Ben Woo 896524b57a Check some checkstyles for info command 2023-09-22 15:46:54 +08:00
Zax71 42ca91d05b Add /mv info 2023-09-21 18:54:49 +01:00
Ben Woo 5db5b948cc Fix some related checkstyles 2023-09-21 11:47:20 +08:00
Ben Woo 2e5679491c Remove UnsafeCallWrapper as now we use varv Try 2023-09-21 11:36:55 +08:00
Ben Woo 980d6784df Merge branch 'MV5' into ben/mv5/teleporter
# Conflicts:
#	src/main/java/org/mvplugins/multiverse/core/commands/RemoveCommand.java
2023-09-21 11:23:05 +08:00
Ben Woo a2f6e201d0 Add injection test for AsyncSafetyTeleporter 2023-09-21 11:20:23 +08:00
Ben Woo f2e193eda3 Improve node suggest javadocs 2023-09-20 23:39:04 +08:00
Ben Woo 4084cd4af1 Move property handling to a separate class 2023-09-20 23:35:10 +08:00
Ben Woo 6fe87fbc7b Implement autocomplete and string parsing for config handling 2023-09-20 16:32:25 +08:00
Ben Woo 6611ec4457 Make defaultValue a supplier and fix some checkstyle in ConfigNode 2023-09-20 13:45:14 +08:00
Ben Woo e4bff69372 Pass multiverse core instance directly into WorldConfigNodes 2023-09-20 12:39:59 +08:00
Ben Woo 5dba08dd1b Merge pull request #3025 from Multiverse/ben/mv5/fix-remove-locale
Fix remove success message key
2023-09-20 12:34:02 +08:00
Ben Woo 2e0ce517a8 Merge pull request #3026 from Multiverse/ben/mv5/enum-completion
Implement lowercased enum completion and fix some checkstyles
2023-09-20 12:33:47 +08:00
Ben Woo 7fcfa64538 Merge pull request #3024 from Multiverse/ben/mv5/mv-world-oncontext
Ben/mv5/mv world oncontext
2023-09-20 12:33:33 +08:00
Ben Woo cce041877f Cleanup NodeGroup with docs and annotation 2023-09-20 12:31:34 +08:00
Ben Woo 6ba51fa573 Implement lowercased enum completion and fix some checkstyles 2023-09-20 12:25:03 +08:00
Ben Woo bbfc1a05e8 Cleanup MultiverseCommand and add docs 2023-09-20 12:18:04 +08:00
Ben Woo 80fcf8fe19 Fix remove success message key 2023-09-20 12:10:02 +08:00
Ben Woo b99de26deb Use MultiverseWorld instead of worldname string for RemoveCommand 2023-09-20 12:06:08 +08:00
Ben Woo fb240a19fa Add context resolving for MultiverseWorld class 2023-09-20 12:02:29 +08:00
Ben Woo 180680f297 Add method to get MultiverseWorld from a bukkit world. 2023-09-20 12:01:26 +08:00
Ben Woo 91f9842b24 Merge pull request #3022 from Multiverse/dtm/mv5/teleporter_attempt
Add AsyncAttempt.
2023-09-14 22:34:34 +08:00
Ben Woo bf8244e587 Refactor some async attempt handling 2023-09-14 11:30:35 +08:00
Ben Woo 94bcca914f Add warning of player still in world while unloading 2023-09-14 11:26:07 +08:00
Ben Woo 23b429940c Fully implement AsyncResult 2023-09-14 11:03:45 +08:00
Jeremy Wood 3df46bc55c Add AsyncAttempt for example purposes. 2023-09-13 16:16:47 -04:00
Ben Woo 2f3306aa97 Add class level docs for AsyncResult 2023-09-14 00:37:33 +08:00
Ben Woo 82c84c2c7c Implement AsyncResult, a wrapper for CompletableFuture 2023-09-14 00:36:22 +08:00
Ben Woo 2642d940ba Clearer docs for tolerance and radius for getSafeLocation 2023-09-13 23:32:10 +08:00
Ben Woo 404ab738c0 Fix imports 2023-09-13 23:21:23 +08:00
Ben Woo bc1a2ff8a1 Merge branch 'MV5' into ben/mv5/teleporter
# Conflicts:
#	src/main/java/org/mvplugins/multiverse/core/commands/DeleteCommand.java
#	src/main/java/org/mvplugins/multiverse/core/commands/RegenCommand.java
#	src/main/java/org/mvplugins/multiverse/core/commands/RemoveCommand.java
#	src/main/java/org/mvplugins/multiverse/core/commands/UnloadCommand.java
#	src/main/java/org/mvplugins/multiverse/core/destination/core/CannonDestination.java
#	src/main/java/org/mvplugins/multiverse/core/destination/core/ExactDestination.java
#	src/main/java/org/mvplugins/multiverse/core/destination/core/WorldDestination.java
#	src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java
#	src/main/java/org/mvplugins/multiverse/core/permissions/CorePermissionsChecker.java
#	src/main/java/org/mvplugins/multiverse/core/world/LoadedMultiverseWorld.java
#	src/main/java/org/mvplugins/multiverse/core/world/helpers/PlayerWorldTeleporter.java
2023-09-13 23:04:36 +08:00
Jeremy Wood db0d5da5ce Merge pull request #3020 from Multiverse/ben/mv5/nuke-worldmanager
Nuke the old world manager
2023-09-13 09:55:32 -04:00
Ben Woo fbab3bc269 Nuke the old world manager 2023-09-12 23:05:51 +08:00
Ben Woo ba93195671 Move logic of teleporting players out of world from world manager 2023-09-12 18:07:12 +08:00
Ben Woo 9ddfa59712 Merge branch 'MV5' into ben/mv5/teleporter
# Conflicts:
#	src/main/java/org/mvplugins/multiverse/core/commands/TeleportCommand.java
2023-09-12 17:25:50 +08:00
Ben Woo 6f014838e9 Cleanup commands checkstyle and flags 2023-09-12 17:22:20 +08:00
Ben Woo ef2b42d9a0 Check for destination's checkTeleportSafety 2023-09-12 16:36:43 +08:00
Ben Woo 245fac98e5 Implement new AsyncSafetyTeleporter 2023-09-12 16:33:43 +08:00
Ben Woo 0e43444523 Merge pull request #3018 from Multiverse/ben/mv5/player-world-action
Implement player world actions and some refactor
2023-09-12 14:20:42 +08:00
Ben Woo f9bd7f136d Split PlayerWorldAction to PlayerWorldTeleporter and EnforcementHandler 2023-09-12 13:13:54 +08:00
Ben Woo a45849799d Implement player world actions and some refactor 2023-09-12 12:45:09 +08:00
Ben Woo 80dba5068c Merge pull request #2991 from zax71/MV5-always-spawn-location
Implement JoinDestination and EnableJoinDestination config options
2023-09-12 11:38:10 +08:00
Ben Woo b78941c0a0 Refactor join-destination config and use async teleport 2023-09-12 11:33:50 +08:00
Ben Woo dc3ec52d74 Merge branch 'MV5' into MV5-always-spawn-location 2023-09-12 11:27:38 +08:00
Ben Woo 57b27ce6e6 Fix hk2 ServiceLocatorGenerator 2023-09-12 11:16:30 +08:00
Ben Woo d6c8d5381f Merge branch 'MV5' into MV5-always-spawn-location
# Conflicts:
#	src/main/java/org/mvplugins/multiverse/core/config/MVCoreConfigNodes.java
#	src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java
2023-09-12 10:38:04 +08:00
Ben Woo 5178d68828 Merge pull request #3017 from Multiverse/dtm/checkstyle/imports
Fix import order check.
2023-09-12 10:26:49 +08:00
Ben Woo f6ba48c5f2 Apply new import order changes 2023-09-12 10:24:58 +08:00
Jeremy Wood ede47e834b Fix import order check. 2023-09-11 22:17:47 -04:00
Ben Woo df7e333610 Merge pull request #3016 from Multiverse/ben/mv5/repackage
Move package to org.mvplugins.multiverse.core
2023-09-12 01:03:17 +08:00
Ben Woo 48f9e65321 Change third party relocate to org.mvplugins.multiverse.external. 2023-09-12 01:02:00 +08:00
Ben Woo 474630d1ff Move package to org.mvplugins.multiverse.core 2023-09-12 00:56:20 +08:00
Ben Woo 1812315033 Merge pull request #3015 from Multiverse/ben/mv5/import-refactor
Optimise all imports
2023-09-12 00:45:18 +08:00
Ben Woo e31ef1428c Fix import order checkstyle and remove comment 2023-09-12 00:43:46 +08:00
Ben Woo 256ac67cf1 Optimise all imports 2023-09-12 00:41:17 +08:00
Ben Woo 9dbe7e20ad Merge pull request #3014 from Multiverse/ben/mv5/a-lot-of-checkstyle
Fix a lot of checkstyles throughout
2023-09-12 00:29:14 +08:00
Ben Woo e005b266ea Add a todo about the todo checkstyle to enable todo warning after mv 2023-09-12 00:19:27 +08:00
Ben Woo 1dfdb611c6 Set back throw count to 0 2023-09-12 00:15:13 +08:00
Ben Woo dd4b01f922 Fix a lot of checkstyles throughout 2023-09-12 00:07:25 +08:00
Ben Woo 39f3805ef3 Fix all imports once and for all 2023-09-11 23:09:34 +08:00
Jeremy Wood d3fa42a035 Merge pull request #3013 from Multiverse/world-revamp-continue
Continue revamping World/WorldManager.
2023-09-11 10:42:47 -04:00
Ben Woo 46d115b2f3 Fix LocalizationTest 2023-09-11 22:13:48 +08:00
Ben Woo 690d956ce2 Merge branch 'MV5' into world-revamp-continue 2023-09-11 22:11:32 +08:00
Ben Woo ffec23c9ed Add docs and fix more checkstyles 2023-09-11 21:52:16 +08:00
Jeremy Wood d77fb43536 Add continue-on-error to step as well. 2023-09-11 08:48:23 -04:00
Jeremy Wood 86e2ab45fb Change checkstyle workflow back to PR annotations without failure. 2023-09-11 08:44:05 -04:00
Jeremy Wood 5a474d7efa Merge pull request #3010 from Multiverse/ben/mv5/nested-locale-message
Add support for nested Message within MessageReplacement and fix some checkstyles
2023-09-11 08:30:09 -04:00
Jeremy Wood ca9b244a89 Merge pull request #3011 from Multiverse/ben/mv5/upstream-checkstyle
Upstream checkstyle changes from world revamp
2023-09-11 08:13:42 -04:00
Ben Woo 329901afa6 Remove public from config nodes and remove names that are the same as path 2023-09-11 17:06:06 +08:00
Ben Woo 61570b1a7f Merge pull request #3012 from Multiverse/ben/mv5/improve-world-purge
Cleanup world purger and add docs
2023-09-11 16:48:31 +08:00
Ben Woo aa063007e8 Fix some checktyle issue in WorldPurger 2023-09-11 16:47:39 +08:00
Ben Woo 58c13c1f73 Copy spawn location when cloning world 2023-09-11 16:42:27 +08:00
Ben Woo c0f2168ba4 Copy spawn location only if seed didnt change on regen 2023-09-11 16:40:03 +08:00
Ben Woo ef0cb4b893 Do not apply spawn location if it's a null location 2023-09-11 16:39:34 +08:00
Ben Woo c2ff8a467f Make unsettable properties have null name 2023-09-11 16:38:49 +08:00
Ben Woo 404a2f4183 Cleanup adjust spawn logic 2023-09-11 16:03:36 +08:00
Ben Woo a4a5be20f9 Use .get() for world folder, since it should fail if null 2023-09-11 15:49:27 +08:00
Ben Woo 481933b948 Add support for removing players before unloading world 2023-09-11 15:39:06 +08:00
Ben Woo 379e0172c4 Fix regen world keeping seed not working 2023-09-11 15:38:28 +08:00
Ben Woo d8334ad71a Refactor world results and add docs 2023-09-11 14:35:56 +08:00
Ben Woo ba7b6ae951 Upstream checkstyle changes from world revamp 2023-09-11 13:40:50 +08:00
Ben Woo 1745c16bec Add support for nested Message within MessageReplacement and fix some checkstyles 2023-09-11 13:37:38 +08:00
Ben Woo 7490996ecb Make getWorldConfig return an Option 2023-09-11 11:49:52 +08:00
Ben Woo bf7a708fb3 Reorder and add more world blacklisted names 2023-09-11 11:41:40 +08:00
Ben Woo d02cd63244 Merge pull request #3008 from Multiverse/ben/mv5/results
Revamp results to support value returns
2023-09-11 10:55:08 +08:00
Jeremy Wood 089655fada Fix some more checkstyle issues. 2023-09-10 13:35:25 -04:00
Jeremy Wood 8ffd716190 Fix some checkstyle issues. 2023-09-10 13:34:36 -04:00
Ben Woo 99846b5567 Add javadocs and fix some checkstyles 2023-09-10 23:00:15 +08:00
Ben Woo 6f9f9085fd Refactor world results to remove success reason 2023-09-10 22:29:42 +08:00
Ben Woo 656d9ac208 Refactor map Attempt methods 2023-09-10 22:17:10 +08:00
Ben Woo 2fe6297b1d Fix unintended changes to result 2023-09-10 21:45:30 +08:00
Ben Woo c8fed72137 Refactor to Result<S, F> and Attempt<T, F> 2023-09-10 21:37:36 +08:00
Ben Woo f9877201f5 Revamp results to support value returns 2023-09-10 19:43:56 +08:00
Zax71andBen Woo d1bc67204b Update src/main/java/com/onarandombox/MultiverseCore/config/MVCoreConfigNodes.java
Co-authored-by: Ben Woo <30431861+benwoo1110@users.noreply.github.com>
2023-09-10 12:15:05 +01:00
Zax71 c8e1143e32 Implement requested changes 2023-09-10 10:22:13 +01:00
Ben Woo e318f1e86f Cleanup world purger and add docs 2023-09-10 15:03:05 +08:00
Ben Woo b780f5c2f3 Update gamerules command to new world manager api 2023-09-10 14:10:40 +08:00
Ben Woo 1740137d1e Merge branch 'MV5' into world-revamp-continue
# Conflicts:
#	src/main/java/com/onarandombox/MultiverseCore/commandtools/MVCommandCompletions.java
2023-09-10 14:05:41 +08:00
Ben Woo 323145ebf0 Merge pull request #3006 from Multiverse/ben/mv5/config-migrate
Implement worlds.yml config migrate
2023-09-10 14:04:03 +08:00
Ben Woo 1a2b88599a Merge pull request #3007 from Multiverse/dtm/mv5/world-revamp-continue-tweaks
WorldManager tweaks.
2023-09-10 14:01:18 +08:00
Ben Woo 903941eb01 Fix wildcard imports for worldmanager 2023-09-10 13:59:01 +08:00
Ben Woo b8c10c412d Improve gamerules command with filter and page flag 2023-09-10 13:56:50 +08:00
Ben Woo 95a1fddbe5 Fix some regression on command flag registering and completion 2023-09-10 13:54:44 +08:00
Jeremy Wood 1eb33c6972 Clean up some return counts in WorldManager. 2023-09-10 01:35:53 -04:00
Ben Woo b2ed43ba22 Add docs to new migration classes 2023-09-10 12:23:20 +08:00
Ben Woo c61c98ff5e Remove serializable including whitespace and newline 2023-09-10 12:03:35 +08:00
Ben Woo 13b9419b85 Improve and fix minor migration regressions 2023-09-10 11:55:00 +08:00
Jeremy Wood e81296015e Ignore DeclarationOrder check. 2023-09-09 23:54:05 -04:00
Jeremy Wood 6b40c3a190 Add interface for keeping world settings for options. 2023-09-09 23:53:45 -04:00
Ben Woo fcbaffc821 Implement basic config migration for worlds.yml 2023-09-10 00:50:58 +08:00
Jeremy Wood f556f6f98a Refactor populateWorldFromConfig to be smaller. 2023-09-09 11:48:54 -04:00
Jeremy Wood c340f16f63 Use different parameter number checks for methods and constructors. 2023-09-09 11:28:24 -04:00
Jeremy Wood 700b0cc81c Allow checkstyle suppression trailing comments. 2023-09-09 11:25:17 -04:00
Jeremy Wood 34b55e4b4d Merge pull request #3004 from Multiverse/dtm/mv5/world-revamp-continue-tweaks
Tweaks for world revamp
2023-09-09 11:19:22 -04:00
Jeremy Wood df0db292ed Fix incorrect world name var. 2023-09-09 11:19:10 -04:00
Jeremy Wood c1d2fe48f0 Reduce Result boilerplate in WorldManager. 2023-09-09 11:14:01 -04:00
Jeremy Wood ba5c054298 Add a bunch of missing package-info.java. 2023-09-09 10:54:10 -04:00
Jeremy Wood 503d054859 Temporarily reduce severity of PackageName check. 2023-09-09 10:52:59 -04:00
Jeremy Wood 6fd56e56e1 Create private message replacement methods in WorldManager. 2023-09-09 10:51:52 -04:00
Jeremy Wood 1affa421d3 Only report on warning/error. 2023-09-09 10:28:55 -04:00
Jeremy Wood 09e1e11016 Give pr write permission to checkstyle workflow. 2023-09-09 10:26:20 -04:00
Jeremy Wood 7a8bd674d2 Fix more checkstyle issues in WorldManager. 2023-09-09 10:23:13 -04:00
Ben Woo ac3666cf7c Merge pull request #3003 from Multiverse/ben/mv5/world-revamp-codestyle
Loosen up some codestyle
2023-09-09 22:21:45 +08:00
Jeremy Wood f5dc049b35 Loosen ClassFanOutComplexity check. 2023-09-09 10:14:59 -04:00
Jeremy Wood ffb578039f Try github-pr-review reporter for checkstyle workflow. 2023-09-09 10:02:10 -04:00
Jeremy Wood 654c12b627 Make checkstyle concessions. 2023-09-09 09:59:00 -04:00
Ben Woo c71bdd83d6 Merge pull request #2997 from Multiverse/better-flag-handling
Better flag handling
2023-09-09 20:05:21 +08:00
Ben Woo b70960d39c Add javadocs to new command flag methods 2023-09-09 20:02:50 +08:00
Ben Woo 2f65bf4597 Merge pull request #2992 from zax71/MV5-gamerules-command
Implement `/mv gamerules` command
2023-09-09 19:54:21 +08:00
Zax71 ee4a8c8ec9 Fix (some) of the checkstyle violations 2023-09-09 12:27:44 +01:00
Zax71 48ff8d8bd1 Switch to ContentDisplay API 2023-09-09 12:16:48 +01:00
Ben Woo 0f105b1777 pain: Add docs to the new world related classes 2023-09-09 13:46:32 +08:00
Ben Woo 4cbe2eaca9 Loosen up some codestyle 2023-09-09 12:32:37 +08:00
Ben Woo 8e95c22c4d Refactor and fix some world manager code style 2023-09-09 12:31:43 +08:00
Ben Woo 5c7c9ba465 Improve world config management with parsing of new and removed worlds on reload 2023-09-09 00:41:36 +08:00
Ben Woo b4617c1c1f Eradicate all reference of offline world 2023-09-08 23:41:26 +08:00
Ben Woo f0d2499dd2 Refactor multiverse world class and getters naming 2023-09-08 23:19:43 +08:00
Ben Woo 17f2f58c1d Fix clone command newworld replacement id 2023-09-08 23:10:47 +08:00
Ben Woo 27ff3b7a7b Merge pull request #3001 from Multiverse/dtm/mv5/world-revamp-continue-patch
Apply basic checkstyle fixes.
2023-09-08 22:43:14 +08:00
Jeremy Wood 8f439abd1b Merge remote-tracking branch 'origin/world-revamp-continue' into dtm/mv5/world-revamp-continue-patch
# Conflicts:
#	src/main/java/com/onarandombox/MultiverseCore/worldnew/WorldManager.java
2023-09-08 09:13:41 -04:00
Jeremy Wood 035005bac3 Apply basic checkstyle fixes to DataStore. 2023-09-08 09:08:30 -04:00
Jeremy Wood 324328f254 Apply basic checkstyle fixes to WorldConfigManager. 2023-09-08 09:07:46 -04:00
Jeremy Wood 7582a84cc6 Apply basic checkstyle fixes to WorldConfigNodes. 2023-09-08 09:07:21 -04:00
Ben Woo cadb931d4c Fix adjust spawn not applying 2023-09-08 21:05:57 +08:00
Jeremy Wood 93d23115ff Apply basic checkstyle fixes to WorldConfig. 2023-09-08 09:04:23 -04:00
Jeremy Wood 58d37e93ee Apply basic checkstyle fixes to NullLocation. 2023-09-08 09:03:10 -04:00
Jeremy Wood 11edd8e631 Apply basic checkstyle fixes to WorldPurger. 2023-09-08 09:02:17 -04:00
Jeremy Wood caba4100a3 Apply basic checkstyle fixes to OfflineWorld. 2023-09-08 08:59:36 -04:00
Jeremy Wood 7726cf3485 Apply basic checkstyle fixes to MVWorld. 2023-09-08 08:58:43 -04:00
Jeremy Wood 1ca6b20755 Apply basic checkstyle fixes to WorldManager. 2023-09-08 08:52:35 -04:00
Ben Woo 9c703ff329 Fix clone world ignore file 2023-09-08 19:51:08 +08:00
Ben Woo 0513865f43 Use Try<Void> for config loading and saving 2023-09-08 19:43:04 +08:00
Ben Woo f1ee2ee227 Merge branch 'MV5' into world-revamp-continue 2023-09-08 15:50:59 +08:00
Jeremy Wood 4f987da090 Merge remote-tracking branch 'origin/main' into MV5 2023-09-08 01:43:37 -04:00
Jeremy Wood 17129f68d2 Merge pull request #3000 from Multiverse/dtm/checkstyle/fix_lparen
Fix lparen issues in checkstyle.
2023-09-08 01:43:03 -04:00
Jeremy Wood e00b06692f Remove LPAREN from SeparatorWrap check. 2023-09-08 01:42:21 -04:00
Jeremy Wood c4063ed5e7 Merge pull request #2999 from Multiverse/dtm/mv5/merge_main
Merge main into MV5.
2023-09-08 01:26:46 -04:00
Jeremy Wood 25a5013a6c Merge remote-tracking branch 'origin/main' into dtm/mv5/merge_main 2023-09-08 01:22:29 -04:00
Jeremy Wood a2339fac2f Merge pull request #2998 from Multiverse/dtm/checkstyle/fix_checkstyle
Soften up checkstyle significantly.
2023-09-08 01:21:33 -04:00
Jeremy Wood 227cddab7c Soften up checkstyle significantly. 2023-09-08 01:19:06 -04:00
Ben Woo f9c6c441e1 Add back /mvtp shorthand command 2023-09-07 23:54:51 +08:00
Ben Woo 3cdf9736ec Refactor a better method of registering and using command flags 2023-09-07 23:31:54 +08:00
Ben Woo 89c6eb41cb Refactor clone world into multiple smaller methods 2023-09-07 22:53:53 +08:00
Ben Woo 7ab8f219dd Better copy folder implementation with try 2023-09-07 22:05:45 +08:00
Ben Woo 6ebcd40a50 Implement remaining locales for clone and regen 2023-09-07 12:20:28 +08:00
Ben Woo 6427881c98 Finish up clone command 2023-09-07 12:07:01 +08:00
Ben Woo 3ef72a993a Implement configurable transfer of data during regen 2023-09-07 11:50:30 +08:00
Ben Woo 9cb8724db2 Finish up regen world 2023-09-07 11:38:29 +08:00
Ben Woo a0fa27f926 Merge branch 'MV5' into world-revamp-continue 2023-09-07 10:30:35 +08:00
Ben Woo 0b7f3246a1 Remove GHA test checkstyle args 2023-09-07 10:30:11 +08:00
Ben Woo 7060e60ddd Merge branch 'MV5' into world-revamp-continue 2023-09-07 10:25:44 +08:00
Ben Woo a292c1bf7d Bump dependencies 2023-09-07 10:21:21 +08:00
Ben Woo 0c3d529285 Merge branch 'main' into MV5
# Conflicts:
#	config/mv_checks.xml
2023-09-07 10:04:54 +08:00
Ben Woo e84fb1f1ba Merge pull request #2996 from Multiverse/mockbukkit-bump
Bump MockBukkit with the onDisable fix
2023-09-07 10:04:05 +08:00
Ben Woo b51cd645bb Bump MockBukkit with the onDisable fix 2023-09-07 09:48:47 +08:00
Ben Woo ff88b30959 Merge pull request #2995 from Multiverse/dtm/no_gradle_checkstyle
Remove checkstyle from gradle.
2023-09-07 09:22:20 +08:00
Jeremy Wood fa6a01d690 Remove checkstyle from gradle. 2023-09-06 18:01:13 -04:00
Jeremy Wood 5f9a002a07 Merge pull request #2994 from Multiverse/dtm/checkstyle_upgrade
Upgrade Checkstyle & Rules.
2023-09-06 17:55:37 -04:00
Jeremy Wood 3198fcc4b1 Fix job name in pr.checkstyle.yml. 2023-09-06 17:54:19 -04:00
Jeremy Wood d50e8c1dde Remove checkstyle debug flag. 2023-09-06 17:49:59 -04:00
Jeremy Wood 87271aa4eb Revert "Test change that fails checkstyle."
This reverts commit 5b8984a492.
2023-09-06 17:49:41 -04:00
Jeremy Wood 5b8984a492 Test change that fails checkstyle. 2023-09-06 17:46:50 -04:00
Jeremy Wood 49fcadf434 Use the correct file extension for checkstyle config. 2023-09-06 17:43:25 -04:00
Jeremy Wood 950fe1217a Add reviewdog debug flag for checkstyle action. 2023-09-06 17:42:17 -04:00
Jeremy Wood 8b895d41f7 Add workflow for running and reporting checkstyle. 2023-09-06 17:37:31 -04:00
Jeremy Wood dcbcca9a62 Remove extra check. 2023-09-06 17:23:15 -04:00
Jeremy Wood bc830ee780 Configure Whitespace checkstyle. 2023-09-06 17:22:50 -04:00
Jeremy Wood 407dcb3125 Configure Regexp checkstyle. 2023-09-06 13:41:41 -04:00
Jeremy Wood 405a033d85 Configure Size Violations checkstyle. 2023-09-06 13:40:19 -04:00
Ben Woo 3f075169a4 Implement basic regen command 2023-09-07 00:27:25 +08:00
Ben Woo af2fc7c630 Implement basic clone command 2023-09-07 00:07:46 +08:00
Jeremy Wood 073d13cf4d Configure Naming Conventions checkstyle. 2023-09-06 12:05:47 -04:00
Jeremy Wood e8e8c4aff6 Configure Modifiers checkstyle. 2023-09-06 11:40:17 -04:00
Ben Woo 12aedc1942 Merge pull request #2993 from Multiverse/fix-binding
Fix binding plugin and bump MockBukkit
2023-09-06 23:33:11 +08:00
Ben Woo b78ea7c7ba Whoops wrong mockbukkit version 2023-09-06 23:22:38 +08:00
Ben Woo dbf0aeeb4c Add papermc repo for mockbukkit 2023-09-06 23:19:24 +08:00
Ben Woo 7246d433bc Fix binding plugin and bump MockBukkit 2023-09-06 23:07:16 +08:00
Jeremy Wood 67f2f1f6b0 Configure Miscellaneous checkstyle. 2023-09-06 10:03:44 -04:00
Jeremy Wood d7f236492b Configure Metrics checkstyle. 2023-09-06 09:43:37 -04:00
Jeremy Wood 086c3e8af0 Configure Imports checkstyle. 2023-09-06 09:26:00 -04:00
Jeremy Wood c62c1278ec Configure Coding checkstyle. 2023-09-06 09:17:31 -04:00
Jeremy Wood 1d47473cd3 Configure Class Design checkstyle. 2023-09-06 08:22:01 -04:00
Jeremy Wood f725723932 Configure Block Checks checkstyle. 2023-09-06 07:57:36 -04:00
Jeremy Wood 28edf86c96 Configure Annotation checkstyle. 2023-09-06 01:15:33 -04:00
Jeremy Wood ab2dd9d316 Configure Javadoc checkstyle. 2023-09-06 01:05:13 -04:00
Jeremy Wood e04b0faa85 Upgrade checkstyle to version 10.12.2. 2023-09-05 23:52:20 -04:00
Jeremy Wood 6a309f04dc Update dtd reference in mv_checks.xml. 2023-09-05 23:33:56 -04:00
Ben Woo f056dcdbc9 Better error handling of world folder deletion 2023-09-06 00:13:53 +08:00
Ben Woo d01a884025 Cleanup WorldManager and improve on locale results 2023-09-05 23:47:58 +08:00
Ben Woo eb5bb4e234 Implement locale error messages for wm result 2023-09-05 18:57:35 +08:00
Ben Woo 8fc2371077 Filter away already loaded worlds for getPotentialWorlds 2023-09-05 15:57:10 +08:00
Ben Woo fda0e038f5 Implement getPotentialWorlds 2023-09-05 15:54:51 +08:00
Ben Woo 80ff02a92b Improve import world result 2023-09-05 15:42:45 +08:00
Ben Woo e8ca95505b Implement new generator API 2023-09-05 15:17:27 +08:00
Ben Woo ec0000bc8a Fix wrong context optional check and arg being null 2023-09-05 00:21:32 +08:00
Ben Woo 82f47af924 Completely remove the old WorldManager from startup 2023-09-05 00:08:38 +08:00
Ben Woo fe26ccb1eb Make spawning amount apply and rename it 2023-09-04 23:58:47 +08:00
Ben Woo f519639893 Fix weather and spawning 2023-09-04 23:48:35 +08:00
Ben Woo 5278eccad2 Fix imports for reload command 2023-09-04 23:30:26 +08:00
Ben Woo 32fb25854f Migrate portal, entity and worldpurger to new wm 2023-09-04 23:30:13 +08:00
Ben Woo c253dc1322 Fix gamerule command permission 2023-09-04 21:51:22 +08:00
zax71 1ac54b7e1d Add i18n 2023-09-04 13:08:39 +01:00
zax71 3b7a801a0c Implement JoinDestination and EnableJoinDestination config options 2023-09-04 12:30:50 +01:00
Ben Woo 0a62081d03 Move weather handling to new wm 2023-09-04 13:37:29 +08:00
Ben Woo 0824108109 Move chat prefix to new wm and fix more imports 2023-09-04 11:33:53 +08:00
Ben Woo c62aa91db7 Move world listener to handle new world manager 2023-09-04 11:27:25 +08:00
Ben Woo 90eb1c882b Dumps command use new wm and fix some imports 2023-09-04 10:48:08 +08:00
Ben Woo 891f7ca136 Remove old wm reference in bstats, tests and placeholders 2023-09-04 10:34:32 +08:00
Ben Woo 55703e6f39 Merge pull request #2989 from zax71/MV5-fix-dumps-command
Fix /mv dumps to support ANSI and UTF-8 encoded log files
2023-09-04 09:59:30 +08:00
Ben Woo f280e2076c Minor cleanup 2023-09-04 09:54:00 +08:00
zax71 17dff457b2 Chore: codestyle changes 2023-09-03 17:36:14 +01:00
Ben Woo 4eb8dfbc67 Move command completion, context, conditions to new world manager api 2023-09-04 00:16:44 +08:00
Ben Woo 08b87cba39 Move destination to new world manager api 2023-09-03 23:42:38 +08:00
Ben Woo 791d8b653c Allow permission check for offline worlds 2023-09-03 23:40:08 +08:00
Ben Woo 6f673066a8 Fix list command permissions checking 2023-09-03 23:38:22 +08:00
Ben Woo f524c5bdde Implement proper spawn location 2023-09-03 23:25:10 +08:00
Ben Woo dc75e87223 Move entrycheck, playerlistener and worldnamechecker to api 2023-09-03 22:21:28 +08:00
Ben Woo d77d7032dd Update list command and fix importWorld bug 2023-09-03 16:15:55 +08:00
Ben Woo fa4391e543 Merge branch 'MV5' into world-revamp-continue 2023-09-03 15:52:56 +08:00
Ben Woo 046840f0d9 refactor: Remove deprecated and unused classes 2023-09-03 15:52:02 +08:00
Ben Woo 3356757c13 Implement proper reloading of worlds config 2023-09-03 15:39:57 +08:00
Ben Woo dff192f3ce Make MVWorld constructor non-public 2023-09-03 14:55:39 +08:00
Ben Woo f2a3d3f85a Refactor newMVWorld instance creation 2023-09-03 14:53:51 +08:00
Ben Woo 550dae92e9 Implement more world manager features 2023-09-03 14:35:27 +08:00
zax71 1fef714b8f Fix /mv dumps to support ANSI and UTF-8 encoded log files 2023-09-02 19:08:09 +01:00
zax71 b42b77b0bf implement /mv gamerules command 2023-09-02 18:04:31 +01:00
Ben Woo b154606922 Finish basic CRUD for new world management 2023-09-03 00:51:07 +08:00
Ben Woo 7828c92926 Add entryfee, spawning and spawn location 2023-09-02 23:07:39 +08:00
Ben Woo 1f7b8ffa96 Add remaining world properties methods 2023-09-02 22:30:06 +08:00
Ben Woo 35993419ca Implement basic load, unload and remove world 2023-09-02 21:59:53 +08:00
Ben Woo a8fbeb53d4 Update bukkit world when world config node set 2023-09-02 17:04:30 +08:00
Ben Woo e1eae48bc7 Implement basic create and delete world 2023-09-02 16:54:33 +08:00
Ben Woo 5dd22b5d9b Basic mvworld and offline world 2023-09-02 16:12:34 +08:00
Ben Woo 07b543a845 Implement AddWorldOptions to condense method parameters 2023-09-02 15:19:30 +08:00
Ben Woo f7295e2c2e Cleanup TODO messages 2023-09-02 14:50:10 +08:00
Ben Woo a7644b6866 Merge pull request #2975 from zax71/MV5-version-command
Implement `/mv dumps` command
2023-09-01 23:52:45 +08:00
Ben Woo 381f440a6b Merge branch 'MV5' into MV5-version-command 2023-09-01 23:42:55 +08:00
Ben Woo 4300d83c90 Merge pull request #2986 from zax71/MV5-coord-command
Add `/mv coordinates` command
2023-09-01 23:42:04 +08:00
Ben Woo adcbcdb7df Merge pull request #2987 from Multiverse/new-config-migrate
Do not migrate if new config file is created
2023-09-01 23:41:51 +08:00
Ben Woo b57b70aa28 Merge pull request #2988 from Multiverse/world-config-props
World config props
2023-09-01 23:41:38 +08:00
Ben Woo 7a8f468f98 Minor refactor to dumps command 2023-09-01 23:39:36 +08:00
Ben Woo 867f4a447d Better error handling for finding files in server directory 2023-09-01 23:33:30 +08:00
Ben Woo 55aac81258 Merge branch 'MV5' into pr/2975
# Conflicts:
#	src/main/java/com/onarandombox/MultiverseCore/world/SimpleMVWorldManager.java
2023-09-01 23:28:05 +08:00
Ben Woo 194dc8ef8a Fix error message i18n path key 2023-09-01 23:26:23 +08:00
Ben Woo c7c344730b Minor refactor to coord command and fix tests 2023-09-01 23:21:57 +08:00
Zax71andBen Woo f8b75c0781 Update src/main/java/com/onarandombox/MultiverseCore/commands/CoordinatesCommand.java
Co-authored-by: Ben Woo <30431861+benwoo1110@users.noreply.github.com>
2023-09-01 23:20:09 +08:00
Zax71 dc89161a04 refactor: rename permission 2023-09-01 23:20:08 +08:00
zax71 90522a014e Add /mv coordinates 2023-09-01 23:20:08 +08:00
Ben Woo 6effeacd1b Add getWorldConfig method 2023-09-01 11:20:25 +08:00
Ben Woo 42eadd91a5 Adda remaining properties methods to WorldConfig 2023-09-01 11:00:59 +08:00
Ben Woo 1b2f8889ce Do not migrate if new config file is created 2023-09-01 00:03:29 +08:00
Ben Woo 1e9f19b01f Merge pull request #2841 from Multiverse/list-command
feat: Implement list command
2023-08-31 23:58:56 +08:00
Ben Woo da1d059b84 Update list command to new api changes 2023-08-31 23:55:40 +08:00
Ben Woo 55805aa618 Merge branch 'MV5' into list-command
# Conflicts:
#	src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java
2023-08-31 23:34:10 +08:00
Ben Woo d1ff487a00 Merge pull request #2984 from Multiverse/worlds-config
Worlds config
2023-08-31 23:27:10 +08:00
Ben Woo 5208028e65 Add todo on comparing config file 2023-08-31 23:25:30 +08:00
Ben Woo 55fd08e0b1 Remove stray white spacing 2023-08-31 23:22:23 +08:00
Ben Woo 904bd8634a Improve tests for world config file 2023-08-31 23:21:27 +08:00
Ben Woo 02b02530bd Revert delete command changes 2023-08-31 23:02:19 +08:00
Ben Woo 5fca5b18b8 Remove from commands and add to tests 2023-08-31 22:58:33 +08:00
Ben Woo aa412b1060 Add todo for loading worlds 2023-08-31 15:17:51 +08:00
Ben Woo 54c8bac3d3 Config node automatically use the enum node serializer 2023-08-31 15:16:41 +08:00
Ben Woo decf20f95f Add basic tests for world config 2023-08-31 14:59:31 +08:00
Ben Woo 6888783d01 Implement world blacklist config 2023-08-31 14:21:33 +08:00
Ben Woo c569bc797f Implement node serialisation 2023-08-31 14:21:33 +08:00
Ben Woo 5dba9b5904 Starting to shift worlds.yml to new config api 2023-08-31 14:21:32 +08:00
Ben Woo 55b21bf17e Fix config tests 2023-08-31 14:14:55 +08:00
Ben Woo 4ff1663353 Temp fix to fix tests 2023-08-31 14:03:03 +08:00
zax71 ac6d42549d Reorder logic to make it more readable 2023-08-30 17:40:52 +01:00
zax71 b500afd8f0 Whitespace fixes 2023-08-30 17:28:04 +01:00
zax71 0c79c6577e Rename Services and LogsType enums 2023-08-30 17:26:15 +01:00
zax71 2b7d1412b5 Remove uploading message and print out directly 2023-08-30 17:23:19 +01:00
zax71 560a6d4d7e Fix whitespace 2023-08-30 17:16:51 +01:00
zax71 8444383f16 Update command syntax 2023-08-30 17:15:17 +01:00
zax71 de77d09eaa Move getBukkitConfig() and getServerProperties()` into FileUtils.java 2023-08-30 17:13:31 +01:00
zax71 69fdfcfd9f Fix syntax 2023-08-30 17:03:28 +01:00
Ben Woo cbf44cb918 Merge pull request #2928 from Multiverse/perm-revamp-3
feat: Revamp teleport world entry checking
2023-08-30 23:38:58 +08:00
Jeremy Wood cb7ee2fc26 Merge pull request #2974 from Multiverse/update-readme
docs: Improve the readme badges
2023-08-30 11:28:34 -04:00
zax71 bf663a76dc Add debug logging (in /mv debug 3) 2023-08-30 11:55:23 +01:00
zax71 4f756a4c2d Change flags used 2023-08-30 11:52:28 +01:00
Ben Woo d2b18b8545 Merge pull request #2982 from Multiverse/enum-flag
Specific flag builder for enum to streamline context and completion
2023-08-29 16:40:33 +08:00
Ben Woo 3800513dc5 Merge pull request #2983 from Multiverse/conditions-id
Fix command conditions not registering and lowercased
2023-08-29 12:16:17 +08:00
Ben Woo 74e7a1c9f3 Merge branch 'MV5' into perm-revamp-3 2023-08-29 10:55:52 +08:00
Ben Woo 0ddb5563be Fix command conditions not registering and lowercased 2023-08-29 10:54:22 +08:00
Ben Woo bf8bca3244 Specific flag builder for enum to streamline context and completion 2023-08-29 10:44:25 +08:00
Jeremy Wood 59d211ce92 Replace dependencies that were dropped accidentally. 2023-08-28 15:42:16 -04:00
Jeremy Wood cba5f7c9d1 Fix up MV5 gradle configurations. 2023-08-28 15:33:41 -04:00
Jeremy Wood 542f321889 Merge remote-tracking branch 'origin/main' into MV5
# Conflicts:
#	.github/workflows/promote_release.yml
#	.github/workflows/release.yml
#	build.gradle
#	src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java
#	src/main/java/com/onarandombox/MultiverseCore/listeners/MVPlayerListener.java
2023-08-28 15:31:34 -04:00
zax71 fa81f5b573 paste.gg and mclo.gs default 2023-08-28 16:45:57 +01:00
Jeremy Wood 2143930fac Merge pull request #2980 from Multiverse/remove-modirnth-plugin
Remove modrinth gradle plugin
2023-08-28 09:57:01 -04:00
zax71 5af06d9a0f Switch from hastebin to pastes.dev and fix non multi-file services 2023-08-28 14:38:42 +01:00
Ben Woo 5f12aa53b4 Remove modrinth gradle plugin 2023-08-28 00:15:39 +08:00
Jeremy Wood 1d371fb625 Merge pull request #2979 from Multiverse/hangar-api
Update hangar plugin deps bcu they changed the API
2023-08-27 12:09:40 -04:00
Ben Woo 320dc82b83 Update hangar plugin deps bcu they changed the API 2023-08-27 18:21:16 +08:00
Ben Woo e06536acd6 Command manager already a parent class field 2023-08-27 13:48:03 +08:00
Ben Woo 39c702a5fc Remove custom sendMessage method 2023-08-27 13:46:47 +08:00
Ben Woo 317b2c679f Minor code style fixes 2023-08-27 13:45:06 +08:00
Ben Woo 5e9739bda9 Merge branch 'MV5' into pr/2975
# Conflicts:
#	src/main/java/com/onarandombox/MultiverseCore/configuration/node/NodeGroup.java
2023-08-27 13:19:32 +08:00
Ben Woo 954e304f3a Merge pull request #2977 from zax71/codestyle-changes 2023-08-26 19:26:51 +08:00
zax71 1f7ad9d27f Add i18n 2023-08-26 11:53:15 +01:00
zax71 f261d88b4a Fix codestyle 2023-08-26 11:28:58 +01:00
zax71 949eb44447 Invert --include-plugin-list to --exclude-plugin-list 2023-08-26 11:25:10 +01:00
zax71 4750839497 Yeet all the wildcard imports 2023-08-26 11:19:11 +01:00
zax71 260777303c Implement /mv dumps command 2023-08-25 19:52:45 +01:00
Ben Woo 3683f93522 docs: Improve the readme badges 2023-08-25 13:25:53 +08:00
Jeremy Wood 288474cd20 Merge pull request #2973 from Multiverse/generic-test
feat: Generify test action
2023-08-24 22:40:54 -04:00
Ben Woo 16ceaa4c40 feat: Generify test action 2023-08-25 10:23:54 +08:00
Jeremy Wood e9f55e43ee Merge pull request #2972 from Multiverse/dtm/fix_pom_deps
Fix dependency set for maven pom.
2023-08-24 22:00:15 -04:00
Jeremy Wood 31f4f20bd8 Allow tests to see compileOnly dependencies. 2023-08-24 13:50:04 -04:00
Jeremy Wood bae909a9e8 Mark runtime dependency as provided in pom. 2023-08-24 13:49:48 -04:00
Jeremy Wood ee5408764f Fix dependency set for maven pom. 2023-08-24 13:28:02 -04:00
Ben Woo e2e0574baa Merge pull request #2971 from zax71/hangar-readme-badge
Add Hangar README.md badge
2023-08-24 23:49:00 +08:00
zax71 e1b6bf75b0 Add Hangar README.md badge 2023-08-24 16:44:53 +01:00
Ben Woo 7017689758 Merge pull request #2970 from Multiverse/optional-deps
feat: Add optional deps references
2023-08-24 22:52:47 +08:00
Ben Woo 58d51f57e5 feat: Add optional deps references 2023-08-24 22:45:36 +08:00
Jeremy Wood ccd417db3e Merge pull request #2969 from Multiverse/dtm/manual_hangar
Switch to manual only prereleases on Hangar.
2023-08-24 08:46:40 -04:00
Jeremy Wood 0eb67bee9c Switch to manual only prereleases on Hangar. 2023-08-24 08:44:39 -04:00
Ben Woo 9b22bdf2ab Merge pull request #2967 from Multiverse/generic-action
Generify actions and add hangar upload
2023-08-24 19:31:50 +08:00
Ben Woo 91e5d343cd Generify actions and add hangar upload 2023-08-24 17:04:57 +08:00
Ben Woo 743feea807 Merge pull request #2965 from Multiverse/fix-cancel-logic 2023-08-23 19:43:48 +08:00
Ben Woo d5d1c94566 fix: Cancel condition for platform upload 2023-08-23 13:00:47 +08:00
Ben Woo f67d8efb44 Merge pull request #2964 from Multiverse/actions-better 2023-08-23 11:45:00 +08:00
Ben Woo 70132c0da4 fix: Remove debug echos 2023-08-23 11:09:23 +08:00
Ben Woo 9c3914d409 Run upload to platform even if the other fails 2023-08-23 11:05:25 +08:00
Ben Woo db89482e29 fix: Use github output instead of env 2023-08-23 11:04:36 +08:00
Ben Woo fdb9125f3a Merge pull request #2963 from Multiverse/update-action
chore: Use major versioning for actions that supports
2023-08-23 10:58:20 +08:00
Ben Woo c3b17d33c3 chore: Use major versioning for actions that supports 2023-08-23 10:49:49 +08:00
Jeremy Wood e9d8db668f Merge pull request #2961 from Multiverse/update-semantic-action-version
fix: Version failing if more than pre.10
2023-08-22 13:43:10 -04:00
Ben Woo 60a4b6fc89 fix: Version failing if more than pre.10 2023-08-22 23:45:48 +08:00
Jeremy Wood f59267374f Merge pull request #2960 from Multiverse/revamp-actions
feat: Revamp github actions workflow
2023-08-22 10:29:24 -04:00
Ben Woo b1c0e94a4b fix: Update for production 2023-08-22 21:38:23 +08:00
Ben Woo 61254bfccb feat: Revamp github actions workflow 2023-08-22 21:35:10 +08:00
Ben Woo 3f5a17e39a Merge pull request #2958 from Multiverse/modrinth-label
chore: Add modrinth label to readme
2023-08-22 12:18:38 +08:00
Ben Woo 7c6f1b5fc4 chore: Add modrinth label to readme 2023-08-22 12:08:15 +08:00
Jeremy Wood 06b87801fe Merge pull request #2957 from Multiverse/directory-issue
fix: DBO file path issue
2023-08-21 23:59:54 -04:00
Ben Woo a92e5c95aa fix: DBO file path issue 2023-08-22 11:56:28 +08:00
Jeremy Wood 590972c933 Merge pull request #2956 from Multiverse/modrinth-versioning
Fix versioning
2023-08-21 23:51:26 -04:00
Ben Woo 007b7149a1 fix: DBO release type 2023-08-22 11:37:00 +08:00
Ben Woo 8b18ccbd1d fix: Modrinth task versioning 2023-08-22 11:36:20 +08:00
Jeremy Wood 73e0b30836 Merge pull request #2955 from Multiverse/tag-input-inconsistent
fix: Tag name and input inconsistency
2023-08-21 23:29:55 -04:00
Ben Woo 42c8e414c2 fix: Tag name and input inconsistency 2023-08-22 11:27:30 +08:00
Ben Woo 82a274bad2 Merge pull request #2954 from Multiverse/fix-release-type
fix: Release mode for release promotion
2023-08-22 11:14:08 +08:00
Ben Woo 8aa01026ea fix: Release mode for release promotion 2023-08-22 11:12:13 +08:00
Ben Woo 750d1ea4fa Merge pull request #2953 from Multiverse/fix-download-artifact
fix: Download artifact wrong file version
2023-08-22 11:02:38 +08:00
Ben Woo 586ac4a90e fix: Download artifact wrong file version 2023-08-22 10:56:59 +08:00
Jeremy Wood 816d5f86d6 Merge pull request #2952 from Multiverse/fix-version
fix: Version of fetch-gh-release-asset
2023-08-21 22:50:46 -04:00
Ben Woo 7e8ebfb8cd fix: Version of fetch-gh-release-asset 2023-08-22 10:47:50 +08:00
Jeremy Wood 350d228975 Merge pull request #2951 from Multiverse/release-actions
Revamp release actions
2023-08-21 22:44:19 -04:00
Ben Woo 2126efe27c fix: Remove error echo message 2023-08-22 10:24:52 +08:00
Ben Woo 3330bd3031 feat: Remove PR labeler and change "no version bump" to "no release" 2023-08-22 09:48:46 +08:00
Ben Woo 4f5b4126f4 Merge branch 'main' into release-actions 2023-08-21 23:26:04 +08:00
Ben Woo c4a80d7b78 feat: use new semantic release action for release promote 2023-08-21 23:22:35 +08:00
Ben Woo d31f7e9d87 fix: Modrinth upload action missing steps 2023-08-21 23:15:25 +08:00
Ben Woo 356d67edf4 feat: Use new semantic release action 2023-08-21 23:00:00 +08:00
Jeremy Wood 8865cfb53f Merge pull request #2948 from Multiverse/fix-null-teleporter
Fix teleporter reference being null
2023-08-20 23:23:15 -04:00
Ben Woo bf72328c37 feat: Complete release actions to DBO and Modrinth 2023-08-20 22:16:20 +08:00
Ben Woo 9a80620aa1 Fix teleporter reference being null 2023-08-20 20:26:52 +08:00
Ben Woo 982eb28f2a Merge pull request #2950 from Multiverse/dbo-upload
Add github action for DBO upload
2023-08-20 19:52:41 +08:00
Ben Woo 4ecd65a589 Add github action for DBO upload 2023-08-20 19:51:02 +08:00
Ben Woo 5fbe16ed5a Merge pull request #2949 from Multiverse/fix-regen-args
Fix regen args parsing logic
2023-08-20 19:50:40 +08:00
Ben Woo 582d256f38 Fix regen args parsing logic 2023-08-19 12:11:13 +08:00
Jeremy Wood 26e587805d Merge pull request #2947 from Multiverse/modrinth-for-promote-release
Upload to modrinth when manually promote release
2023-08-15 23:56:19 -04:00
Ben Woo 3ad2322db7 Upload to modrinth when manually promote release 2023-08-15 23:28:39 +08:00
Jeremy Wood 8764108edd Merge pull request #2946 from Multiverse/force-release
Remove line break from README.md
2023-08-15 10:52:13 -04:00
Jeremy Wood 5fa8e9acf6 Remove line break from README.md
This is just to force a new prerelease.
2023-08-15 10:51:47 -04:00
Jeremy Wood 0ead2da16f Merge pull request #2945 from Multiverse/modrinth-game-version
Fix add missing game version for modrinth
2023-08-15 10:46:59 -04:00
Ben Woo fd4bc7cf60 Fix add missing game version for modrinth 2023-08-15 22:35:10 +08:00
Jeremy Wood ad296fde1f Merge pull request #2944 from Multiverse/fix-modrinth-gha
Fix modrinth gha upload
2023-08-15 10:25:59 -04:00
Ben Woo 6f39a2c97d Fix modrinth gha upload 2023-08-15 14:54:16 +08:00
Jeremy Wood befb2b54d8 Merge pull request #2880 from Multiverse/modrinth-upload
feat: Add automatic Modrinth upload
2023-08-14 11:44:26 -04:00
Zax71 efcd14830e Remove unused GITHUB_TOKEN 2023-08-11 20:24:01 +01:00
Zax71 491bb2467f Add 1.20 to supported versions 2023-08-04 16:28:05 +01:00
Zax71 dfbe81c785 Implement requested changes 2023-08-03 11:11:29 +01:00
Ben Woo 8df371c90c refactor: Rename CheckResult to Result 2023-06-29 11:05:08 +08:00
Ben Woo ad47ab2340 feat: Revamp world entry checking 2023-06-29 11:05:08 +08:00
Zax71 986bafc13d Merge branch 'main' into modrinth-upload 2023-06-27 16:52:29 +01:00
Zax71 9b4613ce84 Support 1.13+ 2023-06-27 16:50:46 +01:00
Jeremy Wood 48e875d13e Merge pull request #2908 from Multiverse/dumptruckman/fix_classifier
Remove the published jar classifier for maven publish.
2023-04-05 08:48:36 -04:00
Jeremy Wood 14b54d5269 Remove the published jar classifier for maven publish.
Fixes #2906.
2023-04-05 08:38:37 -04:00
Jeremy Wood 1c24b17c90 Merge pull request #2872 from Multiverse/new-readme-2
Update README.md
2023-03-30 08:42:10 -04:00
Ben Woo 346ac94737 Merge branch 'main' into new-readme-2 2023-03-27 10:16:41 +08:00
zax71 6d351300de chore: remove Modrinth for now
Signed-off-by: zax71 <zabax32@gmail.com>
2023-03-26 18:26:23 +01:00
zax71 68411ae6bf Add correct number of newlines
Signed-off-by: zax71 <zabax32@gmail.com>
2023-03-02 12:54:20 +00:00
zax71 2c5e86c689 Add Modrinth Upload 2023-03-02 12:37:07 +00:00
zax71 c3eb0ee8bd Center Logo 2023-02-26 14:00:37 +00:00
zax71 6a8c0b6255 Update README.md 2023-02-26 13:56:56 +00:00
Ben Woo 72415cdae5 feat: Implement list command 2023-02-15 12:17:04 +08:00
368 changed files with 16315 additions and 11047 deletions

No files matched your search

-2
View File
@@ -1,2 +0,0 @@
prerelease:
- '*'
+34
View File
@@ -0,0 +1,34 @@
name: 'Call: GitHub Release'
on:
workflow_call:
inputs:
release_mode:
description: 'Release mode'
required: true
type: string
version_bump:
description: 'Version bump'
required: false
type: string
promote_from:
description: 'Promote from'
required: false
type: string
outputs:
release_created:
description: 'Release created'
value: ${{ jobs.github_release.outputs.release_created }}
tag_name:
description: 'Tag name'
value: ${{ jobs.github_release.outputs.tag_name }}
jobs:
github_release:
uses: ./.github/workflows/generic.github_release.yml
secrets: inherit
with:
plugin_name: multiverse-core
release_mode: ${{ inputs.release_mode }}
version_bump: ${{ inputs.version_bump }}
promote_from: ${{ inputs.promote_from }}
@@ -0,0 +1,83 @@
name: 'Call: Platform Uploads'
on:
workflow_call:
inputs:
target_tag:
description: 'Version to upload'
required: true
type: string
upload_modrinth:
description: 'Upload to modrinth.com'
required: true
type: string
upload_dbo:
description: 'Upload to dev.bukkit.org'
required: true
type: string
upload_hangar:
description: 'Upload to hangar.papermc.io'
required: true
type: string
secrets:
MODRINTH_TOKEN:
required: true
DBO_UPLOAD_API_TOKEN:
required: true
HANGAR_UPLOAD_TOKEN:
required: true
jobs:
platform_uploads:
uses: ./.github/workflows/generic.platform_uploads.yml
secrets: inherit
with:
plugin_name: multiverse-core
modrinth_project_id: 3wmN97b8
modrinth_dependencies: >
[
{"project_id": "qvdtDX3s", "dependency_type": "optional"},
{"project_id": "8VMk6P0I", "dependency_type": "optional"},
{"project_id": "vtawPsTo", "dependency_type": "optional"},
{"project_id": "WuErDeI1", "dependency_type": "optional"}
]
dbo_project_id: 30765
dbo_project_relations: >
[
{"slug": "multiverse-inventories", "type": "optionalDependency"},
{"slug": "multiverse-portals", "type": "optionalDependency"},
{"slug": "multiverse-netherportals", "type": "optionalDependency"},
{"slug": "multiverse-signportals", "type": "optionalDependency"},
{"slug": "vault", "type": "optionalDependency"}
]
hangar_slug: Multiverse-Core
hangar_plugin_dependencies: >
{ "PAPER": [
{
"name": "Multiverse-Inventories",
"required": false,
"platforms": ["PAPER"]
},
{
"name": "Multiverse-Portals",
"required": false,
"platforms": ["PAPER"]
},
{
"name": "Multiverse-NetherPortals",
"required": false,
"platforms": ["PAPER"]
},
{
"name": "Multiverse-SignPortals",
"required": false,
"platforms": ["PAPER"]
}
]}
target_tag: ${{ inputs.target_tag }}
upload_modrinth: ${{ inputs.upload_modrinth }}
upload_dbo: ${{ inputs.upload_dbo }}
upload_hangar: ${{ inputs.upload_hangar }}
@@ -0,0 +1,31 @@
name: 'Dispatch: Platform Uploads'
on:
workflow_dispatch:
inputs:
target_tag:
description: 'Version to upload'
required: true
type: string
upload_modrinth:
description: 'Upload to modrinth.com'
required: true
type: boolean
upload_dbo:
description: 'Upload to dev.bukkit.org'
required: true
type: boolean
upload_hangar:
description: 'Upload to hangar.papermc.io'
required: true
type: boolean
jobs:
dispatch_platform_uploads:
uses: ./.github/workflows/call.platform_uploads.yml
secrets: inherit
with:
target_tag: ${{ github.event.inputs.target_tag }}
upload_modrinth: ${{ github.event.inputs.upload_modrinth }}
upload_dbo: ${{ github.event.inputs.upload_dbo }}
upload_hangar: ${{ github.event.inputs.upload_hangar }}
@@ -0,0 +1,38 @@
name: 'Dispatch: Promote Release'
on:
workflow_dispatch:
inputs:
target_tag:
description: 'Version to promote'
required: true
jobs:
check_version:
runs-on: ubuntu-latest
steps:
- name: Verify input version is prerelease
run: |
if [[ "${{ github.event.inputs.target_tag }}" != *"pre"* ]]; then
echo "Version must be a prerelease"
exit 1
fi
github_release:
needs: check_version
uses: ./.github/workflows/call.github_release.yml
secrets: inherit
with:
release_mode: promote
promote_from: ${{ github.event.inputs.target_tag }}
platform_uploads:
needs: github_release
if: needs.github_release.outputs.release_created == 'true'
uses: ./.github/workflows/call.platform_uploads.yml
secrets: inherit
with:
target_tag: ${{ needs.github_release.outputs.tag_name }}
upload_modrinth: 'true'
upload_dbo: 'true'
upload_hangar: 'true'
+22
View File
@@ -0,0 +1,22 @@
name: 'Generic: Checkstyle'
on:
workflow_call:
jobs:
checkstyle:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
continue-on-error: true
steps:
- uses: actions/checkout@v3
- uses: dbelyaev/action-checkstyle@v0.8.4
continue-on-error: true
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
checkstyle_version: 10.12.2
checkstyle_config: ./config/mv_checks.xml
level: warning
@@ -0,0 +1,91 @@
name: 'Generic: GitHub Release'
on:
workflow_call:
inputs:
# Plugin specific
plugin_name:
description: 'Plugin name'
required: true
type: string
# Common params
release_mode:
description: 'Release mode'
required: true
type: string
version_bump:
description: 'Version bump'
required: false
type: string
promote_from:
description: 'Promote from'
required: false
type: string
outputs:
release_created:
description: 'Release created'
value: ${{ jobs.github_release.outputs.release_created }}
tag_name:
description: 'Tag name'
value: ${{ jobs.github_release.outputs.tag_name }}
jobs:
github_release:
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
- name: Echo inputs
run: |
echo "release_mode: ${{ inputs.release_mode }}"
echo "version_bump: ${{ inputs.version_bump }}"
echo "promote_from: ${{ inputs.promote_from }}"
- uses: actions/checkout@v3
with:
ref: ${{ inputs.promote_from }}
- uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'adopt'
cache: gradle
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: Build and test
uses: gradle/gradle-build-action@v2
with:
arguments: clean build -x assemble -x shadowJar
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create release
id: release
uses: benwoo1110/semantic-release-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
release_mode: ${{ inputs.release_mode }}
version_bump: ${{ inputs.version_bump }}
promote_from: ${{ inputs.promote_from }}
- name: Publish package
if: steps.release.outputs.release_created == 'true'
uses: gradle/gradle-build-action@v2
with:
arguments: publish -x test
env:
GITHUB_VERSION: ${{ steps.release.outputs.publish_version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload release artifact
if: steps.release.outputs.release_created == 'true'
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: build/libs/${{ inputs.plugin_name }}-${{ steps.release.outputs.publish_version }}.jar
asset_name: ${{ inputs.plugin_name }}-${{ steps.release.outputs.tag_name }}.jar
tag: ${{ steps.release.outputs.tag_name }}
@@ -0,0 +1,140 @@
name: 'Generic: Platform Uploads'
on:
workflow_call:
inputs:
# Plugin specific params
plugin_name:
description: 'Plugin name'
required: true
type: string
modrinth_project_id:
description: 'modrinth.com project ID'
required: true
type: string
modrinth_dependencies:
description: 'modrinth.com project dependencies'
required: false
type: string
default: '[]'
dbo_project_id:
description: 'dev.bukkit.org project ID'
required: true
type: string
dbo_project_relations:
description: 'dev.bukkit.org project relations'
required: false
type: string
default: '[]'
hangar_slug:
description: 'hangar.papermc.io project slug'
required: true
type: string
hangar_plugin_dependencies:
description: 'hangar.papermc.io project dependencies'
required: false
type: string
default: '{}'
# Common params
target_tag:
description: 'Version to upload'
required: true
type: string
upload_modrinth:
description: 'Upload to modrinth.com'
required: true
type: string
upload_dbo:
description: 'Upload to dev.bukkit.org'
required: true
type: string
upload_hangar:
description: 'Upload to hangar.papermc.io'
required: true
type: string
secrets:
MODRINTH_TOKEN:
required: true
DBO_UPLOAD_API_TOKEN:
required: true
HANGAR_UPLOAD_TOKEN:
required: true
jobs:
platform_uploads:
runs-on: ubuntu-latest
steps:
- name: Get release info
id: release-info
uses: cardinalby/git-get-release-action@1.2.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag: ${{ inputs.target_tag }}
- name: Download release artifact
id: release-artifact
uses: dsaltares/fetch-gh-release-asset@1.1.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
version: tags/${{ steps.release-info.outputs.tag_name }}
file: ${{ inputs.plugin_name }}-${{ steps.release-info.outputs.tag_name }}.jar
- name: Parse release type
id: parse-release-type
run: |
if [[ "${{ steps.release-info.outputs.prerelease }}" == "true" ]]; then
echo Setting release_type to Beta
echo "release_type=Beta" >> $GITHUB_OUTPUT
else
echo Setting release_type to Release
echo "release_type=Release" >> $GITHUB_OUTPUT
fi
- name: Upload to Modrinth
if: ${{ !cancelled() && inputs.upload_modrinth == 'true' }}
uses: benwoo1110/modrinth-upload-action@v1
with:
api_token: ${{ secrets.MODRINTH_TOKEN }}
project_id: ${{ inputs.modrinth_project_id }}
version_number: ${{ steps.release-info.outputs.tag_name }}
files: '["${{ github.workspace }}/${{ inputs.plugin_name }}-${{ steps.release-info.outputs.tag_name }}.jar"]'
name: ${{ steps.release-info.outputs.tag_name }}
changelog: ${{ steps.release-artifact.outputs.body }}
game_versions: 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13
version_type: ${{ steps.parse-release-type.outputs.release_type }}
loaders: bukkit, spigot, paper
dependencies: ${{ inputs.modrinth_dependencies }}
- name: Upload to DBO
if: ${{ !cancelled() && inputs.upload_dbo == 'true' }}
uses: benwoo1110/dbo-upload-action@v1
with:
api_token: ${{ secrets.DBO_UPLOAD_API_TOKEN }}
project_id: ${{ inputs.dbo_project_id }}
changelog: ${{ steps.release-artifact.outputs.body }}
changelog_type: markdown
display_name: ${{ steps.release-info.outputs.tag_name }}
game_versions: 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17, 1.16, 1.15, 1.14, 1.13
release_type: ${{ steps.parse-release-type.outputs.release_type }}
project_relations: ${{ inputs.dbo_project_relations }}
file_path: ${{ github.workspace }}/${{ inputs.plugin_name }}-${{ steps.release-info.outputs.tag_name }}.jar
- name: Upload to Hangar
if: ${{ !cancelled() && inputs.upload_hangar == 'true' }}
uses: benwoo1110/hangar-upload-action@v1
with:
api_token: ${{ secrets.HANGAR_UPLOAD_TOKEN }}
slug: ${{ inputs.hangar_slug }}
version: ${{ steps.release-info.outputs.tag_name }}
channel: ${{ steps.parse-release-type.outputs.release_type }}
files: '[{"path": "${{ github.workspace }}/${{ inputs.plugin_name }}-${{ steps.release-info.outputs.tag_name }}.jar", "platforms": ["PAPER"]}]'
description: ${{ steps.release-artifact.outputs.body }}
platform_dependencies: '{"PAPER": ["1.13-1.20.1"]}'
plugin_dependencies: ${{ inputs.hangar_plugin_dependencies }}
@@ -1,8 +1,12 @@
name: Run unit tests against all PRs
name: 'Generic: Test'
on:
pull_request:
types: [opened, synchronize]
workflow_call:
inputs:
plugin_name:
description: 'Plugin name'
required: true
type: string
jobs:
test:
@@ -24,7 +28,7 @@ jobs:
- name: Run unit tests
uses: gradle/gradle-build-action@v2
with:
arguments: build -x checkstyleMain -x checkstyleTest -x javadoc
arguments: build
env:
GITHUB_VERSION: pr${{ github.event.pull_request.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -32,5 +36,5 @@ jobs:
- name: Artifact output
uses: actions/upload-artifact@v3
with:
name: multiverse-core-pr${{ github.event.pull_request.number }}
path: build/libs/multiverse-core-pr${{ github.event.pull_request.number }}.jar
name: ${{ inputs.plugin_name }}-pr${{ github.event.pull_request.number }}
path: build/libs/${{ inputs.plugin_name }}-pr${{ github.event.pull_request.number }}.jar
+24
View File
@@ -0,0 +1,24 @@
name: 'Main: Prerelease'
on:
push:
branches: [main]
jobs:
github_release_on_push:
uses: ./.github/workflows/call.github_release.yml
secrets: inherit
with:
release_mode: prerelease
version_bump: prlabel
platform_uploads_on_push:
needs: github_release_on_push
if: needs.github_release_on_push.outputs.release_created == 'true'
uses: ./.github/workflows/call.platform_uploads.yml
secrets: inherit
with:
target_tag: ${{ needs.github_release_on_push.outputs.tag_name }}
upload_modrinth: 'true'
upload_dbo: 'false'
upload_hangar: 'false'
+9
View File
@@ -0,0 +1,9 @@
name: 'PR: Checkstyle'
on:
pull_request:
types: [opened, synchronize]
jobs:
checkstyle:
uses: ./.github/workflows/generic.checkstyle.yml
@@ -1,4 +1,4 @@
name: Require PR Labels
name: 'PR: Require Label'
on:
pull_request:
@@ -15,4 +15,4 @@ jobs:
with:
mode: exactly
count: 1
labels: "release:major, release:minor, release:patch, no version bump"
labels: "release:major, release:minor, release:patch, no release"
+11
View File
@@ -0,0 +1,11 @@
name: 'PR: Test'
on:
pull_request:
types: [opened, synchronize]
jobs:
test:
uses: ./.github/workflows/generic.test.yml
with:
plugin_name: multiverse-core
-17
View File
@@ -1,17 +0,0 @@
name: "Pull Request Labeler"
on:
pull_request_target:
types: [opened]
branches: [main]
jobs:
prerelease_labeler:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
-90
View File
@@ -1,90 +0,0 @@
name: Manually promote last prerelease to release
on:
workflow_dispatch:
inputs:
version:
description: 'Version to promote'
required: true
version-bump:
description: 'Version bump to apply - should usually match the version bump used for the prerelease since last release'
required: true
type: choice
options:
- 'patch'
- 'minor'
- 'major'
jobs:
manually_promote_release:
runs-on: ubuntu-latest
steps:
- name: Verify input version is prerelease
run: |
if [[ "${{ github.event.inputs.version }}" != *"pre"* ]]; then
echo "Version must be a prerelease"
exit 1
fi
- name: Get release info
id: get-release
uses: cardinalby/git-get-release-action@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
tag: ${{ github.event.inputs.version }}
- uses: actions/checkout@v3
with:
ref: ${{ steps.get-release.outputs.tag_name }}
- uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
cache: gradle
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: Remove prerelease tag
run: |
echo "Removing prerelease tag from version"
echo "VERSION=$(echo ${{ steps.get-release.outputs.tag_name }} | sed -E 's/-pre.*//')" >> $GITHUB_ENV
- name: Build
uses: gradle/gradle-build-action@v2
with:
arguments: clean build -x test -x checkstyleMain -x checkstyleTest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_VERSION: ${{ env.VERSION }}
- name: Create release
id: release
uses: Multiverse/release-on-push-action@skip_prs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
bump_version_scheme: ${{ github.event.inputs.version-bump }}
tag_prefix: ''
release_name: "<RELEASE_VERSION>"
use_github_release_notes: true
ref: ${{ steps.get-release.outputs.target_commitish }}
skip_prs: true
- name: Publish package
uses: gradle/gradle-build-action@v2
with:
arguments: publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_VERSION: ${{ env.VERSION }}
- name: Upload release artifact
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: build/libs/multiverse-core-${{ env.VERSION }}.jar
asset_name: multiverse-core-${{ steps.release.outputs.tag_name }}.jar
tag: ${{ steps.release.outputs.tag_name }}
-64
View File
@@ -1,64 +0,0 @@
name: Create Release Version & Publish Package
on:
push:
branches: [main]
jobs:
release_on_push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
cache: gradle
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: Test & Build
uses: gradle/gradle-build-action@v2
with:
arguments: clean build -x assemble -x shadowJar
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create release
id: release
uses: Multiverse/release-on-push-action@support_prerelease
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
bump_version_scheme: norelease
tag_prefix: ''
release_name: "<RELEASE_VERSION>"
use_github_release_notes: true
- name: Modify version scheme
run: |
if [[ "${{ steps.release.outputs.tag_name }}" == *"pre"* ]]; then
echo "Replacing prerelease version scheme with SNAPSHOT"
echo "VERSION=$(echo ${{ steps.release.outputs.tag_name }} | sed -E 's/-pre.*/-SNAPSHOT/')" >> $GITHUB_ENV
else
echo "Using release version scheme"
echo "VERSION=${{ steps.release.outputs.tag_name }}" >> $GITHUB_ENV
fi
- name: Publish package
uses: gradle/gradle-build-action@v2
with:
arguments: publish
env:
GITHUB_VERSION: ${{ env.VERSION }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload release artifact
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: build/libs/multiverse-core-${{ env.VERSION }}.jar
asset_name: multiverse-core-${{ steps.release.outputs.tag_name }}.jar
tag: ${{ steps.release.outputs.tag_name }}
+24 -18
View File
@@ -1,26 +1,33 @@
![Multiverse 2](config/multiverse2-long.png)
<p align="center">
<img src="config/multiverse2-long.png" alt="Multiverse Logo">
</p>
[![Maven CI/CD](https://github.com/Multiverse/Multiverse-Core/actions/workflows/build.yml/badge.svg)](https://github.com/Multiverse/Multiverse-Core/actions/workflows/build.yml)
[![Release](https://img.shields.io/nexus/r/com.onarandombox.multiversecore/Multiverse-Core?label=release&server=https%3A%2F%2Frepo.onarandombox.com%2F)](https://dev.bukkit.org/projects/multiverse-core)
[![Dev builds](https://img.shields.io/nexus/s/com.onarandombox.multiversecore/Multiverse-Core?label=dev%20builds&server=http%3A%2F%2Frepo.onarandombox.com%2F)](https://ci.onarandombox.com/job/Multiverse-Core/)
[![Modrinth](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/available/modrinth_vector.svg)](https://modrinth.com/plugin/multiverse-core)
[![hangar](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/available/hangar_vector.svg)](https://hangar.papermc.io/Multiverse/Multiverse-Core)
[![bukkit](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/supported/bukkit_vector.svg)](https://dev.bukkit.org/projects/multiverse-core)
[![Spigot](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/supported/spigot_vector.svg)](https://www.spigotmc.org/resources/multiverse-core.390/)
[![Release](https://img.shields.io/nexus/r/com.onarandombox.multiversecore/multiverse-core?server=https%3A%2F%2Frepo.onarandombox.com&label=release&color=dark-green)](https://dev.bukkit.org/projects/multiverse-core)
[![Dev builds](https://img.shields.io/nexus/s/com.onarandombox.multiversecore/multiverse-core?server=https%3A%2F%2Frepo.onarandombox.com&label=prerelease&color=orange)](https://ci.onarandombox.com/job/Multiverse-Core/)
[![Discord](https://img.shields.io/discord/325459248047980545?label=discord&logo=discord)](https://discord.gg/NZtfKky)
[![Support me on Patreon](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Ddumptruckman%26type%3Dpatrons&style=flat)](https://patreon.com/dumptruckman)
[![License](https://img.shields.io/github/license/Multiverse/Multiverse-Core)](LICENSE.md)
[![Support us on Patreon](https://img.shields.io/badge/donate-patreon-white?logo=patreon)](https://patreon.com/dumptruckman)
[![License](https://img.shields.io/github/license/Multiverse/Multiverse-Core?color=blue)](LICENSE.md)
# About
About
========
[Multiverse](https://dev.bukkit.org/projects/multiverse-core) was created at the dawn of Bukkit multiworld support. It has since then grown into a **complete world management solution!** Multiverse provides the easiest to use world management solution for your Minecraft server, big or small, and with great addons like [Portals](https://dev.bukkit.org/projects/multiverse-portals) and [NetherPortals](https://dev.bukkit.org/projects/multiverse-netherportals/), what's not to love!
<br><br>
Now it's time to create your very own Multiverse server, do check out our [Wiki](https://github.com/Multiverse/Multiverse-Core/wiki) and [Usage Guide](https://github.com/Multiverse/Multiverse-Core/wiki/Basics) to get started. Feel free to hop onto our [Discord](https://discord.gg/NZtfKky) if you have any question or just want to have a chat with us!
### Amazing sub-modules available:
## Amazing sub-modules available:
* [Multiverse-NetherPortals](https://github.com/Multiverse/Multiverse-NetherPortals) -> Have separate nether and end worlds for each of your overworlds!
* [Multiverse-Portals](https://github.com/Multiverse/Multiverse-Portals) -> Make custom portals to go to any destination!
* [Multiverse-Inventories](https://github.com/Multiverse/Multiverse-Inventories) -> Have separated players stats and inventories per world or per group of worlds.
* [Multiverse-SignPortals](https://github.com/Multiverse/Multiverse-SignPortals) -> Signs as teleprompters!
* [Multiverse-SignPortals](https://github.com/Multiverse/Multiverse-SignPortals) -> Signs as teleporters!
Building
========
## Building
Simply build the source with Gradle:
```
./gradlew build
@@ -28,17 +35,16 @@ Simply build the source with Gradle:
More details are available on the [build instructions wiki page](https://github.com/Multiverse/Multiverse-Core/wiki/Building).
Contributing
=======
## Contributing
**Want to help improve Multiverse?** There are several ways you can support and contribute to the project.
* Take a look at our "Bug: Unconfirmed" issues, where you can find issues that need extra testing and investigation.
* Want others to love Multiverse too? You can join the [Multiverse Discord community](https://discord.gg/NZtfKky) and help others with issues and setup!
* A Multiverse guru? You can update our [Wiki](https://github.com/Multiverse/Multiverse-Core/wiki) with your latest tip, tricks and guides! The wiki open for all to edit and improve.
* Love coding? You could look at ["State: Open to PR"](https://github.com/Multiverse/Multiverse-Core/labels/State%3A%20Open%20to%20PR) and ["Resolution: Accepted"](https://github.com/Multiverse/Multiverse-Core/labels/Resolution%3A%20Accepted) issues. We're always happy to receive bug fixes and feature additions as [pull requests](https://www.freecodecamp.org/news/how-to-make-your-first-pull-request-on-github-3/).
* If you'd like to make a financial contribution to the project, do consider joining our [patreon](https://www.patreon.com/dumptruckman) or make a one-time donation [here](https://paypal.me/dumptruckman)!
* If you'd like to make a financial contribution to the project, do consider joining our [Patreon](https://www.patreon.com/dumptruckman) or make a one-time donation [here](https://paypal.me/dumptruckman)!
Additionally, we would like to give a big thanks to everyone that has supported Multiverse over the years, as well as those in the years to come. Thank you!
License
=======
## License
Multiverse-Core is licensed under BSD-3-Clause License. Please see [LICENSE.md](LICENSE.md) for more info.
+86 -51
View File
@@ -3,7 +3,6 @@ import org.apache.tools.ant.filters.ReplaceTokens
plugins {
id 'java-library'
id 'maven-publish'
id 'checkstyle'
id 'com.github.johnrengelman.shadow' version '7.1.2'
id "org.jetbrains.kotlin.jvm" version "1.8.10"
}
@@ -55,61 +54,75 @@ repositories {
name = 'glaremasters repo'
url = 'https://repo.glaremasters.me/repository/towny/'
}
maven {
name = 'PlaceholderAPI'
url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/'
}
maven {
name = 'papermc repo'
url = 'https://repo.papermc.io/repository/maven-public/'
}
}
configurations {
// Add configuration for server API
compileOnly.extendsFrom serverApi
runtimeClasspath.extendsFrom serverApi
// Add configuration for external plugins
implementation.extendsFrom externalPlugin
// Add configuration for dependencies that will be included in fat jar
compileClasspath.extendsFrom shadowed
testCompileClasspath.extendsFrom shadowed
testRuntimeClasspath.extendsFrom shadowed
oldTestCompileClasspath.extendsFrom shadowed
oldTestRuntimeClasspath.extendsFrom shadowed
// Add configuration for old tests
oldTestImplementation.extendsFrom implementation
oldTestRuntime.extendsFrom runtime
relocatedApi
compileClasspath.extendsFrom relocatedApi
runtimeClasspath.extendsFrom relocatedApi
testCompileClasspath.extendsFrom relocatedApi
testRuntimeClasspath.extendsFrom relocatedApi
oldTestCompileClasspath.extendsFrom relocatedApi
oldTestRuntimeClasspath.extendsFrom relocatedApi
}
dependencies {
compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
serverApi 'org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT'
// Economy
implementation('com.github.MilkBowl:VaultAPI:1.7.1') {
externalPlugin('com.github.MilkBowl:VaultAPI:1.7.1') {
exclude group: 'org.bukkit', module: 'bukkit'
}
// PlaceholderAPI
implementation 'me.clip:placeholderapi:2.11.3'
externalPlugin 'me.clip:placeholderapi:2.11.3'
// Command Framework
relocatedApi 'co.aikar:acf-paper:0.5.1-SNAPSHOT'
shadowed 'co.aikar:acf-paper:0.5.1-SNAPSHOT'
// Config
relocatedApi('me.main__.util:SerializationConfig:1.7') {
shadowed('me.main__.util:SerializationConfig:1.7') {
exclude group: 'org.bukkit', module: 'bukkit'
}
relocatedApi('io.github.townyadvanced.commentedconfiguration:CommentedConfiguration:1.0.1') {
shadowed('io.github.townyadvanced.commentedconfiguration:CommentedConfiguration:1.0.1') {
exclude group: 'org.spigotmc', module: 'spigot-api'
}
// Utils
relocatedApi 'io.vavr:vavr:0.10.4'
relocatedApi 'org.glassfish.hk2:hk2-locator:3.0.3'
relocatedApi('com.dumptruckman.minecraft:Logging:1.1.1') {
shadowed 'io.vavr:vavr:0.10.4'
shadowed 'org.glassfish.hk2:hk2-locator:3.0.3'
shadowed('com.dumptruckman.minecraft:Logging:1.1.1') {
exclude group: 'junit', module: 'junit'
}
relocatedApi 'de.themoep.idconverter:mappings:1.2-SNAPSHOT'
relocatedApi 'org.bstats:bstats-bukkit:2.2.1'
relocatedApi 'net.minidev:json-smart:2.4.8'
relocatedApi 'org.jetbrains:annotations:22.0.0'
relocatedApi 'io.papermc:paperlib:1.0.8'
shadowed 'de.themoep.idconverter:mappings:1.2-SNAPSHOT'
shadowed 'org.bstats:bstats-bukkit:2.2.1'
shadowed 'net.minidev:json-smart:2.4.9'
shadowed 'org.jetbrains:annotations:22.0.0'
shadowed 'io.papermc:paperlib:1.0.8'
// Tests
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10'
testImplementation 'com.github.seeseemelk:MockBukkit-v1.19:2.141.0'
testImplementation 'com.github.seeseemelk:MockBukkit-v1.20:3.20.2'
testImplementation('com.googlecode.json-simple:json-simple:1.1.1') {
exclude group: 'junit', module: 'junit'
}
@@ -118,7 +131,7 @@ dependencies {
testImplementation 'org.mockito.kotlin:mockito-kotlin:4.1.0'
// Old Tests
oldTestImplementation 'org.spigotmc:spigot-api:1.19.3-R0.1-SNAPSHOT'
oldTestImplementation 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
oldTestImplementation('com.googlecode.json-simple:json-simple:1.1.1') {
exclude group: 'junit', module: 'junit'
}
@@ -170,6 +183,34 @@ publishing {
publications {
maven(MavenPublication) {
from components.java
pom.withXml {
Node pomNode = asNode()
// Remove Kotlin dependency
pomNode.dependencies.'*'.findAll() {
it.groupId.text() == 'org.jetbrains.kotlin'
}.each() {
it.parent().remove(it)
}
// Switch runtime deps to provided
pomNode.dependencies.'*'.findAll() {
it.scope.text() == 'runtime'
}.each() {
it.scope*.value = 'provided'
}
// Add spigot api to pom
project.configurations.serverApi.allDependencies.each { dependency ->
pomNode.dependencies[0].appendNode("dependency").with {
it.appendNode("groupId", dependency.group)
it.appendNode("artifactId", dependency.name)
it.appendNode("version", dependency.version)
it.appendNode("scope", "provided")
}
}
}
}
}
repositories {
@@ -227,13 +268,6 @@ processResources {
}
checkstyle {
toolVersion = '6.1.1'
configFile file('config/mv_checks.xml')
ignoreFailures = true
}
javadoc {
source = sourceSets.main.allJava
classpath = configurations.compileClasspath
@@ -243,27 +277,27 @@ javadoc {
project.configurations.api.canBeResolved = true
shadowJar {
relocate 'co.aikar.commands', 'com.onarandombox.acf'
relocate 'com.dumptruckman.minecraft.util.Logging', 'com.onarandombox.MultiverseCore.utils.CoreLogging'
relocate 'com.dumptruckman.minecraft.util.DebugLog', 'com.onarandombox.MultiverseCore.utils.DebugFileLogger'
relocate 'de.themoep.idconverter', 'com.onarandombox.idconverter'
relocate 'io.github.townyadvanced.commentedconfiguration', 'com.onarandombox.commentedconfiguration'
relocate 'me.main__.util', 'com.onarandombox.serializationconfig'
relocate 'org.bstats', 'com.onarandombox.bstats'
relocate 'com.sun', 'com.onarandombox.sun'
relocate 'net.minidev', 'com.onarandombox.minidev'
relocate 'org.objectweb', 'com.onarandombox.objectweb'
relocate 'io.vavr', 'com.onarandombox.vavr'
relocate 'jakarta', 'com.onarandombox.jakarta'
relocate 'javassist', 'com.onarandombox.javassist'
relocate 'org.aopalliance', 'com.onarandombox.aopalliance'
relocate 'org.glassfish', 'com.onarandombox.glassfish'
relocate 'org.jvnet', 'com.onarandombox.jvnet'
relocate 'org.intellij', 'com.onarandombox.intellij'
relocate 'org.jetbrains', 'com.onarandombox.jetbrains'
relocate 'io.papermc.lib', 'com.onarandombox.paperlib'
relocate 'co.aikar', 'org.mvplugins.multiverse.external.acf'
relocate 'com.dumptruckman.minecraft.util.Logging', 'org.mvplugins.multiverse.core.utils.CoreLogging'
relocate 'com.dumptruckman.minecraft.util.DebugLog', 'org.mvplugins.multiverse.core.utils.DebugFileLogger'
relocate 'de.themoep.idconverter', 'org.mvplugins.multiverse.external.idconverter'
relocate 'io.github.townyadvanced.commentedconfiguration', 'org.mvplugins.multiverse.external.commentedconfiguration'
relocate 'me.main__.util', 'org.mvplugins.multiverse.external.serializationconfig'
relocate 'org.bstats', 'org.mvplugins.multiverse.external.bstats'
relocate 'com.sun', 'org.mvplugins.multiverse.external.sun'
relocate 'net.minidev', 'org.mvplugins.multiverse.external.minidev'
relocate 'org.objectweb', 'org.mvplugins.multiverse.external.objectweb'
relocate 'io.vavr', 'org.mvplugins.multiverse.external.vavr'
relocate 'jakarta', 'org.mvplugins.multiverse.external.jakarta'
relocate 'javassist', 'org.mvplugins.multiverse.external.javassist'
relocate 'org.aopalliance', 'org.mvplugins.multiverse.external.aopalliance'
relocate 'org.glassfish', 'org.mvplugins.multiverse.external.glassfish'
relocate 'org.jvnet', 'org.mvplugins.multiverse.external.jvnet'
relocate 'org.intellij', 'org.mvplugins.multiverse.external.intellij'
relocate 'org.jetbrains', 'org.mvplugins.multiverse.external.jetbrains'
relocate 'io.papermc.lib', 'org.mvplugins.multiverse.external.paperlib'
configurations = [project.configurations.api, project.configurations.relocatedApi]
configurations = [project.configurations.shadowed]
archiveFileName = "$baseName-$version.$extension"
@@ -272,6 +306,7 @@ shadowJar {
it.moduleGroup == 'org.jetbrains.kotlin'
})
}
//classifier = ''
}
build.dependsOn shadowJar
+625 -101
View File
@@ -6,136 +6,660 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!-- Future reference: valid severity values are 'ignore', 'info', 'warning', 'error' -->
<module name="Checker">
<module name="JavadocPackage">
<property name="allowLegacy" value="true"/>
</module>
<property name="charset" value="UTF-8"/>
<property name="fileExtensions" value="java, properties, xml"/>
<property name="severity" value="warning"/>
<!-- Javadoc Comments -->
<module name="JavadocPackage"/><!-- require package-info.java file -->
<!-- Miscellaneous -->
<module name="NewlineAtEndOfFile" />
<module name="OrderedProperties"/>
<module name="Translation"/>
<module name="FileLength"/>
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="UniqueProperties"/>
<!-- Regexp -->
<module name="RegexpSingleline">
<property name="message" value="Line has trailing spaces."/>
<property name="format" value="\s+$"/>
</module>
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="SUPPRESS CHECKSTYLE: (\w+)"/>
<property name="checkFormat" value="$1"/>
<!-- Size Violations -->
<module name="FileLength">
<property name="max" value="2000"/>
</module>
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="BEGIN CHECKSTYLE-SUPPRESSION\: (\w+)"/>
<property name="onCommentFormat" value="END CHECKSTYLE-SUPPRESSION\: (\w+)"/>
<property name="checkFormat" value="$1"/>
<module name="LineLength">
<property name="fileExtensions" value="java"/>
<property name="max" value="120"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="BEGIN CHECKSTYLE-SUPPRESSION\: ALL"/>
<property name="onCommentFormat" value="END CHECKSTYLE-SUPPRESSION\: ALL"/>
<!-- Whitespace -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="TreeWalker">
<!-- Make suppression possible -->
<module name="FileContentsHolder"/>
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="SUPPRESS CHECKSTYLE: (\w+)"/>
<property name="checkFormat" value="$1"/>
</module>
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="BEGIN CHECKSTYLE-SUPPRESSION\: (\w+)"/>
<property name="onCommentFormat" value="END CHECKSTYLE-SUPPRESSION\: (\w+)"/>
<property name="checkFormat" value="$1"/>
</module>
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="BEGIN CHECKSTYLE-SUPPRESSION\: ALL"/>
<property name="onCommentFormat" value="END CHECKSTYLE-SUPPRESSION\: ALL"/>
</module>
<!-- Actual checks -->
<module name="LineLength">
<property name="max" value="160"/>
<!-- Annotations -->
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, PACKAGE_DEF, ENUM_CONSTANT_DEF,
ENUM_DEF, METHOD_DEF, CTOR_DEF, RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="AnnotationLocation"/>
<module name="AnnotationUseStyle"/>
<module name="MissingDeprecated"/>
<module name="MissingOverride"/>
<!-- Block Checks -->
<module name="AvoidNestedBlocks"/>
<module name="EmptyBlock">
<property name="tokens"
value="LITERAL_WHILE, LITERAL_TRY, LITERAL_FINALLY, LITERAL_DO, LITERAL_IF,
LITERAL_ELSE, LITERAL_FOR, INSTANCE_INIT, STATIC_INIT, LITERAL_SWITCH,
LITERAL_SYNCHRONIZED"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="(ignore|expect)"/>
</module>
<module name="LeftCurly">
<property name="ignoreEnums" value="false"/>
<property name="tokens"
value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
OBJBLOCK, STATIC_INIT, RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="NeedBraces">
<property name="id" value="SingleLineIf"/>
<property name="tokens" value="LITERAL_IF"/>
<property name="allowSingleLineStatement" value="true"/>
</module>
<module name="NeedBraces">
<property name="id" value="NoSingleLineControl"/>
<property name="tokens" value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_WHILE"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF, LITERAL_SWITCH"/>
</module>
<!-- Class Design -->
<module name="DesignForExtension">
<property name="severity" value="info"/>
</module>
<module name="FinalClass"/>
<module name="HideUtilityClassConstructor"/>
<module name="InnerTypeLast"/>
<module name="InterfaceIsType"/>
<module name="MutableException"/>
<module name="OneTopLevelClass"/>
<module name="ThrowsCount">
<property name="max" value="0"/>
</module>
<module name="VisibilityModifier">
<property name="protectedAllowed" value="true"/>
</module>
<!-- Coding -->
<module name="ArrayTrailingComma"/>
<module name="AvoidDoubleBraceInitialization"/>
<module name="AvoidNoArgumentSuperConstructorCall"/>
<module name="CovariantEquals"/>
<module name="DeclarationOrder">
<!-- Doesn't respect static methods at top -->
<property name="severity" value="ignore"/>
</module>
<module name="DefaultComesLast"/>
<module name="EmptyStatement"/>
<module name="EqualsAvoidNull"/>
<module name="EqualsHashCode"/>
<module name="FallThrough">
<property name="checkLastCaseGroup" value="true"/>
</module>
<module name="HiddenField">
<property name="ignoreConstructorParameter" value="true"/>
<property name="ignoreSetter" value="true"/>
<property name="setterCanReturnItsClass" value="true"/>
<property name="ignoreAbstractMethods" value="true"/>
<!-- Not smart enough -->
<property name="severity" value="ignore"/>
</module>
<module name="IllegalCatch"/>
<module name="IllegalThrows"/>
<module name="IllegalToken"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="IllegalType"/>
<module name="InnerAssignment"/>
<module name="MagicNumber">
<property name="ignoreHashCodeMethod" value="true"/>
<property name="ignoreAnnotationElementDefaults" value="true"/>
</module>
<module name="MissingSwitchDefault"/>
<module name="ModifiedControlVariable"/>
<module name="MultipleStringLiterals">
</module>
<module name="MultipleVariableDeclarations"/>
<module name="NestedForDepth">
<property name="severity" value="warning"/>
</module>
<module name="JavadocMethod">
<property name="scope" value="package"/><!-- We don't need javadoc for private methods -->
<property name="tokens" value="METHOD_DEF"/><!-- We don't need javadoc for constructors -->
<module name="NestedIfDepth"/>
<module name="NestedTryDepth"/>
<module name="NoClone"/>
<module name="NoFinalizer"/>
<module name="OneStatementPerLine"/>
<module name="PackageDeclaration"/>
<module name="ParameterAssignment"/>
<module name="RequireThis"/>
<module name="ReturnCount">
<property name="severity" value="info"/>
</module>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<module name="StringLiteralEquality"/>
<module name="SuperClone"/>
<module name="SuperFinalize"/>
<module name="UnnecessaryParentheses"/>
<module name="UnnecessarySemicolonAfterOuterTypeDeclaration"/>
<module name="UnnecessarySemicolonAfterTypeMemberDeclaration"/>
<module name="UnnecessarySemicolonInEnumeration"/>
<module name="UnnecessarySemicolonInTryWithResources"/>
<module name="UnusedLocalVariable"/>
<module name="VariableDeclarationUsageDistance">
<property name="allowedDistance" value="3"/>
<property name="validateBetweenScopes" value="false"/>
</module>
<module name="VariableDeclarationUsageDistance">
<property name="allowedDistance" value="5"/>
<property name="validateBetweenScopes" value="true"/>
</module>
<!-- Imports -->
<module name="AvoidStarImport"/>
<module name="IllegalImport">
<property name="illegalPkgs" value="sun"/>
</module>
<module name="ImportOrder">
<property name="option" value="bottom"/>
<property name="ordered" value="true"/>
<property name="separated" value="true"/>
<property name="separatedStaticGroups" value="true"/>
<property name="caseSensitive" value="true"/>
<property name="sortStaticImportsAlphabetically" value="true"/>
<property name="groups"
value="java,javax,*,org.mvplugins"/>
<property name="staticGroups"
value="/^.*$/"/>
</module>
<module name="RedundantImport"/>
<module name="UnusedImports"/>
<!-- Javadoc Comments -->
<module name="AtclauseOrder">
<property name="target"
value="CLASS_DEF, COMPACT_CTOR_DEF, CTOR_DEF, ENUM_DEF,
INTERFACE_DEF, METHOD_DEF, RECORD_DEF, VARIABLE_DEF"/>
</module>
<module name="InvalidJavadocPosition"/>
<module name="JavadocBlockTagLocation"/>
<module name="JavadocContentLocationCheck"/>
<module name="JavadocMethod">
<property name="accessModifiers" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="JavadocMethod">
<property name="accessModifiers" value="public"/>
</module>
<module name="JavadocMissingLeadingAsterisk"/>
<module name="JavadocMissingWhitespaceAfterAsterisk"/>
<module name="JavadocParagraph">
<property name="allowNewlineParagraph" value="true"/>
</module>
<module name="JavadocStyle">
<property name="scope" value="package"/>
</module>
<module name="JavadocTagContinuationIndentation"/>
<module name="JavadocType"/>
<module name="JavadocVariable">
<property name="scope" value="package"/><!-- We don't need javadoc for private variables -->
<property name="scope" value="package"/>
</module>
<module name="MissingJavadocMethod">
<property name="scope" value="public"/>
<property name="allowMissingPropertyJavadoc" value="true"/>
</module>
<module name="MissingJavadocMethod">
<property name="scope" value="protected"/>
<property name="excludeScope" value="public"/>
<property name="allowMissingPropertyJavadoc" value="true"/>
<property name="minLineCount" value="2"/>
</module>
<module name="MissingJavadocType">
<property name="scope" value="protected"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
RECORD_DEF, ANNOTATION_DEF"/>
<property name="excludeScope" value="nothing"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="RequireEmptyLineBeforeBlockTagGroup"/>
<module name="SingleLineJavadoc"/>
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocStyle"/>
<module name="WriteTag">
<property name="tag" value="@author"/>
<property name="tagFormat" value="\S"/>
<property name="severity" value="ignore"/>
<property name="tagSeverity" value="warning"/>
</module>
<module name="ConstantName"/>
<module name="LocalVariableName"/>
<module name="MemberName"/>
<module name="MethodName"/>
<module name="PackageName"/>
<module name="ParameterName"/>
<module name="StaticVariableName"/>
<module name="TypeName"/>
<module name="AvoidStarImport">
<property name="severity" value="warning"/>
<property name="excludes" value="com.onarandombox.MultiverseCore.utils,com.onarandombox.MultiverseCore.configuration,com.onarandombox.MultiverseCore.commandsold,com.onarandombox.MultiverseCore.destination"/>
<!-- Metrics -->
<module name="BooleanExpressionComplexity"/>
<module name="ClassDataAbstractionCoupling">
<property name="max" value="7"/>
<property name="excludedClasses"
value="ArrayIndexOutOfBoundsException, ArrayList, Boolean, Byte, Character,
Class, Collection, Deprecated, Deque, Double, DoubleStream, EnumSet, Exception,
Float, FunctionalInterface, HashMap, HashSet, IllegalArgumentException,
IllegalStateException, IndexOutOfBoundsException, IntStream, Integer,
LinkedHashMap, LinkedHashSet, LinkedList, List, Long, LongStream, Map,
NullPointerException, Object, Optional, OptionalDouble, OptionalInt,
OptionalLong, Override, Queue, RuntimeException, SafeVarargs, SecurityException,
Set, Short, SortedMap, SortedSet, Stream, String, StringBuffer, StringBuilder,
SuppressWarnings, Throwable, TreeMap, TreeSet, UnsupportedOperationException,
Void, boolean, byte, char, double, float, int, long, short, var, void"/>
</module>
<module name="IllegalImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports">
<property name="processJavadoc" value="true"/>
</module>
<module name="MethodLength">
<property name="severity" value="warning"/>
<property name="countEmpty" value="false"/>
</module>
<module name="ParameterNumber"/>
<module name="EmptyForIteratorPad"/>
<module name="MethodParamPad"/>
<module name="NoWhitespaceAfter">
<property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS"/>
</module>
<module name="NoWhitespaceBefore"/>
<module name="OperatorWrap"/>
<module name="ParenPad"/>
<module name="TypecastParenPad"/>
<module name="WhitespaceAfter">
<property name="severity" value="warning"/>
</module>
<module name="WhitespaceAround">
<property name="severity" value="warning"/>
</module>
<module name="ModifierOrder"/>
<module name="RedundantModifier"/>
<module name="AvoidNestedBlocks"/>
<module name="EmptyBlock">
<property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_FOR,LITERAL_TRY,LITERAL_WHILE,INSTANCE_INIT,STATIC_INIT"/>
</module>
<module name="LeftCurly"/>
<module name="RightCurly"/>
<module name="EmptyStatement"/>
<module name="EqualsHashCode"/>
<module name="HiddenField">
<property name="tokens" value="VARIABLE_DEF"/><!-- We don't care if parameters hide fields. -->
</module>
<module name="IllegalInstantiation"/>
<module name="InnerAssignment"/>
<module name="MagicNumber">
<property name="ignoreNumbers" value="-1, 0, 0.5, 1, 2, 3"/>
</module>
<module name="MissingSwitchDefault"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<!-- Don't like errors for `final` missing
<module name="DesignForExtension"/>
<module name="FinalClass"/>
-->
<module name="HideUtilityClassConstructor"/>
<module name="InterfaceIsType"/>
<module name="VisibilityModifier">
<property name="protectedAllowed" value="true"/>
</module>
<module name="ArrayTypeStyle"/>
<!-- Don't like errors for `final` missing
<module name="FinalParameters"/>
-->
<module name="TodoComment">
<module name="ClassFanOutComplexity">
<property name="id" value="FanOutComplexityGettingTooHigh"/>
<property name="max" value="20"/>
<property name="excludedClasses"
value="ArrayIndexOutOfBoundsException, ArrayList, Boolean, Byte, Character,
Class, Collection, Deprecated, Deque, Double, DoubleStream, EnumSet, Exception,
Float, FunctionalInterface, HashMap, HashSet, IllegalArgumentException,
IllegalStateException, IndexOutOfBoundsException, IntStream, Integer,
LinkedHashMap, LinkedHashSet, LinkedList, List, Long, LongStream, Map,
NullPointerException, Object, Optional, OptionalDouble, OptionalInt,
OptionalLong, Override, Queue, RuntimeException, SafeVarargs, SecurityException,
Set, Short, SortedMap, SortedSet, Stream, String, StringBuffer, StringBuilder,
SuppressWarnings, Throwable, TreeMap, TreeSet, UnsupportedOperationException,
Void, boolean, byte, char, double, float, int, long, short, var, void"/>
<property name="severity" value="info"/>
</module>
<module name="ClassFanOutComplexity">
<property name="id" value="FanOutComplexityProbablyTooHigh"/>
<property name="max" value="35"/>
<property name="excludedClasses"
value="ArrayIndexOutOfBoundsException, ArrayList, Boolean, Byte, Character,
Class, Collection, Deprecated, Deque, Double, DoubleStream, EnumSet, Exception,
Float, FunctionalInterface, HashMap, HashSet, IllegalArgumentException,
IllegalStateException, IndexOutOfBoundsException, IntStream, Integer,
LinkedHashMap, LinkedHashSet, LinkedList, List, Long, LongStream, Map,
NullPointerException, Object, Optional, OptionalDouble, OptionalInt,
OptionalLong, Override, Queue, RuntimeException, SafeVarargs, SecurityException,
Set, Short, SortedMap, SortedSet, Stream, String, StringBuffer, StringBuilder,
SuppressWarnings, Throwable, TreeMap, TreeSet, UnsupportedOperationException,
Void, boolean, byte, char, double, float, int, long, short, var, void"/>
</module>
<module name="CyclomaticComplexity">
<property name="max" value="7"/>
<property name="severity" value="warning"/>
</module>
<module name="JavaNCSS">
<property name="methodMaximum" value="50"/>
<property name="classMaximum" value="1500"/>
<property name="fileMaximum" value="2000"/>
<property name="recordMaximum" value="150"/>
</module>
<module name="NPathComplexity">
<property name="max" value="200"/>
</module>
<!-- Miscellaneous -->
<module name="ArrayTypeStyle"/>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="CommentsIndentation">
<property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN"/>
</module>
<module name="Indentation">
<property name="basicOffset" value="4"/>
<property name="braceAdjustment" value="4"/>
<property name="caseIndent" value="4"/>
<property name="throwsIndent" value="8"/>
<property name="arrayInitIndent" value="4"/>
<property name="lineWrappingIndentation" value="8"/>
<property name="forceStrictCondition" value="true"/>
</module>
<module name="NoCodeInFile"/>
<module name="OuterTypeFilename"/>
<module name="TodoComment">
<property name="format" value="TODO"/>
<!-- TODO change back to warning after MV5 -->
<property name="severity" value="info"/>
</module>
<module name="TrailingComment">
<property name="legalComment" value="^\sSUPPRESS CHECKSTYLE:"/>
</module>
<module name="UncommentedMain"/>
<module name="UpperEll"/>
<module name="Indentation"/>
<module name="MissingDeprecated"/>
<module name="MissingOverride"/>
<!-- Modifiers -->
<module name="ModifierOrder"/>
<module name="RedundantModifier"/>
<!-- Naming Conventions -->
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="0"/>
<property name="allowedAbbreviations" value="MV"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF,
RECORD_COMPONENT_DEF"/>
</module>
<module name="AbstractClassName">
<property name="ignoreName" value="true"/>
<message key="name.invalidPattern"
value="Abstract class name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="^[A-Z]{1,3}$"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ConstantName">
<message key="name.invalidPattern"
value="Constant name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="^[A-Z]{1,3}$"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalFinalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local final variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$|^[A-Z][A-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodName">
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="^[A-Z]{1,3}$"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="PackageName">
<property name="severity" value="info"/>
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="PatternVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Pattern variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordComponentName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Record component name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordTypeParameterName">
<property name="format" value="^[A-Z]{1,3}$"/>
<message key="name.invalidPattern"
value="Record type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="StaticVariableName">
<message key="name.invalidPattern"
value="Static variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
ANNOTATION_DEF, RECORD_DEF"/>
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<!-- Size Violations -->
<module name="AnonInnerLength">
<property name="max" value="20"/>
</module>
<module name="ExecutableStatementCount">
<property name="max" value="30"/>
</module>
<module name="LambdaBodyLength">
<property name="id" value="LambdaGettingTooLong"/>
<property name="max" value="10"/>
<property name="severity" value="info"/>
</module>
<module name="LambdaBodyLength">
<property name="id" value="LambdaProbablyTooLong"/>
<property name="max" value="25"/>
</module>
<module name="MethodCount">
<property name="maxTotal" value="100"/>
<property name="maxPrivate" value="100"/>
<property name="maxPackage" value="100"/>
<property name="maxProtected" value="100"/>
<property name="maxPublic" value="100"/>
</module>
<module name="MethodLength">
<property name="max" value="50"/>
<property name="severity" value="warning"/>
</module>
<module name="OuterTypeNumber">
<property name="max" value="1"/>
</module>
<module name="ParameterNumber">
<property name="id" value="ConsiderLessMethodParameters"/>
<property name="max" value="4"/>
<property name="ignoreOverriddenMethods" value="true"/>
<property name="severity" value="info"/>
<property name="tokens" value="METHOD_DEF"/>
</module>
<module name="ParameterNumber">
<property name="id" value="ProbablyTooManyMethodParameters"/>
<property name="max" value="10"/>
<property name="ignoreOverriddenMethods" value="true"/>
<property name="tokens" value="METHOD_DEF"/>
</module>
<module name="ParameterNumber">
<property name="id" value="ConsiderLessConstructorParameters"/>
<property name="max" value="7"/>
<property name="ignoreOverriddenMethods" value="true"/>
<property name="severity" value="info"/>
<property name="tokens" value="CTOR_DEF"/>
</module>
<module name="ParameterNumber">
<property name="id" value="ProbablyTooManyConstructorParameters"/>
<property name="max" value="12"/>
<property name="ignoreOverriddenMethods" value="true"/>
<property name="tokens" value="CTOR_DEF"/>
</module>
<module name="RecordComponentNumber">
<property name="max" value="8"/>
</module>
<!-- Whitespace -->
<module name="EmptyForInitializerPad"/>
<module name="EmptyForIteratorPad"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
<property name="allowMultipleEmptyLines" value="false"/>
<property name="allowMultipleEmptyLinesInsideClassMembers" value="false"/>
<property name="tokens"
value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/>
</module>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="MethodParamPad">
<property name="tokens"
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
SUPER_CTOR_CALL, ENUM_CONSTANT_DEF, RECORD_DEF"/>
</module>
<module name="NoLineWrap">
<property name="tokens" value="PACKAGE_DEF, IMPORT, STATIC_IMPORT"/>
</module>
<module name="NoWhitespaceAfter">
<property name="tokens"
value="AT, INC, DEC, UNARY_MINUS,UNARY_PLUS,BNOT,LNOT,DOT,ARRAY_DECLARATOR,INDEX_OP,LITERAL_SYNCHRONIZED,METHOD_REF"/>
</module>
<module name="NoWhitespaceBefore">
<property name="id" value="AllowedWhitespaceBeforeWithoutLinebreak"/>
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, ELLIPSIS, LABELED_STAT"/>
</module>
<module name="NoWhitespaceBefore">
<property name="id" value="AllowedWhitespaceBeforeWithLinebreak"/>
<property name="tokens" value="DOT, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="NoWhitespaceBeforeCaseDefaultColon"/>
<module name="OperatorWrap">
<property name="tokens"
value="QUESTION, COLON, EQUAL, NOT_EQUAL, DIV, PLUS, MINUS, STAR, MOD,
SR, BSR, GE, GT, SL, LE, LT, BXOR, BOR, LOR, BAND, LAND, LITERAL_INSTANCEOF,
TYPE_EXTENSION_AND, ASSIGN, DIV_ASSIGN, PLUS_ASSIGN, MINUS_ASSIGN,
STAR_ASSIGN, MOD_ASSIGN, SR_ASSIGN, BSR_ASSIGN, SL_ASSIGN, BXOR_ASSIGN,
BOR_ASSIGN, BAND_ASSIGN, METHOD_REF"/>
</module>
<module name="ParenPad">
<property name="tokens"
value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA,
RECORD_DEF"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapNl"/>
<property name="option" value="nl"/>
<property name="tokens" value="DOT, AT, METHOD_REF"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapEol"/>
<property name="option" value="eol"/>
<property name="tokens"
value="COMMA, SEMI, ELLIPSIS, RPAREN, ARRAY_DECLARATOR, RBRACK"/>
</module>
<module name="SingleSpaceSeparator"/>
<module name="TypecastParenPad"/>
<module name="WhitespaceAfter">
<property name="tokens"
value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE, LITERAL_RETURN,
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, LITERAL_FINALLY, DO_WHILE, ELLIPSIS,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_CATCH, LAMBDA,
LITERAL_YIELD, LITERAL_CASE"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyLambdas" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<property name="ignoreEnhancedForColon" value="false"/>
<property name="tokens"
value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks
may only be represented as '{}' when not part of a multi-block statement"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
</module>
</module>
+6
View File
@@ -2,4 +2,10 @@
* This file was generated by the Gradle 'init' task.
*/
pluginManagement {
repositories {
gradlePluginPortal()
}
}
rootProject.name = 'multiverse-core'
@@ -1,142 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.api;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.Vector;
/**
* A destination API for Multiverse
* Any plugin can add these to MV and when they are, any action that uses them (portals, MVTP, etc.) can use them!
*/
@Deprecated
public interface MVDestination {
/**
* Returns the identifier or prefix that is required for this destination.
* <p>
* Portals have a prefix of "p" for example and OpenWarp (third party plugin) uses "ow". This is derived from a
* hash and cannot have duplicate values. Read that as your plugin cannot use 'p' because it's already used.
* Please check the wiki when adding a custom destination!
*
* @return The identifier or prefix that is required for this destination.
*/
String getIdentifier();
/**
* Allows you to determine if a Destination is valid for the type it thinks it is.
* <p>
* An example of this would be the exact destination. A valid string would be: e:0,0,0 where an invalid one would
* be e:1:2:3. The first string would return true the second would return false. This is simply a convenience
* method
* and does not even NEED to be called, but it's highly recommended if you're teleporting, but it's mainly for
* Multiverse Internal use.
*
* @param plugin The plugin who the type belongs to.
* @param destination The destination string. ex: p:MyPortal:nw
*
* @return True if the destination is valid, false if not.
*/
boolean isThisType(JavaPlugin plugin, String destination);
/**
* Returns the location a specific entity will spawn at when being teleported to this Destination.
* <p>
* To just retrieve the location as it is stored you can just pass null, but be warned some destinations may return
* null back to you if you do this. It is always safer to pass an actual entity. This is used so things like
* minecarts can be teleported.
* <p>
* Do not forget to use {@link #getVelocity()} as destinations can use this too!
*
* @param entity The entity to be teleported.
*
* @return The location of the entity.
*/
Location getLocation(Entity entity);
/**
* Returns the velocity vector for this destination.
* <p>
* Plugins wishing to fully support MVDestinations MUST implement this.
*
* @return A vector representing the speed/direction the player should travel when arriving
*/
Vector getVelocity();
/**
* Sets the destination string.
* <p>
* This should be used when you want to tell this destination object about a change in where it should take people.
* The destination param should be match the result from {@link #getIdentifier()}. A valid example would be that if
* {@link #getIdentifier()} returned "ow" our destination string could be "ow:TownCenter" but could not be
* "p:HomePortal"
*
* @param plugin The plugin who the type belongs to.
* @param destination The destination string. ex: p:MyPortal:nw
*/
void setDestination(JavaPlugin plugin, String destination);
/**
* Returns true if the destination is valid and players will be taken to it.
* <p>
* Even if destinations are in the correct format (p:MyPortal) MyPortal may not exist, and therefore this would
* return false.
*
* @return True if the destination is valid; false if not.
*/
boolean isValid();
/**
* Gives you a general friendly description of the type of destination.
* <p>
* For example, the PlayerDestination sets this to "Player". You can use this to show where a player will be taken.
*
* @return A friendly string description of the type of destination.
*/
String getType();
/**
* Gives you a specific name of the destination.
* <p>
* For example, the PlayerDestination sets this to The Player's Name.
*
* @return A friendly string stating the name of the destination.
*/
String getName();
/**
* Returns a string that can easily be saved in the config that contains all the details needed to rebuild this
* destination.
* <p>
* ex: e:0,0,0:50:50
*
* @return The savable config string.
*/
String toString();
/**
* Returns the permissions string required to go here.
* <p>
* ex: multiverse.access.world
* <p>
* NOTE: This is NOT the permission to use the teleport command.
*
* @return the permissions string required to go here.
*/
String getRequiredPermission();
/**
* Should the Multiverse SafeTeleporter be used?
* <p>
* If not, MV will blindly take people to the location specified.
*
* @return True if the SafeTeleporter will be used, false if not.
*/
boolean useSafeTeleporter();
}
@@ -1,675 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.api;
import java.util.List;
import com.onarandombox.MultiverseCore.exceptions.PropertyDoesNotExistException;
import com.onarandombox.MultiverseCore.world.configuration.AddProperties;
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
import com.onarandombox.MultiverseCore.world.configuration.EnglishChatColor;
import org.bukkit.ChatColor;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.WorldType;
import org.bukkit.permissions.Permission;
import org.jetbrains.annotations.Nullable;
/**
* The API for a Multiverse Handled World.
*/
public interface MVWorld {
/**
* Returns the Bukkit world object that this world describes.
*
* @return A {@link World}
*/
World getCBWorld();
/**
* Gets the name of this world. The name cannot be changed.
* <p>
* Note for plugin developers: Usually {@link #getAlias()}
* is what you want to use instead of this method.
*
* @return The name of the world as a String.
*/
String getName();
/**
* Gets the type of this world. As of 1.2 this will be:
* FLAT, NORMAL or VERSION_1_1
* <p>
* This is <b>not</b> the generator.
*
* @return The Type of this world.
*/
WorldType getWorldType();
/**
* Gets the environment of this world.
*
* @return A {@link org.bukkit.World.Environment}.
*/
World.Environment getEnvironment();
/**
* Sets the environment of a world.
* <p>
* Note: This will ONLY take effect once the world is unloaded/reloaded.
*
* @param environment A {@link org.bukkit.World.Environment}.
*/
void setEnvironment(World.Environment environment);
/**
* Gets the difficulty of this world.
*
* @return The difficulty of this world.
*/
Difficulty getDifficulty();
/**
* Sets the difficulty of this world and returns true if success.
* Valid string values are either an integer of difficulty(0-3) or
* the name that resides in the Bukkit enum, ex. {@code PEACEFUL}
*
* @param difficulty The difficulty to set the world to as a string.
* @return True if success, false if the provided string
* could not be translated to a difficulty.
* @deprecated Use {@link #setDifficulty(Difficulty)} or, if you have to
* pass a string, use {@link #setPropertyValue(String, String)} instead.
*/
@Deprecated
boolean setDifficulty(String difficulty);
/**
* Sets the difficulty of this world and returns {@code true} on success.
* Valid string values are either an integer of difficulty(0-3) or
* the name that resides in the Bukkit enum, ex. PEACEFUL
*
* @param difficulty The new difficulty.
* @return True if success, false if the operation failed... for whatever reason.
*/
boolean setDifficulty(Difficulty difficulty);
/**
* Gets the world seed of this world.
*
* @return The Long version of the seed.
*/
long getSeed();
/**
* Sets the seed of this world.
*
* @param seed A Long that is the seed.
*/
void setSeed(long seed);
/**
* Gets the generator of this world.
*
* @return The name of the generator.
*/
String getGenerator();
/**
* Sets the generator of this world.
*
* @param generator The new generator's name.
*/
void setGenerator(String generator);
/**
* Gets the help-message for a property.
* @param property The name of the property.
* @return The help-message.
* @throws PropertyDoesNotExistException Thrown if the property was not found.
*/
String getPropertyHelp(String property) throws PropertyDoesNotExistException;
/**
* Gets a property as {@link String}.
*
* @param property The name of a world property to get.
* @return The string-representation of that property.
* @throws PropertyDoesNotExistException Thrown if the property was not found in the world.
*/
String getPropertyValue(String property) throws PropertyDoesNotExistException;
/**
* Sets a property to a given value.
*
* @param property The name of a world property to set.
* @param value A value in string representation, it will be parsed to the correct type.
* @return True if the value was set, false if not.
* @throws PropertyDoesNotExistException Thrown if the property was not found in the world.
*/
boolean setPropertyValue(String property, String value) throws PropertyDoesNotExistException;
/**
* Adds a value to the given property. The property must be a {@link AddProperties}.
*
* @param property The name of a {@link AddProperties} to add a value to.
* @param value A value in string representation, it will be parsed to the correct type.
* @return True if the value was added, false if not.
* @deprecated We changed the entire world-config-system. This is not compatible any more.
*/
@Deprecated
boolean addToVariable(String property, String value);
/**
* Removes a value from the given property. The property must be a {@link AddProperties}.
*
* @param property The name of a {@link AddProperties} to remove a value
* from.
* @param value A value in string representation, it will be parsed to the correct type.
* @return True if the value was removed, false if not.
* @deprecated We changed the entire world-config-system. This is not compatible any more.
*/
@Deprecated
boolean removeFromVariable(String property, String value);
/**
* Removes all values from the given property. The property must be a {@link AddProperties}.
*
* @param property The name of a {@link AddProperties} to clear.
* @return True if it was cleared, false if not.
* @deprecated We changed the entire world-config-system. This is not compatible any more.
*/
@Deprecated
boolean clearVariable(String property);
/**
* Clears a list property (sets it to []).
*
* @param property The property to clear.
* @return True if success, false if fail.
* @deprecated We changed the entire world-config-system. This is not compatible any more.
*/
@Deprecated
boolean clearList(String property);
// end of old config stuff
// permission stuff
/**
* Gets the lowercased name of the world. This method is required, since the permissables
* lowercase all permissions when recalculating.
* <p>
* Note: This also means if a user has worlds named: world and WORLD, that they can both
* exist, and both be teleported to independently, but their permissions **cannot** be
* uniqueified at this time. See bug report #.
*
* @return The lowercased name of the world.
*/
String getPermissibleName();
/**
* Gets the permission required to enter this world.
*
* @return The permission required to be exempt from charges to/from this world.
*/
Permission getAccessPermission();
/**
* Gets the permission required to be exempt when entering.
*
* @return The permission required to be exempt when entering.
*/
Permission getExemptPermission();
// end of permission stuff
/**
* Gets the alias of this world.
* <p>
* This alias allows users to have a world named "world" but show up in the list as "FernIsland"
*
* @return The alias of the world as a String.
*/
String getAlias();
/**
* Sets the alias of the world.
*
* @param alias A string that is the new alias.
*/
void setAlias(String alias);
/**
* Gets the color that this world's name/alias will display as.
*
* @return The color of this world.
*/
ChatColor getColor();
/**
* Sets the color that this world's name/alias will display as.
*
* @param color A valid color name.
* @return True if the color was set, false if not.
*/
boolean setColor(String color);
/**
* Gets the style that this world's name/alias will display as.
*
* @return The style of this world. {@code null} for "normal" style.
*/
ChatColor getStyle();
/**
* Sets the style that this world's name/alias will display as.
*
* @param style A valid style name.
* @return True if the style was set, false if not.
*/
boolean setStyle(String style);
/**
* Tells you if someone entered a valid color.
*
* @param color A string that may translate to a color.
* @return True if it is a color, false if not.
*
* @deprecated This has been moved: {@link EnglishChatColor#isValidAliasColor(String)}
*/
@Deprecated
boolean isValidAliasColor(String color);
/**
* Returns a very nicely colored string (using Alias and Color if they are set).
*
* @return A nicely colored string.
*/
String getColoredWorldString();
// animals&monster stuff
/**
* Gets whether or not animals are allowed to spawn in this world.
*
* @return True if ANY animal can, false if no animals can spawn.
*/
boolean canAnimalsSpawn();
/**
* Sets whether or not animals can spawn.
* If there are values in {@link #getAnimalList()} and this is false,
* those animals become the exceptions, and will spawn
*
* @param allowAnimalSpawn True to allow spawning of monsters, false to prevent.
*/
void setAllowAnimalSpawn(boolean allowAnimalSpawn);
/**
* Returns a list of animals. This list always negates the {@link #canAnimalsSpawn()} result.
*
* @return A list of animals that will spawn if {@link #canAnimalsSpawn()} is false.
*/
List<String> getAnimalList();
/**
* Gets whether or not monsters are allowed to spawn in this world.
*
* @return True if ANY monster can, false if no monsters can spawn.
*/
boolean canMonstersSpawn();
/**
* Sets whether or not monsters can spawn.
* If there are values in {@link #getMonsterList()} and this is false,
* those monsters become the exceptions, and will spawn
*
* @param allowMonsterSpawn True to allow spawning of monsters, false to prevent.
*/
void setAllowMonsterSpawn(boolean allowMonsterSpawn);
/**
* Returns a list of monsters. This list always negates the {@link #canMonstersSpawn()} result.
*
* @return A list of monsters that will spawn if {@link #canMonstersSpawn()} is false.
*/
List<String> getMonsterList();
// end of animal&monster stuff
/**
* Gets whether or not PVP is enabled in this world in some form (fake or not).
*
* @return True if players can take damage from other players.
*/
boolean isPVPEnabled();
/**
* Turn pvp on or off. This setting is used to set the world's PVP mode.
*
* @param pvpMode True to enable PVP damage, false to disable it.
*/
void setPVPMode(boolean pvpMode);
/**
* Turn pvp on or off. This setting is used to set the world's PVP mode, and thus relies on fakePVP
*
* @return True if this world has fakepvp on
* @deprecated This is deprecated.
*/
@Deprecated
boolean getFakePVP();
/**
* Gets whether or not this world will display in chat, mvw and mvl regardless if a user has the
* access permissions to go to this world.
*
* @return True if the world will be hidden, false if not.
*/
boolean isHidden();
/**
* Sets whether or not this world will display in chat, mvw and mvl regardless if a user has the
* access permissions to go to this world.
*
* @param hidden Set
*/
void setHidden(boolean hidden);
/**
* Gets whether weather is enabled in this world.
*
* @return True if weather events will occur, false if not.
*/
boolean isWeatherEnabled();
/**
* Sets whether or not there will be weather events in a given world.
* If set to false, Multiverse will disable the weather in the world immediately.
*
* @param enableWeather True if weather events should occur in a world, false if not.
*/
void setEnableWeather(boolean enableWeather);
/**
* Gets whether or not CraftBukkit is keeping the chunks for this world in memory.
*
* @return True if CraftBukkit is keeping spawn chunks in memory.
*/
boolean isKeepingSpawnInMemory();
/**
* If true, tells Craftbukkit to keep a worlds spawn chunks loaded in memory (default: true)
* If not, CraftBukkit will attempt to free memory when players have not used that world.
* This will not happen immediately.
*
* @param keepSpawnInMemory If true, CraftBukkit will keep the spawn chunks loaded in memory.
*/
void setKeepSpawnInMemory(boolean keepSpawnInMemory);
/**
* Gets the spawn location of this world.
*
* @return The spawn location of this world.
*/
Location getSpawnLocation();
/**
* Sets the spawn location for a world.
*
* @param spawnLocation The spawn location for a world.
*/
void setSpawnLocation(Location spawnLocation);
/**
* Gets whether or not the hunger level of players will go down in a world.
*
* @return True if it will go down, false if it will remain steady.
*/
boolean getHunger();
/**
* Sets whether or not the hunger level of players will go down in a world.
*
* @param hungerEnabled True if hunger will go down, false to keep it at
* the level they entered a world with.
*/
void setHunger(boolean hungerEnabled);
/**
* Gets the GameMode of this world.
*
* @return The GameMode of this world.
*/
GameMode getGameMode();
/**
* Sets the game mode of this world.
*
* @param gameMode A valid game mode string (either
* an int ex. 0 or a string ex. creative).
* @return True if the game mode was successfully changed, false if not.
* @deprecated Use {@link #setGameMode(GameMode)} instead. If you have to
* pass a string, use {@link #setPropertyValue(String, String)}.
*/
@Deprecated
boolean setGameMode(String gameMode);
/**
* Sets the game mode of this world.
*
* @param gameMode The new {@link GameMode}.
* @return True if the game mode was successfully changed, false if not.
*/
boolean setGameMode(GameMode gameMode);
/**
* Gets the amount of currency it requires to enter this world.
*
* @return The amount it costs to enter this world.
*/
double getPrice();
/**
* Sets the price for entry to this world.
* You can think of this like an amount.
* The type can be set with {@link #setCurrency(Material)}
*
* @param price The Amount of money/item to enter the world.
*/
void setPrice(double price);
/**
* Gets the type of currency that will be used when users enter this world. A value of null indicates a non-item
* based currency is used.
*
* @return The type of currency that will be used when users enter this world.
*/
@Nullable
Material getCurrency();
/**
* Sets the type of item that will be required given the price is not 0.
* Use a value of null to specify a non-item based currency.
*
* @param item The Type of currency that will be used when users enter this world.
*/
void setCurrency(@Nullable Material item);
/**
* Gets the world players will respawn in if they die in this one.
*
* @return A world that exists on the server.
*/
World getRespawnToWorld();
/**
* Sets the world players will respawn in if they die in this one.
* Returns true upon success, false upon failure.
*
* @param respawnWorld The name of a world that exists on the server.
* @return True if respawnWorld existed, false if not.
*/
boolean setRespawnToWorld(String respawnWorld);
/**
* Gets the scaling value of this world.Really only has an effect if you use
* Multiverse-NetherPortals.
*
* @return This world's non-negative, non-zero scale.
*/
double getScaling();
/**
* Sets the scale of this world. Really only has an effect if you use
* Multiverse-NetherPortals.
*
* @param scaling A scaling value, cannot be negative or 0.
* @return Whether the scale was set successfully.
*/
boolean setScaling(double scaling);
/**
* Gets whether or not a world will auto-heal players if the difficulty is on peaceful.
*
* @return True if the world should heal (default), false if not.
*/
boolean getAutoHeal();
/**
* Sets whether or not a world will auto-heal players if the difficulty is on peaceful.
*
* @param heal True if the world will heal.
*/
void setAutoHeal(boolean heal);
/**
* Gets whether or not Multiverse should auto-adjust the spawn for this world.
*
* @return True if Multiverse should adjust the spawn, false if not.
*/
boolean getAdjustSpawn();
/**
* Sets whether or not Multiverse should auto-adjust the spawn for this world.
*
* @param adjust True if multiverse should adjust the spawn, false if not.
*/
void setAdjustSpawn(boolean adjust);
/**
* Gets whether or not Multiverse should auto-load this world.
*
* @return True if Multiverse should auto-load this world.
*/
boolean getAutoLoad();
/**
* Sets whether or not Multiverse should auto-load this world.
* <p>
* True is default.
*
* @param autoLoad True if multiverse should autoload this world the spawn, false if not.
*/
void setAutoLoad(boolean autoLoad);
/**
* Gets whether or not a player who dies in this world will respawn in their
* bed or follow the normal respawn pattern.
*
* @return True if players dying in this world should respawn at their bed.
*/
boolean getBedRespawn();
/**
* Sets whether or not a player who dies in this world will respawn in their
* bed or follow the normal respawn pattern.
* <p>
* True is default.
*
* @param autoLoad True if players dying in this world respawn at their bed.
*/
void setBedRespawn(boolean autoLoad);
/**
* Sets the player limit for this world after which players without an override
* permission node will not be allowed in. A value of -1 or less signifies no limit
*
* @param limit The new limit
*/
void setPlayerLimit(int limit);
/**
* Gets the player limit for this world after which players without an override
* permission node will not be allowed in. A value of -1 or less signifies no limit
*
* @return The player limit
*/
int getPlayerLimit();
/**
* Same as {@link #getTime()}, but returns a string.
* @return The time as a short string: 12:34pm
*/
String getTime();
/**
* Sets the current time in a world.
* <p>
* This method will take the following formats:
* 11:37am
* 4:30p
* day(morning), night, noon, midnight
*
* @param timeAsString The formatted time to set the world to.
* @return True if the time was set, false if not.
*/
boolean setTime(String timeAsString);
/**
* Sets The types of portals that are allowed in this world.
*
* @param type The type of portals allowed in this world.
*/
void allowPortalMaking(AllowedPortalType type);
/**
* Gets which type(s) of portals are allowed to be constructed in this world.
*
* @return The type of portals that are allowed.
*/
AllowedPortalType getAllowedPortals();
// properties that are not "getter+setter" style
/**
* Gets a list of all the worlds that players CANNOT travel to from this world,
* regardless of their access permissions.
*
* @return A List of world names.
*/
List<String> getWorldBlacklist();
/**
* Gets all the names of all properties that can be SET.
*
* @return All property names, with alternating colors.
*/
String getAllPropertyNames();
/**
* Whether or not players are allowed to fly in this world.
*
* @return True if players allowed to fly in this world.
*/
boolean getAllowFlight();
/**
* Sets whether or not players are allowed to fly in this world.
*
* @param allowFlight True to allow flight in this world.
*/
void setAllowFlight(final boolean allowFlight);
}
@@ -1,325 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.api;
import java.util.Collection;
import java.util.List;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.WorldType;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.generator.ChunkGenerator;
import org.jvnet.hk2.annotations.Contract;
/**
* Multiverse 2 World Manager API
* <p>
* This API contains all of the world managing
* functions that your heart desires!
*/
@Contract
public interface MVWorldManager {
/**
* Add a new World to the Multiverse Setup.
*
* @param name World Name
* @param env Environment Type
* @param seedString The seed in the form of a string.
* If the seed is a Long,
* it will be interpreted as such.
* @param type The Type of the world to be made.
* @param generateStructures If true, this world will get NPC villages.
* @param generator The Custom generator plugin to use.
* @return True if the world is added, false if not.
*/
boolean addWorld(String name, Environment env, String seedString, WorldType type, Boolean generateStructures,
String generator);
/**
* Add a new World to the Multiverse Setup.
*
* @param name World Name
* @param env Environment Type
* @param seedString The seed in the form of a string.
* If the seed is a Long,
* it will be interpreted as such.
* @param type The Type of the world to be made.
* @param generateStructures If true, this world will get NPC villages.
* @param generator The Custom generator plugin to use.
* @param useSpawnAdjust If true, multiverse will search for a safe spawn. If not, It will not modify the level.dat.
* @return True if the world is added, false if not.
*/
boolean addWorld(String name, Environment env, String seedString, WorldType type, Boolean generateStructures,
String generator, boolean useSpawnAdjust);
/**
* Make a copy of a world.
*
* @param oldName
* Name of world to be copied
* @param newName
* Name of world to be created
* @return True if the world is copied successfully, false if not.
*/
boolean cloneWorld(String oldName, String newName);
/**
* Remove the world from the Multiverse list, from the config and deletes
* the folder.
*
* @param name
* The name of the world to remove
* @return True if success, false if failure.
*/
boolean deleteWorld(String name);
/**
* Remove the world from the Multiverse list, from the
* config if wanted, and deletes the folder.
*
* @param name The name of the world to remove
* @param removeConfig If true(default), we'll remove the entries from the
* config. If false, they'll stay and the world may come back.
* @return True if success, false if failure.
*/
boolean deleteWorld(String name, boolean removeConfig);
/**
*
* @param name The name of the world to remove
* @param removeFromConfig If true(default), we'll remove the entries from the
* config. If false, they'll stay and the world may come back.
* @param deleteWorldFolder If true the world folder will be completely deleted. If false
* only the contents of the world folder will be deleted
* @return True if success, false if failure.
*/
boolean deleteWorld(String name, boolean removeFromConfig, boolean deleteWorldFolder);
/**
* Unload a world from Multiverse.
*
* @param name Name of the world to unload
* @return True if the world was unloaded, false if not.
*/
boolean unloadWorld(String name);
/**
* Unload a world from Multiverse with option to prevent calling unloadWorld in Bukkit.
*
* @param name Name of the world to unload
* @param unloadBukkit True if Bukkit world should be unloaded
* @return True if the world was unloaded, false if not.
*/
boolean unloadWorld(String name, boolean unloadBukkit);
/**
* Loads the world. Only use this if the world has been
* unloaded with {@link #unloadWorld(String)}.
*
* @param name The name of the world to load
* @return True if success, false if failure.
*/
boolean loadWorld(String name);
/**
* Removes all players from the specified world.
*
* @param name World to remove players from.
*/
void removePlayersFromWorld(String name);
/**
* Test if a given chunk generator is valid.
*
* @param generator The generator name.
* @param generatorID The generator id.
* @param worldName The worldName to use as the default.
* @return A {@link ChunkGenerator} or null
*/
ChunkGenerator getChunkGenerator(String generator, String generatorID, String worldName);
/**
* Returns a list of all the worlds Multiverse knows about.
*
* @return A list of {@link MVWorld}.
*/
Collection<MVWorld> getMVWorlds();
/**
* Returns a {@link MVWorld} if it exists, and null if it does not.
* This will search name AND alias.
*
* @param name The name or alias of the world to get.
* @return A {@link MVWorld} or null.
*/
MVWorld getMVWorld(String name);
/**
* Returns a {@link MVWorld} if the world with name given exists, and null if it does not.
* This will search optionally for alias names.
*
* @param name The name or optionally the alias of the world to get.
* @param checkAliases Indicates whether to check for world alias name.
* @return A {@link MVWorld} or null.
*/
MVWorld getMVWorld(String name, boolean checkAliases);
/**
* Returns a {@link MVWorld} if it exists, and null if it does not.
*
* @param world The Bukkit world to check.
* @return A {@link MVWorld} or null.
*/
MVWorld getMVWorld(World world);
/**
* Checks to see if the given name is a valid {@link MVWorld}
* Searches based on world name AND alias.
*
* @param name The name or alias of the world to check.
* @return True if the world exists, false if not.
*/
boolean isMVWorld(String name);
/**
* Checks to see if the given name is a valid {@link MVWorld}.
* Optionally searches by alias is specified.
*
* @param name The name or alias of the world to check.
* @param checkAliases Indicates whether to check for world alias name.
* @return True if the world exists, false if not.
*/
boolean isMVWorld(String name, boolean checkAliases);
/**
* Checks to see if the given world is a valid {@link MVWorld}.
*
* @param world The Bukkit world to check.
* @return True if the world has been loaded into MV2, false if not.
*/
boolean isMVWorld(World world);
/**
* Load the Worlds &amp; Settings from the configuration file.
*
* @param forceLoad If set to true, this will perform a total
* reset and not just load new worlds.
*/
void loadWorlds(boolean forceLoad);
/**
* Loads the Worlds &amp; Settings for any worlds that bukkit loaded before us.
* <p>
* This way people will _always_ have some worlds in the list.
*/
void loadDefaultWorlds();
/**
* Gets the world players will spawn in on first join.
* Currently this always returns worlds.get(0) from Bukkit.
*
* @return A Multiverse world that players will spawn in or null if no MV world has been set.
*/
MVWorld getSpawnWorld();
/**
* Gets the list of worlds in the config, but unloaded.
*
* @return A List of worlds as strings.
*/
List<String> getUnloadedWorlds();
/**
* This method populates an internal list and needs to be called after multiverse initialization.
*/
void getDefaultWorldGenerators();
/**
* Load the config from a file.
*
* @return A loaded configuration.
*/
FileConfiguration loadWorldsConfig();
/**
* Saves the world config to disk.
*
* @return True if success, false if fail.
*/
boolean saveWorldsConfig();
/**
* Remove the world from the Multiverse list and from the config.
*
* @param name The name of the world to remove
* @return True if success, false if failure.
*/
boolean removeWorldFromConfig(String name);
/**
* Sets the initial spawn world for new players.
*
* @param world The World new players should spawn in.
*/
void setFirstSpawnWorld(String world);
/**
* Gets the world players should spawn in first.
*
* @return The {@link MVWorld} new players should spawn in.
*/
MVWorld getFirstSpawnWorld();
/**
* Regenerates a world.
*
* @param name Name of the world to regenerate
* @param useNewSeed If a new seed should be used
* @param randomSeed If the new seed should be random
* @param seed The seed of the world.
*
* @return True if success, false if fail.
*/
boolean regenWorld(String name, boolean useNewSeed, boolean randomSeed, String seed);
/**
* Regenerates a world.
*
* @param name Name of the world to regenerate
* @param useNewSeed If a new seed should be used
* @param randomSeed If the new seed should be random
* @param seed The seed of the world.
* @param keepGameRules If GameRules should be kept on world regen.
*
* @return True if success, false if fail.
*/
boolean regenWorld(String name, boolean useNewSeed, boolean randomSeed, String seed, boolean keepGameRules);
boolean isKeepingSpawnInMemory(World world);
/**
* Checks whether Multiverse knows about a provided unloaded world. This
* method will check the parameter against the alias mappings.
*
* @param name The name of the unloaded world
* @param includeLoaded The value to return if the world is loaded
*
* @return True if the world exists and is unloaded. False if the world
* does not exist. {@code includeLoaded} if the world exists and is loaded.
*/
boolean hasUnloadedWorld(String name, boolean includeLoaded);
/**
* Get all the possible worlds that Multiverse has detected to be importable.
*
* @return A collection of world names that are deemed importable.
*/
Collection<String> getPotentialWorlds();
}
@@ -1,87 +0,0 @@
package com.onarandombox.MultiverseCore.api;
import java.util.concurrent.CompletableFuture;
import co.aikar.commands.BukkitCommandIssuer;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.teleportation.TeleportResult;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.jvnet.hk2.annotations.Contract;
/**
* Used to safely teleport people.
*/
@Contract
public interface SafeTTeleporter extends Teleporter {
/**
* Gets the next safe location around the given location.
* @param l A {@link Location}.
* @return A safe {@link Location}.
*/
Location getSafeLocation(Location l);
/**
* Gets the next safe location around the given location.
* @param l A {@link Location}.
* @param tolerance The tolerance.
* @param radius The radius.
* @return A safe {@link Location}.
*/
Location getSafeLocation(Location l, int tolerance, int radius);
/**
* Safely teleport the entity to the MVDestination. This will perform checks to see if the place is safe, and if
* it's not, will adjust the final destination accordingly.
*
* @param teleporter Person who performed the teleport command.
* @param teleportee Entity to teleport
* @param destination Destination to teleport them to
* @return true for success, false for failure
*/
@Deprecated
TeleportResult safelyTeleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination);
/**
* Safely teleport the entity to the MVDestination. This will perform checks to see if the place is safe, and if
* it's not, will adjust the final destination accordingly.
*
* @param teleporter Person who performed the teleport command.
* @param teleportee Entity to teleport
* @param destination Destination to teleport them to
* @return true for success, false for failure
*/
CompletableFuture<TeleportResult> safelyTeleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination);
/**
* Safely teleport the entity to the Location. This may perform checks to
* see if the place is safe, and if
* it's not, will adjust the final destination accordingly.
*
* @param teleporter Person who issued the teleport command.
* @param teleportee Entity to teleport.
* @param location Location to teleport them to.
* @param safely Should the destination be checked for safety before teleport?
* @return true for success, false for failure.
*/
TeleportResult safelyTeleport(CommandSender teleporter, Entity teleportee, Location location,
boolean safely);
/**
* Returns a safe location for the entity to spawn at.
*
* @param entity The entity to spawn
* @param destination The MVDestination to take the entity to.
* @return A new location to spawn the entity at.
*/
Location getSafeLocation(Entity entity, DestinationInstance destination);
/**
* Finds a portal-block next to the specified {@link Location}.
* @param l The {@link Location}
* @return The next portal-block's {@link Location}.
*/
Location findPortalBlockNextTo(Location l);
}
@@ -1,33 +0,0 @@
package com.onarandombox.MultiverseCore.api;
import java.util.concurrent.CompletableFuture;
import co.aikar.commands.BukkitCommandIssuer;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.teleportation.TeleportResult;
import org.bukkit.entity.Entity;
import org.jvnet.hk2.annotations.Contract;
@Contract
public interface Teleporter {
/**
* Teleport the entity to the Multiverse Destination.
*
* @param teleporter Person who performed the teleport command.
* @param teleportee Entity to teleport
* @param destination Destination to teleport them to
* @return true for success, false for failure
*/
@Deprecated
TeleportResult teleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination);
/**
* Teleport the entity to the Multiverse Destination.
*
* @param teleporter Person who performed the teleport command.
* @param teleportee Entity to teleport
* @param destination Destination to teleport them to
* @return true for success, false for failure
*/
CompletableFuture<TeleportResult> teleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination);
}
@@ -1,70 +0,0 @@
package com.onarandombox.MultiverseCore.api;
import java.util.List;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.jvnet.hk2.annotations.Contract;
/**
* Used to remove animals from worlds that don't belong there.
*/
@Contract
public interface WorldPurger {
/**
* Synchronizes the given worlds with their settings.
*
* @param worlds A list of {@link MVWorld}
*/
void purgeWorlds(List<MVWorld> worlds);
/**
* Convenience method for {@link #purgeWorld(MVWorld, java.util.List, boolean, boolean)} that takes the settings from the world-config.
*
* @param world The {@link MVWorld}.
*/
void purgeWorld(MVWorld world);
/**
* Clear all animals/monsters that do not belong to a world according to the config.
*
* @param mvworld The {@link MVWorld}.
* @param thingsToKill A {@link List} of animals/monsters to be killed.
* @param negateAnimals Whether the monsters in the list should be negated.
* @param negateMonsters Whether the animals in the list should be negated.
*/
void purgeWorld(MVWorld mvworld, List<String> thingsToKill, boolean negateAnimals,
boolean negateMonsters);
/**
* Clear all animals/monsters that do not belong to a world according to the config.
*
* @param mvworld The {@link MVWorld}.
* @param thingsToKill A {@link List} of animals/monsters to be killed.
* @param negateAnimals Whether the monsters in the list should be negated.
* @param negateMonsters Whether the animals in the list should be negated.
* @param sender The {@link CommandSender} that initiated the action. He will/should be notified.
*/
void purgeWorld(MVWorld mvworld, List<String> thingsToKill, boolean negateAnimals,
boolean negateMonsters, CommandSender sender);
/**
* Determines whether the specified creature should be killed.
*
* @param e The creature.
* @param thingsToKill A {@link List} of animals/monsters to be killed.
* @param negateAnimals Whether the monsters in the list should be negated.
* @param negateMonsters Whether the animals in the list should be negated.
* @return {@code true} if the creature should be killed, otherwise {@code false}.
*/
boolean shouldWeKillThisCreature(Entity e, List<String> thingsToKill, boolean negateAnimals, boolean negateMonsters);
/**
* Determines whether the specified creature should be killed and automatically reads the params from a world object.
*
* @param w The world.
* @param e The creature.
* @return {@code true} if the creature should be killed, otherwise {@code false}.
*/
boolean shouldWeKillThisCreature(MVWorld w, Entity e);
}
@@ -1,53 +0,0 @@
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class CheckCommand extends MultiverseCommand {
private final DestinationsProvider destinationsProvider;
@Inject
public CheckCommand(@NotNull MVCommandManager commandManager, @NotNull DestinationsProvider destinationsProvider) {
super(commandManager);
this.destinationsProvider = destinationsProvider;
}
@Subcommand("check")
@CommandPermission("multiverse.core.check")
@CommandCompletion("@players @destinations|@mvworlds")
@Syntax("<player> <destination>")
@Description("{@@mv-core.check.description}")
public void onCheckCommand(BukkitCommandIssuer issuer,
@Syntax("<player>")
@Description("{@@mv-core.check.player.description}")
Player player,
@Syntax("<destination>")
@Description("{@@mv-core.check.destination.description}")
ParsedDestination<?> destination
) {
issuer.sendInfo(MVCorei18n.CHECK_CHECKING,
"{player}", player.getName(),
"{destination}", destination.toString());
//TODO More detailed output on permissions required.
this.destinationsProvider.checkTeleportPermissions(issuer, player, destination);
}
}
@@ -1,61 +0,0 @@
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.CommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Conditions;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class CloneCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public CloneCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@Subcommand("clone")
@CommandPermission("multiverse.core.clone")
@CommandCompletion("@mvworlds:scope=both @empty")
@Syntax("<world> <new world name>")
@Description("{@@mv-core.clone.description}")
public void onCloneCommand(CommandIssuer issuer,
@Conditions("validWorldName:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.clone.world.description}")
String worldName,
@Single
@Conditions("validWorldName:scope=new")
@Syntax("<new world name>")
@Description("{@@mv-core.clone.newWorld.description}")
String newWorldName
) {
issuer.sendInfo(MVCorei18n.CLONE_CLONING,
"{world}", worldName,
"{newWorld}", newWorldName);
if (!this.worldManager.cloneWorld(worldName, newWorldName)) {
issuer.sendError(MVCorei18n.CLONE_FAILED);
return;
}
issuer.sendInfo(MVCorei18n.CLONE_SUCCESS,
"{world}", newWorldName);
}
}
@@ -1,143 +0,0 @@
package com.onarandombox.MultiverseCore.commands;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Conditions;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper;
import jakarta.inject.Inject;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldType;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class CreateCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public CreateCommand(
@NotNull MVCommandManager commandManager,
@NotNull MVWorldManager worldManager,
@NotNull UnsafeCallWrapper unsafeCallWrapper
) {
super(commandManager);
this.worldManager = worldManager;
registerFlagGroup(CommandFlagGroup.builder("mvcreate")
.add(CommandValueFlag.builder("--seed", String.class)
.addAlias("-s")
.completion(() -> Collections.singleton(String.valueOf(new Random().nextLong())))
.build())
.add(CommandValueFlag.builder("--generator", String.class)
.addAlias("-g")
.completion(() -> Arrays.stream(Bukkit.getServer().getPluginManager().getPlugins())
.filter(Plugin::isEnabled)
.filter(genplugin -> unsafeCallWrapper.wrap(
() -> genplugin.getDefaultWorldGenerator("world", ""),
genplugin.getName(),
"Get generator"
) != null)
.map(genplugin -> genplugin.getDescription().getName())
.collect(Collectors.toList()))
.build())
.add(CommandValueFlag.builder("--world-type", WorldType.class)
.addAlias("-t")
.context((value) -> {
try {
return WorldType.valueOf(value.toUpperCase());
} catch (IllegalArgumentException e) {
throw new InvalidCommandArgument("Invalid world type: " + value);
}
})
.completion(() -> {
List<String> types = new ArrayList<>();
for (WorldType type : WorldType.values()) {
types.add(type.name().toLowerCase());
}
return types;
})
.build())
.add(CommandFlag.builder("--adjust-spawn")
.addAlias("-n")
.build())
.add(CommandFlag.builder("--no-structures")
.addAlias("-a")
.build())
.build());
}
@Subcommand("create")
@CommandPermission("multiverse.core.create")
@CommandCompletion("@empty @flags:groupName=mvcreate")
@Syntax("<name> <environment> --seed [seed] --generator [generator[:id]] --world-type [worldtype] --adjust-spawn --no-structures")
@Description("{@@mv-core.create.description}")
public void onCreateCommand(BukkitCommandIssuer issuer,
@Conditions("validWorldName:scope=new")
@Syntax("<name>")
@Description("{@@mv-core.create.name.description}")
String worldName,
@Syntax("<environment>")
@Description("{@@mv-core.create.environment.description}")
World.Environment environment,
@Optional
@Syntax("--seed [seed] --generator [generator[:id]] --world-type [worldtype] --adjust-spawn --no-structures")
@Description("{@@mv-core.create.flags.description}")
String[] flags
) {
ParsedCommandFlags parsedFlags = parseFlags(flags);
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES, "{worldName}", worldName);
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_ENVIRONMENT, "{environment}", environment.name());
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_SEED, "{seed}", parsedFlags.flagValue("--seed", "RANDOM", String.class));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_WORLDTYPE, "{worldType}", parsedFlags.flagValue("--world-type", WorldType.NORMAL, WorldType.class).name());
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_ADJUSTSPAWN, "{adjustSpawn}", String.valueOf(parsedFlags.hasFlag("--adjust-spawn")));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_GENERATOR, "{generator}", parsedFlags.flagValue("--generator", "null", String.class));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_STRUCTURES, "{structures}", String.valueOf(!parsedFlags.hasFlag("--no-structures")));
issuer.sendInfo(MVCorei18n.CREATE_LOADING);
if (!worldManager.addWorld(
worldName,
environment,
parsedFlags.flagValue("--seed", String.class),
parsedFlags.flagValue("--world-type", WorldType.NORMAL, WorldType.class),
parsedFlags.hasFlag("--adjust-spawn"),
parsedFlags.flagValue("--generator", String.class),
parsedFlags.hasFlag("--no-structures")
)) {
issuer.sendError(MVCorei18n.CREATE_FAILED, "{worldName}", worldName);
return;
}
issuer.sendInfo(MVCorei18n.CREATE_SUCCESS, "{worldName}", worldName);
}
}
@@ -1,67 +0,0 @@
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.MessageType;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Conditions;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class DeleteCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public DeleteCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@Subcommand("delete")
@CommandPermission("multiverse.core.delete")
@CommandCompletion("@mvworlds:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.delete.description}")
public void onDeleteCommand(BukkitCommandIssuer issuer,
@Single
@Conditions("validWorldName:scope=both")
@Syntax("<world>")
@Description("The world you want to delete.")
String worldName
) {
this.commandManager.getCommandQueueManager().addToQueue(new QueuedCommand(
issuer.getIssuer(),
() -> {
issuer.sendInfo(MVCorei18n.DELETE_DELETING,
"{world}", worldName);
if (!this.worldManager.deleteWorld(worldName)) {
issuer.sendError(MVCorei18n.DELETE_FAILED,
"{world}", worldName);
return;
}
issuer.sendInfo(MVCorei18n.DELETE_SUCCESS,
"{world}", worldName);
},
this.commandManager.formatMessage(
issuer,
MessageType.INFO,
MVCorei18n.DELETE_PROMPT,
"{world}", worldName)
));
}
}
@@ -1,79 +0,0 @@
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Flags;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.context.GameRuleValue;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.bukkit.GameRule;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class GameruleCommand extends MultiverseCommand {
@Inject
public GameruleCommand(@NotNull MVCommandManager commandManager) {
super(commandManager);
}
@Subcommand("gamerule")
@CommandPermission("multiverse.core.gamerule")
@CommandCompletion("@gamerules true|false|@range:1-10 @mvworlds:multiple|*")
@Syntax("<Gamerule> <Gamerule value> [World or *]")
@Description("{@@mv-core.gamerule.description}")
public void onGameruleCommand(BukkitCommandIssuer issuer,
@Syntax("<Gamerule>")
@Description("{@@mv-core.gamerule.gamerule.description}")
GameRule gamerule,
@Syntax("<Value>")
@Description("{@@mv-core.gamerule.value.description}")
GameRuleValue gameRuleValue,
@Flags("resolve=issuerAware")
@Syntax("[World or *]")
@Description("{@@mv-core.gamerule.world.description}")
MVWorld[] worlds
) {
Object value = gameRuleValue.getValue();
boolean success = true;
for(MVWorld world : worlds) {
// Set gamerules and add false to list if it fails
if (!world.getCBWorld().setGameRule(gamerule, value)) {
issuer.sendError(MVCorei18n.GAMERULE_FAILED,
"{gamerule}", gamerule.getName(),
"{value}", value.toString(),
"{world}", world.getName(),
"{type}", gamerule.getType().getName());
success = false;
}
}
// Tell user if it was successful
if (success) {
if (worlds.length == 1) {
issuer.sendInfo(MVCorei18n.GAMERULE_SUCCESS_SINGLE,
"{gamerule}", gamerule.getName(),
"{value}", value.toString(),
"{world}", worlds[0].getName());
}
else if (worlds.length > 1) {
issuer.sendInfo(MVCorei18n.GAMERULE_SUCCESS_MULTIPLE,
"{gamerule}", gamerule.getName(),
"{value}", value.toString(),
"{count}", String.valueOf(worlds.length));
}
}
}
}
@@ -1,104 +0,0 @@
package com.onarandombox.MultiverseCore.commands;
import java.util.Arrays;
import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Conditions;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper;
import jakarta.inject.Inject;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class ImportCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public ImportCommand(
@NotNull MVCommandManager commandManager,
@NotNull MVWorldManager worldManager,
@NotNull UnsafeCallWrapper unsafeCallWrapper
) {
super(commandManager);
this.worldManager = worldManager;
registerFlagGroup(CommandFlagGroup.builder("mvimport")
.add(CommandValueFlag.builder("--generator", String.class)
.addAlias("-g")
.completion(() -> Arrays.stream(Bukkit.getServer().getPluginManager().getPlugins())
.filter(Plugin::isEnabled)
.filter(genplugin -> unsafeCallWrapper.wrap(
() -> genplugin.getDefaultWorldGenerator("world", ""),
genplugin.getName(),
"Get generator"
) != null)
.map(genplugin -> genplugin.getDescription().getName())
.collect(Collectors.toList()))
.build())
.add(CommandFlag.builder("--adjust-spawn")
.addAlias("-a")
.build())
.build());
}
@Subcommand("import")
@CommandPermission("multiverse.core.import")
@CommandCompletion("@mvworlds:scope=potential @flags:groupName=mvimport")
@Syntax("<name> <env> --generator [generator[:id]] --adjust-spawn")
@Description("{@@mv-core.import.description")
public void onImportCommand(BukkitCommandIssuer issuer,
@Conditions("validWorldName:scope=new")
@Syntax("<name>")
@Description("{@@mv-core.import.name.description}")
String worldName,
@Syntax("<env>")
@Description("{@@mv-core.import.env.description}")
World.Environment environment,
@Optional
@Syntax("--generator [generator[:id]] --adjust-spawn")
@Description("{@@mv-core.import.other.description}")
String[] flags) {
ParsedCommandFlags parsedFlags = parseFlags(flags);
issuer.sendInfo(MVCorei18n.IMPORT_IMPORTING,
"{world}", worldName);
if (!this.worldManager.addWorld(
worldName, environment,
null,
null,
null,
parsedFlags.flagValue("--generator", String.class),
parsedFlags.hasFlag("--adjust-spawn"))
) {
issuer.sendError(MVCorei18n.IMPORT_FAILED);
return;
}
issuer.sendInfo(MVCorei18n.IMPORT_SUCCESS);
}
}
@@ -1,56 +0,0 @@
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Conditions;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class LoadCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public LoadCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@Subcommand("load")
@CommandPermission("multiverse.core.load")
@CommandCompletion("@mvworlds:scope=unloaded")
@Syntax("<world>")
@Description("{@@mv-core.load.description}")
public void onLoadCommand(BukkitCommandIssuer issuer,
@Single
@Conditions("validWorldName:scope=unloaded")
@Syntax("<world>")
@Description("{@@mv-core.load.world.description}")
String worldName
) {
issuer.sendInfo(MVCorei18n.LOAD_LOADING,
"{world}", worldName);
if (!this.worldManager.loadWorld(worldName)) {
issuer.sendError(MVCorei18n.LOAD_FAILED,
"{world}", worldName);
return;
}
issuer.sendInfo(MVCorei18n.LOAD_SUCCESS,
"{world}", worldName);
}
}
@@ -1,97 +0,0 @@
package com.onarandombox.MultiverseCore.commands;
import java.util.Collections;
import java.util.Random;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.MessageType;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Conditions;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class RegenCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public RegenCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
registerFlagGroup(CommandFlagGroup.builder("mvregen")
.add(CommandValueFlag.builder("--seed", String.class)
.addAlias("-s")
.completion(() -> Collections.singleton(String.valueOf(new Random().nextLong())))
.optional()
.build())
.add(CommandFlag.builder("--keep-gamerules")
.addAlias("-k")
.build())
.build());
}
@Subcommand("regen")
@CommandPermission("multiverse.core.regen")
@CommandCompletion("@mvworlds:scope=both @flags:groupName=mvregen")
@Syntax("<world> --seed [seed] --keep-gamerules")
@Description("{@@mv-core.regen.description}")
public void onRegenCommand(BukkitCommandIssuer issuer,
@Conditions("validWorldName:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.regen.world.description}")
String worldName,
@Optional
@Syntax("--seed [seed] --keep-gamerules")
@Description("{@@mv-core.regen.other.description}")
String[] flags
) {
ParsedCommandFlags parsedFlags = parseFlags(flags);
this.commandManager.getCommandQueueManager().addToQueue(new QueuedCommand(
issuer.getIssuer(),
() -> {
issuer.sendInfo(MVCorei18n.REGEN_REGENERATING,
"{world}", worldName);
if (!this.worldManager.regenWorld(
worldName,
parsedFlags.hasFlag("--seed"),
!parsedFlags.hasFlagValue("--seed"),
parsedFlags.flagValue("--seed", String.class),
parsedFlags.hasFlag("--keep-gamerules")
)) {
issuer.sendError(MVCorei18n.REGEN_FAILED,
"{world}", worldName);
return;
}
issuer.sendInfo(MVCorei18n.REGEN_SUCCESS,
"{world}", worldName);
},
this.commandManager.formatMessage(
issuer,
MessageType.INFO,
MVCorei18n.REGEN_PROMPT,
"{world}", worldName)
));
}
}
@@ -1,52 +0,0 @@
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Conditions;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class RemoveCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public RemoveCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@Subcommand("remove")
@CommandPermission("multiverse.core.remove")
@CommandCompletion("@mvworlds:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.remove.description}")
public void onRemoveCommand(BukkitCommandIssuer issuer,
@Single
@Conditions("mvworlds:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.remove.world.description}")
String worldName
) {
if (!this.worldManager.removeWorldFromConfig(worldName)) {
issuer.sendError(MVCorei18n.REMOVE_FAILED);
return;
}
issuer.sendInfo(MVCorei18n.REMOVE_SUCCESS,
"{world}", worldName);
}
}
@@ -1,69 +0,0 @@
package com.onarandombox.MultiverseCore.commands;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.CommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Flags;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.bukkit.entity.Player;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class TeleportCommand extends MultiverseCommand {
private final DestinationsProvider destinationsProvider;
@Inject
public TeleportCommand(MVCommandManager commandManager, DestinationsProvider destinationsProvider) {
super(commandManager);
this.destinationsProvider = destinationsProvider;
}
@Subcommand("teleport|tp")
@CommandCompletion("@players|@mvworlds:playerOnly|@destinations:playerOnly @mvworlds|@destinations")
@Syntax("[player] <destination>")
@Description("{@@mv-core.teleport.description}")
public void onTeleportCommand(BukkitCommandIssuer issuer,
@Flags("resolve=issuerAware")
@Syntax("[player]")
@Description("{@@mv-core.teleport.player.description}")
Player[] players,
@Syntax("<destination>")
@Description("{@@mv-core.teleport.destination.description}")
ParsedDestination<?> destination
) {
// TODO Add warning if teleporting too many players at once.
CompletableFuture.allOf(Arrays.stream(players)
.map(player -> this.destinationsProvider.playerTeleportAsync(issuer, player, destination))
.toArray(CompletableFuture[]::new))
.thenRun(() -> {
String playerName = players.length == 1
? issuer.getPlayer() == players[0] ? "you" : players[0].getName()
: players.length + " players";
issuer.sendInfo(MVCorei18n.TELEPORT_SUCCESS,
"{player}", playerName, "{destination}", destination.toString());
});
}
@Override
public boolean hasPermission(CommandIssuer issuer) {
return this.destinationsProvider.hasAnyTeleportPermission(issuer);
}
}
@@ -1,54 +0,0 @@
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class UnloadCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public UnloadCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@Subcommand("unload")
@CommandPermission("multiverse.core.unload")
@CommandCompletion("@mvworlds")
@Syntax("<world>")
@Description("{@@mv-core.unload.description}")
public void onUnloadCommand(BukkitCommandIssuer issuer,
@Syntax("<world>")
@Description("{@@mv-core.unload.world.description}")
MVWorld world
) {
issuer.sendInfo(MVCorei18n.UNLOAD_UNLOADING,
"{world}", world.getColoredWorldString());
//TODO API: Should be able to use MVWorld object directly
if (!this.worldManager.unloadWorld(world.getName())) {
issuer.sendError(MVCorei18n.UNLOAD_FAILURE,
"{world}", world.getColoredWorldString());
return;
}
issuer.sendInfo(MVCorei18n.UNLOAD_SUCCESS,
"{world}", world.getColoredWorldString());
}
}
@@ -1,146 +0,0 @@
package com.onarandombox.MultiverseCore.commandtools;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandCompletionContext;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.CommandIssuer;
import co.aikar.commands.PaperCommandCompletions;
import co.aikar.commands.RegisteredCommand;
import co.aikar.commands.RootCommand;
import com.google.common.collect.Sets;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import jakarta.inject.Inject;
import org.bukkit.GameRule;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
public class MVCommandCompletions extends PaperCommandCompletions {
protected final MVCommandManager commandManager;
private final MVWorldManager worldManager;
private final DestinationsProvider destinationsProvider;
@Inject
public MVCommandCompletions(
@NotNull MVCommandManager mvCommandManager,
@NotNull MVWorldManager worldManager,
@NotNull DestinationsProvider destinationsProvider,
@NotNull MVCoreConfig config
) {
super(mvCommandManager);
this.commandManager = mvCommandManager;
this.worldManager = worldManager;
this.destinationsProvider = destinationsProvider;
registerAsyncCompletion("commands", this::suggestCommands);
registerAsyncCompletion("destinations", this::suggestDestinations);
registerAsyncCompletion("flags", this::suggestFlags);
registerStaticCompletion("gamerules", this::suggestGamerules);
registerStaticCompletion("mvconfigs", config.getNodes().getNames());
registerAsyncCompletion("mvworlds", this::suggestMVWorlds);
setDefaultCompletion("destinations", ParsedDestination.class);
setDefaultCompletion("flags", String[].class);
setDefaultCompletion("gamerules", GameRule.class);
setDefaultCompletion("mvworlds", MVWorld.class);
}
private Collection<String> suggestCommands(BukkitCommandCompletionContext context) {
String rootCmdName = context.getConfig();
if (rootCmdName == null) {
return Collections.emptyList();
}
RootCommand rootCommand = this.commandManager.getRegisteredRootCommands().stream()
.unordered()
.filter(c -> c.getCommandName().equals(rootCmdName))
.findFirst()
.orElse(null);
if (rootCommand == null) {
return Collections.emptyList();
}
return rootCommand.getSubCommands().entries().stream()
.filter(entry -> checkPerms(context.getIssuer(), entry.getValue()))
.map(Map.Entry::getKey)
.filter(cmdName -> !cmdName.startsWith("__"))
.collect(Collectors.toList());
}
private boolean checkPerms(CommandIssuer issuer, RegisteredCommand<?> command) {
return this.commandManager.hasPermission(issuer, command.getRequiredPermissions());
}
private Collection<String> suggestDestinations(BukkitCommandCompletionContext context) {
if (context.hasConfig("playerOnly") && !context.getIssuer().isPlayer()) {
return Collections.emptyList();
}
return this.destinationsProvider
.suggestDestinations((BukkitCommandIssuer)context.getIssuer(), context.getInput());
}
private Collection<String> suggestFlags(@NotNull BukkitCommandCompletionContext context) {
return this.commandManager.getFlagsManager().suggest(
context.getConfig("groupName", ""), context.getContextValue(String[].class));
}
private Collection<String> suggestGamerules() {
return Arrays.stream(GameRule.values()).map(GameRule::getName).collect(Collectors.toList());
}
private Collection<String> suggestMVWorlds(BukkitCommandCompletionContext context) {
if (context.hasConfig("playerOnly") && !context.getIssuer().isPlayer()) {
return Collections.emptyList();
}
if (!context.hasConfig("multiple")) {
return getMVWorldNames(context);
}
String input = context.getInput();
int lastComma = input.lastIndexOf(',');
String currentWorldsString = input.substring(0, lastComma + 1);
Set<String> currentWorlds = Sets.newHashSet(input.split(","));
return getMVWorldNames(context).stream()
.filter(world -> !currentWorlds.contains(world))
.map(world -> currentWorldsString + world)
.collect(Collectors.toList());
}
private List<String> getMVWorldNames(BukkitCommandCompletionContext context) {
String scope = context.getConfig("scope", "loaded");
List<String> worlds = new ArrayList<>();
switch (scope) {
case "both":
worlds.addAll(worldManager.getUnloadedWorlds());
case "loaded":
worldManager.getMVWorlds()
.stream()
.map(MVWorld::getName)
.forEach(worlds::add);
break;
case "unloaded":
worlds.addAll(worldManager.getUnloadedWorlds());
break;
case "potential":
worlds.addAll(worldManager.getPotentialWorlds());
break;
}
return worlds;
}
}
@@ -1,48 +0,0 @@
package com.onarandombox.MultiverseCore.commandtools;
import co.aikar.commands.MessageType;
import co.aikar.commands.OpenBukkitCommandIssuer;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.utils.message.Message;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class MVCommandIssuer extends OpenBukkitCommandIssuer {
private final MVCommandManager commandManager;
MVCommandIssuer(@NotNull MVCommandManager commandManager, @NotNull CommandSender sender) {
super(commandManager, sender);
this.commandManager = commandManager;
}
@Override
public MVCommandManager getManager() {
return commandManager;
}
public void sendError(Message message) {
sendMessage(MessageType.ERROR, message);
}
public void sendSyntax(Message message) {
sendMessage(MessageType.SYNTAX, message);
}
public void sendInfo(Message message) {
sendMessage(MessageType.INFO, message);
}
private void sendMessage(MessageType messageType, Message message) {
if (message instanceof MessageKeyProvider) {
sendMessage(messageType, (MessageKeyProvider) message, message.getReplacements());
} else {
var formatter = getManager().getFormat(messageType);
if (formatter != null) {
sendMessage(formatter.format(message.formatted()));
} else {
sendMessage(message.formatted());
}
}
}
}
@@ -1,35 +0,0 @@
package com.onarandombox.MultiverseCore.commandtools;
import co.aikar.commands.BaseCommand;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagsManager;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Contract;
@Contract
public abstract class MultiverseCommand extends BaseCommand {
protected final MVCommandManager commandManager;
private String flagGroupName;
protected MultiverseCommand(@NotNull MVCommandManager commandManager) {
this.commandManager = commandManager;
}
protected CommandFlagsManager getFlagsManager() {
return commandManager.getFlagsManager();
}
protected void registerFlagGroup(@NotNull CommandFlagGroup flagGroup) {
if (flagGroupName != null) {
throw new IllegalStateException("Flag group already registered! (name: " + flagGroupName + ")");
}
getFlagsManager().registerFlagGroup(flagGroup);
flagGroupName = flagGroup.getName();
}
protected @NotNull ParsedCommandFlags parseFlags(@NotNull String[] flags) {
return getFlagsManager().parse(flagGroupName, flags);
}
}
@@ -1,13 +0,0 @@
package com.onarandombox.MultiverseCore.commandtools.context;
public class MVConfigValue {
private final Object value;
public MVConfigValue(Object value) {
this.value = value;
}
public Object getValue() {
return value;
}
}
@@ -1,172 +0,0 @@
package com.onarandombox.MultiverseCore.commandtools.flags;
import java.util.Collection;
import java.util.function.Function;
import java.util.function.Supplier;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents a flag with a value.
*
* @param <T> The type of the value.
*/
public class CommandValueFlag<T> extends CommandFlag {
/**
* A builder for a flag.
*
* @param key The key for the new flag.
* @param type The type of the value.
* @return The builder.
*/
public static @NotNull <T> Builder<T, ?> builder(@NotNull String key, @NotNull Class<T> type) {
return new Builder<>(key, type);
}
private final Class<T> type;
private final boolean optional;
private final T defaultValue;
private final Function<String, T> context;
private final Supplier<Collection<String>> completion;
/**
* Creates a new flag.
*
* @param builder The builder.
*/
protected CommandValueFlag(@NotNull Builder<T, ?> builder) {
super(builder);
type = builder.type;
optional = builder.optional;
defaultValue = builder.defaultValue;
context = builder.context;
completion = builder.completion;
}
/**
* Get the type of the value.
*
* @return The type of the value.
*/
public @NotNull Class<T> getType() {
return type;
}
/**
* Check if it is optional for users to specify a value.
*
* @return True if the value is optional, false otherwise.
*/
public boolean isOptional() {
return optional;
}
/**
* Get the default value. May be null.
*
* @return The default value.
*/
public @Nullable T getDefaultValue() {
return defaultValue;
}
/**
* Get the context. May be null for {@link String} value type.
*
* @return The context.
*/
public @Nullable Function<String, T> getContext() {
return context;
}
/**
* Get the completion. May be null.
*
* @return The completion.
*/
public @Nullable Supplier<Collection<String>> getCompletion() {
return completion;
}
/**
* A builder for a flag.
*
* @param <T> The type of the value.
* @param <S> The type of the builder.
*/
public static class Builder<T, S extends Builder<T, S>> extends CommandFlag.Builder<S> {
private final Class<T> type;
private boolean optional = false;
private T defaultValue = null;
private Function<String, T> context = null;
private Supplier<Collection<String>> completion = null;
/**
* Create a new builder.
*
* @param key The key for the new flag.
* @param type The type of the value.
*/
public Builder(@NotNull String key, @NotNull Class<T> type) {
super(key);
this.type = type;
}
/**
* Set the flag as optional for users to specify a value.
*
* @return The builder.
*/
public @NotNull S optional() {
this.optional = true;
return (S) this;
}
/**
* Set the default value. Used if optional is true and user does not specify a value.
*
* @param defaultValue The default value.
* @return The builder.
*/
public @NotNull S defaultValue(@NotNull T defaultValue) {
this.defaultValue = defaultValue;
return (S) this;
}
/**
* Set the context callback for parsing string into value type.
*
* @param context The context.
* @return The builder.
*/
public @NotNull S context(@NotNull Function<String, T> context) {
this.context = context;
return (S) this;
}
/**
* Set the completion callback for autocomplete.
*
* @param completion The completion.
* @return The builder.
*/
public @NotNull S completion(@NotNull Supplier<Collection<String>> completion) {
this.completion = completion;
return (S) this;
}
/**
* Build the flag.
*
* @return The flag.
*/
@Override
public @NotNull CommandFlag build() {
if (context == null && !String.class.equals(type)) {
throw new IllegalStateException("Context is required for none-string value flags");
}
return new CommandValueFlag<>(this);
}
}
}
@@ -1,61 +0,0 @@
package com.onarandombox.MultiverseCore.commandtools.flags;
import java.util.HashMap;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Object to contain the results of the flags present and its values.
*/
public class ParsedCommandFlags
{
public static final ParsedCommandFlags EMPTY = new ParsedCommandFlags();
private final Map<String, Object> flagValues;
public ParsedCommandFlags() {
flagValues = new HashMap<>();
}
/**
* Add a flag result to the parsed flags.
*
* @param key The key of the flag.
* @param value The value of the flag.
*/
void addFlagResult(@NotNull String key, @Nullable Object value) {
flagValues.put(key, value);
}
/**
* Check if a flag is present.
*
* @param key The key of the flag.
* @return True if the flag is present, false otherwise.
*/
public boolean hasFlag(@Nullable String key) {
return this.flagValues.containsKey(key);
}
public boolean hasFlagValue(@Nullable String key) {
return flagValue(key, Object.class) != null;
}
/**
* Get the value of a flag.
*
* @param key The key of the flag.
* @return The value of the flag, null if flag does not exist or no value.
*/
public @Nullable <T> T flagValue(@Nullable String key, @NotNull Class<T> type) {
Object value = this.flagValues.get(key);
return (T) value;
}
public @NotNull <T> T flagValue(@Nullable String key, @NotNull T defaultValue, @NotNull Class<T> type) {
T value = flagValue(key, type);
return value != null ? value : defaultValue;
}
}
@@ -1,47 +0,0 @@
package com.onarandombox.MultiverseCore.configuration.handle;
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.logging.Logger;
/**
* Configuration handle for a single configuration section.
*/
public class ConfigurationSectionHandle extends GenericConfigHandle<ConfigurationSection> {
public static Builder<? extends Builder> builder(@NotNull ConfigurationSection configurationSection) {
return new Builder<>(configurationSection);
}
public ConfigurationSectionHandle(@NotNull ConfigurationSection configurationSection,
@Nullable Logger logger,
@Nullable NodeGroup nodes,
@Nullable ConfigMigrator migrator) {
super(logger, nodes, migrator);
this.config = configurationSection;
}
/**
* Builder for {@link ConfigurationSectionHandle}.
*
* @param <B> The builder type.
*/
public static class Builder<B extends Builder<B>> extends GenericConfigHandle.Builder<ConfigurationSection, B> {
private final ConfigurationSection configurationSection;
protected Builder(@NotNull ConfigurationSection configurationSection) {
this.configurationSection = configurationSection;
}
/**
* {@inheritDoc}
*/
@Override
public @NotNull ConfigurationSectionHandle build() {
return new ConfigurationSectionHandle(configurationSection, logger, nodes, migrator);
}
}
}
@@ -1,130 +0,0 @@
package com.onarandombox.MultiverseCore.configuration.handle;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.logging.Logger;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Generic configuration handle for file based configurations.
* @param <C> The configuration type.
*/
abstract class FileConfigHandle<C extends FileConfiguration> extends GenericConfigHandle<C> {
protected final @NotNull Path configPath;
protected final @NotNull File configFile;
protected FileConfigHandle(@NotNull Path configPath, @Nullable Logger logger, @Nullable NodeGroup nodes, @Nullable ConfigMigrator migrator) {
super(logger, nodes, migrator);
this.configPath = configPath;
this.configFile = configPath.toFile();
}
/**
* {@inheritDoc}
*/
@Override
public boolean load() {
if (!createConfigFile()) {
Logging.severe("Failed to create config file: %s", configFile.getName());
return false;
}
if (!loadConfigObject()) {
Logging.severe("Failed to load config file: %s", configFile.getName());
return false;
}
migrateConfig();
setUpNodes();
return true;
}
/**
* Create a new config file if file does not exist
*
* @return True if file exist or created successfully, otherwise false.
*/
protected boolean createConfigFile() {
if (configFile.exists()) {
return true;
}
try {
if (!configFile.createNewFile()) {
return false;
}
Logging.info("Created new config file: %s", configFile.getName());
} catch (IOException e) {
return false;
}
return true;
}
/**
* Loads the configuration object.
*
* @return True if the configuration was loaded successfully, false otherwise.
*/
protected abstract boolean loadConfigObject();
/**
* Saves the configuration.
*/
public abstract boolean save();
/**
* Checks if the configuration is loaded.
*
* @return True if the configuration is loaded, false otherwise.
*/
public boolean isLoaded() {
return config != null;
}
/**
* Gets the configuration.
*
* @return The configuration.
*/
public C getConfig() {
return config;
}
/**
* Abstract builder for {@link FileConfigHandle}.
*
* @param <C> The configuration type.
* @param <B> The builder type.
*/
public static abstract class Builder<C extends FileConfiguration, B extends Builder<C, B>> extends GenericConfigHandle.Builder<C, B> {
protected @NotNull Path configPath;
protected @Nullable Logger logger;
protected @Nullable NodeGroup nodes;
protected @Nullable ConfigMigrator migrator;
protected Builder(@NotNull Path configPath) {
this.configPath = configPath;
}
/**
* Builds the configuration handle.
*
* @return The configuration handle.
*/
public abstract @NotNull FileConfigHandle<C> build();
@SuppressWarnings("unchecked")
protected B self() {
return (B) this;
}
}
}
@@ -1,196 +0,0 @@
package com.onarandombox.MultiverseCore.configuration.handle;
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
import com.onarandombox.MultiverseCore.configuration.node.ConfigNodeNotFoundException;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
import io.vavr.control.Try;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.logging.Logger;
/**
* Generic configuration handle for all ConfigurationSection types.
*/
public abstract class GenericConfigHandle<C extends ConfigurationSection> {
protected final @Nullable Logger logger;
protected final @Nullable NodeGroup nodes;
protected final @Nullable ConfigMigrator migrator;
protected C config;
public GenericConfigHandle(@Nullable Logger logger, @Nullable NodeGroup nodes, @Nullable ConfigMigrator migrator) {
this.logger = logger;
this.nodes = nodes;
this.migrator = migrator;
}
/**
* Loads the configuration.
*
* @return True if the configuration was loaded successfully, false otherwise.
*/
public boolean load() {
migrateConfig();
setUpNodes();
return true;
}
/**
* Migrates the configuration.
*/
protected void migrateConfig() {
if (migrator != null) {
migrator.migrate(config);
}
}
/**
* Sets up the nodes.
*/
protected void setUpNodes() {
if (nodes == null || nodes.isEmpty()) {
return;
}
nodes.forEach(node -> {
if (node instanceof ValueNode valueNode) {
set(valueNode, config.getObject(valueNode.getPath(), valueNode.getType(), valueNode.getDefaultValue()));
}
});
}
/**
* Gets the value of a node, if the node has a default value, it will be returned if the node is not found.
* @param name The name of the node.
* @return The value of the node.
*/
public Try<Object> get(@Nullable String name) {
return nodes.findNode(name, ValueNode.class)
.toTry(() -> new ConfigNodeNotFoundException(name))
.map(node -> get((ValueNode<Object>) node));
}
/**
* Gets the value of a node, if the node has a default value, it will be returned if the node is not found.
*
* @param node The node to get the value of.
* @return The value of the node.
*/
public <T> T get(@NotNull ValueNode<T> node) {
return config.getObject(node.getPath(), node.getType(), node.getDefaultValue());
}
/**
* Sets the value of a node, if the validator is not null, it will be tested first.
*
* @param name The name of the node.
* @param value The value to set.
* @return True if the value was set, false otherwise.
*/
public Try<Void> set(@Nullable String name, Object value) {
return nodes.findNode(name, ValueNode.class)
.toTry(() -> new ConfigNodeNotFoundException(name))
.flatMap(node -> set(node, value));
}
/**
* Sets the value of a node, if the validator is not null, it will be tested first.
*
* @param node The node to set the value of.
* @param value The value to set.
* @return True if the value was set, false otherwise.
* @param <T> The type of the node value.
*/
public <T> Try<Void> set(@NotNull ValueNode<T> node, T value) {
return node.validate(value).map(ignore -> {
T oldValue = get(node);
config.set(node.getPath(), value);
node.onSetValue(oldValue, get(node));
return null;
});
}
/**
* Sets the default value of a node.
*
* @param node The node to set the default value of.
*/
public void setDefault(@NotNull ValueNode node) {
config.set(node.getPath(), node.getDefaultValue());
}
/**
* Abstract builder for {@link GenericConfigHandle}.
*
* @param <C> The configuration type.
* @param <B> The builder type.
*/
public static abstract class Builder<C extends ConfigurationSection, B extends GenericConfigHandle.Builder<C, B>> {
protected @Nullable Logger logger;
protected @Nullable NodeGroup nodes;
protected @Nullable ConfigMigrator migrator;
protected Builder() {}
/**
* Sets the logger.
*
* @param logger The logger.
* @return The builder.
*/
public B logger(@Nullable Logger logger) {
this.logger = logger;
return self();
}
/**
* Sets the logger.
*
* @param plugin The plugin to get the logger from.
* @return The builder.
*/
public B logger(Plugin plugin) {
this.logger = plugin.getLogger();
return self();
}
/**
* Sets the nodes.
*
* @param nodes The nodes.
* @return The builder.
*/
public B nodes(@Nullable NodeGroup nodes) {
this.nodes = nodes;
return self();
}
/**
* Sets the migrator.
*
* @param migrator The migrator.
* @return The builder.
*/
public B migrator(@Nullable ConfigMigrator migrator) {
this.migrator = migrator;
return self();
}
/**
* Builds the configuration handle.
*
* @return The configuration handle.
*/
public abstract @NotNull GenericConfigHandle<C> build();
@SuppressWarnings("unchecked")
protected B self() {
return (B) this;
}
}
}
@@ -1,172 +0,0 @@
package com.onarandombox.MultiverseCore.configuration.node;
import java.util.function.BiConsumer;
import java.util.function.Function;
import io.vavr.control.Option;
import io.vavr.control.Try;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A node that contains a value.
* @param <T> The type of the value.
*/
public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
/**
* Creates a new builder for a {@link ConfigNode}.
*
* @param path The path of the node.
* @param type The type of the value.
* @return The new builder.
* @param <T> The type of the value.
*/
public static @NotNull <T> ConfigNode.Builder<T, ? extends ConfigNode.Builder<T, ?>> builder(
@NotNull String path,
@NotNull Class<T> type
) {
return new ConfigNode.Builder<>(path, type);
}
protected final @Nullable String name;
protected final @NotNull Class<T> type;
protected final @Nullable T defaultValue;
protected final @Nullable Function<T, Try<Void>> validator;
protected final @Nullable BiConsumer<T, T> onSetValue;
protected ConfigNode(
@NotNull String path,
@NotNull String[] comments,
@Nullable String name,
@NotNull Class<T> type,
@Nullable T defaultValue,
@Nullable Function<T, Try<Void>> validator,
@Nullable BiConsumer<T, T> onSetValue
) {
super(path, comments);
this.name = name;
this.type = type;
this.defaultValue = defaultValue;
this.validator = validator;
this.onSetValue = onSetValue;
}
/**
* {@inheritDoc}
*/
@Override
public @NotNull Option<String> getName() {
return Option.of(name);
}
/**
* {@inheritDoc}
*/
@Override
public @NotNull Class<T> getType() {
return type;
}
/**
* {@inheritDoc}
*/
@Override
public @Nullable T getDefaultValue() {
return defaultValue;
}
/**
* {@inheritDoc}
*/
@Override
public Try<Void> validate(@Nullable T value) {
if (validator != null) {
return validator.apply(value);
}
return Try.success(null);
}
/**
* {@inheritDoc}
*/
@Override
public void onSetValue(@Nullable T oldValue, @Nullable T newValue) {
if (onSetValue != null) {
onSetValue.accept(oldValue, newValue);
}
}
/**
* Builder for {@link ConfigNode}.
*
* @param <T> The type of the value.
* @param <B> The type of the builder.
*/
public static class Builder<T, B extends ConfigNode.Builder<T, B>> extends ConfigHeaderNode.Builder<B> {
protected @Nullable String name;
protected @NotNull final Class<T> type;
protected @Nullable T defaultValue;
protected @Nullable Function<T, Try<Void>> validator;
protected @Nullable BiConsumer<T, T> onSetValue;
/**
* Creates a new builder.
*
* @param path The path of the node.
* @param type The type of the value.
*/
protected Builder(@NotNull String path, @NotNull Class<T> type) {
super(path);
this.name = path;
this.type = type;
}
/**
* Sets the default value for this node.
*
* @param defaultValue The default value.
* @return This builder.
*/
public @NotNull B defaultValue(@NotNull T defaultValue) {
this.defaultValue = defaultValue;
return (B) this;
}
/**
* Sets the name of this node. Used for identifying the node from user input.
*
* @param name The name of this node.
* @return This builder.
*/
public @NotNull B name(@Nullable String name) {
this.name = name;
return (B) this;
}
public @NotNull B validator(@NotNull Function<T, Try<Void>> validator) {
this.validator = validator;
return (B) this;
}
/**
* Sets the action to be performed when the value is set.
*
* @param onSetValue The action to be performed.
* @return This builder.
*/
public @NotNull B onSetValue(@NotNull BiConsumer<T, T> onSetValue) {
this.onSetValue = onSetValue;
return (B) this;
}
/**
* {@inheritDoc}
*/
@Override
public @NotNull ConfigNode<T> build() {
return new ConfigNode<>(path, comments.toArray(new String[0]), name, type, defaultValue, validator, onSetValue);
}
}
}
@@ -1,213 +0,0 @@
package com.onarandombox.MultiverseCore.destination;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.CommandIssuer;
import com.onarandombox.MultiverseCore.api.Destination;
import com.onarandombox.MultiverseCore.api.DestinationInstance;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.api.Teleporter;
import com.onarandombox.MultiverseCore.teleportation.TeleportResult;
import jakarta.inject.Inject;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.PluginManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
/**
* Provides destinations for teleportation.
*/
@Service
public class DestinationsProvider {
private static final String SEPARATOR = ":";
private static final String PERMISSION_PREFIX = "multiverse.teleport.";
private final PluginManager pluginManager;
private final SafeTTeleporter safeTTeleporter;
private final Map<String, Destination<?>> destinationMap;
/**
* Creates a new destinations provider.
*/
@Inject
public DestinationsProvider(@NotNull PluginManager pluginManager, @NotNull SafeTTeleporter safeTTeleporter) {
this.pluginManager = pluginManager;
this.safeTTeleporter = safeTTeleporter;
this.destinationMap = new HashMap<>();
}
/**
* Adds a destination to the provider.
*
* @param destination The destination.
*/
public void registerDestination(@NotNull Destination<?> destination) {
this.destinationMap.put(destination.getIdentifier(), destination);
this.registerDestinationPerms(destination);
}
private void registerDestinationPerms(@NotNull Destination<?> destination) {
pluginManager.addPermission(new Permission(PERMISSION_PREFIX + "self." + destination.getIdentifier()));
pluginManager.addPermission(new Permission(PERMISSION_PREFIX + "other." + destination.getIdentifier()));
}
/**
* Suggest tab completions for a destination string.
*
* @param issuer The command issuer.
* @param deststring The current destination string.
* @return A collection of tab completions.
*/
public @NotNull Collection<String> suggestDestinations(@NotNull BukkitCommandIssuer issuer,
@Nullable String deststring
) {
return destinationMap.values().stream()
.filter(destination -> issuer.hasPermission(PERMISSION_PREFIX + "self." + destination.getIdentifier())
|| issuer.hasPermission(PERMISSION_PREFIX + "other." + destination.getIdentifier()))
.map(destination -> destination.suggestDestinations(issuer, deststring).stream()
.map(s -> destination.getIdentifier() + SEPARATOR + s)
.collect(Collectors.toList()))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
/**
* Converts a destination string to a destination object.
*
* @param destinationString The destination string.
* @return The destination object, or null if invalid format.
*/
public ParsedDestination<?> parseDestination(String destinationString) {
String[] items = destinationString.split(SEPARATOR, 2);
String idString = items[0];
String destinationParams;
Destination<?> destination;
if (items.length < 2) {
// Assume world destination
destination = this.getDestinationById("w");
destinationParams = items[0];
} else {
destination = this.getDestinationById(idString);
destinationParams = items[1];
}
if (destination == null) {
return null;
}
DestinationInstance destinationInstance = destination.getDestinationInstance(destinationParams);
if (destinationInstance == null) {
return null;
}
return new ParsedDestination<>(destination, destinationInstance);
}
/**
* Gets a destination by its identifier.
*
* @param identifier The identifier.
* @return The destination, or null if not found.
*/
public @Nullable Destination<?> getDestinationById(@Nullable String identifier) {
return this.destinationMap.get(identifier);
}
/**
* Teleports the teleportee to the destination.
*
* @param teleporter The teleporter.
* @param teleportee The teleportee.
* @param destination The destination.
*/
public CompletableFuture<TeleportResult> playerTeleportAsync(@NotNull BukkitCommandIssuer teleporter,
@NotNull Player teleportee,
@NotNull ParsedDestination<?> destination
) {
if (!checkTeleportPermissions(teleporter, teleportee, destination)) {
return CompletableFuture.completedFuture(TeleportResult.FAIL_PERMISSION);
}
return teleportAsync(teleporter, teleportee, destination);
}
/**
* Teleports the teleportee to the destination.
*
* @param teleporter The teleporter.
* @param teleportee The teleportee.
* @param destination The destination.
*/
public CompletableFuture<TeleportResult> teleportAsync(@NotNull BukkitCommandIssuer teleporter,
@NotNull Entity teleportee,
@NotNull ParsedDestination<?> destination
) {
Teleporter teleportHandler = destination.getDestination().getTeleporter();
if (teleportHandler == null) {
teleportHandler = safeTTeleporter;
}
return teleportHandler.teleportAsync(teleporter, teleportee, destination);
}
/**
* Checks if the teleporter has permission to teleport the teleportee to the destination.
*
* @param teleporter The teleporter.
* @param teleportee The teleportee.
* @param destination The destination.
* @return True if the teleporter has permission, false otherwise.
*/
public boolean checkTeleportPermissions(CommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination) {
//TODO Move permission checking to a separate class
String permission = PERMISSION_PREFIX
+ (teleportee.equals(teleporter.getIssuer()) ? "self" : "other") + "."
+ destination.getDestination().getIdentifier();
if (!teleporter.hasPermission(permission)) {
teleporter.sendMessage("You don't have permission to teleport to this destination.");
return false;
}
//TODO Config whether to use finer permission
String finerPermissionSuffix = destination.getDestinationInstance().getFinerPermissionSuffix();
if (finerPermissionSuffix == null || finerPermissionSuffix.isEmpty()) {
return true;
}
String finerPermission = permission + "." + finerPermissionSuffix;
if (!teleporter.hasPermission(finerPermission)) {
teleporter.sendMessage("You don't have permission to teleport to this destination.");
return false;
}
return true;
}
/**
* Checks if the issuer has permission to teleport to at least one destination.
*
* @param issuer The issuer.
* @return True if the issuer has permission, false otherwise.
*/
public boolean hasAnyTeleportPermission(CommandIssuer issuer) {
for (Destination<?> destination : this.destinationMap.values()) {
String permission = PERMISSION_PREFIX + "self." + destination.getIdentifier();
if (issuer.hasPermission(permission)) {
return true;
}
permission = PERMISSION_PREFIX + "other." + destination.getIdentifier();
if (issuer.hasPermission(permission)) {
return true;
}
}
return false;
}
}
@@ -1,4 +0,0 @@
/**
* This package contains all events.
*/
package com.onarandombox.MultiverseCore.event;
@@ -1,4 +0,0 @@
/**
* This package contains all exceptions.
*/
package com.onarandombox.MultiverseCore.exceptions;
@@ -1,70 +0,0 @@
package com.onarandombox.MultiverseCore.listeners;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.inject.InjectableListener;
import jakarta.inject.Inject;
import org.bukkit.ChatColor;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.jvnet.hk2.annotations.Service;
/**
* Multiverse's Listener for players.
*/
@Service
public class MVChatListener implements InjectableListener {
private final MVCoreConfig config;
private final MVWorldManager worldManager;
private final MVPlayerListener playerListener;
@Inject
public MVChatListener(
MVCoreConfig config,
MVWorldManager worldManager,
MVPlayerListener playerListener
) {
this.config = config;
this.worldManager = worldManager;
this.playerListener = playerListener;
}
/**
* This handles a {@link AsyncPlayerChatEvent}.
* @param event The {@link AsyncPlayerChatEvent}.
*/
@EventHandler
public void playerChat(AsyncPlayerChatEvent event) {
if (event.isCancelled()) {
return;
}
// Check whether the Server is set to prefix the chat with the World name.
// If not we do nothing, if so we need to check if the World has an Alias.
if (config.isEnablePrefixChat()) {
String world = playerListener.getPlayerWorld().get(event.getPlayer().getName());
if (world == null) {
world = event.getPlayer().getWorld().getName();
playerListener.getPlayerWorld().put(event.getPlayer().getName(), world);
}
String prefix = "";
// If we're not a MV world, don't do anything
if (!this.worldManager.isMVWorld(world)) {
return;
}
MVWorld mvworld = this.worldManager.getMVWorld(world);
if (mvworld.isHidden()) {
return;
}
prefix = mvworld.getColoredWorldString();
String chat = event.getFormat();
String prefixChatFormat = config.getPrefixChatFormat();
prefixChatFormat = prefixChatFormat.replace("%world%", prefix).replace("%chat%", chat);
prefixChatFormat = ChatColor.translateAlternateColorCodes('&', prefixChatFormat);
event.setFormat(prefixChatFormat);
}
}
}
@@ -1,135 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.listeners;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.WorldPurger;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.inject.InjectableListener;
import jakarta.inject.Inject;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.event.entity.EntityPortalEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
/**
* Multiverse's Entity {@link Listener}.
*/
@Service
public class MVEntityListener implements InjectableListener {
private final MVCoreConfig config;
private final MVWorldManager worldManager;
private final WorldPurger worldPurger;
@Inject
public MVEntityListener(
@NotNull MVCoreConfig config,
@NotNull MVWorldManager worldManager,
@NotNull WorldPurger worldPurger
) {
this.config = config;
this.worldManager = worldManager;
this.worldPurger = worldPurger;
}
/**
* This method is called when an entity's food level goes higher or lower.
* @param event The Event that was fired.
*/
@EventHandler
public void foodLevelChange(FoodLevelChangeEvent event) {
if (event.isCancelled()) {
return;
}
if (event.getEntity() instanceof Player) {
Player p = (Player) event.getEntity();
MVWorld w = this.worldManager.getMVWorld(p.getWorld().getName());
if (w != null && !w.getHunger()) {
// If the world has hunger set to false, do not let the level go down
if (event.getFoodLevel() < ((Player) event.getEntity()).getFoodLevel()) {
event.setCancelled(true);
}
}
}
}
/**
* This method is called when an entity's health goes up or down.
* @param event The Event that was fired.
*/
@EventHandler
public void entityRegainHealth(EntityRegainHealthEvent event) {
if (event.isCancelled()) {
return;
}
RegainReason reason = event.getRegainReason();
MVWorld world = this.worldManager.getMVWorld(event.getEntity().getLocation().getWorld());
if (world != null && reason == RegainReason.REGEN && !world.getAutoHeal()) {
event.setCancelled(true);
}
}
/**
* Handle Animal/Monster Spawn settings, seems like a more concrete method than using CraftBukkit.
* @param event The event.
*/
@EventHandler
public void creatureSpawn(CreatureSpawnEvent event) {
// Check to see if the Creature is spawned by a plugin, we don't want to prevent this behaviour.
// TODO: Allow the egg thing to be a config param. Doubt this will be per world; seems silly.
if (event.getSpawnReason() == SpawnReason.CUSTOM || event.getSpawnReason() == SpawnReason.SPAWNER_EGG
|| event.getSpawnReason() == SpawnReason.BREEDING) {
return;
}
World world = event.getEntity().getWorld();
if (event.isCancelled())
return;
// Check if it's a world which we are meant to be managing.
if (!(this.worldManager.isMVWorld(world.getName())))
return;
EntityType type = event.getEntityType();
/**
* Handle people with non-standard animals: ie a patched craftbukkit.
*/
if (type == null || type.getName() == null) {
Logging.finer("Found a null typed creature.");
return;
}
MVWorld mvworld = this.worldManager.getMVWorld(world.getName());
event.setCancelled(this.worldPurger.shouldWeKillThisCreature(mvworld, event.getEntity()));
}
/**
* Handles portal search radius adjustment.
* @param event The Event that was fired.
*/
@EventHandler
public void entityPortal(EntityPortalEvent event) {
if (event.isCancelled() || event.getTo() == null) {
return;
}
if (!config.isUsingCustomPortalSearch()) {
event.setSearchRadius(config.getCustomPortalSearchRadius());
}
}
}
@@ -1,403 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.listeners;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.event.MVRespawnEvent;
import com.onarandombox.MultiverseCore.inject.InjectableListener;
import com.onarandombox.MultiverseCore.teleportation.TeleportQueue;
import com.onarandombox.MultiverseCore.utils.MVPermissions;
import com.onarandombox.MultiverseCore.utils.PermissionTools;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.plugin.Plugin;
import org.jvnet.hk2.annotations.Service;
/**
* Multiverse's Listener for players.
*/
@Service
public class MVPlayerListener implements InjectableListener {
private final Plugin plugin;
private final MVCoreConfig config;
private final Provider<MVWorldManager> worldManagerProvider;
private final PermissionTools pt;
private final Provider<MVPermissions> mvPermsProvider;
private final SafeTTeleporter safeTTeleporter;
private final Server server;
private final TeleportQueue teleportQueue;
private final Map<String, String> playerWorld = new ConcurrentHashMap<String, String>();
@Inject
public MVPlayerListener(
MultiverseCore plugin,
MVCoreConfig config,
Provider<MVWorldManager> worldManagerProvider,
PermissionTools permissionTools,
Provider<MVPermissions> mvPermsProvider,
SafeTTeleporter safeTTeleporter,
Server server,
TeleportQueue teleportQueue
) {
this.plugin = plugin;
this.config = config;
this.worldManagerProvider = worldManagerProvider;
this.pt = permissionTools;
this.mvPermsProvider = mvPermsProvider;
this.safeTTeleporter = safeTTeleporter;
this.server = server;
this.teleportQueue = teleportQueue;
}
private MVWorldManager getWorldManager() {
return worldManagerProvider.get();
}
private MVPermissions getMVPerms() {
return mvPermsProvider.get();
}
/**
* @return the playerWorld-map
*/
public Map<String, String> getPlayerWorld() {
return playerWorld;
}
/**
* This method is called when a player respawns.
* @param event The Event that was fired.
*/
@EventHandler(priority = EventPriority.LOW)
public void playerRespawn(PlayerRespawnEvent event) {
World world = event.getPlayer().getWorld();
MVWorld mvWorld = getWorldManager().getMVWorld(world.getName());
// If it's not a World MV manages we stop.
if (mvWorld == null) {
return;
}
if (mvWorld.getBedRespawn() && (event.isBedSpawn() || event.isAnchorSpawn())) {
Logging.fine("Spawning %s at their %s.", event.getPlayer().getName(), event.isBedSpawn() ? "BED" : "ANCHOR");
return;
}
// Get the instance of the World the player should respawn at.
MVWorld respawnWorld = null;
if (getWorldManager().isMVWorld(mvWorld.getRespawnToWorld())) {
respawnWorld = getWorldManager().getMVWorld(mvWorld.getRespawnToWorld());
}
// If it's null then it either means the World doesn't exist or the value is blank, so we don't handle it.
// NOW: We'll always handle it to get more accurate spawns
if (respawnWorld != null) {
world = respawnWorld.getCBWorld();
}
// World has been set to the appropriate world
Location respawnLocation = getMostAccurateRespawnLocation(world);
MVRespawnEvent respawnEvent = new MVRespawnEvent(respawnLocation, event.getPlayer(), "compatability");
this.server.getPluginManager().callEvent(respawnEvent);
event.setRespawnLocation(respawnEvent.getPlayersRespawnLocation());
}
private Location getMostAccurateRespawnLocation(World w) {
MVWorld mvw = getWorldManager().getMVWorld(w.getName());
if (mvw != null) {
return mvw.getSpawnLocation();
}
return w.getSpawnLocation();
}
/**
* This method is called when a player joins the server.
* @param event The Event that was fired.
*/
@EventHandler
public void playerJoin(PlayerJoinEvent event) {
Player p = event.getPlayer();
if (!p.hasPlayedBefore()) {
Logging.finer("Player joined for the FIRST time!");
if (config.getFirstSpawnOverride()) {
Logging.fine("Moving NEW player to(firstspawnoverride): "
+ getWorldManager().getFirstSpawnWorld().getSpawnLocation());
this.sendPlayerToDefaultWorld(p);
}
return;
} else {
Logging.finer("Player joined AGAIN!");
if (config.getEnforceAccess() // check this only if we're enforcing access!
&& !this.getMVPerms().hasPermission(p, "multiverse.access." + p.getWorld().getName(), false)) {
p.sendMessage("[MV] - Sorry you can't be in this world anymore!");
this.sendPlayerToDefaultWorld(p);
}
}
// Handle the Players GameMode setting for the new world.
this.handleGameModeAndFlight(event.getPlayer(), event.getPlayer().getWorld());
playerWorld.put(p.getName(), p.getWorld().getName());
}
/**
* This method is called when a player changes worlds.
* @param event The Event that was fired.
*/
@EventHandler(priority = EventPriority.MONITOR)
public void playerChangedWorld(PlayerChangedWorldEvent event) {
// Permissions now determine whether or not to handle a gamemode.
this.handleGameModeAndFlight(event.getPlayer(), event.getPlayer().getWorld());
playerWorld.put(event.getPlayer().getName(), event.getPlayer().getWorld().getName());
}
/**
* This method is called when a player teleports anywhere.
* @param event The Event that was fired.
*/
@EventHandler(priority = EventPriority.HIGHEST)
public void playerTeleport(PlayerTeleportEvent event) {
Logging.finer("Got teleport event for player '"
+ event.getPlayer().getName() + "' with cause '" + event.getCause() + "'");
if (event.isCancelled()) {
return;
}
Player teleportee = event.getPlayer();
CommandSender teleporter = null;
Optional<String> teleporterName = teleportQueue.popFromQueue(teleportee.getName());
if (teleporterName.isPresent()) {
if (teleporterName.equals("CONSOLE")) {
Logging.finer("We know the teleporter is the console! Magical!");
teleporter = this.server.getConsoleSender();
} else {
teleporter = this.server.getPlayerExact(teleporterName.get());
}
}
Logging.finer("Inferred sender '" + teleporter + "' from name '"
+ teleporterName + "', fetched from name '" + teleportee.getName() + "'");
MVWorld fromWorld = getWorldManager().getMVWorld(event.getFrom().getWorld().getName());
MVWorld toWorld = getWorldManager().getMVWorld(event.getTo().getWorld().getName());
if (toWorld == null) {
Logging.fine("Player '" + teleportee.getName() + "' is teleporting to world '"
+ event.getTo().getWorld().getName() + "' which is not managed by Multiverse-Core. No further "
+ "actions will be taken by Multiverse-Core.");
return;
}
if (event.getFrom().getWorld().equals(event.getTo().getWorld())) {
// The player is Teleporting to the same world.
Logging.finer("Player '" + teleportee.getName() + "' is teleporting to the same world.");
this.stateSuccess(teleportee.getName(), toWorld.getAlias());
return;
}
// TODO: Refactor these lines.
// Charge the teleporter
event.setCancelled(!pt.playerHasMoneyToEnter(fromWorld, toWorld, teleporter, teleportee, true));
if (event.isCancelled() && teleporter != null) {
Logging.fine("Player '" + teleportee.getName()
+ "' was DENIED ACCESS to '" + toWorld.getAlias()
+ "' because '" + teleporter.getName()
+ "' don't have the FUNDS required to enter it.");
return;
}
// Check if player is allowed to enter the world if we're enforcing permissions
if (config.getEnforceAccess()) {
event.setCancelled(!pt.playerCanGoFromTo(fromWorld, toWorld, teleporter, teleportee));
if (event.isCancelled() && teleporter != null) {
Logging.fine("Player '" + teleportee.getName()
+ "' was DENIED ACCESS to '" + toWorld.getAlias()
+ "' because '" + teleporter.getName()
+ "' don't have: multiverse.access." + event.getTo().getWorld().getName());
return;
}
} else {
Logging.fine("Player '" + teleportee.getName()
+ "' was allowed to go to '" + toWorld.getAlias() + "' because enforceaccess is off.");
}
// Does a limit actually exist?
if (toWorld.getPlayerLimit() > -1) {
// Are there equal or more people on the world than the limit?
if (toWorld.getCBWorld().getPlayers().size() >= toWorld.getPlayerLimit()) {
// Ouch the world is full, lets see if the player can bypass that limitation
if (!pt.playerCanBypassPlayerLimit(toWorld, teleporter, teleportee)) {
Logging.fine("Player '" + teleportee.getName()
+ "' was DENIED ACCESS to '" + toWorld.getAlias()
+ "' because the world is full and '" + teleporter.getName()
+ "' doesn't have: mv.bypass.playerlimit." + event.getTo().getWorld().getName());
event.setCancelled(true);
return;
}
}
}
// By this point anything cancelling the event has returned on the method, meaning the teleport is a success \o/
this.stateSuccess(teleportee.getName(), toWorld.getAlias());
}
private void stateSuccess(String playerName, String worldName) {
Logging.fine("MV-Core is allowing Player '" + playerName
+ "' to go to '" + worldName + "'.");
}
/**
* This method is called to adjust the portal location to the actual portal location (and not
* right outside of it.
* @param event The Event that was fired.
*/
@EventHandler(priority = EventPriority.LOWEST)
public void playerPortalCheck(PlayerPortalEvent event) {
if (event.isCancelled() || event.getFrom() == null) {
return;
}
// REMEMBER! getTo MAY be NULL HERE!!!
// If the player was actually outside of the portal, adjust the from location
if (event.getFrom().getWorld().getBlockAt(event.getFrom()).getType() != Material.NETHER_PORTAL) {
Location newloc = this.safeTTeleporter.findPortalBlockNextTo(event.getFrom());
// TODO: Fix this. Currently, we only check for PORTAL blocks. I'll have to figure out what
// TODO: we want to do here.
if (newloc != null) {
event.setFrom(newloc);
}
}
// Wait for the adjust, then return!
if (event.getTo() == null) {
return;
}
}
/**
* This method is called when a player actually portals via a vanilla style portal.
* @param event The Event that was fired.
*/
@EventHandler(priority = EventPriority.HIGH)
public void playerPortal(PlayerPortalEvent event) {
if (event.isCancelled() || (event.getFrom() == null)) {
return;
}
// The adjust should have happened much earlier.
if (event.getTo() == null) {
return;
}
MVWorld fromWorld = getWorldManager().getMVWorld(event.getFrom().getWorld().getName());
MVWorld toWorld = getWorldManager().getMVWorld(event.getTo().getWorld().getName());
if (event.getFrom().getWorld().equals(event.getTo().getWorld())) {
// The player is Portaling to the same world.
Logging.finer("Player '" + event.getPlayer().getName() + "' is portaling to the same world.");
return;
}
event.setCancelled(!pt.playerHasMoneyToEnter(fromWorld, toWorld, event.getPlayer(), event.getPlayer(), true));
if (event.isCancelled()) {
Logging.fine("Player '" + event.getPlayer().getName()
+ "' was DENIED ACCESS to '" + event.getTo().getWorld().getName()
+ "' because they don't have the FUNDS required to enter.");
return;
}
if (config.getEnforceAccess()) {
event.setCancelled(!pt.playerCanGoFromTo(fromWorld, toWorld, event.getPlayer(), event.getPlayer()));
if (event.isCancelled()) {
Logging.fine("Player '" + event.getPlayer().getName()
+ "' was DENIED ACCESS to '" + event.getTo().getWorld().getName()
+ "' because they don't have: multiverse.access." + event.getTo().getWorld().getName());
}
} else {
Logging.fine("Player '" + event.getPlayer().getName()
+ "' was allowed to go to '" + event.getTo().getWorld().getName()
+ "' because enforceaccess is off.");
}
if (!config.isUsingCustomPortalSearch()) {
event.setSearchRadius(config.getCustomPortalSearchRadius());
}
}
private void sendPlayerToDefaultWorld(final Player player) {
// Remove the player 1 tick after the login. I'm sure there's GOT to be a better way to do this...
this.server.getScheduler().scheduleSyncDelayedTask(this.plugin,
new Runnable() {
@Override
public void run() {
player.teleport(getWorldManager().getFirstSpawnWorld().getSpawnLocation());
}
}, 1L);
}
// FOLLOWING 2 Methods and Private class handle Per Player GameModes.
private void handleGameModeAndFlight(Player player, World world) {
MVWorld mvWorld = getWorldManager().getMVWorld(world.getName());
if (mvWorld != null) {
this.handleGameModeAndFlight(player, mvWorld);
} else {
Logging.finer("Not handling gamemode and flight for world '" + world.getName()
+ "' not managed by Multiverse.");
}
}
/**
* Handles the gamemode for the specified {@link Player}.
* @param player The {@link Player}.
* @param world The world the player is in.
*/
public void handleGameModeAndFlight(final Player player, final MVWorld world) {
// We perform this task one tick later to MAKE SURE that the player actually reaches the
// destination world, otherwise we'd be changing the player mode if they havent moved anywhere.
this.server.getScheduler().scheduleSyncDelayedTask(this.plugin,
new Runnable() {
@Override
public void run() {
if (!MVPlayerListener.this.pt.playerCanIgnoreGameModeRestriction(world, player)) {
// Check that the player is in the new world and they haven't been teleported elsewhere or the event cancelled.
if (player.getWorld() == world.getCBWorld()) {
Logging.fine("Handling gamemode for player: %s, Changing to %s", player.getName(), world.getGameMode().toString());
Logging.finest("From World: %s", player.getWorld());
Logging.finest("To World: %s", world);
player.setGameMode(world.getGameMode());
// Check if their flight mode should change
// TODO need a override permission for this
if (player.getAllowFlight() && !world.getAllowFlight() && player.getGameMode() != GameMode.CREATIVE) {
player.setAllowFlight(false);
if (player.isFlying()) {
player.setFlying(false);
}
} else if (world.getAllowFlight()) {
if (player.getGameMode() == GameMode.CREATIVE) {
player.setAllowFlight(true);
}
}
} else {
Logging.fine("The gamemode/allowfly was NOT changed for player '%s' because he is now in world '%s' instead of world '%s'",
player.getName(), player.getWorld().getName(), world.getName());
}
} else {
Logging.fine("Player: " + player.getName() + " is IMMUNE to gamemode changes!");
}
}
}, 1L);
}
}
@@ -1,113 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2012. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.listeners;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.inject.InjectableListener;
import jakarta.inject.Inject;
import org.bukkit.Material;
import org.bukkit.PortalType;
import org.bukkit.block.BlockState;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.world.PortalCreateEvent;
import org.jvnet.hk2.annotations.Service;
/**
* A custom listener for portal related events.
*/
@Service
public class MVPortalListener implements InjectableListener {
private MVWorldManager worldManager;
@Inject
public MVPortalListener(MVWorldManager worldManager) {
this.worldManager = worldManager;
}
/**
* This is called when a portal is formed.
* @param event The event where a portal was created or formed due to a world link
*/
@EventHandler(ignoreCancelled = true)
public void portalForm(PortalCreateEvent event) {
Logging.fine("Attempting to create portal at '%s' with reason: %s", event.getWorld().getName(), event.getReason());
MVWorld world = this.worldManager.getMVWorld(event.getWorld());
if (world == null) {
Logging.fine("World '%s' is not managed by Multiverse! Ignoring at PortalCreateEvent.", event.getWorld().getName());
return;
}
PortalType targetType;
switch (event.getReason()) {
case FIRE:
// Ensure portal by flint and steel actually creates nether
boolean isNether = false;
for (BlockState block : event.getBlocks()) {
if (block.getType() == Material.NETHER_PORTAL) {
isNether = true;
break;
}
}
if (!isNether) {
return;
}
targetType = PortalType.NETHER;
break;
case NETHER_PAIR:
targetType = PortalType.NETHER;
break;
case END_PLATFORM:
targetType = PortalType.ENDER;
break;
default:
Logging.fine("Portal created is not NETHER or ENDER type. Ignoring...");
return;
}
if (!world.getAllowedPortals().isPortalAllowed(targetType)) {
Logging.fine("Cancelling creation of %s portal because portalForm disallows.", targetType);
event.setCancelled(true);
}
}
/**
* This method will prevent ender portals from being created in worlds where they are not allowed due to portalForm.
*
* @param event The player interact event.
*/
@EventHandler(ignoreCancelled = true)
public void portalForm(PlayerInteractEvent event) {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) {
return;
}
if (event.getClickedBlock() == null || event.getClickedBlock().getType() != Material.END_PORTAL_FRAME) {
return;
}
if (event.getItem() == null || event.getItem().getType() != Material.ENDER_EYE) {
return;
}
MVWorld world = this.worldManager.getMVWorld(event.getPlayer().getWorld());
if (world == null) {
Logging.fine("World '%s' is not managed by Multiverse! Ignoring at PlayerInteractEvent.",
event.getPlayer().getWorld().getName());
return;
}
if (!world.getAllowedPortals().isPortalAllowed(PortalType.ENDER)) {
Logging.fine("Cancelling creation of ENDER portal because portalForm disallows.");
event.setCancelled(true);
}
}
}
@@ -1,33 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.listeners;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.inject.InjectableListener;
import jakarta.inject.Inject;
import org.bukkit.event.EventHandler;
import org.bukkit.event.world.WorldInitEvent;
import org.jvnet.hk2.annotations.Service;
@Service
public class MVWorldInitListener implements InjectableListener {
private final MVWorldManager worldManager;
@Inject
public MVWorldInitListener(MVWorldManager worldManager) {
this.worldManager = worldManager;
}
@EventHandler
public void initWorld(WorldInitEvent event) {
if (!worldManager.isKeepingSpawnInMemory(event.getWorld())) {
event.getWorld().setKeepSpawnInMemory(false);
}
}
}
@@ -1,69 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.listeners;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.inject.InjectableListener;
import jakarta.inject.Inject;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import org.jvnet.hk2.annotations.Service;
/**
* Multiverse's World Listener.
*/
@Service
public class MVWorldListener implements InjectableListener {
private MVWorldManager worldManager;
@Inject
public MVWorldListener(MVWorldManager worldManager) {
this.worldManager = worldManager;
}
/**
* This method is called when Bukkit fires off a WorldUnloadEvent.
* @param event The Event that was fired.
*/
@EventHandler
public void unloadWorld(WorldUnloadEvent event) {
if (event.isCancelled()) {
return;
}
if (event.getWorld() instanceof World) {
World world = (World) event.getWorld();
if (world != null) {
this.worldManager.unloadWorld(world.getName(), false);
}
}
}
/**
* This method is called when Bukkit fires off a WorldLoadEvent.
* @param event The Event that was fired.
*/
@EventHandler
public void loadWorld(WorldLoadEvent event) {
World world = event.getWorld();
if (world != null) {
if (this.worldManager.getUnloadedWorlds().contains(world.getName())) {
this.worldManager.loadWorld(world.getName());
}
MVWorld mvWorld = worldManager.getMVWorld(world);
if (mvWorld != null) {
// This is where we can temporarily fix those pesky property issues!
world.setPVP(mvWorld.isPVPEnabled());
world.setDifficulty(mvWorld.getDifficulty());
}
}
}
}
@@ -1,79 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.listeners;
import com.onarandombox.MultiverseCore.event.MVConfigReloadEvent;
import com.onarandombox.MultiverseCore.event.MVPlayerTouchedPortalEvent;
import com.onarandombox.MultiverseCore.event.MVRespawnEvent;
import com.onarandombox.MultiverseCore.event.MVTeleportEvent;
import com.onarandombox.MultiverseCore.event.MVVersionEvent;
import com.onarandombox.MultiverseCore.event.MVWorldDeleteEvent;
import com.onarandombox.MultiverseCore.event.MVWorldPropertyChangeEvent;
import com.onarandombox.MultiverseCore.inject.InjectableListener;
import org.bukkit.event.EventHandler;
/**
* Subclasses of this listener can be used to conveniently listen to MultiverseCore-events.
*/
public abstract class MultiverseCoreListener implements InjectableListener {
/**
* Called when a {@link MVWorldPropertyChangeEvent} is fired.
* @param event The event.
*/
@EventHandler
public void worldPropertyChange(MVWorldPropertyChangeEvent event) {
}
/**
* Called when a {@link MVWorldDeleteEvent} is fired.
* @param event The event.
*/
@EventHandler
public void worldDelete(MVWorldDeleteEvent event) {
}
/**
* Called when a {@link MVVersionEvent} is fired.
* @param event The event.
*/
@EventHandler
public void versionRequest(MVVersionEvent event) {
}
/**
* Called when a {@link MVTeleportEvent} is fired.
* @param event The event.
*/
@EventHandler
public void playerTeleport(MVTeleportEvent event) {
}
/**
* Called when a {@link MVRespawnEvent} is fired.
* @param event The event.
*/
@EventHandler
public void playerRespawn(MVRespawnEvent event) {
}
/**
* Called when a {@link MVPlayerTouchedPortalEvent} is fired.
* @param event The event.
*/
@EventHandler
public void playerTouchedPortal(MVPlayerTouchedPortalEvent event) {
}
/**
* Called when a {@link MVConfigReloadEvent} is fired.
* @param event The event.
*/
@EventHandler
public void configReload(MVConfigReloadEvent event) {
}
}
@@ -1,4 +0,0 @@
/**
* This package contains all listeners.
*/
package com.onarandombox.MultiverseCore.listeners;
@@ -1,272 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.teleportation;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.BlockSafety;
import com.onarandombox.MultiverseCore.api.LocationManipulation;
import jakarta.inject.Inject;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Bed;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Vehicle;
import org.jvnet.hk2.annotations.Service;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Set;
/**
* The default-implementation of {@link BlockSafety}.
*/
@Service
public class SimpleBlockSafety implements BlockSafety {
private final LocationManipulation locationManipulation;
private static final Set<BlockFace> AROUND_BLOCK = EnumSet.noneOf(BlockFace.class);
static {
AROUND_BLOCK.add(BlockFace.NORTH);
AROUND_BLOCK.add(BlockFace.NORTH_EAST);
AROUND_BLOCK.add(BlockFace.EAST);
AROUND_BLOCK.add(BlockFace.SOUTH_EAST);
AROUND_BLOCK.add(BlockFace.SOUTH);
AROUND_BLOCK.add(BlockFace.SOUTH_WEST);
AROUND_BLOCK.add(BlockFace.WEST);
AROUND_BLOCK.add(BlockFace.NORTH_WEST);
}
@Inject
public SimpleBlockSafety(LocationManipulation locationManipulation) {
this.locationManipulation = locationManipulation;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isBlockAboveAir(Location l) {
Location downOne = l.clone();
downOne.setY(downOne.getY() - 1);
return (downOne.getBlock().getType() == Material.AIR);
}
/**
* {@inheritDoc}
*/
@Override
public boolean playerCanSpawnHereSafely(World world, double x, double y, double z) {
Location l = new Location(world, x, y, z);
return playerCanSpawnHereSafely(l);
}
/**
* {@inheritDoc}
*/
@Override
public boolean playerCanSpawnHereSafely(Location l) {
if (l == null) {
// Can't safely spawn at a null location!
return false;
}
World world = l.getWorld();
Location actual = l.clone();
Location upOne = l.clone();
Location downOne = l.clone();
upOne.setY(upOne.getY() + 1);
downOne.setY(downOne.getY() - 1);
if (isSolidBlock(world.getBlockAt(actual).getType())
|| isSolidBlock(upOne.getBlock().getType())) {
Logging.finer("Error Here (Actual)? (%s)[%s]", actual.getBlock().getType(),
isSolidBlock(actual.getBlock().getType()));
Logging.finer("Error Here (upOne)? (%s)[%s]", upOne.getBlock().getType(),
isSolidBlock(upOne.getBlock().getType()));
return false;
}
if (downOne.getBlock().getType() == Material.LAVA) {
Logging.finer("Error Here (downOne)? (%s)[%s]", downOne.getBlock().getType(), isSolidBlock(downOne.getBlock().getType()));
return false;
}
if (downOne.getBlock().getType() == Material.FIRE) {
Logging.finer("There's fire below! (%s)[%s]", actual.getBlock().getType(), isSolidBlock(actual.getBlock().getType()));
return false;
}
if (isBlockAboveAir(actual)) {
Logging.finer("Is block above air [%s]", isBlockAboveAir(actual));
Logging.finer("Has 2 blocks of water below [%s]", this.hasTwoBlocksofWaterBelow(actual));
return this.hasTwoBlocksofWaterBelow(actual);
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public Location getSafeBedSpawn(Location l) {
// The passed location, may be null (if the bed is invalid)
if (l == null) {
return null;
}
final Location trySpawn = this.getSafeSpawnAroundABlock(l);
if (trySpawn != null) {
return trySpawn;
}
Location otherBlock = this.findOtherBedPiece(l);
if (otherBlock == null) {
return null;
}
// Now we have 2 locations, check around each, if the type is bed, skip it.
return this.getSafeSpawnAroundABlock(otherBlock);
}
/**
* Find a safe spawn around a location. (N,S,E,W,NE,NW,SE,SW)
* @param l Location to check around
* @return A safe location, or none if it wasn't found.
*/
private Location getSafeSpawnAroundABlock(Location l) {
Iterator<BlockFace> checkblock = AROUND_BLOCK.iterator();
while (checkblock.hasNext()) {
final BlockFace face = checkblock.next();
if (this.playerCanSpawnHereSafely(l.getBlock().getRelative(face).getLocation())) {
// Don't forget to center the player.
return l.getBlock().getRelative(face).getLocation().add(.5, 0, .5);
}
}
return null;
}
/**
* Find the other bed block.
* @param checkLoc The location to check for the other piece at
* @return The location of the other bed piece, or null if it was a jacked up bed.
*/
private Location findOtherBedPiece(Location checkLoc) {
BlockData data = checkLoc.getBlock().getBlockData();
if (!(data instanceof Bed)) {
return null;
}
Bed b = (Bed) data;
if (b.getPart() == Bed.Part.HEAD) {
return checkLoc.getBlock().getRelative(b.getFacing().getOppositeFace()).getLocation();
}
// We shouldn't ever be looking at the foot, but here's the code for it.
return checkLoc.getBlock().getRelative(b.getFacing()).getLocation();
}
/**
* {@inheritDoc}
*/
@Override
public Location getTopBlock(Location l) {
Location check = l.clone();
check.setY(127); // SUPPRESS CHECKSTYLE: MagicNumberCheck
while (check.getY() > 0) {
if (this.playerCanSpawnHereSafely(check)) {
return check;
}
check.setY(check.getY() - 1);
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public Location getBottomBlock(Location l) {
Location check = l.clone();
check.setY(0);
while (check.getY() < 127) { // SUPPRESS CHECKSTYLE: MagicNumberCheck
if (this.playerCanSpawnHereSafely(check)) {
return check;
}
check.setY(check.getY() + 1);
}
return null;
}
/*
* If someone has a better way of this... Please either tell us, or submit a pull request!
*/
public static boolean isSolidBlock(Material type) {
return type.isSolid();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEntitiyOnTrack(Location l) {
Material currentBlock = l.getBlock().getType();
return (currentBlock == Material.POWERED_RAIL
|| currentBlock == Material.DETECTOR_RAIL
|| currentBlock == Material.RAIL
|| currentBlock == Material.ACTIVATOR_RAIL);
}
/**
* Checks recursively below a {@link Location} for 2 blocks of water.
*
* @param l The {@link Location}
* @return Whether there are 2 blocks of water
*/
private boolean hasTwoBlocksofWaterBelow(Location l) {
if (l.getBlockY() < 0) {
return false;
}
Location oneBelow = l.clone();
oneBelow.subtract(0, 1, 0);
if (oneBelow.getBlock().getType() == Material.WATER) {
Location twoBelow = oneBelow.clone();
twoBelow.subtract(0, 1, 0);
return (oneBelow.getBlock().getType() == Material.WATER);
}
if (oneBelow.getBlock().getType() != Material.AIR) {
return false;
}
return hasTwoBlocksofWaterBelow(oneBelow);
}
/**
* {@inheritDoc}
*/
@Override
public boolean canSpawnCartSafely(Minecart cart) {
if (this.isBlockAboveAir(cart.getLocation())) {
return true;
}
if (this.isEntitiyOnTrack(locationManipulation.getNextBlock(cart))) {
return true;
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean canSpawnVehicleSafely(Vehicle vehicle) {
if (this.isBlockAboveAir(vehicle.getLocation())) {
return true;
}
return false;
}
}
@@ -1,377 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.teleportation;
import java.util.concurrent.CompletableFuture;
import co.aikar.commands.BukkitCommandIssuer;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.BlockSafety;
import com.onarandombox.MultiverseCore.api.DestinationInstance;
import com.onarandombox.MultiverseCore.api.LocationManipulation;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import io.papermc.lib.PaperLib;
import jakarta.inject.Inject;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
import org.bukkit.util.Vector;
import org.jvnet.hk2.annotations.Service;
/**
* The default-implementation of {@link SafeTTeleporter}.
*/
@Service
public class SimpleSafeTTeleporter implements SafeTTeleporter {
private final MultiverseCore plugin;
private final LocationManipulation locationManipulation;
private final BlockSafety blockSafety;
private final TeleportQueue teleportQueue;
@Inject
public SimpleSafeTTeleporter(
MultiverseCore plugin,
LocationManipulation locationManipulation,
BlockSafety blockSafety,
TeleportQueue teleportQueue
) {
this.plugin = plugin;
this.locationManipulation = locationManipulation;
this.blockSafety = blockSafety;
this.teleportQueue = teleportQueue;
}
private static final Vector DEFAULT_VECTOR = new Vector();
private static final int DEFAULT_TOLERANCE = 6;
private static final int DEFAULT_RADIUS = 9;
/**
* {@inheritDoc}
*/
@Override
public Location getSafeLocation(Location l) {
return this.getSafeLocation(l, DEFAULT_TOLERANCE, DEFAULT_RADIUS);
}
/**
* {@inheritDoc}
*/
@Override
public Location getSafeLocation(Location l, int tolerance, int radius) {
// Check around the player first in a configurable radius:
// TODO: Make this configurable
Location safe = checkAboveAndBelowLocation(l, tolerance, radius);
if (safe != null) {
safe.setX(safe.getBlockX() + .5); // SUPPRESS CHECKSTYLE: MagicNumberCheck
safe.setZ(safe.getBlockZ() + .5); // SUPPRESS CHECKSTYLE: MagicNumberCheck
Logging.fine("Hey! I found one: " + locationManipulation.strCoordsRaw(safe));
} else {
Logging.fine("Uh oh! No safe place found!");
}
return safe;
}
private Location checkAboveAndBelowLocation(Location l, int tolerance, int radius) {
// Tolerance must be an even number:
if (tolerance % 2 != 0) {
tolerance += 1;
}
// We want half of it, so we can go up and down
tolerance /= 2;
Logging.finer("Given Location of: " + locationManipulation.strCoordsRaw(l));
Logging.finer("Checking +-" + tolerance + " with a radius of " + radius);
// For now this will just do a straight up block.
Location locToCheck = l.clone();
// Check the main level
Location safe = this.checkAroundLocation(locToCheck, radius);
if (safe != null) {
return safe;
}
// We've already checked zero right above this.
int currentLevel = 1;
while (currentLevel <= tolerance) {
// Check above
locToCheck = l.clone();
locToCheck.add(0, currentLevel, 0);
safe = this.checkAroundLocation(locToCheck, radius);
if (safe != null) {
return safe;
}
// Check below
locToCheck = l.clone();
locToCheck.subtract(0, currentLevel, 0);
safe = this.checkAroundLocation(locToCheck, radius);
if (safe != null) {
return safe;
}
currentLevel++;
}
return null;
}
/*
* For my crappy algorithm, radius MUST be odd.
*/
private Location checkAroundLocation(Location l, int diameter) {
if (diameter % 2 == 0) {
diameter += 1;
}
Location checkLoc = l.clone();
// Start at 3, the min diameter around a block
int loopcounter = 3;
while (loopcounter <= diameter) {
boolean foundSafeArea = checkAroundSpecificDiameter(checkLoc, loopcounter);
// If a safe area was found:
if (foundSafeArea) {
// Return the checkLoc, it is the safe location.
return checkLoc;
}
// Otherwise, let's reset our location
checkLoc = l.clone();
// And increment the radius
loopcounter += 2;
}
return null;
}
private boolean checkAroundSpecificDiameter(Location checkLoc, int circle) {
// Adjust the circle to get how many blocks to step out.
// A radius of 3 makes the block step 1
// A radius of 5 makes the block step 2
// A radius of 7 makes the block step 3
// ...
int adjustedCircle = ((circle - 1) / 2);
checkLoc.add(adjustedCircle, 0, 0);
if (blockSafety.playerCanSpawnHereSafely(checkLoc)) {
return true;
}
// Now we go to the right that adjustedCircle many
for (int i = 0; i < adjustedCircle; i++) {
checkLoc.add(0, 0, 1);
if (blockSafety.playerCanSpawnHereSafely(checkLoc)) {
return true;
}
}
// Then down adjustedCircle *2
for (int i = 0; i < adjustedCircle * 2; i++) {
checkLoc.add(-1, 0, 0);
if (blockSafety.playerCanSpawnHereSafely(checkLoc)) {
return true;
}
}
// Then left adjustedCircle *2
for (int i = 0; i < adjustedCircle * 2; i++) {
checkLoc.add(0, 0, -1);
if (blockSafety.playerCanSpawnHereSafely(checkLoc)) {
return true;
}
}
// Then up Then left adjustedCircle *2
for (int i = 0; i < adjustedCircle * 2; i++) {
checkLoc.add(1, 0, 0);
if (blockSafety.playerCanSpawnHereSafely(checkLoc)) {
return true;
}
}
// Then finish up by doing adjustedCircle - 1
for (int i = 0; i < adjustedCircle - 1; i++) {
checkLoc.add(0, 0, 1);
if (blockSafety.playerCanSpawnHereSafely(checkLoc)) {
return true;
}
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public TeleportResult safelyTeleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination) {
return safelyTeleportAsync(teleporter, teleportee, destination).join();
}
@Override
public CompletableFuture<TeleportResult> safelyTeleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination) {
if (destination == null) {
Logging.finer("Entity tried to teleport to an invalid destination");
return CompletableFuture.completedFuture(TeleportResult.FAIL_INVALID);
}
Player teleporteePlayer = null;
if (teleportee instanceof Player) {
teleporteePlayer = ((Player) teleportee);
} else if (teleportee.getPassenger() instanceof Player) {
teleporteePlayer = ((Player) teleportee.getPassenger());
}
if (teleporteePlayer == null) {
return CompletableFuture.completedFuture(TeleportResult.FAIL_INVALID);
}
teleportQueue.addToQueue(teleporter.getIssuer().getName(), teleporteePlayer.getName());
Location safeLoc = destination.getLocation(teleportee);
if (destination.getDestination().checkTeleportSafety()) {
safeLoc = this.getSafeLocation(teleportee, destination.getDestinationInstance());
}
if (safeLoc == null) {
return CompletableFuture.completedFuture(TeleportResult.FAIL_UNSAFE);
}
CompletableFuture<TeleportResult> future = new CompletableFuture<>();
PaperLib.teleportAsync(teleportee, safeLoc).thenAccept(result -> {
if (!result) {
future.complete(TeleportResult.FAIL_OTHER);
return;
}
Vector v = destination.getDestinationInstance().getVelocity(teleportee);
if (v != null && !DEFAULT_VECTOR.equals(v)) {
Bukkit.getScheduler().runTaskLater(this.plugin, () -> {
teleportee.setVelocity(v);
}, 1);
}
future.complete(TeleportResult.SUCCESS);
});
return future;
}
/**
* {@inheritDoc}
*/
@Override
public TeleportResult safelyTeleport(CommandSender teleporter, Entity teleportee, Location location, boolean safely) {
if (safely) {
location = this.getSafeLocation(location);
}
if (location != null) {
if (teleportee.teleport(location)) {
return TeleportResult.SUCCESS;
}
return TeleportResult.FAIL_OTHER;
}
return TeleportResult.FAIL_UNSAFE;
}
@Override
public Location getSafeLocation(Entity entity, DestinationInstance destination) {
Location l = destination.getLocation(entity);
if (blockSafety.playerCanSpawnHereSafely(l)) {
Logging.fine("The first location you gave me was safe.");
return l;
}
if (entity instanceof Minecart) {
Minecart m = (Minecart) entity;
if (!blockSafety.canSpawnCartSafely(m)) {
return null;
}
} else if (entity instanceof Vehicle) {
Vehicle v = (Vehicle) entity;
if (!blockSafety.canSpawnVehicleSafely(v)) {
return null;
}
}
Location safeLocation = this.getSafeLocation(l);
if (safeLocation != null) {
// Add offset to account for a vehicle on dry land!
if (entity instanceof Minecart && !blockSafety.isEntitiyOnTrack(safeLocation)) {
safeLocation.setY(safeLocation.getBlockY() + .5);
Logging.finer("Player was inside a minecart. Offsetting Y location.");
}
Logging.finer("Had to look for a bit, but I found a safe place for ya!");
return safeLocation;
}
if (entity instanceof Player) {
Player p = (Player) entity;
p.sendMessage("No safe locations found!");
Logging.finer("No safe location found for " + p.getName());
} else if (entity.getPassenger() instanceof Player) {
Player p = (Player) entity.getPassenger();
p.sendMessage("No safe locations found!");
Logging.finer("No safe location found for " + p.getName());
}
Logging.fine("Sorry champ, you're basically trying to teleport into a minefield. I should just kill you now.");
return null;
}
/**
* {@inheritDoc}
*/
@Override
public Location findPortalBlockNextTo(Location l) {
Block b = l.getWorld().getBlockAt(l);
Location foundLocation = null;
if (b.getType() == Material.NETHER_PORTAL) {
return l;
}
if (b.getRelative(BlockFace.NORTH).getType() == Material.NETHER_PORTAL) {
foundLocation = getCloserBlock(l, b.getRelative(BlockFace.NORTH).getLocation(), foundLocation);
}
if (b.getRelative(BlockFace.SOUTH).getType() == Material.NETHER_PORTAL) {
foundLocation = getCloserBlock(l, b.getRelative(BlockFace.SOUTH).getLocation(), foundLocation);
}
if (b.getRelative(BlockFace.EAST).getType() == Material.NETHER_PORTAL) {
foundLocation = getCloserBlock(l, b.getRelative(BlockFace.EAST).getLocation(), foundLocation);
}
if (b.getRelative(BlockFace.WEST).getType() == Material.NETHER_PORTAL) {
foundLocation = getCloserBlock(l, b.getRelative(BlockFace.WEST).getLocation(), foundLocation);
}
return foundLocation;
}
private static Location getCloserBlock(Location source, Location blockA, Location blockB) {
// If B wasn't given, return a.
if (blockB == null) {
return blockA;
}
// Center our calculations
blockA.add(.5, 0, .5);
blockB.add(.5, 0, .5);
// Retrieve the distance to the normalized blocks
double testA = source.distance(blockA);
double testB = source.distance(blockB);
// Compare and return
if (testA <= testB) {
return blockA;
}
return blockB;
}
@Override
public TeleportResult teleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination) {
return safelyTeleport(teleporter, teleportee, destination);
}
@Override
public CompletableFuture<TeleportResult> teleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination) {
return safelyTeleportAsync(teleporter, teleportee, destination);
}
}
@@ -1,38 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.teleportation;
/**
* An enum containing possible teleport-results.
*/
public enum TeleportResult {
/**
* Insufficient permissions.
*/
FAIL_PERMISSION,
/**
* The teleport was unsafe.
*/
FAIL_UNSAFE,
/**
* The player was to poor.
*/
FAIL_TOO_POOR,
/**
* The teleport was invalid.
*/
FAIL_INVALID,
/**
* Unknown reason.
*/
FAIL_OTHER,
/**
* The player was successfully teleported.
*/
SUCCESS
}
@@ -1,96 +0,0 @@
package com.onarandombox.MultiverseCore.utils;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.utils.message.Message;
import com.onarandombox.MultiverseCore.utils.message.MessageReplacement;
import org.jetbrains.annotations.NotNull;
public enum MVCorei18n implements MessageKeyProvider {
// config status
CONFIG_SAVE_FAILED,
CONFIG_NODE_NOTFOUND,
// check command
CHECK_CHECKING,
// clone command
CLONE_CLONING,
CLONE_FAILED,
CLONE_SUCCESS,
// create command
CREATE_PROPERTIES,
CREATE_PROPERTIES_ENVIRONMENT,
CREATE_PROPERTIES_SEED,
CREATE_PROPERTIES_WORLDTYPE,
CREATE_PROPERTIES_ADJUSTSPAWN,
CREATE_PROPERTIES_GENERATOR,
CREATE_PROPERTIES_STRUCTURES,
CREATE_LOADING,
CREATE_FAILED,
CREATE_SUCCESS,
// delete command
DELETE_DELETING,
DELETE_FAILED,
DELETE_SUCCESS,
DELETE_PROMPT,
// gamerule command
GAMERULE_FAILED,
GAMERULE_SUCCESS_SINGLE,
GAMERULE_SUCCESS_MULTIPLE,
// import command
IMPORT_IMPORTING,
IMPORT_FAILED,
IMPORT_SUCCESS,
// load command
LOAD_LOADING,
LOAD_FAILED,
LOAD_SUCCESS,
// regen command
REGEN_REGENERATING,
REGEN_FAILED,
REGEN_SUCCESS,
REGEN_PROMPT,
// reload command
RELOAD_RELOADING,
RELOAD_SUCCESS,
// remove command
REMOVE_FAILED,
REMOVE_SUCCESS,
// root MV command
ROOT_TITLE,
ROOT_HELP,
// teleport command
TELEPORT_SUCCESS,
// unload command
UNLOAD_UNLOADING,
UNLOAD_FAILURE,
UNLOAD_SUCCESS,
// debug command
DEBUG_INFO_OFF,
DEBUG_INFO_ON;
private final MessageKey key = MessageKey.of("mv-core." + this.name().replace('_', '.').toLowerCase());
@Override
public MessageKey getMessageKey() {
return this.key;
}
@NotNull
public Message bundle(@NotNull String nonLocalizedMessage, @NotNull MessageReplacement... replacements) {
return Message.of(this, nonLocalizedMessage, replacements);
}
}
@@ -1,415 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.utils;
import java.util.List;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.MVDestination;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import jakarta.inject.Inject;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.PluginManager;
import org.jvnet.hk2.annotations.Service;
/**
* Multiverse's permission checker
*/
@Service
public class MVPermissions {
private final PluginManager pluginManager;
private final MVCoreConfig config;
private final MVWorldManager worldMgr;
@Inject
public MVPermissions(
PluginManager pluginManager,
MVCoreConfig config,
MVWorldManager worldManager
) {
this.pluginManager = pluginManager;
this.config = config;
this.worldMgr = worldManager;
}
/**
* Check if a Player can ignore GameMode restrictions for world they travel to.
*
* @param p The {@link Player} to check.
* @param w The {@link MVWorld} the player wants to teleport to.
* @return True if they should bypass restrictions.
*/
public boolean canIgnoreGameModeRestriction(Player p, MVWorld w) {
return p.hasPermission("mv.bypass.gamemode." + w.getName());
}
/**
* Check if a Player can teleport to the Destination world from there current world.
*
* @param p The {@link Player} to check.
* @param w The {@link MVWorld} the player wants to teleport to.
* @return Whether the player can teleport to the given {@link MVWorld}.
*/
public boolean canTravelFromWorld(Player p, MVWorld w) {
List<String> blackList = w.getWorldBlacklist();
boolean returnValue = true;
for (String s : blackList) {
if (s.equalsIgnoreCase(p.getWorld().getName())) {
returnValue = false;
break;
}
}
return returnValue;
}
/**
* Checks if the specified {@link CommandSender} can travel to the specified {@link Location}.
* @param sender The {@link CommandSender}.
* @param location The {@link Location}.
* @return Whether the {@link CommandSender} can travel to the specified {@link Location}.
*/
public boolean canTravelFromLocation(CommandSender sender, Location location) {
// Now The Bed destination can return null now.
if (location == null) {
return false;
}
if (!(sender instanceof Player)) {
return true;
}
Player teleporter = (Player) sender;
if (!this.worldMgr.isMVWorld(location.getWorld().getName())) {
return false;
}
return canTravelFromWorld(teleporter, this.worldMgr.getMVWorld(location.getWorld().getName()));
}
/**
* Check if the Player has the permissions to enter this world.
*
* @param p The {@link Player} player that wants to enter
* @param w The {@link MVWorld} he wants to enter
* @return Whether he has the permission to enter the world
*/
public boolean canEnterWorld(Player p, MVWorld w) {
// If we're not enforcing access, anyone can enter.
if (!config.getEnforceAccess()) {
Logging.finest("EnforceAccess is OFF. Player was allowed in " + w.getAlias());
return true;
}
return this.hasPermission(p, "multiverse.access." + w.getName(), false);
}
private boolean canEnterLocation(Player p, Location l) {
if (l == null) {
return false;
}
String worldName = l.getWorld().getName();
if (!this.worldMgr.isMVWorld(worldName)) {
return false;
}
return this.hasPermission(p, "multiverse.access." + worldName, false);
}
/**
* Check to see if a sender can enter a destination.
* The reason this is not a player, is it can be used to simply check permissions
* The console should, for exmaple, always see all worlds
*
* @param sender The CommandSender to check.
* @param d The destination they are requesting.
* @return True if that sender can go to that destination
*/
public boolean canEnterDestination(CommandSender sender, MVDestination d) {
if (!(sender instanceof Player)) {
return true;
}
Player p = (Player) sender;
if (d == null || d.getLocation(p) == null) {
return false;
}
String worldName = d.getLocation(p).getWorld().getName();
if (!this.worldMgr.isMVWorld(worldName)) {
return false;
}
if (!canEnterLocation(p, d.getLocation(p))) {
return false;
}
return this.hasPermission(p, d.getRequiredPermission(), false);
}
/**
* Tells a {@link CommandSender} why another {@link CommandSender} can or can not access a certain {@link MVDestination}.
* @param asker The {@link CommandSender} that's asking.
* @param playerInQuestion The {@link CommandSender} whose permissions we want to know.
* @param d The {@link MVDestination}.
*/
public void tellMeWhyICantDoThis(CommandSender asker, CommandSender playerInQuestion, MVDestination d) {
boolean cango = true;
if (!(playerInQuestion instanceof Player)) {
asker.sendMessage(String.format("The console can do %severything%s.", ChatColor.RED, ChatColor.WHITE));
return;
}
Player p = (Player) playerInQuestion;
if (d == null) {
asker.sendMessage(String.format("The provided Destination is %sNULL%s, and therefore %sINVALID%s.",
ChatColor.RED, ChatColor.WHITE, ChatColor.RED, ChatColor.WHITE));
cango = false;
}
// We know it'll be a player here due to the first line of this method.
if (d.getLocation(p) == null) {
asker.sendMessage(String.format(
"The player will spawn at an %sindeterminate location%s. Talk to the MV Devs if you see this",
ChatColor.RED, ChatColor.WHITE));
cango = false;
}
String worldName = d.getLocation(p).getWorld().getName();
if (!this.worldMgr.isMVWorld(worldName)) {
asker.sendMessage(String.format("The destination resides in a world(%s%s%s) that is not managed by Multiverse.",
ChatColor.AQUA, worldName, ChatColor.WHITE));
asker.sendMessage(String.format("Type %s/mv import ?%s to see the import command's help page.",
ChatColor.DARK_AQUA, ChatColor.WHITE));
cango = false;
}
if (!this.hasPermission(p, "multiverse.access." + worldName, false)) {
asker.sendMessage(String.format("The player (%s%s%s) does not have the required world entry permission (%s%s%s) to go to the destination (%s%s%s).",
ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE,
ChatColor.GREEN, "multiverse.access." + worldName, ChatColor.WHITE,
ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE));
cango = false;
}
if (!this.hasPermission(p, d.getRequiredPermission(), false)) {
asker.sendMessage(String.format("The player (%s%s%s) does not have the required entry permission (%s%s%s) to go to the destination (%s%s%s).",
ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE,
ChatColor.GREEN, d.getRequiredPermission(), ChatColor.WHITE,
ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE));
cango = false;
}
if (cango) {
asker.sendMessage(String.format("The player (%s%s%s) CAN go to the destination (%s%s%s).",
ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE,
ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE));
} else {
asker.sendMessage(String.format("The player (%s%s%s) cannot access the destination %s%s%s. Therefore they can't use mvtp at all for this.",
ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE,
ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE));
return;
}
if (!this.hasPermission(p, "multiverse.teleport.self." + d.getIdentifier(), false)) {
asker.sendMessage(String.format("The player (%s%s%s) does not have the required teleport permission (%s%s%s) to use %s/mvtp %s%s.",
ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE,
ChatColor.GREEN, "multiverse.teleport.self." + d.getIdentifier(), ChatColor.WHITE,
ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE));
} else {
asker.sendMessage(String.format("The player (%s%s%s) has the required teleport permission (%s%s%s) to use %s/mvtp %s%s.",
ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE,
ChatColor.GREEN, "multiverse.teleport.self." + d.getIdentifier(), ChatColor.WHITE,
ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE));
}
if (!this.hasPermission(p, "multiverse.teleport.other." + d.getIdentifier(), false)) {
asker.sendMessage(String.format("The player (%s%s%s) does not have the required teleport permission (%s%s%s) to send others to %s%s%s via mvtp.",
ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE,
ChatColor.GREEN, "multiverse.teleport.other." + d.getIdentifier(), ChatColor.WHITE,
ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE));
} else {
asker.sendMessage(String.format("The player (%s%s%s) has required teleport permission (%s%s%s) to send others to %s%s%s via mvtp.",
ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE,
ChatColor.GREEN, "multiverse.teleport.other." + d.getIdentifier(), ChatColor.WHITE,
ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE));
}
}
/**
* Check to see if a player has a permission.
*
* @param sender Who is requesting the permission.
* @param node The permission node in string format; multiverse.core.list.worlds for example.
* @param isOpRequired deprecated This is not used for anything anymore.
* @return True if they have that permission or any parent.
*/
public boolean hasPermission(CommandSender sender, String node, boolean isOpRequired) {
if (!(sender instanceof Player)) {
return true;
}
// NO one can access a null permission (mainly used for destinations):w
if (node == null) {
return false;
}
// Everyone can access an empty permission
// Currently used for the PlayerDestination
if (node.equals("")) {
return true;
}
return checkActualPermission(sender, node);
}
// TODO: Better player checks, most likely not needed, but safer.
private boolean checkActualPermission(CommandSender sender, String node) {
Player player = (Player) sender;
boolean hasPermission = sender.hasPermission(node);
if (!sender.isPermissionSet(node)) {
Logging.finer(String.format("The node [%s%s%s] was %sNOT%s set for [%s%s%s].",
ChatColor.RED, node, ChatColor.WHITE, ChatColor.RED, ChatColor.WHITE, ChatColor.AQUA,
player.getDisplayName(), ChatColor.WHITE));
}
if (hasPermission) {
Logging.finer("Checking to see if player [" + player.getName() + "] has permission [" + node + "]... YES");
} else {
Logging.finer("Checking to see if player [" + player.getName() + "] has permission [" + node + "]... NO");
}
return hasPermission;
}
/**
* Checks to see if the sender has any parent perms.
* Stops when it finds one or when there are no more parents.
* This method is recursive.
*
* @param sender Who is asking for the permission.
* @param node The permission node to check (possibly already a parent).
* @return True if they have any parent perm, false if none.
*/
// TODO remove this...?
private boolean hasAnyParentPermission(CommandSender sender, String node) {
String parentPerm = this.pullOneLevelOff(node);
// Base case
if (parentPerm == null) {
return false;
}
// If they have a parent, they're good
if (this.checkActualPermission(sender, parentPerm + ".*")) {
return true;
}
return hasAnyParentPermission(sender, parentPerm);
}
/**
* Pulls one level off of a yaml style node.
* Given multiverse.core.list.worlds will return multiverse.core.list
*
* @param node The root node to check.
* @return The parent of the node
*/
private static String pullOneLevelOff(String node) {
if (node == null) {
return null;
}
int index = node.lastIndexOf(".");
if (index > 0) {
return node.substring(0, index);
}
return null;
}
/**
* {@inheritDoc}
*/
public boolean hasAnyPermission(CommandSender sender, List<String> nodes, boolean isOpRequired) {
for (String node : nodes) {
if (this.hasPermission(sender, node, isOpRequired)) {
return true;
}
}
return false;
}
/**
* {@inheritDoc}
*/
public boolean hasAllPermission(CommandSender sender, List<String> nodes, boolean isOpRequired) {
for (String node : nodes) {
if (!this.hasPermission(sender, node, isOpRequired)) {
return false;
}
}
return true;
}
/**
* Adds a permission.
* @param string The permission as {@link String}.
* @param defaultValue The default-value.
* @return The permission as {@link Permission}.
*/
public Permission addPermission(String string, PermissionDefault defaultValue) {
if (this.pluginManager.getPermission(string) == null) {
Permission permission = new Permission(string, defaultValue);
this.pluginManager.addPermission(permission);
this.addToParentPerms(string);
}
return this.pluginManager.getPermission(string);
}
private void addToParentPerms(String permString) {
String permStringChopped = permString.replace(".*", "");
String[] seperated = permStringChopped.split("\\.");
String parentPermString = getParentPerm(seperated);
if (parentPermString == null) {
addToRootPermission("*", permStringChopped);
addToRootPermission("*.*", permStringChopped);
return;
}
Permission parentPermission = this.pluginManager.getPermission(parentPermString);
// Creat parent and grandparents
if (parentPermission == null) {
parentPermission = new Permission(parentPermString);
this.pluginManager.addPermission(parentPermission);
this.addToParentPerms(parentPermString);
}
// Create actual perm.
Permission actualPermission = this.pluginManager.getPermission(permString);
// Extra check just to make sure the actual one is added
if (actualPermission == null) {
actualPermission = new Permission(permString);
this.pluginManager.addPermission(actualPermission);
}
if (!parentPermission.getChildren().containsKey(permString)) {
parentPermission.getChildren().put(actualPermission.getName(), true);
this.pluginManager.recalculatePermissionDefaults(parentPermission);
}
}
private void addToRootPermission(String rootPerm, String permStringChopped) {
Permission rootPermission = this.pluginManager.getPermission(rootPerm);
if (rootPermission == null) {
rootPermission = new Permission(rootPerm);
this.pluginManager.addPermission(rootPermission);
}
rootPermission.getChildren().put(permStringChopped + ".*", true);
this.pluginManager.recalculatePermissionDefaults(rootPermission);
}
/**
* If the given permission was 'multiverse.core.tp.self', this would return 'multiverse.core.tp.*'.
*/
private static String getParentPerm(String[] seperated) {
if (seperated.length == 1) {
return null;
}
String returnString = "";
for (int i = 0; i < seperated.length - 1; i++) {
returnString += seperated[i] + ".";
}
return returnString + "*";
}
}
@@ -1,322 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.utils;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.economy.MVEconomist;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.PluginManager;
import org.jvnet.hk2.annotations.Service;
/**
* Utility-class for permissions.
*/
@Service
public class PermissionTools {
private final MVCoreConfig config;
private final PluginManager pluginManager;
private final Provider<MVPermissions> mvPermsProvider;
private final MVEconomist economist;
@Inject
public PermissionTools(
MVCoreConfig config,
PluginManager pluginManager,
Provider<MVPermissions> mvPermsProvider,
MVEconomist economist)
{
this.config = config;
this.pluginManager = pluginManager;
this.mvPermsProvider = mvPermsProvider;
this.economist = economist;
}
private MVPermissions getMVPerms() {
return this.mvPermsProvider.get();
}
/**
* Adds a permission to the parent-permissions.
* @param permString The new permission as {@link String}.
*/
public void addToParentPerms(String permString) {
String permStringChopped = permString.replace(".*", "");
String[] seperated = permStringChopped.split("\\.");
String parentPermString = getParentPerm(seperated);
if (parentPermString == null) {
addToRootPermission("*", permStringChopped);
addToRootPermission("*.*", permStringChopped);
return;
}
Permission parentPermission = this.pluginManager.getPermission(parentPermString);
// Creat parent and grandparents
if (parentPermission == null) {
parentPermission = new Permission(parentPermString);
this.pluginManager.addPermission(parentPermission);
this.addToParentPerms(parentPermString);
}
// Create actual perm.
Permission actualPermission = this.pluginManager.getPermission(permString);
// Extra check just to make sure the actual one is added
if (actualPermission == null) {
actualPermission = new Permission(permString);
this.pluginManager.addPermission(actualPermission);
}
if (!parentPermission.getChildren().containsKey(permString)) {
parentPermission.getChildren().put(actualPermission.getName(), true);
this.pluginManager.recalculatePermissionDefaults(parentPermission);
}
}
private void addToRootPermission(String rootPerm, String permStringChopped) {
Permission rootPermission = this.pluginManager.getPermission(rootPerm);
if (rootPermission == null) {
rootPermission = new Permission(rootPerm);
this.pluginManager.addPermission(rootPermission);
}
rootPermission.getChildren().put(permStringChopped + ".*", true);
this.pluginManager.recalculatePermissionDefaults(rootPermission);
}
/**
* If the given permission was 'multiverse.core.tp.self', this would return 'multiverse.core.tp.*'.
*
* @param separatedPermissionString The array of a dot separated perm string.
* @return The dot separated parent permission string.
*/
private static String getParentPerm(String[] separatedPermissionString) {
if (separatedPermissionString.length == 1) {
return null;
}
String returnString = "";
for (int i = 0; i < separatedPermissionString.length - 1; i++) {
returnString += separatedPermissionString[i] + ".";
}
return returnString + "*";
}
/**
* Checks if the given {@link Player} has enough money to enter the specified {@link MVWorld}.
* @param fromWorld The {@link MVWorld} the player is coming from.
* @param toWorld The {@link MVWorld} the player is going to.
* @param teleporter The teleporter.
* @param teleportee The teleportee.
* @param pay If the player has to pay the money.
* @return True if the player can enter the world.
*/
public boolean playerHasMoneyToEnter(MVWorld fromWorld, MVWorld toWorld, CommandSender teleporter, Player teleportee, boolean pay) {
Player teleporterPlayer;
if (config.getTeleportIntercept()) {
if (teleporter instanceof ConsoleCommandSender) {
return true;
}
if (teleporter == null) {
teleporter = teleportee;
}
if (!(teleporter instanceof Player)) {
return false;
}
teleporterPlayer = (Player) teleporter;
} else {
if (teleporter instanceof Player) {
teleporterPlayer = (Player) teleporter;
} else {
teleporterPlayer = null;
}
// Old-style!
if (teleporterPlayer == null) {
return true;
}
}
// If the toWorld isn't controlled by MV,
// We don't care.
if (toWorld == null) {
return true;
}
// Only check payments if it's a different world:
if (!toWorld.equals(fromWorld)) {
final double price = toWorld.getPrice();
// Don't bother checking economy stuff if it doesn't even cost to enter.
if (price == 0D) {
return true;
}
// If the player does not have to pay, return now.
if (this.getMVPerms().hasPermission(teleporter, toWorld.getExemptPermission().getName(), true)) {
return true;
}
final Material currency = toWorld.getCurrency();
final String formattedAmount = economist.formatPrice(price, currency);
if (economist.isPlayerWealthyEnough(teleporterPlayer, price, currency)) {
if (pay) {
if (price < 0D) {
economist.deposit(teleporterPlayer, -price, currency);
} else {
economist.withdraw(teleporterPlayer, price, currency);
}
sendTeleportPaymentMessage(economist, teleporterPlayer, teleportee, toWorld.getColoredWorldString(), price, currency);
}
} else {
if (teleportee.equals(teleporter)) {
teleporterPlayer.sendMessage(economist.getNSFMessage(currency,
"You need " + formattedAmount + " to enter " + toWorld.getColoredWorldString()));
} else {
teleporterPlayer.sendMessage(economist.getNSFMessage(currency,
"You need " + formattedAmount + " to send " + teleportee.getName() + " to " + toWorld.getColoredWorldString()));
}
return false;
}
}
return true;
}
private void sendTeleportPaymentMessage (MVEconomist economist, Player teleporterPlayer, Player teleportee, String toWorld, double price, Material currency) {
price = Math.abs(price);
if (teleporterPlayer.equals(teleportee)) {
teleporterPlayer.sendMessage("You were " + (price > 0D ? "charged " : "given ") + economist.formatPrice(price, currency) + " for teleporting to " + toWorld);
} else {
teleporterPlayer.sendMessage("You were " + (price > 0D ? "charged " : "given ") + economist.formatPrice(price, currency) + " for teleporting " + teleportee.getName() + " to " + toWorld);
}
}
/**
* Checks to see if player can go to a world given their current status.
* <p>
* The return is a little backwards, and will return a value safe for event.setCancelled.
*
* @param fromWorld The MultiverseWorld they are in.
* @param toWorld The MultiverseWorld they want to go to.
* @param teleporter The CommandSender that wants to send someone somewhere. If null,
* will be given the same value as teleportee.
* @param teleportee The player going somewhere.
* @return True if they can't go to the world, False if they can.
*/
public boolean playerCanGoFromTo(MVWorld fromWorld, MVWorld toWorld, CommandSender teleporter, Player teleportee) {
Logging.finest("Checking '" + teleporter + "' can send '" + teleportee + "' somewhere");
Player teleporterPlayer;
if (config.getTeleportIntercept()) {
// The console can send anyone anywhere
if (teleporter instanceof ConsoleCommandSender) {
return true;
}
// Make sure we have a teleporter of some kind, even if it's inferred to be the teleportee
if (teleporter == null) {
teleporter = teleportee;
}
// Now make sure we can cast the teleporter to a player, 'cause I'm tired of console things now
if (!(teleporter instanceof Player)) {
return false;
}
teleporterPlayer = (Player) teleporter;
} else {
if (teleporter instanceof Player) {
teleporterPlayer = (Player) teleporter;
} else {
teleporterPlayer = null;
}
// Old-style!
if (teleporterPlayer == null) {
return true;
}
}
// Actual checks
if (toWorld != null) {
if (!this.getMVPerms().canEnterWorld(teleporterPlayer, toWorld)) {
if (teleportee.equals(teleporter)) {
teleporter.sendMessage("You don't have access to go here...");
} else {
teleporter.sendMessage("You can't send " + teleportee.getName() + " here...");
}
return false;
}
} else {
// TODO: Determine if this value is false because a world didn't exist
// or if it was because a world wasn't imported.
return true;
}
if (fromWorld != null) {
if (fromWorld.getWorldBlacklist().contains(toWorld.getName())) {
if (teleportee.equals(teleporter)) {
teleporter.sendMessage("You don't have access to go to " + toWorld.getColoredWorldString() + " from " + fromWorld.getColoredWorldString());
} else {
teleporter.sendMessage("You don't have access to send " + teleportee.getName() + " from "
+ fromWorld.getColoredWorldString() + " to " + toWorld.getColoredWorldString());
}
return false;
}
}
return true;
}
/**
* Checks to see if a player can bypass the player limit.
*
* @param toWorld The world travelling to.
* @param teleporter The player that initiated the teleport.
* @param teleportee The player travelling.
* @return True if they can bypass the player limit.
*/
public boolean playerCanBypassPlayerLimit(MVWorld toWorld, CommandSender teleporter, Player teleportee) {
if (teleporter == null) {
teleporter = teleportee;
}
if (!(teleporter instanceof Player)) {
return true;
}
if (getMVPerms().hasPermission(teleportee, "mv.bypass.playerlimit." + toWorld.getName(), false)) {
return true;
} else {
teleporter.sendMessage("The world " + toWorld.getColoredWorldString() + " is full");
return false;
}
}
/**
* Checks to see if a player should bypass game mode restrictions.
*
* @param toWorld world travelling to.
* @param teleportee player travelling.
* @return True if they should bypass restrictions
*/
public boolean playerCanIgnoreGameModeRestriction(MVWorld toWorld, Player teleportee) {
if (toWorld != null) {
return this.getMVPerms().canIgnoreGameModeRestriction(teleportee, toWorld);
} else {
// TODO: Determine if this value is false because a world didn't exist
// or if it was because a world wasn't imported.
return true;
}
}
}
@@ -1,48 +0,0 @@
package com.onarandombox.MultiverseCore.utils;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import jakarta.inject.Inject;
import org.jvnet.hk2.annotations.Service;
import java.util.concurrent.Callable;
/**
* Wraps calls that could result in exceptions that are not Multiverse's fault.
*/
@Service
public class UnsafeCallWrapper {
private final MVCoreConfig config;
@Inject
public UnsafeCallWrapper(MVCoreConfig configProvider) {
this.config = configProvider;
}
/**
* Wraps calls that could result in exceptions that are not Multiverse's fault.
*
* @param callable The potentially unsafe call.
* @param plugin The plugin that's probably the culprit.
* @param action What MV was attempting to do (error message, format string).
* @param formatArgs The formatting arguments for the error message.
* The exception that was thrown will be appended to these objects.
* @param <T> The type of the return value.
* @return The return value or null if the call failed.
*/
public <T> T wrap(Callable<T> callable, String plugin, String action, Object... formatArgs) {
try {
// We're ready to catch you! JUMP!
return callable.call();
} catch (Throwable t) {
Object[] actualFormatArgs = new Object[formatArgs.length + 1];
System.arraycopy(formatArgs, 0, actualFormatArgs, 0, formatArgs.length);
actualFormatArgs[formatArgs.length] = t;
Logging.warning(action, actualFormatArgs);
Logging.warning("This is a bug in %s, NOT a bug in Multiverse!", plugin);
if (config.getGlobalDebug() >= 1)
t.printStackTrace();
return null;
}
}
}
@@ -1,40 +0,0 @@
package com.onarandombox.MultiverseCore.utils.message;
import co.aikar.commands.ACFUtil;
import co.aikar.commands.CommandIssuer;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.commandtools.PluginLocales;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
final class LocalizedMessage extends Message implements MessageKeyProvider {
private final @NotNull MessageKeyProvider messageKeyProvider;
LocalizedMessage(
@NotNull MessageKeyProvider messageKeyProvider,
@NotNull String message,
@NotNull MessageReplacement... replacements
) {
super(message, replacements);
this.messageKeyProvider = messageKeyProvider;
}
@Override
public MessageKey getMessageKey() {
return messageKeyProvider.getMessageKey();
}
@Override
public @NotNull String formatted(@NotNull PluginLocales locales, @Nullable CommandIssuer commandIssuer) {
Objects.requireNonNull(locales, "locales must not be null");
if (getReplacements().length == 0) {
return raw();
}
return ACFUtil.replaceStrings(locales.getMessage(commandIssuer, getMessageKey()), getReplacements());
}
}
@@ -1,4 +0,0 @@
/**
* This package contains the Metrics class, which is used to collect anonymous data for bstats
*/
package com.onarandombox.MultiverseCore.utils.metrics;
@@ -1,4 +0,0 @@
/**
* This package contains webpaste-utilities.
*/
package com.onarandombox.MultiverseCore.utils.webpaste;
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -1,198 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.world;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.WorldPurger;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Ghast;
import org.bukkit.entity.Golem;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Phantom;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Squid;
import org.jvnet.hk2.annotations.Service;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Utility class that removes animals from worlds that don't belong there.
*/
@Service
public class SimpleWorldPurger implements WorldPurger {
private Class<Entity> ambientClass = null;
public SimpleWorldPurger() {
try {
Class entityClass = Class.forName("org.bukkit.entity.Ambient");
if (Entity.class.isAssignableFrom(entityClass)) {
ambientClass = entityClass;
}
} catch (ClassNotFoundException ignore) { }
}
/**
* {@inheritDoc}
*/
@Override
public void purgeWorlds(List<MVWorld> worlds) {
if (worlds == null || worlds.isEmpty()) {
return;
}
for (MVWorld world : worlds) {
this.purgeWorld(world);
}
}
/**
* {@inheritDoc}
*/
@Override
public void purgeWorld(MVWorld world) {
if (world == null) {
return;
}
ArrayList<String> allMobs = new ArrayList<String>(world.getAnimalList());
allMobs.addAll(world.getMonsterList());
purgeWorld(world, allMobs, !world.canAnimalsSpawn(), !world.canMonstersSpawn());
}
/**
* {@inheritDoc}
*/
@Override
public boolean shouldWeKillThisCreature(MVWorld world, Entity e) {
ArrayList<String> allMobs = new ArrayList<String>(world.getAnimalList());
allMobs.addAll(world.getMonsterList());
return this.shouldWeKillThisCreature(e, allMobs, !world.canAnimalsSpawn(), !world.canMonstersSpawn());
}
/**
* {@inheritDoc}
*/
@Override
public void purgeWorld(MVWorld mvworld, List<String> thingsToKill,
boolean negateAnimals, boolean negateMonsters, CommandSender sender) {
if (mvworld == null) {
return;
}
World world = mvworld.getCBWorld();
if (world == null) {
return;
}
int projectilesKilled = 0;
int entitiesKilled = 0;
boolean specifiedAll = thingsToKill.contains("ALL");
boolean specifiedAnimals = thingsToKill.contains("ANIMALS") || specifiedAll;
boolean specifiedMonsters = thingsToKill.contains("MONSTERS") || specifiedAll;
List<Entity> worldEntities = world.getEntities();
List<LivingEntity> livingEntities = new ArrayList<LivingEntity>(worldEntities.size());
List<Projectile> projectiles = new ArrayList<Projectile>(worldEntities.size());
for (final Entity e : worldEntities) {
if (e instanceof Projectile) {
final Projectile p = (Projectile) e;
if (p.getShooter() != null) {
projectiles.add((Projectile) e);
}
} else if (e instanceof LivingEntity) {
livingEntities.add((LivingEntity) e);
}
}
for (final LivingEntity e : livingEntities) {
if (killDecision(e, thingsToKill, negateAnimals, negateMonsters, specifiedAnimals, specifiedMonsters)) {
final Iterator<Projectile> it = projectiles.iterator();
while (it.hasNext()) {
final Projectile p = it.next();
if (p.getShooter().equals(e)) {
p.remove();
it.remove();
projectilesKilled++;
}
}
e.remove();
entitiesKilled++;
}
}
if (sender != null) {
sender.sendMessage(entitiesKilled + " entities purged from the world '" + world.getName() + "' along with " + projectilesKilled + " projectiles that belonged to them.");
}
}
private boolean killDecision(Entity e, List<String> thingsToKill, boolean negateAnimals,
boolean negateMonsters, boolean specifiedAnimals, boolean specifiedMonsters) {
boolean negate = false;
boolean specified = false;
if (e instanceof Golem || e instanceof Squid || e instanceof Animals
|| (ambientClass != null && ambientClass.isInstance(e))) {
// it's an animal
if (specifiedAnimals && !negateAnimals) {
Logging.finest("Removing an entity because I was told to remove all animals in world %s: %s", e.getWorld().getName(), e);
return true;
}
if (specifiedAnimals)
specified = true;
negate = negateAnimals;
} else if (e instanceof Monster || e instanceof Ghast || e instanceof Slime || e instanceof Phantom) {
// it's a monster
if (specifiedMonsters && !negateMonsters) {
Logging.finest("Removing an entity because I was told to remove all monsters in world %s: %s", e.getWorld().getName(), e);
return true;
}
if (specifiedMonsters)
specified = true;
negate = negateMonsters;
}
for (String s : thingsToKill) {
EntityType type = EntityType.fromName(s);
if (type != null && type.equals(e.getType())) {
specified = true;
if (!negate) {
Logging.finest("Removing an entity because it WAS specified and we are NOT negating in world %s: %s", e.getWorld().getName(), e);
return true;
}
break;
}
}
if (!specified && negate) {
Logging.finest("Removing an entity because it was NOT specified and we ARE negating in world %s: %s", e.getWorld().getName(), e);
return true;
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean shouldWeKillThisCreature(Entity e, List<String> thingsToKill, boolean negateAnimals, boolean negateMonsters) {
boolean specifiedAll = thingsToKill.contains("ALL");
boolean specifiedAnimals = thingsToKill.contains("ANIMALS") || specifiedAll;
boolean specifiedMonsters = thingsToKill.contains("MONSTERS") || specifiedAll;
return this.killDecision(e, thingsToKill, negateAnimals, negateMonsters, specifiedAnimals, specifiedMonsters);
}
/**
* {@inheritDoc}
*/
@Override
public void purgeWorld(MVWorld mvworld, List<String> thingsToKill, boolean negateAnimals, boolean negateMonsters) {
purgeWorld(mvworld, thingsToKill, negateAnimals, negateMonsters, null);
}
}
@@ -1,655 +0,0 @@
package com.onarandombox.MultiverseCore.world;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.onarandombox.MultiverseCore.world.configuration.EntryFee;
import com.onarandombox.MultiverseCore.world.configuration.SpawnLocation;
import com.onarandombox.MultiverseCore.world.configuration.SpawnSettings;
import com.onarandombox.MultiverseCore.world.configuration.WorldPropertyValidator;
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
import com.onarandombox.MultiverseCore.world.configuration.EnglishChatColor;
import com.onarandombox.MultiverseCore.world.configuration.EnglishChatStyle;
import com.onarandombox.MultiverseCore.world.SimpleMVWorld.NullLocation;
import me.main__.util.SerializationConfig.IllegalPropertyValueException;
import me.main__.util.SerializationConfig.Property;
import me.main__.util.SerializationConfig.SerializationConfig;
import me.main__.util.SerializationConfig.Serializor;
import me.main__.util.SerializationConfig.Validator;
import me.main__.util.SerializationConfig.VirtualProperty;
import org.bukkit.ChatColor;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World.Environment;
import org.bukkit.configuration.serialization.SerializableAs;
import org.jetbrains.annotations.Nullable;
/*
* This is a property class, I think we don't need that much javadoc.
* BEGIN CHECKSTYLE-SUPPRESSION: Javadoc
*/
@SerializableAs("MVWorld")
public class WorldProperties extends SerializationConfig {
private static final Map<String, String> PROPERTY_ALIASES;
static {
PROPERTY_ALIASES = new HashMap<String, String>();
PROPERTY_ALIASES.put("curr", "entryfee.currency");
PROPERTY_ALIASES.put("currency", "entryfee.currency");
PROPERTY_ALIASES.put("price", "entryfee.amount");
PROPERTY_ALIASES.put("scaling", "scale");
PROPERTY_ALIASES.put("aliascolor", "color");
PROPERTY_ALIASES.put("heal", "autoHeal");
PROPERTY_ALIASES.put("storm", "allowWeather");
PROPERTY_ALIASES.put("weather", "allowWeather");
PROPERTY_ALIASES.put("spawnmemory", "keepSpawnInMemory");
PROPERTY_ALIASES.put("memory", "keepSpawnInMemory");
PROPERTY_ALIASES.put("mode", "gameMode");
PROPERTY_ALIASES.put("diff", "difficulty");
PROPERTY_ALIASES.put("spawnlocation", "spawn");
PROPERTY_ALIASES.put("limit", "playerLimit");
PROPERTY_ALIASES.put("animals", "spawning.animals.spawn");
PROPERTY_ALIASES.put("monsters", "spawning.monsters.spawn");
PROPERTY_ALIASES.put("animalsrate", "spawning.animals.spawnrate");
PROPERTY_ALIASES.put("monstersrate", "spawning.monsters.spawnrate");
PROPERTY_ALIASES.put("flight", "allowFlight");
PROPERTY_ALIASES.put("fly", "allowFlight");
PROPERTY_ALIASES.put("allowfly", "allowFlight");
}
private final boolean keepSpawnFallback;
public WorldProperties(Map<String, Object> values) {
super(values);
Object keepSpawnObject = values.get("keepSpawnInMemory");
keepSpawnFallback = keepSpawnObject == null || Boolean.parseBoolean(keepSpawnObject.toString());
}
public WorldProperties() {
super();
keepSpawnFallback = true;
}
public WorldProperties(final boolean fixSpawn, final Environment environment) {
super();
if (!fixSpawn) {
this.adjustSpawn = false;
}
setScaling(getDefaultScale(environment));
keepSpawnFallback = true;
}
void setMVWorld(SimpleMVWorld world) {
registerObjectUsing(world);
registerGlobalValidator(new WorldPropertyValidator());
}
/**
* Serializor for the color-property.
*/
private static final class EnumPropertySerializor<T extends Enum<T>> implements Serializor<T, String> {
@Override
public String serialize(T from) {
return from.toString();
}
@Override
public T deserialize(String serialized, Class<T> wanted) throws IllegalPropertyValueException {
try {
return Enum.valueOf(wanted, serialized.toUpperCase());
} catch (IllegalArgumentException e) {
throw new IllegalPropertyValueException(e);
}
}
}
/**
* Serializor for the difficulty-property.
*/
private static final class DifficultyPropertySerializor implements Serializor<Difficulty, String> {
@Override
public String serialize(Difficulty from) {
return from.toString();
}
@Override
public Difficulty deserialize(String serialized, Class<Difficulty> wanted) throws IllegalPropertyValueException {
try {
return Difficulty.getByValue(Integer.parseInt(serialized));
} catch (Exception e) {
}
try {
return Difficulty.valueOf(serialized.toUpperCase());
} catch (Exception e) {
}
throw new IllegalPropertyValueException();
}
}
/**
* Serializor for the gameMode-property.
*/
private static final class GameModePropertySerializor implements Serializor<GameMode, String> {
@Override
public String serialize(GameMode from) {
return from.toString();
}
@Override
public GameMode deserialize(String serialized, Class<GameMode> wanted) throws IllegalPropertyValueException {
try {
return GameMode.getByValue(Integer.parseInt(serialized));
} catch (NumberFormatException nfe) {
}
try {
return GameMode.valueOf(serialized.toUpperCase());
} catch (Exception e) {
}
throw new IllegalPropertyValueException();
}
}
/**
* Serializor for the time-property.
*/
private static final class TimePropertySerializor implements Serializor<Long, String> {
// BEGIN CHECKSTYLE-SUPPRESSION: MagicNumberCheck
private static final String TIME_REGEX = "(\\d\\d?):?(\\d\\d)(a|p)?m?";
private static final Map<String, String> TIME_ALIASES;
static {
Map<String, String> staticTimes = new HashMap<String, String>();
staticTimes.put("morning", "8:00");
staticTimes.put("day", "12:00");
staticTimes.put("noon", "12:00");
staticTimes.put("midnight", "0:00");
staticTimes.put("night", "20:00");
// now set TIME_ALIASES to a "frozen" map
TIME_ALIASES = Collections.unmodifiableMap(staticTimes);
}
@Override
public String serialize(Long from) {
// I'm tired, so they get time in 24 hour for now.
// Someone else can add 12 hr format if they want :P
int hours = (int) ((from / 1000 + 8) % 24);
int minutes = (int) (60 * (from % 1000) / 1000);
return String.format("%d:%02d", hours, minutes);
}
@Override
public Long deserialize(String serialized, Class<Long> wanted) throws IllegalPropertyValueException {
if (TIME_ALIASES.containsKey(serialized.toLowerCase())) {
serialized = TIME_ALIASES.get(serialized.toLowerCase());
}
// Regex that extracts a time in the following formats:
// 11:11pm, 11:11, 23:11, 1111, 1111p, and the aliases at the top of this file.
Pattern pattern = Pattern.compile(TIME_REGEX, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(serialized);
matcher.find();
int hour = 0;
double minute = 0;
int count = matcher.groupCount();
if (count >= 2) {
hour = Integer.parseInt(matcher.group(1));
minute = Integer.parseInt(matcher.group(2));
}
// If there were 4 matches (all, hour, min, am/pm)
if (count == 4) {
// We want 24 hour time for calcs, but if they
// added a p[m], turn it into a 24 hr one.
if (matcher.group(3).equals("p")) {
hour += 12;
}
}
// Translate 24th hour to 0th hour.
if (hour == 24) {
hour = 0;
}
// Clamp the hour
if (hour > 23 || hour < 0) {
throw new IllegalPropertyValueException("Illegal hour!");
}
// Clamp the minute
if (minute > 59 || minute < 0) {
throw new IllegalPropertyValueException("Illegal minute!");
}
// 60 seconds in a minute, time needs to be in hrs * 1000, per
// the bukkit docs.
double totaltime = (hour + (minute / 60.0)) * 1000;
// Somehow there's an 8 hour offset...
totaltime -= 8000;
if (totaltime < 0) {
totaltime = 24000 + totaltime;
}
return (long) totaltime;
}
// END CHECKSTYLE-SUPPRESSION: MagicNumberCheck
}
// --------------------------------------------------------------
// Begin properties
@Property(description = "Sorry, 'hidden' must either be: true or false.")
private volatile boolean hidden;
@Property(description = "Alias must be a valid string.")
private volatile String alias;
@Property(serializor = EnumPropertySerializor.class, description = "Sorry, 'color' must be a valid color-name.")
private volatile EnglishChatColor color;
@Property(serializor = EnumPropertySerializor.class, description = "Sorry, 'style' must be a valid style-name.")
private volatile EnglishChatStyle style;
@Property(description = "Sorry, 'pvp' must either be: true or false.", virtualType = Boolean.class, persistVirtual = true)
volatile VirtualProperty<Boolean> pvp; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property(description = "Scale must be a positive double value. ex: 2.3")
private volatile double scale;
@Property(description = "You must set this to the NAME not alias of a world.")
private volatile String respawnWorld;
@Property(description = "Sorry, this must either be: true or false.")
private volatile boolean allowWeather;
@Property(serializor = DifficultyPropertySerializor.class, virtualType = Difficulty.class, persistVirtual = true,
description = "Difficulty must be set as one of the following: peaceful easy normal hard")
volatile VirtualProperty<Difficulty> difficulty; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property(description = "Sorry, 'animals' must either be: true or false.")
private volatile SpawnSettings spawning;
@Property
volatile EntryFee entryfee;
@Property(description = "Sorry, 'hunger' must either be: true or false.")
private volatile boolean hunger;
@Property(description = "Sorry, 'autoheal' must either be: true or false.")
private volatile boolean autoHeal;
@Property(description = "Sorry, 'adjustspawn' must either be: true or false.")
private volatile boolean adjustSpawn;
@Property(serializor = EnumPropertySerializor.class, description = "Allow portal forming must be NONE, ALL, NETHER or END.")
private volatile AllowedPortalType portalForm;
@Property(serializor = GameModePropertySerializor.class, description = "GameMode must be set as one of the following: survival creative")
private volatile GameMode gameMode;
@Property(description = "Sorry, this must either be: true or false.", virtualType = Boolean.class, persistVirtual = true)
volatile VirtualProperty<Boolean> keepSpawnInMemory; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property
volatile SpawnLocation spawnLocation; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property(virtualType = Location.class,
description = "There is no help available for this variable. Go bug Rigby90 about it.")
volatile VirtualProperty<Location> spawn; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property(description = "Set this to false ONLY if you don't want this world to load itself on server restart.")
private volatile boolean autoLoad;
@Property(description = "If a player dies in this world, shoudld they go to their bed?")
private volatile boolean bedRespawn;
@Property
private volatile List<String> worldBlacklist;
@Property(serializor = TimePropertySerializor.class, virtualType = Long.class,
description = "Set the time to whatever you want! (Will NOT freeze time)")
volatile VirtualProperty<Long> time; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property
volatile Environment environment; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property
volatile long seed; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property
private volatile String generator;
@Property
private volatile int playerLimit;
@Property
private volatile boolean allowFlight;
// End of properties
// --------------------------------------------------------------
void setValidator(String fieldName, Validator validator) {
registerValidator(fieldName, validator); //To change body of overridden methods use File | Settings | File Templates.
}
/**
* {@inheritDoc}
*/
@Override
public void copyValues(SerializationConfig other) {
super.copyValues(other);
}
/**
* This prepares the MVWorld for unloading.
*/
public void cacheVirtualProperties() {
try {
this.buildVPropChanges();
} catch (IllegalStateException e) {
// do nothing
}
}
/**
* {@inheritDoc}
*/
@Override
protected void setDefaults() {
this.hidden = false;
this.alias = new String();
this.color = EnglishChatColor.WHITE;
this.style = EnglishChatStyle.NORMAL;
this.scale = 1D;
this.respawnWorld = new String();
this.allowWeather = true;
this.spawning = new SpawnSettings();
this.entryfee = new EntryFee();
this.hunger = true;
this.autoHeal = true;
this.adjustSpawn = true;
this.portalForm = AllowedPortalType.ALL;
this.gameMode = GameMode.SURVIVAL;
this.spawnLocation = new NullLocation();
this.autoLoad = true;
this.bedRespawn = true;
this.worldBlacklist = new ArrayList<String>();
this.generator = null;
this.playerLimit = -1;
this.allowFlight = true;
}
private static double getDefaultScale(Environment environment) {
if (environment == Environment.NETHER) {
return 8.0; // SUPPRESS CHECKSTYLE: MagicNumberCheck
} else if (environment == Environment.THE_END) {
return 16.0; // SUPPRESS CHECKSTYLE: MagicNumberCheck
}
return 1.0;
}
/**
* getAliases().
* @return The alias-map.
* @see SerializationConfig
*/
protected static Map<String, String> getAliases() {
return PROPERTY_ALIASES;
}
void flushChanges() {
this.flushPendingVPropChanges();
}
public String getAlias() {
return this.alias;
}
public void setAlias(String alias) {
this.setPropertyValueUnchecked("alias", alias);
}
public Environment getEnvironment() {
return this.environment;
}
public void setEnvironment(Environment environment) {
this.setPropertyValueUnchecked("environment", environment);
}
public long getSeed() {
return this.seed;
}
public void setSeed(long seed) {
this.setPropertyValueUnchecked("seed", seed);
}
public String getGenerator() {
return this.generator;
}
public void setGenerator(String generator) {
this.setPropertyValueUnchecked("generator", generator);
}
public int getPlayerLimit() {
return this.playerLimit;
}
public void setPlayerLimit(int limit) {
this.setPropertyValueUnchecked("playerLimit", limit);
}
public boolean canAnimalsSpawn() {
return this.spawning.getAnimalSettings().doSpawn();
}
public void setAllowAnimalSpawn(boolean animals) {
this.setPropertyValueUnchecked("spawning.animals.spawn", animals);
}
public List<String> getAnimalList() {
// These don't fire events at the moment. Should they?
return this.spawning.getAnimalSettings().getExceptions();
}
public boolean canMonstersSpawn() {
return this.spawning.getMonsterSettings().doSpawn();
}
public void setAllowMonsterSpawn(boolean monsters) {
this.setPropertyValueUnchecked("spawning.monsters.spawn", monsters);
}
public int getAnimalSpawnRate() {
return this.spawning.getAnimalSettings().getSpawnRate();
}
public int getMonsterSpawnRate() {
return this.spawning.getMonsterSettings().getSpawnRate();
}
public List<String> getMonsterList() {
// These don't fire events at the moment. Should they?
return this.spawning.getMonsterSettings().getExceptions();
}
public boolean isPVPEnabled() {
return this.pvp.get();
}
public void setPVPMode(boolean pvp) {
this.setPropertyValueUnchecked("pvp", pvp);
}
public boolean isHidden() {
return this.hidden;
}
public void setHidden(boolean hidden) {
this.setPropertyValueUnchecked("hidden", hidden);
}
public List<String> getWorldBlacklist() {
return this.worldBlacklist;
}
public double getScaling() {
return this.scale;
}
public boolean setScaling(double scaling) {
return this.setPropertyValueUnchecked("scale", scaling);
}
public boolean setColor(String aliasColor) {
return this.setPropertyUnchecked("color", aliasColor);
}
public boolean setColor(EnglishChatColor color) {
return this.setPropertyValueUnchecked("color", color);
}
public EnglishChatColor getColor() {
return this.color;
}
public String getRespawnToWorld() {
return this.respawnWorld;
}
public boolean setRespawnToWorld(String respawnToWorld) {
return this.setPropertyValueUnchecked("respawnWorld", respawnToWorld);
}
public Material getCurrency() {
return this.entryfee.getCurrency();
}
public void setCurrency(@Nullable Material currency) {
this.setPropertyValueUnchecked("entryfee.currency", currency);
}
public double getPrice() {
return this.entryfee.getAmount();
}
public void setPrice(double price) {
this.setPropertyValueUnchecked("entryfee.amount", price);
}
public boolean setGameMode(String mode) {
return this.setPropertyUnchecked("gameMode", mode);
}
public boolean setGameMode(GameMode mode) {
return this.setPropertyValueUnchecked("gameMode", mode);
}
public GameMode getGameMode() {
return this.gameMode;
}
public void setEnableWeather(boolean weather) {
this.setPropertyValueUnchecked("allowWeather", weather);
}
public boolean isWeatherEnabled() {
return this.allowWeather;
}
public boolean isKeepingSpawnInMemory() {
if (keepSpawnInMemory == null) {
return keepSpawnFallback;
}
try {
return this.keepSpawnInMemory.get();
} catch (IllegalStateException e) {
return keepSpawnFallback;
}
}
public void setKeepSpawnInMemory(boolean value) {
this.setPropertyValueUnchecked("keepSpawnInMemory", value);
}
public boolean getHunger() {
return this.hunger;
}
public void setHunger(boolean hunger) {
this.setPropertyValueUnchecked("hunger", hunger);
}
public Location getSpawnLocation() {
return this.spawn.get();
}
public void setSpawnLocation(Location l) {
this.setPropertyValueUnchecked("spawn", l);
}
public Difficulty getDifficulty() {
return this.difficulty.get();
}
@Deprecated // SUPPRESS CHECKSTYLE: Deprecated
public boolean setDifficulty(String difficulty) {
return this.setPropertyUnchecked("difficulty", difficulty);
}
public boolean setDifficulty(Difficulty difficulty) {
return this.setPropertyValueUnchecked("difficulty", difficulty);
}
public boolean getAutoHeal() {
return this.autoHeal;
}
public void setAutoHeal(boolean heal) {
this.setPropertyValueUnchecked("autoHeal", heal);
}
public void setAdjustSpawn(boolean adjust) {
this.setPropertyValueUnchecked("adjustSpawn", adjust);
}
public boolean getAdjustSpawn() {
return this.adjustSpawn;
}
public void setAutoLoad(boolean load) {
this.setPropertyValueUnchecked("autoLoad", load);
}
public boolean getAutoLoad() {
return this.autoLoad;
}
public void setBedRespawn(boolean respawn) {
this.setPropertyValueUnchecked("bedRespawn", respawn);
}
public boolean getBedRespawn() {
return this.bedRespawn;
}
public String getAllPropertyNames() {
ChatColor myColor = ChatColor.AQUA;
StringBuilder result = new StringBuilder();
Map<String, Object> serialized = this.serialize();
for (String key : serialized.keySet()) {
result.append(myColor).append(key).append(' ');
myColor = (myColor == ChatColor.AQUA) ? ChatColor.GOLD : ChatColor.AQUA;
}
return result.toString();
}
public String getTime() {
return this.getPropertyUnchecked("time");
}
public boolean setTime(String timeAsString) {
return this.setPropertyUnchecked("time", timeAsString);
}
public AllowedPortalType getAllowedPortals() {
return portalForm;
}
public void allowPortalMaking(AllowedPortalType portalType) {
this.setPropertyValueUnchecked("portalForm", portalType);
}
public EnglishChatStyle getStyle() {
return style;
}
public boolean setStyle(String style) {
return this.setPropertyUnchecked("style", style);
}
public boolean getAllowFlight() {
return this.allowFlight;
}
public void setAllowFlight(final boolean allowFlight) {
this.setPropertyValueUnchecked("allowFlight", allowFlight);
}
}
@@ -1,30 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.world.configuration;
/**
* A enum containing all actions that can be used to modify world-properties.
*/
public enum Action {
/**
* Setting a property.
*/
Set,
/**
* Adding something to a list-property.
*/
Add,
/**
* Removing something from a list-property.
*/
Remove,
/**
* Clearing a list-property.
*/
Clear
}
@@ -1,26 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.world.configuration;
/**
* An enum containing all list-properties.
*/
public enum AddProperties {
/**
* Worlds that people cannot go to from a world.
*/
worldblacklist,
/**
* Animal-exceptions.
*/
animals,
/**
* Monster-exceptions.
*/
monsters
}
@@ -1,95 +0,0 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.world.configuration;
import org.bukkit.ChatColor;
/**
* A regular {@link ChatColor} represented by an english string.
* @see ChatColor
*/
public enum EnglishChatColor {
// BEGIN CHECKSTYLE-SUPPRESSION: JavadocVariable
AQUA(ChatColor.AQUA),
BLACK(ChatColor.BLACK),
BLUE(ChatColor.BLUE),
DARKAQUA(ChatColor.DARK_AQUA),
DARKBLUE(ChatColor.DARK_BLUE),
DARKGRAY(ChatColor.DARK_GRAY),
DARKGREEN(ChatColor.DARK_GREEN),
DARKPURPLE(ChatColor.DARK_PURPLE),
DARKRED(ChatColor.DARK_RED),
GOLD(ChatColor.GOLD),
GRAY(ChatColor.GRAY),
GREEN(ChatColor.GREEN),
LIGHTPURPLE(ChatColor.LIGHT_PURPLE),
RED(ChatColor.RED),
YELLOW(ChatColor.YELLOW),
WHITE(ChatColor.WHITE);
// END CHECKSTYLE-SUPPRESSION: JavadocVariable
private final ChatColor color;
//private final String text;
EnglishChatColor(ChatColor color) {
this.color = color;
}
/**
* Gets the text.
* @return The text.
*/
public String getText() {
return this.name();
}
/**
* Gets the color.
* @return The color as {@link ChatColor}.
*/
public ChatColor getColor() {
return this.color;
}
/**
* Constructs a string containing all available colors.
* @return That {@link String}.
*/
public static String getAllColors() {
String buffer = "";
for (EnglishChatColor c : EnglishChatColor.values()) {
buffer += c.getColor() + c.getText() + " ";
}
return buffer;
}
/**
* Constructs an {@link EnglishChatColor} from a {@link String}.
* @param text The {@link String}.
* @return The {@link EnglishChatColor}.
*/
public static EnglishChatColor fromString(String text) {
if (text != null) {
for (EnglishChatColor c : EnglishChatColor.values()) {
if (text.equalsIgnoreCase(c.name())) {
return c;
}
}
}
return null;
}
/**
* Looks if the given-color name is a valid color.
* @param aliasColor A color-name.
* @return True if the name is a valid color, false if it isn't.
*/
public static boolean isValidAliasColor(String aliasColor) {
return (EnglishChatColor.fromString(aliasColor) != null);
}
}
@@ -1,49 +0,0 @@
package com.onarandombox.MultiverseCore.world.configuration;
import org.bukkit.ChatColor;
/**
* A regular {@link ChatColor} represented by an english string.
* @see ChatColor
*/
public enum EnglishChatStyle {
// BEGIN CHECKSTYLE-SUPPRESSION: JavadocVariable
/** No style. */
NORMAL(null),
MAGIC(ChatColor.MAGIC),
BOLD(ChatColor.BOLD),
STRIKETHROUGH(ChatColor.STRIKETHROUGH),
UNDERLINE(ChatColor.UNDERLINE),
ITALIC(ChatColor.ITALIC);
// END CHECKSTYLE-SUPPRESSION: JavadocVariable
private final ChatColor color;
EnglishChatStyle(ChatColor color) {
this.color = color;
}
/**
* Gets the color.
* @return The color as {@link ChatColor}.
*/
public ChatColor getColor() {
return color;
}
/**
* Constructs an {@link EnglishChatStyle} from a {@link String}.
* @param text The {@link String}.
* @return The {@link EnglishChatStyle}.
*/
public static EnglishChatStyle fromString(String text) {
if (text != null) {
for (EnglishChatStyle c : EnglishChatStyle.values()) {
if (text.equalsIgnoreCase(c.name())) {
return c;
}
}
}
return null;
}
}
@@ -1,89 +0,0 @@
package com.onarandombox.MultiverseCore.world.configuration;
import java.util.Map;
import com.onarandombox.MultiverseCore.utils.MaterialConverter;
import me.main__.util.SerializationConfig.Property;
import me.main__.util.SerializationConfig.SerializationConfig;
import me.main__.util.SerializationConfig.Serializor;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.SerializableAs;
import org.jetbrains.annotations.Nullable;
/**
* Entryfee-settings.
*/
@SerializableAs("MVEntryFee")
public class EntryFee extends SerializationConfig {
@Property
private double amount;
@Property(serializor = EntryFeeCurrencySerializor.class)
@Nullable
private Material currency;
private final Material DISABLED_MATERIAL = Material.AIR;
public EntryFee() {
super();
}
public EntryFee(Map<String, Object> values) {
super(values);
}
/**
* {@inheritDoc}
*/
@Override
protected void setDefaults() {
amount = 0D;
currency = null;
}
/**
* @return the amount
*/
public double getAmount() {
return amount;
}
/**
* @return the currency
*/
@Nullable
public Material getCurrency() {
if (currency == null || currency.equals(DISABLED_MATERIAL)) {
return null;
}
return currency;
}
/**
* Sets the amount.
* @param amount The new value.
*/
public void setAmount(double amount) {
this.amount = amount;
}
/**
* Sets the currency.
* @param currency The new value.
*/
public void setCurrency(@Nullable Material currency) {
this.currency = currency;
}
public static final class EntryFeeCurrencySerializor implements Serializor<Material, Object> {
@Override
public String serialize(Material material) {
return material.toString();
}
@Override
public Material deserialize(Object o, Class<Material> aClass) {
return MaterialConverter.convertTypeString(o.toString());
}
}
}
@@ -1,50 +0,0 @@
package com.onarandombox.MultiverseCore.world.configuration;
import java.util.Map;
import me.main__.util.SerializationConfig.Property;
import me.main__.util.SerializationConfig.SerializationConfig;
import org.bukkit.configuration.serialization.SerializableAs;
/**
* Spawning-Settings.
*/
@SerializableAs("MVSpawnSettings")
public class SpawnSettings extends SerializationConfig {
@Property
private SubSpawnSettings animals;
@Property
private SubSpawnSettings monsters;
public SpawnSettings() {
super();
}
public SpawnSettings(Map<String, Object> values) {
super(values);
}
/**
* {@inheritDoc}
*/
@Override
public void setDefaults() {
animals = new SubSpawnSettings();
monsters = new SubSpawnSettings();
}
/**
* @return the animal-settings
*/
public SubSpawnSettings getAnimalSettings() {
return animals;
}
/**
* @return the monster-settings
*/
public SubSpawnSettings getMonsterSettings() {
return monsters;
}
}
@@ -1,76 +0,0 @@
package com.onarandombox.MultiverseCore.world.configuration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import me.main__.util.SerializationConfig.Property;
import me.main__.util.SerializationConfig.SerializationConfig;
import org.bukkit.configuration.serialization.SerializableAs;
/**
* SpawnSubSettings.
*/
@SerializableAs("MVSpawnSubSettings")
public class SubSpawnSettings extends SerializationConfig {
@Property
private boolean spawn;
@Property
private int spawnrate;
@Property
private List<String> exceptions;
public SubSpawnSettings() {
super();
}
public SubSpawnSettings(Map<String, Object> values) {
super(values);
}
/**
* {@inheritDoc}
*/
@Override
public void setDefaults() {
spawn = true;
exceptions = new ArrayList<String>();
spawnrate = -1;
}
/**
* @return spawn
*/
public boolean doSpawn() {
return spawn;
}
/**
* @param spawn The new value.
*/
public void setSpawn(boolean spawn) {
this.spawn = spawn;
}
/**
* @return The exceptions
*/
public List<String> getExceptions() {
return exceptions;
}
/**
* @param rate The new spawn rate
*/
public void setSpawnRate(int rate) {
this.spawnrate = rate;
}
/**
* @return The spawn rate
*/
public int getSpawnRate() {
return this.spawnrate;
}
}
@@ -1,27 +0,0 @@
package com.onarandombox.MultiverseCore.world.configuration;
import org.bukkit.Bukkit;
import com.onarandombox.MultiverseCore.world.SimpleMVWorld;
import com.onarandombox.MultiverseCore.event.MVWorldPropertyChangeEvent;
import me.main__.util.SerializationConfig.ChangeDeniedException;
import me.main__.util.SerializationConfig.ObjectUsingValidator;
/**
* Validates world-property-changes.
* @param <T> The type of the property that should be validated.
*/
public class WorldPropertyValidator<T> extends ObjectUsingValidator<T, SimpleMVWorld> {
/**
* {@inheritDoc}
*/
@Override
public T validateChange(String property, T newValue, T oldValue, SimpleMVWorld object) throws ChangeDeniedException {
MVWorldPropertyChangeEvent<T> event = new MVWorldPropertyChangeEvent<T>(object, null, property, newValue);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled())
throw new ChangeDeniedException();
return event.getTheNewValue();
}
}
@@ -1,4 +0,0 @@
/**
* This package contains the configuration classes for the worlds.
*/
package com.onarandombox.MultiverseCore.world.configuration;
@@ -1,4 +0,0 @@
/**
* This package contains all the classes that are used to create and manage worlds.
*/
package com.onarandombox.MultiverseCore.world;
@@ -5,38 +5,20 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore;
package org.mvplugins.multiverse.core;
import java.io.File;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.anchor.AnchorManager;
import com.onarandombox.MultiverseCore.api.Destination;
import com.onarandombox.MultiverseCore.api.MVCore;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.PluginLocales;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
import com.onarandombox.MultiverseCore.economy.MVEconomist;
import com.onarandombox.MultiverseCore.inject.InjectableListener;
import com.onarandombox.MultiverseCore.inject.PluginInjection;
import com.onarandombox.MultiverseCore.placeholders.MultiverseCorePlaceholders;
import com.onarandombox.MultiverseCore.utils.TestingMode;
import com.onarandombox.MultiverseCore.utils.metrics.MetricsConfigurator;
import com.onarandombox.MultiverseCore.world.WorldProperties;
import io.vavr.control.Try;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import me.main__.util.SerializationConfig.SerializationConfig;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader;
@@ -47,6 +29,24 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.anchor.AnchorManager;
import org.mvplugins.multiverse.core.api.Destination;
import org.mvplugins.multiverse.core.api.MVCore;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
import org.mvplugins.multiverse.core.commandtools.PluginLocales;
import org.mvplugins.multiverse.core.config.MVCoreConfig;
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
import org.mvplugins.multiverse.core.economy.MVEconomist;
import org.mvplugins.multiverse.core.inject.InjectableListener;
import org.mvplugins.multiverse.core.inject.PluginInjection;
import org.mvplugins.multiverse.core.placeholders.MultiverseCorePlaceholders;
import org.mvplugins.multiverse.core.utils.TestingMode;
import org.mvplugins.multiverse.core.utils.metrics.MetricsConfigurator;
import org.mvplugins.multiverse.core.world.WorldManager;
import org.mvplugins.multiverse.core.world.config.NullLocation;
import org.mvplugins.multiverse.core.world.config.SpawnLocation;
/**
* The implementation of the Multiverse-{@link MVCore}.
*/
@@ -56,9 +56,9 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
private ServiceLocator serviceLocator;
@Inject
private MVCoreConfig config;
private Provider<MVCoreConfig> configProvider;
@Inject
private Provider<MVWorldManager> worldManagerProvider;
private Provider<WorldManager> worldManagerProvider;
@Inject
private Provider<AnchorManager> anchorManagerProvider;
@Inject
@@ -84,15 +84,20 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
@Override
public void onLoad() {
// Create our DataFolder
getDataFolder().mkdirs();
// Setup our Logging
Logging.init(this);
// Create our DataFolder
if (!getDataFolder().exists() && !getDataFolder().mkdirs()) {
Logging.severe("Failed to create data folder!");
getServer().getPluginManager().disablePlugin(this);
return;
}
// Register our config classes
SerializationConfig.registerAll(WorldProperties.class);
SerializationConfig.initLogging(Logging.getLogger());
ConfigurationSerialization.registerClass(NullLocation.class);
ConfigurationSerialization.registerClass(SpawnLocation.class);
}
/**
@@ -103,42 +108,35 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
initializeDependencyInjection();
// Load our configs first as we need them for everything else.
if (config == null || !config.isLoaded()) {
var config = configProvider.get();
if (!config.isLoaded()) {
Logging.severe("Your configs were not loaded.");
Logging.severe("Please check your configs and restart the server.");
this.getServer().getPluginManager().disablePlugin(this);
return;
}
Logging.setShowingConfig(shouldShowConfig());
var worldManager = worldManagerProvider.get();
// Initialize the worlds
worldManagerProvider.get().initAllWorlds().andThenTry(() -> {
// Setup economy here so vault is loaded
loadEconomist();
worldManager.loadWorldsConfig();
worldManager.getDefaultWorldGenerators();
worldManager.loadDefaultWorlds();
worldManager.loadWorlds(true);
// Now set the firstspawnworld (after the worlds are loaded):
worldManager.setFirstSpawnWorld(config.getFirstSpawnLocation());
MVWorld firstSpawnWorld = worldManager.getFirstSpawnWorld();
if (firstSpawnWorld != null) {
config.setFirstSpawnLocation(firstSpawnWorld.getName());
}
//Setup economy here so vault is loaded
this.loadEconomist();
// Init all the other stuff
this.loadAnchors();
this.registerEvents();
this.setUpLocales();
this.registerCommands();
this.registerDestinations();
this.setupMetrics();
this.loadPlaceholderAPIIntegration();
this.saveAllConfigs();
this.logEnableMessage();
// Init all the other stuff
loadAnchors();
registerEvents();
setUpLocales();
registerCommands();
registerDestinations();
setupMetrics();
loadPlaceholderApiIntegration();
saveAllConfigs();
logEnableMessage();
}).onFailure(e -> {
Logging.severe("Failed to multiverse core! Disabling...");
e.printStackTrace();
getServer().getPluginManager().disablePlugin(this);
});
}
/**
@@ -146,7 +144,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
*/
@Override
public void onDisable() {
this.saveAllConfigs();
saveAllConfigs();
shutdownDependencyInjection();
Logging.shutdown();
}
@@ -171,7 +169,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
}
private boolean shouldShowConfig() {
return !config.getSilentStart();
return !configProvider.get().getSilentStart();
}
private void loadEconomist() {
@@ -197,8 +195,8 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
private void registerEvents() {
var pluginManager = getServer().getPluginManager();
Try.run(() -> serviceLocator.getAllServices(InjectableListener.class)
.forEach(listener -> pluginManager.registerEvents(listener, this)))
Try.run(() -> serviceLocator.getAllServices(InjectableListener.class).forEach(
listener -> pluginManager.registerEvents(listener, this)))
.onFailure(e -> {
throw new RuntimeException("Failed to register listeners. Terminating...", e);
});
@@ -220,7 +218,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
}
/**
* Register locales
* Register locales.
*/
private void setUpLocales() {
Try.of(() -> commandManagerProvider.get())
@@ -275,14 +273,14 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
private void logEnableMessage() {
Logging.config("Version %s (API v%s) Enabled - By %s", this.getDescription().getVersion(), PROTOCOL, getAuthors());
if (config.isShowingDonateMessage()) {
if (configProvider.get().isShowingDonateMessage()) {
Logging.config("Help dumptruckman keep this project alive. Become a patron! https://www.patreon.com/dumptruckman");
Logging.config("One time donations are also appreciated: https://www.paypal.me/dumptruckman");
}
}
private void loadPlaceholderAPIIntegration() {
if (config.isRegisterPapiHook()
private void loadPlaceholderApiIntegration() {
if (configProvider.get().isRegisterPapiHook()
&& getServer().getPluginManager().getPlugin("PlaceholderAPI") != null) {
Try.run(() -> serviceLocator.createAndInitialize(MultiverseCorePlaceholders.class))
.onFailure(e -> {
@@ -314,7 +312,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
@Override
public String getAuthors() {
List<String> authorsList = this.getDescription().getAuthors();
if (authorsList.size() == 0) {
if (authorsList.isEmpty()) {
return "";
}
@@ -367,17 +365,18 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
*/
@Override
public boolean saveAllConfigs() {
return config.save()
// TODO: Make this all Try<Void>
return configProvider.get().save().isSuccess()
&& worldManagerProvider.get().saveWorldsConfig()
&& anchorManagerProvider.get().saveAnchors();
}
/**
* Gets the best service from this plugin that implements the given contract or has the given implementation.
*
* @param contractOrImpl The contract or concrete implementation to get the best instance of
* @param qualifiers The set of qualifiers that must match this service definition
* @param qualifiers The set of qualifiers that must match this service definition
* @param <T> The type of the contract to get
* @return An instance of the contract or impl if it is a service and is already instantiated, null otherwise
* @throws MultiException if there was an error during service lookup
*/
@@ -395,16 +394,16 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
* the provided qualifiers.
*
* @param contractOrImpl The contract or concrete implementation to get the best instance of
* @param qualifiers The set of qualifiers that must match this service definition
* @param qualifiers The set of qualifiers that must match this service definition
* @param <T> The type of the contract to get
* @return A list of services implementing this contract or concrete implementation. May not return null, but may
* return an empty list
* return an empty list.
* @throws MultiException if there was an error during service lookup
*/
@NotNull
public <T> List<T> getAllServices(
@NotNull Class<T> contractOrImpl,
Annotation... qualifiers
) throws MultiException {
Annotation... qualifiers) throws MultiException {
var handles = serviceLocator.getAllServiceHandles(contractOrImpl, qualifiers);
return handles.stream()
.filter(ServiceHandle::isActive)
@@ -415,10 +414,10 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
/**
* This is for unit testing ONLY. Do not use this constructor.
*
* @param loader The PluginLoader to use.
* @param loader The PluginLoader to use.
* @param description The Description file to use.
* @param dataFolder The folder that other datafiles can be found in.
* @param file The location of the plugin.
* @param dataFolder The folder that other datafiles can be found in.
* @param file The location of the plugin.
*/
public MultiverseCore(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) {
super(loader, description, dataFolder, file);
@@ -1,10 +1,11 @@
package com.onarandombox.MultiverseCore;
package org.mvplugins.multiverse.core;
import com.onarandombox.MultiverseCore.api.MVCore;
import com.onarandombox.MultiverseCore.inject.binder.JavaPluginBinder;
import org.glassfish.hk2.utilities.binding.ScopedBindingBuilder;
import org.jetbrains.annotations.NotNull;
import org.mvplugins.multiverse.core.api.MVCore;
import org.mvplugins.multiverse.core.inject.binder.JavaPluginBinder;
class MultiverseCorePluginBinder extends JavaPluginBinder<MultiverseCore> {
protected MultiverseCorePluginBinder(@NotNull MultiverseCore plugin) {
@@ -12,7 +13,8 @@ class MultiverseCorePluginBinder extends JavaPluginBinder<MultiverseCore> {
}
@Override
protected ScopedBindingBuilder<MultiverseCore> bindPluginClass(ScopedBindingBuilder<MultiverseCore> bindingBuilder) {
protected ScopedBindingBuilder<MultiverseCore> bindPluginClass(
ScopedBindingBuilder<MultiverseCore> bindingBuilder) {
return super.bindPluginClass(bindingBuilder).to(MVCore.class).to(MultiverseCore.class);
}
}
@@ -5,12 +5,17 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.anchor;
package org.mvplugins.multiverse.core.anchor;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.LocationManipulation;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import jakarta.inject.Inject;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
@@ -20,13 +25,9 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.jvnet.hk2.annotations.Service;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.mvplugins.multiverse.core.MultiverseCore;
import org.mvplugins.multiverse.core.api.LocationManipulation;
import org.mvplugins.multiverse.core.config.MVCoreConfig;
/**
* Manages anchors.
@@ -1,4 +1,4 @@
/**
* this package contains the classes that are used for the anchor system.
*/
package com.onarandombox.MultiverseCore.anchor;
package org.mvplugins.multiverse.core.anchor;
@@ -1,9 +1,10 @@
package com.onarandombox.MultiverseCore.api;
package org.mvplugins.multiverse.core.api;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Vehicle;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Contract;
/**
@@ -37,8 +38,35 @@ public interface BlockSafety {
*/
boolean playerCanSpawnHereSafely(Location l);
/**
* Finds a portal-block next to the specified {@link Location}.
*
* @param location The {@link Location}
* @return The next portal-block's {@link Location}.
*/
Location findPortalBlockNextTo(Location location);
/**
* Gets the next safe location around the given location.
*
* @param location A {@link Location}.
* @return A safe {@link Location}.
*/
@Nullable Location getSafeLocation(Location location);
/**
* Gets the next safe location around the given location.
*
* @param location A {@link Location}.
* @param tolerance The tolerance of how far up and down to search.
* @param radius The radius around given location to search.
* @return A safe {@link Location}.
*/
@Nullable Location getSafeLocation(Location location, int tolerance, int radius);
/**
* Gets a safe bed spawn location OR null if the bed is invalid.
*
* @param l The location of the bead head (block with the pillow on it).
* @return Safe location around the bed or null if no location was found.
*/
@@ -46,6 +74,7 @@ public interface BlockSafety {
/**
* Gets the location of the top block at the specified {@link Location}.
*
* @param l Any {@link Location}.
* @return The {@link Location} of the top-block.
*/
@@ -53,6 +82,7 @@ public interface BlockSafety {
/**
* Gets the location of the top block at the specified {@link Location}.
*
* @param l Any {@link Location}.
* @return The {@link Location} of the top-block.
*/
@@ -60,6 +90,7 @@ public interface BlockSafety {
/**
* Checks if an entity would be on track at the specified {@link Location}.
*
* @param l The {@link Location}.
* @return True if an entity would be on tracks at the specified {@link Location}.
*/
@@ -67,6 +98,7 @@ public interface BlockSafety {
/**
* Checks if the specified {@link Minecart} can spawn safely.
*
* @param cart The {@link Minecart}.
* @return True if the minecart can spawn safely.
*/
@@ -74,6 +106,7 @@ public interface BlockSafety {
/**
* Checks if the specified {@link Vehicle} can spawn safely.
*
* @param vehicle The {@link Vehicle}.
* @return True if the vehicle can spawn safely.
*/
@@ -1,4 +1,4 @@
package com.onarandombox.MultiverseCore.api;
package org.mvplugins.multiverse.core.api;
import java.util.Collection;
@@ -45,14 +45,4 @@ public interface Destination<T extends DestinationInstance> {
* @return True if the SafeTeleporter will be used, false if not.
*/
boolean checkTeleportSafety();
/**
* Returns the teleporter to use for this destination.
*
* <p>By default, Multiverse will automatically use SafeTeleporter. If you want to use a different teleporter, you can
* override this method.</p>
*
* @return The custom teleporter to use for this destination. Return null to use the default teleporter.
*/
@Nullable Teleporter getTeleporter();
}
@@ -1,4 +1,4 @@
package com.onarandombox.MultiverseCore.api;
package org.mvplugins.multiverse.core.api;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
@@ -1,4 +1,4 @@
package com.onarandombox.MultiverseCore.api;
package org.mvplugins.multiverse.core.api;
import org.bukkit.Location;
import org.bukkit.entity.Vehicle;
@@ -1,10 +1,11 @@
package com.onarandombox.MultiverseCore.api;
package org.mvplugins.multiverse.core.api;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import com.onarandombox.MultiverseCore.placeholders.MultiverseCorePlaceholders;
import io.vavr.control.Try;
import org.jvnet.hk2.annotations.Contract;
import org.mvplugins.multiverse.core.configuration.handle.StringPropertyHandle;
import org.mvplugins.multiverse.core.placeholders.MultiverseCorePlaceholders;
@Contract
public interface MVConfig {
@@ -12,7 +13,7 @@ public interface MVConfig {
* Loads the config from disk.
* @return True if the config was loaded successfully.
*/
boolean load();
Try<Void> load();
/**
* Whether the config has been loaded.
@@ -23,33 +24,14 @@ public interface MVConfig {
/**
* Saves the config to disk.
*/
boolean save();
Try<Void> save();
/**
* Gets the nodes for the config.
* Gets the handler for managing config with string names and values.
*
* @return The nodes for the config.
* @return The config handle for string properties.
*/
NodeGroup getNodes();
/**
* Gets a property from the config.
*
* @param name The name of the property.
* @return A {@link Try} with the value of the property, otherwise a {@link Try.Failure} if there is no property by
* that name.
*/
Try<Object> getProperty(String name);
/**
* Sets a property in the config.
*
* @param name The name of the property.
* @param value The value of the property.
* @return An empty {@link Try} if the property was set successfully, otherwise a {@link Try.Failure} with the
* exception explaining why the property could not be set.
*/
Try<Void> setProperty(String name, Object value);
StringPropertyHandle getStringPropertyHandle();
/**
* Sets world access permissions should be enforced.
@@ -125,6 +107,30 @@ public interface MVConfig {
*/
String getFirstSpawnLocation();
/**
* Sets whether join destination should be enabled.
* @param enableJoinDestination The new value
*/
void setEnableJoinDestination(boolean enableJoinDestination);
/**
* Gets enableJoinDestination.
* @return enableJoinDestination
*/
boolean getEnableJoinDestination();
/**
* Sets alwaysSpawnDestination.
* @param alwaysSpawnDestination The new value
*/
void setJoinDestination(String alwaysSpawnDestination);
/**
* Gets alwaysSpawnDestination.
* @return alwaysSpawnLocation
*/
String getJoinDestination();
/**
* Sets whether or not to let Bukkit determine portal search radius on its own or if Multiverse should give input.
*
@@ -5,7 +5,7 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.api;
package org.mvplugins.multiverse.core.api;
/**
* Multiverse 2 Core API
@@ -5,7 +5,7 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.api;
package org.mvplugins.multiverse.core.api;
/**
* This interface is implemented by every official Multiverse-plugin.
@@ -14,7 +14,7 @@ public interface MVPlugin {
/**
* Gets the reference to MultiverseCore.
*
* @return A valid {@link com.onarandombox.MultiverseCore}.
* @return A valid {@link org.mvplugins.multiverse.core.MultiverseCore}.
*/
MVCore getCore();
@@ -2,4 +2,4 @@
* The Multiverse-API, containing lots of interfaces that can be quite useful for other
* plugins when interacting with Multiverse.
*/
package com.onarandombox.MultiverseCore.api;
package org.mvplugins.multiverse.core.api;
@@ -0,0 +1,54 @@
package org.mvplugins.multiverse.core.commands;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import jakarta.inject.Inject;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
import org.mvplugins.multiverse.core.destination.ParsedDestination;
import org.mvplugins.multiverse.core.utils.MVCorei18n;
@Service
@CommandAlias("mv")
class CheckCommand extends MultiverseCommand {
private final DestinationsProvider destinationsProvider;
@Inject
CheckCommand(@NotNull MVCommandManager commandManager, @NotNull DestinationsProvider destinationsProvider) {
super(commandManager);
this.destinationsProvider = destinationsProvider;
}
@Subcommand("check")
@CommandPermission("multiverse.core.check")
@CommandCompletion("@players @destinations|@mvworlds")
@Syntax("<player> <destination>")
@Description("{@@mv-core.check.description}")
void onCheckCommand(
MVCommandIssuer issuer,
@Syntax("<player>")
@Description("{@@mv-core.check.player.description}")
Player player,
@Syntax("<destination>")
@Description("{@@mv-core.check.destination.description}")
ParsedDestination<?> destination) {
issuer.sendInfo(MVCorei18n.CHECK_CHECKING,
"{player}", player.getName(),
"{destination}", destination.toString());
// TODO: More detailed output on permissions required.
// this.destinationsProvider.checkTeleportPermissions(issuer, player, destination);
}
}
@@ -0,0 +1,85 @@
package org.mvplugins.multiverse.core.commands;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.dumptruckman.minecraft.util.Logging;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
import org.mvplugins.multiverse.core.commandtools.flags.CommandFlag;
import org.mvplugins.multiverse.core.commandtools.flags.ParsedCommandFlags;
import org.mvplugins.multiverse.core.utils.MVCorei18n;
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
import org.mvplugins.multiverse.core.world.WorldManager;
import org.mvplugins.multiverse.core.world.options.CloneWorldOptions;
@Service
@CommandAlias("mv")
class CloneCommand extends MultiverseCommand {
private final WorldManager worldManager;
private final CommandFlag RESET_WORLD_CONFIG_FLAG = flag(CommandFlag.builder("--reset-world-config")
.addAlias("-wc")
.build());
private final CommandFlag RESET_GAMERULES_FLAG = flag(CommandFlag.builder("--reset-gamerules")
.addAlias("-gm")
.build());
private final CommandFlag RESET_WORLD_BORDER_FLAG = flag(CommandFlag.builder("--reset-world-border")
.addAlias("-wb")
.build());
@Inject
CloneCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@Subcommand("clone")
@CommandPermission("multiverse.core.clone")
@CommandCompletion("@mvworlds:scope=loaded @empty @flags:groupName=mvclonecommand")
@Syntax("<world> <new world name>")
@Description("{@@mv-core.clone.description}")
void onCloneCommand(
MVCommandIssuer issuer,
@Syntax("<world>")
@Description("{@@mv-core.clone.world.description}")
LoadedMultiverseWorld world,
@Syntax("<new world name>")
@Description("{@@mv-core.clone.newWorld.description}")
String newWorldName,
@Optional
@Syntax(/* TODO */ "")
@Description("{@@mv-core.regen.other.description}")
String[] flags) {
ParsedCommandFlags parsedFlags = parseFlags(flags);
issuer.sendInfo(MVCorei18n.CLONE_CLONING, "{world}", world.getName(), "{newworld}", newWorldName);
CloneWorldOptions cloneWorldOptions = CloneWorldOptions.fromTo(world, newWorldName)
.keepWorldConfig(!parsedFlags.hasFlag(RESET_WORLD_CONFIG_FLAG))
.keepGameRule(!parsedFlags.hasFlag(RESET_GAMERULES_FLAG))
.keepWorldBorder(!parsedFlags.hasFlag(RESET_WORLD_BORDER_FLAG));
worldManager.cloneWorld(cloneWorldOptions)
.onSuccess(newWorld -> {
Logging.fine("World clone success: " + newWorld);
issuer.sendInfo(MVCorei18n.CLONE_SUCCESS, "{world}", newWorld.getName());
}).onFailure(failure -> {
Logging.fine("World clone failure: " + failure);
issuer.sendError(failure.getFailureMessage());
});
}
}
@@ -1,68 +1,66 @@
package com.onarandombox.MultiverseCore.commands;
package org.mvplugins.multiverse.core.commands;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.commandtools.MVCommandIssuer;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.context.MVConfigValue;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.exceptions.MultiverseException;
import io.vavr.control.Option;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
import org.mvplugins.multiverse.core.config.MVCoreConfig;
import org.mvplugins.multiverse.core.exceptions.MultiverseException;
@Service
@CommandAlias("mv")
public class ConfigCommand extends MultiverseCommand {
class ConfigCommand extends MultiverseCommand {
private final MVCoreConfig config;
@Inject
public ConfigCommand(@NotNull MVCommandManager commandManager, @NotNull MVCoreConfig config) {
ConfigCommand(@NotNull MVCommandManager commandManager, @NotNull MVCoreConfig config) {
super(commandManager);
this.config = config;
}
@Subcommand("config")
@CommandPermission("multiverse.core.config")
@CommandCompletion("@mvconfigs")
@Syntax("<name> [new-value]")
@Description("") //TODO
public void onConfigCommand(MVCommandIssuer issuer,
@CommandCompletion("@mvconfigs @mvconfigvalues")
@Syntax("<name> [value]")
@Description("Show or set a config value.")
void onConfigCommand(
MVCommandIssuer issuer,
@Syntax("<name>")
@Description("") //TODO
String name,
@Syntax("<name>")
@Description("The name of the config to set or show.")
String name,
@Optional
@Single
@Syntax("[new-value]")
@Description("") //TODO
MVConfigValue value
) {
@Optional
@Syntax("[value]")
@Description("The value to set the config to. If not specified, the current value will be shown.")
String value) {
if (value == null) {
showConfigValue(issuer, name);
return;
}
updateConfigValue(issuer, name, value.getValue());
updateConfigValue(issuer, name, value);
}
private void showConfigValue(MVCommandIssuer issuer, String name) {
config.getProperty(name)
config.getStringPropertyHandle().getProperty(name)
.onSuccess(value -> issuer.sendMessage(name + "is currently set to " + value))
.onFailure(e -> issuer.sendMessage(e.getMessage()));
}
private void updateConfigValue(MVCommandIssuer issuer, String name, Object value) {
config.setProperty(name, value)
private void updateConfigValue(MVCommandIssuer issuer, String name, String value) {
config.getStringPropertyHandle().setPropertyString(name, value)
.onSuccess(ignore -> {
config.save();
issuer.sendMessage("Successfully set " + name + " to " + value);
@@ -1,29 +1,30 @@
package com.onarandombox.MultiverseCore.commands;
package org.mvplugins.multiverse.core.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
@Service
@CommandAlias("mv")
public class ConfirmCommand extends MultiverseCommand {
class ConfirmCommand extends MultiverseCommand {
@Inject
public ConfirmCommand(@NotNull MVCommandManager commandManager) {
ConfirmCommand(@NotNull MVCommandManager commandManager) {
super(commandManager);
}
@Subcommand("confirm")
@CommandPermission("multiverse.core.confirm")
@Description("{@@mv-core.confirm.description}")
public void onConfirmCommand(@NotNull BukkitCommandIssuer issuer) {
void onConfirmCommand(@NotNull BukkitCommandIssuer issuer) {
this.commandManager.getCommandQueueManager().runQueuedCommand(issuer.getIssuer());
}
}
@@ -0,0 +1,52 @@
package org.mvplugins.multiverse.core.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Flags;
import co.aikar.commands.annotation.Subcommand;
import jakarta.inject.Inject;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.api.LocationManipulation;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
import org.mvplugins.multiverse.core.utils.MVCorei18n;
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
@Service
@CommandAlias("mv")
class CoordinatesCommand extends MultiverseCommand {
private final LocationManipulation locationManipulation;
@Inject
CoordinatesCommand(
@NotNull MVCommandManager commandManager,
@NotNull LocationManipulation locationManipulation) {
super(commandManager);
this.locationManipulation = locationManipulation;
}
@Subcommand("coordinates|coords|coord|co")
@CommandPermission("multiverse.core.coord")
@Description("{@@mv-core.coordinates.description}")
void onCoordinatesCommand(
BukkitCommandIssuer issuer,
@Flags("resolve=issuerOnly")
Player player,
@Flags("resolve=issuerOnly")
LoadedMultiverseWorld world) {
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_TITLE);
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_WORLD, "{world}", world.getName());
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_ALIAS, "{alias}", world.getAlias());
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_WORLDSCALE, "{scale}", String.valueOf(world.getScale()));
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_COORDINATES, "{coordinates}", locationManipulation.strCoords(player.getLocation()));
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_DIRECTION, "{direction}", locationManipulation.getDirection(player.getLocation()));
}
}
@@ -0,0 +1,126 @@
package org.mvplugins.multiverse.core.commands;
import java.util.Collections;
import java.util.Random;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.dumptruckman.minecraft.util.Logging;
import jakarta.inject.Inject;
import org.bukkit.World;
import org.bukkit.WorldType;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
import org.mvplugins.multiverse.core.commandtools.flags.CommandFlag;
import org.mvplugins.multiverse.core.commandtools.flags.CommandValueFlag;
import org.mvplugins.multiverse.core.commandtools.flags.ParsedCommandFlags;
import org.mvplugins.multiverse.core.utils.MVCorei18n;
import org.mvplugins.multiverse.core.world.WorldManager;
import org.mvplugins.multiverse.core.world.generators.GeneratorProvider;
import org.mvplugins.multiverse.core.world.options.CreateWorldOptions;
@Service
@CommandAlias("mv")
class CreateCommand extends MultiverseCommand {
private final WorldManager worldManager;
private GeneratorProvider generatorProvider;
private final CommandValueFlag<String> SEED_FLAG = flag(CommandValueFlag.builder("--seed", String.class)
.addAlias("-s")
.completion(input -> Collections.singleton(String.valueOf(new Random().nextLong())))
.build());
private final CommandValueFlag<String> GENERATOR_FLAG = flag(CommandValueFlag
.builder("--generator", String.class)
.addAlias("-g")
.completion(input -> generatorProvider.suggestGeneratorString(input))
.build());
private final CommandValueFlag<WorldType> WORLD_TYPE_FLAG = flag(CommandValueFlag
.enumBuilder("--world-type", WorldType.class)
.addAlias("-t")
.build());
private final CommandFlag NO_ADJUST_SPAWN_FLAG = flag(CommandFlag.builder("--no-adjust-spawn")
.addAlias("-n")
.build());
private final CommandFlag NO_STRUCTURES_FLAG = flag(CommandFlag.builder("--no-structures")
.addAlias("-a")
.build());
@Inject
CreateCommand(
@NotNull MVCommandManager commandManager,
@NotNull WorldManager worldManager,
@NotNull GeneratorProvider generatorProvider) {
super(commandManager);
this.worldManager = worldManager;
this.generatorProvider = generatorProvider;
}
@Subcommand("create")
@CommandPermission("multiverse.core.create")
@CommandCompletion("@empty @environments @flags:groupName=mvcreatecommand")
@Syntax("<name> <environment> --seed [seed] --generator [generator[:id]] --world-type [worldtype] --adjust-spawn --no-structures")
@Description("{@@mv-core.create.description}")
void onCreateCommand(
MVCommandIssuer issuer,
@Syntax("<name>")
@Description("{@@mv-core.create.name.description}")
String worldName,
@Syntax("<environment>")
@Description("{@@mv-core.create.environment.description}")
World.Environment environment,
@Optional
@Syntax("--seed [seed] --generator [generator[:id]] --world-type [worldtype] --adjust-spawn --no-structures")
@Description("{@@mv-core.create.flags.description}")
String[] flags) {
ParsedCommandFlags parsedFlags = parseFlags(flags);
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES,
"{worldName}", worldName);
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_ENVIRONMENT,
"{environment}", environment.name());
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_SEED,
"{seed}", parsedFlags.flagValue(SEED_FLAG, "RANDOM"));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_WORLDTYPE,
"{worldType}", parsedFlags.flagValue(WORLD_TYPE_FLAG, WorldType.NORMAL).name());
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_ADJUSTSPAWN,
"{adjustSpawn}", String.valueOf(!parsedFlags.hasFlag(NO_ADJUST_SPAWN_FLAG)));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_GENERATOR,
"{generator}", parsedFlags.flagValue(GENERATOR_FLAG, ""));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_STRUCTURES,
"{structures}", String.valueOf(!parsedFlags.hasFlag(NO_STRUCTURES_FLAG)));
issuer.sendInfo(MVCorei18n.CREATE_LOADING);
worldManager.createWorld(CreateWorldOptions.worldName(worldName)
.environment(environment)
.seed(parsedFlags.flagValue(SEED_FLAG))
.worldType(parsedFlags.flagValue(WORLD_TYPE_FLAG, WorldType.NORMAL))
.useSpawnAdjust(!parsedFlags.hasFlag(NO_ADJUST_SPAWN_FLAG))
.generator(parsedFlags.flagValue(GENERATOR_FLAG, ""))
.generateStructures(!parsedFlags.hasFlag(NO_STRUCTURES_FLAG)))
.onSuccess(newWorld -> {
Logging.fine("World create success: " + newWorld);
issuer.sendInfo(MVCorei18n.CREATE_SUCCESS, "{world}", newWorld.getName());
}).onFailure(failure -> {
Logging.fine("World create failure: " + failure);
issuer.sendError(failure.getFailureMessage());
});
}
}
Loaded 100 of 368 files, more files were not shown because too many files have changed in this diff. Show more