Compare commits

..
Author SHA1 Message Date
JRoy eb781a192b Release 2.21.2 2025-08-03 19:21:20 +01:00
Flask BotandMD 16f643a41f New Crowdin updates (#6225)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2025-08-03 18:01:24 +00:00
Josh Roy c01ba4eec4 Bump adventure dependencies (#6243)
Fixes #6215
2025-07-30 19:17:53 +00:00
Josh Roy f4cd1c92e2 Discord: Fix custom bot name requiring show-avatar (#6239)
Fixes #5878. Caused by a regression from
384f63bf92, we were checking for for the
legacy options when we should really be checking if
`mc-to-discord-name-format` is anything other than the bot name.
2025-07-28 05:38:13 +00:00
Josh Roy d002c34fe8 Add version data extraction (#6235)
Will allow me to dynamically fetch the version for the site making it so
we don't have to update it every mc release
2025-07-27 07:10:47 +00:00
Josh Roy ff7c952715 Fix per-player locale for messages with arguments (#6227)
Fixes #6029
2025-07-20 19:01:58 +00:00
Josh Roy 0417624bda Fix local chat spy formatting (#6226)
Fixes #5828
2025-07-20 08:56:46 +00:00
Josh Roy 9ef4fc34c3 Update to Minecraft 1.21.8 (#6224) 2025-07-17 21:55:01 +00:00
Flask BotandMD 73da278b02 New Crowdin updates (#6143)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2025-07-13 14:19:48 +00:00
Josh Roy e04f4888cd Fix inventory behavior with new body/saddle slot (#6218)
There are new slots that are persistent in the player inventory, the
saddle slot + the body slot, ignore them from our inventory
calculations.

Fixes #6216
2025-07-12 14:10:16 +00:00
Josh RoyandMD dfd83cfb0b Fix /tpr on legacy versions (#6212)
Commodore breaks this on legacy likely, use a provider to ensure we use
the old ABI...................i love legacy

Fixes #6211

---------

Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2025-07-12 14:09:07 +00:00
Josh Roy cc25a798fc Fix player commands option not working (#6214)
Fixes regression from 8d44d1ae7e
2025-07-10 06:24:24 +00:00
Josh Roy e39b61447b Fix numerous antibuild bypasses with signs (#6186)
Fix numerous antibuild bypasses when it came to breaking blocks that
signs were attached to

BOY DO WE NEED BALLOON TO CLEAN ALL THIS STUFF UP

Fixes #5784
Fixes #6173
2025-07-09 19:44:44 +00:00
b996a9f143 Fix formatCommand to handle empty args correctly (#6213)
<!--

EssentialsX bug fix submission guide
====================================

NOTE: Failure to fill out this template properly may result in your PR
being
      delayed or ignored without warning.

NOTE: Don't type between any arrows in the template, as this text will
be
hidden. This includes this header block and any other explanation text
      blocks.

Want to discuss your PR before submitting it? Join the EssentialsX
Development
server: https://discord.gg/CUN7qVb


EssentialsX is GPL
------------------

By contributing to EssentialsX, you agree to license your code under the
GNU General Public License version 3, which can be found at the link
below:
https://github.com/EssentialsX/Essentials/blob/2.x/LICENSE


Instructions
------------

If you are submitting a bug fix, please follow the following steps:

1.  Fill out the template in full.
This includes providing screenshots and a link to the original bug
report. If there isn't an existing bug report, we recommend opening a
new
detailed bug report BEFORE opening your PR to fix it, else your PR may
be
      delayed or rejected without warning.
      
      You can open a new bug report by following this link:
      https://github.com/EssentialsX/Essentials/issues/new/choose 

2.  When linking logs or config files, do not attach them to the post!
Copy and paste any logs into https://gist.github.com/, then paste a
link to them in the relevant parts of the template. Do not use Hastebin
      or Pastebin, as this can cause issues with future reviews.
      
DO NOT drag logs directly into this text box, as we cannot read these!

3.  If you are fixing a performance issue, please include a link to a
    Timings and/or profiler report, both before and after your PR.

4.  If you are fixing a visual bug, such as in commands, please include
    screenshots so that we can more easily review the proposed fix.
    (You can drag screenshots into the bottom of the editor.)

-->

### Information

<!--
Replace #nnnn with the number of the original issue. If this PR fixes
multiple issues, you should repeat the phrase "fixes #nnnn" for each
issue.
-->

This PR fixes #nnnn. 

### Details

**Proposed fix:**    
<!-- Type a description of your proposed fix below this line. -->
Allows creating a clickable confirmation button for the clear command
message.
The space prevents the command from being executed properly, as this
tries to run `'/clear '` instead of `'/clear'`.

**Environments tested:**    

<!-- Type the OS you have used below. -->
OS: Linux

<!-- Type the JDK version (from java -version) you have used below. -->
Java version:  21

<!--
Put an "x" inside the boxes for the server software you have tested this
bug fix on. If this feature does not apply to a server, strike through
the server software using ~~strikethrough~~. If you have tested on other
    environments, add a new line with relevant details.
-->
- [X] Most recent Paper version (1.XX.Y, git-Paper-BUILD)
- [ ] CraftBukkit/Spigot/Paper 1.12.2
- [ ] CraftBukkit 1.8.8


**Demonstration:**    
<!--
Below this block, include screenshots/log snippets from before and after
as
necessary. If you have created or used a test case plugin, please link
to a
download of the plugin, source code and exact version used where
possible.
-->

---------

Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-09 18:11:18 +00:00
Josh Roy 3563b41556 Fix command data task (#6207) 2025-07-05 21:54:18 +00:00
Josh Roy ed3c9b83b5 Command + Permission Data Extraction (#6083)
for the new site, we're gonna have our own command and permissions page
and to make this less of a pain, this PR adds a gradle task which will
export that data. the resulting files end up in the root directory under
the generated folder.


gotta figure out how we automatically fetch this for the site, maybe we
make the generated json files part of the jenkins build process?
2025-07-05 21:43:29 +00:00
Josh Roy 6ad737d87a Fix various TPR issues (#6205)
Fixes various issues from the TPR improvements PR

Fixes #6035
2025-07-05 07:17:53 +00:00
Josh Roy 8d44d1ae7e Fix bstats error with unsupported permission plugins (#6190)
Fixes #5225
2025-07-04 15:35:00 +00:00
Josh Roy dae9e3d091 Trim chat messages with shout/question prefix (#6192)
Fixes #5333
2025-07-04 15:33:11 +00:00
Josh Roy 573aae01ee Fix /skull issues on 1.20.4+ (#6188)
Fixes #6124
2025-07-04 15:33:09 +00:00
Josh Roy c43ad269a8 Fix chat url parsing for tlds >3 chars (#6184)
Mojang only looks for urls with 2,3 chars but if we don't block urls
with >3 their regex will still parse the url trimming the extra chars
off the tld *sigh*

Fixes #6156
2025-07-04 15:33:06 +00:00
Josh Roy e3b4e7723f Fix PlaceholderAPI maven repo url (#6204) 2025-07-04 15:33:04 +00:00
Josh Roy 6100cedc58 Fix max nick length with hex color codes (#6185)
Hex color codes convert to the obnoxious md5 format which massively
inflates the character count than what the user entered. Unformat the
nickname before getting the length to remain true to what the user
entered as the command argument.

Fixes #6174
2025-07-04 15:21:57 +00:00
Josh Roy e6b8493749 Fix misleading whois command description (#6187)
Fixes #5616
2025-07-04 15:21:53 +00:00
MD fa4c6b66d5 Add merge queue trigger to PR workflow (#6203) 2025-07-04 15:17:39 +00:00
JRoy 715589c071 Add 1.21.7 Aliases 2025-06-30 08:45:26 -07:00
JRoy 4a06fd1138 Update to Minecraft 1.21.7 2025-06-30 08:45:26 -07:00
Josh Roy 25f2f76302 Update paste link inside of issue template (#6182)
paste.gg is kill
2025-06-28 07:03:27 +01:00
Josh Roy ff1b8b8615 Add 1.21.6 Aliases 2025-06-21 13:55:02 -07:00
Josh Roy 31ea9036cf Move tests to MockBukkit 2025-06-21 13:55:02 -07:00
Josh Roy 2796399268 Add 1.21.6 Mobs 2025-06-21 13:55:02 -07:00
Josh Roy 4057326b4f Update to Minecraft 1.21.6 2025-06-21 13:55:02 -07:00
Josh Roy b44a9b2256 Initial Move to Paper 1.21.6 2025-06-21 13:55:02 -07:00
Ahmed Waleed 4ab3bbca95 [ci skip] Update setup-gradle version (#6165) 2025-06-07 09:19:56 -07:00
Josh Roy f5c06b9676 Fix javadoc publish (#6164)
Netlify now requires a modern node version
2025-06-07 12:10:13 +01:00
Ahmed WaleedandJosh Roy 997f600c15 Update adventure dependencies (#6163)
Fixes issues with clickable chat components on 1.21.5

Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2025-06-05 22:17:44 -07:00
ThiagoROX d42347fb09 Fix sending message during /editsign paste if SignChangeEvent is cancelled (#6136) 2025-05-25 13:27:48 -07:00
Josh Roy e836747244 Prepare for 2.21.2 dev builds (#6128) 2025-05-25 20:35:54 +01:00
JRoy 3d28d82709 Release 2.21.1 2025-05-25 20:24:18 +01:00
MD 3a5c7c44b8 Revert changes to /home and /sethome that break bed interactions (#6151)
This reverts PR #5991 (commit 3fe1495).
2025-05-25 18:05:54 +00:00
Josh Roy aebe851bff Fix double messages when deleting a non-existent home (#6150)
Fixes #6144
2025-05-25 08:12:02 +01:00
Hunh0wandJosh Roy 3fe1495fdb Fix unexpected behavior with essentials.home.bed & essentials.sethome.bed permissions (#5991)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2025-05-24 20:01:58 -07:00
Flask BotandMD 3b0c229e78 New Crowdin updates (#6131)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2025-05-18 08:42:47 +00:00
JasonandMD d137031a0a Improve config comments & ordering (#6108)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>

This PR significantly overhauls the comments of the EssentialsX configuration files, ensuring consistency, clarity, and overall improved grammar (validated by Grammarly and LLMs). There are still a few things that must be completed before this is ready to be merged, but no further significant changes are expected. A couple of options have been moved entirely to make more logical sense, but this will not affect any compatibility.
2025-05-18 08:36:04 +00:00
MD a58db237a4 Update English source strings with fixes from Crowdin (#6140)
Migrate the few typo fixes from Crowdin's English US translation into the source messages.properties file (which is also English US).
2025-05-18 09:28:16 +01:00
_luftwaffleandMD fe430174a1 Fix "heer" typo in messages_en.properties (#6135)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2025-04-29 20:11:11 +00:00
Nassim Jahnke 3f5b12294f Use legacy text for TranslatableException#getMessage (#6134)
Fixes an issue for API consumers getting Adventure in our exception messages.
2025-04-27 19:13:35 +00:00
Flask BotandMD be3e641c62 New Crowdin updates (#6089)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2025-04-19 18:31:22 +00:00
Josh Roy 84552120c1 Fix /spawnmob on < 1.21.5 (#6121)
Fixes #6120
2025-04-05 07:59:29 +01:00
Josh Roy 2bb44386c7 Fix further trade sign validation mismatches (#6116)
can never win with this

fixes #6107
2025-03-31 17:43:27 +00:00
Josh Roy 06c886ca69 Fix /baltop on 1.15.2 and below (#6115)
Fixes #6093
2025-03-30 22:23:45 -04:00
Josh Roy f3a1b2b495 Fix hex colors not working in chat (#6114)
Need to explicitly enable them in our LegacyComponentSerializer.
2025-03-30 20:02:34 -04:00
MD c7ff994d18 Fire GlobalChatEvent even when local chat is disabled (#6113)
This allows EssentialsX Discord to send EssentialsX Chat messages to
Discord when `use-essentials-events: true` is set in the Discord config
while local chat is disabled.

It also allows plugins to hook and modify EssentialsX Chat message
contents, formatting and recipients when local chat is disabled.
2025-03-30 18:04:56 -04:00
Josh Roy f09541cfa6 Update to Minecraft 1.21.5 (#6109) 2025-03-29 22:49:13 +00:00
Josh Roy 0cb387fb05 Fix NPE when unlinking offline players (#6111)
Fixes #6105
2025-03-29 15:43:28 -04:00
Rasmus dabe68701d Add SignTransactionEvent for buy and sell signs (#6071) 2025-03-24 19:51:11 -04:00
William B. 50b696bc07 Adds social spy message type for in EssentialsDiscord (#5620) 2025-03-24 13:54:21 -04:00
Angelillo15 cb6187bbf2 Add option to customize nickname regex filter (#5200) 2025-03-24 16:43:53 +00:00
maxcom1 40540ebb3d Expose IUser#getLastActivityTime to API (#6101) 2025-03-24 16:29:06 +00:00
Josh Roy 46ba679c02 Prepare for 2.21.1 dev builds 2025-03-22 21:15:51 +00:00
Josh Roy 2719a189af Release 2.21.0 2025-03-22 20:52:40 +00:00
Olivia b4a97ab2a9 chore: add issue types to new issues (#6094)
Adds a new [issue
type](https://docs.github.com/en/issues/tracking-your-work-with-issues/configuring-issues/managing-issue-types-in-an-organization)
to new issues. Basically built in labels.
2025-03-19 07:43:07 +00:00
Flask BotandJosh Roy eab220183e New Crowdin updates (#6068)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2025-03-13 14:26:17 +00:00
Josh Roy 43d1e37b8f Fix flight ability preservation between worlds (#6079)
Fixes #6041
2025-03-09 16:13:50 +00:00
Josh Roy 80bdc5269f Fix wrong SpawnerBlockProvider on 1.21+
1.21 Adds a new org.bukkit.spawner.Spawner class as a superclass of CreatureSpawner which now contains the setMaxSpawnDelay method. Change our test to look for the method on any superclasses too.
2025-03-09 10:14:00 +00:00
Josh Roy 90d766df2b Add non-reflection provider for syncCommands
On 1.21.4+ Player#updateCommands has the same logic as CraftServer#updateCommands, so we can just use that.
2025-03-09 10:11:35 +00:00
Josh Roy 5bf158c1d4 Fix negative playtime stat breaking /baltop (#6074)
Unclear how this happens, possibly a division error?

Fixes #6043
2025-03-01 13:59:46 -05:00
Josh Roy 1531cf4146 Fix exception sending a chat with discord module (#6075)
We do not want or need to set the renderer, EssXChat or the server will do that.
2025-03-01 09:16:56 -05:00
Josh Roy b5748eb32f Update various dependencies (#6078)
Mainly Configurate, JDA, and Adventure
2025-03-01 07:21:48 -05:00
JRoy e49021fffe Fix item overflow issue with kits & trade signs 2025-02-27 22:01:43 -05:00
JRoy ba5257c8e6 Fix translation error in EssentialsSign#getItemStack 2025-02-27 22:01:43 -05:00
Flask BotandJosh Roy fe27182ba8 New Crowdin updates (#6037)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2025-02-24 01:58:14 +00:00
Josh Roy 5458241fcd Fix expired mails showing as unread on join (#6063) 2025-02-23 22:10:05 +00:00
Josh Roy bad79b79ac Fix /book command on 1.20+ (#6064) 2025-02-23 22:06:26 +00:00
Josh Roy 1ff24cb634 Use an identity map for Paper chat listener (#6067) 2025-02-23 17:02:31 -05:00
JRoy f5efa26300 Fix per-world flight permissions
With the implementation of #6012, there was no permission check done when we re-add flight to user's changing worlds. This broke servers with per-world flight permissions.
2025-02-23 08:42:10 +00:00
Théo DufreneandJosh Roy 263dab54d0 Fix spawn command sending message before teleportation (#6025)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2025-02-21 22:21:28 -05:00
Hernán Indíbil de la Cruz CalvoandJRoy e3e247dd61 Add discord module support for Paper's chat events (#5908)
Co-authored-by: JRoy <10731363+JRoy@users.noreply.github.com>
2025-02-21 21:00:24 -05:00
Josh Roy 5a839c47bc Fix modifying messages with Paper chat events
Previously, our wrapper for Paper chat events did not account for other plugins modifying the message component during the event lifecycle, this will translate calls between (get/set)Message to and from legacy strings. This further add a barrier hover/click events for now but those never worked with EssXChat installed anyway and will require further refactoring at a later date in order to add support.
2025-02-20 16:41:16 -05:00
Josh Roy 3025ba5c05 Fix NPE when chat messages are canceled 2025-02-20 16:41:16 -05:00
Josh Roy 8313d522dc Add config for use of Paper chat events (#6050)
adds a config option to disable the use of paper chat events while other
plugins learn how to join the 21st century.

re #6048
re #6051
2025-02-19 21:00:46 +00:00
Josh Roy 196a2a19c4 Fix startup issue with potion providers (#6055)
The LegacyPotionMetaProvider was initializing a map with enums that
don't exist on modern versions. Since this was a static variable, this
map got initialized when the test method was called, leading to a
NoSuchFieldError.

Also improved resilience of these provider-type issues again by catching
a Throwable rather than an Exception in the ProviderFactory.

Fixes #6054
2025-02-19 15:58:00 -05:00
MD 69ed07a536 Fix the wrong potion meta provider being used on 1.8.8 (#6047) 2025-02-15 11:30:13 -05:00
Josh Roy cb00783ede Add support for Paper's chat events (#6033)
Fixes #4970
Fixes #5887
2025-02-14 15:14:44 -05:00
Josh Roy 4e6478224c Fix loot tables getting removed with essentials.keepinv (#6036) 2025-02-09 10:24:13 -05:00
Flask BotandJosh Roy fb6edc04c6 New Crowdin updates (#6024)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2025-02-06 14:50:21 +00:00
Josh Roy d232ce4037 Parse MiniMessage in default command usage & descriptions (#6018) 2025-02-05 08:14:09 -05:00
Josh RoyandMD 1a4d75ced7 [AntiBuild] Fix ender crystal breaking on 1.8 (#6009)
Ugly fix but it works for now...

Fixes #4418

---------

Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2025-02-02 14:14:21 +00:00
Josh Roy 42121aa4be Remove deprecated teleport APIs (#6017)
They have been no-op deprecations for a while now
2025-02-02 13:45:07 +00:00
Josh RoyandShane Freeder ea3ea202a7 Fix flight state between world teleports (#6012)
Thanks to @electronicboy for the general fix.

Fixes #4325 for Paper only :)

Co-authored-by: Shane Freeder <theboyetronic@gmail.com>
2025-01-28 14:26:39 -05:00
Flask Bot 62fb6a16d4 New Crowdin updates (#6019)
Fixes #6022.
2025-01-28 19:12:50 +00:00
jquery-packageandJosh Roy e2295c1e1f Add permission node for giving skulls to other players (#6008)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2025-01-24 10:40:55 -05:00
Flask BotandJosh Roy eb6e192d8d New Crowdin updates (#5640)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2025-01-24 10:35:42 -05:00
JRoy b293f2328a Fix adventure error when using color in local chat
We were feeding legacy text into miniToLegacy which logs an annoying message in console
2025-01-24 01:55:00 -05:00
JRoy 22de3d8bab Revert 4219450705
Hotfix is no longer needed as it has been fixed in adventure.
2025-01-24 01:55:00 -05:00
JRoy fe4e388c42 Update adventure versions 2025-01-24 01:55:00 -05:00
Josh Roy 803771e74a Switch to pastes.dev for /ess dump (#6011)
Requires merge of https://github.com/EssentialsX/Website/pull/106
2025-01-17 07:38:54 -05:00
Henning Storck 667b0f7523 Skip upgrading random teleport config when tpr.yml isn't initialized yet (#6003)
If there's no tpr.yml, upgrading the random teleport config will fail
and the plugin cannot be loaded.
2025-01-01 17:03:46 +00:00
Matt Baxter 8e53214b50 Fix paper maven repository URL (#6002) 2024-12-31 23:39:08 -05:00
Josh Roy 5515f9f3f6 Rework the provider system (#5087) 2024-12-31 19:29:23 -05:00
Charles DeLancey f2af9528b0 Add new "world" argument to settpr messages (#5990) 2024-12-09 19:41:53 +00:00
Justin M.andJosh Roy e1091d887d Added sell multipliers (#4770)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2024-12-08 20:08:23 -05:00
JRoy 424816ef51 Add 1.21.4 Items 2024-12-04 02:49:55 -05:00
JRoy baa8258936 Add 1.21.4 Tree Types 2024-12-04 02:49:55 -05:00
JRoy c37064ff74 Add 1.21.4 Mobs 2024-12-04 02:49:55 -05:00
JRoy d58db0dce9 Update to 1.21.4 2024-12-04 02:49:55 -05:00
Josh Roy bc8aa76690 Revert removal of InvalidWorldException (#5984)
Fixes API breakage for people who catch the exception.
2024-12-02 22:14:03 -05:00
Zarkrey d31ff5553e Remove extraneous code in command preprocess event handling 2024-11-30 23:56:54 +00:00
JRoy b560bbdec4 Fix actions permissions on PRs for junit reports 2024-11-27 17:12:47 -05:00
Flowsqy 2a41ea050a Add config options for specific chat type formats 2024-11-27 17:12:47 -05:00
Gibson PilconisandJosh Roy c7cc1b4f93 Fix respawn-at-anchor setting. (#5825)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2024-11-25 03:15:25 +00:00
Ayush DeotareandJosh Roy 57c9edcc0c Add optional requirements for balance top listing (#5394)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2024-11-25 03:06:08 +00:00
KyriakumandJRoy 3f0a412390 Add locale based comma support for /pay (#5962)
Co-authored-by: JRoy <10731363+JRoy@users.noreply.github.com>
2024-11-25 02:51:52 +00:00
Charles DeLanceyandJRoy 9590d4cd75 Add translation key for /alts output (#5595)
Co-authored-by: JRoy <10731363+JRoy@users.noreply.github.com>
2024-11-25 02:28:49 +00:00
Clement RaynaudandJosh Roy f02eeecee8 Add method to get all linked players in DiscordLinkService (#5896)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2024-11-25 02:20:54 +00:00
AjMacandJosh Roy 3203e97a5e Parse /pay modifiers more strictly (#5638)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2024-11-25 02:16:28 +00:00
Charles DeLanceyandJosh Roy bea43e8798 Fix mini message parsing in NumberUtil#displayCurrency (#5921)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2024-11-25 02:11:41 +00:00
int4_tandJosh Roy 1af1565059 Discord: Add start time placeholder for start message (#5686)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2024-11-25 01:45:40 +00:00
YurakaiiandJosh Roy 38e42f9f90 Add argument to /skull to give skull to other player (#5822)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2024-11-24 20:42:04 -05:00
2418a6fb78 Improvements to Random Teleport (#4271)
Co-authored-by: triagonal <10545540+triagonal@users.noreply.github.com>
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2024-11-24 18:07:18 -05:00
Ahmed WaleedandJosh Roy 1778bf5ada Respect per player locale for command descriptions (#5972)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2024-11-24 22:24:03 +00:00
Adrián Oliva Del Río a87760d3ce Add wildcard support for /delhome (#5919) 2024-11-24 01:47:36 +00:00
Josh Roy 2ac37d8dd4 Fix repair sign translation error (#5967)
Fixes #5964
2024-11-10 22:41:29 -05:00
JRoy 0b49421bad Fix typo in build logic 2024-11-09 08:00:08 -05:00
JRoy aa2eca17ef Fix compile errors from Sound no longer being an enum 2024-11-09 08:00:08 -05:00
JRoy fe6b04ed84 Support boat variants on older versions
New versions will need to use the specific entity, as we cannot swap the entity type after it has been spawned
2024-11-09 08:00:08 -05:00
JRoy 2b209a4a2f 1.12.3 Item Changes 2024-11-09 08:00:08 -05:00
JRoy a4a09299e7 1.12.3 Mob Changes 2024-11-09 08:00:08 -05:00
JRoy 4a68758975 Update to 1.12.3 2024-11-09 08:00:08 -05:00
JRoy cb15b467ab Update toolchain 2024-11-09 08:00:08 -05:00
MD f7a8f86850 Update shadow config for Discord module (#5960)
trove4j's artifact name changed and so it was no longer being shaded in
the Discord module.

Fixes #5959.
2024-10-21 13:55:22 -04:00
Josh Roy cd06e737e1 Fix error message during warp sign creation (#5956)
Fixes #5954
2024-10-21 10:36:35 +00:00
Josh Roy a8452b4615 Update JDA (#5958) 2024-10-20 22:18:21 +00:00
Josh Roy 1bede4ae3f Fix confirmClear & confirmPayment messages (#5957) 2024-10-20 18:15:57 -04:00
Josh Roy c80bef9841 Fix recipe message not being translated correctly (#5952)
I truly don't understand how this slipped through the cracks.

Fixes #5943
2024-10-15 11:13:16 +00:00
Josh Roy 9c3e0eb312 Add wind charge to /fireball (#5951)
Closes #5949
2024-10-15 06:56:11 -04:00
MD 6157668a63 Bump PlaceholderAPI dependency to version 2.11.6 (#5936)
Versions older than 2.11.5 are currently missing from the PlaceholderAPI
Maven repo, so we need to bump this for EssentialsX to compile.
2024-09-15 09:11:26 +01:00
JRoy 04518dbbb3 Use a click component for discord link command 2024-09-14 16:35:45 -04:00
JRoy 3e29e04722 Fix kittycannon on old versions 2024-09-14 16:35:45 -04:00
JRoy 9dfa8cf3cb Fix similarWarpExist message not being translated correctly 2024-09-14 16:35:45 -04:00
Slimified b54c8c1774 Parse colors from broadcast world command (#5913)
Make the broadcast world command mimic the behavior of the broadcast
command which correctly parses colors from the broadcast message.

Broadcast World Command Output Before: https://i.imgur.com/aFR6Zzb.png

Broadcast World Command Output After: https://i.imgur.com/qrvb8XD.png
2024-08-25 21:25:14 +00:00
Charles DeLancey f1a5caf98e Fixes wording on CannotRemoveNegativeItems (#5901) 2024-08-11 16:32:41 -04:00
TriassicandJosh Roy 7ae01a03ac Update to Minecraft 1.21.1 (#5900)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2024-08-11 14:48:53 +00:00
Charles DeLanceyandJRoy b763fd3868 Fix removing negative items in /clearinventory (#5899)
Co-authored-by: JRoy <10731363+JRoy@users.noreply.github.com>
2024-08-11 10:43:00 -04:00
Jason Penilla 7b02d22ac7 Fix incompatibility with AlternativeCommandsHandler & Paper API (#5881) 2024-08-01 19:59:37 -04:00
pop4959 8b08a8f2c8 Update placeholder colors for eco give (#5738) 2024-07-23 20:20:12 +00:00
Josh Roy 80c3150e44 Fix trade signs not updating signs (Fixes #5814)
i guess these things are transactional now whatever
2024-07-21 17:48:16 -04:00
282 changed files with 14531 additions and 7402 deletions

No files matched your search

+3 -2
View File
@@ -1,6 +1,7 @@
name: Report bug
description: Report a bug in EssentialsX.
labels: 'bug: unconfirmed'
type: Bug
body:
- type: markdown
attributes:
@@ -31,8 +32,8 @@ body:
- type: input
attributes:
label: Error log (if applicable)
description: If you are reporting a console error, upload any relevant log excerpts to either https://paste.gg or https://gist.github.com, save and the paste the link in this box. If you included those files in the same paste as your startup log, paste the same link here.
placeholder: "Example: https://paste.gg/p/anonymous/109dd6a10a734a3aa430d5a351ea5210"
description: If you are reporting a console error, upload any relevant log excerpts to either https://pastes.dev or https://gist.github.com, save and the paste the link in this box. If you included those files in the same paste as your startup log, paste the same link here.
placeholder: "Example: https://pastes.dev/UYL3ASLsee"
- type: textarea
attributes:
@@ -1,6 +1,7 @@
name: Request a feature
description: Suggest a feature you want to see in EssentialsX!
labels: 'type: enhancement'
type: Feature
body:
- type: markdown
attributes:
+3 -3
View File
@@ -27,7 +27,7 @@ jobs:
java-version: 17
- name: Setup Gradle
uses: gradle/gradle-build-action@v3
uses: gradle/actions/setup-gradle@v4
- name: Build with Gradle
run: |
@@ -35,7 +35,7 @@ jobs:
./gradlew build --stacktrace
- name: Publish JUnit report
uses: mikepenz/action-junit-report@v4
uses: mikepenz/action-junit-report@v5
if: success() || failure() # Run even if the previous step fails
with:
report_paths: '**/build/test-results/test*/TEST-*.xml'
@@ -82,7 +82,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 16
node-version: 22
- name: Download Javadocs
uses: actions/download-artifact@v4
+6 -1
View File
@@ -10,6 +10,11 @@ on:
- 2.x
- mc/*
- dev/*
merge_group:
types: [checks_requested]
permissions:
checks: write
jobs:
build:
@@ -29,7 +34,7 @@ jobs:
java-version: 17
- name: Setup Gradle
uses: gradle/gradle-build-action@v3
uses: gradle/actions/setup-gradle@v4
- name: Build with Gradle
run: |
+43
View File
@@ -0,0 +1,43 @@
name: Command and Permissions Data
on:
push:
branches:
- 2.x
jobs:
data:
name: Generate and Upload
runs-on: ubuntu-latest
steps:
- name: Checkout Git Repo
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: Generate Data
run: |
chmod +x gradlew
./gradlew commandData
./gradlew versionData
- name: Upload Data
uses: ryand56/r2-upload-action@v1
with:
r2-account-id: ${{ secrets.R2_ACCOUNT_ID }}
r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }}
r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }}
r2-bucket: ${{ secrets.R2_BUCKET }}
source-dir: generated
destination-dir: ./
+3
View File
@@ -21,10 +21,13 @@
# Build files
.gradle/
/jars/
generated/
out/
build/
target/
*.class
build-logic/.kotlin/
build-logic/bin/
# Run directory
/run/
+18 -10
View File
@@ -10,25 +10,29 @@ dependencies {
api 'io.papermc:paperlib:1.0.6'
implementation 'org.spongepowered:configurate-yaml:4.1.2'
implementation 'org.checkerframework:checker-qual:3.21.0'
implementation 'org.spongepowered:configurate-yaml:4.2.0'
implementation 'org.checkerframework:checker-qual:3.49.0'
implementation 'nu.studer:java-ordered-properties:1.0.4'
implementation 'net.kyori:adventure-api:4.17.0'
implementation 'net.kyori:adventure-text-minimessage:4.17.0'
implementation 'net.kyori:adventure-platform-bukkit:4.3.3'
implementation 'net.kyori:adventure-api:4.24.0'
implementation 'net.kyori:adventure-text-minimessage:4.24.0'
implementation 'net.kyori:adventure-platform-bukkit:4.4.1'
// Providers
api project(':providers:BaseProviders')
api project(path: ':providers:PaperProvider', configuration: 'shadow')
api(project(':providers:BaseProviders')) {
exclude(module: 'spigot-api')
}
api(project(path: ':providers:PaperProvider', configuration: 'shadow')){
exclude(module: 'paper-api')
}
api(project(':providers:NMSReflectionProvider')) {
exclude group: "org.bukkit", module: "bukkit"
exclude(module: 'bukkit')
}
api(project(':providers:1_8Provider')) {
exclude group: "org.spigotmc", module: "spigot"
exclude(module: 'spigot-api')
}
api(project(':providers:1_12Provider')) {
exclude group: "org.bukkit", module: "bukkit"
exclude(module: 'bukkit')
}
}
@@ -36,6 +40,10 @@ test {
testLogging.showStandardStreams = true
}
tasks.register('versionData', VersionDataTask) {
destination.set(rootProject.layout.projectDirectory.dir("generated").file("version-data.json"))
}
shadowJar {
dependencies {
include (dependency('io.papermc:paperlib'))
@@ -1,5 +1,7 @@
package com.earth2me.essentials;
import java.util.stream.Collectors;
import net.ess3.provider.KnownCommandsProvider;
import org.bukkit.command.Command;
import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.plugin.Plugin;
@@ -31,7 +33,7 @@ public class AlternativeCommandsHandler {
if (plugin.getDescription().getMain().contains("com.earth2me.essentials") || plugin.getDescription().getMain().contains("net.essentialsx")) {
return;
}
for (final Map.Entry<String, Command> entry : getPluginCommands(plugin).entrySet()) {
for (final Map.Entry<String, Command> entry : getPluginCommands(plugin)) {
final String[] commandSplit = entry.getKey().split(":", 2);
final String commandName = commandSplit.length > 1 ? commandSplit[1] : entry.getKey();
final Command command = entry.getValue();
@@ -64,14 +66,23 @@ public class AlternativeCommandsHandler {
}
}
private Map<String, Command> getPluginCommands(Plugin plugin) {
private List<Map.Entry<String, Command>> getPluginCommands(Plugin plugin) {
final Map<String, Command> commands = new HashMap<>();
for (final Map.Entry<String, Command> entry : ess.getKnownCommandsProvider().getKnownCommands().entrySet()) {
for (final Map.Entry<String, Command> entry : ess.provider(KnownCommandsProvider.class).getKnownCommands().entrySet()) {
if (entry.getValue() instanceof PluginIdentifiableCommand && ((PluginIdentifiableCommand) entry.getValue()).getPlugin().equals(plugin)) {
commands.put(entry.getKey(), entry.getValue());
}
}
return commands;
// Try to use non-namespaced commands first if we can, some Commands may not like being registered under a
// different label than their getName() returns, so avoid doing that when we can
return commands.entrySet().stream().sorted((o1, o2) -> {
if (o1.getKey().contains(":") && !o2.getKey().contains(":")) {
return 1;
} else if (!o1.getKey().contains(":") && o2.getKey().contains(":")) {
return -1;
}
return 0;
}).collect(Collectors.toList());
}
public void removePlugin(final Plugin plugin) {
@@ -7,7 +7,6 @@ import com.earth2me.essentials.utils.LocationUtil;
import io.papermc.lib.PaperLib;
import net.ess3.api.IEssentials;
import net.ess3.api.IUser;
import net.ess3.api.InvalidWorldException;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.UserWarpEvent;
import net.ess3.api.events.teleport.PreTeleportEvent;
@@ -424,7 +423,7 @@ public class AsyncTeleport implements IAsyncTeleport {
final Location loc;
try {
loc = ess.getWarps().getWarp(warp);
} catch (final WarpNotFoundException | InvalidWorldException e) {
} catch (final WarpNotFoundException e) {
future.completeExceptionally(e);
return;
}
@@ -59,36 +59,20 @@ import net.ess3.nms.refl.providers.ReflServerStateProvider;
import net.ess3.nms.refl.providers.ReflSpawnEggProvider;
import net.ess3.nms.refl.providers.ReflSpawnerBlockProvider;
import net.ess3.nms.refl.providers.ReflSyncCommandsProvider;
import net.ess3.provider.BannerDataProvider;
import net.ess3.provider.BiomeKeyProvider;
import net.ess3.provider.ContainerProvider;
import net.ess3.provider.DamageEventProvider;
import net.ess3.provider.FormattedCommandAliasProvider;
import net.ess3.provider.InventoryViewProvider;
import net.ess3.provider.ItemUnbreakableProvider;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.MaterialTagProvider;
import net.ess3.provider.PersistentDataProvider;
import net.ess3.provider.PlayerLocaleProvider;
import net.ess3.provider.PotionMetaProvider;
import net.ess3.provider.ProviderListener;
import net.ess3.provider.SerializationProvider;
import net.ess3.provider.ServerStateProvider;
import net.ess3.provider.SignDataProvider;
import net.ess3.provider.SpawnEggProvider;
import net.ess3.provider.SpawnerBlockProvider;
import net.ess3.provider.SpawnerItemProvider;
import net.ess3.provider.SyncCommandsProvider;
import net.ess3.provider.WorldInfoProvider;
import net.ess3.provider.providers.BaseBannerDataProvider;
import net.ess3.provider.providers.BaseInventoryViewProvider;
import net.ess3.provider.providers.BaseLoggerProvider;
import net.ess3.provider.providers.BlockMetaSpawnerItemProvider;
import net.ess3.provider.providers.BukkitMaterialTagProvider;
import net.ess3.provider.providers.BukkitSpawnerBlockProvider;
import net.ess3.provider.providers.FixedHeightWorldInfoProvider;
import net.ess3.provider.providers.FlatSpawnEggProvider;
import net.ess3.provider.providers.LegacyBannerDataProvider;
import net.ess3.provider.providers.LegacyBiomeNameProvider;
import net.ess3.provider.providers.LegacyDamageEventProvider;
import net.ess3.provider.providers.LegacyInventoryViewProvider;
import net.ess3.provider.providers.LegacyItemUnbreakableProvider;
@@ -102,6 +86,7 @@ import net.ess3.provider.providers.ModernPersistentDataProvider;
import net.ess3.provider.providers.ModernPlayerLocaleProvider;
import net.ess3.provider.providers.ModernPotionMetaProvider;
import net.ess3.provider.providers.ModernSignDataProvider;
import net.ess3.provider.providers.ModernSyncCommandsProvider;
import net.ess3.provider.providers.PaperBiomeKeyProvider;
import net.ess3.provider.providers.PaperContainerProvider;
import net.ess3.provider.providers.PaperKnownCommandsProvider;
@@ -109,6 +94,7 @@ import net.ess3.provider.providers.PaperMaterialTagProvider;
import net.ess3.provider.providers.PaperRecipeBookListener;
import net.ess3.provider.providers.PaperSerializationProvider;
import net.ess3.provider.providers.PaperServerStateProvider;
import net.ess3.provider.providers.PaperTickCountProvider;
import net.ess3.provider.providers.PrehistoricPotionMetaProvider;
import net.essentialsx.api.v2.services.BalanceTop;
import net.essentialsx.api.v2.services.mail.MailService;
@@ -134,18 +120,13 @@ import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.inventory.InventoryView;
import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -154,6 +135,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.UUID;
import java.util.function.Predicate;
@@ -170,6 +152,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private final transient TNTExplodeListener tntListener = new TNTExplodeListener();
private final transient Set<String> vanishedPlayers = new LinkedHashSet<>();
private final transient Map<String, IEssentialsCommand> commandMap = new HashMap<>();
private final transient ProviderFactory providerFactory = new ProviderFactory(this);
private transient ISettings settings;
private transient Jails jails;
private transient Warps warps;
@@ -189,28 +172,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private transient I18n i18n;
private transient MetricsWrapper metrics;
private transient EssentialsTimer timer;
private transient SpawnerItemProvider spawnerItemProvider;
private transient SpawnerBlockProvider spawnerBlockProvider;
private transient SpawnEggProvider spawnEggProvider;
private transient PotionMetaProvider potionMetaProvider;
private transient BannerDataProvider bannerDataProvider;
private transient ServerStateProvider serverStateProvider;
private transient ContainerProvider containerProvider;
private transient SerializationProvider serializationProvider;
private transient KnownCommandsProvider knownCommandsProvider;
private transient FormattedCommandAliasProvider formattedCommandAliasProvider;
private transient ProviderListener recipeBookEventProvider;
private transient MaterialTagProvider materialTagProvider;
private transient SyncCommandsProvider syncCommandsProvider;
private transient PersistentDataProvider persistentDataProvider;
private transient ReflOnlineModeProvider onlineModeProvider;
private transient ItemUnbreakableProvider unbreakableProvider;
private transient WorldInfoProvider worldInfoProvider;
private transient PlayerLocaleProvider playerLocaleProvider;
private transient SignDataProvider signDataProvider;
private transient DamageEventProvider damageEventProvider;
private transient BiomeKeyProvider biomeKeyProvider;
private transient InventoryViewProvider inventoryViewProvider;
private transient Kits kits;
private transient RandomTeleport randomTeleport;
private transient UpdateChecker updateChecker;
@@ -220,52 +182,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
EconomyLayers.init();
}
public Essentials() {
}
protected Essentials(final JavaPluginLoader loader, final PluginDescriptionFile description, final File dataFolder, final File file) {
super(loader, description, dataFolder, file);
}
public Essentials(final Server server) {
super(new JavaPluginLoader(server), new PluginDescriptionFile("Essentials", "", "com.earth2me.essentials.Essentials"), null, null);
}
@Override
public ISettings getSettings() {
return settings;
}
public void setupForTesting(final Server server) throws IOException, InvalidDescriptionException {
TESTING = true;
LOGGER = new BaseLoggerProvider(this, BUKKIT_LOGGER);
final File dataFolder = File.createTempFile("essentialstest", "");
if (!dataFolder.delete()) {
throw new IOException();
}
if (!dataFolder.mkdir()) {
throw new IOException();
}
i18n = new I18n(this);
i18n.onEnable();
i18n.updateLocale("en");
Console.setInstance(this);
LOGGER.log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("usingTempFolderForTesting")));
LOGGER.log(Level.INFO, dataFolder.toString());
settings = new Settings(this);
mail = new MailServiceImpl(this);
userMap = new ModernUserMap(this);
balanceTop = new BalanceTopImpl(this);
permissionsHandler = new PermissionsHandler(this, false);
Economy.setEss(this);
confList = new ArrayList<>();
jails = new Jails(this);
registerListeners(server.getPluginManager());
kits = new Kits(this);
bukkitAudience = BukkitAudiences.create(this);
}
@Override
public void onLoad() {
try {
@@ -357,6 +278,10 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
upgrade.convertKits();
execTimer.mark("Kits");
randomTeleport = new RandomTeleport(this);
confList.add(randomTeleport);
execTimer.mark("Init(RandomTeleport)");
upgrade.afterSettings();
execTimer.mark("Upgrade3");
@@ -372,13 +297,6 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
confList.add(itemDb);
execTimer.mark("Init(ItemDB)");
randomTeleport = new RandomTeleport(this);
if (randomTeleport.getPreCache()) {
randomTeleport.cacheRandomLocations(randomTeleport.getCenter(), randomTeleport.getMinRange(), randomTeleport.getMaxRange());
}
confList.add(randomTeleport);
execTimer.mark("Init(RandomTeleport)");
customItemResolver = new CustomItemResolver(this);
try {
itemDb.registerResolver(this, "custom_items", customItemResolver);
@@ -394,53 +312,82 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
execTimer.mark("Init(Jails)");
EconomyLayers.onEnable(this);
execTimer.mark("Init(EconomyLayers)");
//Spawner item provider only uses one but it's here for legacy...
spawnerItemProvider = new BlockMetaSpawnerItemProvider();
// Spawner item provider only uses one, but it's here for legacy...
providerFactory.registerProvider(BlockMetaSpawnerItemProvider.class);
//Spawner block providers
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_12_0_R01)) {
spawnerBlockProvider = new ReflSpawnerBlockProvider();
} else {
spawnerBlockProvider = new BukkitSpawnerBlockProvider();
}
// Spawner block providers
providerFactory.registerProvider(ReflSpawnerBlockProvider.class, BukkitSpawnerBlockProvider.class);
//Spawn Egg Providers
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
spawnEggProvider = new LegacySpawnEggProvider();
} else if (VersionUtil.getServerBukkitVersion().isLowerThanOrEqualTo(VersionUtil.v1_12_2_R01)) {
spawnEggProvider = new ReflSpawnEggProvider();
} else {
spawnEggProvider = new FlatSpawnEggProvider();
}
// Spawn Egg Providers
providerFactory.registerProvider(LegacySpawnEggProvider.class, ReflSpawnEggProvider.class, FlatSpawnEggProvider.class);
//Potion Meta Provider
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_6_R01)) {
potionMetaProvider = new ModernPotionMetaProvider();
} else if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
potionMetaProvider = new PrehistoricPotionMetaProvider();
} else {
potionMetaProvider = new LegacyPotionMetaProvider();
}
providerFactory.registerProvider(PrehistoricPotionMetaProvider.class, LegacyPotionMetaProvider.class, ModernPotionMetaProvider.class);
//Banner Meta Provider
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_6_R01)) {
bannerDataProvider = new BaseBannerDataProvider();
} else {
bannerDataProvider = new LegacyBannerDataProvider();
providerFactory.registerProvider(LegacyBannerDataProvider.class, BaseBannerDataProvider.class);
// Server State Provider
providerFactory.registerProvider(ReflServerStateProvider.class, PaperServerStateProvider.class);
// Container Provider
providerFactory.registerProvider(PaperContainerProvider.class);
// Serialization Provider
providerFactory.registerProvider(PaperSerializationProvider.class);
// Known Commands Provider
providerFactory.registerProvider(ReflKnownCommandsProvider.class, PaperKnownCommandsProvider.class);
// Command Aliases Provider
providerFactory.registerProvider(ReflFormattedCommandAliasProvider.class);
// Material Tag Providers
providerFactory.registerProvider(BukkitMaterialTagProvider.class, PaperMaterialTagProvider.class);
// Sync Commands Provider
providerFactory.registerProvider(ReflSyncCommandsProvider.class, ModernSyncCommandsProvider.class);
// Persistent Data Provider
providerFactory.registerProvider(ReflPersistentDataProvider.class, ModernPersistentDataProvider.class);
// Online Mode Provider
providerFactory.registerProvider(ReflOnlineModeProvider.class);
// Unbreakable Provider
providerFactory.registerProvider(LegacyItemUnbreakableProvider.class, ModernItemUnbreakableProvider.class);
// World Info Provider
providerFactory.registerProvider(FixedHeightWorldInfoProvider.class, ReflDataWorldInfoProvider.class, ModernDataWorldInfoProvider.class);
// Sign Data Provider
providerFactory.registerProvider(ModernSignDataProvider.class);
// Player Locale Provider
providerFactory.registerProvider(ModernPlayerLocaleProvider.class, LegacyPlayerLocaleProvider.class);
// Damage Event Provider
providerFactory.registerProvider(ModernDamageEventProvider.class, LegacyDamageEventProvider.class);
// Inventory View Provider
providerFactory.registerProvider(LegacyInventoryViewProvider.class, BaseInventoryViewProvider.class);
// Biome Name Provider
providerFactory.registerProvider(LegacyBiomeNameProvider.class);
// Biome Key Provider
providerFactory.registerProvider(PaperBiomeKeyProvider.class);
// Tick Count Provider
providerFactory.registerProvider(PaperTickCountProvider.class);
if (!TESTING) {
providerFactory.finalizeRegistration();
}
//Server State Provider
//Container Provider
if (PaperLib.isPaper() && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_15_2_R01)) {
serverStateProvider = new PaperServerStateProvider();
containerProvider = new PaperContainerProvider();
serializationProvider = new PaperSerializationProvider();
} else {
serverStateProvider = new ReflServerStateProvider();
}
//Event Providers
// Event Providers
if (PaperLib.isPaper()) {
try {
Class.forName("com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent");
@@ -449,76 +396,13 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
((Cancellable) event).setCancelled(true);
}
});
if (getSettings().isDebug()) {
LOGGER.log(Level.INFO, "Registered Paper Recipe Book Event Listener");
}
} catch (final ClassNotFoundException ignored) {
}
}
//Known Commands Provider
if (PaperLib.isPaper() && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_11_2_R01)) {
knownCommandsProvider = new PaperKnownCommandsProvider();
} else {
knownCommandsProvider = new ReflKnownCommandsProvider();
}
// Command aliases provider
formattedCommandAliasProvider = new ReflFormattedCommandAliasProvider(PaperLib.isPaper());
// Material Tag Providers
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_13_0_R01)) {
materialTagProvider = PaperLib.isPaper() ? new PaperMaterialTagProvider() : new BukkitMaterialTagProvider();
}
// Sync Commands Provider
syncCommandsProvider = new ReflSyncCommandsProvider();
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_14_4_R01)) {
persistentDataProvider = new ModernPersistentDataProvider(this);
} else {
persistentDataProvider = new ReflPersistentDataProvider(this);
}
onlineModeProvider = new ReflOnlineModeProvider();
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_11_2_R01)) {
unbreakableProvider = new ModernItemUnbreakableProvider();
} else {
unbreakableProvider = new LegacyItemUnbreakableProvider();
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_17_1_R01)) {
worldInfoProvider = new ModernDataWorldInfoProvider();
} else if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_16_5_R01)) {
worldInfoProvider = new ReflDataWorldInfoProvider();
} else {
worldInfoProvider = new FixedHeightWorldInfoProvider();
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_14_4_R01)) {
signDataProvider = new ModernSignDataProvider(this);
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_12_2_R01)) {
playerLocaleProvider = new ModernPlayerLocaleProvider();
} else {
playerLocaleProvider = new LegacyPlayerLocaleProvider();
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_4_R01)) {
damageEventProvider = new ModernDamageEventProvider();
} else {
damageEventProvider = new LegacyDamageEventProvider();
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_21_R01)) {
inventoryViewProvider = new BaseInventoryViewProvider();
} else {
inventoryViewProvider = new LegacyInventoryViewProvider();
}
if (PaperLib.isPaper() && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_19_4_R01)) {
biomeKeyProvider = new PaperBiomeKeyProvider();
}
execTimer.mark("Init(Providers)");
reload();
@@ -539,15 +423,17 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
PermissionsDefaults.registerAllBackDefaults();
PermissionsDefaults.registerAllHatDefaults();
updateChecker = new UpdateChecker(this);
runTaskAsynchronously(() -> {
getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("versionFetching")));
for (final Component component : updateChecker.getVersionMessages(false, true, new CommandSource(this, Bukkit.getConsoleSender()))) {
getLogger().log(getSettings().isUpdateCheckEnabled() ? Level.WARNING : Level.INFO, AdventureUtil.adventureToLegacy(component));
}
});
if (!TESTING) {
updateChecker = new UpdateChecker(this);
runTaskAsynchronously(() -> {
getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("versionFetching")));
for (final Component component : updateChecker.getVersionMessages(false, true, new CommandSource(this, Bukkit.getConsoleSender()))) {
getLogger().log(getSettings().isUpdateCheckEnabled() ? Level.WARNING : Level.INFO, AdventureUtil.adventureToLegacy(component));
}
});
metrics = new MetricsWrapper(this, 858, true);
metrics = new MetricsWrapper(this, 858, true);
}
execTimer.mark("Init(External)");
@@ -561,7 +447,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
handleCrash(ex);
throw ex;
}
getBackup().setPendingShutdown(false);
if (!TESTING) {
getBackup().setPendingShutdown(false);
}
}
// Returns our provider logger if available
@@ -622,13 +510,26 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
jails.resetListener();
}
@Override
public ProviderFactory getProviders() {
return providerFactory;
}
@Override
public void onDisable() {
final boolean stopping = getServerStateProvider().isStopping();
if (bukkitAudience != null) {
bukkitAudience.close();
}
final boolean stopping = TESTING || provider(ServerStateProvider.class).isStopping();
if (!stopping) {
LOGGER.log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("serverReloading")));
}
getBackup().setPendingShutdown(true);
if (!TESTING) {
getBackup().setPendingShutdown(true);
}
for (final User user : getOnlineUsers()) {
if (user.isVanished()) {
user.setVanished(false);
@@ -645,7 +546,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
}
cleanupOpenInventories();
if (getBackup().getTaskLock() != null && !getBackup().getTaskLock().isDone()) {
if (!TESTING && getBackup().getTaskLock() != null && !getBackup().getTaskLock().isDone()) {
LOGGER.log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("backupInProgress")));
getBackup().getTaskLock().join();
}
@@ -656,9 +557,12 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
backup.stopTask();
}
this.getPermissionsHandler().unregisterContexts();
if (!TESTING) {
this.getPermissionsHandler().unregisterContexts();
}
Economy.setEss(null);
AdventureUtil.setEss(null);
Trade.closeLog();
getUsers().shutdown();
@@ -683,8 +587,8 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
for (final String commandName : this.getDescription().getCommands().keySet()) {
final Command command = this.getCommand(commandName);
if (command != null) {
command.setDescription(tlLiteral(commandName + "CommandDescription"));
command.setUsage(tlLiteral(commandName + "CommandUsage"));
command.setDescription(AdventureUtil.miniToLegacy(tlLiteral(commandName + "CommandDescription")));
command.setUsage(AdventureUtil.miniToLegacy(tlLiteral(commandName + "CommandUsage")));
}
}
@@ -745,11 +649,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
// Check for disabled commands
if (getSettings().isCommandDisabled(commandLabel)) {
if (getKnownCommandsProvider().getKnownCommands().containsKey(commandLabel)) {
final Command newCmd = getKnownCommandsProvider().getKnownCommands().get(commandLabel);
if (!(newCmd instanceof PluginIdentifiableCommand) || ((PluginIdentifiableCommand) newCmd).getPlugin() != this) {
return newCmd.tabComplete(cSender, commandLabel, args);
}
final Command newCmd = provider(KnownCommandsProvider.class).getKnownCommands().get(commandLabel);
if (newCmd != null && (!(newCmd instanceof PluginIdentifiableCommand) || ((PluginIdentifiableCommand) newCmd).getPlugin() != this)) {
return newCmd.tabComplete(cSender, commandLabel, args);
}
return Collections.emptyList();
}
@@ -812,7 +714,8 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
} catch (final Exception ex) {
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
if (cSender instanceof Player) {
cSender.sendMessage(tlLocale(I18n.getLocale(getPlayerLocaleProvider().getLocale((Player) cSender)), "internalError"));
final PlayerLocaleProvider localeProvider = provider(PlayerLocaleProvider.class);
getBukkitAudience().sender(cSender).sendMessage(AdventureUtil.miniMessage().deserialize(tlLocale(I18n.getLocale(localeProvider.getLocale((Player) cSender)), "internalError")));
} else {
cSender.sendMessage(tlLiteral("internalError"));
}
@@ -855,11 +758,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
// Check for disabled commands
if (getSettings().isCommandDisabled(commandLabel)) {
if (getKnownCommandsProvider().getKnownCommands().containsKey(commandLabel)) {
final Command newCmd = getKnownCommandsProvider().getKnownCommands().get(commandLabel);
if (!(newCmd instanceof PluginIdentifiableCommand) || !isEssentialsPlugin(((PluginIdentifiableCommand) newCmd).getPlugin())) {
return newCmd.execute(cSender, commandLabel, args);
}
final Command newCmd = provider(KnownCommandsProvider.class).getKnownCommands().get(commandLabel);
if (newCmd != null && (!(newCmd instanceof PluginIdentifiableCommand) || !isEssentialsPlugin(((PluginIdentifiableCommand) newCmd).getPlugin()))) {
return newCmd.execute(cSender, commandLabel, args);
}
sender.sendTl("commandDisabled", commandLabel);
return true;
@@ -903,7 +804,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
} catch (final NotEnoughArgumentsException ex) {
if (getSettings().isVerboseCommandUsages() && !cmd.getUsageStrings().isEmpty()) {
sender.sendTl("commandHelpLine1", commandLabel);
sender.sendTl("commandHelpLine2", command.getDescription());
String description = command.getDescription();
try {
description = sender.tl(command.getName() + "CommandDescription");
} catch (MissingResourceException ignored) {}
sender.sendTl("commandHelpLine2", description);
sender.sendTl("commandHelpLine3");
for (Map.Entry<String, String> usage : cmd.getUsageStrings().entrySet()) {
sender.sendTl("commandHelpLineUsage", AdventureUtil.parsed(usage.getKey().replace("<command>", commandLabel)), AdventureUtil.parsed(usage.getValue()));
@@ -937,16 +842,17 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
public void cleanupOpenInventories() {
final InventoryViewProvider provider = provider(InventoryViewProvider.class);
for (final User user : getOnlineUsers()) {
if (user.isRecipeSee()) {
final InventoryView view = user.getBase().getOpenInventory();
inventoryViewProvider.getTopInventory(view).clear();
inventoryViewProvider.close(view);
provider.getTopInventory(view).clear();
provider.close(view);
user.setRecipeSee(false);
}
if (user.isInvSee() || user.isEnderSee()) {
inventoryViewProvider.close(user.getBase().getOpenInventory());
provider.close(user.getBase().getOpenInventory());
user.setInvSee(false);
user.setEnderSee(false);
}
@@ -1373,115 +1279,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
return onlineUsers;
}
@Override
public SpawnerItemProvider getSpawnerItemProvider() {
return spawnerItemProvider;
}
@Override
public SpawnerBlockProvider getSpawnerBlockProvider() {
return spawnerBlockProvider;
}
@Override
public SpawnEggProvider getSpawnEggProvider() {
return spawnEggProvider;
}
@Override
public PotionMetaProvider getPotionMetaProvider() {
return potionMetaProvider;
}
@Override
public BannerDataProvider getBannerDataProvider() {
return bannerDataProvider;
}
@Override
public InventoryViewProvider getInventoryViewProvider() {
return inventoryViewProvider;
}
@Override
public CustomItemResolver getCustomItemResolver() {
return customItemResolver;
}
@Override
public ServerStateProvider getServerStateProvider() {
return serverStateProvider;
}
public MaterialTagProvider getMaterialTagProvider() {
return materialTagProvider;
}
@Override
public ContainerProvider getContainerProvider() {
return containerProvider;
}
@Override
public KnownCommandsProvider getKnownCommandsProvider() {
return knownCommandsProvider;
}
@Override
public SerializationProvider getSerializationProvider() {
return serializationProvider;
}
@Override
public FormattedCommandAliasProvider getFormattedCommandAliasProvider() {
return formattedCommandAliasProvider;
}
@Override
public SyncCommandsProvider getSyncCommandsProvider() {
return syncCommandsProvider;
}
@Override
public PersistentDataProvider getPersistentDataProvider() {
return persistentDataProvider;
}
@Override
public ReflOnlineModeProvider getOnlineModeProvider() {
return onlineModeProvider;
}
@Override
public ItemUnbreakableProvider getItemUnbreakableProvider() {
return unbreakableProvider;
}
@Override
public WorldInfoProvider getWorldInfoProvider() {
return worldInfoProvider;
}
@Override
public PlayerLocaleProvider getPlayerLocaleProvider() {
return playerLocaleProvider;
}
@Override
public DamageEventProvider getDamageEventProvider() {
return damageEventProvider;
}
@Override
public BiomeKeyProvider getBiomeKeyProvider() {
return biomeKeyProvider;
}
@Override
public SignDataProvider getSignDataProvider() {
return signDataProvider;
}
@Override
public PluginCommand getPluginCommand(final String cmd) {
return this.getCommand(cmd);
@@ -3,6 +3,8 @@ package com.earth2me.essentials;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.MaterialUtil;
import net.ess3.api.IEssentials;
import net.ess3.provider.PersistentDataProvider;
import net.ess3.provider.SpawnerItemProvider;
import org.bukkit.GameMode;
import org.bukkit.block.BlockState;
import org.bukkit.block.CreatureSpawner;
@@ -26,11 +28,11 @@ public class EssentialsBlockListener implements Listener {
public void onBlockPlace(final BlockPlaceEvent event) {
final ItemStack is = event.getItemInHand();
if (is.getType() == MaterialUtil.SPAWNER && ess.getPersistentDataProvider().getString(is, "convert") != null) {
if (is.getType() == MaterialUtil.SPAWNER && ess.provider(PersistentDataProvider.class).getString(is, "convert") != null) {
final BlockState blockState = event.getBlockPlaced().getState();
if (blockState instanceof CreatureSpawner) {
final CreatureSpawner spawner = (CreatureSpawner) blockState;
final EntityType type = ess.getSpawnerItemProvider().getEntityType(event.getItemInHand());
final EntityType type = ess.provider(SpawnerItemProvider.class).getEntityType(event.getItemInHand());
if (type != null && Mob.fromBukkitType(type) != null) {
if (ess.getUser(event.getPlayer()).isAuthorized("essentials.spawnerconvert." + Mob.fromBukkitType(type).name().toLowerCase(Locale.ENGLISH))) {
spawner.setSpawnedType(type);
@@ -190,7 +190,15 @@ public class EssentialsEntityListener implements Listener {
final User user = ess.getUser(event.getEntity());
if (user.isAuthorized("essentials.keepinv")) {
event.setKeepInventory(true);
event.getDrops().clear();
// We don't do getDrops().clear() here because it would remove any loot tables that were added by other plugins/datapacks.
// Instead, we remove the items from the drops that are in the player's inventory. This way, the loot tables can still drop items.
// This is the same behavior as the vanilla /gamerule keepInventory.
final ItemStack[] inventory = Inventories.getInventory(event.getEntity(), true);
for (final ItemStack item : inventory) {
if (item != null) {
event.getDrops().remove(item);
}
}
final ISettings.KeepInvPolicy vanish = ess.getSettings().getVanishingItemsPolicy();
final ISettings.KeepInvPolicy bind = ess.getSettings().getBindingItemsPolicy();
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_11_2_R01) && (vanish != ISettings.KeepInvPolicy.KEEP || bind != ISettings.KeepInvPolicy.KEEP)) {
@@ -17,6 +17,10 @@ import io.papermc.lib.PaperLib;
import net.ess3.api.IEssentials;
import net.ess3.api.events.AfkStatusChangeEvent;
import net.ess3.provider.CommandSendListenerProvider;
import net.ess3.provider.FormattedCommandAliasProvider;
import net.ess3.provider.InventoryViewProvider;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.TickCountProvider;
import net.ess3.provider.providers.BukkitCommandSendListenerProvider;
import net.ess3.provider.providers.PaperCommandSendListenerProvider;
import net.essentialsx.api.v2.events.AsyncUserDataLoadEvent;
@@ -65,7 +69,6 @@ import java.lang.management.ManagementFactory;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -299,7 +302,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
}
user.setLogoutLocation();
if (user.isRecipeSee()) {
ess.getInventoryViewProvider().getTopInventory(user.getBase().getOpenInventory()).clear();
ess.provider(InventoryViewProvider.class).getTopInventory(user.getBase().getOpenInventory()).clear();
}
final ArrayList<HumanEntity> viewers = new ArrayList<>(user.getBase().getInventory().getViewers());
@@ -586,6 +589,21 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
if (ess.getSettings().isTeleportInvulnerability()) {
user.enableInvulnerabilityAfterTeleport();
}
// Mitigation for https://github.com/EssentialsX/Essentials/issues/4325
final TickCountProvider tickCountProvider = ess.provider(TickCountProvider.class);
if (tickCountProvider != null && ess.getSettings().isWorldChangePreserveFlying() && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_17_R01)) {
if (user.isAuthorized("essentials.fly")) {
//noinspection DataFlowIssue - not real
if (event.getFrom().getWorld() != event.getTo().getWorld() && player.getAllowFlight()) {
// If the player is not flying but has the ability to fly, we set the sign of the tick count to -1
// Later on in the PlayerChangedWorldEvent, we will set the player's flying state to true if the tick count is positive.
// If the tick count is negative, we simply just set the player's flight ability to true.
final int tick = player.isFlying() ? tickCountProvider.getTickCount() : -tickCountProvider.getTickCount();
user.setFlightTick(tick);
}
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
@@ -609,17 +627,17 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) {
final String cmd = event.getMessage().toLowerCase(Locale.ENGLISH).split(" ")[0].replace("/", "").toLowerCase(Locale.ENGLISH);
final String cmd = event.getMessage().split(" ")[0].replace("/", "").toLowerCase(Locale.ENGLISH);
final int argStartIndex = event.getMessage().indexOf(" ");
final String args = argStartIndex == -1 ? "" // No arguments present
: event.getMessage().substring(argStartIndex); // arguments start at argStartIndex; substring from there.
// If the plugin command does not exist, check if it is an alias from commands.yml
if (ess.getServer().getPluginCommand(cmd) == null) {
final Command knownCommand = ess.getKnownCommandsProvider().getKnownCommands().get(cmd);
final Command knownCommand = ess.provider(KnownCommandsProvider.class).getKnownCommands().get(cmd);
if (knownCommand instanceof FormattedCommandAlias) {
final FormattedCommandAlias command = (FormattedCommandAlias) knownCommand;
for (String fullCommand : ess.getFormattedCommandAliasProvider().createCommands(command, event.getPlayer(), args.split(" "))) {
for (String fullCommand : ess.provider(FormattedCommandAliasProvider.class).createCommands(command, event.getPlayer(), args.split(" "))) {
handlePlayerCommandPreprocess(event, fullCommand);
}
return;
@@ -632,7 +650,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
public void handlePlayerCommandPreprocess(final PlayerCommandPreprocessEvent event, final String effectiveCommand) {
final Player player = event.getPlayer();
final String cmd = effectiveCommand.toLowerCase(Locale.ENGLISH).split(" ")[0].replace("/", "").toLowerCase(Locale.ENGLISH);
final String cmd = effectiveCommand.split(" ")[0].replace("/", "").toLowerCase(Locale.ENGLISH);
final PluginCommand pluginCommand = ess.getServer().getPluginCommand(cmd);
if (ess.getSettings().getSocialSpyCommands().contains(cmd) || ess.getSettings().getSocialSpyCommands().contains("*")) {
@@ -705,21 +723,17 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
// If so, no need to check for (and write) new ones.
boolean cooldownFound = false;
// Iterate over a copy of getCommandCooldowns in case of concurrent modifications
for (final Entry<Pattern, Long> entry : new HashMap<>(user.getCommandCooldowns()).entrySet()) {
for (final Entry<Pattern, Long> entry : user.getCommandCooldowns().entrySet()) {
// Remove any expired cooldowns
if (entry.getValue() <= System.currentTimeMillis()) {
user.clearCommandCooldown(entry.getKey());
// Don't break in case there are other command cooldowns left to clear.
} else if (entry.getKey().matcher(fullCommand).matches()) {
// User's current cooldown hasn't expired, inform and terminate cooldown code.
if (entry.getValue() > System.currentTimeMillis()) {
final String commandCooldownTime = DateUtil.formatDateDiff(entry.getValue());
user.sendTl("commandCooldown", commandCooldownTime);
cooldownFound = true;
event.setCancelled(true);
break;
}
final String commandCooldownTime = DateUtil.formatDateDiff(entry.getValue());
user.sendTl("commandCooldown", commandCooldownTime);
cooldownFound = true;
event.setCancelled(true);
}
}
@@ -743,8 +757,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
if (ess.getSettings().isWorldChangeFlyResetEnabled()) {
if (user.getBase().getGameMode() != GameMode.CREATIVE
// COMPAT: String compare for 1.7.10
&& !user.getBase().getGameMode().name().equals("SPECTATOR")
&& user.getBase().getGameMode() != GameMode.SPECTATOR
&& !user.isAuthorized("essentials.fly")) {
user.getBase().setFallDistance(0f);
user.getBase().setAllowFlight(false);
@@ -767,6 +780,16 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
}
}
}
final TickCountProvider tickCountProvider = ess.provider(TickCountProvider.class);
final int flightTick = user.getFlightTick();
if (tickCountProvider != null && Math.abs(flightTick) == tickCountProvider.getTickCount() && user.isAuthorized("essentials.fly")) {
user.getBase().setAllowFlight(true);
if (flightTick > 0) {
user.getBase().setFlying(true);
}
}
user.setFlightTick(-1);
}
@EventHandler(priority = EventPriority.MONITOR)
@@ -897,14 +920,15 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onInventoryClickEvent(final InventoryClickEvent event) {
Player refreshPlayer = null;
final Inventory top = ess.getInventoryViewProvider().getTopInventory(event.getView());
final InventoryViewProvider provider = ess.provider(InventoryViewProvider.class);
final Inventory top = provider.getTopInventory(event.getView());
final InventoryType type = top.getType();
final Inventory clickedInventory;
if (event.getRawSlot() < 0) {
clickedInventory = null;
} else {
clickedInventory = event.getRawSlot() < top.getSize() ? top : ess.getInventoryViewProvider().getBottomInventory(event.getView());
clickedInventory = event.getRawSlot() < top.getSize() ? top : provider.getBottomInventory(event.getView());
}
final User user = ess.getUser((Player) event.getWhoClicked());
@@ -963,7 +987,8 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
@EventHandler(priority = EventPriority.MONITOR)
public void onInventoryCloseEvent(final InventoryCloseEvent event) {
Player refreshPlayer = null;
final Inventory top = ess.getInventoryViewProvider().getTopInventory(event.getView());
final InventoryViewProvider provider = ess.provider(InventoryViewProvider.class);
final Inventory top = provider.getTopInventory(event.getView());
final InventoryType type = top.getType();
if (type == InventoryType.PLAYER) {
final User user = ess.getUser((Player) event.getPlayer());
@@ -977,7 +1002,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
final User user = ess.getUser((Player) event.getPlayer());
if (user.isRecipeSee()) {
user.setRecipeSee(false);
ess.getInventoryViewProvider().getTopInventory(event.getView()).clear();
provider.getTopInventory(event.getView()).clear();
refreshPlayer = user.getBase();
}
} else if (type == InventoryType.CHEST && top.getSize() == 9) {
@@ -3,6 +3,7 @@ package com.earth2me.essentials;
import com.earth2me.essentials.config.ConfigurateUtil;
import com.earth2me.essentials.config.EssentialsConfiguration;
import com.earth2me.essentials.config.EssentialsUserConfiguration;
import com.earth2me.essentials.config.entities.LazyLocation;
import com.earth2me.essentials.craftbukkit.BanLookup;
import com.earth2me.essentials.userstorage.ModernUUIDCache;
import com.earth2me.essentials.utils.AdventureUtil;
@@ -156,6 +157,41 @@ public class EssentialsUpgrade {
ess.getLogger().info("To rerun the conversion type /essentials uuidconvert");
}
public void updateRandomTeleport() {
if (doneFile.getBoolean("updateRandomTeleport", false)) {
return;
}
final EssentialsConfiguration config = ess.getRandomTeleport().getConfig();
if (config.getRootNode() != null) {
final LazyLocation center = config.getLocation("center");
final Location centerLoc = center != null ? center.location() : null;
if (center != null && centerLoc != null) {
final double minRange = config.getDouble("min-range", Double.MIN_VALUE);
final double maxRange = config.getDouble("max-range", Double.MIN_VALUE);
for (final World world : ess.getServer().getWorlds()) {
final String propPrefix = "locations." + world.getName() + ".";
config.setProperty(propPrefix + "center", centerLoc);
if (minRange != Double.MIN_VALUE) {
config.setProperty(propPrefix + "min-range", minRange);
}
if (maxRange != Double.MIN_VALUE) {
config.setProperty(propPrefix + "max-range", maxRange);
}
}
}
config.removeProperty("center");
config.blockingSave();
}
doneFile.setProperty("updateRandomTeleport", true);
doneFile.save();
ess.getLogger().info("Done converting random teleport config.");
}
public void convertMailList() {
if (doneFile.getBoolean("updateUsersMailList", false)) {
return;
@@ -1068,5 +1104,6 @@ public class EssentialsUpgrade {
convertStupidCamelCaseUserdataKeys();
convertMailList();
purgeBrokenNpcAccounts();
updateRandomTeleport();
}
}
@@ -92,7 +92,7 @@ public class I18n implements net.ess3.api.II18n {
if (objects.length == 0) {
return NODOUBLEMARK.matcher(instance.translate(locale, tlKey)).replaceAll("'");
} else {
return instance.format(tlKey, objects);
return instance.format(locale, tlKey, objects);
}
}
@@ -162,10 +162,6 @@ public class I18n implements net.ess3.api.II18n {
}
}
private String format(final String string, final Object... objects) {
return format(currentLocale, string, objects);
}
private String format(final Locale locale, final String string, final Object... objects) {
String format = translate(locale, string);
@@ -281,7 +277,7 @@ public class I18n implements net.ess3.api.II18n {
* Reads .properties files as UTF-8 instead of ISO-8859-1, which is the default on Java 8/below.
* Java 9 fixes this by defaulting to UTF-8 for .properties files.
*/
private static class UTF8PropertiesControl extends ResourceBundle.Control {
private static final class UTF8PropertiesControl extends ResourceBundle.Control {
public ResourceBundle newBundle(final String baseName, final Locale locale, final String format, final ClassLoader loader, final boolean reload) throws IOException {
final String resourceName = toResourceName(toBundleName(baseName, locale), "properties");
ResourceBundle bundle = null;
@@ -8,25 +8,7 @@ import com.earth2me.essentials.commands.PlayerNotFoundException;
import com.earth2me.essentials.perm.PermissionsHandler;
import com.earth2me.essentials.updatecheck.UpdateChecker;
import com.earth2me.essentials.userstorage.IUserMap;
import net.ess3.nms.refl.providers.ReflOnlineModeProvider;
import net.ess3.provider.BannerDataProvider;
import net.ess3.provider.BiomeKeyProvider;
import net.ess3.provider.ContainerProvider;
import net.ess3.provider.DamageEventProvider;
import net.ess3.provider.FormattedCommandAliasProvider;
import net.ess3.provider.InventoryViewProvider;
import net.ess3.provider.ItemUnbreakableProvider;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.MaterialTagProvider;
import net.ess3.provider.PersistentDataProvider;
import net.ess3.provider.PlayerLocaleProvider;
import net.ess3.provider.SerializationProvider;
import net.ess3.provider.ServerStateProvider;
import net.ess3.provider.SignDataProvider;
import net.ess3.provider.SpawnerBlockProvider;
import net.ess3.provider.SpawnerItemProvider;
import net.ess3.provider.SyncCommandsProvider;
import net.ess3.provider.WorldInfoProvider;
import net.ess3.provider.Provider;
import net.essentialsx.api.v2.services.BalanceTop;
import net.essentialsx.api.v2.services.mail.MailService;
import org.bukkit.Server;
@@ -157,43 +139,11 @@ public interface IEssentials extends Plugin {
Iterable<User> getOnlineUsers();
SpawnerItemProvider getSpawnerItemProvider();
SpawnerBlockProvider getSpawnerBlockProvider();
ServerStateProvider getServerStateProvider();
MaterialTagProvider getMaterialTagProvider();
ContainerProvider getContainerProvider();
KnownCommandsProvider getKnownCommandsProvider();
SerializationProvider getSerializationProvider();
FormattedCommandAliasProvider getFormattedCommandAliasProvider();
SyncCommandsProvider getSyncCommandsProvider();
PersistentDataProvider getPersistentDataProvider();
ReflOnlineModeProvider getOnlineModeProvider();
ItemUnbreakableProvider getItemUnbreakableProvider();
WorldInfoProvider getWorldInfoProvider();
SignDataProvider getSignDataProvider();
PlayerLocaleProvider getPlayerLocaleProvider();
DamageEventProvider getDamageEventProvider();
BiomeKeyProvider getBiomeKeyProvider();
BannerDataProvider getBannerDataProvider();
InventoryViewProvider getInventoryViewProvider();
PluginCommand getPluginCommand(String cmd);
ProviderFactory getProviders();
default <P extends Provider> P provider(final Class<P> providerClass) {
return getProviders().get(providerClass);
}
}
@@ -3,6 +3,7 @@ package com.earth2me.essentials;
import com.earth2me.essentials.commands.IEssentialsCommand;
import com.earth2me.essentials.signs.EssentialsSign;
import com.earth2me.essentials.textreader.IText;
import net.essentialsx.api.v2.ChatType;
import net.kyori.adventure.text.minimessage.tag.Tag;
import org.bukkit.Material;
import org.bukkit.event.EventPriority;
@@ -37,6 +38,8 @@ public interface ISettings extends IConf {
String getChatFormat(String group);
String getChatFormat(String group, ChatType chatType);
String getWorldAlias(String world);
int getChatRadius();
@@ -53,6 +56,8 @@ public interface ISettings extends IConf {
boolean isChatQuestionEnabled();
boolean isUsePaperChatEvent();
BigDecimal getCommandCost(IEssentialsCommand cmd);
BigDecimal getCommandCost(String label);
@@ -100,12 +105,18 @@ public interface ISettings extends IConf {
List<Material> getProtectList(final String configName);
List<String> getProtectListRaw(final String configName);
boolean getProtectPreventSpawn(final String creatureName);
String getProtectString(final String configName);
boolean getRespawnAtHome();
String getRandomSpawnLocation();
String getRandomRespawnLocation();
boolean isRespawnAtAnchor();
Set getMultipleHomes();
@@ -337,6 +348,8 @@ public interface ISettings extends IConf {
boolean isWorldChangeFlyResetEnabled();
boolean isWorldChangePreserveFlying();
boolean isWorldChangeSpeedResetEnabled();
long getCommandCooldownMs(String label);
@@ -411,12 +424,20 @@ public interface ISettings extends IConf {
boolean showZeroBaltop();
String getNickRegex();
BigDecimal getMultiplier(final User user);
int getMaxItemLore();
Tag getPrimaryColor();
Tag getSecondaryColor();
BigDecimal getBaltopMinBalance();
long getBaltopMinPlaytime();
enum KeepInvPolicy {
KEEP,
DELETE,
@@ -3,7 +3,6 @@ package com.earth2me.essentials;
import com.earth2me.essentials.api.IAsyncTeleport;
import com.earth2me.essentials.commands.IEssentialsCommand;
import com.earth2me.essentials.config.entities.CommandCooldown;
import net.ess3.api.ITeleport;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.events.AfkStatusChangeEvent;
import net.essentialsx.api.v2.services.mail.MailMessage;
@@ -70,13 +69,9 @@ public interface IUser {
* @return whether there is a teleport request
*/
@Deprecated
boolean hasOutstandingTeleportRequest();
/**
* @deprecated This API is not asynchronous. Use {@link com.earth2me.essentials.api.IAsyncTeleport IAsyncTeleport} with {@link IUser#getAsyncTeleport()}
*/
@Deprecated
ITeleport getTeleport();
default boolean hasOutstandingTeleportRequest() {
return getNextTpaRequest(false, false, false) != null;
}
IAsyncTeleport getAsyncTeleport();
@@ -182,6 +177,17 @@ public interface IUser {
String getFormattedJailTime();
/**
* Returns last activity time.
* <p>
* It is used internally to determine if user's afk status should be set to
* true because of ACTIVITY {@link AfkStatusChangeEvent.Cause}, or the player
* should be kicked for being afk too long.
*
* @return Last activity time (Epoch Milliseconds)
*/
long getLastActivityTime();
@Deprecated
List<String> getMails();
@@ -40,7 +40,7 @@ import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tlLiteral;
public class Jails implements net.ess3.api.IJails {
private static transient boolean enabled = false;
private static boolean enabled = false;
private final IEssentials ess;
private final EssentialsConfiguration config;
private final Map<String, LazyLocation> jails = new HashMap<>();
@@ -142,28 +142,6 @@ public class Jails implements net.ess3.api.IJails {
}
}
/**
* @deprecated This method does not use asynchronous teleportation. Use {@link Jails#sendToJail(IUser, String, CompletableFuture)}
*/
@SuppressWarnings("deprecation")
@Override
@Deprecated
public void sendToJail(final IUser user, String jail) throws Exception {
if (jail == null || jail.isEmpty()) {
return;
}
jail = jail.toLowerCase(Locale.ENGLISH);
synchronized (jails) {
if (jails.containsKey(jail)) {
if (user.getBase().isOnline()) {
user.getTeleport().now(getJail(jail), false, TeleportCause.COMMAND);
}
user.setJail(jail);
}
}
}
@Override
public void sendToJail(final IUser user, final String jailName, final CompletableFuture<Boolean> future) throws Exception {
if (jailName == null || jailName.isEmpty()) {
@@ -12,6 +12,7 @@ import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.KitClaimEvent;
import net.ess3.provider.SerializationProvider;
import net.essentialsx.api.v2.events.KitPreExpandItemsEvent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@@ -191,13 +192,14 @@ public class Kit {
}
final ItemStack stack;
final SerializationProvider serializationProvider = ess.provider(SerializationProvider.class);
if (kitItem.startsWith("@")) {
if (ess.getSerializationProvider() == null) {
if (serializationProvider == null) {
ess.getLogger().log(Level.WARNING, AdventureUtil.miniToLegacy(tlLiteral("kitError3", kitName, user.getName())));
continue;
}
stack = ess.getSerializationProvider().deserializeItem(Base64Coder.decodeLines(kitItem.substring(1)));
stack = serializationProvider.deserializeItem(Base64Coder.decodeLines(kitItem.substring(1)));
} else {
final String[] parts = kitItem.split(" +");
final ItemStack parseStack = ess.getItemDb().get(parts[0], parts.length > 1 ? Integer.parseInt(parts[1]) : 1);
@@ -240,10 +242,10 @@ public class Kit {
for (final ItemStack itemStack : leftover.values()) {
int spillAmount = itemStack.getAmount();
if (maxStackSize != 0) {
itemStack.setAmount(Math.min(spillAmount, itemStack.getMaxStackSize()));
}
while (spillAmount > 0) {
if (maxStackSize != 0) {
itemStack.setAmount(Math.min(spillAmount, itemStack.getMaxStackSize()));
}
user.getWorld().dropItemNaturally(user.getLocation(), itemStack);
spillAmount -= itemStack.getAmount();
}
@@ -3,7 +3,6 @@ package com.earth2me.essentials;
import com.earth2me.essentials.textreader.BookInput;
import com.earth2me.essentials.textreader.BookPager;
import com.earth2me.essentials.textreader.IText;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
@@ -11,6 +10,9 @@ import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.base.Joiner;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
import net.ess3.provider.BannerDataProvider;
import net.ess3.provider.ItemUnbreakableProvider;
import net.ess3.provider.PotionMetaProvider;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.FireworkEffect;
@@ -214,8 +216,6 @@ public class MetaItemStack {
return;
}
final Material WRITTEN_BOOK = EnumUtil.getMaterial("WRITTEN_BOOK");
if (split.length > 1 && split[0].equalsIgnoreCase("name") && hasMetaPermission(sender, "name", false, true, ess)) {
final String displayName = FormatUtil.replaceFormat(split[1].replaceAll("(?<!\\\\)_", " ").replace("\\_", "_"));
final ItemMeta meta = stack.getItemMeta();
@@ -251,7 +251,7 @@ public class MetaItemStack {
final IText input = new BookInput("book", true, ess);
final BookPager pager = new BookPager(input);
// This fix only applies to written books - which require an author and a title. https://bugs.mojang.com/browse/MC-59153
if (stack.getType() == WRITTEN_BOOK) {
if (stack.getType() == Material.WRITTEN_BOOK) {
if (!meta.hasAuthor()) {
// The sender can be null when this method is called from {@link com.earth2me.essentials.signs.EssentialsSign#getItemMeta(ItemStack, String, IEssentials)}
meta.setAuthor(sender == null ? Console.getInstance().getDisplayName() : sender.getPlayer().getName());
@@ -264,12 +264,12 @@ public class MetaItemStack {
final List<String> pages = pager.getPages(split[1]);
meta.setPages(pages);
stack.setItemMeta(meta);
} else if (split.length > 1 && split[0].equalsIgnoreCase("author") && stack.getType() == WRITTEN_BOOK && hasMetaPermission(sender, "author", false, true, ess)) {
} else if (split.length > 1 && split[0].equalsIgnoreCase("author") && stack.getType() == Material.WRITTEN_BOOK && hasMetaPermission(sender, "author", false, true, ess)) {
final String author = FormatUtil.replaceFormat(split[1]);
final BookMeta meta = (BookMeta) stack.getItemMeta();
meta.setAuthor(author);
stack.setItemMeta(meta);
} else if (split.length > 1 && split[0].equalsIgnoreCase("title") && stack.getType() == WRITTEN_BOOK && hasMetaPermission(sender, "title", false, true, ess)) {
} else if (split.length > 1 && split[0].equalsIgnoreCase("title") && stack.getType() == Material.WRITTEN_BOOK && hasMetaPermission(sender, "title", false, true, ess)) {
final String title = FormatUtil.replaceFormat(split[1].replaceAll("(?<!\\\\)_", " ").replace("\\_", "_"));
final BookMeta meta = (BookMeta) stack.getItemMeta();
meta.setTitle(title);
@@ -565,7 +565,7 @@ public class MetaItemStack {
}
pmeta.addCustomEffect(pEffect, true);
stack.setItemMeta(pmeta);
ess.getPotionMetaProvider().setSplashPotion(stack, isSplashPotion);
ess.provider(PotionMetaProvider.class).setSplashPotion(stack, isSplashPotion);
resetPotionMeta();
}
}
@@ -655,7 +655,7 @@ public class MetaItemStack {
final BannerMeta meta = (BannerMeta) stack.getItemMeta();
if (split[0].equalsIgnoreCase("basecolor")) {
final Color color = Color.fromRGB(Integer.parseInt(split[1]));
ess.getBannerDataProvider().setBaseColor(stack, DyeColor.getByColor(color));
ess.provider(BannerDataProvider.class).setBaseColor(stack, DyeColor.getByColor(color));
} else if (patternType != null) {
//noinspection removal
final PatternType type = PatternType.getByIdentifier(split[0]);
@@ -718,7 +718,7 @@ public class MetaItemStack {
private void setUnbreakable(final IEssentials ess, final ItemStack is, final boolean unbreakable) {
final ItemMeta meta = is.getItemMeta();
ess.getItemUnbreakableProvider().setUnbreakable(meta, unbreakable);
ess.provider(ItemUnbreakableProvider.class).setUnbreakable(meta, unbreakable);
is.setItemMeta(meta);
}
}
@@ -50,7 +50,16 @@ public enum Mob {
WITHER("Wither", Enemies.ENEMY, EntityType.WITHER),
BAT("Bat", Enemies.FRIENDLY, EntityType.BAT),
WITCH("Witch", Enemies.ENEMY, EntityType.WITCH),
BOAT("Boat", Enemies.NEUTRAL, EntityType.BOAT),
BOAT("Boat", Enemies.NEUTRAL, MobCompat.OAK_BOAT),
ACACIA_BOAT("AcaciaBoat", Enemies.NEUTRAL, "ACACIA_BOAT"),
DARK_OAK_BOAT("DarkOakBoat", Enemies.NEUTRAL, "DARK_OAK_BOAT"),
BIRCH_BOAT("BirchBoat", Enemies.NEUTRAL, "BIRCH_BOAT"),
JUNGLE_BOAT("JungleBoat", Enemies.NEUTRAL, "JUNGLE_BOAT"),
SPRUCE_BOAT("SpruceBoat", Enemies.NEUTRAL, "SPRUCE_BOAT"),
MANGROVE_BOAT("MangroveBoat", Enemies.NEUTRAL, "MANGROVE_BOAT"),
CHERRY_BOAT("CherryBoat", Enemies.NEUTRAL, "CHERRY_BOAT"),
BAMBOO_RAFT("BambooRaft", Enemies.NEUTRAL, "BAMBOO_RAFT"),
PALE_OAK_BOAT("PaleOakBoat", Enemies.NEUTRAL, "PALE_OAK_BOAT"),
MINECART("Minecart", Enemies.NEUTRAL, EntityType.MINECART),
MINECART_CHEST("ChestMinecart", Enemies.NEUTRAL, MobCompat.CHEST_MINECART),
MINECART_FURNACE("FurnaceMinecart", Enemies.NEUTRAL, MobCompat.FURNACE_MINECART),
@@ -115,6 +124,8 @@ public enum Mob {
ARMADILLO("Armadillo", Enemies.FRIENDLY, "ARMADILLO"),
BREEZE("Breeze", Enemies.ENEMY, "BREEZE"),
BOGGED("Bogged", Enemies.ENEMY, "BOGGED"),
CREAKING("Creaking", Enemies.ENEMY, "CREAKING"),
HAPPY_GHAST("HappyGhast", Enemies.FRIENDLY, "HAPPY_GHAST")
;
private static final Map<String, Mob> hashMap = new HashMap<>();
@@ -9,6 +9,8 @@ import org.bukkit.TreeSpecies;
import org.bukkit.entity.Axolotl;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Camel;
import org.bukkit.entity.Chicken;
import org.bukkit.entity.Cow;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Fox;
@@ -18,12 +20,17 @@ import org.bukkit.entity.MushroomCow;
import org.bukkit.entity.Ocelot;
import org.bukkit.entity.Panda;
import org.bukkit.entity.Parrot;
import org.bukkit.entity.Pig;
import org.bukkit.entity.Player;
import org.bukkit.entity.Salmon;
import org.bukkit.entity.TropicalFish;
import org.bukkit.entity.Villager;
import org.bukkit.entity.Wolf;
import org.bukkit.inventory.ItemStack;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import static com.earth2me.essentials.utils.EnumUtil.getEntityType;
@@ -31,8 +38,21 @@ import static com.earth2me.essentials.utils.EnumUtil.getEntityType;
public final class MobCompat {
// Constants for mob interfaces added in later versions
@SuppressWarnings("rawtypes")
public static final Class RAIDER = ReflUtil.getClassCached("org.bukkit.entity.Raider");
public static final Class<?> RAIDER = ReflUtil.getClassCached("org.bukkit.entity.Raider");
// Stupid hacks to avoid Commodore rewrites.
private static final Class<?> COW = ReflUtil.getClassCached("org.bukkit.entity.Cow");
private static final Class<?> COW_VARIANT = ReflUtil.getClassCached("org.bukkit.entity.Cow$Variant");
private static final MethodHandle COW_VARIANT_HANDLE;
static {
MethodHandle handle = null;
try {
handle = MethodHandles.lookup().findVirtual(COW, "setVariant", MethodType.methodType(void.class, COW_VARIANT));
} catch (final Throwable ignored) {
}
COW_VARIANT_HANDLE = handle;
}
// Constants for mobs added in later versions
public static final EntityType LLAMA = getEntityType("LLAMA");
@@ -48,6 +68,7 @@ public final class MobCompat {
public static final EntityType GOAT = getEntityType("GOAT");
public static final EntityType FROG = getEntityType("FROG");
public static final EntityType CAMEL = getEntityType("CAMEL");
public static final EntityType SALMON = getEntityType("SALMON");
// Constants for mobs that have changed since earlier versions
public static final EntityType CAT = getEntityType("CAT", "OCELOT");
@@ -61,6 +82,7 @@ public final class MobCompat {
public static final EntityType SPAWNER_MINECART = getEntityType("SPAWNER_MINECART", "MINECART_MOB_SPAWNER");
public static final EntityType END_CRYSTAL = getEntityType("END_CRYSTAL", "ENDER_CRYSTAL");
public static final EntityType FIREWORK_ROCKET = getEntityType("FIREWORK_ROCKET", "FIREWORK");
public static final EntityType OAK_BOAT = getEntityType("BOAT", "OAK_BOAT");
private MobCompat() {
}
@@ -194,7 +216,7 @@ public final class MobCompat {
}
public static void setBoatVariant(final Entity entity, final BoatVariant variant) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_21_3_R01) || VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
return;
}
final Boat boat;
@@ -207,6 +229,7 @@ public final class MobCompat {
//noinspection deprecation
boat.setWoodType(TreeSpecies.valueOf(variant.getTreeSpecies()));
} else {
//noinspection deprecation
boat.setBoatType(Boat.Type.valueOf(variant.getBoatType()));
}
}
@@ -236,6 +259,51 @@ public final class MobCompat {
}
}
public static void setSalmonSize(Entity spawned, String s) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_21_3_R01)) {
return;
}
if (spawned instanceof org.bukkit.entity.Salmon) {
((Salmon) spawned).setVariant(Salmon.Variant.valueOf(s));
}
}
public static void setCowVariant(final Entity spawned, final String variant) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_21_5_R01) || COW_VARIANT_HANDLE == null) {
return;
}
if (spawned instanceof Cow) {
try {
COW_VARIANT_HANDLE.invoke(spawned, RegistryUtil.valueOf(COW_VARIANT, variant));
} catch (Throwable ignored) {
}
}
}
public static void setChickenVariant(final Entity spawned, final String variant) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_21_5_R01)) {
return;
}
if (spawned instanceof Chicken) {
//noinspection DataFlowIssue
((Chicken) spawned).setVariant(RegistryUtil.valueOf(Chicken.Variant.class, variant));
}
}
public static void setPigVariant(final Entity spawned, final String variant) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_21_5_R01)) {
return;
}
if (spawned instanceof Pig) {
//noinspection DataFlowIssue
((Pig) spawned).setVariant(RegistryUtil.valueOf(Pig.Variant.class, variant));
}
}
public enum CatType {
// These are (loosely) Mojang names for the cats
SIAMESE("SIAMESE", "SIAMESE_CAT"),
@@ -10,6 +10,7 @@ import org.bukkit.Material;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.Boat;
import org.bukkit.entity.ChestedHorse;
import org.bukkit.entity.Chicken;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@@ -218,6 +219,18 @@ public enum MobData {
WOODS_WOLF("woods", EntityType.WOLF, "wolf:WOODS", true),
CHESTNUT_WOLF("chestnut", EntityType.WOLF, "wolf:CHESTNUT", true),
STRIPED_WOLF("striped", EntityType.WOLF, "wolf:STRIPED", true),
SMALL_SALMON("small", MobCompat.SALMON, "salmon:SMALL", true),
MEDIUM_SALMON("medium", MobCompat.SALMON, "salmon:MEDIUM", true),
LARGE_SALMON("large", MobCompat.SALMON, "salmon:LARGE", true),
TEMPERATE_COW("temperate", EntityType.COW.getEntityClass(), "cow:TEMPERATE", true),
WARM_COW("warm", EntityType.COW.getEntityClass(), "cow:WARM", true),
COLD_COW("cold", EntityType.COW.getEntityClass(), "cow:COLD", true),
TEMPERATE_CHICKEN("temperate", Chicken.class, "chicken:TEMPERATE", true),
WARM_CHICKEN("warm", Chicken.class, "chicken:WARM", true),
COLD_CHICKEN("cold", Chicken.class, "chicken:COLD", true),
TEMPERATE_PIG("temperate", Pig.class, "pig:TEMPERATE", true),
WARM_PIG("warm", Pig.class, "pig:WARM", true),
COLD_PIG("cold", Pig.class, "pig:COLD", true),
;
final private String nickname;
@@ -436,6 +449,18 @@ public enum MobData {
case "wolf":
MobCompat.setWolfVariant(spawned, split[1]);
break;
case "salmon":
MobCompat.setSalmonSize(spawned, split[1]);
break;
case "cow":
MobCompat.setCowVariant(spawned, split[1]);
break;
case "chicken":
MobCompat.setChickenVariant(spawned, split[1]);
break;
case "pig":
MobCompat.setPigVariant(spawned, split[1]);
break;
}
} else {
Essentials.getWrappedLogger().warning("Unknown mob data type: " + this.toString());
@@ -0,0 +1,137 @@
package com.earth2me.essentials;
import io.papermc.lib.PaperLib;
import net.ess3.provider.Provider;
import net.essentialsx.providers.NullableProvider;
import net.essentialsx.providers.ProviderData;
import net.essentialsx.providers.ProviderTest;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
public class ProviderFactory {
private final Map<Class<? extends Provider>, Provider> providers = new HashMap<>();
private final Map<Class<? extends Provider>, List<Class<? extends Provider>>> registeredProviders = new HashMap<>();
private final Essentials essentials;
public ProviderFactory(final Essentials essentials) {
this.essentials = essentials;
}
/**
* Gets the provider which has been selected for the given type.
* @param providerClass The provider type.
* @return the provider or null if no provider could be selected for that type.
*/
public <P extends Provider> P get(final Class<P> providerClass) {
final Provider provider = providers.get(providerClass);
if (provider == null) {
return null;
}
//noinspection unchecked
return (P) provider;
}
@SafeVarargs
public final void registerProvider(final Class<? extends Provider>... toRegister) {
for (final Class<? extends Provider> provider : toRegister) {
final Class<?> superclass = provider.getInterfaces().length > 0 ? provider.getInterfaces()[0] : provider.getSuperclass();
if (Provider.class.isAssignableFrom(superclass)) {
//noinspection unchecked
registeredProviders.computeIfAbsent((Class<? extends Provider>) superclass, k -> new ArrayList<>()).add(provider);
if (essentials.getSettings().isDebug()) {
essentials.getLogger().info("Registered provider " + provider.getSimpleName() + " for " + superclass.getSimpleName());
}
}
}
}
public void finalizeRegistration() {
for (final Map.Entry<Class<? extends Provider>, List<Class<? extends Provider>>> entry : registeredProviders.entrySet()) {
final Class<? extends Provider> providerClass = entry.getKey();
final boolean nullable = providerClass.isAnnotationPresent(NullableProvider.class);
Class<? extends Provider> highestProvider = null;
ProviderData highestProviderData = null;
int highestWeight = -1;
for (final Class<? extends Provider> provider : entry.getValue()) {
try {
final ProviderData providerData = provider.getAnnotation(ProviderData.class);
if (providerData.weight() > highestWeight && testProvider(provider)) {
highestWeight = providerData.weight();
highestProvider = provider;
highestProviderData = providerData;
}
} catch (final Throwable e) {
essentials.getLogger().log(Level.SEVERE, "Failed to initialize provider " + provider.getName(), e);
}
}
if (highestProvider != null) {
essentials.getLogger().info("Selected " + highestProviderData.description() + " as the provider for " + providerClass.getSimpleName());
providers.put(providerClass, getProviderInstance(highestProvider));
} else if (!nullable) {
throw new IllegalStateException("No provider found for " + providerClass.getName());
} else {
essentials.getLogger().info("No provider found for " + providerClass.getSimpleName() + ", but it is nullable");
}
}
registeredProviders.clear();
}
private boolean testProvider(final Class<?> providerClass) throws InvocationTargetException, IllegalAccessException {
try {
for (final Method method : providerClass.getMethods()) {
if (method.isAnnotationPresent(ProviderTest.class)) {
return (Boolean) method.invoke(null);
}
}
return true;
} catch (final NoClassDefFoundError ignored) {
return false;
}
}
private <P extends Provider> P getProviderInstance(final Class<P> provider) {
try {
final Constructor<?> constructor = provider.getConstructors()[0];
if (constructor.getParameterTypes().length == 0) {
//noinspection unchecked
return (P) constructor.newInstance();
}
final Object[] args = new Object[constructor.getParameterTypes().length];
/*
Providers can have constructors with any of the following types, and this code will automatically supply them;
- Plugin - The Essentials instance will be passed
- boolean - True will be passed if this server is running Paper, otherwise false.
*/
for (int i = 0; i < args.length; i++) {
final Class<?> paramType = constructor.getParameterTypes()[i];
if (paramType.isAssignableFrom(Plugin.class)) {
args[i] = essentials;
} else if (paramType.isAssignableFrom(boolean.class)) {
args[i] = PaperLib.isPaper();
} else {
throw new IllegalArgumentException("Unsupported parameter type " + paramType.getName());
}
}
//noinspection unchecked
return (P) constructor.newInstance(args);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
try {
return provider.getConstructor().newInstance();
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException ex) {
e.printStackTrace();
throw new RuntimeException(ex);
}
}
}
}
@@ -1,17 +1,24 @@
package com.earth2me.essentials;
import com.earth2me.essentials.config.ConfigurateUtil;
import com.earth2me.essentials.config.EssentialsConfiguration;
import com.earth2me.essentials.config.entities.LazyLocation;
import com.earth2me.essentials.utils.LocationUtil;
import com.earth2me.essentials.utils.VersionUtil;
import io.papermc.lib.PaperLib;
import net.ess3.api.InvalidWorldException;
import net.ess3.provider.BiomeKeyProvider;
import net.ess3.provider.BiomeNameProvider;
import net.ess3.provider.WorldInfoProvider;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
@@ -23,58 +30,73 @@ public class RandomTeleport implements IConf {
private static final int HIGHEST_BLOCK_Y_OFFSET = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_15_R01) ? 1 : 0;
private final IEssentials ess;
private final EssentialsConfiguration config;
private final ConcurrentLinkedQueue<Location> cachedLocations = new ConcurrentLinkedQueue<>();
private final Map<String, ConcurrentLinkedQueue<Location>> cachedLocations = new HashMap<>();
private WorldInfoProvider worldInfoProvider;
public RandomTeleport(final IEssentials essentials) {
this.ess = essentials;
config = new EssentialsConfiguration(new File(essentials.getDataFolder(), "tpr.yml"), "/tpr.yml",
"Configuration for the random teleport command.\nSome settings may be defaulted, and can be changed via the /settpr command in-game.");
reloadConfig();
"Configuration for the random teleport command.\nUse the /settpr command in-game to set random teleport locations.");
}
public EssentialsConfiguration getConfig() {
return config;
}
@Override
public void reloadConfig() {
worldInfoProvider = ess.provider(WorldInfoProvider.class);
config.load();
cachedLocations.clear();
}
public Location getCenter() {
try {
final LazyLocation center = config.getLocation("center");
if (center != null && center.location() != null) {
return center.location();
}
} catch (final InvalidWorldException ignored) {
public boolean hasLocation(final String name) {
return config.hasProperty("locations." + name);
}
public Location getCenter(final String name) {
final LazyLocation center = config.getLocation(locationKey(name, "center"));
if (center != null && center.location() != null) {
return center.location();
}
final Location center = ess.getServer().getWorlds().get(0).getWorldBorder().getCenter();
center.setY(center.getWorld().getHighestBlockYAt(center) + HIGHEST_BLOCK_Y_OFFSET);
setCenter(center);
return center;
final Location worldCenter = ess.getServer().getWorlds().get(0).getWorldBorder().getCenter();
worldCenter.setY(worldCenter.getWorld().getHighestBlockYAt(worldCenter) + HIGHEST_BLOCK_Y_OFFSET);
setCenter(name, worldCenter);
return worldCenter;
}
public void setCenter(final Location center) {
config.setProperty("center", center);
public void setCenter(final String name, final Location center) {
config.setProperty(locationKey(name, "center"), center);
config.save();
}
public double getMinRange() {
return config.getDouble("min-range", 0d);
public double getMinRange(final String name) {
return config.getDouble(locationKey(name, "min-range"), 0d);
}
public void setMinRange(final double minRange) {
config.setProperty("min-range", minRange);
public void setMinRange(final String name, final double minRange) {
config.setProperty(locationKey(name, "min-range"), minRange);
config.save();
}
public double getMaxRange() {
return config.getDouble("max-range", getCenter().getWorld().getWorldBorder().getSize() / 2);
public double getMaxRange(final String name) {
return config.getDouble(locationKey(name, "max-range"), getCenter(name).getWorld().getWorldBorder().getSize() / 2);
}
public void setMaxRange(final double maxRange) {
config.setProperty("max-range", maxRange);
public void setMaxRange(final String name, final double maxRange) {
config.setProperty(locationKey(name, "max-range"), maxRange);
config.save();
}
public String getDefaultLocation() {
return config.getString("default-location", "{world}");
}
public boolean isPerLocationPermission() {
return config.getBoolean("per-location-permission", false);
}
public Set<String> getExcludedBiomes() {
final Set<String> excludedBiomes = new HashSet<>();
for (final String key : config.getList("excluded-biomes", String.class)) {
@@ -91,39 +113,48 @@ public class RandomTeleport implements IConf {
return config.getInt("cache-threshold", 10);
}
public boolean getPreCache() {
return config.getBoolean("pre-cache", false);
public List<String> listLocations() {
return new ArrayList<>(ConfigurateUtil.getKeys(config.getRootNode().node("locations")));
}
public Queue<Location> getCachedLocations() {
return cachedLocations;
public Queue<Location> getCachedLocations(final String name) {
this.cachedLocations.computeIfAbsent(name, x -> new ConcurrentLinkedQueue<>());
return cachedLocations.get(name);
}
// Get a random location; cached if possible. Otherwise on demand.
public CompletableFuture<Location> getRandomLocation(final Location center, final double minRange, final double maxRange) {
final int findAttempts = this.getFindAttempts();
final Queue<Location> cachedLocations = this.getCachedLocations();
// Get a named random teleport location; cached if possible, otherwise on demand.
public CompletableFuture<Location> getRandomLocation(final String name) {
final Queue<Location> cached = this.getCachedLocations(name);
// Try to build up the cache if it is below the threshold
if (cachedLocations.size() < this.getCacheThreshold()) {
cacheRandomLocations(center, minRange, maxRange);
if (cached.size() < this.getCacheThreshold()) {
cacheRandomLocations(name);
}
final CompletableFuture<Location> future = new CompletableFuture<>();
// Return a random location immediately if one is available, otherwise try to find one now
if (cachedLocations.isEmpty()) {
if (cached.isEmpty()) {
final int findAttempts = this.getFindAttempts();
final Location center = this.getCenter(name);
final double minRange = this.getMinRange(name);
final double maxRange = this.getMaxRange(name);
attemptRandomLocation(findAttempts, center, minRange, maxRange).thenAccept(future::complete);
} else {
future.complete(cachedLocations.poll());
future.complete(cached.poll());
}
return future;
}
// Prompts caching random valid locations, up to a maximum number of attempts
public void cacheRandomLocations(final Location center, final double minRange, final double maxRange) {
// Get a random location with specific parameters (note: not cached).
public CompletableFuture<Location> getRandomLocation(final Location center, final double minRange, final double maxRange) {
return attemptRandomLocation(this.getFindAttempts(), center, minRange, maxRange);
}
// Prompts caching random valid locations, up to a maximum number of attempts.
public void cacheRandomLocations(final String name) {
ess.getServer().getScheduler().scheduleSyncDelayedTask(ess, () -> {
for (int i = 0; i < this.getFindAttempts(); ++i) {
calculateRandomLocation(center, minRange, maxRange).thenAccept(location -> {
calculateRandomLocation(getCenter(name), getMinRange(name), getMaxRange(name)).thenAccept(location -> {
if (isValidRandomLocation(location)) {
this.getCachedLocations().add(location);
this.getCachedLocations(name).add(location);
}
});
}
@@ -172,7 +203,7 @@ public class RandomTeleport implements IConf {
final Location location = new Location(
center.getWorld(),
center.getX() + offsetX,
ess.getWorldInfoProvider().getMaxHeight(center.getWorld()),
worldInfoProvider.getMaxHeight(center.getWorld()),
center.getZ() + offsetZ,
360 * RANDOM.nextFloat() - 180,
0
@@ -188,24 +219,29 @@ public class RandomTeleport implements IConf {
return future;
}
// Returns an appropriate elevation for a given location in the nether, or -1 if none is found
// Returns an appropriate elevation for a given location in the nether, or MIN_VALUE if none is found
private double getNetherYAt(final Location location) {
for (int y = 32; y < ess.getWorldInfoProvider().getMaxHeight(location.getWorld()); ++y) {
if (!LocationUtil.isBlockUnsafe(ess, location.getWorld(), location.getBlockX(), y, location.getBlockZ())) {
final World world = location.getWorld();
for (int y = 32; y < worldInfoProvider.getMaxHeight(world); ++y) {
if (Material.BEDROCK.equals(world.getBlockAt(location.getBlockX(), y, location.getBlockZ()).getType())) {
break;
}
if (!LocationUtil.isBlockUnsafe(ess, world, location.getBlockX(), y, location.getBlockZ())) {
return y;
}
}
return -1;
return Double.MIN_VALUE;
}
private boolean isValidRandomLocation(final Location location) {
return location.getBlockY() > ess.getWorldInfoProvider().getMinHeight(location.getWorld()) && !isExcludedBiome(location);
return location.getBlockY() > worldInfoProvider.getMinHeight(location.getWorld()) && !isExcludedBiome(location);
}
// Exclude biome if enum or namespaced key matches
private boolean isExcludedBiome(final Location location) {
final BiomeNameProvider biomeNameProvider = ess.provider(BiomeNameProvider.class);
final Set<String> excluded = getExcludedBiomes();
final String enumKey = location.getBlock().getBiome().name().toLowerCase();
final String enumKey = biomeNameProvider.getBiomeName(location.getBlock());
// Try with good old bukkit enum
if (excluded.contains(enumKey)) {
return true;
@@ -215,7 +251,7 @@ public class RandomTeleport implements IConf {
return false;
}
final String biomeKey;
final BiomeKeyProvider biomeKeyProvider = ess.getBiomeKeyProvider();
final BiomeKeyProvider biomeKeyProvider = ess.provider(BiomeKeyProvider.class);
if (biomeKeyProvider != null) {
// Works with custom biome keys
biomeKey = biomeKeyProvider.getBiomeKey(location.getBlock()).toString();
@@ -226,6 +262,10 @@ public class RandomTeleport implements IConf {
return excluded.contains(biomeKey);
}
private String locationKey(final String name, final String key) {
return "locations." + name + "." + key;
}
public File getFile() {
return config.getFile();
}
@@ -14,6 +14,9 @@ import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.LocationUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.IEssentials;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.SyncCommandsProvider;
import net.essentialsx.api.v2.ChatType;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.minimessage.tag.Tag;
@@ -23,6 +26,7 @@ import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.event.EventPriority;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.spongepowered.configurate.CommentedConfigurationNode;
import java.io.File;
@@ -34,6 +38,7 @@ import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -44,6 +49,7 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
@@ -58,7 +64,7 @@ public class Settings implements net.ess3.api.ISettings {
private final transient EssentialsConfiguration config;
private final transient IEssentials ess;
private final transient AtomicInteger reloadCount = new AtomicInteger(0);
private final Map<String, String> chatFormats = Collections.synchronizedMap(new HashMap<>());
private final ChatFormats chatFormats = new ChatFormats();
private int chatRadius = 0;
// #easteregg
private char chatShout = '!';
@@ -145,6 +151,8 @@ public class Settings implements net.ess3.api.ISettings {
private Map<String, String> worldAliases;
private Tag primaryColor = DEFAULT_PRIMARY_COLOR;
private Tag secondaryColor = DEFAULT_SECONDARY_COLOR;
private Set<String> multiplierPerms;
private BigDecimal defaultMultiplier;
public Settings(final IEssentials ess) {
this.ess = ess;
@@ -162,6 +170,16 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("respawn-at-home", false);
}
@Override
public String getRandomSpawnLocation() {
return config.getString("random-spawn-location", "none");
}
@Override
public String getRandomRespawnLocation() {
return config.getString("random-respawn-location", "none");
}
@Override
public boolean isRespawnAtAnchor() {
return config.getBoolean("respawn-at-anchor", false);
@@ -188,7 +206,7 @@ public class Settings implements net.ess3.api.ISettings {
final Set<String> homeList = getMultipleHomes();
if (homeList != null) {
for (final String set : homeList) {
if (user.isAuthorized("essentials.sethome.multiple." + set) && (limit < getHomeLimit(set))) {
if (user.isAuthorized("essentials.sethome.multiple." + set) && limit < getHomeLimit(set)) {
limit = getHomeLimit(set);
}
}
@@ -248,6 +266,11 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("chat.question-enabled", true);
}
@Override
public boolean isUsePaperChatEvent() {
return config.getBoolean("chat.paper-chat-events", true);
}
public boolean _isTeleportSafetyEnabled() {
return config.getBoolean("teleport-safety", true);
}
@@ -322,9 +345,11 @@ public class Settings implements net.ess3.api.ISettings {
}
private void _addAlternativeCommand(final String label, final Command current) {
final KnownCommandsProvider knownCommandsProvider = ess.provider(KnownCommandsProvider.class);
Command cmd = ess.getAlternativeCommandsHandler().getAlternative(label);
if (cmd == null) {
for (final Map.Entry<String, Command> entry : ess.getKnownCommandsProvider().getKnownCommands().entrySet()) {
for (final Map.Entry<String, Command> entry : knownCommandsProvider.getKnownCommands().entrySet()) {
final String[] split = entry.getKey().split(":");
if (entry.getValue() != current && split[split.length - 1].equals(label)) {
cmd = entry.getValue();
@@ -334,7 +359,7 @@ public class Settings implements net.ess3.api.ISettings {
}
if (cmd != null) {
ess.getKnownCommandsProvider().getKnownCommands().put(label, cmd);
knownCommandsProvider.getKnownCommands().put(label, cmd);
}
}
@@ -579,32 +604,132 @@ public class Settings implements net.ess3.api.ISettings {
@Override
public String getChatFormat(final String group) {
String mFormat = chatFormats.get(group);
if (mFormat == null) {
mFormat = config.getString("chat.group-formats." + (group == null ? "Default" : group), config.getString("chat.format", "&7[{GROUP}]&r {DISPLAYNAME}&7:&r {MESSAGE}"));
mFormat = FormatUtil.replaceFormat(mFormat);
mFormat = mFormat.replace("{DISPLAYNAME}", "%1$s");
mFormat = mFormat.replace("{MESSAGE}", "%2$s");
mFormat = mFormat.replace("{GROUP}", "{0}");
mFormat = mFormat.replace("{WORLD}", "{1}");
mFormat = mFormat.replace("{WORLDNAME}", "{1}");
mFormat = mFormat.replace("{SHORTWORLDNAME}", "{2}");
mFormat = mFormat.replace("{TEAMPREFIX}", "{3}");
mFormat = mFormat.replace("{TEAMSUFFIX}", "{4}");
mFormat = mFormat.replace("{TEAMNAME}", "{5}");
mFormat = mFormat.replace("{PREFIX}", "{6}");
mFormat = mFormat.replace("{SUFFIX}", "{7}");
mFormat = mFormat.replace("{USERNAME}", "{8}");
mFormat = mFormat.replace("{NICKNAME}", "{9}");
mFormat = "§r".concat(mFormat);
chatFormats.put(group, mFormat);
}
return getChatFormat(group, null);
}
@Override
public String getChatFormat(final String group, final ChatType chatType) {
final String mFormat = chatFormats.getFormat(group, chatType, new ChatFormatConfigSupplier(group, chatType));
if (isDebug()) {
ess.getLogger().info(String.format("Found format '%s' for group '%s'", mFormat, group));
}
return mFormat;
}
private class ChatFormatConfigSupplier implements Supplier<String> {
private final String group;
private final ChatType chatType;
ChatFormatConfigSupplier(String group, ChatType chatType) {
this.group = group;
this.chatType = chatType;
}
@Override
public String get() {
final String chatKey = chatType.key();
final String groupPath = "chat.group-formats." + (group == null ? "Default" : group);
String configFormat = config.getString(groupPath + "." + chatKey, null);
if (configFormat == null) {
configFormat = config.getString(groupPath, null);
}
final String formatPath = "chat.format";
if (configFormat == null) {
configFormat = config.getString(formatPath + "." + chatKey, null);
}
if (configFormat == null) {
configFormat = config.getString(formatPath, null);
}
if (configFormat == null) {
configFormat = "&7[{GROUP}]&r {DISPLAYNAME}&7:&r {MESSAGE}";
}
configFormat = FormatUtil.replaceFormat(configFormat);
configFormat = configFormat.replace("{DISPLAYNAME}", "%1$s");
configFormat = configFormat.replace("{MESSAGE}", "%2$s");
configFormat = configFormat.replace("{GROUP}", "{0}");
configFormat = configFormat.replace("{WORLD}", "{1}");
configFormat = configFormat.replace("{WORLDNAME}", "{1}");
configFormat = configFormat.replace("{SHORTWORLDNAME}", "{2}");
configFormat = configFormat.replace("{TEAMPREFIX}", "{3}");
configFormat = configFormat.replace("{TEAMSUFFIX}", "{4}");
configFormat = configFormat.replace("{TEAMNAME}", "{5}");
configFormat = configFormat.replace("{PREFIX}", "{6}");
configFormat = configFormat.replace("{SUFFIX}", "{7}");
configFormat = configFormat.replace("{USERNAME}", "{8}");
configFormat = configFormat.replace("{NICKNAME}", "{9}");
configFormat = "§r".concat(configFormat);
return configFormat;
}
}
private static class ChatFormats {
private final Map<String, TypedChatFormat> groupFormats;
private TypedChatFormat defaultFormat;
ChatFormats() {
defaultFormat = null;
groupFormats = new HashMap<>();
}
public String getFormat(String group, ChatType type, Supplier<String> configSupplier) {
// With such a large synchronize block, we synchronize a potential config deserialization
// It does not matter as it needs to be done. It's even better as we ensure to do it once
// TypedChatFormat is also synchronized
synchronized (this) {
final TypedChatFormat typedChatFormat;
if (group == null) {
if (defaultFormat == null) {
defaultFormat = new TypedChatFormat();
}
typedChatFormat = defaultFormat;
} else {
typedChatFormat = groupFormats.computeIfAbsent(group, s -> new TypedChatFormat());
}
return typedChatFormat.getFormat(type, configSupplier);
}
}
public void clear() {
synchronized (this) {
defaultFormat = null;
groupFormats.clear();
}
}
}
private static class TypedChatFormat {
private final Map<ChatType, String> typedFormats;
private String defaultFormat;
TypedChatFormat() {
defaultFormat = null;
typedFormats = new EnumMap<>(ChatType.class);
}
public String getFormat(ChatType type, Supplier<String> configSupplier) {
final String format;
if (type == null) {
if (defaultFormat == null) {
defaultFormat = configSupplier.get();
}
format = defaultFormat;
} else {
format = typedFormats.computeIfAbsent(type, c -> configSupplier.get());
}
return format;
}
}
@Override
public String getWorldAlias(String world) {
return worldAliases.getOrDefault(world.toLowerCase(), world);
@@ -693,18 +818,32 @@ public class Settings implements net.ess3.api.ISettings {
overriddenCommands = _getOverriddenCommands();
playerCommands = _getPlayerCommands();
final KnownCommandsProvider knownCommandsProvider = ess.provider(KnownCommandsProvider.class);
// This will be late loaded
if (ess.getKnownCommandsProvider() != null) {
if (knownCommandsProvider != null) {
boolean mapModified = false;
if (!disabledBukkitCommands.isEmpty()) {
if (isDebug()) {
ess.getLogger().log(Level.INFO, "Re-adding " + disabledBukkitCommands.size() + " disabled commands!");
}
ess.getKnownCommandsProvider().getKnownCommands().putAll(disabledBukkitCommands);
knownCommandsProvider.getKnownCommands().putAll(disabledBukkitCommands);
disabledBukkitCommands.clear();
mapModified = true;
}
if (reloadCount.get() < 2) {
// on startup: add plugins again in case they registered commands with the new API
// we need to schedule this task before any of the below tasks using _addAlternativeCommand.
ess.scheduleSyncDelayedTask(() -> {
for (final Plugin plugin : ess.getServer().getPluginManager().getPlugins()) {
if (plugin.isEnabled()) {
ess.getAlternativeCommandsHandler().addPlugin(plugin);
}
}
});
}
for (final String command : disabledCommands) {
final String effectiveAlias = command.toLowerCase(Locale.ENGLISH);
final Command toDisable = ess.getPluginCommand(effectiveAlias);
@@ -712,7 +851,7 @@ public class Settings implements net.ess3.api.ISettings {
if (isDebug()) {
ess.getLogger().log(Level.INFO, "Attempting removal of " + effectiveAlias);
}
final Command removed = ess.getKnownCommandsProvider().getKnownCommands().remove(effectiveAlias);
final Command removed = knownCommandsProvider.getKnownCommands().remove(effectiveAlias);
if (removed != null) {
if (isDebug()) {
ess.getLogger().log(Level.INFO, "Adding command " + effectiveAlias + " to disabled map!");
@@ -730,14 +869,16 @@ public class Settings implements net.ess3.api.ISettings {
}
}
final SyncCommandsProvider syncCommandsProvider = ess.provider(SyncCommandsProvider.class);
if (mapModified) {
if (isDebug()) {
ess.getLogger().log(Level.INFO, "Syncing commands");
}
if (reloadCount.get() < 2) {
ess.scheduleSyncDelayedTask(() -> ess.getSyncCommandsProvider().syncCommands());
ess.scheduleSyncDelayedTask(syncCommandsProvider::syncCommands);
} else {
ess.getSyncCommandsProvider().syncCommands();
syncCommandsProvider.syncCommands();
}
}
}
@@ -795,6 +936,8 @@ public class Settings implements net.ess3.api.ISettings {
worldAliases = _getWorldAliases();
primaryColor = _getPrimaryColor();
secondaryColor = _getSecondaryColor();
multiplierPerms = _getMultiplierPerms();
defaultMultiplier = _getDefaultMultiplier();
reloadCount.incrementAndGet();
}
@@ -953,14 +1096,23 @@ public class Settings implements net.ess3.api.ISettings {
}
@Override
public List<Material> getProtectList(final String configName) {
final List<Material> list = new ArrayList<>();
public List<String> getProtectListRaw(String configName) {
final List<String> list = new ArrayList<>();
for (String itemName : config.getString(configName, "").split(",")) {
itemName = itemName.trim();
if (itemName.isEmpty()) {
continue;
}
list.add(itemName);
}
return list;
}
@Override
public List<Material> getProtectList(final String configName) {
final List<Material> list = new ArrayList<>();
for (String itemName : getProtectListRaw(configName)) {
Material mat = EnumUtil.getMaterial(itemName.toUpperCase());
if (mat == null) {
@@ -1781,6 +1933,11 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("world-change-fly-reset", true);
}
@Override
public boolean isWorldChangePreserveFlying() {
return config.getBoolean("world-change-preserve-flying", true);
}
@Override
public boolean isWorldChangeSpeedResetEnabled() {
return config.getBoolean("world-change-speed-reset", true);
@@ -1788,9 +1945,7 @@ public class Settings implements net.ess3.api.ISettings {
private List<String> _getDefaultEnabledConfirmCommands() {
final List<String> commands = config.getList("default-enabled-confirm-commands", String.class);
for (int i = 0; i < commands.size(); i++) {
commands.set(i, commands.get(i).toLowerCase());
}
commands.replaceAll(String::toLowerCase);
return commands;
}
@@ -1966,6 +2121,38 @@ public class Settings implements net.ess3.api.ISettings {
}
@Override
public String getNickRegex() {
return config.getString("allowed-nicks-regex", "^[a-zA-Z_0-9§]+$");
}
@Override
public BigDecimal getMultiplier(final User user) {
BigDecimal multiplier = defaultMultiplier;
if (multiplierPerms == null) {
return defaultMultiplier;
}
for (final String multiplierPerm : multiplierPerms) {
if (user.isAuthorized("essentials.sell.multiplier." + multiplierPerm)) {
final BigDecimal value = config.getBigDecimal("sell-multipliers." + multiplierPerm, BigDecimal.ZERO);
if (value.compareTo(multiplier) > 0) {
multiplier = value;
}
}
}
return multiplier;
}
private BigDecimal _getDefaultMultiplier() {
return config.getBigDecimal("sell-multipliers.default", BigDecimal.ONE);
}
private Set<String> _getMultiplierPerms() {
final CommentedConfigurationNode section = config.getSection("sell-multipliers");
return section == null ? null : ConfigurateUtil.getKeys(section);
}
public int getMaxItemLore() {
return config.getInt("max-itemlore-lines", 10);
}
@@ -2007,4 +2194,14 @@ public class Settings implements net.ess3.api.ISettings {
}
return null;
}
@Override
public BigDecimal getBaltopMinBalance() {
return config.getBigDecimal("baltop-requirements.minimum-balance", BigDecimal.ZERO);
}
@Override
public long getBaltopMinPlaytime() {
return config.getLong("baltop-requirements.minimum-playtime", 0);
}
}
@@ -1,402 +0,0 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.LocationUtil;
import io.papermc.lib.PaperLib;
import net.ess3.api.IEssentials;
import net.ess3.api.ITeleport;
import net.ess3.api.IUser;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.UserWarpEvent;
import net.ess3.api.events.teleport.PreTeleportEvent;
import net.ess3.api.events.teleport.TeleportWarmupEvent;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.GregorianCalendar;
/**
* @deprecated This API is not asynchronous. Use {@link com.earth2me.essentials.AsyncTeleport AsyncTeleport}
*/
@Deprecated
public class Teleport implements ITeleport {
private final IUser teleportOwner;
private final IEssentials ess;
private TimedTeleport timedTeleport;
private TeleportType tpType;
@Deprecated
public Teleport(final IUser user, final IEssentials ess) {
this.teleportOwner = user;
this.ess = ess;
tpType = TeleportType.NORMAL;
}
@Deprecated
public void cooldown(final boolean check) throws Exception {
final Calendar time = new GregorianCalendar();
if (teleportOwner.getLastTeleportTimestamp() > 0) {
// Take the current time, and remove the delay from it.
final double cooldown = ess.getSettings().getTeleportCooldown();
final Calendar earliestTime = new GregorianCalendar();
earliestTime.add(Calendar.SECOND, -(int) cooldown);
earliestTime.add(Calendar.MILLISECOND, -(int) ((cooldown * 1000.0) % 1000.0));
// This value contains the most recent time a teleportPlayer could have been used that would allow another use.
final long earliestLong = earliestTime.getTimeInMillis();
// When was the last teleportPlayer used?
final long lastTime = teleportOwner.getLastTeleportTimestamp();
if (lastTime > time.getTimeInMillis()) {
// This is to make sure time didn't get messed up on last teleportPlayer use.
// If this happens, let's give the user the benifit of the doubt.
teleportOwner.setLastTeleportTimestamp(time.getTimeInMillis());
return;
} else if (lastTime > earliestLong
&& cooldownApplies()) {
time.setTimeInMillis(lastTime);
time.add(Calendar.SECOND, (int) cooldown);
time.add(Calendar.MILLISECOND, (int) ((cooldown * 1000.0) % 1000.0));
throw new TranslatableException("timeBeforeTeleport", DateUtil.formatDateDiff(time.getTimeInMillis()));
}
}
// if justCheck is set, don't update lastTeleport; we're just checking
if (!check) {
teleportOwner.setLastTeleportTimestamp(time.getTimeInMillis());
}
}
@Deprecated
private boolean cooldownApplies() {
boolean applies = true;
final String globalBypassPerm = "essentials.teleport.cooldown.bypass";
switch (tpType) {
case NORMAL:
applies = !teleportOwner.isAuthorized(globalBypassPerm);
break;
case BACK:
applies = !(teleportOwner.isAuthorized(globalBypassPerm) &&
teleportOwner.isAuthorized("essentials.teleport.cooldown.bypass.back"));
break;
case TPA:
applies = !(teleportOwner.isAuthorized(globalBypassPerm) &&
teleportOwner.isAuthorized("essentials.teleport.cooldown.bypass.tpa"));
break;
}
return applies;
}
@Deprecated
private void warnUser(final IUser user, final double delay) {
final Calendar c = new GregorianCalendar();
c.add(Calendar.SECOND, (int) delay);
c.add(Calendar.MILLISECOND, (int) ((delay * 1000.0) % 1000.0));
user.sendTl("dontMoveMessage", DateUtil.formatDateDiff(c.getTimeInMillis()));
}
//The now function is used when you want to skip tp delay when teleporting someone to a location or player.
@Override
@Deprecated
public void now(final Location loc, final boolean cooldown, final TeleportCause cause) throws Exception {
if (cooldown) {
cooldown(false);
}
final ITarget target = new LocationTarget(loc);
now(teleportOwner, target, cause);
}
@Override
@Deprecated
public void now(final Player entity, final boolean cooldown, final TeleportCause cause) throws Exception {
if (cooldown) {
cooldown(false);
}
final ITarget target = new PlayerTarget(entity);
now(teleportOwner, target, cause);
teleportOwner.sendTl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ());
}
@Deprecated
protected void now(final IUser teleportee, final ITarget target, final TeleportCause cause) throws Exception {
cancel(false);
Location loc = target.getLocation();
final PreTeleportEvent event = new PreTeleportEvent(teleportee, cause, target);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
if (teleportee.isAuthorized("essentials.back.onteleport")) {
teleportee.setLastLocation();
}
if (!teleportee.getBase().isEmpty()) {
if (!ess.getSettings().isTeleportPassengerDismount()) {
throw new TranslatableException("passengerTeleportFail");
}
teleportee.getBase().eject();
}
if (LocationUtil.isBlockUnsafeForUser(ess, teleportee, loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
if (ess.getSettings().isTeleportSafetyEnabled()) {
if (ess.getSettings().isForceDisableTeleportSafety()) {
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
} else {
PaperLib.teleportAsync(teleportee.getBase(), LocationUtil.getSafeDestination(ess, teleportee, loc), cause);
}
} else {
throw new TranslatableException("unsafeTeleportDestination", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
}
} else {
if (ess.getSettings().isForceDisableTeleportSafety()) {
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
} else {
if (ess.getSettings().isTeleportToCenterLocation()) {
loc = LocationUtil.getRoundedDestination(loc);
}
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
}
}
}
//The teleportPlayer function is used when you want to normally teleportPlayer someone to a location or player.
//This method is nolonger used internally and will be removed.
@Deprecated
@Override
public void teleport(final Location loc, final Trade chargeFor) throws Exception {
teleport(loc, chargeFor, TeleportCause.PLUGIN);
}
@Override
@Deprecated
public void teleport(final Location loc, final Trade chargeFor, final TeleportCause cause) throws Exception {
teleport(teleportOwner, new LocationTarget(loc), chargeFor, cause);
}
//This is used when teleporting to a player
@Override
@Deprecated
public void teleport(final Player entity, final Trade chargeFor, final TeleportCause cause) throws Exception {
final ITarget target = new PlayerTarget(entity);
teleportOwner.sendTl("teleportToPlayer", entity.getDisplayName());
teleport(teleportOwner, target, chargeFor, cause);
}
//This is used when teleporting to stored location
@Override
@Deprecated
public void teleportPlayer(final IUser teleportee, final Location loc, final Trade chargeFor, final TeleportCause cause) throws Exception {
teleport(teleportee, new LocationTarget(loc), chargeFor, cause);
}
//This is used on /tphere
@Override
@Deprecated
public void teleportPlayer(final IUser teleportee, final Player entity, final Trade chargeFor, final TeleportCause cause) throws Exception {
final ITarget target = new PlayerTarget(entity);
teleport(teleportee, target, chargeFor, cause);
teleportee.sendTl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ());
teleportOwner.sendTl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ());
}
@Deprecated
private void teleport(final IUser teleportee, final ITarget target, final Trade chargeFor, final TeleportCause cause) throws Exception {
double delay = ess.getSettings().getTeleportDelay();
final TeleportWarmupEvent event = new TeleportWarmupEvent(teleportee, cause, target, delay);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
delay = event.getDelay();
Trade cashCharge = chargeFor;
if (chargeFor != null) {
chargeFor.isAffordableFor(teleportOwner);
//This code is to make sure that commandcosts are checked in the initial world, and not in the resulting world.
if (!chargeFor.getCommandCost(teleportOwner).equals(BigDecimal.ZERO)) {
//By converting a command cost to a regular cost, the command cost permission isn't checked when executing the charge after teleport.
cashCharge = new Trade(chargeFor.getCommandCost(teleportOwner), ess);
}
}
cooldown(true);
if (delay <= 0 || teleportOwner.isAuthorized("essentials.teleport.timer.bypass") || teleportee.isAuthorized("essentials.teleport.timer.bypass")) {
cooldown(false);
now(teleportee, target, cause);
if (cashCharge != null) {
cashCharge.charge(teleportOwner);
}
return;
}
cancel(false);
warnUser(teleportee, delay);
initTimer((long) (delay * 1000.0), teleportee, target, cashCharge, cause, false);
}
@Deprecated
private void teleportOther(final IUser teleporter, final IUser teleportee, final ITarget target, final Trade chargeFor, final TeleportCause cause) throws Exception {
double delay = ess.getSettings().getTeleportDelay();
final TeleportWarmupEvent event = new TeleportWarmupEvent(teleporter, teleportee, cause, target, delay);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
delay = event.getDelay();
Trade cashCharge = chargeFor;
if (teleporter != null && chargeFor != null) {
chargeFor.isAffordableFor(teleporter);
//This code is to make sure that commandcosts are checked in the initial world, and not in the resulting world.
if (!chargeFor.getCommandCost(teleporter).equals(BigDecimal.ZERO)) {
//By converting a command cost to a regular cost, the command cost permission isn't checked when executing the charge after teleport.
cashCharge = new Trade(chargeFor.getCommandCost(teleporter), ess);
}
}
cooldown(true);
if (delay <= 0 || teleporter == null
|| teleporter.isAuthorized("essentials.teleport.timer.bypass")
|| teleportOwner.isAuthorized("essentials.teleport.timer.bypass")
|| teleportee.isAuthorized("essentials.teleport.timer.bypass")) {
cooldown(false);
now(teleportee, target, cause);
if (teleporter != null && cashCharge != null) {
cashCharge.charge(teleporter);
}
return;
}
cancel(false);
warnUser(teleportee, delay);
initTimer((long) (delay * 1000.0), teleportee, target, cashCharge, cause, false);
}
//The respawn function is a wrapper used to handle tp fallback, on /jail and /home
@Override
@Deprecated
public void respawn(final Trade chargeFor, final TeleportCause cause) throws Exception {
double delay = ess.getSettings().getTeleportDelay();
final TeleportWarmupEvent event = new TeleportWarmupEvent(teleportOwner, cause, null, delay);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
delay = event.getDelay();
if (chargeFor != null) {
chargeFor.isAffordableFor(teleportOwner);
}
cooldown(true);
if (delay <= 0 || teleportOwner.isAuthorized("essentials.teleport.timer.bypass")) {
cooldown(false);
respawnNow(teleportOwner, cause);
if (chargeFor != null) {
chargeFor.charge(teleportOwner);
}
return;
}
cancel(false);
warnUser(teleportOwner, delay);
initTimer((long) (delay * 1000.0), teleportOwner, null, chargeFor, cause, true);
}
@Deprecated
void respawnNow(final IUser teleportee, final TeleportCause cause) throws Exception {
final Player player = teleportee.getBase();
final Location bed = player.getBedSpawnLocation();
if (bed != null) {
now(teleportee, new LocationTarget(bed), cause);
} else {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("Could not find bed spawn, forcing respawn event.");
}
final PlayerRespawnEvent pre = new PlayerRespawnEvent(player, player.getWorld().getSpawnLocation(), false);
ess.getServer().getPluginManager().callEvent(pre);
now(teleportee, new LocationTarget(pre.getRespawnLocation()), cause);
}
}
//The warp function is a wrapper used to teleportPlayer a player to a /warp
@Override
@Deprecated
public void warp(final IUser teleportee, String warp, final Trade chargeFor, final TeleportCause cause) throws Exception {
final UserWarpEvent event = new UserWarpEvent(teleportee, warp, chargeFor);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
warp = event.getWarp();
final Location loc = ess.getWarps().getWarp(warp);
teleportee.sendTl("warpingTo", warp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
if (!teleportee.equals(teleportOwner)) {
teleportOwner.sendTl("warpingTo", warp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
}
teleport(teleportee, new LocationTarget(loc), chargeFor, cause);
}
//The back function is a wrapper used to teleportPlayer a player /back to their previous location.
@Override
@Deprecated
public void back(final Trade chargeFor) throws Exception {
back(teleportOwner, chargeFor);
}
//This function is a wrapper over the other back function for cases where another player performs back for them
@Override
@Deprecated
public void back(final IUser teleporter, final Trade chargeFor) throws Exception {
tpType = TeleportType.BACK;
final Location loc = teleportOwner.getLastLocation();
teleportOwner.sendTl("backUsageMsg", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
teleportOther(teleporter, teleportOwner, new LocationTarget(loc), chargeFor, TeleportCause.COMMAND);
}
//This function is used to throw a user back after a jail sentence
@Override
@Deprecated
public void back() throws Exception {
now(teleportOwner, new LocationTarget(teleportOwner.getLastLocation()), TeleportCause.COMMAND);
}
@Deprecated
public void setTpType(final TeleportType tpType) {
this.tpType = tpType;
}
//If we need to cancelTimer a pending teleportPlayer call this method
@Deprecated
private void cancel(final boolean notifyUser) {
if (timedTeleport != null) {
timedTeleport.cancelTimer(notifyUser);
timedTeleport = null;
}
}
@Deprecated
private void initTimer(final long delay, final IUser teleportUser, final ITarget target, final Trade chargeFor, final TeleportCause cause, final boolean respawn) {
timedTeleport = new TimedTeleport(teleportOwner, ess, this, delay, teleportUser, target, chargeFor, cause, respawn);
}
public enum TeleportType {
TPA,
BACK,
NORMAL
}
}
@@ -1,138 +0,0 @@
package com.earth2me.essentials;
import net.ess3.api.IEssentials;
import net.ess3.api.IUser;
import org.bukkit.Location;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.util.UUID;
@Deprecated
public class TimedTeleport implements Runnable {
private static final double MOVE_CONSTANT = 0.3;
private final IUser teleportOwner;
private final IEssentials ess;
private final Teleport teleport;
private final UUID timer_teleportee;
private final long timer_started; // time this task was initiated
private final long timer_delay; // how long to delay the teleportPlayer
// note that I initially stored a clone of the location for reference, but...
// when comparing locations, I got incorrect mismatches (rounding errors, looked like)
// so, the X/Y/Z values are stored instead and rounded off
private final long timer_initX;
private final long timer_initY;
private final long timer_initZ;
private final ITarget timer_teleportTarget;
private final boolean timer_respawn;
private final boolean timer_canMove;
private final Trade timer_chargeFor;
private final TeleportCause timer_cause;
private int timer_task;
private double timer_health;
TimedTeleport(final IUser user, final IEssentials ess, final Teleport teleport, final long delay, final IUser teleportUser, final ITarget target, final Trade chargeFor, final TeleportCause cause, final boolean respawn) {
this.teleportOwner = user;
this.ess = ess;
this.teleport = teleport;
this.timer_started = System.currentTimeMillis();
this.timer_delay = delay;
this.timer_health = teleportUser.getBase().getHealth();
this.timer_initX = Math.round(teleportUser.getBase().getLocation().getX() * MOVE_CONSTANT);
this.timer_initY = Math.round(teleportUser.getBase().getLocation().getY() * MOVE_CONSTANT);
this.timer_initZ = Math.round(teleportUser.getBase().getLocation().getZ() * MOVE_CONSTANT);
this.timer_teleportee = teleportUser.getBase().getUniqueId();
this.timer_teleportTarget = target;
this.timer_chargeFor = chargeFor;
this.timer_cause = cause;
this.timer_respawn = respawn;
this.timer_canMove = user.isAuthorized("essentials.teleport.timer.move");
timer_task = ess.runTaskTimerAsynchronously(this, 20, 20).getTaskId();
}
@Override
public void run() {
if (teleportOwner == null || !teleportOwner.getBase().isOnline() || teleportOwner.getBase().getLocation() == null) {
cancelTimer(false);
return;
}
final IUser teleportUser = ess.getUser(this.timer_teleportee);
if (teleportUser == null || !teleportUser.getBase().isOnline()) {
cancelTimer(false);
return;
}
final Location currLocation = teleportUser.getBase().getLocation();
if (currLocation == null) {
cancelTimer(false);
return;
}
if (!timer_canMove && (Math.round(currLocation.getX() * MOVE_CONSTANT) != timer_initX || Math.round(currLocation.getY() * MOVE_CONSTANT) != timer_initY || Math.round(currLocation.getZ() * MOVE_CONSTANT) != timer_initZ || teleportUser.getBase().getHealth() < timer_health)) {
// user moved, cancelTimer teleportPlayer
cancelTimer(true);
return;
}
class DelayedTeleportTask implements Runnable {
@Override
public void run() {
timer_health = teleportUser.getBase().getHealth(); // in case user healed, then later gets injured
final long now = System.currentTimeMillis();
if (now > timer_started + timer_delay) {
try {
teleport.cooldown(false);
} catch (final Exception ex) {
teleportOwner.sendTl("cooldownWithMessage", ex.getMessage());
if (teleportOwner != teleportUser) {
teleportUser.sendTl("cooldownWithMessage", ex.getMessage());
}
}
try {
cancelTimer(false);
teleportUser.sendTl("teleportationCommencing");
if (timer_chargeFor != null) {
timer_chargeFor.isAffordableFor(teleportOwner);
}
if (timer_respawn) {
teleport.respawnNow(teleportUser, timer_cause);
} else {
teleport.now(teleportUser, timer_teleportTarget, timer_cause);
}
if (timer_chargeFor != null) {
timer_chargeFor.charge(teleportOwner);
}
} catch (final Exception ex) {
ess.showError(teleportOwner.getSource(), ex, "\\ teleport");
}
}
}
}
ess.scheduleSyncDelayedTask(new DelayedTeleportTask());
}
//If we need to cancelTimer a pending teleportPlayer call this method
void cancelTimer(final boolean notifyUser) {
if (timer_task == -1) {
return;
}
try {
ess.getServer().getScheduler().cancelTask(timer_task);
if (notifyUser) {
teleportOwner.sendTl("pendingTeleportCancelled");
if (timer_teleportee != null && !timer_teleportee.equals(teleportOwner.getBase().getUniqueId())) {
ess.getUser(timer_teleportee).sendTl("pendingTeleportCancelled");
}
}
} finally {
timer_task = -1;
}
}
}
@@ -2,6 +2,7 @@ package com.earth2me.essentials;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.craftbukkit.SetExpFix;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
@@ -191,7 +192,7 @@ public class Trade {
}
if (getMoney() != null && getMoney().signum() > 0 && !user.canAfford(getMoney())) {
future.completeExceptionally(new ChargeException("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess)));
future.completeExceptionally(new ChargeException("notEnoughMoney", AdventureUtil.parsed(NumberUtil.displayCurrency(getMoney(), ess))));
return;
}
@@ -202,7 +203,7 @@ public class Trade {
final BigDecimal money;
if (command != null && !command.isEmpty() && (money = getCommandCost(user)).signum() > 0 && !user.canAfford(money)) {
future.completeExceptionally(new ChargeException("notEnoughMoney", NumberUtil.displayCurrency(money, ess)));
future.completeExceptionally(new ChargeException("notEnoughMoney", AdventureUtil.parsed(NumberUtil.displayCurrency(money, ess))));
return;
}
@@ -241,8 +242,8 @@ public class Trade {
} else {
for (final ItemStack itemStack : leftover.values()) {
int spillAmount = itemStack.getAmount();
itemStack.setAmount(Math.min(spillAmount, itemStack.getMaxStackSize()));
while (spillAmount > 0) {
itemStack.setAmount(Math.min(spillAmount, itemStack.getMaxStackSize()));
user.getBase().getWorld().dropItemNaturally(user.getBase().getLocation(), itemStack);
spillAmount -= itemStack.getAmount();
}
@@ -285,7 +286,7 @@ public class Trade {
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " money " + getMoney().toPlainString());
}
if (!user.canAfford(getMoney()) && getMoney().signum() > 0) {
future.completeExceptionally(new ChargeException("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess)));
future.completeExceptionally(new ChargeException("notEnoughMoney", AdventureUtil.parsed(NumberUtil.displayCurrency(getMoney(), ess))));
return;
}
user.takeMoney(getMoney());
@@ -304,7 +305,7 @@ public class Trade {
if (command != null) {
final BigDecimal cost = getCommandCost(user);
if (!user.canAfford(cost) && cost.signum() > 0) {
future.completeExceptionally(new ChargeException("notEnoughMoney", NumberUtil.displayCurrency(cost, ess)));
future.completeExceptionally(new ChargeException("notEnoughMoney", AdventureUtil.parsed(NumberUtil.displayCurrency(cost, ess))));
return;
}
user.takeMoney(cost);
@@ -21,6 +21,7 @@ import net.ess3.api.events.AfkStatusChangeEvent;
import net.ess3.api.events.JailStatusChangeEvent;
import net.ess3.api.events.MuteStatusChangeEvent;
import net.ess3.api.events.UserBalanceUpdateEvent;
import net.ess3.provider.PlayerLocaleProvider;
import net.essentialsx.api.v2.events.TransactionEvent;
import net.essentialsx.api.v2.services.mail.MailSender;
import net.kyori.adventure.text.Component;
@@ -62,8 +63,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
// User modules
private final IMessageRecipient messageRecipient;
private transient final AsyncTeleport teleport;
@SuppressWarnings("deprecation")
private transient final Teleport legacyTeleport;
// User command confirmation strings
private final Map<User, BigDecimal> confirmingPayments = new WeakHashMap<>();
@@ -101,14 +100,13 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
// Misc
private transient final List<String> signCopy = Lists.newArrayList("", "", "", "");
private transient long lastVanishTime = System.currentTimeMillis();
private transient int flightTick = -1;
private String lastLocaleString;
private Locale playerLocale;
public User(final Player base, final IEssentials ess) {
super(base, ess);
teleport = new AsyncTeleport(this, ess);
//noinspection deprecation
legacyTeleport = new Teleport(this, ess);
if (isAfk()) {
afkPosition = this.getLocation();
}
@@ -138,6 +136,10 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public boolean isAuthorized(final String node) {
if (Essentials.TESTING) {
return false;
}
final boolean result = isAuthorizedCheck(node);
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "checking if " + base.getName() + " has " + node + " - " + result);
@@ -147,6 +149,10 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public boolean isPermissionSet(final String node) {
if (Essentials.TESTING) {
return false;
}
final boolean result = isPermSetCheck(node);
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "checking if " + base.getName() + " has " + node + " (set-explicit) - " + result);
@@ -247,9 +253,9 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return;
}
setMoney(getMoney().add(value), cause);
sendTl("addedToAccount", NumberUtil.displayCurrency(value, ess));
sendTl("addedToAccount", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)));
if (initiator != null) {
initiator.sendTl("addedToOthersAccount", NumberUtil.displayCurrency(value, ess), getDisplayName(), NumberUtil.displayCurrency(getMoney(), ess));
initiator.sendTl("addedToOthersAccount", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)), getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(getMoney(), ess)));
}
}
@@ -266,12 +272,12 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
if (canAfford(value)) {
setMoney(getMoney().subtract(value), cause);
reciever.setMoney(reciever.getMoney().add(value), cause);
sendTl("moneySentTo", NumberUtil.displayCurrency(value, ess), reciever.getDisplayName());
reciever.sendTl("moneyRecievedFrom", NumberUtil.displayCurrency(value, ess), getDisplayName());
sendTl("moneySentTo", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)), reciever.getDisplayName());
reciever.sendTl("moneyRecievedFrom", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)), getDisplayName());
final TransactionEvent transactionEvent = new TransactionEvent(this.getSource(), reciever, value);
ess.getServer().getPluginManager().callEvent(transactionEvent);
} else {
throw new ChargeException("notEnoughMoney", NumberUtil.displayCurrency(value, ess));
throw new ChargeException("notEnoughMoney", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)));
}
}
@@ -294,9 +300,9 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
} catch (final MaxMoneyException ex) {
ess.getLogger().log(Level.WARNING, "Invalid call to takeMoney, total balance can't be more than the max-money limit.", ex);
}
sendTl("takenFromAccount", NumberUtil.displayCurrency(value, ess));
sendTl("takenFromAccount", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)));
if (initiator != null) {
initiator.sendTl("takenFromOthersAccount", NumberUtil.displayCurrency(value, ess), getDisplayName(), NumberUtil.displayCurrency(getMoney(), ess));
initiator.sendTl("takenFromOthersAccount", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)), getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(getMoney(), ess)));
}
}
@@ -375,13 +381,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
teleportRequestQueue.put(request.getName(), request);
}
@SuppressWarnings("deprecation")
@Override
@Deprecated
public boolean hasOutstandingTeleportRequest() {
return getNextTpaRequest(false, false, false) != null;
}
public Collection<String> getPendingTpaKeys() {
return teleportRequestQueue.keySet();
}
@@ -565,16 +564,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return teleport;
}
/**
* @deprecated This API is not asynchronous. Use {@link User#getAsyncTeleport()}
*/
@SuppressWarnings("deprecation")
@Override
@Deprecated
public Teleport getTeleport() {
return legacyTeleport;
}
public long getLastOnlineActivity() {
return lastOnlineActivity;
}
@@ -794,6 +783,11 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return false;
}
@Override
public long getLastActivityTime() {
return this.lastActivity;
}
@Deprecated
public void updateActivity(final boolean broadcast) {
updateActivity(broadcast, AfkStatusChangeEvent.Cause.UNKNOWN);
@@ -1088,7 +1082,8 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public String playerTl(String tlKey, Object... args) {
if (ess.getSettings().isPerPlayerLocale()) {
return tlLocale(getPlayerLocale(ess.getPlayerLocaleProvider().getLocale(base)), tlKey, args);
final PlayerLocaleProvider provider = ess.provider(PlayerLocaleProvider.class);
return tlLocale(getPlayerLocale(provider.getLocale(base)), tlKey, args);
}
return tlLiteral(tlKey, args);
}
@@ -1297,4 +1292,12 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
return toggleShout == null ? toggleShout = ess.getSettings().isShoutDefault() : toggleShout;
}
public int getFlightTick() {
return flightTick;
}
public void setFlightTick(int flightTick) {
this.flightTick = flightTick;
}
}
@@ -348,7 +348,17 @@ public abstract class UserData extends PlayerExtension implements IConf {
}
public int getMailAmount() {
return holder.mail() == null ? 0 : holder.mail().size();
if (holder.mail() == null) {
return 0;
}
int amount = 0;
for (MailMessage element : holder.mail()) {
if (!element.isExpired()) {
amount++;
}
}
return amount;
}
public int getUnreadMailAmount() {
@@ -358,7 +368,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
int unread = 0;
for (MailMessage element : holder.mail()) {
if (!element.isRead()) {
if (!element.isRead() && !element.isExpired()) {
unread++;
}
}
@@ -5,7 +5,6 @@ import com.earth2me.essentials.config.EssentialsConfiguration;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.StringUtil;
import net.ess3.api.InvalidNameException;
import net.ess3.api.InvalidWorldException;
import net.ess3.api.TranslatableException;
import org.bukkit.Location;
@@ -54,7 +53,7 @@ public class Warps implements IConf, net.ess3.api.IWarps {
}
@Override
public Location getWarp(final String warp) throws WarpNotFoundException, InvalidWorldException {
public Location getWarp(final String warp) throws WarpNotFoundException {
final EssentialsConfiguration conf = warpPoints.get(new StringIgnoreCase(warp));
if (conf == null) {
throw new WarpNotFoundException();
@@ -79,7 +78,7 @@ public class Warps implements IConf, net.ess3.api.IWarps {
if (conf == null) {
final File confFile = new File(warpsFolder, filename + ".yml");
if (confFile.exists()) {
throw new Exception(user == null ? tlLiteral("similarWarpExist") : user.playerTl("similarWarpExist"));
throw new TranslatableException("similarWarpExist");
}
conf = new EssentialsConfiguration(confFile);
conf.load();
@@ -46,17 +46,6 @@ public interface IJails extends IConf {
*/
void removeJail(String jail) throws Exception;
/**
* Attempts to send the given user to the given jail
*
* @param user the user to send to jail
* @param jail the jail to send the user to
* @throws Exception if the user is offline or jail does not exist
* @deprecated Use {@link IJails#sendToJail(IUser, String, CompletableFuture)}
*/
@Deprecated
void sendToJail(IUser user, String jail) throws Exception;
/**
* Attempts to send the given user to the given jail
*
@@ -22,9 +22,8 @@ public interface IWarps extends IConf {
* @param warp - Warp name
* @return - Location the warp is set to
* @throws WarpNotFoundException When the warp is not found
* @throws net.ess3.api.InvalidWorldException When the world the warp is in is not found
*/
Location getWarp(String warp) throws WarpNotFoundException, net.ess3.api.InvalidWorldException;
Location getWarp(String warp) throws WarpNotFoundException;
/**
* Checks if the provided name is a warp.
@@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.provider.ContainerProvider;
import org.bukkit.Server;
public class Commandanvil extends EssentialsCommand {
@@ -11,11 +12,13 @@ public class Commandanvil extends EssentialsCommand {
@Override
protected void run(Server server, User user, String commandLabel, String[] args) throws Exception {
if (ess.getContainerProvider() == null) {
final ContainerProvider containerProvider = ess.provider(ContainerProvider.class);
if (containerProvider == null) {
user.sendTl("unsupportedBrand");
return;
}
ess.getContainerProvider().openAnvil(user.getBase());
containerProvider.openAnvil(user.getBase());
}
}
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.NumberUtil;
import org.bukkit.Server;
@@ -20,16 +21,16 @@ public class Commandbalance extends EssentialsCommand {
}
final User target = getPlayer(server, args, 0, false, true);
sender.sendTl("balanceOther", target.isHidden() ? target.getName() : target.getDisplayName(), NumberUtil.displayCurrency(target.getMoney(), ess));
sender.sendTl("balanceOther", target.isHidden() ? target.getName() : target.getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(target.getMoney(), ess)));
}
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
if (args.length == 1 && user.isAuthorized("essentials.balance.others")) {
final User target = getPlayer(server, args, 0, true, true);
user.sendTl("balanceOther", target.isHidden() ? target.getName() : target.getDisplayName(), NumberUtil.displayCurrency(target.getMoney(), ess));
user.sendTl("balanceOther", target.isHidden() ? target.getName() : target.getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(target.getMoney(), ess)));
} else if (args.length < 2) {
user.sendTl("balance", NumberUtil.displayCurrency(user.getMoney(), ess));
user.sendTl("balance", AdventureUtil.parsed(NumberUtil.displayCurrency(user.getMoney(), ess)));
} else {
throw new NotEnoughArgumentsException();
}
@@ -1,13 +1,18 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.textreader.SimpleTextInput;
import com.earth2me.essentials.textreader.TextPager;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists;
import net.essentialsx.api.v2.services.BalanceTop;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.Statistic;
import org.bukkit.command.BlockCommandSender;
import java.math.BigDecimal;
@@ -110,17 +115,38 @@ public class Commandbalancetop extends EssentialsCommand {
future.thenRun(() -> {
if (fresh) {
final SimpleTextInput newCache = new SimpleTextInput();
newCache.getLines().add(AdventureUtil.miniToLegacy(tlLiteral("serverTotal", NumberUtil.displayCurrency(ess.getBalanceTop().getBalanceTopTotal(), ess))));
newCache.getLines().add(AdventureUtil.miniToLegacy(tlLiteral("serverTotal", AdventureUtil.parsed(NumberUtil.displayCurrency(ess.getBalanceTop().getBalanceTopTotal(), ess)))));
int pos = 1;
for (final Map.Entry<UUID, BalanceTop.Entry> entry : ess.getBalanceTop().getBalanceTopCache().entrySet()) {
if (ess.getSettings().showZeroBaltop() || entry.getValue().getBalance().compareTo(BigDecimal.ZERO) > 0) {
newCache.getLines().add(AdventureUtil.miniToLegacy(tlLiteral("balanceTopLine", pos, entry.getValue().getDisplayName(), NumberUtil.displayCurrency(entry.getValue().getBalance(), ess))));
final BigDecimal balance = entry.getValue().getBalance();
final User user = ess.getUser(entry.getKey());
final Statistic PLAY_ONE_TICK = EnumUtil.getStatistic("PLAY_ONE_MINUTE", "PLAY_ONE_TICK");
final boolean offlineStatisticSupported = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_15_2_R01);
final long playtime;
if (user.getBase() == null || !user.getBase().isOnline()) {
if (offlineStatisticSupported) {
playtime = Bukkit.getServer().getOfflinePlayer(entry.getKey()).getStatistic(PLAY_ONE_TICK);
} else {
playtime = -1;
}
} else {
playtime = user.getBase().getStatistic(PLAY_ONE_TICK);
}
// Play time in seconds
final long playTimeSecs = Math.max(playtime / 20, 0);
// Checking if player meets the requirements of minimum balance and minimum playtime to be listed in baltop list
if ((ess.getSettings().showZeroBaltop() || balance.compareTo(BigDecimal.ZERO) > 0)
&& balance.compareTo(ess.getSettings().getBaltopMinBalance()) >= 0 &&
// Skip playtime check for offline players on versions below 1.15.2
(playtime == -1 || playTimeSecs >= ess.getSettings().getBaltopMinPlaytime())) {
newCache.getLines().add(AdventureUtil.miniToLegacy(tlLiteral("balanceTopLine", pos, entry.getValue().getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(balance, ess)))));
}
pos++;
}
cache = newCache;
}
outputCache(sender, page);
});
}
@@ -4,12 +4,14 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists;
import net.ess3.api.TranslatableException;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.WritableBookMeta;
import java.util.Collections;
import java.util.List;
@@ -50,7 +52,14 @@ public class Commandbook extends EssentialsCommand {
} else {
if (isAuthor(bmeta, player) || user.isAuthorized("essentials.book.others")) {
final ItemStack newItem = new ItemStack(WRITABLE_BOOK, item.getAmount());
newItem.setItemMeta(bmeta);
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_6_R01)) {
final WritableBookMeta wbmeta = (WritableBookMeta) newItem.getItemMeta();
//noinspection DataFlowIssue
wbmeta.setPages(bmeta.getPages());
newItem.setItemMeta(wbmeta);
} else {
newItem.setItemMeta(bmeta);
}
Inventories.setItemInMainHand(user.getBase(), newItem);
user.sendTl("editBookContents");
} else {
@@ -63,7 +72,15 @@ public class Commandbook extends EssentialsCommand {
bmeta.setAuthor(player);
}
final ItemStack newItem = new ItemStack(Material.WRITTEN_BOOK, item.getAmount());
newItem.setItemMeta(bmeta);
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_6_R01)) {
final BookMeta real = (BookMeta) newItem.getItemMeta();
real.setAuthor(bmeta.getAuthor());
real.setTitle(bmeta.getTitle());
real.setPages(bmeta.getPages());
newItem.setItemMeta(real);
} else {
newItem.setItemMeta(bmeta);
}
Inventories.setItemInMainHand(user.getBase(), newItem);
user.sendTl("bookLocked");
} else {
@@ -3,6 +3,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.LocationUtil;
import net.ess3.provider.WorldInfoProvider;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.event.player.PlayerTeleportEvent;
@@ -21,7 +22,7 @@ public class Commandbottom extends EssentialsCommand {
final int bottomZ = user.getLocation().getBlockZ();
final float pitch = user.getLocation().getPitch();
final float yaw = user.getLocation().getYaw();
final Location unsafe = new Location(user.getWorld(), bottomX, ess.getWorldInfoProvider().getMinHeight(user.getWorld()), bottomZ, yaw, pitch);
final Location unsafe = new Location(user.getWorld(), bottomX, ess.provider(WorldInfoProvider.class).getMinHeight(user.getWorld()), bottomZ, yaw, pitch);
final Location safe = LocationUtil.getSafeDestination(ess, unsafe);
final CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
future.thenAccept(success -> {
@@ -3,6 +3,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.FormatUtil;
import com.google.common.collect.Lists;
import net.ess3.api.TranslatableException;
import org.bukkit.Server;
@@ -53,7 +54,7 @@ public class Commandbroadcastworld extends EssentialsCommand {
if (message.isEmpty()) {
throw new NotEnoughArgumentsException();
}
ess.broadcastTl(null, u -> !u.getBase().getWorld().equals(world), true, "broadcast", message, AdventureUtil.parsed(AdventureUtil.legacyToMini(name)));
ess.broadcastTl(null, u -> !u.getBase().getWorld().equals(world), true, "broadcast", FormatUtil.replaceFormat(message).replace("\\n", "\n"), AdventureUtil.parsed(AdventureUtil.legacyToMini(name)));
}
@Override
@@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.provider.ContainerProvider;
import org.bukkit.Server;
public class Commandcartographytable extends EssentialsCommand {
@@ -11,11 +12,13 @@ public class Commandcartographytable extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
if (ess.getContainerProvider() == null) {
final ContainerProvider containerProvider = ess.provider(ContainerProvider.class);
if (containerProvider == null) {
user.sendTl("unsupportedBrand");
return;
}
ess.getContainerProvider().openCartographyTable(user.getBase());
containerProvider.openCartographyTable(user.getBase());
}
}
@@ -6,6 +6,7 @@ import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.TranslatableException;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.entity.Player;
@@ -80,7 +81,7 @@ public class Commandclearinventory extends EssentialsCommand {
}
}
protected void clearHandler(final CommandSource sender, final Player player, final String[] args, final int offset, final boolean showExtended) {
protected void clearHandler(final CommandSource sender, final Player player, final String[] args, final int offset, final boolean showExtended) throws TranslatableException {
ClearHandlerType type = ClearHandlerType.ALL_EXCEPT_ARMOR;
final Set<Item> items = new HashSet<>();
int amount = -1;
@@ -124,6 +125,11 @@ public class Commandclearinventory extends EssentialsCommand {
stack.setDurability(item.getData());
}
// can't remove a negative amount of items. (it adds them)
if (amount < -1) {
throw new TranslatableException("cannotRemoveNegativeItems");
}
// amount -1 means all items will be cleared
if (amount == -1) {
final int removedAmount = Inventories.removeItemSimilar(player, stack, true);
@@ -131,7 +137,6 @@ public class Commandclearinventory extends EssentialsCommand {
sender.sendTl("inventoryClearingStack", removedAmount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName());
}
} else {
stack.setAmount(amount < 0 ? 1 : amount);
if (Inventories.removeItemAmount(player, stack, amount)) {
sender.sendTl("inventoryClearingStack", amount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName());
} else {
@@ -191,6 +196,9 @@ public class Commandclearinventory extends EssentialsCommand {
}
private String formatCommand(final String commandLabel, final String[] args) {
if (args == null || args.length == 0) {
return "/" + commandLabel;
}
return "/" + commandLabel + " " + StringUtil.joinList(" ", (Object[]) args);
}
@@ -6,6 +6,7 @@ import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.PasteUtil;
import net.ess3.api.TranslatableException;
import net.ess3.provider.SerializationProvider;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.ItemStack;
@@ -42,9 +43,10 @@ public class Commandcreatekit extends EssentialsCommand {
final ItemStack[] items = Inventories.getInventory(user.getBase(), true);
final List<String> list = new ArrayList<>();
final SerializationProvider serializationProvider = ess.provider(SerializationProvider.class);
boolean useSerializationProvider = ess.getSettings().isUseBetterKits();
if (useSerializationProvider && ess.getSerializationProvider() == null) {
if (useSerializationProvider && serializationProvider == null) {
ess.showError(user.getSource(), new TranslatableException("createKitUnsupported"), commandLabel);
useSerializationProvider = false;
}
@@ -53,7 +55,7 @@ public class Commandcreatekit extends EssentialsCommand {
if (is != null && is.getType() != null && is.getType() != Material.AIR) {
final String serialized;
if (useSerializationProvider) {
serialized = "@" + Base64Coder.encodeLines(ess.getSerializationProvider().serializeItem(is));
serialized = "@" + Base64Coder.encodeLines(serializationProvider.serializeItem(is));
} else {
serialized = ess.getItemDb().serialize(is);
}
@@ -18,6 +18,24 @@ public class Commanddelhome extends EssentialsCommand {
super("delhome");
}
private void deleteHome(CommandSource sender, User user, String home) {
final HomeModifyEvent event = new HomeModifyEvent(sender.getUser(), user, home, user.getHome(home), false);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("HomeModifyEvent canceled for /delhome execution by " + sender.getDisplayName());
}
return;
}
try {
user.delHome(home);
sender.sendTl("deleteHome", home);
} catch (Exception e) {
sender.sendTl("invalidHome", home);
}
}
@Override
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 1) {
@@ -45,21 +63,19 @@ public class Commanddelhome extends EssentialsCommand {
name = expandedArg[0].toLowerCase(Locale.ENGLISH);
}
if (name.equals("bed")) {
throw new TranslatableException("invalidHomeName");
switch (name) {
case "bed":
throw new TranslatableException("invalidHomeName");
case "*":
final List<String> homes = user.getHomes();
for (String home : homes) {
deleteHome(sender, user, home);
}
break;
default:
deleteHome(sender, user, name);
break;
}
final HomeModifyEvent event = new HomeModifyEvent(sender.getUser(), user, name, user.getHome(name), false);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("HomeModifyEvent canceled for /delhome execution by " + sender.getDisplayName());
}
return;
}
user.delHome(name);
sender.sendTl("deleteHome", name);
}
@Override
@@ -81,6 +97,7 @@ public class Commanddelhome extends EssentialsCommand {
return homes;
}
otherUser.getHomes().forEach(home -> homes.add(namePart + ":" + home));
homes.add(namePart + ":" + "*");
}
}
return homes;
@@ -3,6 +3,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.google.common.collect.Lists;
import net.ess3.api.MaxMoneyException;
@@ -53,7 +54,7 @@ public class Commandeco extends EssentialsLoopCommand {
if (player.getMoney().subtract(userAmount).compareTo(ess.getSettings().getMinMoney()) >= 0) {
player.takeMoney(userAmount, sender, UserBalanceUpdateEvent.Cause.COMMAND_ECO);
} else {
ess.showError(sender, new TranslatableException("minimumBalanceError", NumberUtil.displayCurrency(ess.getSettings().getMinMoney(), ess)), commandLabel);
ess.showError(sender, new TranslatableException("minimumBalanceError", AdventureUtil.parsed(NumberUtil.displayCurrency(ess.getSettings().getMinMoney(), ess))), commandLabel);
}
break;
}
@@ -64,8 +65,8 @@ public class Commandeco extends EssentialsLoopCommand {
final boolean underMin = userAmount.compareTo(minBal) < 0;
final boolean aboveMax = userAmount.compareTo(maxBal) > 0;
player.setMoney(underMin ? minBal : aboveMax ? maxBal : userAmount, UserBalanceUpdateEvent.Cause.COMMAND_ECO);
player.sendTl("setBal", NumberUtil.displayCurrency(player.getMoney(), ess));
sender.sendTl("setBalOthers", player.getDisplayName(), NumberUtil.displayCurrency(player.getMoney(), ess));
player.sendTl("setBal", AdventureUtil.parsed(NumberUtil.displayCurrency(player.getMoney(), ess)));
sender.sendTl("setBalOthers", player.getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(player.getMoney(), ess)));
break;
}
}
@@ -17,7 +17,6 @@ import org.bukkit.block.data.type.HangingSign;
import org.bukkit.block.data.type.WallHangingSign;
import org.bukkit.block.data.type.WallSign;
import org.bukkit.block.sign.Side;
import org.bukkit.entity.Player;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.util.Vector;
@@ -49,7 +48,7 @@ public class Commandeditsign extends EssentialsCommand {
throw new TranslatableException("editsignCommandLimit");
}
existingLines[line] = text;
if (callSignEvent(sign, user.getBase(), existingLines)) {
if (callSignEvent(sign, user, existingLines)) {
return;
}
@@ -61,7 +60,7 @@ public class Commandeditsign extends EssentialsCommand {
existingLines[i] = "";
}
if (callSignEvent(sign, user.getBase(), existingLines)) {
if (callSignEvent(sign, user, existingLines)) {
return;
}
@@ -71,7 +70,7 @@ public class Commandeditsign extends EssentialsCommand {
final int line = Integer.parseInt(args[1]) - 1;
existingLines[line] = "";
if (callSignEvent(sign, user.getBase(), existingLines)) {
if (callSignEvent(sign, user, existingLines)) {
return;
}
@@ -100,13 +99,17 @@ public class Commandeditsign extends EssentialsCommand {
for (int i = 0; i < 4; i++) {
existingLines[i] = FormatUtil.formatString(user, "essentials.editsign", user.getSignCopy().get(i));
}
if (callSignEvent(sign, user, existingLines)) {
return;
}
user.sendTl("editsignPaste", commandLabel);
} else {
existingLines[line] = FormatUtil.formatString(user, "essentials.editsign", user.getSignCopy().get(line));
if (callSignEvent(sign, user, existingLines)) {
return;
}
user.sendTl("editsignPasteLine", line + 1, commandLabel);
}
callSignEvent(sign, user.getBase(), existingLines);
} else {
throw new NotEnoughArgumentsException();
}
@@ -115,22 +118,22 @@ public class Commandeditsign extends EssentialsCommand {
}
}
private boolean callSignEvent(final ModifiableSign sign, final Player player, final String[] lines) {
private boolean callSignEvent(final ModifiableSign sign, final User user, final String[] lines) {
final SignChangeEvent event;
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_1_R01)) {
if (sign.isWaxed() && !player.hasPermission("essentials.editsign.waxed.exempt")) {
if (sign.isWaxed() && !user.isAuthorized("essentials.editsign.waxed.exempt")) {
return true;
}
event = new SignChangeEvent(sign.getBlock(), player, lines, sign.isFront() ? Side.FRONT : Side.BACK);
event = new SignChangeEvent(sign.getBlock(), user.getBase(), lines, sign.isFront() ? Side.FRONT : Side.BACK);
} else {
//noinspection deprecation
event = new SignChangeEvent(sign.getBlock(), player, lines);
event = new SignChangeEvent(sign.getBlock(), user.getBase(), lines);
}
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("SignChangeEvent canceled for /editsign execution by " + player.getName());
ess.getLogger().info("SignChangeEvent canceled for /editsign execution by " + user.getName());
}
return true;
}
@@ -10,10 +10,10 @@ import com.earth2me.essentials.userstorage.ModernUserMap;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.CommandMapUtil;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FloatUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.PasteUtil;
import com.earth2me.essentials.utils.RegistryUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
@@ -22,6 +22,8 @@ import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import net.ess3.api.TranslatableException;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.OnlineModeProvider;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
@@ -67,8 +69,8 @@ import static com.earth2me.essentials.I18n.tlLiteral;
// This command has 4 undocumented behaviours #EasterEgg
public class Commandessentials extends EssentialsCommand {
private static final Sound NOTE_HARP = EnumUtil.valueOf(Sound.class, "BLOCK_NOTE_BLOCK_HARP", "BLOCK_NOTE_HARP", "NOTE_PIANO");
private static final Sound MOO_SOUND = EnumUtil.valueOf(Sound.class, "COW_IDLE", "ENTITY_COW_MILK");
private static final Sound NOTE_HARP = RegistryUtil.valueOf(Sound.class, "BLOCK_NOTE_BLOCK_HARP", "BLOCK_NOTE_HARP", "NOTE_PIANO");
private static final Sound MOO_SOUND = RegistryUtil.valueOf(Sound.class, "COW_IDLE", "ENTITY_COW_MILK");
private static final String HOMES_USAGE = "/<command> homes (fix | delete [world])";
@@ -263,7 +265,7 @@ public class Commandessentials extends EssentialsCommand {
serverData.addProperty("bukkit-version", Bukkit.getBukkitVersion());
serverData.addProperty("server-version", Bukkit.getVersion());
serverData.addProperty("server-brand", Bukkit.getName());
serverData.addProperty("online-mode", ess.getOnlineModeProvider().getOnlineModeString());
serverData.addProperty("online-mode", ess.provider(OnlineModeProvider.class).getOnlineModeString());
final JsonObject supportStatus = new JsonObject();
final VersionUtil.SupportStatus status = VersionUtil.getServerSupportStatus();
supportStatus.addProperty("status", status.name());
@@ -334,7 +336,7 @@ public class Commandessentials extends EssentialsCommand {
final Plugin essDiscordLink = Bukkit.getPluginManager().getPlugin("EssentialsDiscordLink");
final Plugin essSpawn = Bukkit.getPluginManager().getPlugin("EssentialsSpawn");
final Map<String, Command> knownCommandsCopy = new HashMap<>(ess.getKnownCommandsProvider().getKnownCommands());
final Map<String, Command> knownCommandsCopy = new HashMap<>(ess.provider(KnownCommandsProvider.class).getKnownCommands());
final Map<String, String> disabledCommandsCopy = new HashMap<>(ess.getAlternativeCommandsHandler().disabledCommands());
// Further operations will be heavy IO
@@ -459,12 +461,14 @@ public class Commandessentials extends EssentialsCommand {
final CompletableFuture<PasteUtil.PasteResult> future = PasteUtil.createPaste(files);
future.thenAccept(result -> {
if (result != null) {
final String dumpUrl = "https://essentialsx.net/dump.html?id=" + result.getPasteId();
final String dumpUrl = "https://essentialsx.net/dump.html?bytebin=" + result.getPasteId();
sender.sendTl("dumpUrl", dumpUrl);
sender.sendTl("dumpDeleteKey", result.getDeletionKey());
// pastes.dev doesn't support deletion keys
//sender.sendTl("dumpDeleteKey", result.getDeletionKey());
if (sender.isPlayer()) {
ess.getLogger().info(AdventureUtil.miniToLegacy(tlLiteral("dumpConsoleUrl", dumpUrl)));
ess.getLogger().info(AdventureUtil.miniToLegacy(tlLiteral("dumpDeleteKey", result.getDeletionKey())));
// pastes.dev doesn't support deletion keys
//ess.getLogger().info(AdventureUtil.miniToLegacy(tlLiteral("dumpDeleteKey", result.getDeletionKey())));
}
}
files.clear();
@@ -19,6 +19,7 @@ import org.bukkit.entity.Snowball;
import org.bukkit.entity.SplashPotion;
import org.bukkit.entity.ThrownExpBottle;
import org.bukkit.entity.Trident;
import org.bukkit.entity.WindCharge;
import org.bukkit.entity.WitherSkull;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.util.Vector;
@@ -55,6 +56,10 @@ public class Commandfireball extends EssentialsCommand {
builder.put("trident", Trident.class);
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_21_R01)) {
builder.put("windcharge", WindCharge.class);
}
types = builder.build();
}
@@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.provider.ContainerProvider;
import org.bukkit.Server;
public class Commandgrindstone extends EssentialsCommand {
@@ -11,11 +12,13 @@ public class Commandgrindstone extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
if (ess.getContainerProvider() == null) {
final ContainerProvider containerProvider = ess.provider(ContainerProvider.class);
if (containerProvider == null) {
user.sendTl("unsupportedBrand");
return;
}
ess.getContainerProvider().openGrindstone(user.getBase());
containerProvider.openGrindstone(user.getBase());
}
}
@@ -9,6 +9,7 @@ import com.earth2me.essentials.textreader.TextInput;
import com.earth2me.essentials.textreader.TextPager;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.provider.KnownCommandsProvider;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.command.PluginIdentifiableCommand;
@@ -18,6 +19,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
public class Commandhelp extends EssentialsCommand {
public Commandhelp() {
@@ -35,20 +37,27 @@ public class Commandhelp extends EssentialsCommand {
if (input.getLines().isEmpty()) {
if (pageStr != null && pageStr.startsWith("/")) {
final String cmd = pageStr.substring(1);
for (final Map.Entry<String, Command> knownCmd : ess.getKnownCommandsProvider().getKnownCommands().entrySet()) {
for (final Map.Entry<String, Command> knownCmd : ess.provider(KnownCommandsProvider.class).getKnownCommands().entrySet()) {
if (knownCmd.getKey().equalsIgnoreCase(cmd)) {
final Command bukkit = knownCmd.getValue();
final boolean isEssCommand = bukkit instanceof PluginIdentifiableCommand && ((PluginIdentifiableCommand) bukkit).getPlugin().equals(ess);
final IEssentialsCommand essCommand = isEssCommand ? ess.getCommandMap().get(bukkit.getName()) : null;
user.sendTl("commandHelpLine1", cmd);
user.sendTl("commandHelpLine2", knownCmd.getValue().getDescription());
user.sendTl("commandHelpLine4", knownCmd.getValue().getAliases().toString());
String description = bukkit.getDescription();
if (essCommand != null) {
try {
description = user.playerTl(bukkit.getName() + "CommandDescription");
} catch (MissingResourceException ignored) {}
}
user.sendTl("commandHelpLine2", description);
user.sendTl("commandHelpLine4", bukkit.getAliases().toString());
user.sendTl("commandHelpLine3");
final boolean isEssCommand = knownCmd.getValue() instanceof PluginIdentifiableCommand && ((PluginIdentifiableCommand) knownCmd.getValue()).getPlugin().equals(ess);
final IEssentialsCommand essCommand = isEssCommand ? ess.getCommandMap().get(knownCmd.getValue().getName()) : null;
if (essCommand != null && !essCommand.getUsageStrings().isEmpty()) {
for (Map.Entry<String, String> usage : essCommand.getUsageStrings().entrySet()) {
user.sendTl("commandHelpLineUsage", AdventureUtil.parsed(usage.getKey().replace("<command>", cmd)), AdventureUtil.parsed(usage.getValue()));
}
} else {
user.sendMessage(knownCmd.getValue().getUsage());
user.sendMessage(bukkit.getUsage());
}
return;
}
@@ -43,7 +43,7 @@ public class Commandhelpop extends EssentialsCommand {
final List<IUser> recipients = new ArrayList<>();
for (IUser user : ess.getOnlineUsers()) {
if (user.getBase().hasPermission("essentials.helpop.receive")) {
if (user.isAuthorized("essentials.helpop.receive")) {
recipients.add(user);
}
}
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import net.ess3.provider.DamageEventProvider;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent;
@@ -29,7 +30,9 @@ public class Commandkill extends EssentialsLoopCommand {
if (sender.isPlayer() && user.isAuthorized("essentials.kill.exempt") && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.kill.force")) {
throw new PlayerExemptException("killExempt", matchPlayer.getDisplayName());
}
final EntityDamageEvent ede = ess.getDamageEventProvider().callDamageEvent(matchPlayer, sender.isPlayer() && sender.getPlayer().getName().equals(matchPlayer.getName()) ? EntityDamageEvent.DamageCause.SUICIDE : EntityDamageEvent.DamageCause.CUSTOM, Float.MAX_VALUE);
final DamageEventProvider provider = ess.provider(DamageEventProvider.class);
final EntityDamageEvent ede = provider.callDamageEvent(matchPlayer, sender.isPlayer() && sender.getPlayer().getName().equals(matchPlayer.getName()) ? EntityDamageEvent.DamageCause.SUICIDE : EntityDamageEvent.DamageCause.CUSTOM, Float.MAX_VALUE);
if (ede.isCancelled() && sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.kill.force")) {
return;
}
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.Mob;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.RegistryUtil;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.entity.Cat;
@@ -21,8 +22,12 @@ public class Commandkittycannon extends EssentialsCommand {
private static Ocelot spawnOcelot(final Server server, final User user) throws Mob.MobException {
final Ocelot ocelot = (Ocelot) Mob.OCELOT.spawn(user.getWorld(), server, user.getBase().getEyeLocation());
final int i = random.nextInt(Ocelot.Type.values().length);
ocelot.setCatType(Ocelot.Type.values()[i]);
//noinspection deprecation
final Object[] values = RegistryUtil.values(Ocelot.Type.class);
final int i = random.nextInt(values.length);
//noinspection deprecation
ocelot.setCatType((Ocelot.Type) values[i]);
((Tameable) ocelot).setTamed(true);
ocelot.setBaby();
ocelot.setVelocity(user.getBase().getEyeLocation().getDirection().multiply(2));
@@ -31,8 +36,10 @@ public class Commandkittycannon extends EssentialsCommand {
private static Entity spawnCat(final Server server, final User user) throws Mob.MobException {
final Cat cat = (Cat) Mob.CAT.spawn(user.getWorld(), server, user.getBase().getEyeLocation());
final int i = random.nextInt(Cat.Type.values().length);
cat.setCatType(Cat.Type.values()[i]);
final Object[] values = RegistryUtil.values(Cat.Type.class);
final int i = random.nextInt(values.length);
cat.setCatType((Cat.Type) values[i]);
cat.setTamed(true);
cat.setBaby();
cat.setVelocity(user.getBase().getEyeLocation().getDirection().multiply(2));
@@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.provider.ContainerProvider;
import org.bukkit.Server;
public class Commandloom extends EssentialsCommand {
@@ -11,11 +12,13 @@ public class Commandloom extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
if (ess.getContainerProvider() == null) {
final ContainerProvider containerProvider = ess.provider(ContainerProvider.class);
if (containerProvider == null) {
user.sendTl("unsupportedBrand");
return;
}
ess.getContainerProvider().openLoom(user.getBase());
containerProvider.openLoom(user.getBase());
}
}
@@ -5,7 +5,6 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.NickChangeEvent;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import java.util.Collections;
@@ -63,7 +62,7 @@ public class Commandnick extends EssentialsLoopCommand {
private String formatNickname(final User user, final String nick) throws Exception {
final String newNick = user == null ? FormatUtil.replaceFormat(nick) : FormatUtil.formatString(user, "essentials.nick", nick);
if (!newNick.matches("^[a-zA-Z_0-9" + ChatColor.COLOR_CHAR + "]+$") && user != null && !user.isAuthorized("essentials.nick.allowunsafe")) {
if (!newNick.matches(ess.getSettings().getNickRegex()) && user != null && !user.isAuthorized("essentials.nick.allowunsafe")) {
throw new TranslatableException("nickNamesAlpha");
} else if (getNickLength(newNick) > ess.getSettings().getMaxNickLength()) {
throw new TranslatableException("nickTooLong");
@@ -87,7 +86,10 @@ public class Commandnick extends EssentialsLoopCommand {
}
private int getNickLength(final String nick) {
return ess.getSettings().ignoreColorsInMaxLength() ? ChatColor.stripColor(nick).length() : nick.length();
if (ess.getSettings().ignoreColorsInMaxLength()) {
return FormatUtil.stripFormat(nick).length();
}
return FormatUtil.unformatString(nick).length();
}
private boolean nickInUse(final User target, final String nick) {
@@ -3,12 +3,14 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import com.google.common.collect.Lists;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.UserBalanceUpdateEvent;
import net.ess3.provider.PlayerLocaleProvider;
import org.bukkit.Server;
import java.math.BigDecimal;
@@ -17,11 +19,6 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class Commandpay extends EssentialsLoopCommand {
private static final BigDecimal THOUSAND = new BigDecimal(1000);
private static final BigDecimal MILLION = new BigDecimal(1_000_000);
private static final BigDecimal BILLION = new BigDecimal(1_000_000_000);
private static final BigDecimal TRILLION = new BigDecimal(1_000_000_000_000L);
public Commandpay() {
super("pay");
}
@@ -44,33 +41,16 @@ public class Commandpay extends EssentialsLoopCommand {
throw new NotEnoughArgumentsException();
}
BigDecimal tempAmount = new BigDecimal(sanitizedString);
switch (Character.toLowerCase(ogStr.charAt(ogStr.length() - 1))) {
case 'k': {
tempAmount = tempAmount.multiply(THOUSAND);
break;
}
case 'm': {
tempAmount = tempAmount.multiply(MILLION);
break;
}
case 'b': {
tempAmount = tempAmount.multiply(BILLION);
break;
}
case 't': {
tempAmount = tempAmount.multiply(TRILLION);
break;
}
default: {
break;
}
final BigDecimal amount;
if (ess.getSettings().isPerPlayerLocale()) {
final String playerLocale = ess.provider(PlayerLocaleProvider.class).getLocale(user.getBase());
amount = NumberUtil.parseStringToBDecimal(ogStr, user.getPlayerLocale(playerLocale));
} else {
amount = NumberUtil.parseStringToBDecimal(ogStr);
}
final BigDecimal amount = tempAmount;
if (amount.compareTo(ess.getSettings().getMinimumPayAmount()) < 0) { // Check if amount is less than minimum-pay-amount
throw new TranslatableException("minimumPayAmount", NumberUtil.displayCurrencyExactly(ess.getSettings().getMinimumPayAmount(), ess));
throw new TranslatableException("minimumPayAmount", AdventureUtil.parsed(NumberUtil.displayCurrencyExactly(ess.getSettings().getMinimumPayAmount(), ess)));
}
final AtomicBoolean informToConfirm = new AtomicBoolean(false);
final boolean canPayOffline = user.isAuthorized("essentials.pay.offline");
@@ -117,7 +97,7 @@ public class Commandpay extends EssentialsLoopCommand {
});
if (informToConfirm.get()) {
final String cmd = "/" + commandLabel + " " + StringUtil.joinList(" ", args);
user.sendTl("confirmPayment", NumberUtil.displayCurrency(amount, ess), cmd);
user.sendTl("confirmPayment", AdventureUtil.parsed(NumberUtil.displayCurrency(amount, ess)), cmd);
}
}
@@ -3,10 +3,13 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.TranslatableException;
import net.ess3.provider.InventoryViewProvider;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.FurnaceRecipe;
@@ -131,7 +134,7 @@ public class Commandrecipe extends EssentialsCommand {
if (VersionUtil.PRE_FLATTENING && item.getDurability() == Short.MAX_VALUE) {
item.setDurability((short) 0);
}
ess.getInventoryViewProvider().getTopInventory(view).setItem(j * 3 + k + 1, item);
ess.provider(InventoryViewProvider.class).getTopInventory(view).setItem(j * 3 + k + 1, item);
}
}
} else {
@@ -150,18 +153,28 @@ public class Commandrecipe extends EssentialsCommand {
materials[j][k] = item == null ? null : item.getType();
}
}
sender.sendTl("recipeGrid", colorMap.get(materials[0][0]), colorMap.get(materials[0][1]), colorMap.get(materials[0][2]));
sender.sendTl("recipeGrid", colorMap.get(materials[1][0]), colorMap.get(materials[1][1]), colorMap.get(materials[1][2]));
sender.sendTl("recipeGrid", colorMap.get(materials[2][0]), colorMap.get(materials[2][1]), colorMap.get(materials[2][2]));
sender.sendTl("recipeGrid", colorTag(colorMap, materials, 0, 0), colorTag(colorMap, materials, 0, 1), colorTag(colorMap, materials, 0, 2));
sender.sendTl("recipeGrid", colorTag(colorMap, materials, 1, 0), colorTag(colorMap, materials, 1, 1), colorTag(colorMap, materials, 1, 2));
sender.sendTl("recipeGrid", colorTag(colorMap, materials, 2, 0), colorTag(colorMap, materials, 2, 1), colorTag(colorMap, materials, 2, 2));
final StringBuilder s = new StringBuilder();
for (final Material items : colorMap.keySet().toArray(new Material[0])) {
s.append(sender.tl("recipeGridItem", colorMap.get(items), getMaterialName(sender, items)));
s.append(sender.tl("recipeGridItem", colorMap.get(items), getMaterialName(sender, items))).append(" ");
}
sender.sendTl("recipeWhere", s.toString());
sender.sendTl("recipeWhere", AdventureUtil.parsed(s.toString()));
}
}
private AdventureUtil.ParsedPlaceholder colorTag(final Map<Material, String> colorMap, final Material[][] materials, final int x, final int y) {
final char colorChar = colorMap.get(materials[x][y]).charAt(0);
final NamedTextColor namedTextColor = AdventureUtil.fromChar(colorChar);
if (namedTextColor == null) {
throw new IllegalStateException("Illegal amount of materials in recipe");
}
return AdventureUtil.parsed("<" + namedTextColor + ">" + colorChar);
}
public void shapelessRecipe(final CommandSource sender, final ShapelessRecipe recipe, final boolean showWindow) {
final List<ItemStack> ingredients = recipe.getIngredientList();
if (showWindow) {
@@ -174,7 +187,7 @@ public class Commandrecipe extends EssentialsCommand {
if (VersionUtil.PRE_FLATTENING && item.getDurability() == Short.MAX_VALUE) {
item.setDurability((short) 0);
}
ess.getInventoryViewProvider().setItem(view, i + 1, item);
ess.provider(InventoryViewProvider.class).setItem(view, i + 1, item);
}
} else {
@@ -216,7 +216,7 @@ public class Commandseen extends EssentialsCommand {
if (matches.size() > 0) {
sender.sendTl("matchingIPAddress");
sender.sendMessage(StringUtil.joinList(matches));
sender.sendTl("matchingAccounts", StringUtil.joinList(matches));
} else {
sender.sendTl("noMatchingPlayers");
}
@@ -82,7 +82,7 @@ public class Commandsell extends EssentialsCommand {
ess.showError(user.getSource(), new TranslatableException("cannotSellTheseNamedItems", String.join(ChatColor.RESET + ", ", names)), commandLabel);
}
if (count != 1) {
final String totalWorthStr = NumberUtil.displayCurrency(totalWorth, ess);
final AdventureUtil.ParsedPlaceholder totalWorthStr = AdventureUtil.parsed(NumberUtil.displayCurrency(totalWorth, ess));
if (args[0].equalsIgnoreCase("blocks")) {
user.sendTl("totalWorthBlocks", totalWorthStr, totalWorthStr);
} else {
@@ -93,7 +93,8 @@ public class Commandsell extends EssentialsCommand {
private BigDecimal sellItem(final User user, final ItemStack is, final String[] args, final boolean isBulkSell) throws Exception {
final int amount = ess.getWorth().getAmount(ess, user, is, args, isBulkSell);
final BigDecimal worth = ess.getWorth().getPrice(ess, is);
final BigDecimal originalWorth = ess.getWorth().getPrice(ess, is);
final BigDecimal worth = originalWorth == null ? null : originalWorth.multiply(ess.getSettings().getMultiplier(user));
if (worth == null) {
throw new TranslatableException("itemCannotBeSold");
@@ -101,7 +102,7 @@ public class Commandsell extends EssentialsCommand {
if (amount <= 0) {
if (!isBulkSell) {
user.sendTl("itemSold", NumberUtil.displayCurrency(BigDecimal.ZERO, ess), BigDecimal.ZERO, is.getType().toString().toLowerCase(Locale.ENGLISH), NumberUtil.displayCurrency(worth, ess));
user.sendTl("itemSold", AdventureUtil.parsed(NumberUtil.displayCurrency(BigDecimal.ZERO, ess)), BigDecimal.ZERO, is.getType().toString().toLowerCase(Locale.ENGLISH), NumberUtil.displayCurrency(worth, ess));
}
return BigDecimal.ZERO;
}
@@ -120,9 +121,9 @@ public class Commandsell extends EssentialsCommand {
Trade.log("Command", "Sell", "Item", user.getName(), new Trade(ris, ess), user.getName(), new Trade(result, ess), user.getLocation(), user.getMoney(), ess);
user.giveMoney(result, null, UserBalanceUpdateEvent.Cause.COMMAND_SELL);
final String typeName = is.getType().toString().toLowerCase(Locale.ENGLISH);
final String worthDisplay = NumberUtil.displayCurrency(worth, ess);
user.sendTl("itemSold", NumberUtil.displayCurrency(result, ess), amount, typeName, worthDisplay);
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("itemSoldConsole", user.getName(), typeName, NumberUtil.displayCurrency(result, ess), amount, worthDisplay, user.getDisplayName())));
final AdventureUtil.ParsedPlaceholder worthDisplay = AdventureUtil.parsed(NumberUtil.displayCurrency(worth, ess));
user.sendTl("itemSold", AdventureUtil.parsed(NumberUtil.displayCurrency(result, ess)), amount, typeName, worthDisplay);
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("itemSoldConsole", user.getName(), typeName, AdventureUtil.miniToLegacy(NumberUtil.displayCurrency(result, ess)), amount, AdventureUtil.miniToLegacy(worthDisplay.toString()), user.getDisplayName())));
return result;
}
@@ -3,10 +3,12 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.RandomTeleport;
import com.earth2me.essentials.User;
import org.bukkit.Server;
import org.bukkit.World;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class Commandsettpr extends EssentialsCommand {
public Commandsettpr() {
@@ -15,22 +17,20 @@ public class Commandsettpr extends EssentialsCommand {
@Override
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
if (args.length == 0) {
if (args.length < 2) {
throw new NotEnoughArgumentsException();
}
final RandomTeleport randomTeleport = ess.getRandomTeleport();
randomTeleport.getCachedLocations().clear();
if ("center".equalsIgnoreCase(args[0])) {
randomTeleport.setCenter(user.getLocation());
if ("center".equalsIgnoreCase(args[1])) {
randomTeleport.setCenter(args[0], user.getLocation());
user.sendTl("settpr");
} else if (args.length > 1) {
if ("minrange".equalsIgnoreCase(args[0])) {
randomTeleport.setMinRange(Double.parseDouble(args[1]));
} else if ("maxrange".equalsIgnoreCase(args[0])) {
randomTeleport.setMaxRange(Double.parseDouble(args[1]));
} else if (args.length > 2) {
if ("minrange".equalsIgnoreCase(args[1])) {
randomTeleport.setMinRange(args[0], Double.parseDouble(args[2]));
} else if ("maxrange".equalsIgnoreCase(args[1])) {
randomTeleport.setMaxRange(args[0], Double.parseDouble(args[2]));
}
user.sendTl("settprValue", args[0].toLowerCase(), args[1].toLowerCase());
user.sendTl("settprValue", args[1].toLowerCase(), args[2].toLowerCase());
} else {
throw new NotEnoughArgumentsException();
}
@@ -39,6 +39,8 @@ public class Commandsettpr extends EssentialsCommand {
@Override
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
if (args.length == 1) {
return user.getServer().getWorlds().stream().map(World::getName).collect(Collectors.toList());
} else if (args.length == 2) {
return Arrays.asList("center", "minrange", "maxrange");
}
return Collections.emptyList();
@@ -4,7 +4,6 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.api.IWarps;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import net.ess3.api.InvalidWorldException;
import net.ess3.api.TranslatableException;
import net.essentialsx.api.v2.events.WarpModifyEvent;
import org.bukkit.Bukkit;
@@ -31,7 +30,7 @@ public class Commandsetwarp extends EssentialsCommand {
try {
warpLoc = warps.getWarp(args[0]);
} catch (final WarpNotFoundException | InvalidWorldException ignored) {
} catch (final WarpNotFoundException ignored) {
}
if (warpLoc == null) {
final WarpModifyEvent event = new WarpModifyEvent(user, args[0], null, user.getLocation(), WarpModifyEvent.WarpModifyCause.CREATE);
@@ -9,6 +9,7 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import net.ess3.api.TranslatableException;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
@@ -48,7 +49,14 @@ public class Commandskull extends EssentialsCommand {
@Override
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final String owner;
if (args.length > 0 && user.isAuthorized("essentials.skull.others")) {
final User player;
if (args.length == 2) {
player = getPlayer(server, args, 1, false, false);
} else {
player = user;
}
if (args.length > 0 && player.isAuthorized("essentials.skull.others")) {
if (BASE_64_PATTERN.matcher(args[0]).matches()) {
try {
final String decoded = new String(Base64.getDecoder().decode(args[0]));
@@ -80,9 +88,9 @@ public class Commandskull extends EssentialsCommand {
final SkullMeta metaSkull;
boolean spawn = false;
if (itemSkull != null && MaterialUtil.isPlayerHead(itemSkull)) {
if (itemSkull != null && MaterialUtil.isPlayerHead(itemSkull) && user == player) {
metaSkull = (SkullMeta) itemSkull.getItemMeta();
} else if (user.isAuthorized("essentials.skull.spawn")) {
} else if (user == player ? user.isAuthorized("essentials.skull.spawn") : user.isAuthorized("essentials.skull.spawn.others")) {
itemSkull = new ItemStack(SKULL_ITEM, 1, (byte) 3);
metaSkull = (SkullMeta) itemSkull.getItemMeta();
spawn = true;
@@ -94,14 +102,14 @@ public class Commandskull extends EssentialsCommand {
throw new TranslatableException("noPermissionSkull");
}
editSkull(user, itemSkull, metaSkull, owner, spawn);
editSkull(user, player, itemSkull, metaSkull, owner, spawn);
}
private void editSkull(final User user, final ItemStack stack, final SkullMeta skullMeta, final String owner, final boolean spawn) {
private void editSkull(final User user, final User receive, final ItemStack stack, final SkullMeta skullMeta, final String owner, final boolean spawn) {
ess.runTaskAsynchronously(() -> {
// Run this stuff async because it causes an HTTP request
final String shortOwnerName;
String shortOwnerName;
if (URL_VALUE_PATTERN.matcher(owner).matches()) {
if (!playerProfileSupported) {
user.sendTl("unsupportedFeature");
@@ -122,20 +130,46 @@ public class Commandskull extends EssentialsCommand {
shortOwnerName = owner.substring(0, 7);
} else {
//noinspection deprecation
skullMeta.setOwner(owner);
shortOwnerName = owner;
if (playerProfileSupported) {
try {
PlayerProfile profile = ess.getServer().createPlayerProfile(null, owner);
profile = profile.update().join();
if (profile != null) {
skullMeta.setOwnerProfile(profile);
}
if (skullMeta.getOwnerProfile() == null) {
final OfflinePlayer offline = ess.getServer().getOfflinePlayer(owner);
skullMeta.setOwningPlayer(offline);
}
shortOwnerName = owner;
} catch (final Exception e) {
//noinspection deprecation
skullMeta.setOwner(owner);
shortOwnerName = owner;
}
} else {
//noinspection deprecation
skullMeta.setOwner(owner);
shortOwnerName = owner;
}
}
skullMeta.setDisplayName("§fSkull of " + shortOwnerName);
final String shortNameFinal = shortOwnerName;
ess.scheduleSyncDelayedTask(() -> {
stack.setItemMeta(skullMeta);
if (spawn) {
Inventories.addItem(user.getBase(), stack);
user.sendTl("givenSkull", shortOwnerName);
Inventories.addItem(receive.getBase(), stack);
receive.sendTl("givenSkull", shortNameFinal);
if (user != receive) {
user.sendTl("givenSkullOther", receive.getDisplayName(), shortNameFinal);
}
return;
}
user.sendTl("skullChanged", shortOwnerName);
user.sendTl("skullChanged", shortNameFinal);
});
});
}
@@ -148,6 +182,12 @@ public class Commandskull extends EssentialsCommand {
} else {
return Lists.newArrayList(user.getName());
}
} else if (args.length == 2){
if (user.isAuthorized("essentials.skull.others")) {
return getPlayers(server, user);
} else {
return Lists.newArrayList(user.getName());
}
} else {
return Collections.emptyList();
}
@@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.provider.ContainerProvider;
import org.bukkit.Server;
public class Commandsmithingtable extends EssentialsCommand {
@@ -11,11 +12,13 @@ public class Commandsmithingtable extends EssentialsCommand {
@Override
protected void run(Server server, User user, String commandLabel, String[] args) throws Exception {
if (ess.getContainerProvider() == null) {
final ContainerProvider containerProvider = ess.provider(ContainerProvider.class);
if (containerProvider == null) {
user.sendTl("unsupportedBrand");
return;
}
ess.getContainerProvider().openSmithingTable(user.getBase());
containerProvider.openSmithingTable(user.getBase());
}
}
@@ -60,7 +60,7 @@ public class Commandspawner extends EssentialsCommand {
final CreatureSpawner spawner = (CreatureSpawner) target.getBlock().getState();
spawner.setSpawnedType(mob.getType());
if (delay > 0) {
final SpawnerBlockProvider spawnerBlockProvider = ess.getSpawnerBlockProvider();
final SpawnerBlockProvider spawnerBlockProvider = ess.provider(SpawnerBlockProvider.class);
spawnerBlockProvider.setMinSpawnDelay(spawner, 1);
spawnerBlockProvider.setMaxSpawnDelay(spawner, Integer.MAX_VALUE);
spawnerBlockProvider.setMinSpawnDelay(spawner, delay);
@@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.provider.ContainerProvider;
import org.bukkit.Server;
public class Commandstonecutter extends EssentialsCommand {
@@ -11,11 +12,13 @@ public class Commandstonecutter extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
if (ess.getContainerProvider() == null) {
final ContainerProvider containerProvider = ess.provider(ContainerProvider.class);
if (containerProvider == null) {
user.sendTl("unsupportedBrand");
return;
}
ess.getContainerProvider().openStonecutter(user.getBase());
containerProvider.openStonecutter(user.getBase());
}
}
@@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.provider.DamageEventProvider;
import org.bukkit.Server;
import org.bukkit.event.entity.EntityDamageEvent;
@@ -14,7 +15,9 @@ public class Commandsuicide extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final EntityDamageEvent ede = ess.getDamageEventProvider().callDamageEvent(user.getBase(), EntityDamageEvent.DamageCause.SUICIDE, Float.MAX_VALUE);
final DamageEventProvider provider = ess.provider(DamageEventProvider.class);
final EntityDamageEvent ede = provider.callDamageEvent(user.getBase(), EntityDamageEvent.DamageCause.SUICIDE, Float.MAX_VALUE);
ede.getEntity().setLastDamageCause(ede);
user.getBase().setHealth(0);
user.sendTl("suicideMessage");
@@ -3,6 +3,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.LocationUtil;
import net.ess3.provider.WorldInfoProvider;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
@@ -20,7 +21,7 @@ public class Commandtop extends EssentialsCommand {
final int topZ = user.getLocation().getBlockZ();
final float pitch = user.getLocation().getPitch();
final float yaw = user.getLocation().getYaw();
final Location unsafe = new Location(user.getWorld(), topX, ess.getWorldInfoProvider().getMaxHeight(user.getWorld()), topZ, yaw, pitch);
final Location unsafe = new Location(user.getWorld(), topX, ess.provider(WorldInfoProvider.class).getMaxHeight(user.getWorld()), topZ, yaw, pitch);
final Location safe = LocationUtil.getSafeDestination(ess, unsafe);
final CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
future.thenAccept(success -> {
@@ -1,8 +1,10 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.RandomTeleport;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.UserRandomTeleportEvent;
import org.bukkit.Server;
import org.bukkit.event.player.PlayerTeleportEvent;
@@ -10,6 +12,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class Commandtpr extends EssentialsCommand {
@@ -22,25 +25,101 @@ public class Commandtpr extends EssentialsCommand {
final Trade charge = new Trade(this.getName(), ess);
charge.isAffordableFor(user);
final RandomTeleport randomTeleport = ess.getRandomTeleport();
final UserRandomTeleportEvent event = new UserRandomTeleportEvent(user, randomTeleport.getCenter(), randomTeleport.getMinRange(), randomTeleport.getMaxRange());
final String randomLocationName;
final User target;
if (args.length == 0) {
// No arguments provided, use the default random teleport location
randomLocationName = randomTeleport.getDefaultLocation().replace("{world}", user.getLocation().getWorld().getName());
target = user;
} else {
// Use the first argument as the location name
randomLocationName = args[0];
if (!randomTeleport.hasLocation(randomLocationName)) {
throw new TranslatableException("tprNotExist");
}
if (randomTeleport.isPerLocationPermission() && !user.isAuthorized("essentials.tpr.location." + randomLocationName)) {
throw new TranslatableException("tprNoPermission");
}
if (args.length > 1 && user.isAuthorized("essentials.tpr.others")) {
target = getPlayer(server, user, args, 1);
} else {
target = user;
}
}
final UserRandomTeleportEvent event = new UserRandomTeleportEvent(target, randomLocationName, randomTeleport.getCenter(randomLocationName), randomTeleport.getMinRange(randomLocationName), randomTeleport.getMaxRange(randomLocationName));
server.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
randomTeleport.getRandomLocation(event.getCenter(), event.getMinRange(), event.getMaxRange()).thenAccept(location -> {
final CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
user.getAsyncTeleport().teleport(location, charge, PlayerTeleportEvent.TeleportCause.COMMAND, future);
future.thenAccept(success -> {
if (success) {
user.sendTl("tprSuccess");
}
});
});
target.sendTl("tprSuccess");
if (target != user) {
user.sendTl("tprOtherUser", target.getDisplayName());
}
(event.isModified() ? randomTeleport.getRandomLocation(event.getCenter(), event.getMinRange(), event.getMaxRange()) : randomTeleport.getRandomLocation(randomLocationName))
.thenAccept(location -> {
final CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
future.thenAccept(success -> {
if (success) {
target.sendTl("tprSuccessDone");
}
});
target.getAsyncTeleport().teleport(location, charge, PlayerTeleportEvent.TeleportCause.COMMAND, future);
});
throw new NoChargeException();
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
protected void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 2) {
throw new NotEnoughArgumentsException();
}
final RandomTeleport randomTeleport = ess.getRandomTeleport();
final User userToTeleport = getPlayer(server, sender, args, 1);
// Validate the location name - only use if it exists and sender has permission
final String potentialLocation = args[0];
if (!randomTeleport.hasLocation(potentialLocation)) {
throw new TranslatableException("tprNotExist");
}
final UserRandomTeleportEvent event = new UserRandomTeleportEvent(userToTeleport, potentialLocation, randomTeleport.getCenter(potentialLocation), randomTeleport.getMinRange(potentialLocation), randomTeleport.getMaxRange(potentialLocation));
server.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
userToTeleport.sendTl("tprSuccess");
sender.sendTl("tprOtherUser", userToTeleport.getDisplayName());
(event.isModified() ? randomTeleport.getRandomLocation(event.getCenter(), event.getMinRange(), event.getMaxRange()) : randomTeleport.getRandomLocation(potentialLocation))
.thenAccept(location -> {
final CompletableFuture<Boolean> future = getNewExceptionFuture(sender, commandLabel);
future.thenAccept(success -> {
if (success) {
userToTeleport.sendTl("tprSuccessDone");
}
});
userToTeleport.getAsyncTeleport().now(location, false, PlayerTeleportEvent.TeleportCause.COMMAND, future);
});
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
final RandomTeleport randomTeleport = ess.getRandomTeleport();
if (args.length == 1) {
if (randomTeleport.isPerLocationPermission()) {
return randomTeleport.listLocations().stream().filter(name -> sender.isAuthorized("essentials.tpr.location." + name)).collect(Collectors.toList());
} else {
return randomTeleport.listLocations();
}
} else if (args.length == 2 && sender.isAuthorized("essentials.tpr.others")) {
return getPlayers(server, sender);
}
return Collections.emptyList();
}
}
@@ -43,7 +43,7 @@ public class Commandwhois extends EssentialsCommand {
final long playtimeMs = System.currentTimeMillis() - (user.getBase().getStatistic(PLAY_ONE_TICK) * 50L);
sender.sendTl("whoisPlaytime", DateUtil.formatDateDiff(playtimeMs));
if (!ess.getSettings().isEcoDisabled()) {
sender.sendTl("whoisMoney", NumberUtil.displayCurrency(user.getMoney(), ess));
sender.sendTl("whoisMoney", AdventureUtil.parsed(NumberUtil.displayCurrency(user.getMoney(), ess)));
}
if (!sender.isPlayer() || ess.getUser(sender.getPlayer()).isAuthorized("essentials.whois.ip")) {
sender.sendTl("whoisIPAddress", user.getBase().getAddress().getAddress().toString());
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.google.common.collect.Lists;
@@ -45,7 +46,7 @@ public class Commandworth extends EssentialsCommand {
}
}
if (count > 1) {
final String totalWorthStr = NumberUtil.displayCurrency(totalWorth, ess);
final AdventureUtil.ParsedPlaceholder totalWorthStr = AdventureUtil.parsed(NumberUtil.displayCurrency(totalWorth, ess));
if (args.length > 0 && args[0].equalsIgnoreCase("blocks")) {
user.sendTl("totalSellableBlocks", totalWorthStr, totalWorthStr);
return;
@@ -88,8 +89,8 @@ public class Commandworth extends EssentialsCommand {
final BigDecimal result = worth.multiply(BigDecimal.valueOf(amount));
final String typeName = is.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
final String resultDisplay = NumberUtil.displayCurrency(result, ess);
final String worthDisplay = NumberUtil.displayCurrency(worth, ess);
final AdventureUtil.ParsedPlaceholder resultDisplay = AdventureUtil.parsed(NumberUtil.displayCurrency(result, ess));
final AdventureUtil.ParsedPlaceholder worthDisplay = AdventureUtil.parsed(NumberUtil.displayCurrency(worth, ess));
if (MaterialUtil.getDamage(is) != 0) {
sender.sendTl("worthMeta", typeName, MaterialUtil.getDamage(is), resultDisplay, amount, worthDisplay);
} else {
@@ -11,6 +11,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
import net.ess3.provider.KnownCommandsProvider;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@@ -277,7 +278,7 @@ public abstract class EssentialsCommand implements IEssentialsCommand {
* Lists all commands.
*/
protected final List<String> getCommands(Server server) {
final Map<String, Command> commandMap = Maps.newHashMap(this.ess.getKnownCommandsProvider().getKnownCommands());
final Map<String, Command> commandMap = Maps.newHashMap(this.ess.provider(KnownCommandsProvider.class).getKnownCommands());
final List<String> commands = Lists.newArrayListWithCapacity(commandMap.size());
for (final Command command : commandMap.values()) {
if (!(command instanceof PluginIdentifiableCommand)) {
@@ -0,0 +1,9 @@
package com.earth2me.essentials.commands;
import net.ess3.api.TranslatableException;
public class InvalidModifierException extends TranslatableException {
public InvalidModifierException() {
super("invalidModifier");
}
}
@@ -13,7 +13,6 @@ import com.earth2me.essentials.config.serializers.LocationTypeSerializer;
import com.earth2me.essentials.config.serializers.MailMessageSerializer;
import com.earth2me.essentials.config.serializers.MaterialTypeSerializer;
import com.earth2me.essentials.utils.AdventureUtil;
import net.ess3.api.InvalidWorldException;
import net.essentialsx.api.v2.services.mail.MailMessage;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -123,7 +122,7 @@ public class EssentialsConfiguration {
setInternal(path, LazyLocation.fromLocation(location));
}
public LazyLocation getLocation(final String path) throws InvalidWorldException {
public LazyLocation getLocation(final String path) {
final CommentedConfigurationNode node = path == null ? getRootNode() : getSection(path);
if (node == null) {
return null;
@@ -19,6 +19,8 @@ public final class Inventories {
private static final int CHEST_SLOT = 38;
private static final int LEG_SLOT = 37;
private static final int BOOT_SLOT = 36;
private static final int BODY_SLOT = 41;
private static final int SADDLE_SLOT = 42;
private static final boolean HAS_OFFHAND = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01);
private static final int INVENTORY_SIZE = HAS_OFFHAND ? 41 : 40;
@@ -224,6 +226,10 @@ public final class Inventories {
int removedAmount = 0;
final ItemStack[] items = player.getInventory().getContents();
for (int i = 0; i < items.length; i++) {
if (isContortedSlot(i)) {
continue;
}
if (!includeArmor && isArmorSlot(i)) {
continue;
}
@@ -243,10 +249,18 @@ public final class Inventories {
}
public static boolean removeItemAmount(final Player player, final ItemStack toRemove, int amount) {
if (amount < 0) {
throw new IllegalArgumentException("Amount cannot be negative.");
}
final List<Integer> clearSlots = new ArrayList<>();
final ItemStack[] items = player.getInventory().getContents();
for (int i = 0; i < items.length; i++) {
if (isContortedSlot(i)) {
continue;
}
final ItemStack item = items[i];
if (isEmpty(item)) {
continue;
@@ -338,6 +352,10 @@ public final class Inventories {
final HashMap<ItemStack, List<Integer>> partialSlots = new HashMap<>();
for (int i = 0; i < inventoryContents.length; i++) {
if (isContortedSlot(i)) {
continue;
}
if (!includeArmor && isArmorSlot(i)) {
continue;
}
@@ -399,6 +417,10 @@ public final class Inventories {
return stack == null || MaterialUtil.isAir(stack.getType());
}
public static boolean isContortedSlot(final int slot) {
return slot == BODY_SLOT || slot == SADDLE_SLOT;
}
private static boolean isArmorSlot(final int slot) {
return slot == HELM_SLOT || slot == CHEST_SLOT || slot == LEG_SLOT || slot == BOOT_SLOT;
}
@@ -5,6 +5,7 @@ import com.earth2me.essentials.OfflinePlayerStub;
import com.earth2me.essentials.api.NoLoanPermittedException;
import com.earth2me.essentials.api.UserDoesNotExistException;
import com.earth2me.essentials.config.EssentialsUserConfiguration;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import com.google.common.base.Charsets;
@@ -61,7 +62,7 @@ public class VaultEconomyProvider implements Economy {
@Override
public String format(double amount) {
return NumberUtil.displayCurrency(BigDecimal.valueOf(amount), ess);
return AdventureUtil.miniToLegacy(NumberUtil.displayCurrency(BigDecimal.valueOf(amount), ess));
}
@Override
@@ -9,6 +9,8 @@ import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.PluginKey;
import net.ess3.provider.BannerDataProvider;
import net.ess3.provider.PotionMetaProvider;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.FireworkEffect;
@@ -284,8 +286,9 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
serializeEffectMeta(sb, fireworkEffectMeta.getEffect());
}
} else if (MaterialUtil.isPotion(material)) {
final boolean splash = ess.getPotionMetaProvider().isSplashPotion(is);
final Collection<PotionEffect> effects = ess.getPotionMetaProvider().getCustomEffects(is);
final PotionMetaProvider provider = ess.provider(PotionMetaProvider.class);
final boolean splash = provider.isSplashPotion(is);
final Collection<PotionEffect> effects = provider.getCustomEffects(is);
for (final PotionEffect e : effects) {
// long but needs to be effect:speed power:2 duration:120 in that order.
@@ -316,7 +319,7 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
} else {
final BannerMeta bannerMeta = (BannerMeta) is.getItemMeta();
if (bannerMeta != null) {
DyeColor baseDyeColor = ess.getBannerDataProvider().getBaseColor(is);
DyeColor baseDyeColor = ess.provider(BannerDataProvider.class).getBaseColor(is);
if (baseDyeColor == null) {
baseDyeColor = MaterialUtil.getColorOf(material);
}
@@ -9,7 +9,9 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
import net.ess3.provider.PersistentDataProvider;
import net.ess3.provider.PotionMetaProvider;
import net.ess3.provider.SpawnerItemProvider;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
@@ -132,7 +134,7 @@ public class FlatItemDb extends AbstractItemDb {
final ItemData.EssentialPotionData potionData = data.getPotionData();
if (potionData != null && stack.getItemMeta() instanceof PotionMeta) {
ess.getPotionMetaProvider().setBasePotionType(stack, potionData.getType(), potionData.isExtended(), potionData.isUpgraded());
ess.provider(PotionMetaProvider.class).setBasePotionType(stack, potionData.getType(), potionData.isExtended(), potionData.isUpgraded());
}
final ItemMeta meta = stack.getItemMeta();
@@ -150,8 +152,8 @@ public class FlatItemDb extends AbstractItemDb {
// setItemMeta to prevent a race condition
final EntityType entity = data.getEntity();
if (entity != null && material.toString().contains("SPAWNER")) {
ess.getSpawnerItemProvider().setEntityType(stack, entity);
ess.getPersistentDataProvider().set(stack, "convert", "true");
ess.provider(SpawnerItemProvider.class).setEntityType(stack, entity);
ess.provider(PersistentDataProvider.class).set(stack, "convert", "true");
}
return stack;
@@ -206,10 +208,10 @@ public class FlatItemDb extends AbstractItemDb {
final Material type = is.getType();
if (MaterialUtil.isPotion(type) && is.getItemMeta() instanceof PotionMeta) {
final PotionMetaProvider provider = ess.getPotionMetaProvider();
final PotionMetaProvider provider = ess.provider(PotionMetaProvider.class);
return new ItemData(type, new ItemData.EssentialPotionData(provider.getBasePotionType(is), provider.isUpgraded(is), provider.isExtended(is)));
} else if (type.toString().contains("SPAWNER")) {
final EntityType entity = ess.getSpawnerItemProvider().getEntityType(is);
final EntityType entity = ess.provider(SpawnerItemProvider.class).getEntityType(is);
return new ItemData(type, entity);
} else {
return new ItemData(type);
@@ -7,6 +7,10 @@ import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
import net.ess3.provider.PersistentDataProvider;
import net.ess3.provider.PotionMetaProvider;
import net.ess3.provider.SpawnEggProvider;
import net.ess3.provider.SpawnerItemProvider;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
@@ -187,8 +191,8 @@ public class LegacyItemDb extends AbstractItemDb {
if (mat == MOB_SPAWNER) {
if (metaData == 0) metaData = EntityType.PIG.getTypeId();
try {
retval = ess.getSpawnerItemProvider().setEntityType(retval, EntityType.fromId(metaData));
ess.getPersistentDataProvider().set(retval, "convert", "true");
retval = ess.provider(SpawnerItemProvider.class).setEntityType(retval, EntityType.fromId(metaData));
ess.provider(PersistentDataProvider.class).set(retval, "convert", "true");
} catch (final IllegalArgumentException e) {
throw new Exception("Can't spawn entity ID " + metaData + " from mob spawners.");
}
@@ -199,10 +203,10 @@ public class LegacyItemDb extends AbstractItemDb {
} catch (final IllegalArgumentException e) {
throw new Exception("Can't spawn entity ID " + metaData + " from spawn eggs.");
}
retval = ess.getSpawnEggProvider().createEggItem(type);
retval = ess.provider(SpawnEggProvider.class).createEggItem(type);
} else if (mat.name().endsWith("POTION")
&& VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_11_R01)) { // Only apply this to pre-1.11 as items.csv might only work in 1.11
retval = ess.getPotionMetaProvider().createPotionItem(mat, metaData);
retval = ess.provider(PotionMetaProvider.class).createPotionItem(mat, metaData);
} else {
retval.setDurability(metaData);
}
@@ -52,7 +52,8 @@ public class MetricsWrapper {
final Map<String, Map<String, Integer>> result = new HashMap<>();
final String handler = ess.getPermissionsHandler().getName();
final Map<String, Integer> backend = new HashMap<>();
backend.put(ess.getPermissionsHandler().getBackendName(), 1);
final String backendName = ess.getPermissionsHandler().getBackendName();
backend.put(backendName != null ? backendName : "Other", 1);
result.put(handler, backend);
return result;
}));
@@ -1,7 +1,6 @@
package com.earth2me.essentials.perm;
import com.earth2me.essentials.commands.Commandhat;
import com.earth2me.essentials.utils.MaterialUtil;
import com.google.common.collect.ImmutableMap;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@@ -11,16 +10,16 @@ import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.PluginManager;
public final class PermissionsDefaults {
private PermissionsDefaults() {
}
public static void registerAllBackDefaults() {
for (final World world : Bukkit.getWorlds()) {
registerBackDefaultFor(world);
}
}
public static void registerBackDefaultFor(final World w) {
final String permName = "essentials.back.into." + w.getName();
@@ -42,7 +41,7 @@ public final class PermissionsDefaults {
}
final ImmutableMap.Builder<String, Boolean> children = ImmutableMap.builder();
for (final Material mat : MaterialUtil.getKnownMaterials()) {
for (final Material mat : Material.values()) {
final String matPerm = Commandhat.PERM_PREFIX + mat.name().toLowerCase();
children.put(matPerm, true);
pluginManager.addPermission(new Permission(matPerm, "Prevent using " + mat + " as a type of hat.", PermissionDefault.FALSE));
@@ -198,6 +198,9 @@ public class PermissionsHandler implements IPermissionsHandler {
String enabledPermsPlugin = ((AbstractVaultHandler) handler).getEnabledPermsPlugin();
if (enabledPermsPlugin == null) enabledPermsPlugin = "generic";
ess.getLogger().info("Using Vault based permissions (" + enabledPermsPlugin + ")");
} else if (handler.getClass() == ConfigPermissionsHandler.class) {
ess.getLogger().info("Using config file enhanced permissions.");
ess.getLogger().info("Permissions listed in as player-commands will be given to all users.");
} else if (handler.getClass() == SuperpermsHandler.class) {
if (handler.tryProvider(ess)) {
ess.getLogger().warning("Detected supported permissions plugin " +
@@ -206,9 +209,6 @@ public class PermissionsHandler implements IPermissionsHandler {
"work until you install Vault.");
}
ess.getLogger().info("Using superperms-based permissions.");
} else if (handler.getClass() == ConfigPermissionsHandler.class) {
ess.getLogger().info("Using config file enhanced permissions.");
ess.getLogger().info("Permissions listed in as player-commands will be given to all users.");
}
}
@@ -170,6 +170,7 @@ public class SuperpermsHandler implements IPermissionsHandler {
break;
}
}
return enabledPermsPlugin;
}
}
@@ -12,9 +12,11 @@ import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.SignBreakEvent;
import net.ess3.api.events.SignCreateEvent;
import net.ess3.api.events.SignInteractEvent;
import net.ess3.provider.SignDataProvider;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -166,24 +168,26 @@ public class EssentialsSign {
}
public void setOwnerData(final IEssentials ess, final User user, final ISign signProvider) {
if (ess.getSignDataProvider() == null) {
final SignDataProvider dataProvider = ess.provider(SignDataProvider.class);
if (dataProvider == null) {
return;
}
final Sign sign = (Sign) signProvider.getBlock().getState();
ess.getSignDataProvider().setSignData(sign, SIGN_OWNER_KEY, user.getUUID().toString());
dataProvider.setSignData(sign, SIGN_OWNER_KEY, user.getUUID().toString());
}
public boolean isOwner(final IEssentials ess, final User user, final ISign signProvider, final int nameIndex, final String namePrefix) {
final SignDataProvider dataProvider = ess.provider(SignDataProvider.class);
final Sign sign = (Sign) signProvider.getBlock().getState();
if (ess.getSignDataProvider() == null || ess.getSignDataProvider().getSignData(sign, SIGN_OWNER_KEY) == null) {
if (dataProvider == null || dataProvider.getSignData(sign, SIGN_OWNER_KEY) == null) {
final boolean isLegacyOwner = FormatUtil.stripFormat(signProvider.getLine(nameIndex)).equalsIgnoreCase(getUsername(user));
if (ess.getSignDataProvider() != null && isLegacyOwner) {
ess.getSignDataProvider().setSignData(sign, SIGN_OWNER_KEY, user.getUUID().toString());
if (dataProvider != null && isLegacyOwner) {
dataProvider.setSignData(sign, SIGN_OWNER_KEY, user.getUUID().toString());
}
return isLegacyOwner;
}
if (user.getUUID().toString().equals(ess.getSignDataProvider().getSignData(sign, SIGN_OWNER_KEY))) {
if (user.getUUID().toString().equals(dataProvider.getSignData(sign, SIGN_OWNER_KEY))) {
signProvider.setLine(nameIndex, namePrefix + getUsername(user));
return true;
}
@@ -408,6 +412,10 @@ public class EssentialsSign {
item.setAmount(quantity);
return item;
} catch (final Exception ex) {
if (ex instanceof TranslatableException) {
final TranslatableException te = (TranslatableException) ex;
throw new SignException(ex, te.getTlKey(), te.getArgs());
}
throw new SignException(ex, "errorWithMessage", ex.getMessage());
}
}
@@ -550,9 +558,11 @@ public class EssentialsSign {
static class BlockSign implements ISign {
private final transient Block block;
private transient Sign sign;
BlockSign(final Block block) {
this.block = block;
this.sign = getSign();
}
@Override
@@ -569,7 +579,7 @@ public class EssentialsSign {
@Override
public final void setLine(final int index, final String text) {
getSign().setLine(index, text);
sign.setLine(index, text);
updateSign();
}
@@ -586,7 +596,8 @@ public class EssentialsSign {
@Override
public final void updateSign() {
getSign().update();
sign.update();
sign = getSign();
}
}
}
@@ -2,6 +2,7 @@ package com.earth2me.essentials.signs;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import net.ess3.provider.ContainerProvider;
public class SignAnvil extends EssentialsSign {
public SignAnvil() {
@@ -10,7 +11,7 @@ public class SignAnvil extends EssentialsSign {
@Override
protected boolean onSignCreate(final ISign sign, final User player, final String username, final IEssentials ess) {
if (ess.getContainerProvider() == null) {
if (ess.provider(ContainerProvider.class) == null) {
player.sendTl("unsupportedBrand");
return false;
}
@@ -19,7 +20,7 @@ public class SignAnvil extends EssentialsSign {
@Override
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) {
ess.getContainerProvider().openAnvil(player.getBase());
ess.provider(ContainerProvider.class).openAnvil(player.getBase());
return true;
}
}
@@ -1,6 +1,7 @@
package com.earth2me.essentials.signs;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.IEssentials;
@@ -11,7 +12,7 @@ public class SignBalance extends EssentialsSign {
@Override
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException {
player.sendTl("balance", NumberUtil.displayCurrency(player.getMoney(), ess));
player.sendTl("balance", AdventureUtil.parsed(NumberUtil.displayCurrency(player.getMoney(), ess)));
return true;
}
}
@@ -3,6 +3,7 @@ package com.earth2me.essentials.signs;
import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import net.ess3.api.events.SignTransactionEvent;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
import org.bukkit.inventory.ItemStack;
@@ -45,6 +46,12 @@ public class SignBuy extends EssentialsSign {
}
charge.isAffordableFor(player);
final SignTransactionEvent signTransactionEvent = new SignTransactionEvent(sign, this, player, items.getItemStack(), SignTransactionEvent.TransactionType.BUY, charge.getMoney());
ess.getServer().getPluginManager().callEvent(signTransactionEvent);
if (signTransactionEvent.isCancelled()) {
return true;
}
if (!items.pay(player)) {
throw new ChargeException("inventoryFull");
}
@@ -2,6 +2,7 @@ package com.earth2me.essentials.signs;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import net.ess3.provider.ContainerProvider;
public class SignCartography extends EssentialsSign {
public SignCartography() {
@@ -10,7 +11,7 @@ public class SignCartography extends EssentialsSign {
@Override
protected boolean onSignCreate(final ISign sign, final User player, final String username, final IEssentials ess) {
if (ess.getContainerProvider() == null) {
if (ess.provider(ContainerProvider.class) == null) {
player.sendTl("unsupportedBrand");
return false;
}
@@ -19,7 +20,7 @@ public class SignCartography extends EssentialsSign {
@Override
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) {
ess.getContainerProvider().openCartographyTable(player.getBase());
ess.provider(ContainerProvider.class).openCartographyTable(player.getBase());
return true;
}
}
@@ -21,7 +21,7 @@ public class SignEnchant extends EssentialsSign {
protected boolean onSignCreate(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException, ChargeException {
final ItemStack stack;
final String itemName = sign.getLine(1);
final MaterialTagProvider tagProvider = ess.getMaterialTagProvider();
final MaterialTagProvider tagProvider = ess.provider(MaterialTagProvider.class);
try {
stack = itemName.equals("*") || itemName.equalsIgnoreCase("any") || (tagProvider != null && tagProvider.tagExists(itemName)) ? null : getItemStack(sign.getLine(1), 1, ess);
} catch (final SignException e) {
@@ -66,7 +66,7 @@ public class SignEnchant extends EssentialsSign {
@Override
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException, ChargeException {
final ItemStack playerHand = Inventories.getItemInHand(player.getBase());
final MaterialTagProvider tagProvider = ess.getMaterialTagProvider();
final MaterialTagProvider tagProvider = ess.provider(MaterialTagProvider.class);
final String itemName = sign.getLine(1);
final ItemStack search = itemName.equals("*") || itemName.equalsIgnoreCase("any") || (tagProvider != null && tagProvider.tagExists(itemName) && tagProvider.isTagged(itemName, playerHand.getType())) ? null : getItemStack(itemName, 1, ess);
final Trade charge = getTrade(sign, 3, ess);
@@ -2,6 +2,7 @@ package com.earth2me.essentials.signs;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import net.ess3.provider.ContainerProvider;
public class SignGrindstone extends EssentialsSign {
public SignGrindstone() {
@@ -10,7 +11,7 @@ public class SignGrindstone extends EssentialsSign {
@Override
protected boolean onSignCreate(final ISign sign, final User player, final String username, final IEssentials ess) {
if (ess.getContainerProvider() == null) {
if (ess.provider(ContainerProvider.class) == null) {
player.sendTl("unsupportedBrand");
return false;
}
@@ -19,7 +20,7 @@ public class SignGrindstone extends EssentialsSign {
@Override
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) {
ess.getContainerProvider().openGrindstone(player.getBase());
ess.provider(ContainerProvider.class).openGrindstone(player.getBase());
return true;
}
}
@@ -2,6 +2,7 @@ package com.earth2me.essentials.signs;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import net.ess3.provider.ContainerProvider;
public class SignLoom extends EssentialsSign {
public SignLoom() {
@@ -10,7 +11,7 @@ public class SignLoom extends EssentialsSign {
@Override
protected boolean onSignCreate(final ISign sign, final User player, final String username, final IEssentials ess) {
if (ess.getContainerProvider() == null) {
if (ess.provider(ContainerProvider.class) == null) {
player.sendTl("unsupportedBrand");
return false;
}
@@ -19,7 +20,7 @@ public class SignLoom extends EssentialsSign {
@Override
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) {
ess.getContainerProvider().openLoom(player.getBase());
ess.provider(ContainerProvider.class).openLoom(player.getBase());
return true;
}
}
@@ -0,0 +1,32 @@
package com.earth2me.essentials.signs;
import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.RandomTeleport;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.concurrent.CompletableFuture;
public class SignRandomTeleport extends EssentialsSign {
public SignRandomTeleport() {
super("RandomTeleport");
}
@Override
protected boolean onSignInteract(ISign sign, User player, String username, IEssentials ess) throws SignException, ChargeException, MaxMoneyException {
final String name = sign.getLine(1);
final RandomTeleport randomTeleport = ess.getRandomTeleport();
randomTeleport.getRandomLocation(name).thenAccept(location -> {
final CompletableFuture<Boolean> future = new CompletableFuture<>();
future.thenAccept(success -> {
if (success) {
player.sendTl("tprSuccess");
}
});
player.getAsyncTeleport().now(location, false, PlayerTeleportEvent.TeleportCause.COMMAND, future);
});
return true;
}
}
@@ -6,6 +6,7 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.commands.Commandrepair;
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
public class SignRepair extends EssentialsSign {
public SignRepair() {
@@ -42,6 +43,8 @@ public class SignRepair extends EssentialsSign {
throw new NotEnoughArgumentsException();
}
} catch (final TranslatableException ex) {
throw new SignException(ex.getTlKey(), ex.getArgs());
} catch (final Exception ex) {
throw new SignException(ex, "errorWithMessage", ex.getMessage());
}
@@ -4,6 +4,7 @@ import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.Trade.OverflowType;
import com.earth2me.essentials.User;
import net.ess3.api.events.SignTransactionEvent;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
import org.bukkit.inventory.ItemStack;
@@ -41,11 +42,19 @@ public class SignSell extends EssentialsSign {
//noinspection BigDecimalMethodWithoutRoundingCalled
BigDecimal pricePerSingleItem = chargeAmount.divide(new BigDecimal(initialItemAmount));
pricePerSingleItem = pricePerSingleItem.multiply(new BigDecimal(newItemAmount));
pricePerSingleItem = pricePerSingleItem.multiply(ess.getSettings().getMultiplier(player));
money = new Trade(pricePerSingleItem, ess);
}
}
charge.isAffordableFor(player);
final SignTransactionEvent signTransactionEvent = new SignTransactionEvent(sign, this, player, charge.getItemStack(), SignTransactionEvent.TransactionType.SELL, money.getMoney());
ess.getServer().getPluginManager().callEvent(signTransactionEvent);
if (signTransactionEvent.isCancelled()) {
return false;
}
money.pay(player, OverflowType.DROP);
charge.charge(player);
Trade.log("Sign", "Sell", "Interact", username, charge, username, money, sign.getBlock().getLocation(), player.getMoney(), ess);
@@ -2,6 +2,7 @@ package com.earth2me.essentials.signs;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import net.ess3.provider.ContainerProvider;
public class SignSmithing extends EssentialsSign {
public SignSmithing() {
@@ -10,7 +11,7 @@ public class SignSmithing extends EssentialsSign {
@Override
protected boolean onSignCreate(final ISign sign, final User player, final String username, final IEssentials ess) {
if (ess.getContainerProvider() == null) {
if (ess.provider(ContainerProvider.class) == null) {
player.sendTl("unsupportedBrand");
return false;
}
@@ -19,7 +20,7 @@ public class SignSmithing extends EssentialsSign {
@Override
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) {
ess.getContainerProvider().openSmithingTable(player.getBase());
ess.provider(ContainerProvider.class).openSmithingTable(player.getBase());
return true;
}
}
@@ -16,7 +16,6 @@ import org.bukkit.inventory.ItemStack;
import java.math.BigDecimal;
import java.util.Map;
//TODO: TL exceptions
public class SignTrade extends EssentialsSign {
private static final int MAX_STOCK_LINE_LENGTH = 15;
@@ -47,14 +46,14 @@ public class SignTrade extends EssentialsSign {
final Trade stored;
try {
stored = getTrade(sign, 1, AmountType.TOTAL, true, true, ess);
subtractAmount(sign, 1, stored, ess);
subtractAmount(sign, 1, stored, ess, false);
final Map<Integer, ItemStack> withdraw = stored.pay(player, OverflowType.RETURN);
if (withdraw == null) {
Trade.log("Sign", "Trade", "Withdraw", username, store, username, null, sign.getBlock().getLocation(), player.getMoney(), ess);
} else {
setAmount(sign, 1, BigDecimal.valueOf(withdraw.get(0).getAmount()), ess);
setAmount(sign, 1, BigDecimal.valueOf(withdraw.get(0).getAmount()), ess, false);
Trade.log("Sign", "Trade", "Withdraw", username, stored, username, new Trade(withdraw.get(0), ess), sign.getBlock().getLocation(), player.getMoney(), ess);
}
} catch (final SignException e) {
@@ -67,11 +66,16 @@ public class SignTrade extends EssentialsSign {
final Trade charge = getTrade(sign, 1, AmountType.COST, false, true, ess);
final Trade trade = getTrade(sign, 2, AmountType.COST, true, true, ess);
charge.isAffordableFor(player);
addAmount(sign, 1, charge, ess);
subtractAmount(sign, 2, trade, ess);
// validate addAmount + subtractAmount first to ensure they both do not throw exceptions
addAmount(sign, 1, charge, ess, true);
subtractAmount(sign, 2, trade, ess, true);
addAmount(sign, 1, charge, ess, false);
subtractAmount(sign, 2, trade, ess, false);
if (!trade.pay(player)) {
subtractAmount(sign, 1, charge, ess);
addAmount(sign, 2, trade, ess);
subtractAmount(sign, 1, charge, ess, false);
addAmount(sign, 2, trade, ess, false);
throw new ChargeException("inventoryFull");
}
charge.charge(player);
@@ -93,7 +97,7 @@ public class SignTrade extends EssentialsSign {
stack = stack.clone();
stack.setAmount(amount);
final Trade store = new Trade(stack, ess);
addAmount(sign, 2, store, ess);
addAmount(sign, 2, store, ess, false);
store.charge(player);
return store;
}
@@ -127,10 +131,10 @@ public class SignTrade extends EssentialsSign {
return true;
}
setAmount(sign, 1, BigDecimal.valueOf(withdraw1 == null ? 0L : withdraw1.get(0).getAmount()), ess);
setAmount(sign, 1, BigDecimal.valueOf(withdraw1 == null ? 0L : withdraw1.get(0).getAmount()), ess, false);
Trade.log("Sign", "Trade", "Withdraw", signOwner.substring(2), stored1, username, withdraw1 == null ? null : new Trade(withdraw1.get(0), ess), sign.getBlock().getLocation(), player.getMoney(), ess);
setAmount(sign, 2, BigDecimal.valueOf(withdraw2 == null ? 0L : withdraw2.get(0).getAmount()), ess);
setAmount(sign, 2, BigDecimal.valueOf(withdraw2 == null ? 0L : withdraw2.get(0).getAmount()), ess, false);
Trade.log("Sign", "Trade", "Withdraw", signOwner.substring(2), stored2, username, withdraw2 == null ? null : new Trade(withdraw2.get(0), ess), sign.getBlock().getLocation(), player.getMoney(), ess);
sign.updateSign();
@@ -267,38 +271,37 @@ public class SignTrade extends EssentialsSign {
throw new SignException("invalidSignLine", index + 1);
}
protected final void subtractAmount(final ISign sign, final int index, final Trade trade, final IEssentials ess) throws SignException {
protected final void subtractAmount(final ISign sign, final int index, final Trade trade, final IEssentials ess, final boolean validationRun) throws SignException {
final BigDecimal money = trade.getMoney();
if (money != null) {
changeAmount(sign, index, money.negate(), ess);
changeAmount(sign, index, money.negate(), ess, validationRun);
}
final ItemStack item = trade.getItemStack();
if (item != null) {
changeAmount(sign, index, BigDecimal.valueOf(-item.getAmount()), ess);
changeAmount(sign, index, BigDecimal.valueOf(-item.getAmount()), ess, validationRun);
}
final Integer exp = trade.getExperience();
if (exp != null) {
changeAmount(sign, index, BigDecimal.valueOf(-exp), ess);
changeAmount(sign, index, BigDecimal.valueOf(-exp), ess, validationRun);
}
}
protected final void addAmount(final ISign sign, final int index, final Trade trade, final IEssentials ess) throws SignException {
protected final void addAmount(final ISign sign, final int index, final Trade trade, final IEssentials ess, final boolean validationRun) throws SignException {
final BigDecimal money = trade.getMoney();
if (money != null) {
changeAmount(sign, index, money, ess);
changeAmount(sign, index, money, ess, validationRun);
}
final ItemStack item = trade.getItemStack();
if (item != null) {
changeAmount(sign, index, BigDecimal.valueOf(item.getAmount()), ess);
changeAmount(sign, index, BigDecimal.valueOf(item.getAmount()), ess, validationRun);
}
final Integer exp = trade.getExperience();
if (exp != null) {
changeAmount(sign, index, BigDecimal.valueOf(exp), ess);
changeAmount(sign, index, BigDecimal.valueOf(exp), ess, validationRun);
}
}
//TODO: Translate these exceptions.
private void changeAmount(final ISign sign, final int index, final BigDecimal value, final IEssentials ess) throws SignException {
private void changeAmount(final ISign sign, final int index, final BigDecimal value, final IEssentials ess, final boolean validationRun) throws SignException {
final String line = sign.getLine(index).trim();
if (line.isEmpty()) {
throw new SignException("emptySignLine", index + 1);
@@ -307,20 +310,18 @@ public class SignTrade extends EssentialsSign {
if (split.length == 2) {
final BigDecimal amount = getBigDecimal(split[1], ess).add(value);
setAmount(sign, index, amount, ess);
setAmount(sign, index, amount, ess, validationRun);
return;
}
if (split.length == 3) {
final BigDecimal amount = getBigDecimal(split[2], ess).add(value);
setAmount(sign, index, amount, ess);
setAmount(sign, index, amount, ess, validationRun);
return;
}
throw new SignException("invalidSignLine", index + 1);
}
//TODO: Translate these exceptions.
private void setAmount(final ISign sign, final int index, final BigDecimal value, final IEssentials ess) throws SignException {
private void setAmount(final ISign sign, final int index, final BigDecimal value, final IEssentials ess, final boolean validationRun) throws SignException {
final String line = sign.getLine(index).trim();
if (line.isEmpty()) {
throw new SignException("emptySignLine", index + 1);
@@ -333,7 +334,9 @@ public class SignTrade extends EssentialsSign {
if (money != null && amount != null) {
final String newline = NumberUtil.shortCurrency(money, ess) + ":" + NumberUtil.formatAsCurrency(value);
validateSignLength(newline);
sign.setLine(index, newline);
if (!validationRun) {
sign.setLine(index, newline);
}
return;
}
}
@@ -343,12 +346,16 @@ public class SignTrade extends EssentialsSign {
if (split[1].equalsIgnoreCase("exp") || split[1].equalsIgnoreCase("xp")) {
final String newline = stackAmount + " " + split[1] + ":" + value.intValueExact();
validateSignLength(newline);
sign.setLine(index, newline);
if (!validationRun) {
sign.setLine(index, newline);
}
} else {
getItemStack(split[1], stackAmount, ess);
final String newline = stackAmount + " " + split[1] + ":" + value.intValueExact();
validateSignLength(newline);
sign.setLine(index, newline);
if (!validationRun) {
sign.setLine(index, newline);
}
}
return;
}
@@ -4,6 +4,7 @@ import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.util.concurrent.CompletableFuture;
@@ -25,6 +26,10 @@ public class SignWarp extends EssentialsSign {
try {
ess.getWarps().getWarp(warpName);
} catch (final Exception ex) {
if (ex instanceof TranslatableException) {
final TranslatableException te = (TranslatableException) ex;
throw new SignException(ex, te.getTlKey(), te.getArgs());
}
throw new SignException(ex, "errorWithMessage", ex.getMessage());
}
final String group = sign.getLine(2);
@@ -25,7 +25,8 @@ public enum Signs {
TRADE(new SignTrade()),
WARP(new SignWarp()),
WEATHER(new SignWeather()),
WORKBENCH(new SignWorkbench());
WORKBENCH(new SignWorkbench()),
RANDOMTELEPORT(new SignRandomTeleport());
private final EssentialsSign sign;
Signs(final EssentialsSign sign) {
@@ -5,6 +5,7 @@ import com.earth2me.essentials.utils.AdventureUtil;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import net.ess3.api.IEssentials;
import net.ess3.provider.KnownCommandsProvider;
import org.bukkit.command.Command;
import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.plugin.Plugin;
@@ -32,7 +33,7 @@ public class HelpInput implements IText {
}
final Multimap<Plugin, Command> pluginCommands = HashMultimap.create();
for (final Command command : ess.getKnownCommandsProvider().getKnownCommands().values()) {
for (final Command command : ess.provider(KnownCommandsProvider.class).getKnownCommands().values()) {
if (!(command instanceof PluginIdentifiableCommand)) {
continue;
}
@@ -4,6 +4,7 @@ import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.ExecuteTimer;
import com.earth2me.essentials.PlayerList;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.DescParseTickFormat;
import com.earth2me.essentials.utils.EnumUtil;
@@ -227,7 +228,7 @@ public class KeywordReplacer implements IText {
break;
case BALANCE:
if (user != null) {
replacer = NumberUtil.displayCurrency(user.getMoney(), ess);
replacer = AdventureUtil.miniToLegacy(NumberUtil.displayCurrency(user.getMoney(), ess));
}
break;
case MAILS:
Loaded 100 of 282 files, more files were not shown because too many files have changed in this diff. Show more