Compare commits

...
158 Commits
Author SHA1 Message Date
Josh Roy f176893940 Release 2.19.7 2022-08-21 16:48:14 -04:00
Josh Roy af18afad7a Fix discord url link message (#5079) 2022-08-18 20:42:57 -07:00
Josh Roy bdc5f4c830 Fix baltop not working in command blocks (#5078) 2022-08-18 18:37:15 +00:00
Josh Roy 0be056b9c2 Improve error messages in Backup 2022-08-18 14:14:29 -04:00
Josh Roy 5f5d65c463 Fix null log messages causing an NPE 2022-08-18 14:14:29 -04:00
Josh Roy ca4077b204 Fix rgb color codes getting stripped in some cases (#5076) 2022-08-18 17:29:12 +00:00
Josh Roy 4ab3e20a0c Fix remaining uses of Bukkit's logger (#5075)
Fixes #5056
2022-08-18 17:35:53 +01:00
Josh Roy 576866540e Fix gson incompatibility on 1.8.8 (#5067) 2022-08-17 06:52:38 +00:00
Josh Roy dfcb9a1c52 Update Checkstyle IDEA config (#5047) 2022-08-16 08:18:12 +00:00
Josh Roy a7a9cbc034 Bump down to 2.19.7 (#5064)
Never ending cycle
2022-08-15 14:26:52 +01:00
MDandJosh Roy 2f4f555923 Fix issues with chat preview refactor (#5062)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2022-08-14 18:49:02 -04:00
MD 1c22edbb1b Prevent players opening their own inventories in /invsee (#5061) 2022-08-14 16:31:23 -04:00
Josh Roy b71fb520aa Prepare for 2.20.0 dev builds 2022-08-12 22:30:18 +01:00
Josh Roy 8f7b7d0a5f Release 2.19.6 2022-08-12 16:59:48 -04:00
Josh Roy f379323d7a Fix mappings in ReflOnlineModeProvider 2022-08-12 16:59:02 -04:00
MD f2dde4154c Release 2.19.5 2022-08-11 21:05:44 +01:00
Flask Bot 12c2a4f2b5 Update translations from Crowdin (#4823) 2022-08-11 20:24:59 +01:00
BoomEaro ee7c1b1cf1 Fix wrong message length check (#5041) 2022-08-08 14:53:59 -07:00
Sam 422f25af8b Fix erroneous addition to VersionUtil class check (#5037) 2022-08-07 19:41:27 +00:00
Josh RoyandMD 728c746200 Add commands info to /ess dump (#4965)
See #4961 and EssentialsX/Website#71.

Adds `commands.yml`, the known command map and `AlternativeCommandHandler` handover information to `/ess dump`.

Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2022-08-07 11:43:59 +01:00
MD 6dfa18ca53 Implement chat message signing for 1.19.1+ (#5030)
**Known issue: this inadvertently reformats `/minecraft:tell`. There's not much we can do about this in 2.19.x.**

This commit refactors EssentialsX Chat in order to support chat previews and signed chat messages in 1.19.1+.
2022-08-06 22:27:58 +01:00
Josh Roy a394760677 Update VersionUtil and /ess version (#5036) 2022-08-06 15:48:26 -04:00
MD 5f48cdef13 Bump to 1.19.2 (#5035) 2022-08-06 12:14:07 -04:00
pop4959andMD c56a9e6741 Add spawnable boat variants (#5027)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2022-08-02 14:18:57 -04:00
pop4959 5b20f30350 Fix ice other message (#5028)
Fix `iceOther` being sent to the target player instead of the sender. Fixes #5002.
2022-08-02 08:40:10 +01:00
pop4959 037577162b Add swift sneak enchantment (#5026)
Closes #5024.
2022-07-31 19:03:31 +00:00
Josh Roy 908189a233 Bump Spigot to 1.19.1 2022-07-28 11:30:24 -04:00
Josh Roy c938767b2d Prepare for 1.19.1 2022-07-28 11:30:24 -04:00
Josh Roy b135fcf086 Fix leave messages being sent when vanished (#5009) 2022-07-23 18:35:14 -04:00
Warrior 09dc49aacb Fix nickname feedback message when change-displayname is off (#4980)
Make the feedback message use the nickname instead of the player's display name if change-displayname is disabled. Fixes #4979.
2022-07-11 08:02:10 +00:00
Josh Roy f4b6197a49 Fix boolean logic for sleep ignore during afk status change (#4985) 2022-07-10 22:28:08 -07:00
Josh Roy 4a53cfe7ac Prevent role snowflakes from resolving roles with ids as names (#4983)
Fixes #4981.
2022-07-10 00:24:04 +01:00
DeltricandJosh Roy 2bba577567 Fix /unlimited with changing stack sizes (#4877)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2022-07-05 17:01:13 +00:00
pop4959andJosh Roy 6e674c73e0 Update unsupported message (#4976)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2022-07-05 09:52:14 -04:00
Josh Roy a60f3c067f Fix Essentials' logger breaking on 1.8.8-1.12.2 (#4975) 2022-07-02 14:50:45 -04:00
Josh RoyandMD 6816eb4e18 Use component logger on Paper for console colors (#4941)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2022-06-27 14:54:10 -04:00
Tristan Hermanns 9c5536b2e6 Fix minecraft namespace not working in give command (#4960) 2022-06-25 17:40:43 -04:00
Josh Roy ff80338350 Log filenames during configuration serialization errors (#4959) 2022-06-21 22:01:25 +00:00
Josh RoyandMD 8d856dd6db Fix paths and farmland not being solid (#4915)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2022-06-18 19:31:54 +00:00
Josh Roy 96c6c951e8 Don't teleport to a safe location for AFK freeze when flying (#4944)
Fixes #4902.
2022-06-15 15:43:57 +00:00
Josh Roy 0931b21f6d Fix places where Discord formatting wasn't sanitized (#4945)
Fixes #4891
2022-06-15 15:35:12 +00:00
Josh Roy 9147d1036d Fix ANSI color codes not getting stripped on Paper (#4942)
Paper uses 0x7f as an intermediate character between adventure and its ANSI pattern converter, we need to strip this.
2022-06-15 16:31:42 +01:00
MD a7f602e2ad Remove commons-lang3 dependency
`commons-lang3` is scheduled for removal by Spigot.

This commit reimplements the methods we use from StringUtils in StringUtil, and replaces NumberUtils.isDigits(String) with NumberUtil.isLong(String).
2022-06-15 16:18:35 +01:00
Flask Bot 0c81980ead Update items.json for 1.19
Note: this action was performed by a human (@mdcfe) under the
Flask-Bot account.
2022-06-15 16:18:35 +01:00
MD 2d5794f68d Add mangrove signs to MaterialUtil 2022-06-15 16:18:35 +01:00
MD 6b80e0b113 Bump run-paper MC version to 1.19 2022-06-15 16:18:35 +01:00
Josh Roy 18f9af898e Add 1.19 mobs/data 2022-06-15 16:18:35 +01:00
Josh Roy d04c933abe Fix server state reflection provider mappings 2022-06-15 16:18:35 +01:00
Josh Roy b916488de2 Bump VersionUtil and Spigot 2022-06-15 16:18:35 +01:00
MDandJosh Roy c6066bd2d8 Update README and contributing guide (#4851)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>

This PR brings the README up-to-date, reduces the number of references to upstream Essentials, and fleshes out the contributing guide with much more detail.
2022-06-10 13:06:24 +00:00
Josh Roy 3af931740b Don't progress playtime for vanished users (#4918) 2022-06-04 01:43:12 +00:00
Josh Roy 1c5a7e9ffb Bump down to 2.19.5 (#4914)
Mojang will be releasing 1.19 within two weeks and 2.20.0 is not ready for that timeframe. We want to release 2.19.5 with 1.19 support before that.
2022-05-30 21:21:19 +01:00
pop4959 ea5cdc097d Fix erroneous TeleportWarmupEvent event call (#4913) 2022-05-22 17:20:39 -04:00
Deltric d891268143 Fix /nick off breaking with changecolor permissions (#4876) 2022-03-31 19:57:36 -04:00
lucko 4bd1b3c09f Reduce user lookups for LuckPerms contexts (#4869) 2022-03-27 09:07:36 -04:00
MD c4f10d9c1d Fix double charge for /tpa when target has /tpauto on (#4862)
If a player uses `/tpa` to request a teleport to someone with `/tpauto` enabled, `/tpa` manually creates a charge for the teleportation.  
This PR changes the subsequent code to throw a `NoChargeException` instead of returning, meaning only the `AsyncTeleport` charge is applied, not the standard command one.

Fixes #4854.
2022-03-20 11:19:20 +00:00
MD e12f1b5022 Bump run-paper to 1.18.2 (#4857) 2022-03-15 07:56:52 -04:00
MDandJosh Roy 31732cec95 Prepare for 2.20.0 dev builds (#4849)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2022-03-12 19:33:28 -05:00
MD f104b6ec15 Release 2.19.4 2022-03-12 23:00:24 +00:00
MD 695546420f Run update check using Bukkit scheduler (#4839)
Fixes #4825.
2022-03-12 12:02:20 +00:00
Josh Roy 997fb1800e Fix preemptive setting of owner metadata on to trade signs (#4835)
Fixes #4836.
2022-03-08 15:08:34 +00:00
MD 3984bddd9d Fix 2.19.4 dev build version (#4834) 2022-03-06 00:06:48 +00:00
MD d92ce8bdfe Bump to 2.19.4 dev (#4831) 2022-03-05 18:33:04 +00:00
MD 3348bd9129 Release 2.19.3 2022-03-04 11:41:56 +00:00
Josh Roy 1a5526867c Fix IllegalAccessException with advancement listener on 1.12.2 (#4826)
Fixes #4809.
2022-03-03 20:38:39 +00:00
MD c5253bc5e2 Update to Minecraft 1.18.2 (#4821)
This PR updates the build setup to Gradle 7.4 and updates EssentialsX to Minecraft 1.18.2.
2022-02-28 20:51:26 +00:00
Flask Bot 29a2a865c5 New Crowdin updates (#4744) 2022-02-28 20:31:02 +00:00
MD c3b994808f Use GitHub proxy fallback for update checker (#4818) 2022-02-26 17:09:54 -05:00
triagonal bc2da98703 Make OfflinePlayer#setName protected for CMI Importer (#4805) 2022-02-14 07:40:48 -05:00
Josh Roy cbb012853c Fix toggleshout causing issues with question/local chat 2022-02-13 22:44:37 -05:00
Josh Roy 4bf4bd432a Add some color to the local prefix by default 2022-02-13 22:44:37 -05:00
Josh Roy 83d0e0d9a0 Add permissions to receive certain channel channels 2022-02-13 22:44:37 -05:00
Josh Roy 2f5c24d114 Add permission for local channel chat 2022-02-13 22:44:37 -05:00
Josh Roy 88c8ccd29b Add config for default shout state and for persisting shout state 2022-02-13 22:44:37 -05:00
Josh Roy 94edbcfeb1 Add chat question config option 2022-02-13 22:44:37 -05:00
Josh RoyandMD d5822e9a41 Add config for max /tree and /bigtree range (#4728)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2022-02-13 16:46:18 -05:00
Josh Roy debf09437e Add UUID support to trade and protection signs (#4713) 2022-02-13 15:54:19 -05:00
Josh Roy a9e5f079a9 Fix trade sign length validation issues (#4748) 2022-02-13 15:50:43 -05:00
Josh Roy f00c2dcf92 Fix keepinv policies ignoring offhand (#4725) 2022-02-13 20:37:25 +00:00
Josh Roy 63cbf7e2da Prevent legacy material support from being initiated (#4697) 2022-02-13 15:33:51 -05:00
Josh Roy 19837f9309 Add some more dump files (#4785)
Adds worth, tpr, and spawns configs.

See also https://github.com/EssentialsX/Website/pull/68
2022-02-08 09:26:05 +00:00
Josh Roy 4b8b770c30 Allow /nick without change-displayname (#4758)
Closes #4709.
2022-02-06 18:23:17 +00:00
Josh Roy ddc258ed11 Fix teleport request queue being reversed order (#4755)
Fix #4753
2022-02-06 18:18:40 +00:00
Josh Roy d23796dade Support doubles in /tppos (#4729)
Closes #1785
2022-02-06 18:01:51 +00:00
Josh Roy 41f5cc3175 Use Paper command forwarding API (#4794)
Uses API added in PaperMC/Paper@9940bca, when available.
2022-02-06 17:56:13 +00:00
Josh Roy c6fe160b47 Fix Paper command executor on modern Paper versions (#4791) 2022-02-01 22:13:16 +00:00
sxphirus 5c46bea2ca Add translation key for /near entries (#4740) 2022-01-20 10:05:31 -05:00
Flask Bot a9585bb525 New Crowdin updates (#4668) 2022-01-09 16:27:25 +00:00
Josh Roy bb88a6a749 Fix rate limit exception in update checker (#4731) 2022-01-02 17:24:32 +00:00
Pierre Dedrie 739600eb05 Fix safelogin for 1.18 and above by using worldProvider minHeight (#4715) 2021-12-26 23:56:03 +00:00
Josh Roy 5f98d3fac5 Add mitigation for JDK-8274349 (#4711) 2021-12-24 21:40:41 -05:00
Josh Roy 84326cf13e Fix LocationUtil#getSafeDestination NSME on older versions (#4708)
Fixes a NoSuchMethodError from old guava versions in old MC versions.

Fixes #4703
2021-12-23 11:55:31 +00:00
Josh Roy 685084219e Use futureproof Paper component serializer when available (#4706)
#plainSerializer will be removed when adventure 5.0.0 releases. This PR prevents this from breaking in the future.

Closes #4705
2021-12-23 10:57:41 +00:00
Josh Roy c4e62ae22b Remove usused configuration classes (#4707)
These were not used since configurate, no plugin should be using this, and it causes compile errors on the latest spigot version.
2021-12-23 01:18:02 +00:00
MD 05ce11f657 Bump to 2.19.3 dev 2021-12-15 21:29:45 +00:00
MD bcb0fb5825 Bump to 2.19.2 release 2021-12-15 20:58:38 +00:00
MD 91f4493fe0 Run Actions builds for dev branches (#4691) 2021-12-15 20:55:37 +00:00
MD d53ff36a2a Prevent IndexOutOfBoundsException in interaction replies (#4690) 2021-12-15 20:55:37 +00:00
MD 98917d97c8 Bump down to 2.19.2-dev 2021-12-15 20:55:37 +00:00
Josh Roy 7e1d18fee4 Prepare for 2.20.0 dev builds 2021-12-14 21:26:44 +00:00
Josh Roy 0b7e7801d0 Release 2.19.1 (#4681) 2021-12-14 19:16:08 +00:00
Josh Roy 840035944a Truncate Discord interaction messages to proper length (#4686) 2021-12-14 18:46:59 +00:00
Josh RoyandMD 20a7d1c7ee Add DiscordRelayEvent to edit relayed Discord->MC messages (#4656)
Implements the event suggested in #4580.

Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2021-12-14 16:26:57 +00:00
pop4959 253185bd0e Remove ignore teleport metadata 2021-12-12 22:23:56 +00:00
Josh Roy dae519494e Fix stack overflow when disabling commands from other addons (#4680) 2021-12-11 19:16:23 -08:00
Josh Roy dc27af78bf Update to MC 1.18.1 2021-12-11 12:13:50 +00:00
Flask Bot 41861a8551 New Crowdin updates (#4467) 2021-12-04 14:53:26 +00:00
Josh Roy 9b629e42d8 Bump JDA + discord-webhooks dependencies (#4655) 2021-12-04 14:47:40 +00:00
7794634d37 Add support for multiple queued TPA requests (#3801)
This PR adds support for players to receive multiple teleport requests, which are queued and can be managed independently of one another.

All commands should retain their current behavior but have some new additions;
* `/tpaccept`: now allows you to specify a player or `*` to accept a specific player's or all players' teleport request(s) respectively.
  - Using a wildcard will only accept all tpahere requests, as players can't teleport to multiple places simultaneously.
* `/tpdeny`: now allows you to specify a player or `*` to deny a specific player's or all players' teleport request(s) respectively.

This PR also adds a new setting for the maximum amount of pending TPA requests a user can have at once.
```yml
# The maximum amount of simultaneous tpa requests that can be pending for any given user.
# Once at this threshold, any new tpa requests will bump the oldest tpa requests out of queue.
# Defaults to 5.
tpa-max-amount: 5
```

Closes #3769
Closes #1550

Co-authored-by: Mariell Hoversholm <proximyst@proximy.st>
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2021-12-04 14:40:06 +00:00
Josh Roy d091d6902c Fix safelogin support with 1.18 world heights (#4667)
Fixes #4665.
2021-12-03 20:31:36 +00:00
MD c45c741210 Bump supported version to 1.18 release 2021-11-30 16:33:05 +00:00
MD e35c65b976 Refactor world info provider; only clamp to logical height when already below
Fixes #4657.
2021-11-30 16:33:05 +00:00
MDandJason 0983167740 Port remaining groovy build logic to kotlin
Co-authored-by: Jason <11360596+jpenilla@users.noreply.github.com>
2021-11-30 16:33:05 +00:00
1509cf8978 Support 0>y>256 for safe/random teleports (#4641)
Co-authored-by: pop4959 <pop4959@gmail.com>
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2021-11-30 16:33:05 +00:00
MD c0082ee734 Update to Gradle 7.3 and toolchain to JDK 17 2021-11-30 16:33:05 +00:00
Flask Bot db2ec1b436 Update items.json for Minecraft 1.18 2021-11-30 16:33:05 +00:00
Josh Roy 7a1e50d10f Fix reflection mappings for the ServerStateProvider in 1.18 2021-11-30 16:33:05 +00:00
Josh Roy b6ba1768a1 Mark 1.18 as a supported version 2021-11-30 16:33:05 +00:00
Josh Roy c38dd997d2 Update Spigot to 1.18 2021-11-30 16:33:05 +00:00
Josh Roy f8ca1bae5d Fix offline player error in /playtime for versions < 1.15.2 (#4649) 2021-11-25 19:50:49 +00:00
Josh Roy 3c60bcf2de Allow unsafe homes when force-disable-teleport-safety is enabled (#4650) 2021-11-25 19:47:42 +00:00
Josh Roy 3f857e3183 Fix DiscordUtil#getOrCreateWebhook using webhooks without tokens 2021-11-25 14:03:56 -05:00
Josh Roy 668c9634ca Ensure JDA is started before allowing calls to the JDA object 2021-11-25 14:03:56 -05:00
nik2143andJosh Roy 51c49b0de6 Set a metadata value for vanished players (#4646)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2021-11-24 09:57:55 -05:00
Lax 5723dac6ba Send discord config in dump even when plugin is disabled 2021-11-17 19:15:02 -05:00
Josh Roy 680d3230ea Add /discord command to display invite code (#4620) 2021-11-06 19:18:37 -04:00
Josh Roy 8f679de352 Add offline user support to /playtime (#4619) 2021-11-06 15:41:38 -07:00
Josh Roy 86d435eee1 Move UUID below alts in /seen (#4615) 2021-11-06 13:50:56 -07:00
Bobcat00andBobcat00 e4cf965bae Add translation for /list real name (#4614)
Co-authored-by: Bobcat00 <Bobcat00@users.noreply.github.com>
2021-11-05 22:24:21 +00:00
Andre_601 78c846a0a8 Minor typo corrections for EssentialsXDiscord (#4603) 2021-11-01 21:41:58 -04:00
pop4959andJosh Roy c466c9c370 Add metadata value to bypass last location setting on teleport (#4597)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2021-10-31 17:25:18 -04:00
Josh Roy 6994005a5f Fix light blocks being considering solid (#4601) 2021-10-30 22:25:03 -07:00
Josh Roy e43f06bfa6 Add /mail sendtempall (#4561)
Implements #4558
2021-10-24 16:45:01 +00:00
Josh Roy 9601687190 Add console regex filter for discord module (#4534) 2021-10-24 12:12:42 -04:00
Josh Roy 2ed94f1048 Add provider to use new Paper advancement API (#4588)
Paper added in PaperMC/Paper@40ee634
2021-10-24 14:27:07 +00:00
Josh Roy 70045c30f3 Migrate reflection in MetaItemStack to a provider (#4592) 2021-10-24 15:17:06 +01:00
Josh Roy ce88c0e1e4 Fix kit issues with potions in 1.8 (#4591)
Fixes #2867
2021-10-24 14:12:20 +00:00
Josh Roy 494e82e581 Fix ability to delete warps in unloaded worlds (#4590)
Fixes #4584.
2021-10-24 15:05:10 +01:00
MelluhandJosh Roy edd15132fd Add playtime command (#4562)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2021-10-23 15:29:37 -04:00
Tadhg BoyleandJosh Roy add664441e Add notify messages to jail command (#4576)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2021-10-23 15:18:51 -04:00
Josh Roy 58b0fb089f Improve error message when primary channel is improperly defined (#4586)
* Improve message verboseness when primary channel is improperly defined

* Clarify primary channel behavior
2021-10-20 13:09:56 +01:00
Josh Roy 90e4845627 Remove config reloads on world load/unload (#4573)
Since the Configurate rewrite, we hold locations using `LazyLocation`, which is converted to a `Location` with world lookups on demand; as such we no longer need to reload configs on each world load since invalid locations will now softly fail.
2021-10-13 18:41:48 +01:00
Josh RoyandMD 43f4d306be Add discordbroadcast command (#4541)
* Add discordbroadcast command

* Update EssentialsDiscord/src/main/resources/plugin.yml

Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>

* Add emoji parsing/tab complete for discordbroadcast command

Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2021-10-11 15:54:55 -04:00
Josh Roy cb7d9baf7a Fix exception while running vanilla commands for chat command relay (#4552)
Fixes #4545
2021-10-11 19:32:41 +00:00
Josh Roy f3aea5e6ec Improve error message for updater checker rate limit (#4560)
Fixes #4556
2021-10-11 20:06:18 +01:00
Josh Roy a7a1fcd98c Fix Discord token regex censor pattern (#4563)
Discord changed their token format again
2021-10-07 09:22:41 +01:00
ef8bcc8bc4 Add kits subfolder to allow for multiple kit files (#4407)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2021-10-02 19:14:41 -04:00
MDandJosh Roy b3692d18b0 Update plugin.yml authors to reflect EssentialsX contributions (#4551)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2021-09-28 15:49:55 -04:00
Josh Roy a7b2b675d5 Add essentials.seen.uuid permission to show uuids in seen (#4531)
Adds `essentials.seen.uuid` permission requirement to show uuids in `/seen`. People were complaining this cluttered it so whatever. Also adds said permission to the `essentials.seen.extra` permission group.

Closes #4499.
2021-09-28 13:13:50 +00:00
Josh RoyandMD 7d7a8e47ac Fix verbose command usages not being disabled properly (#4530)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2021-09-28 13:09:04 +00:00
MDandJosh Roy f0da17b75c Asynchronously filter commands on Paper when possible (#4460)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2021-09-15 17:23:31 -04:00
Josh Roy d86b471402 Add action message type (#4520)
Adds a message type which will show when a player runs the /action (/me) command.

Message Type:
```yml
# Configure which Discord channels different messages will be sent to.
# You can either use the names of the channels listed above or just the id of a channel.
# If an invalid channel is used, the primary channel will be used instead.
#
# To disable a message from showing, use 'none' as the channel name.
message-types:
  ...
  # Action messages sent when a player runs the /me or /action commands.
  action: primary
```

Message Format:
```yml
# The following entries allow you to customize the formatting of messages sent by the plugin.
# Each message has a description of how it is used along with placeholders that can be used.
messages:
  ...
  # This is the message sent to Discord when a player runs the /me or /action command.
  # The following placeholders can be used here:
  # - {username}: The name of the user who ran the command
  # - {displayname}: The display name of the user who ran the command
  # - {action}: The action (message) the user used in the command.
  # ... PlaceholderAPI placeholders are also supported here too!
  action: ":person_biking: {displayname} *{action}*"
```
2021-09-15 14:52:14 +00:00
Josh Roy 767508fb87 Fix bed spawn setting when waking up villagers (#4524)
Fixes #4461.
2021-09-15 15:40:23 +01:00
LaxandJosh Roy c85d772e1b Add /ess dump all as alias for /ess dump * (#4517)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2021-09-08 17:48:47 -04:00
MDandJosh Roy fde6524e46 Fix error with commands ending in single colon (#4508)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2021-09-01 13:37:46 -04:00
b2886969f0 Update to bStats v2 (#4350)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2021-09-01 13:33:43 -04:00
Josh RoyandMD 19ca5186e4 Replace unneeded inputs with new /ess dump in issue template (#4479)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2021-09-01 13:26:54 +01:00
Josh Roy b86a34c909 Prepare for 2.19.1 dev builds (#4505) 2021-09-01 12:55:37 +01:00
263 changed files with 13292 additions and 4146 deletions

No files matched your search

+2 -16
View File
@@ -22,24 +22,10 @@ body:
validations:
required: true
- type: textarea
attributes:
label: "`/ess version` output"
description: Run `/ess version` in the console, then copy and paste the full output of the command into this box.
validations:
required: true
- type: input
attributes:
label: Server startup log
description: Upload your server startup log (from the start of `latest.log` up to where it says "Done!") to either https://paste.gg or https://gist.github.com, save and then paste the link in this box.
placeholder: "Example: https://paste.gg/p/anonymous/109dd6a10a734a3aa430d5a351ea5210"
validations:
required: true
- type: input
attributes:
label: EssentialsX config files
description: Upload your EssentialsX `config.yml` (and any other relevant files like `kits.yml`) to either https://paste.gg or https://gist.github.com, save and then 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"
label: "`/ess dump all` output"
description: Run `/ess dump all` in the console, then copy and paste the link from the output of the command into this box. (If this command doesn't work, you should [update EssentialsX](https://essentialsx.net/downloads.html) and try again.)
validations:
required: true
- type: input
+1
View File
@@ -4,6 +4,7 @@ on:
push:
branches:
- 2.x
- dev/*
jobs:
build:
+1
View File
@@ -9,6 +9,7 @@ on:
branches:
- 2.x
- mc/*
- dev/*
jobs:
build:
+22 -14
View File
@@ -1,19 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CheckStyle-IDEA">
<option name="configuration">
<map>
<entry key="active-configuration" value="PROJECT_RELATIVE:$PROJECT_DIR$/.checkstyle/checkstyle.xml:EssentialsX" />
<entry key="checkstyle-version" value="8.36.2" />
<entry key="copy-libs" value="true" />
<entry key="location-0" value="BUNDLED:(bundled):Sun Checks" />
<entry key="location-1" value="BUNDLED:(bundled):Google Checks" />
<entry key="location-2" value="PROJECT_RELATIVE:$PROJECT_DIR$/.checkstyle/checkstyle.xml:EssentialsX" />
<entry key="property-2.configDirectory" value=".checkstyle/" />
<entry key="scan-before-checkin" value="true" />
<entry key="scanscope" value="JavaOnly" />
<entry key="suppress-errors" value="false" />
</map>
<component name="CheckStyle-IDEA" serialisationVersion="2">
<checkstyleVersion>8.36.2</checkstyleVersion>
<scanScope>JavaOnly</scanScope>
<copyLibs>true</copyLibs>
<scanBeforeCheckin>true</scanBeforeCheckin>
<option name="thirdPartyClasspath" />
<option name="activeLocationIds">
<option value="321e5753-4201-4d2c-bf31-6232011122fd" />
</option>
<option name="locations">
<list>
<ConfigurationLocation id="bundled-sun-checks" type="BUNDLED" scope="All" description="Sun Checks">(bundled)</ConfigurationLocation>
<ConfigurationLocation id="bundled-google-checks" type="BUNDLED" scope="All" description="Google Checks">(bundled)</ConfigurationLocation>
<ConfigurationLocation id="321e5753-4201-4d2c-bf31-6232011122fd" type="PROJECT_RELATIVE" scope="All" description="EssentialsX">
$PROJECT_DIR$/.checkstyle/checkstyle.xml
<option name="properties">
<map>
<entry key="configDirectory" value=".checkstyle/" />
</map>
</option>
</ConfigurationLocation>
</list>
</option>
</component>
</project>
+93 -22
View File
@@ -1,31 +1,102 @@
Contributing to EssentialsX
===========================
# Contributing to EssentialsX
Want to help improve EssentialsX? There are several ways you can support and contribute to the project.
*By contributing to EssentialsX, you agree to license your changes under the [GNU General Public License version 3](https://github.com/EssentialsX/Essentials/blob/2.x/LICENSE).*
If you'd like to make a financial contribution to the project, you can join our [Patreon](https://www.patreon.com/essentialsx/),
or to make a one-off donation you can visit our [Ko-fi page](https://ko-fi.com/essentialsx). If you can't make a
donation, don't worry! There are lots of other ways to contribute:
## Submitting code changes to EssentialsX
* Do you run a server? Take a look at our ["help wanted"](https://github.com/EssentialsX/Essentials/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22help+wanted%22)
and ["bug: unconfirmed"](https://github.com/EssentialsX/Essentials/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22bug%3A+unconfirmed%22)
issues, where you can find issues that need extra testing and investigation.
* Do you speak multiple languages? If so, we always welcome contributions to our [Crowdin project](https://crowdin.com/project/essentialsx-official).
* Do you enjoy helping others? If so, why not contribute to the [EssentialsX documentation](https://github.com/EssentialsX/wiki)?
You can also join the [MOSS Discord community](https://discord.gg/casfFyh) and provide direct community support to
other EssentialsX users.
* If you're a developer, you could look through our ["open to PR"](https://github.com/EssentialsX/Essentials/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22status%3A+open+to+PR%22)
issues. We're always happy to receive bug fixes and feature additions as pull requests.
If you're interested in submitting new code to EssentialsX, we accept changes via GitHub pull requests.
Submitting a PR
---------------
### Adding features
EssentialsX has extensive templates for PRs that detail how to submit your PR. To find out more, see the PR templates for:
* [Bug fixes](https://github.com/EssentialsX/Essentials/blob/2.x/.github/PULL_REQUEST_TEMPLATE/bug-fix.md)
* [New features](https://github.com/EssentialsX/Essentials/blob/2.x/.github/PULL_REQUEST_TEMPLATE/new-feature.md)
In general, we will only consider PRs for features if they have already been discussed with the team through
GitHub issues and discussions. Check the list of
["open to PR" issues](https://github.com/EssentialsX/Essentials/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22status%3A+open+to+PR%22)
and [feature request discussions](https://github.com/EssentialsX/Essentials/discussions/categories/ideas-and-feature-suggestions)
before you start working on your changes. If you don't see your desired feature listed,
[open a feature request](https://github.com/EssentialsX/Essentials/issues/new/choose) and wait for a response, otherwise
you may end up wasting your time on a feature that we aren't in a position to accept.
Want to discuss a feature before opening a PR? Join the [EssentialsX Development Discord server](https://discord.gg/CUN7qVb). Note that this server is **not for end-users** - if you need support with EssentialsX, you should join [MOSS](https://discord.gg/casfFyh) instead.
#### Keep it focused
By contributing to EssentialsX, you agree to license your code under the [GNU General Public License version 3](https://github.com/EssentialsX/Essentials/blob/2.x/LICENSE).
Please try to keep feature PRs focused around one feature. Your PR should ideally contain
one feature, or a few closely-linked features. If you submit several unrelated features
in one PR, the PR will not be accepted.
### Fixing bugs
If you're opening a PR to fix a bug, please ensure a bug report has been filed - search the
[issue tracker](https://github.com/EssentialsX/Essentials/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22bug%3A+confirmed%22%2C%22bug%3A+unconfirmed%22%2C%22bug%3A+upstream%22)
for an existing report, and if you can't find a bug report,
[create one](https://github.com/EssentialsX/Essentials/issues/new/choose) before you submit your PR.
#### Unconfirmed bugs
You may find a bug report with the label `bug: unconfirmed`. This means the EssentialsX team hasn't had the time
to review the bug report yet or hasn't been able to confirm
whether the reported issue is actually a bug in EssentialsX. You can help us by following the steps in the report and
posting whether you are able to replicate this issue, ideally on the latest versions of EssentialsX and Paper. This will
help us confirm issues and prioritise PRs accordingly.
#### Upstream bugs
You may also find bug reports with the `bug: upstream` label. This label means the issue is caused by a bug in *another
project*, not EssentialsX. This includes bugs in CraftBukkit/Spigot and bugs in other plugins. It may be appropriate to
mitigate an issue in EssentialsX, but please check with us in the [EssentialsX Development Discord server](https://discord.gg/CUN7qVb) before you submit a PR.
### Making your changes
You'll need the following to make your changes to EssentialsX:
* A GitHub account
* [`git`](https://git-scm.com/downloads): the Git command-line tool, used to track and save your changes
* [`gh`](https://cli.github.com/): the GitHub command-line tool, used to submit your changes to EssentialsX
* Your IDE of choice - we recommend [IntelliJ IDEA Community Edition](https://www.jetbrains.com/idea/download)
If you're already familiar with Git, you can skip this next section.
You'll need to clone the EssentialsX repository
(`gh repo clone EssentialsX/Essentials`), then create a new branch for your work
(`cd Essentials` then `git switch -c my-cool-pr`).
You can then make changes using your IDE of choice. Follow the instructions in `README.md` to build and test your
changes.
Once you've finished, you should commit your changes (`git commit -am "My cool commit name!"`).
### Submitting your PR
*Even if you're already familiar with GitHub, you will need to follow these steps in order to submit a PR to
EssentialsX. This ensures we have the information we need to test and review your changes.*
Next, you'll need to fork EssentialsX on GitHub and push your changes to a branch on that fork. We strongly recommend
using the `gh` command-line tool for this:
* In your terminal, run `gh pr create`.
* Select either the bug fix or feature template, depending on what your PR is for.
* If you get asked `Where should we push the '...' branch?`, select `Create a fork of EssentialsX/Essentials`.
* For the title, choose a title that describes what your PR does. For example, `Add more ducks to /spawnmob`.
* For the body, press E. You will then need to fill in the PR template in your text editor.
- Follow the instructions in the template and fill out the sections as required.
- This step is important! Without it, we won't know why you've made your changes or how to test them.
* Save the file in your text editor and close it, then return to the terminal.
* Select `Submit` to open your PR.
If you follow these steps correctly, GitHub will create a fork (if necessary) and then open a PR with your changes. You
can now sit back while we review your changes. If we need to ask questions or request further changes to your code,
we will review your PR and post a comment on GitHub. You can respond to our reviews and comments on the GitHub website,
and you can push new changes using `git commit` and `git push`.
## Submitting community translations to EssentialsX
EssentialsX relies on community translations for its messages in other languages. You can help translate EssentialsX on
[Crowdin](https://translate.essentialsx.net/). You'll need a Crowdin account to translate and improve messages.
If your language isn't listed or doesn't have an active proofreader, please let us know on Discord (see below).
## Discussing EssentialsX contributions
Want to discuss something before opening a PR or translating messages? Join the
[EssentialsX Development Discord server](https://discord.gg/CUN7qVb). Note that this server is **not for end-users** -
if you need support with EssentialsX, you should join [MOSS](https://discord.gg/casfFyh) instead.
+12 -1
View File
@@ -10,6 +10,8 @@ dependencies {
api 'io.papermc:paperlib:1.0.6'
api 'org.bstats:bstats-bukkit:2.2.1'
implementation 'org.spongepowered:configurate-yaml:4.1.2'
implementation 'org.checkerframework:checker-qual:3.14.0'
@@ -20,14 +22,22 @@ dependencies {
exclude group: "org.bukkit", module: "bukkit"
}
api(project(':providers:1_8Provider')) {
exclude group: "org.spigotmc", module: "spigot"
}
api(project(':providers:1_12Provider')) {
exclude group: "org.bukkit", module: "bukkit"
}
}
test {
testLogging.showStandardStreams = true
}
shadowJar {
dependencies {
include (dependency('io.papermc:paperlib'))
include (dependency('org.bstats:bstats-bukkit'))
include (dependency('org.bstats:bstats-base'))
include (dependency('org.spongepowered:configurate-yaml'))
include (dependency('org.spongepowered:configurate-core'))
include (dependency('org.yaml:snakeyaml'))
@@ -37,9 +47,10 @@ shadowJar {
include (project(':providers:PaperProvider'))
include (project(':providers:NMSReflectionProvider'))
include (project(':providers:1_8Provider'))
include (project(':providers:1_12Provider'))
}
relocate 'io.papermc.lib', 'com.earth2me.essentials.paperlib'
relocate 'org.bstats.bukkit', 'com.earth2me.essentials.metrics'
relocate 'org.bstats', 'com.earth2me.essentials.libs.bstats'
relocate 'org.spongepowered.configurate', 'com.earth2me.essentials.libs.configurate'
relocate 'org.yaml.snakeyaml', 'com.earth2me.essentials.libs.snakeyaml'
relocate 'io.leangen.geantyref', 'com.earth2me.essentials.libs.geantyref'
@@ -11,10 +11,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AlternativeCommandsHandler {
private static final Logger LOGGER = Logger.getLogger("Essentials");
private final transient Map<String, List<Command>> altcommands = new HashMap<>();
private final transient Map<String, String> disabledList = new HashMap<>();
private final transient IEssentials ess;
@@ -29,11 +27,12 @@ public class AlternativeCommandsHandler {
}
public final void addPlugin(final Plugin plugin) {
if (plugin.getDescription().getMain().contains("com.earth2me.essentials")) {
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()) {
final String commandName = entry.getKey().contains(":") ? entry.getKey().split(":")[1] : entry.getKey();
final String[] commandSplit = entry.getKey().split(":", 2);
final String commandName = commandSplit.length > 1 ? commandSplit[1] : entry.getKey();
final Command command = entry.getValue();
final List<Command> pluginCommands = altcommands.computeIfAbsent(commandName.toLowerCase(Locale.ENGLISH), k -> new ArrayList<>());
@@ -94,7 +93,7 @@ public class AlternativeCommandsHandler {
if (pc instanceof PluginIdentifiableCommand) {
final String altString = ((PluginIdentifiableCommand) pc).getPlugin().getName() + ":" + pc.getName();
if (ess.getSettings().isDebug()) {
LOGGER.log(Level.INFO, "Essentials: Alternative command " + label + " found, using " + altString);
ess.getLogger().log(Level.INFO, "Essentials: Alternative command " + label + " found, using " + altString);
}
disabledList.put(label, altString);
}
@@ -189,7 +189,7 @@ public class AsyncTeleport implements IAsyncTeleport {
}
PaperLib.getChunkAtAsync(targetLoc.getWorld(), targetLoc.getBlockX() >> 4, targetLoc.getBlockZ() >> 4, true, true).thenAccept(chunk -> {
Location loc = targetLoc;
if (LocationUtil.isBlockUnsafeForUser(teleportee, chunk.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
if (LocationUtil.isBlockUnsafeForUser(ess, teleportee, chunk.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
if (ess.getSettings().isTeleportSafetyEnabled()) {
if (ess.getSettings().isForceDisableTeleportSafety()) {
//The chunk we're teleporting to is 100% going to be loaded here, no need to teleport async.
@@ -308,7 +308,7 @@ public class AsyncTeleport implements IAsyncTeleport {
private void teleportOther(final IUser teleporter, final IUser teleportee, final ITarget target, final Trade chargeFor, final TeleportCause cause, final CompletableFuture<Boolean> future) {
double delay = ess.getSettings().getTeleportDelay();
final TeleportWarmupEvent event = new TeleportWarmupEvent(teleportee, cause, target, delay);
final TeleportWarmupEvent event = new TeleportWarmupEvent(teleporter, teleportee, cause, target, delay);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
@@ -10,12 +10,10 @@ import java.io.InputStreamReader;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
public class Backup implements Runnable {
private static final Logger LOGGER = Logger.getLogger("Essentials");
private transient final Server server;
private transient final IEssentials ess;
private final AtomicBoolean pendingShutdown = new AtomicBoolean(false);
@@ -81,7 +79,7 @@ public class Backup implements Runnable {
taskLock.complete(new Object());
return;
}
LOGGER.log(Level.INFO, tl("backupStarted"));
ess.getLogger().log(Level.INFO, tl("backupStarted"));
final CommandSender cs = server.getConsoleSender();
server.dispatchCommand(cs, "save-all");
server.dispatchCommand(cs, "save-off");
@@ -99,17 +97,17 @@ public class Backup implements Runnable {
do {
line = reader.readLine();
if (line != null) {
LOGGER.log(Level.INFO, line);
ess.getLogger().log(Level.INFO, line);
}
} while (line != null);
}
} catch (final IOException ex) {
LOGGER.log(Level.SEVERE, null, ex);
ess.getLogger().log(Level.SEVERE, "An error occurred while reading backup child process", ex);
}
});
child.waitFor();
} catch (final InterruptedException | IOException ex) {
LOGGER.log(Level.SEVERE, null, ex);
ess.getLogger().log(Level.SEVERE, "An error occurred while building the backup child process", ex);
} finally {
class BackupEnableSaveTask implements Runnable {
@Override
@@ -120,7 +118,7 @@ public class Backup implements Runnable {
}
active = false;
taskLock.complete(new Object());
LOGGER.log(Level.INFO, tl("backupFinished"));
ess.getLogger().log(Level.INFO, tl("backupFinished"));
}
}
@@ -263,6 +263,14 @@ public final class Enchantments {
} catch (final IllegalArgumentException ignored) {
}
try { // 1.19
final Enchantment swiftSneak = Enchantment.getByName("SWIFT_SNEAK");
if (swiftSneak != null) {
ENCHANTMENTS.put("swiftsneak", swiftSneak);
}
} catch (final IllegalArgumentException ignored) {
}
try {
final Class<?> namespacedKeyClass = Class.forName("org.bukkit.NamespacedKey");
final Class<?> enchantmentClass = Class.forName("org.bukkit.enchantments.Enchantment");
@@ -47,6 +47,7 @@ import net.ess3.api.IEssentials;
import net.ess3.api.IItemDb;
import net.ess3.api.IJails;
import net.ess3.api.ISettings;
import net.ess3.nms.refl.providers.ReflDataWorldInfoProvider;
import net.ess3.nms.refl.providers.ReflFormattedCommandAliasProvider;
import net.ess3.nms.refl.providers.ReflKnownCommandsProvider;
import net.ess3.nms.refl.providers.ReflOnlineModeProvider;
@@ -57,25 +58,34 @@ import net.ess3.nms.refl.providers.ReflSpawnerBlockProvider;
import net.ess3.nms.refl.providers.ReflSyncCommandsProvider;
import net.ess3.provider.ContainerProvider;
import net.ess3.provider.FormattedCommandAliasProvider;
import net.ess3.provider.ItemUnbreakableProvider;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.MaterialTagProvider;
import net.ess3.provider.PersistentDataProvider;
import net.ess3.provider.PotionMetaProvider;
import net.ess3.provider.SerializationProvider;
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.BaseLoggerProvider;
import net.ess3.provider.providers.BasePotionDataProvider;
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.LegacyItemUnbreakableProvider;
import net.ess3.provider.providers.LegacyPotionMetaProvider;
import net.ess3.provider.providers.LegacySpawnEggProvider;
import net.ess3.provider.providers.ModernDataWorldInfoProvider;
import net.ess3.provider.providers.ModernItemUnbreakableProvider;
import net.ess3.provider.providers.ModernPersistentDataProvider;
import net.ess3.provider.providers.ModernSignDataProvider;
import net.ess3.provider.providers.PaperContainerProvider;
import net.ess3.provider.providers.PaperKnownCommandsProvider;
import net.ess3.provider.providers.PaperMaterialTagProvider;
@@ -84,7 +94,6 @@ import net.ess3.provider.providers.PaperSerializationProvider;
import net.ess3.provider.providers.PaperServerStateProvider;
import net.essentialsx.api.v2.services.BalanceTop;
import net.essentialsx.api.v2.services.mail.MailService;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.block.Block;
@@ -103,7 +112,6 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
@@ -133,7 +141,8 @@ import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private static final Logger LOGGER = Logger.getLogger("Essentials");
private static final Logger BUKKIT_LOGGER = Logger.getLogger("Essentials");
private static Logger LOGGER = null;
private final transient TNTExplodeListener tntListener = new TNTExplodeListener(this);
private final transient Set<String> vanishedPlayers = new LinkedHashSet<>();
private transient ISettings settings;
@@ -167,6 +176,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private transient SyncCommandsProvider syncCommandsProvider;
private transient PersistentDataProvider persistentDataProvider;
private transient ReflOnlineModeProvider onlineModeProvider;
private transient ItemUnbreakableProvider unbreakableProvider;
private transient WorldInfoProvider worldInfoProvider;
private transient SignDataProvider signDataProvider;
private transient Kits kits;
private transient RandomTeleport randomTeleport;
private transient UpdateChecker updateChecker;
@@ -193,6 +205,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
public void setupForTesting(final Server server) throws IOException, InvalidDescriptionException {
LOGGER = new BaseLoggerProvider(this, BUKKIT_LOGGER);
final File dataFolder = File.createTempFile("essentialstest", "");
if (!dataFolder.delete()) {
throw new IOException();
@@ -233,9 +246,12 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
@Override
public void onEnable() {
try {
if (LOGGER != this.getLogger()) {
LOGGER.setParent(this.getLogger());
if (BUKKIT_LOGGER != super.getLogger()) {
BUKKIT_LOGGER.setParent(super.getLogger());
}
LOGGER = EssentialsLogger.getLoggerProvider(this);
EssentialsLogger.updatePluginLogger(this);
execTimer = new ExecuteTimer();
execTimer.start();
i18n = new I18n(this);
@@ -251,6 +267,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
case DANGEROUS_FORK:
getLogger().severe(tl("serverUnsupportedDangerous"));
break;
case STUPID_PLUGIN:
getLogger().severe(tl("serverUnsupportedDumbPlugins"));
break;
case UNSTABLE:
getLogger().severe(tl("serverUnsupportedMods"));
break;
@@ -410,6 +429,24 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
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);
}
execTimer.mark("Init(Providers)");
reload();
@@ -444,7 +481,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
final String timeroutput = execTimer.end();
if (getSettings().isDebug()) {
LOGGER.log(Level.INFO, "Essentials load {0}", timeroutput);
LOGGER.log(Level.INFO, "Essentials load " + timeroutput);
}
} catch (final NumberFormatException ex) {
handleCrash(ex);
@@ -455,6 +492,15 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
getBackup().setPendingShutdown(false);
}
// Returns our provider logger if available
public static Logger getWrappedLogger() {
if (LOGGER != null) {
return LOGGER;
}
return BUKKIT_LOGGER;
}
@Override
public void saveConfig() {
// We don't use any of the bukkit config writing, as this breaks our config file formatting.
@@ -603,7 +649,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
return completer.onTabComplete(cSender, command, commandLabel, args);
}
} catch (final Exception ex) {
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
}
}
}
@@ -684,7 +730,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
try {
pc.execute(cSender, commandLabel, args);
} catch (final Exception ex) {
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
cSender.sendMessage(tl("internalError"));
}
return true;
@@ -704,10 +750,10 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
if (bSenderBlock != null) {
if (getSettings().logCommandBlockCommands()) {
Bukkit.getLogger().log(Level.INFO, "CommandBlock at {0},{1},{2} issued server command: /{3} {4}", new Object[] {bSenderBlock.getX(), bSenderBlock.getY(), bSenderBlock.getZ(), commandLabel, EssentialsCommand.getFinalArg(args, 0)});
LOGGER.log(Level.INFO, "CommandBlock at " + bSenderBlock.getX() + "," + bSenderBlock.getY() + "," + bSenderBlock.getZ() + " issued server command: /" + commandLabel + " " + EssentialsCommand.getFinalArg(args, 0));
}
} else if (user == null) {
Bukkit.getLogger().log(Level.INFO, "{0} issued server command: /{1} {2}", new Object[] {cSender.getName(), commandLabel, EssentialsCommand.getFinalArg(args, 0)});
LOGGER.log(Level.INFO, cSender.getName()+ " issued server command: /" + commandLabel + " " + EssentialsCommand.getFinalArg(args, 0));
}
final CommandSource sender = new CommandSource(cSender);
@@ -727,7 +773,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
if (getSettings().isCommandDisabled(commandLabel)) {
if (getKnownCommandsProvider().getKnownCommands().containsKey(commandLabel)) {
final Command newCmd = getKnownCommandsProvider().getKnownCommands().get(commandLabel);
if (!(newCmd instanceof PluginIdentifiableCommand) || ((PluginIdentifiableCommand) newCmd).getPlugin() != this) {
if (!(newCmd instanceof PluginIdentifiableCommand) || !isEssentialsPlugin(((PluginIdentifiableCommand) newCmd).getPlugin())) {
return newCmd.execute(cSender, commandLabel, args);
}
}
@@ -771,14 +817,15 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
} catch (final NoChargeException | QuietAbortException ex) {
return true;
} catch (final NotEnoughArgumentsException ex) {
sender.sendMessage(tl("commandHelpLine1", commandLabel));
sender.sendMessage(tl("commandHelpLine2", command.getDescription()));
sender.sendMessage(tl("commandHelpLine3"));
if (getSettings().isVerboseCommandUsages() && !cmd.getUsageStrings().isEmpty()) {
sender.sendMessage(tl("commandHelpLine1", commandLabel));
sender.sendMessage(tl("commandHelpLine2", command.getDescription()));
sender.sendMessage(tl("commandHelpLine3"));
for (Map.Entry<String, String> usage : cmd.getUsageStrings().entrySet()) {
sender.sendMessage(tl("commandHelpLineUsage", usage.getKey().replace("<command>", commandLabel), usage.getValue()));
}
} else {
sender.sendMessage(command.getDescription());
sender.sendMessage(command.getUsage().replace("<command>", commandLabel));
}
if (!ex.getMessage().isEmpty()) {
@@ -801,6 +848,10 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
}
private boolean isEssentialsPlugin(Plugin plugin) {
return plugin.getDescription().getMain().contains("com.earth2me.essentials") || plugin.getDescription().getMain().contains("net.essentialsx");
}
public void cleanupOpenInventories() {
for (final User user : getOnlineUsers()) {
if (user.isRecipeSee()) {
@@ -1014,7 +1065,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
if (user == null) {
if (getSettings().isDebug()) {
LOGGER.log(Level.INFO, "Constructing new userfile from base player {0}", base.getName());
LOGGER.log(Level.INFO, "Constructing new userfile from base player " + base.getName());
}
user = new User(base, this);
} else {
@@ -1269,6 +1320,21 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
return onlineModeProvider;
}
@Override
public ItemUnbreakableProvider getItemUnbreakableProvider() {
return unbreakableProvider;
}
@Override
public WorldInfoProvider getWorldInfoProvider() {
return worldInfoProvider;
}
@Override
public SignDataProvider getSignDataProvider() {
return signDataProvider;
}
@Override
public PluginCommand getPluginCommand(final String cmd) {
return this.getCommand(cmd);
@@ -1302,25 +1368,6 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
@EventHandler(priority = EventPriority.LOW)
public void onWorldLoad(final WorldLoadEvent event) {
PermissionsDefaults.registerBackDefaultFor(event.getWorld());
ess.getJails().reloadConfig();
ess.getWarps().reloadConfig();
for (final IConf iConf : ((Essentials) ess).confList) {
if (iConf instanceof IEssentialsModule) {
iConf.reloadConfig();
}
}
}
@EventHandler(priority = EventPriority.LOW)
public void onWorldUnload(final WorldUnloadEvent event) {
ess.getJails().reloadConfig();
ess.getWarps().reloadConfig();
for (final IConf iConf : ((Essentials) ess).confList) {
if (iConf instanceof IEssentialsModule) {
iConf.reloadConfig();
}
}
}
@Override
@@ -42,8 +42,12 @@ public class EssentialsBlockListener implements Listener {
final User user = ess.getUser(event.getPlayer());
if (user.hasUnlimited(is) && user.getBase().getGameMode() == GameMode.SURVIVAL) {
ess.scheduleSyncDelayedTask(() -> {
user.getBase().getInventory().addItem(is);
user.getBase().updateInventory();
if (is != null && is.getType() != null && !MaterialUtil.isAir(is.getType())) {
final ItemStack cloneIs = is.clone();
cloneIs.setAmount(1);
user.getBase().getInventory().addItem(cloneIs);
user.getBase().updateInventory();
}
});
}
}
@@ -1,674 +0,0 @@
package com.earth2me.essentials;
import com.google.common.io.Files;
import net.ess3.api.InvalidWorldException;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.math.BigDecimal;
import java.math.MathContext;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
public class EssentialsConf extends YamlConfiguration {
protected static final Logger LOGGER = Logger.getLogger("Essentials");
protected static final Charset UTF8 = StandardCharsets.UTF_8;
private static final ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
protected final File configFile;
private final AtomicInteger pendingDiskWrites = new AtomicInteger(0);
private final AtomicBoolean transaction = new AtomicBoolean(false);
private final byte[] bytebuffer = new byte[1024];
protected String templateName = null;
private Class<?> resourceClass = EssentialsConf.class;
public EssentialsConf(final File configFile) {
super();
this.configFile = configFile.getAbsoluteFile();
}
public static BigDecimal toBigDecimal(final String input, final BigDecimal def) {
if (input == null || input.isEmpty()) {
return def;
} else {
try {
return new BigDecimal(input, MathContext.DECIMAL128);
} catch (final NumberFormatException | ArithmeticException e) {
return def;
}
}
}
public synchronized void load() {
if (pendingDiskWrites.get() != 0) {
LOGGER.log(Level.INFO, "File {0} not read, because it''s not yet written to disk.", configFile);
return;
}
if (!configFile.getParentFile().exists()) {
if (!configFile.getParentFile().mkdirs()) {
LOGGER.log(Level.SEVERE, tl("failedToCreateConfig", configFile.toString()));
}
}
// This will delete files where the first character is 0. In most cases they are broken.
if (configFile.exists() && configFile.length() != 0) {
try {
final InputStream input = new FileInputStream(configFile);
try {
if (input.read() == 0) {
input.close();
configFile.delete();
}
} catch (final IOException ex) {
LOGGER.log(Level.SEVERE, null, ex);
} finally {
try {
input.close();
} catch (final IOException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
} catch (final FileNotFoundException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
if (!configFile.exists()) {
if (legacyFileExists()) {
convertLegacyFile();
} else if (altFileExists()) {
convertAltFile();
} else if (templateName != null) {
LOGGER.log(Level.INFO, tl("creatingConfigFromTemplate", configFile.toString()));
createFromTemplate();
} else {
return;
}
}
try {
try (final FileInputStream inputStream = new FileInputStream(configFile)) {
final long startSize = configFile.length();
if (startSize > Integer.MAX_VALUE) {
throw new InvalidConfigurationException("File too big");
}
ByteBuffer buffer = ByteBuffer.allocate((int) startSize);
int length;
while ((length = inputStream.read(bytebuffer)) != -1) {
if (length > buffer.remaining()) {
final ByteBuffer resize = ByteBuffer.allocate(buffer.capacity() + length - buffer.remaining());
final int resizePosition = buffer.position();
// Fix builds compiled against Java 9+ breaking on Java 8
((Buffer) buffer).rewind();
resize.put(buffer);
resize.position(resizePosition);
buffer = resize;
}
buffer.put(bytebuffer, 0, length);
}
((Buffer) buffer).rewind();
final CharBuffer data = CharBuffer.allocate(buffer.capacity());
CharsetDecoder decoder = UTF8.newDecoder();
CoderResult result = decoder.decode(buffer, data, true);
if (result.isError()) {
((Buffer) buffer).rewind();
((Buffer) data).clear();
LOGGER.log(Level.INFO, "File " + configFile.getAbsolutePath() + " is not utf-8 encoded, trying " + Charset.defaultCharset().displayName());
decoder = Charset.defaultCharset().newDecoder();
result = decoder.decode(buffer, data, true);
if (result.isError()) {
throw new InvalidConfigurationException("Invalid Characters in file " + configFile.getAbsolutePath());
} else {
decoder.flush(data);
}
} else {
decoder.flush(data);
}
final int end = data.position();
((Buffer) data).rewind();
super.loadFromString(data.subSequence(0, end).toString());
}
} catch (final IOException ex) {
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
} catch (final InvalidConfigurationException ex) {
final File broken = new File(configFile.getAbsolutePath() + ".broken." + System.currentTimeMillis());
configFile.renameTo(broken);
LOGGER.log(Level.SEVERE, "The file " + configFile.toString() + " is broken, it has been renamed to " + broken.toString(), ex.getCause());
}
}
public boolean legacyFileExists() {
return false;
}
public void convertLegacyFile() {
LOGGER.log(Level.SEVERE, "Unable to import legacy config file.");
}
public boolean altFileExists() {
return false;
}
public void convertAltFile() {
LOGGER.log(Level.SEVERE, "Unable to import alt config file.");
}
private void createFromTemplate() {
InputStream istr = null;
OutputStream ostr = null;
try {
istr = resourceClass.getResourceAsStream(templateName);
if (istr == null) {
LOGGER.log(Level.SEVERE, tl("couldNotFindTemplate", templateName));
return;
}
ostr = new FileOutputStream(configFile);
final byte[] buffer = new byte[1024];
int length = 0;
length = istr.read(buffer);
while (length > 0) {
ostr.write(buffer, 0, length);
length = istr.read(buffer);
}
} catch (final IOException ex) {
LOGGER.log(Level.SEVERE, tl("failedToWriteConfig", configFile.toString()), ex);
} finally {
try {
if (istr != null) {
istr.close();
}
} catch (final IOException ex) {
Logger.getLogger(EssentialsConf.class.getName()).log(Level.SEVERE, null, ex);
}
try {
if (ostr != null) {
ostr.close();
}
} catch (final IOException ex) {
LOGGER.log(Level.SEVERE, tl("failedToCloseConfig", configFile.toString()), ex);
}
}
}
public void setTemplateName(final String templateName) {
this.templateName = templateName;
}
public File getFile() {
return configFile;
}
public void setTemplateName(final String templateName, final Class<?> resClass) {
this.templateName = templateName;
this.resourceClass = resClass;
}
public void startTransaction() {
transaction.set(true);
}
public void stopTransaction() {
transaction.set(false);
save();
}
public void save() {
try {
save(configFile);
} catch (final IOException ex) {
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
}
}
public void saveWithError() throws IOException {
save(configFile);
}
@Override
public synchronized void save(final File file) throws IOException {
if (!transaction.get()) {
delayedSave(file);
}
}
//This may be aborted if there are stagnant requests sitting in queue.
//This needs fixed to discard outstanding save requests.
public synchronized void forceSave() {
try {
final Future<?> future = delayedSave(configFile);
if (future != null) {
future.get();
}
} catch (final InterruptedException | ExecutionException ex) {
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
}
}
public synchronized void cleanup() {
forceSave();
}
private Future<?> delayedSave(final File file) {
if (file == null) {
throw new IllegalArgumentException("File cannot be null");
}
final String data = saveToString();
if (data.length() == 0) {
return null;
}
pendingDiskWrites.incrementAndGet();
return EXECUTOR_SERVICE.submit(new WriteRunner(configFile, data, pendingDiskWrites));
}
public boolean hasProperty(final String path) {
return isSet(path);
}
public Location getLocation(final String path, final Server server) throws InvalidWorldException {
final String worldString = (path == null ? "" : path + ".") + "world";
final String worldName = getString(worldString);
if (worldName == null || worldName.isEmpty()) {
return null;
}
final World world = server.getWorld(worldName);
if (world == null) {
throw new InvalidWorldException(worldName);
}
return new Location(world, getDouble((path == null ? "" : path + ".") + "x", 0), getDouble((path == null ? "" : path + ".") + "y", 0), getDouble((path == null ? "" : path + ".") + "z", 0), (float) getDouble((path == null ? "" : path + ".") + "yaw", 0), (float) getDouble((path == null ? "" : path + ".") + "pitch", 0));
}
public void setProperty(final String path, final Location loc) {
set((path == null ? "" : path + ".") + "world", loc.getWorld().getName());
set((path == null ? "" : path + ".") + "x", loc.getX());
set((path == null ? "" : path + ".") + "y", loc.getY());
set((path == null ? "" : path + ".") + "z", loc.getZ());
set((path == null ? "" : path + ".") + "yaw", loc.getYaw());
set((path == null ? "" : path + ".") + "pitch", loc.getPitch());
}
@Override
public ItemStack getItemStack(final String path) {
final ItemStack stack = new ItemStack(Material.valueOf(getString(path + ".type", "AIR")), getInt(path + ".amount", 1), (short) getInt(path + ".damage", 0));
final ConfigurationSection enchants = getConfigurationSection(path + ".enchant");
if (enchants != null) {
for (final String enchant : enchants.getKeys(false)) {
final Enchantment enchantment = Enchantment.getByName(enchant.toUpperCase(Locale.ENGLISH));
if (enchantment == null) {
continue;
}
final int level = getInt(path + ".enchant." + enchant, enchantment.getStartLevel());
stack.addUnsafeEnchantment(enchantment, level);
}
}
return stack;
/*
* ,
* (byte)getInt(path + ".data", 0)
*/
}
public void setProperty(final String path, final ItemStack stack) {
final Map<String, Object> map = new HashMap<>();
map.put("type", stack.getType().toString());
map.put("amount", stack.getAmount());
map.put("damage", stack.getDurability());
final Map<Enchantment, Integer> enchantments = stack.getEnchantments();
if (!enchantments.isEmpty()) {
final Map<String, Integer> enchant = new HashMap<>();
for (final Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
enchant.put(entry.getKey().getName().toLowerCase(Locale.ENGLISH), entry.getValue());
}
map.put("enchant", enchant);
}
// getData().getData() is broken
//map.put("data", stack.getDurability());
set(path, map);
}
public void setProperty(final String path, final List object) {
set(path, new ArrayList(object));
}
public void setProperty(final String path, final Map object) {
set(path, new LinkedHashMap(object));
}
public Object getProperty(final String path) {
return get(path);
}
public void setProperty(final String path, final BigDecimal bigDecimal) {
set(path, bigDecimal.toString());
}
public void setProperty(final String path, final Object object) {
set(path, object);
}
public void removeProperty(final String path) {
set(path, null);
}
@Override
public synchronized Object get(final String path) {
return super.get(path);
}
@Override
public synchronized Object get(final String path, final Object def) {
return super.get(path, def);
}
public synchronized BigDecimal getBigDecimal(final String path, final BigDecimal def) {
final String input = super.getString(path);
return toBigDecimal(input, def);
}
@Override
public synchronized boolean getBoolean(final String path) {
return super.getBoolean(path);
}
@Override
public synchronized boolean getBoolean(final String path, final boolean def) {
return super.getBoolean(path, def);
}
@Override
public synchronized List<Boolean> getBooleanList(final String path) {
return super.getBooleanList(path);
}
@Override
public synchronized List<Byte> getByteList(final String path) {
return super.getByteList(path);
}
@Override
public synchronized List<Character> getCharacterList(final String path) {
return super.getCharacterList(path);
}
@Override
public synchronized ConfigurationSection getConfigurationSection(final String path) {
return super.getConfigurationSection(path);
}
@Override
public synchronized double getDouble(final String path) {
return super.getDouble(path);
}
@Override
public synchronized double getDouble(final String path, final double def) {
return super.getDouble(path, def);
}
@Override
public synchronized List<Double> getDoubleList(final String path) {
return super.getDoubleList(path);
}
@Override
public synchronized List<Float> getFloatList(final String path) {
return super.getFloatList(path);
}
@Override
public synchronized int getInt(final String path) {
return super.getInt(path);
}
@Override
public synchronized int getInt(final String path, final int def) {
return super.getInt(path, def);
}
@Override
public synchronized List<Integer> getIntegerList(final String path) {
return super.getIntegerList(path);
}
@Override
public synchronized ItemStack getItemStack(final String path, final ItemStack def) {
return super.getItemStack(path, def);
}
@Override
public synchronized Set<String> getKeys(final boolean deep) {
return super.getKeys(deep);
}
@Override
public synchronized List<?> getList(final String path) {
return super.getList(path);
}
@Override
public synchronized List<?> getList(final String path, final List<?> def) {
return super.getList(path, def);
}
@Override
public synchronized long getLong(final String path) {
return super.getLong(path);
}
@Override
public synchronized long getLong(final String path, final long def) {
return super.getLong(path, def);
}
@Override
public synchronized List<Long> getLongList(final String path) {
return super.getLongList(path);
}
public synchronized Map<String, Object> getMap() {
return map;
}
@Override
public synchronized List<Map<?, ?>> getMapList(final String path) {
return super.getMapList(path);
}
@Override
public synchronized OfflinePlayer getOfflinePlayer(final String path) {
return super.getOfflinePlayer(path);
}
@Override
public synchronized OfflinePlayer getOfflinePlayer(final String path, final OfflinePlayer def) {
return super.getOfflinePlayer(path, def);
}
@Override
public synchronized List<Short> getShortList(final String path) {
return super.getShortList(path);
}
@Override
public synchronized String getString(final String path) {
return super.getString(path);
}
@Override
public synchronized String getString(final String path, final String def) {
return super.getString(path, def);
}
@Override
public synchronized List<String> getStringList(final String path) {
return super.getStringList(path);
}
@Override
public synchronized Map<String, Object> getValues(final boolean deep) {
return super.getValues(deep);
}
@Override
public synchronized Vector getVector(final String path) {
return super.getVector(path);
}
@Override
public synchronized Vector getVector(final String path, final Vector def) {
return super.getVector(path, def);
}
@Override
public synchronized boolean isBoolean(final String path) {
return super.isBoolean(path);
}
@Override
public synchronized boolean isConfigurationSection(final String path) {
return super.isConfigurationSection(path);
}
@Override
public synchronized boolean isDouble(final String path) {
return super.isDouble(path);
}
@Override
public synchronized boolean isInt(final String path) {
return super.isInt(path);
}
@Override
public synchronized boolean isItemStack(final String path) {
return super.isItemStack(path);
}
@Override
public synchronized boolean isList(final String path) {
return super.isList(path);
}
@Override
public synchronized boolean isLong(final String path) {
return super.isLong(path);
}
@Override
public synchronized boolean isOfflinePlayer(final String path) {
return super.isOfflinePlayer(path);
}
@Override
public synchronized boolean isSet(final String path) {
return super.isSet(path);
}
@Override
public synchronized boolean isString(final String path) {
return super.isString(path);
}
@Override
public synchronized boolean isVector(final String path) {
return super.isVector(path);
}
@Override
public synchronized void set(final String path, final Object value) {
super.set(path, value);
}
private static final class WriteRunner implements Runnable {
private final File configFile;
private final String data;
private final AtomicInteger pendingDiskWrites;
private WriteRunner(final File configFile, final String data, final AtomicInteger pendingDiskWrites) {
this.configFile = configFile;
this.data = data;
this.pendingDiskWrites = pendingDiskWrites;
}
@Override
public void run() {
//long startTime = System.nanoTime();
synchronized (configFile) {
if (pendingDiskWrites.get() > 1) {
// Writes can be skipped, because they are stored in a queue (in the executor).
// Only the last is actually written.
pendingDiskWrites.decrementAndGet();
//LOGGER.log(Level.INFO, configFile + " skipped writing in " + (System.nanoTime() - startTime) + " nsec.");
return;
}
try {
Files.createParentDirs(configFile);
if (!configFile.exists()) {
try {
LOGGER.log(Level.INFO, tl("creatingEmptyConfig", configFile.toString()));
if (!configFile.createNewFile()) {
LOGGER.log(Level.SEVERE, tl("failedToCreateConfig", configFile.toString()));
return;
}
} catch (final IOException ex) {
LOGGER.log(Level.SEVERE, tl("failedToCreateConfig", configFile.toString()), ex);
return;
}
}
try (final FileOutputStream fos = new FileOutputStream(configFile)) {
try (final OutputStreamWriter writer = new OutputStreamWriter(fos, UTF8)) {
writer.write(data);
}
}
} catch (final IOException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
} finally {
//LOGGER.log(Level.INFO, configFile + " written to disk in " + (System.nanoTime() - startTime) + " nsec.");
pendingDiskWrites.decrementAndGet();
}
}
}
}
}
@@ -1,5 +1,6 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
import org.bukkit.Location;
@@ -29,13 +30,11 @@ import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
public class EssentialsEntityListener implements Listener {
private static final Logger LOGGER = Logger.getLogger("Essentials");
private static final transient Pattern powertoolPlayer = Pattern.compile("\\{player\\}");
private final IEssentials ess;
@@ -109,7 +108,7 @@ public class EssentialsEntityListener implements Listener {
@Override
public void run() {
attacker.getBase().chat("/" + command);
LOGGER.log(Level.INFO, String.format("[PT] %s issued server command: /%s", attacker.getName(), command));
ess.getLogger().log(Level.INFO, String.format("[PT] %s issued server command: /%s", attacker.getName(), command));
}
}
@@ -198,7 +197,7 @@ public class EssentialsEntityListener implements Listener {
final ISettings.KeepInvPolicy bind = ess.getSettings().getBindingItemsPolicy();
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_11_2_R01) && (vanish != ISettings.KeepInvPolicy.KEEP || bind != ISettings.KeepInvPolicy.KEEP)) {
for (final ItemStack stack : event.getEntity().getInventory()) {
if (stack != null) {
if (stack != null && !MaterialUtil.isAir(stack.getType())) {
if (stack.getEnchantments().containsKey(Enchantment.VANISHING_CURSE)) {
if (vanish == ISettings.KeepInvPolicy.DELETE) {
event.getEntity().getInventory().remove(stack);
@@ -217,10 +216,12 @@ public class EssentialsEntityListener implements Listener {
}
}
}
// Now check armor
final ItemStack[] armor = event.getEntity().getInventory().getArmorContents();
for (int i = 0; i < armor.length; i++) {
final ItemStack stack = armor[i];
if (stack != null) {
if (stack != null && !MaterialUtil.isAir(stack.getType())) {
if (stack.getEnchantments().containsKey(Enchantment.VANISHING_CURSE)) {
if (vanish == ISettings.KeepInvPolicy.DELETE) {
armor[i] = null;
@@ -244,6 +245,24 @@ public class EssentialsEntityListener implements Listener {
}
}
event.getEntity().getInventory().setArmorContents(armor);
// Now check offhand
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01)) {
final ItemStack stack = event.getEntity().getInventory().getItemInOffHand();
//noinspection ConstantConditions
if (stack != null && !MaterialUtil.isAir(stack.getType())) {
final boolean isVanish = stack.getEnchantments().containsKey(Enchantment.VANISHING_CURSE);
final boolean isBind = stack.getEnchantments().containsKey(Enchantment.BINDING_CURSE);
if (isVanish || isBind) {
event.getEntity().getInventory().setItemInOffHand(null);
if ((isVanish && vanish == ISettings.KeepInvPolicy.DROP) || (isBind && bind == ISettings.KeepInvPolicy.DROP)) {
if (!event.getDrops().contains(stack)) {
event.getDrops().add(stack);
}
}
}
}
}
}
}
}
@@ -0,0 +1,74 @@
package com.earth2me.essentials;
import net.ess3.nms.refl.ReflUtil;
import net.ess3.provider.LoggerProvider;
import net.ess3.provider.providers.BaseLoggerProvider;
import net.ess3.provider.providers.PaperLoggerProvider;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public final class EssentialsLogger {
private final static Map<String, LoggerProvider> loggerProviders = new HashMap<>();
private final static MethodHandle loggerFieldHandle;
static {
try {
final Field loggerField = ReflUtil.getFieldCached(JavaPlugin.class, "logger");
//noinspection ConstantConditions
loggerFieldHandle = MethodHandles.lookup().unreflectSetter(loggerField);
} catch (Throwable t) {
throw new RuntimeException("Failed to get logger field handle", t);
}
}
private EssentialsLogger() {
}
public static LoggerProvider getLoggerProvider(final Plugin plugin) {
if (loggerProviders.containsKey(plugin.getName())) {
return loggerProviders.get(plugin.getName());
}
final Logger parentLogger = Logger.getLogger(plugin.getName());
final LoggerProvider provider;
if (ReflUtil.getClassCached("io.papermc.paper.adventure.providers.ComponentLoggerProviderImpl") != null) {
provider = new PaperLoggerProvider(plugin);
provider.setParent(parentLogger);
} else {
provider = new BaseLoggerProvider(plugin, parentLogger);
provider.setParent(parentLogger);
}
loggerProviders.put(plugin.getName(), provider);
return provider;
}
public static void updatePluginLogger(final Plugin plugin) {
final LoggerProvider provider = getLoggerProvider(plugin);
try {
loggerFieldHandle.invoke(plugin, provider);
} catch (Throwable e) {
provider.log(Level.SEVERE, "Failed to update " + plugin.getName() + " logger", e);
}
}
public static LoggerProvider getLoggerProvider(final String pluginName) {
if (loggerProviders.containsKey(pluginName)) {
return loggerProviders.get(pluginName);
}
final Plugin plugin = Bukkit.getPluginManager().getPlugin(pluginName);
if (plugin == null) {
throw new IllegalArgumentException("Plugin not found: " + pluginName);
}
return getLoggerProvider(plugin);
}
}
@@ -13,6 +13,9 @@ import com.earth2me.essentials.utils.VersionUtil;
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.providers.BukkitCommandSendListenerProvider;
import net.ess3.provider.providers.PaperCommandSendListenerProvider;
import net.essentialsx.api.v2.events.AsyncUserDataLoadEvent;
import org.bukkit.BanEntry;
import org.bukkit.BanList;
@@ -37,7 +40,6 @@ import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerCommandSendEvent;
import org.bukkit.event.player.PlayerEggThrowEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerInteractEvent;
@@ -68,14 +70,13 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
public class EssentialsPlayerListener implements Listener, FakeAccessor {
private static final Logger LOGGER = Logger.getLogger("Essentials");
private final transient IEssentials ess;
private final ConcurrentHashMap<UUID, Integer> pendingMotdTasks = new ConcurrentHashMap<>();
@@ -101,6 +102,15 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
}
}
private static boolean isPaperCommandSendEvent() {
try {
Class.forName("com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent");
return true;
} catch (final ClassNotFoundException ignored) {
return false;
}
}
private static boolean isArrowPickupEvent() {
try {
Class.forName("org.bukkit.event.player.PlayerPickupArrowEvent");
@@ -123,8 +133,10 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
ess.getServer().getPluginManager().registerEvents(new PickupListenerPre1_12(), ess);
}
if (isCommandSendEvent()) {
ess.getServer().getPluginManager().registerEvents(new CommandSendListener(), ess);
if (isPaperCommandSendEvent()) {
ess.getServer().getPluginManager().registerEvents(new PaperCommandSendListenerProvider(new CommandSendFilter()), ess);
} else if (isCommandSendEvent()) {
ess.getServer().getPluginManager().registerEvents(new BukkitCommandSendListenerProvider(new CommandSendFilter()), ess);
}
}
@@ -152,7 +164,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
user.sendMessage(user.hasMuteReason() ? tl("voiceSilencedReasonTime", dateDiff, user.getMuteReason()) : tl("voiceSilencedTime", dateDiff));
}
LOGGER.info(tl("mutedUserSpeaks", user.getName(), event.getMessage()));
ess.getLogger().info(tl("mutedUserSpeaks", user.getName(), event.getMessage()));
}
try {
final Iterator<Player> it = event.getRecipients().iterator();
@@ -184,7 +196,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
event.getHandlers().unregister(this);
if (ess.getSettings().isDebug()) {
LOGGER.log(Level.INFO, "Unregistering move listener");
ess.getLogger().log(Level.INFO, "Unregistering move listener");
}
return;
@@ -203,7 +215,11 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
to.setY(from.getY());
to.setZ(from.getZ());
try {
event.setTo(LocationUtil.getSafeDestination(to));
if (event.getPlayer().getAllowFlight()) {
// Don't teleport to a safe location here, they are either a god or flying
throw new Exception();
}
event.setTo(LocationUtil.getSafeDestination(ess, to));
} catch (final Exception ex) {
event.setTo(to);
}
@@ -244,6 +260,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
user.setGodModeEnabled(false);
}
if (user.isVanished()) {
user.setLeavingHidden(true);
user.setVanished(false);
}
user.setLogoutLocation();
@@ -318,6 +335,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
user.setLastLogin(currentTime);
user.setDisplayNick();
updateCompass(user);
user.setLeavingHidden(false);
// Check for new username. If they don't want the message, let's just say it's false.
final boolean newUsername = ess.getSettings().isCustomNewUsernameMessage() && lastAccountName != null && !lastAccountName.equals(user.getBase().getName());
@@ -398,7 +416,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
if (user.isAuthorized("essentials.fly.safelogin")) {
user.getBase().setFallDistance(0);
if (LocationUtil.shouldFly(user.getLocation())) {
if (LocationUtil.shouldFly(ess, user.getLocation())) {
user.getBase().setAllowFlight(true);
user.getBase().setFlying(true);
if (ess.getSettings().isSendFlyEnableOnJoin()) {
@@ -446,9 +464,9 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
tempInput = new TextInput(user.getSource(), "motd", true, ess);
} catch (final IOException ex) {
if (ess.getSettings().isDebug()) {
LOGGER.log(Level.WARNING, ex.getMessage(), ex);
ess.getLogger().log(Level.WARNING, ex.getMessage(), ex);
} else {
LOGGER.log(Level.WARNING, ex.getMessage());
ess.getLogger().log(Level.WARNING, ex.getMessage());
}
}
}
@@ -521,21 +539,16 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerTeleport(final PlayerTeleportEvent event) {
final boolean backListener = ess.getSettings().registerBackInListener();
final boolean teleportInvulnerability = ess.getSettings().isTeleportInvulnerability();
if (backListener || teleportInvulnerability) {
final Player player = event.getPlayer();
if (player.hasMetadata("NPC")) {
return;
}
final User user = ess.getUser(player);
//There is TeleportCause.COMMMAND but plugins have to actively pass the cause in on their teleports.
if (user.isAuthorized("essentials.back.onteleport") && backListener && (event.getCause() == TeleportCause.PLUGIN || event.getCause() == TeleportCause.COMMAND)) {
user.setLastLocation();
}
if (teleportInvulnerability && (event.getCause() == TeleportCause.PLUGIN || event.getCause() == TeleportCause.COMMAND)) {
user.enableInvulnerabilityAfterTeleport();
}
final Player player = event.getPlayer();
if (player.hasMetadata("NPC") || !(event.getCause() == TeleportCause.PLUGIN || event.getCause() == TeleportCause.COMMAND)) {
return;
}
final User user = ess.getUser(player);
if (ess.getSettings().registerBackInListener() && user.isAuthorized("essentials.back.onteleport")) {
user.setLastLocation();
}
if (ess.getSettings().isTeleportInvulnerability()) {
user.enableInvulnerabilityAfterTeleport();
}
}
@@ -613,7 +626,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
} else {
player.sendMessage(user.hasMuteReason() ? tl("voiceSilencedReasonTime", dateDiff, user.getMuteReason()) : tl("voiceSilencedTime", dateDiff));
}
LOGGER.info(tl("mutedUserSpeaks", player.getName(), event.getMessage()));
ess.getLogger().info(tl("mutedUserSpeaks", player.getName(), event.getMessage()));
return;
}
@@ -738,6 +751,9 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
switch (event.getAction()) {
case RIGHT_CLICK_BLOCK:
if (!event.isCancelled() && MaterialUtil.isBed(event.getClickedBlock().getType()) && ess.getSettings().getUpdateBedAtDaytime()) {
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_13_2_R01) && ((org.bukkit.block.data.type.Bed) event.getClickedBlock().getBlockData()).isOccupied()) {
break;
}
final User player = ess.getUser(event.getPlayer());
if (player.isAuthorized("essentials.sethome.bed") && player.getWorld().getEnvironment().equals(World.Environment.NORMAL)) {
player.getBase().setBedSpawnLocation(event.getClickedBlock().getLocation());
@@ -798,7 +814,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
ess.scheduleSyncDelayedTask(new DelayedClickJumpTask());
} catch (final Exception ex) {
if (ess.getSettings().isDebug()) {
LOGGER.log(Level.WARNING, ex.getMessage(), ex);
ess.getLogger().log(Level.WARNING, ex.getMessage(), ex);
}
}
}
@@ -822,7 +838,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
@Override
public void run() {
user.getBase().chat("/" + command);
LOGGER.log(Level.INFO, String.format("[PT] %s issued server command: /%s", user.getName(), command));
ess.getLogger().log(Level.INFO, String.format("[PT] %s issued server command: /%s", user.getName(), command));
}
}
@@ -972,15 +988,14 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
}
}
private final class CommandSendListener implements Listener {
@EventHandler(priority = EventPriority.NORMAL)
public void onCommandSend(final PlayerCommandSendEvent event) {
final User user = ess.getUser(event.getPlayer());
private final class CommandSendFilter implements CommandSendListenerProvider.Filter {
@Override
public Predicate<String> apply(Player player) {
final User user = ess.getUser(player);
final Set<PluginCommand> checked = new HashSet<>();
final Set<PluginCommand> toRemove = new HashSet<>();
event.getCommands().removeIf(label -> {
return label -> {
if (isEssentialsCommand(label)) {
final PluginCommand command = ess.getServer().getPluginCommand(label);
if (!checked.contains(command)) {
@@ -992,25 +1007,21 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
return toRemove.contains(command);
}
return false;
});
if (ess.getSettings().isDebug()) {
ess.getLogger().info("Removed commands: " + toRemove.toString());
}
};
}
/**
* Returns true if all of the following are true:
* - The command is a plugin command
* - The plugin command is from a plugin in an essentials-controlled package
* - The plugin command is from an official EssentialsX plugin or addon
* - There is no known alternative OR the alternative is overridden by Essentials
*/
private boolean isEssentialsCommand(final String label) {
final PluginCommand command = ess.getServer().getPluginCommand(label);
return command != null
&& (command.getPlugin() == ess || command.getPlugin().getClass().getName().startsWith("com.earth2me.essentials"))
&& (ess.getSettings().isCommandOverridden(label) || (ess.getAlternativeCommandsHandler().getAlternative(label) == null));
&& (command.getPlugin() == ess || command.getPlugin().getClass().getName().startsWith("com.earth2me.essentials") || command.getPlugin().getClass().getName().startsWith("net.essentialsx"))
&& (ess.getSettings().isCommandOverridden(label) || (ess.getAlternativeCommandsHandler().getAlternative(label) == null));
}
}
@@ -47,14 +47,12 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
public class EssentialsUpgrade {
private final static Logger LOGGER = Logger.getLogger("Essentials");
private static final FileFilter YML_FILTER = pathname -> pathname.isFile() && pathname.getName().endsWith(".yml");
private static final String PATTERN_CONFIG_UUID_REGEX = "(?mi)^uuid:\\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\s*$";
private static final Pattern PATTERN_CONFIG_UUID = Pattern.compile(PATTERN_CONFIG_UUID_REGEX);
@@ -186,13 +184,13 @@ public class EssentialsUpgrade {
config.blockingSave();
}
} catch (RuntimeException ex) {
LOGGER.log(Level.INFO, "File: " + file);
ess.getLogger().log(Level.INFO, "File: " + file);
throw ex;
}
}
doneFile.setProperty("updateUsersMailList", true);
doneFile.save();
LOGGER.info("Done converting mail list.");
ess.getLogger().info("Done converting mail list.");
}
public void convertStupidCamelCaseUserdataKeys() {
@@ -200,7 +198,7 @@ public class EssentialsUpgrade {
return;
}
LOGGER.info("Attempting to migrate legacy userdata keys to Configurate");
ess.getLogger().info("Attempting to migrate legacy userdata keys to Configurate");
final File userdataFolder = new File(ess.getDataFolder(), "userdata");
if (!userdataFolder.exists() || !userdataFolder.isDirectory()) {
@@ -241,13 +239,13 @@ public class EssentialsUpgrade {
}
config.blockingSave();
} catch (final RuntimeException ex) {
LOGGER.log(Level.INFO, "File: " + file);
ess.getLogger().log(Level.INFO, "File: " + file);
throw ex;
}
}
doneFile.setProperty("updateUsersStupidLegacyPathNames", true);
doneFile.save();
LOGGER.info("Done converting legacy userdata keys to Configurate.");
ess.getLogger().info("Done converting legacy userdata keys to Configurate.");
}
/**
@@ -290,31 +288,31 @@ public class EssentialsUpgrade {
}
final File backupFolder = new File(ess.getDataFolder(), "userdata-npc-backup");
if (backupFolder.exists()) {
LOGGER.info("NPC backup folder already exists; skipping NPC purge.");
LOGGER.info("To finish purging broken NPC accounts, rename the \"plugins/Essentials/userdata-npc-backup\" folder and restart your server.");
ess.getLogger().info("NPC backup folder already exists; skipping NPC purge.");
ess.getLogger().info("To finish purging broken NPC accounts, rename the \"plugins/Essentials/userdata-npc-backup\" folder and restart your server.");
return;
} else if (!backupFolder.mkdir()) {
LOGGER.info("Skipping NPC purge due to error creating backup folder.");
ess.getLogger().info("Skipping NPC purge due to error creating backup folder.");
return;
}
LOGGER.info("#===========================================================================#");
LOGGER.info(" EssentialsX will now purge any NPC accounts which were incorrectly created.");
LOGGER.info(" Only NPC accounts with the default starting balance will be deleted. If");
LOGGER.info(" they turn out to be valid NPC accounts, they will be re-created as needed.");
LOGGER.info(" Any files deleted here will be backed up to the ");
LOGGER.info(" \"plugins/Essentials/userdata-npc-backup\" folder. If you notice any files");
LOGGER.info(" have been purged incorrectly, you should restore it from the backup and");
LOGGER.info(" report it to us on GitHub:");
LOGGER.info(" https://github.com/EssentialsX/Essentials/issues/new/choose");
LOGGER.info("");
LOGGER.info(" NOTE: This is a one-time process and will take several minutes if you have");
LOGGER.info(" a lot of userdata files! If you interrupt this process, EssentialsX will");
LOGGER.info(" skip the process until you rename or remove the backup folder.");
LOGGER.info("#===========================================================================#");
ess.getLogger().info("#===========================================================================#");
ess.getLogger().info(" EssentialsX will now purge any NPC accounts which were incorrectly created.");
ess.getLogger().info(" Only NPC accounts with the default starting balance will be deleted. If");
ess.getLogger().info(" they turn out to be valid NPC accounts, they will be re-created as needed.");
ess.getLogger().info(" Any files deleted here will be backed up to the ");
ess.getLogger().info(" \"plugins/Essentials/userdata-npc-backup\" folder. If you notice any files");
ess.getLogger().info(" have been purged incorrectly, you should restore it from the backup and");
ess.getLogger().info(" report it to us on GitHub:");
ess.getLogger().info(" https://github.com/EssentialsX/Essentials/issues/new/choose");
ess.getLogger().info("");
ess.getLogger().info(" NOTE: This is a one-time process and will take several minutes if you have");
ess.getLogger().info(" a lot of userdata files! If you interrupt this process, EssentialsX will");
ess.getLogger().info(" skip the process until you rename or remove the backup folder.");
ess.getLogger().info("#===========================================================================#");
final int totalUserFiles = userFiles.length;
LOGGER.info("Found ~" + totalUserFiles + " files under \"plugins/Essentials/userdata\"...");
ess.getLogger().info("Found ~" + totalUserFiles + " files under \"plugins/Essentials/userdata\"...");
final AtomicInteger movedAccounts = new AtomicInteger(0);
final AtomicInteger totalAccounts = new AtomicInteger(0);
@@ -324,7 +322,7 @@ public class EssentialsUpgrade {
final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
final ScheduledFuture<?> feedbackTask = executor.scheduleWithFixedDelay(
() -> LOGGER.info("Scanned " + totalAccounts.get() + "/" + totalUserFiles + " accounts; moved " + movedAccounts.get() + " accounts"),
() -> ess.getLogger().info("Scanned " + totalAccounts.get() + "/" + totalUserFiles + " accounts; moved " + movedAccounts.get() + " accounts"),
5, feedbackInterval, TimeUnit.SECONDS);
for (final File file : userFiles) {
@@ -358,10 +356,10 @@ public class EssentialsUpgrade {
Files.move(file, new File(backupFolder, file.getName()));
movedAccounts.incrementAndGet();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Error while moving NPC file", e);
ess.getLogger().log(Level.SEVERE, "Error while moving NPC file", e);
}
} catch (final RuntimeException ex) {
LOGGER.log(Level.INFO, "File: " + file);
ess.getLogger().log(Level.INFO, "File: " + file);
feedbackTask.cancel(false);
executor.shutdown();
throw ex;
@@ -372,18 +370,18 @@ public class EssentialsUpgrade {
doneFile.setProperty("updatePurgeBrokenNpcAccounts", true);
doneFile.save();
LOGGER.info("#===========================================================================#");
LOGGER.info(" EssentialsX has finished purging NPC accounts.");
LOGGER.info("");
LOGGER.info(" Deleted accounts: " + movedAccounts);
LOGGER.info(" Total accounts processed: " + totalAccounts);
LOGGER.info("");
LOGGER.info(" Purged accounts have been backed up to");
LOGGER.info(" \"plugins/Essentials/userdata-npc-backup\", and can be restored from there");
LOGGER.info(" if needed. Please report any files which have been incorrectly deleted");
LOGGER.info(" to us on GitHub:");
LOGGER.info(" https://github.com/EssentialsX/Essentials/issues/new/choose");
LOGGER.info("#===========================================================================#");
ess.getLogger().info("#===========================================================================#");
ess.getLogger().info(" EssentialsX has finished purging NPC accounts.");
ess.getLogger().info("");
ess.getLogger().info(" Deleted accounts: " + movedAccounts);
ess.getLogger().info(" Total accounts processed: " + totalAccounts);
ess.getLogger().info("");
ess.getLogger().info(" Purged accounts have been backed up to");
ess.getLogger().info(" \"plugins/Essentials/userdata-npc-backup\", and can be restored from there");
ess.getLogger().info(" if needed. Please report any files which have been incorrectly deleted");
ess.getLogger().info(" to us on GitHub:");
ess.getLogger().info(" https://github.com/EssentialsX/Essentials/issues/new/choose");
ess.getLogger().info("#===========================================================================#");
}
public void convertIgnoreList() {
@@ -392,7 +390,7 @@ public class EssentialsUpgrade {
return;
}
LOGGER.info("Attempting to migrate ignore list to UUIDs");
ess.getLogger().info("Attempting to migrate ignore list to UUIDs");
final File userdataFolder = new File(ess.getDataFolder(), "userdata");
if (!userdataFolder.exists() || !userdataFolder.isDirectory()) {
@@ -414,7 +412,7 @@ public class EssentialsUpgrade {
continue;
}
if (pattern.matcher(name.trim()).matches()) {
LOGGER.info("Detected already migrated ignore list!");
ess.getLogger().info("Detected already migrated ignore list!");
return;
}
final User user = ess.getOfflineUser(name);
@@ -427,41 +425,41 @@ public class EssentialsUpgrade {
config.blockingSave();
}
} catch (final RuntimeException ex) {
LOGGER.log(Level.INFO, "File: " + file);
ess.getLogger().log(Level.INFO, "File: " + file);
throw ex;
}
}
doneFile.setProperty("updateUsersIgnoreListUUID", true);
doneFile.save();
LOGGER.info("Done converting ignore list.");
ess.getLogger().info("Done converting ignore list.");
}
public void convertKits() {
final Kits kits = ess.getKits();
final EssentialsConfiguration config = kits.getConfig();
final EssentialsConfiguration config = kits.getRootConfig();
if (doneFile.getBoolean("kitsyml", false)) {
return;
}
LOGGER.info("Attempting to convert old kits in config.yml to new kits.yml");
ess.getLogger().info("Attempting to convert old kits in config.yml to new kits.yml");
final CommentedConfigurationNode section = ess.getSettings().getKitSection();
if (section == null) {
LOGGER.info("No kits found to migrate.");
ess.getLogger().info("No kits found to migrate.");
return;
}
final Map<String, Object> legacyKits = ConfigurateUtil.getRawMap(section);
for (final Map.Entry<String, Object> entry : legacyKits.entrySet()) {
LOGGER.info("Converting " + entry.getKey());
ess.getLogger().info("Converting " + entry.getKey());
config.setRaw("kits." + entry.getKey(), entry.getValue());
}
config.save();
doneFile.setProperty("kitsyml", true);
doneFile.save();
LOGGER.info("Done converting kits.");
ess.getLogger().info("Done converting kits.");
}
private void moveMotdRulesToFile(final String name) {
@@ -494,7 +492,7 @@ public class EssentialsUpgrade {
doneFile.setProperty("move" + name + "ToFile", true);
doneFile.save();
} catch (final IOException e) {
LOGGER.log(Level.SEVERE, tl("upgradingFilesError"), e);
ess.getLogger().log(Level.SEVERE, tl("upgradingFilesError"), e);
}
}
@@ -572,7 +570,7 @@ public class EssentialsUpgrade {
config.blockingSave();
}
} catch (final RuntimeException ex) {
LOGGER.log(Level.INFO, "File: " + file);
ess.getLogger().log(Level.INFO, "File: " + file);
throw ex;
}
}
@@ -628,7 +626,7 @@ public class EssentialsUpgrade {
}
} catch (final RuntimeException ex) {
LOGGER.log(Level.INFO, "File: " + file);
ess.getLogger().log(Level.INFO, "File: " + file);
throw ex;
}
}
@@ -657,15 +655,15 @@ public class EssentialsUpgrade {
final File tmpFile = new File(listOfFile.getParentFile(), sanitizedFilename + ".tmp");
final File newFile = new File(listOfFile.getParentFile(), sanitizedFilename);
if (!listOfFile.renameTo(tmpFile)) {
LOGGER.log(Level.WARNING, tl("userdataMoveError", filename, sanitizedFilename));
ess.getLogger().log(Level.WARNING, tl("userdataMoveError", filename, sanitizedFilename));
continue;
}
if (newFile.exists()) {
LOGGER.log(Level.WARNING, tl("duplicatedUserdata", filename, sanitizedFilename));
ess.getLogger().log(Level.WARNING, tl("duplicatedUserdata", filename, sanitizedFilename));
continue;
}
if (!tmpFile.renameTo(newFile)) {
LOGGER.log(Level.WARNING, tl("userdataMoveBackError", sanitizedFilename, sanitizedFilename));
ess.getLogger().log(Level.WARNING, tl("userdataMoveBackError", sanitizedFilename, sanitizedFilename));
}
}
doneFile.setProperty("sanitizeAllUserFilenames", true);
@@ -722,7 +720,7 @@ public class EssentialsUpgrade {
doneFile.setProperty("deleteOldItemsCsv", true);
doneFile.save();
} catch (final IOException ex) {
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
ess.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
}
}
}
@@ -748,7 +746,7 @@ public class EssentialsUpgrade {
config.blockingSave();
}
} catch (final Exception ex) {
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
ess.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
}
}
doneFile.setProperty("updateSpawnsToNewSpawnsConfig", true);
@@ -776,7 +774,7 @@ public class EssentialsUpgrade {
config.blockingSave();
}
} catch (final Exception ex) {
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
ess.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
}
}
doneFile.setProperty("updateJailsToNewJailsConfig", true);
@@ -1,66 +0,0 @@
package com.earth2me.essentials;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import org.bukkit.Bukkit;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.UUID;
import java.util.logging.Level;
public class EssentialsUserConf extends EssentialsConf {
public String username;
public final UUID uuid;
public EssentialsUserConf(final String username, final UUID uuid, final File configFile) {
super(configFile);
this.username = username;
this.uuid = uuid;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public boolean legacyFileExists() {
final File file = new File(configFile.getParentFile(), username + ".yml");
return file.exists();
}
@Override
public void convertLegacyFile() {
final File file = new File(configFile.getParentFile(), username + ".yml");
try {
Files.move(file, new File(configFile.getParentFile(), uuid + ".yml"));
} catch (final IOException ex) {
Bukkit.getLogger().log(Level.WARNING, "Failed to migrate user: " + username, ex);
}
setProperty("lastAccountName", username);
}
private File getAltFile() {
final UUID fn = UUID.nameUUIDFromBytes(("OfflinePlayer:" + username.toLowerCase(Locale.ENGLISH)).getBytes(Charsets.UTF_8));
return new File(configFile.getParentFile(), fn.toString() + ".yml");
}
@Override
public boolean altFileExists() {
if (username.equals(username.toLowerCase())) {
return false;
}
return getAltFile().exists();
}
@Override
public void convertAltFile() {
try {
Files.move(getAltFile(), new File(configFile.getParentFile(), uuid + ".yml"));
} catch (final IOException ex) {
Bukkit.getLogger().log(Level.WARNING, "Failed to migrate user: " + username, ex);
}
}
}
@@ -21,7 +21,6 @@ import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
public class I18n implements net.ess3.api.II18n {
@@ -89,7 +88,7 @@ public class I18n implements net.ess3.api.II18n {
}
} catch (final MissingResourceException ex) {
if (ess == null || ess.getSettings().isDebug()) {
Logger.getLogger("Essentials").log(Level.WARNING, String.format("Missing translation key \"%s\" in translation file %s", ex.getKey(), localeBundle.getLocale().toString()), ex);
ess.getLogger().log(Level.WARNING, String.format("Missing translation key \"%s\" in translation file %s", ex.getKey(), localeBundle.getLocale().toString()), ex);
}
return defaultBundle.getString(string);
}
@@ -126,7 +125,7 @@ public class I18n implements net.ess3.api.II18n {
}
ResourceBundle.clearCache();
messageFormatCache = new HashMap<>();
Logger.getLogger("Essentials").log(Level.INFO, String.format("Using locale %s", currentLocale.toString()));
ess.getLogger().log(Level.INFO, String.format("Using locale %s", currentLocale.toString()));
try {
localeBundle = ResourceBundle.getBundle(MESSAGES, currentLocale, new UTF8PropertiesControl());
@@ -10,14 +10,17 @@ import com.earth2me.essentials.updatecheck.UpdateChecker;
import net.ess3.nms.refl.providers.ReflOnlineModeProvider;
import net.ess3.provider.ContainerProvider;
import net.ess3.provider.FormattedCommandAliasProvider;
import net.ess3.provider.ItemUnbreakableProvider;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.MaterialTagProvider;
import net.ess3.provider.PersistentDataProvider;
import net.ess3.provider.ServerStateProvider;
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.essentialsx.api.v2.services.BalanceTop;
import net.essentialsx.api.v2.services.mail.MailService;
import org.bukkit.Server;
@@ -159,5 +162,11 @@ public interface IEssentials extends Plugin {
ReflOnlineModeProvider getOnlineModeProvider();
ItemUnbreakableProvider getItemUnbreakableProvider();
WorldInfoProvider getWorldInfoProvider();
SignDataProvider getSignDataProvider();
PluginCommand getPluginCommand(String cmd);
}
@@ -46,6 +46,12 @@ public interface ISettings extends IConf {
char getChatQuestion();
boolean isShoutDefault();
boolean isPersistShout();
boolean isChatQuestionEnabled();
BigDecimal getCommandCost(IEssentialsCommand cmd);
BigDecimal getCommandCost(String label);
@@ -228,6 +234,8 @@ public interface ISettings extends IConf {
boolean isWorldHomePermissions();
int getMaxTreeCommandRange();
boolean registerBackInListener();
boolean getDisableItemPickupWhileAfk();
@@ -238,6 +246,8 @@ public interface ISettings extends IConf {
long getTpaAcceptCancellation();
int getTpaMaxRequests();
long getTeleportInvulnerability();
boolean isTeleportInvulnerability();
@@ -12,13 +12,16 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
/**
@@ -61,8 +64,11 @@ public interface IUser {
/**
* Returns whether this user has an outstanding teleport request to deal with.
*
* @deprecated The teleport request system has been moved into a multi-user teleport request queue.
* @see IUser#hasPendingTpaRequests(boolean, boolean)
* @return whether there is a teleport request
*/
@Deprecated
boolean hasOutstandingTeleportRequest();
/**
@@ -88,6 +94,15 @@ public interface IUser {
*/
boolean isHidden();
/**
* Whether the user was hidden before leaving the server.
*
* @return true if the user was hidden.
*/
boolean isLeavingHidden();
void setLeavingHidden(boolean leavingHidden);
void setHidden(boolean vanish);
boolean isGodModeEnabled();
@@ -98,6 +113,11 @@ public interface IUser {
boolean canBuild();
/**
* @deprecated The teleport request system has been moved into a multi-user teleport request queue.
* @see IUser#getNextTpaRequest(boolean, boolean, boolean)
*/
@Deprecated
long getTeleportRequestTime();
void enableInvulnerabilityAfterTeleport();
@@ -205,6 +225,8 @@ public interface IUser {
String getName();
UUID getUUID();
String getDisplayName();
String getFormattedNickname();
@@ -238,4 +260,74 @@ public interface IUser {
void setToggleShout(boolean toggleShout);
boolean isToggleShout();
/**
* Gets information about the most-recently-made, non-expired TPA request in the tpa queue of this {@link IUser}.
* <p>
* The TPA Queue is Last-In-First-Out queue which stores all the active pending teleport
* requests of this {@link IUser}. Timeout calculations are also done during the
* iteration process of this method, ensuring that teleport requests made past the timeout
* period are removed from queue and therefore not returned here. The maximum size of this
* queue is determined by {@link ISettings#getTpaMaxRequests()}.
*
* @param inform true if the underlying {@link IUser} should be informed if a request expires during iteration.
* @param ignoreExpirations true if this method should not process expirations for the entire queue and stop execution on the first unexpired request.
* @param excludeHere true if /tphere requests should be ignored in fetching the next tpa request.
* @return A {@link TpaRequest} corresponding to the next available request or null if no valid request is present.
*/
@Nullable TpaRequest getNextTpaRequest(boolean inform, boolean ignoreExpirations, boolean excludeHere);
/**
* Whether or not this {@link IUser} has any valid TPA requests in queue.
*
* @param inform true if the user should be informed if a request expires during iteration.
* @param excludeHere true if /tpahere requests should be ignored in checking if a tpa request is available.
* @return true if the user has an available pending request in queue.
*/
boolean hasPendingTpaRequests(boolean inform, boolean excludeHere);
class TpaRequest {
private final String name;
private final UUID requesterUuid;
private boolean here;
private Location location;
private long time;
public TpaRequest(String name, UUID requesterUuid) {
this.name = name;
this.requesterUuid = requesterUuid;
}
public String getName() {
return name;
}
public UUID getRequesterUuid() {
return requesterUuid;
}
public boolean isHere() {
return here;
}
public void setHere(boolean here) {
this.here = here;
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
}
}
@@ -34,12 +34,10 @@ import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
public class Jails implements net.ess3.api.IJails {
private static final transient Logger LOGGER = Logger.getLogger("Essentials");
private static transient boolean enabled = false;
private final IEssentials ess;
private final EssentialsConfiguration config;
@@ -76,7 +74,7 @@ public class Jails implements net.ess3.api.IJails {
final JailListener blockListener = new JailListener();
pluginManager.registerEvents(blockListener, ess);
if (ess.getSettings().isDebug()) {
LOGGER.log(Level.INFO, "Registering Jail listener");
ess.getLogger().log(Level.INFO, "Registering Jail listener");
}
}
@@ -268,9 +266,9 @@ public class Jails implements net.ess3.api.IJails {
event.setRespawnLocation(getJail(user.getJail()));
} catch (final Exception ex) {
if (ess.getSettings().isDebug()) {
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
} else {
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
}
}
}
@@ -286,9 +284,9 @@ public class Jails implements net.ess3.api.IJails {
event.setTo(getJail(user.getJail()));
} catch (final Exception ex) {
if (ess.getSettings().isDebug()) {
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
} else {
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
}
}
user.sendMessage(tl("jailMessage"));
@@ -306,9 +304,9 @@ public class Jails implements net.ess3.api.IJails {
final CompletableFuture<Boolean> future = new CompletableFuture<>();
future.exceptionally(ex -> {
if (ess.getSettings().isDebug()) {
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
} else {
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
}
return false;
});
@@ -4,84 +4,106 @@ import com.earth2me.essentials.config.ConfigurateUtil;
import com.earth2me.essentials.config.EssentialsConfiguration;
import com.earth2me.essentials.utils.NumberUtil;
import org.spongepowered.configurate.CommentedConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import java.io.File;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import static com.earth2me.essentials.I18n.capitalCase;
import static com.earth2me.essentials.I18n.tl;
public class Kits implements IConf {
private final EssentialsConfiguration config;
private CommentedConfigurationNode kits;
private final IEssentials ess;
private final EssentialsConfiguration rootConfig;
private final Map<String, EssentialsConfiguration> kitToConfigMap = new HashMap<>();
private final Map<String, Map<String, Object>> kitMap = new HashMap<>();
public Kits(final IEssentials essentials) {
config = new EssentialsConfiguration(new File(essentials.getDataFolder(), "kits.yml"), "/kits.yml");
this.ess = essentials;
this.rootConfig = new EssentialsConfiguration(new File(essentials.getDataFolder(), "kits.yml"), "/kits.yml");
reloadConfig();
}
@Override
public void reloadConfig() {
config.load();
kits = _getKits();
rootConfig.load();
parseKits();
}
public File getFile() {
return config.getFile();
return rootConfig.getFile();
}
private CommentedConfigurationNode _getKits() {
final CommentedConfigurationNode section = config.getSection("kits");
if (section != null) {
final CommentedConfigurationNode newSection = config.newSection();
for (final String kitItem : ConfigurateUtil.getKeys(section)) {
final CommentedConfigurationNode kitSection = section.node(kitItem);
if (kitSection.isMap()) {
try {
newSection.node(kitItem.toLowerCase(Locale.ENGLISH)).set(kitSection);
} catch (SerializationException e) {
e.printStackTrace();
private void parseKit(final String kitName, final CommentedConfigurationNode kitSection, final EssentialsConfiguration parentConfig) {
if (kitSection.isMap()) {
final String effectiveKitName = kitName.toLowerCase(Locale.ENGLISH);
kitToConfigMap.put(effectiveKitName, parentConfig);
kitMap.put(effectiveKitName, ConfigurateUtil.getRawMap(kitSection));
}
}
private void parseKits() {
kitToConfigMap.clear();
kitMap.clear();
// Kits from kits.yml file
final CommentedConfigurationNode fileKits = rootConfig.getSection("kits");
if (fileKits != null) {
for (final Map.Entry<String, CommentedConfigurationNode> kitEntry : ConfigurateUtil.getMap(fileKits).entrySet()) {
parseKit(kitEntry.getKey(), kitEntry.getValue(), rootConfig);
}
}
// Kits from kits subdirectory
final File kitsFolder = new File(this.ess.getDataFolder(), "kits");
if (!kitsFolder.exists() || !kitsFolder.isDirectory()) {
return;
}
final File[] kitsFiles = kitsFolder.listFiles();
//noinspection ConstantConditions - will not be null, conditions checked above.
for (final File kitFile : kitsFiles) {
if (kitFile.getName().endsWith(".yml")) {
final EssentialsConfiguration kitConfig = new EssentialsConfiguration(kitFile);
kitConfig.load();
final CommentedConfigurationNode kits = kitConfig.getSection("kits");
if (kits != null) {
for (final Map.Entry<String, CommentedConfigurationNode> kitEntry : ConfigurateUtil.getMap(kits).entrySet()) {
parseKit(kitEntry.getKey(), kitEntry.getValue(), kitConfig);
}
}
}
return newSection;
}
return null;
}
public EssentialsConfiguration getConfig() {
return config;
/**
* Should be used for EssentialsUpgrade conversions <b>only</b>.
*/
public EssentialsConfiguration getRootConfig() {
return rootConfig;
}
public CommentedConfigurationNode getKits() {
return kits;
public Set<String> getKitKeys() {
return kitMap.keySet();
}
public Map<String, Object> getKit(String name) {
name = name.replace('.', '_').replace('/', '_');
if (getKits() != null) {
final CommentedConfigurationNode kits = getKits();
// Other parts of the codebase/3rd party plugins expect us to lowercase kit names here.
// This isn't strictly needed for the future of Essentials, but for compatibility it's here.
final CommentedConfigurationNode kitSection = kits.node(name.toLowerCase());
if (!kitSection.virtual() && kitSection.isMap()) {
return ConfigurateUtil.getRawMap(kitSection);
}
public Map<String, Object> getKit(final String name) {
if (name != null) {
return kitMap.get(name.replace('.', '_').replace('/', '_'));
}
return null;
}
// Tries to find an existing kit name that matches the given name, ignoring case. Returns null if no match.
public String matchKit(final String name) {
final CommentedConfigurationNode section = config.getSection("kits");
if (section != null) {
for (final String kitName : ConfigurateUtil.getKeys(section)) {
if (name != null) {
for (final String kitName : kitMap.keySet()) {
if (kitName.equalsIgnoreCase(name)) {
return kitName;
}
@@ -90,25 +112,32 @@ public class Kits implements IConf {
return null;
}
public void addKit(final String name, final List<String> lines, final long delay) {
public void addKit(String name, final List<String> lines, final long delay) {
name = name.replace('.', '_').replace('/', '_').toLowerCase(Locale.ENGLISH);
// Will overwrite but w/e
config.setProperty("kits." + name + ".delay", delay);
config.setProperty("kits." + name + ".items", lines);
kits = _getKits();
config.save();
rootConfig.setProperty("kits." + name + ".delay", delay);
rootConfig.setProperty("kits." + name + ".items", lines);
parseKits();
rootConfig.save();
}
public void removeKit(final String name) {
public void removeKit(String name) {
name = name.replace('.', '_').replace('/', '_').toLowerCase(Locale.ENGLISH);
if (!kitToConfigMap.containsKey(name) || !kitMap.containsKey(name)) {
return;
}
final EssentialsConfiguration config = kitToConfigMap.get(name);
config.removeProperty("kits." + name);
kits = _getKits();
config.save();
config.blockingSave();
parseKits();
}
public String listKits(final net.ess3.api.IEssentials ess, final User user) throws Exception {
try {
final CommentedConfigurationNode kits = config.getSection("kits");
final StringBuilder list = new StringBuilder();
for (final String kitItem : ConfigurateUtil.getKeys(kits)) {
for (final String kitItem : kitMap.keySet()) {
if (user == null) {
list.append(" ").append(capitalCase(kitItem));
} else if (user.isAuthorized("essentials.kits." + kitItem.toLowerCase(Locale.ENGLISH))) {
@@ -1,7 +1,6 @@
package com.earth2me.essentials;
import net.ess3.api.IEssentials;
import org.bukkit.Bukkit;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
@@ -38,7 +37,7 @@ public class ManagedFile {
throw new IOException("Could not delete file " + file.toString());
}
} catch (final IOException ex) {
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
Essentials.getWrappedLogger().log(Level.SEVERE, ex.getMessage(), ex);
}
}
@@ -46,7 +45,7 @@ public class ManagedFile {
try {
copyResourceAscii("/" + filename, file);
} catch (final IOException ex) {
Bukkit.getLogger().log(Level.SEVERE, tl("itemsCsvNotLoaded", filename), ex);
Essentials.getWrappedLogger().log(Level.SEVERE, tl("itemsCsvNotLoaded", filename), ex);
}
}
}
@@ -113,7 +112,7 @@ public class ManagedFile {
if (correct.equals(test)) {
return true;
} else {
Bukkit.getLogger().warning("File " + file.toString() + " has been modified by user and file version differs, please update the file manually.");
Essentials.getWrappedLogger().warning("File " + file.toString() + " has been modified by user and file version differs, please update the file manually.");
}
}
}
@@ -147,7 +146,7 @@ public class ManagedFile {
return lines;
}
} catch (final IOException ex) {
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
Essentials.getWrappedLogger().log(Level.SEVERE, ex.getMessage(), ex);
return Collections.emptyList();
}
}
@@ -7,9 +7,9 @@ import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.base.Joiner;
import net.ess3.api.IEssentials;
import net.ess3.nms.refl.ReflUtil;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.FireworkEffect;
@@ -33,7 +33,6 @@ import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -48,9 +47,6 @@ import static com.earth2me.essentials.I18n.tl;
public class MetaItemStack {
private static final Map<String, DyeColor> colorMap = new HashMap<>();
private static final Map<String, FireworkEffect.Type> fireworkShape = new HashMap<>();
private static int bukkitUnbreakableSupport = -1;
private static Method spigotMethod;
private static Method setUnbreakableMethod;
private static boolean useNewSkullMethod = true;
static {
@@ -212,9 +208,9 @@ public class MetaItemStack {
stack.setItemMeta(meta);
} else if (split[0].equalsIgnoreCase("unbreakable") && hasMetaPermission(sender, "unbreakable", false, true, ess)) {
final boolean value = split.length <= 1 || Boolean.parseBoolean(split[1]);
setUnbreakable(stack, value);
setUnbreakable(ess, stack, value);
} else if (split.length > 1 && (split[0].equalsIgnoreCase("player") || split[0].equalsIgnoreCase("owner")) && hasMetaPermission(sender, "head", false, true, ess)) {
if (MaterialUtil.isPlayerHead(stack.getType(), stack.getDurability())) {
if (MaterialUtil.isPlayerHead(stack)) {
final String owner = split[1];
setSkullOwner(ess, stack, owner);
} else {
@@ -529,14 +525,14 @@ public class MetaItemStack {
}
pmeta.addCustomEffect(pEffect, true);
stack.setItemMeta(pmeta);
if (ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_9_R1)) {
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01)) {
if (isSplashPotion && stack.getType() != Material.SPLASH_POTION) {
stack.setType(Material.SPLASH_POTION);
} else if (!isSplashPotion && stack.getType() != Material.POTION) {
stack.setType(Material.POTION);
}
} else {
final Potion potion = Potion.fromItemStack(stack);
final Potion potion = Potion.fromDamage(stack.getDurability());
potion.setSplash(isSplashPotion);
potion.apply(stack);
}
@@ -686,35 +682,9 @@ public class MetaItemStack {
}
}
private void setUnbreakable(final ItemStack is, final boolean unbreakable) {
private void setUnbreakable(final IEssentials ess, final ItemStack is, final boolean unbreakable) {
final ItemMeta meta = is.getItemMeta();
try {
if (bukkitUnbreakableSupport == -1) {
try {
ItemMeta.class.getDeclaredMethod("setUnbreakable", boolean.class);
bukkitUnbreakableSupport = 1;
} catch (final NoSuchMethodException | SecurityException ex) {
bukkitUnbreakableSupport = 0;
}
}
if (bukkitUnbreakableSupport == 1) {
meta.setUnbreakable(unbreakable);
} else {
if (spigotMethod == null) {
spigotMethod = meta.getClass().getDeclaredMethod("spigot");
spigotMethod.setAccessible(true);
}
final Object itemStackSpigot = spigotMethod.invoke(meta);
if (setUnbreakableMethod == null) {
setUnbreakableMethod = itemStackSpigot.getClass().getDeclaredMethod("setUnbreakable", Boolean.TYPE);
setUnbreakableMethod.setAccessible(true);
}
setUnbreakableMethod.invoke(itemStackSpigot, unbreakable);
}
is.setItemMeta(meta);
} catch (final Throwable t) {
t.printStackTrace();
}
ess.getItemUnbreakableProvider().setUnbreakable(meta, unbreakable);
is.setItemMeta(meta);
}
}
@@ -13,7 +13,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
@@ -105,9 +104,13 @@ public enum Mob {
AXOLOTL("Axolotl", Enemies.FRIENDLY, "AXOLOTL"),
GOAT("Goat", Enemies.NEUTRAL, "GOAT"),
GLOW_SQUID("GlowSquid", Enemies.FRIENDLY, "GLOW_SQUID"),
ALLAY("Allay", Enemies.FRIENDLY, "ALLAY"),
FROG("Frog", Enemies.FRIENDLY, "FROG"),
TADPOLE("Tadpole", Enemies.FRIENDLY, "TADPOLE"),
WARDEN("Warden", Enemies.ENEMY, "WARDEN"),
CHEST_BOAT("ChestBoat", Enemies.NEUTRAL, "CHEST_BOAT"),
;
public static final Logger logger = Logger.getLogger("Essentials");
private static final Map<String, Mob> hashMap = new HashMap<>();
private static final Map<EntityType, Mob> bukkitMap = new HashMap<>();
@@ -166,7 +169,7 @@ public enum Mob {
public Entity spawn(final World world, final Server server, final Location loc) throws MobException {
final Entity entity = world.spawn(loc, this.bukkitType.getEntityClass());
if (entity == null) {
logger.log(Level.WARNING, tl("unableToSpawnMob"));
Essentials.getWrappedLogger().log(Level.WARNING, tl("unableToSpawnMob"));
throw new MobException();
}
return entity;
@@ -3,10 +3,13 @@ package com.earth2me.essentials;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.nms.refl.ReflUtil;
import org.bukkit.TreeSpecies;
import org.bukkit.entity.Axolotl;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Fox;
import org.bukkit.entity.Frog;
import org.bukkit.entity.Llama;
import org.bukkit.entity.MushroomCow;
import org.bukkit.entity.Ocelot;
@@ -37,6 +40,7 @@ public final class MobCompat {
public static final EntityType PHANTOM = getEntityType("PHANTOM");
public static final EntityType AXOLOTL = getEntityType("AXOLOTL");
public static final EntityType GOAT = getEntityType("GOAT");
public static final EntityType FROG = getEntityType("FROG");
// Constants for mobs that have changed since earlier versions
public static final EntityType CAT = getEntityType("CAT", "OCELOT");
@@ -164,6 +168,33 @@ public final class MobCompat {
}
}
public static void setFrogVariant(final Entity entity, final String variant) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_19_R01)) {
return;
}
if (entity instanceof Frog) {
((Frog) entity).setVariant(Frog.Variant.valueOf(variant));
}
}
public static void setBoatVariant(final Entity entity, final BoatVariant variant) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
return;
}
final Boat boat;
if (entity instanceof Boat) {
boat = (Boat) entity;
} else {
return;
}
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_19_R01)) {
//noinspection deprecation
boat.setWoodType(TreeSpecies.valueOf(variant.getTreeSpecies()));
} else {
boat.setBoatType(Boat.Type.valueOf(variant.getBoatType()));
}
}
public enum CatType {
// These are (loosely) Mojang names for the cats
SIAMESE("SIAMESE", "SIAMESE_CAT"),
@@ -228,4 +259,34 @@ public final class MobCompat {
}
}
public enum BoatVariant {
// Mappings for TreeSpecies names
ACACIA("ACACIA", "ACACIA"),
BIRCH("BIRCH", "BIRCH"),
DARKOAK("DARK_OAK", "DARK_OAK"),
GENERIC("GENERIC", "OAK"),
JUNGLE("JUNGLE", "JUNGLE"),
REDWOOD("REDWOOD", "SPRUCE"),
// Mappings for Boat.Type names (falling back to GENERIC where undefined)
OAK("GENERIC", "OAK"),
SPRUCE("REDWOOD", "SPRUCE"),
MANGROVE("GENERIC", "MANGROVE"),
;
private final String treeSpecies;
private final String boatType;
BoatVariant(final String treeSpecies, final String boatType) {
this.treeSpecies = treeSpecies;
this.boatType = boatType;
}
public String getTreeSpecies() {
return treeSpecies;
}
public String getBoatType() {
return boatType;
}
}
}
@@ -7,6 +7,7 @@ import com.earth2me.essentials.utils.VersionUtil;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.Boat;
import org.bukkit.entity.ChestedHorse;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Entity;
@@ -35,7 +36,6 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import static com.earth2me.essentials.I18n.tl;
@@ -197,9 +197,20 @@ public enum MobData {
CYAN_AXOLOTL("cyan", MobCompat.AXOLOTL, "axolotl:CYAN", true),
BLUE_AXOLOTL("blue", MobCompat.AXOLOTL, "axolotl:BLUE", true),
SCREAMING_GOAT("screaming", MobCompat.GOAT, Data.GOAT_SCREAMING, true),
TEMPERATE_FROG("temperate", MobCompat.FROG, "frog:TEMPERATE", true),
WARM_FROG("warm", MobCompat.FROG, "frog:WARM", true),
COLD_FROG("cold", MobCompat.FROG, "frog:COLD", true),
ACACIA_BOAT("acacia", Boat.class, MobCompat.BoatVariant.ACACIA, true),
BIRCH_BOAT("birch", Boat.class, MobCompat.BoatVariant.BIRCH, true),
DARK_OAK_BOAT("darkoak", Boat.class, MobCompat.BoatVariant.DARKOAK, true),
GENERIC_BOAT("generic", Boat.class, MobCompat.BoatVariant.GENERIC, true),
JUNGLE_BOAT("jungle", Boat.class, MobCompat.BoatVariant.JUNGLE, true),
REDWOOD_BOAT("redwood", Boat.class, MobCompat.BoatVariant.REDWOOD, true),
MANGROVE_BOAT("mangrove", Boat.class, MobCompat.BoatVariant.MANGROVE, true),
OAK_BOAT("oak", Boat.class, MobCompat.BoatVariant.OAK, true),
SPRUCE_BOAT("spruce", Boat.class, MobCompat.BoatVariant.SPRUCE, true),
;
public static final Logger logger = Logger.getLogger("Essentials");
final private String nickname;
final private List<String> suggestions;
final private Object type;
@@ -376,6 +387,8 @@ public enum MobData {
}
} else if (this.value.equals(Data.GOAT_SCREAMING)) {
((Goat) spawned).setScreaming(true);
} else if (this.value instanceof MobCompat.BoatVariant) {
MobCompat.setBoatVariant(spawned, (MobCompat.BoatVariant) this.value);
} else if (this.value instanceof String) {
final String[] split = ((String) this.value).split(":");
switch (split[0]) {
@@ -403,13 +416,15 @@ public enum MobData {
case "fox":
MobCompat.setFoxType(spawned, split[1]);
break;
case "axolotl": {
case "axolotl":
MobCompat.setAxolotlVariant(spawned, split[1]);
break;
}
case "frog":
MobCompat.setFrogVariant(spawned, split[1]);
break;
}
} else {
logger.warning("Unknown mob data type: " + this.toString());
Essentials.getWrappedLogger().warning("Unknown mob data type: " + this.toString());
}
}
@@ -42,7 +42,7 @@ public final class PlayerList {
final String strippedNick = FormatUtil.stripFormat(user.getNickname());
if (ess.getSettings().realNamesOnList() && strippedNick != null && !strippedNick.equals(user.getName())) {
groupString.append(" (").append(user.getName()).append(")");
groupString.append(" ").append(tl("listRealName",user.getName()));
}
groupString.append(ChatColor.WHITE.toString());
}
@@ -22,12 +22,12 @@ import java.util.concurrent.ConcurrentLinkedQueue;
public class RandomTeleport implements IConf {
private static final Random RANDOM = new Random();
private static final int HIGHEST_BLOCK_Y_OFFSET = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_15_R01) ? 1 : 0;
private final IEssentials essentials;
private final IEssentials ess;
private final EssentialsConfiguration config;
private final ConcurrentLinkedQueue<Location> cachedLocations = new ConcurrentLinkedQueue<>();
public RandomTeleport(final IEssentials essentials) {
this.essentials = 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();
@@ -47,8 +47,8 @@ public class RandomTeleport implements IConf {
}
} catch (final InvalidWorldException ignored) {
}
final Location center = essentials.getServer().getWorlds().get(0).getWorldBorder().getCenter();
center.setY(center.getWorld().getHighestBlockYAt(center) + 1);
final Location center = ess.getServer().getWorlds().get(0).getWorldBorder().getCenter();
center.setY(center.getWorld().getHighestBlockYAt(center) + HIGHEST_BLOCK_Y_OFFSET);
setCenter(center);
return center;
}
@@ -124,7 +124,7 @@ public class RandomTeleport implements IConf {
// Prompts caching random valid locations, up to a maximum number of attempts
public void cacheRandomLocations(final Location center, final double minRange, final double maxRange) {
essentials.getServer().getScheduler().scheduleSyncDelayedTask(essentials, () -> {
ess.getServer().getScheduler().scheduleSyncDelayedTask(ess, () -> {
for (int i = 0; i < this.getFindAttempts(); ++i) {
calculateRandomLocation(center, minRange, maxRange).thenAccept(location -> {
if (isValidRandomLocation(location)) {
@@ -177,7 +177,7 @@ public class RandomTeleport implements IConf {
final Location location = new Location(
center.getWorld(),
center.getX() + offsetX,
center.getWorld().getMaxHeight(),
ess.getWorldInfoProvider().getMaxHeight(center.getWorld()),
center.getZ() + offsetZ,
360 * RANDOM.nextFloat() - 180,
0
@@ -195,8 +195,8 @@ public class RandomTeleport implements IConf {
// Returns an appropriate elevation for a given location in the nether, or -1 if none is found
private double getNetherYAt(final Location location) {
for (int y = 32; y < location.getWorld().getMaxHeight() / 2; ++y) {
if (!LocationUtil.isBlockUnsafe(location.getWorld(), location.getBlockX(), y, location.getBlockZ())) {
for (int y = 32; y < ess.getWorldInfoProvider().getMaxHeight(location.getWorld()); ++y) {
if (!LocationUtil.isBlockUnsafe(ess, location.getWorld(), location.getBlockX(), y, location.getBlockZ())) {
return y;
}
}
@@ -204,6 +204,10 @@ public class RandomTeleport implements IConf {
}
private boolean isValidRandomLocation(final Location location) {
return location.getBlockY() > 0 && !this.getExcludedBiomes().contains(location.getBlock().getBiome());
return location.getBlockY() > ess.getWorldInfoProvider().getMinHeight(location.getWorld()) && !this.getExcludedBiomes().contains(location.getBlock().getBiome());
}
public File getFile() {
return config.getFile();
}
}
@@ -40,14 +40,12 @@ import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import static com.earth2me.essentials.I18n.tl;
public class Settings implements net.ess3.api.ISettings {
private static final Logger logger = Logger.getLogger("Essentials");
private static final BigDecimal DEFAULT_MAX_MONEY = new BigDecimal("10000000000000");
private static final BigDecimal DEFAULT_MIN_MONEY = new BigDecimal("-10000000000000");
private final transient EssentialsConfiguration config;
@@ -226,6 +224,21 @@ public class Settings implements net.ess3.api.ISettings {
return chatQuestion;
}
@Override
public boolean isShoutDefault() {
return config.getBoolean("chat.shout-default", false);
}
@Override
public boolean isPersistShout() {
return config.getBoolean("chat.persist-shout", false);
}
@Override
public boolean isChatQuestionEnabled() {
return config.getBoolean("chat.question-enabled", true);
}
public boolean _isTeleportSafetyEnabled() {
return config.getBoolean("teleport-safety", true);
}
@@ -671,7 +684,7 @@ public class Settings implements net.ess3.api.ISettings {
boolean mapModified = false;
if (!disabledBukkitCommands.isEmpty()) {
if (isDebug()) {
logger.log(Level.INFO, "Re-adding " + disabledBukkitCommands.size() + " disabled commands!");
ess.getLogger().log(Level.INFO, "Re-adding " + disabledBukkitCommands.size() + " disabled commands!");
}
ess.getKnownCommandsProvider().getKnownCommands().putAll(disabledBukkitCommands);
disabledBukkitCommands.clear();
@@ -683,12 +696,12 @@ public class Settings implements net.ess3.api.ISettings {
final Command toDisable = ess.getPluginCommand(effectiveAlias);
if (toDisable != null) {
if (isDebug()) {
logger.log(Level.INFO, "Attempting removal of " + effectiveAlias);
ess.getLogger().log(Level.INFO, "Attempting removal of " + effectiveAlias);
}
final Command removed = ess.getKnownCommandsProvider().getKnownCommands().remove(effectiveAlias);
if (removed != null) {
if (isDebug()) {
logger.log(Level.INFO, "Adding command " + effectiveAlias + " to disabled map!");
ess.getLogger().log(Level.INFO, "Adding command " + effectiveAlias + " to disabled map!");
}
disabledBukkitCommands.put(effectiveAlias, removed);
}
@@ -705,7 +718,7 @@ public class Settings implements net.ess3.api.ISettings {
if (mapModified) {
if (isDebug()) {
logger.log(Level.INFO, "Syncing commands");
ess.getLogger().log(Level.INFO, "Syncing commands");
}
if (reloadCount.get() < 2) {
ess.scheduleSyncDelayedTask(() -> ess.getSyncCommandsProvider().syncCommands());
@@ -784,7 +797,7 @@ public class Settings implements net.ess3.api.ISettings {
//noinspection deprecation
final IItemDb itemDb = ess.getItemDb();
if (itemDb == null || !itemDb.isReady()) {
logger.log(Level.FINE, "Skipping item spawn blacklist read; item DB not yet loaded.");
ess.getLogger().log(Level.FINE, "Skipping item spawn blacklist read; item DB not yet loaded.");
return epItemSpwn;
}
for (String itemName : config.getString("item-spawn-blacklist", "").split(",")) {
@@ -796,7 +809,7 @@ public class Settings implements net.ess3.api.ISettings {
final ItemStack iStack = itemDb.get(itemName);
epItemSpwn.add(iStack.getType());
} catch (final Exception ex) {
logger.log(Level.SEVERE, tl("unknownItemInList", itemName, "item-spawn-blacklist"), ex);
ess.getLogger().log(Level.SEVERE, tl("unknownItemInList", itemName, "item-spawn-blacklist"), ex);
}
}
return epItemSpwn;
@@ -824,7 +837,7 @@ public class Settings implements net.ess3.api.ISettings {
try {
newSigns.add(Signs.valueOf(signName).getSign());
} catch (final Exception ex) {
logger.log(Level.SEVERE, tl("unknownItemInList", signName, "enabledSigns"));
ess.getLogger().log(Level.SEVERE, tl("unknownItemInList", signName, "enabledSigns"));
continue;
}
signsEnabled = true;
@@ -938,7 +951,7 @@ public class Settings implements net.ess3.api.ISettings {
}
if (mat == null) {
logger.log(Level.SEVERE, tl("unknownItemInList", itemName, configName));
ess.getLogger().log(Level.SEVERE, tl("unknownItemInList", itemName, configName));
} else {
list.add(mat);
}
@@ -1212,6 +1225,11 @@ public class Settings implements net.ess3.api.ISettings {
return registerBackInListener;
}
@Override
public int getMaxTreeCommandRange() {
return config.getInt("tree-command-range-limit", 300);
}
private boolean _registerBackInListener() {
return config.getBoolean("register-back-in-listener", false);
}
@@ -1264,6 +1282,11 @@ public class Settings implements net.ess3.api.ISettings {
return config.getLong("tpa-accept-cancellation", 120);
}
@Override
public int getTpaMaxRequests() {
return config.getInt("tpa-max-requests", 5);
}
private long _getTeleportInvulnerability() {
return config.getLong("teleport-invulnerability", 0) * 1000;
}
@@ -1670,7 +1693,7 @@ public class Settings implements net.ess3.api.ISettings {
try {
newSigns.add(Signs.valueOf(signName).getSign());
} catch (final Exception ex) {
logger.log(Level.SEVERE, tl("unknownItemInList", signName, "unprotected-sign-names"));
ess.getLogger().log(Level.SEVERE, tl("unknownItemInList", signName, "unprotected-sign-names"));
}
}
return newSigns;
@@ -1855,7 +1878,7 @@ public class Settings implements net.ess3.api.ISettings {
try {
blacklist.add(Pattern.compile(entry).asPredicate());
} catch (final PatternSyntaxException e) {
logger.warning("Invalid nickname blacklist regex: " + entry);
ess.getLogger().warning("Invalid nickname blacklist regex: " + entry);
}
});
@@ -103,7 +103,7 @@ public final class SpawnMob {
// This method spawns a mob at loc, owned by target
public static void spawnmob(final IEssentials ess, final Server server, final CommandSource sender, final User target, final Location loc, final List<String> parts, final List<String> data, int mobCount) throws Exception {
final Location sloc = LocationUtil.getSafeDestination(loc);
final Location sloc = LocationUtil.getSafeDestination(ess, loc);
for (final String part : parts) {
final Mob mob = Mob.fromName(part);
@@ -145,7 +145,7 @@ public class Teleport implements ITeleport {
teleportee.getBase().eject();
}
if (LocationUtil.isBlockUnsafeForUser(teleportee, loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
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);
@@ -3,6 +3,7 @@ package com.earth2me.essentials;
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
import com.earth2me.essentials.craftbukkit.SetExpFix;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.IUser;
import net.ess3.api.MaxMoneyException;
@@ -21,7 +22,6 @@ import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
@@ -79,7 +79,7 @@ public class Trade {
try {
fw = new FileWriter(new File(ess.getDataFolder(), "trade.log"), true);
} catch (final IOException ex) {
Logger.getLogger("Essentials").log(Level.SEVERE, null, ex);
Essentials.getWrappedLogger().log(Level.SEVERE, null, ex);
}
}
final StringBuilder sb = new StringBuilder();
@@ -95,8 +95,10 @@ public class Trade {
} else {
if (charge.getItemStack() != null) {
sb.append(charge.getItemStack().getAmount()).append(",");
sb.append(charge.getItemStack().getType().toString()).append(",");
sb.append(charge.getItemStack().getDurability());
sb.append(charge.getItemStack().getType()).append(",");
if (VersionUtil.PRE_FLATTENING) {
sb.append(charge.getItemStack().getDurability());
}
}
if (charge.getMoney() != null) {
sb.append(charge.getMoney()).append(",");
@@ -119,8 +121,10 @@ public class Trade {
} else {
if (pay.getItemStack() != null) {
sb.append(pay.getItemStack().getAmount()).append(",");
sb.append(pay.getItemStack().getType().toString()).append(",");
sb.append(pay.getItemStack().getDurability());
sb.append(pay.getItemStack().getType()).append(",");
if (VersionUtil.PRE_FLATTENING) {
sb.append(pay.getItemStack().getDurability());
}
}
if (pay.getMoney() != null) {
sb.append(pay.getMoney()).append(",");
@@ -154,7 +158,7 @@ public class Trade {
fw.write(sb.toString());
fw.flush();
} catch (final IOException ex) {
Logger.getLogger("Essentials").log(Level.SEVERE, null, ex);
Essentials.getWrappedLogger().log(Level.SEVERE, null, ex);
}
}
@@ -163,7 +167,7 @@ public class Trade {
try {
fw.close();
} catch (final IOException ex) {
Logger.getLogger("Essentials").log(Level.SEVERE, null, ex);
Essentials.getWrappedLogger().log(Level.SEVERE, null, ex);
}
fw = null;
}
@@ -1,7 +1,6 @@
package com.earth2me.essentials;
import com.google.common.io.Files;
import org.bukkit.Bukkit;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@@ -90,7 +89,7 @@ public class UUIDMap {
}
loading = false;
} catch (final IOException ex) {
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
Essentials.getWrappedLogger().log(Level.SEVERE, ex.getMessage(), ex);
}
}
@@ -147,9 +146,9 @@ public class UUIDMap {
Files.move(configFile, new File(endFile.getParentFile(), "usermap.bak.csv"));
}
} catch (final Exception ex2) {
Bukkit.getLogger().log(Level.SEVERE, ex2.getMessage(), ex2);
Essentials.getWrappedLogger().log(Level.SEVERE, ex2.getMessage(), ex2);
}
Bukkit.getLogger().log(Level.WARNING, ex.getMessage(), ex);
Essentials.getWrappedLogger().log(Level.WARNING, ex.getMessage(), ex);
}
}
}
@@ -28,54 +28,70 @@ import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.WeakHashMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
public class User extends UserData implements Comparable<User>, IMessageRecipient, net.ess3.api.IUser {
private static final Statistic PLAY_ONE_TICK = EnumUtil.getStatistic("PLAY_ONE_MINUTE", "PLAY_ONE_TICK");
private static final Logger logger = Logger.getLogger("Essentials");
// User modules
private final IMessageRecipient messageRecipient;
private transient final AsyncTeleport teleport;
private transient final Teleport legacyTeleport;
// User command confirmation strings
private final Map<User, BigDecimal> confirmingPayments = new WeakHashMap<>();
private transient UUID teleportRequester;
private transient boolean teleportRequestHere;
private transient Location teleportLocation;
// User teleport variables
private final transient LinkedHashMap<String, TpaRequest> teleportRequestQueue = new LinkedHashMap<>();
// User properties
private transient boolean vanished;
private transient long teleportRequestTime;
private transient long lastOnlineActivity;
private transient long lastThrottledAction;
private transient long lastActivity = System.currentTimeMillis();
private boolean hidden = false;
private boolean leavingHidden = false;
private boolean rightClickJump = false;
private transient Location afkPosition = null;
private boolean invSee = false;
private boolean recipeSee = false;
private boolean enderSee = false;
private transient long teleportInvulnerabilityTimestamp = 0;
private boolean ignoreMsg = false;
// User afk variables
private String afkMessage;
private long afkSince;
private transient Location afkPosition = null;
// Misc
private transient long lastOnlineActivity;
private transient long lastThrottledAction;
private transient long lastActivity = System.currentTimeMillis();
private transient long teleportInvulnerabilityTimestamp = 0;
private String confirmingClearCommand;
private long lastNotifiedAboutMailsMs;
private String lastHomeConfirmation;
private long lastHomeConfirmationTimestamp;
private boolean toggleShout = false;
private Boolean toggleShout;
private transient final List<String> signCopy = Lists.newArrayList("", "", "", "");
private transient long lastVanishTime = System.currentTimeMillis();
public User(final Player base, final IEssentials ess) {
super(base, ess);
@@ -90,9 +106,12 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
this.messageRecipient = new SimpleMessageRecipient(ess, this);
}
User update(final Player base) {
void update(final Player base) {
setBase(base);
return this;
}
public IEssentials getEssentials() {
return ess;
}
@Override
@@ -304,7 +323,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
if (isAuthorized("essentials.itemspawn.item-all") || isAuthorized("essentials.itemspawn.item-" + name))
return true;
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01)) {
if (VersionUtil.PRE_FLATTENING) {
final int id = material.getId();
if (isAuthorized("essentials.itemspawn.item-" + id)) return true;
}
@@ -327,44 +346,94 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public void requestTeleport(final User player, final boolean here) {
teleportRequestTime = System.currentTimeMillis();
teleportRequester = player == null ? null : player.getBase().getUniqueId();
teleportRequestHere = here;
if (player == null) {
teleportLocation = null;
} else {
teleportLocation = here ? player.getLocation() : this.getLocation();
final TpaRequest request = teleportRequestQueue.getOrDefault(player.getName(), new TpaRequest(player.getName(), player.getUUID()));
request.setTime(System.currentTimeMillis());
request.setHere(here);
request.setLocation(here ? player.getLocation() : this.getLocation());
// Handle max queue size
teleportRequestQueue.remove(request.getName());
if (teleportRequestQueue.size() >= ess.getSettings().getTpaMaxRequests()) {
final List<String> keys = new ArrayList<>(teleportRequestQueue.keySet());
teleportRequestQueue.remove(keys.get(keys.size() - 1));
}
// Add request to queue
teleportRequestQueue.put(request.getName(), request);
}
@Override
@Deprecated
public boolean hasOutstandingTeleportRequest() {
if (getTeleportRequest() != null) { // Player has outstanding teleport request.
final long timeout = ess.getSettings().getTpaAcceptCancellation();
if (timeout != 0) {
if ((System.currentTimeMillis() - getTeleportRequestTime()) / 1000 <= timeout) { // Player has outstanding request
return true;
} else { // outstanding request expired.
requestTeleport(null, false);
return false;
return getNextTpaRequest(false, false, false) != null;
}
public Collection<String> getPendingTpaKeys() {
return teleportRequestQueue.keySet();
}
@Override
public boolean hasPendingTpaRequests(boolean inform, boolean excludeHere) {
return getNextTpaRequest(inform, false, excludeHere) != null;
}
public boolean hasOutstandingTpaRequest(String playerUsername, boolean here) {
final TpaRequest request = getOutstandingTpaRequest(playerUsername, false);
return request != null && request.isHere() == here;
}
public @Nullable TpaRequest getOutstandingTpaRequest(String playerUsername, boolean inform) {
if (!teleportRequestQueue.containsKey(playerUsername)) {
return null;
}
final long timeout = ess.getSettings().getTpaAcceptCancellation();
final TpaRequest request = teleportRequestQueue.get(playerUsername);
if (timeout < 1 || System.currentTimeMillis() - request.getTime() <= timeout * 1000) {
return request;
}
teleportRequestQueue.remove(playerUsername);
if (inform) {
sendMessage(tl("requestTimedOutFrom", ess.getUser(request.getRequesterUuid()).getDisplayName()));
}
return null;
}
public TpaRequest removeTpaRequest(String playerUsername) {
return teleportRequestQueue.remove(playerUsername);
}
@Override
public TpaRequest getNextTpaRequest(boolean inform, boolean ignoreExpirations, boolean excludeHere) {
if (teleportRequestQueue.isEmpty()) {
return null;
}
final long timeout = ess.getSettings().getTpaAcceptCancellation();
final List<String> keys = new ArrayList<>(teleportRequestQueue.keySet());
Collections.reverse(keys);
TpaRequest nextRequest = null;
for (final String key : keys) {
final TpaRequest request = teleportRequestQueue.get(key);
if (timeout < 1 || (System.currentTimeMillis() - request.getTime()) <= TimeUnit.SECONDS.toMillis(timeout)) {
if (excludeHere && request.isHere()) {
continue;
}
} else { // outstanding request does not expire
return true;
if (ignoreExpirations) {
return request;
} else if (nextRequest == null) {
nextRequest = request;
}
} else {
if (inform) {
sendMessage(tl("requestTimedOutFrom", ess.getUser(request.getRequesterUuid()).getDisplayName()));
}
teleportRequestQueue.remove(key);
}
}
return false;
}
public UUID getTeleportRequest() {
return teleportRequester;
}
public boolean isTpRequestHere() {
return teleportRequestHere;
}
public Location getTpRequestLocation() {
return teleportLocation;
return nextRequest;
}
public String getNick() {
@@ -450,7 +519,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
this.getBase().setPlayerListName(name);
} catch (final IllegalArgumentException e) {
if (ess.getSettings().isDebug()) {
logger.log(Level.INFO, "Playerlist for " + name + " was not updated. Name clashed with another online player.");
ess.getLogger().log(Level.INFO, "Playerlist for " + name + " was not updated. Name clashed with another online player.");
}
}
}
@@ -568,7 +637,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return;
}
this.getBase().setSleepingIgnored(this.isAuthorized("essentials.sleepingignored") || set && ess.getSettings().sleepIgnoresAfkPlayers());
this.getBase().setSleepingIgnored(this.isAuthorized("essentials.sleepingignored") || (set && ess.getSettings().sleepIgnoresAfkPlayers()));
if (set && !isAfk()) {
afkPosition = this.getLocation();
this.afkSince = System.currentTimeMillis();
@@ -613,6 +682,16 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return hidden;
}
@Override
public boolean isLeavingHidden() {
return leavingHidden;
}
@Override
public void setLeavingHidden(boolean leavingHidden) {
this.leavingHidden = leavingHidden;
}
@Override
public void setHidden(final boolean hidden) {
this.hidden = hidden;
@@ -823,8 +902,11 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return ess.getPermissionsHandler().canBuild(base, getGroup());
}
@Override
@Deprecated
public long getTeleportRequestTime() {
return teleportRequestTime;
final TpaRequest request = getNextTpaRequest(false, false, false);
return request == null ? 0L : request.getTime();
}
public boolean isInvSee() {
@@ -892,7 +974,9 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
}
setHidden(true);
lastVanishTime = System.currentTimeMillis();
ess.getVanishedPlayersNew().add(getName());
this.getBase().setMetadata("vanished", new FixedMetadataValue(ess, true));
if (isAuthorized("essentials.vanish.effect")) {
this.getBase().addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, Integer.MAX_VALUE, 1, false));
}
@@ -905,6 +989,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
setHidden(false);
ess.getVanishedPlayersNew().remove(getName());
this.getBase().setMetadata("vanished", new FixedMetadataValue(ess, false));
if (isAuthorized("essentials.vanish.effect")) {
this.getBase().removePotionEffect(PotionEffectType.INVISIBILITY);
}
@@ -990,7 +1075,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public UUID getUUID() {
return getBase().getUniqueId();
return this.getBase().getUniqueId();
}
@Override
@@ -1116,6 +1201,10 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return isBaltopExcludeCache();
}
public long getLastVanishTime() {
return lastVanishTime;
}
@Override
public Block getTargetBlock(int maxDistance) {
final Block block;
@@ -1128,10 +1217,16 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public void setToggleShout(boolean toggleShout) {
this.toggleShout = toggleShout;
if (ess.getSettings().isPersistShout()) {
setShouting(toggleShout);
}
}
@Override
public boolean isToggleShout() {
return toggleShout;
if (ess.getSettings().isPersistShout()) {
return toggleShout = isShouting();
}
return toggleShout == null ? toggleShout = ess.getSettings().isShoutDefault() : toggleShout;
}
}
@@ -85,14 +85,14 @@ public abstract class UserData extends PlayerExtension implements IConf {
try {
holder = config.getRootNode().get(UserConfigHolder.class);
} catch (SerializationException e) {
ess.getLogger().log(Level.SEVERE, "Error while reading user config: " + e.getMessage(), e);
ess.getLogger().log(Level.SEVERE, "Error while reading user config: " + config.getFile().getName(), e);
throw new RuntimeException(e);
}
config.setSaveHook(() -> {
try {
config.getRootNode().set(UserConfigHolder.class, holder);
} catch (SerializationException e) {
ess.getLogger().log(Level.SEVERE, "Error while saving user config: " + e.getMessage(), e);
ess.getLogger().log(Level.SEVERE, "Error while saving user config: " + config.getFile().getName(), e);
throw new RuntimeException(e);
}
});
@@ -722,6 +722,18 @@ public abstract class UserData extends PlayerExtension implements IConf {
config.save();
}
public boolean isShouting() {
if (holder.shouting() == null) {
holder.shouting(ess.getSettings().isShoutDefault());
}
return holder.shouting();
}
public void setShouting(boolean shouting) {
holder.shouting(shouting);
config.save();
}
public UUID getConfigUUID() {
return config.getUuid();
}
@@ -16,12 +16,10 @@ import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
public class Warps implements IConf, net.ess3.api.IWarps {
private static final Logger logger = Logger.getLogger("Essentials");
private final Map<StringIgnoreCase, EssentialsConfiguration> warpPoints = new HashMap<>();
private final File warpsFolder;
@@ -38,6 +36,11 @@ public class Warps implements IConf, net.ess3.api.IWarps {
return warpPoints.isEmpty();
}
@Override
public boolean isWarp(String name) {
return warpPoints.containsKey(new StringIgnoreCase(name));
}
@Override
public Collection<String> getList() {
final List<String> keys = new ArrayList<>();
@@ -130,7 +133,7 @@ public class Warps implements IConf, net.ess3.api.IWarps {
warpPoints.put(new StringIgnoreCase(name), conf);
}
} catch (final Exception ex) {
logger.log(Level.WARNING, tl("loadWarpError", filename), ex);
Essentials.getWrappedLogger().log(Level.WARNING, tl("loadWarpError", filename), ex);
}
}
}
@@ -30,13 +30,15 @@ public class Worth implements IConf {
* @return The price from the config.
*/
public BigDecimal getPrice(final IEssentials ess, final ItemStack itemStack) {
BigDecimal result;
BigDecimal result = BigDecimal.ONE.negate();
final String itemname = itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
// Check for matches with data value from stack
// Note that we always default to BigDecimal.ONE.negate(), equivalent to -1
result = config.getBigDecimal("worth." + itemname + "." + itemStack.getDurability(), BigDecimal.ONE.negate());
if (VersionUtil.PRE_FLATTENING) {
// Check for matches with data value from stack
// Note that we always default to BigDecimal.ONE.negate(), equivalent to -1
result = config.getBigDecimal("worth." + itemname + "." + itemStack.getDurability(), BigDecimal.ONE.negate());
}
// Check for matches with data value 0
if (result.signum() < 0) {
@@ -140,7 +142,7 @@ public class Worth implements IConf {
String path = "worth." + itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
// Spigot 1.13+ throws an exception if a 1.13+ plugin even *attempts* to do set data.
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01) && itemStack.getType().getData() == null) {
if (VersionUtil.PRE_FLATTENING && itemStack.getType().getData() == null) {
// Bukkit-bug: getDurability still contains the correct value, while getData().getData() is 0.
path = path + "." + itemStack.getDurability();
}
@@ -149,6 +151,10 @@ public class Worth implements IConf {
config.save();
}
public File getFile() {
return config.getFile();
}
@Override
public void reloadConfig() {
config.load();
@@ -17,14 +17,12 @@ import java.math.MathContext;
import java.text.MessageFormat;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* You should use Vault instead of directly using this class.
*/
public class Economy {
public static final MathContext MATH_CONTEXT = MathContext.DECIMAL128;
private static final Logger LOGGER = Logger.getLogger("Essentials");
private static IEssentials ess;
private static final String WARN_CALL_BEFORE_LOAD = "Essentials API is called before Essentials is loaded.";
@@ -54,8 +52,8 @@ public class Economy {
final UUID npcUUID = UUID.nameUUIDFromBytes(("NPC:" + name).getBytes(Charsets.UTF_8));
final File npcFile = new File(folder, npcUUID + ".yml");
if (npcFile.exists()) {
LOGGER.log(Level.SEVERE, MessageFormat.format(WARN_NPC_RECREATE_1, name, npcUUID.toString()), new RuntimeException());
LOGGER.log(Level.SEVERE, WARN_NPC_RECREATE_2);
ess.getLogger().log(Level.SEVERE, MessageFormat.format(WARN_NPC_RECREATE_1, name, npcUUID.toString()), new RuntimeException());
ess.getLogger().log(Level.SEVERE, WARN_NPC_RECREATE_2);
}
final EssentialsUserConfiguration npcConfig = new EssentialsUserConfiguration(name, npcUUID, npcFile);
npcConfig.load();
@@ -90,7 +88,7 @@ public class Economy {
if (player != null) {
user = ess.getUser(player.getUniqueId());
if (user != null) {
LOGGER.log(Level.INFO, MessageFormat.format(WARN_PLAYER_UUID_NO_NAME, name, player.getUniqueId().toString()), new RuntimeException());
ess.getLogger().log(Level.INFO, MessageFormat.format(WARN_PLAYER_UUID_NO_NAME, name, player.getUniqueId().toString()), new RuntimeException());
}
}
}
@@ -190,7 +188,7 @@ public class Economy {
try {
setMoney(name, BigDecimal.valueOf(balance));
} catch (final ArithmeticException e) {
LOGGER.log(Level.WARNING, "Failed to set balance of " + name + " to " + balance + ": " + e.getMessage(), e);
ess.getLogger().log(Level.WARNING, "Failed to set balance of " + name + " to " + balance + ": " + e.getMessage(), e);
}
}
@@ -268,7 +266,7 @@ public class Economy {
try {
add(name, BigDecimal.valueOf(amount));
} catch (final ArithmeticException e) {
LOGGER.log(Level.WARNING, "Failed to add " + amount + " to balance of " + name + ": " + e.getMessage(), e);
ess.getLogger().log(Level.WARNING, "Failed to add " + amount + " to balance of " + name + ": " + e.getMessage(), e);
}
}
@@ -340,7 +338,7 @@ public class Economy {
try {
substract(name, BigDecimal.valueOf(amount));
} catch (final ArithmeticException e) {
LOGGER.log(Level.WARNING, "Failed to subtract " + amount + " of balance of " + name + ": " + e.getMessage(), e);
ess.getLogger().log(Level.WARNING, "Failed to subtract " + amount + " of balance of " + name + ": " + e.getMessage(), e);
}
}
@@ -410,7 +408,7 @@ public class Economy {
try {
divide(name, BigDecimal.valueOf(amount));
} catch (final ArithmeticException e) {
LOGGER.log(Level.WARNING, "Failed to divide balance of " + name + " by " + amount + ": " + e.getMessage(), e);
ess.getLogger().log(Level.WARNING, "Failed to divide balance of " + name + " by " + amount + ": " + e.getMessage(), e);
}
}
@@ -482,7 +480,7 @@ public class Economy {
try {
multiply(name, BigDecimal.valueOf(amount));
} catch (final ArithmeticException e) {
LOGGER.log(Level.WARNING, "Failed to multiply balance of " + name + " by " + amount + ": " + e.getMessage(), e);
ess.getLogger().log(Level.WARNING, "Failed to multiply balance of " + name + " by " + amount + ": " + e.getMessage(), e);
}
}
@@ -603,7 +601,7 @@ public class Economy {
try {
return hasEnough(name, BigDecimal.valueOf(amount));
} catch (final ArithmeticException e) {
LOGGER.log(Level.WARNING, "Failed to compare balance of " + name + " with " + amount + ": " + e.getMessage(), e);
ess.getLogger().log(Level.WARNING, "Failed to compare balance of " + name + " with " + amount + ": " + e.getMessage(), e);
return false;
}
}
@@ -664,7 +662,7 @@ public class Economy {
try {
return hasMore(name, BigDecimal.valueOf(amount));
} catch (final ArithmeticException e) {
LOGGER.log(Level.WARNING, "Failed to compare balance of " + name + " with " + amount + ": " + e.getMessage(), e);
ess.getLogger().log(Level.WARNING, "Failed to compare balance of " + name + " with " + amount + ": " + e.getMessage(), e);
return false;
}
}
@@ -726,7 +724,7 @@ public class Economy {
try {
return hasLess(name, BigDecimal.valueOf(amount));
} catch (final ArithmeticException e) {
LOGGER.log(Level.WARNING, "Failed to compare balance of " + name + " with " + amount + ": " + e.getMessage(), e);
ess.getLogger().log(Level.WARNING, "Failed to compare balance of " + name + " with " + amount + ": " + e.getMessage(), e);
return false;
}
}
@@ -833,7 +831,7 @@ public class Economy {
try {
return format(BigDecimal.valueOf(amount));
} catch (final NumberFormatException e) {
LOGGER.log(Level.WARNING, "Failed to display " + amount + ": " + e.getMessage(), e);
ess.getLogger().log(Level.WARNING, "Failed to display " + amount + ": " + e.getMessage(), e);
return "NaN";
}
}
@@ -900,7 +898,7 @@ public class Economy {
createNPCFile(name);
return true;
}
LOGGER.log(Level.WARNING, MessageFormat.format(WARN_EXISTING_NPC_CREATE, name, user.getConfigUUID()), new RuntimeException());
ess.getLogger().log(Level.WARNING, MessageFormat.format(WARN_EXISTING_NPC_CREATE, name, user.getConfigUUID()), new RuntimeException());
return false;
}
@@ -26,6 +26,14 @@ public interface IWarps extends IConf {
*/
Location getWarp(String warp) throws WarpNotFoundException, net.ess3.api.InvalidWorldException;
/**
* Checks if the provided name is a warp.
*
* @param name The warp name.
* @return true if a warp by that name exists.
*/
boolean isWarp(String name);
/**
* Gets a list of warps
*
@@ -7,6 +7,7 @@ import com.earth2me.essentials.utils.NumberUtil;
import com.google.common.collect.Lists;
import net.essentialsx.api.v2.services.BalanceTop;
import org.bukkit.Server;
import org.bukkit.command.BlockCommandSender;
import java.math.BigDecimal;
import java.text.DateFormat;
@@ -32,8 +33,15 @@ public class Commandbalancetop extends EssentialsCommand {
final Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(ess.getBalanceTop().getCacheAge());
final DateFormat format = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
sender.sendMessage(tl("balanceTop", format.format(cal.getTime())));
new TextPager(cache).showPage(Integer.toString(page), null, "balancetop", sender);
final Runnable runnable = () -> {
sender.sendMessage(tl("balanceTop", format.format(cal.getTime())));
new TextPager(cache).showPage(Integer.toString(page), null, "balancetop", sender);
};
if (sender.getSender() instanceof BlockCommandSender) {
ess.scheduleSyncDelayedTask(runnable);
} else {
runnable.run();
}
}
@Override
@@ -54,7 +54,7 @@ public class Commandban extends EssentialsCommand {
final String banDisplay = tl("banFormat", banReason, senderDisplayName);
user.getBase().kickPlayer(banDisplay);
server.getLogger().log(Level.INFO, tl("playerBanned", senderDisplayName, user.getName(), banDisplay));
ess.getLogger().log(Level.INFO, tl("playerBanned", senderDisplayName, user.getName(), banDisplay));
if (nomatch) {
sender.sendMessage(tl("userUnknown", user.getName()));
@@ -54,7 +54,7 @@ public class Commandbanip extends EssentialsCommand {
final String banDisplay = tl("banFormat", banReason, senderDisplayName);
ess.getServer().getBanList(BanList.Type.IP).addBan(ipAddress, banReason, null, senderName);
server.getLogger().log(Level.INFO, tl("playerBanIpAddress", senderDisplayName, ipAddress, banReason));
ess.getLogger().log(Level.INFO, tl("playerBanIpAddress", senderDisplayName, ipAddress, banReason));
for (final Player player : ess.getServer().getOnlinePlayers()) {
if (player.getAddress().getAddress().getHostAddress().equalsIgnoreCase(ipAddress)) {
@@ -32,7 +32,7 @@ public class Commandbigtree extends EssentialsCommand {
throw new NotEnoughArgumentsException();
}
final Location loc = LocationUtil.getTarget(user.getBase()).add(0, 1, 0);
final Location loc = LocationUtil.getTarget(user.getBase(), ess.getSettings().getMaxTreeCommandRange()).add(0, 1, 0);
if (loc.getBlock().getType().isSolid()) {
throw new Exception(tl("bigTreeFailure"));
}
@@ -130,7 +130,7 @@ public class Commandclearinventory extends EssentialsCommand {
} else {
for (final Item item : items) {
final ItemStack stack = new ItemStack(item.getMaterial());
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01)) {
if (VersionUtil.PRE_FLATTENING) {
stack.setDurability(item.getData());
}
// amount -1 means all items will be cleared
@@ -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 com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.MaxMoneyException;
import org.bukkit.Material;
import org.bukkit.Server;
@@ -161,8 +162,7 @@ public class Commandcondense extends EssentialsCommand {
iter.remove();
continue;
}
if (inputSlot.getDurability() == Short.MAX_VALUE) {
if (VersionUtil.PRE_FLATTENING && inputSlot.getDurability() == Short.MAX_VALUE) {
inputSlot.setDurability((short) 0);
}
if (!inputSlot.isSimilar(stack)) {
@@ -2,7 +2,6 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.Kit;
import com.earth2me.essentials.config.ConfigurateUtil;
import com.google.common.collect.Lists;
import org.bukkit.Server;
@@ -38,7 +37,7 @@ public class Commanddelkit extends EssentialsCommand {
@Override
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
if (args.length == 1) {
return Lists.newArrayList(ConfigurateUtil.getKeys(ess.getKits().getKits()));
return Lists.newArrayList(ess.getKits().getKitKeys());
}
return Collections.emptyList();
}
@@ -23,8 +23,14 @@ public class Commanddelwarp extends EssentialsCommand {
throw new NotEnoughArgumentsException();
}
//Check if warp exists before calling the event
final Location location = ess.getWarps().getWarp(args[0]);
if (location != null) {
if (ess.getWarps().isWarp(args[0])) {
Location location;
try {
location = ess.getWarps().getWarp(args[0]);
} catch (Exception ignored) {
// World is unloaded/deleted
location = null;
}
final WarpModifyEvent event = new WarpModifyEvent(sender.getUser(this.ess), args[0], location, null, WarpModifyEvent.WarpModifyCause.DELETE);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
@@ -6,6 +6,7 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.UserMap;
import com.earth2me.essentials.economy.EconomyLayer;
import com.earth2me.essentials.economy.EconomyLayers;
import com.earth2me.essentials.utils.CommandMapUtil;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FloatUtil;
@@ -25,6 +26,7 @@ import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
@@ -42,6 +44,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -76,7 +79,12 @@ public class Commandessentials extends EssentialsCommand {
"PermissionsEx", // permissions (unsupported)
"GroupManager", // permissions (unsupported)
"bPermissions", // permissions (unsupported)
"DiscordSRV" // potential for issues if EssentialsXDiscord is installed
"DiscordSRV", // potential for issues if EssentialsXDiscord is installed
// Chat signing bypass plugins that can potentially break EssentialsChat
"AntiPopup",
"NoChatReports",
"NoEncryption"
);
private static final List<String> officialPlugins = Arrays.asList(
"EssentialsAntiBuild",
@@ -90,7 +98,11 @@ public class Commandessentials extends EssentialsCommand {
private static final List<String> warnPlugins = Arrays.asList(
"PermissionsEx",
"GroupManager",
"bPermissions"
"bPermissions",
// Brain-dead chat signing bypass that break EssentialsChat
"NoChatReports",
"NoEncryption"
);
private transient TuneRunnable currentTune = null;
@@ -258,6 +270,10 @@ public class Commandessentials extends EssentialsCommand {
files.add(new PasteUtil.PasteFile("dump.json", dump.toString()));
final Plugin essDiscord = Bukkit.getPluginManager().getPlugin("EssentialsDiscord");
final Plugin essSpawn = Bukkit.getPluginManager().getPlugin("EssentialsSpawn");
final Map<String, Command> knownCommandsCopy = new HashMap<>(ess.getKnownCommandsProvider().getKnownCommands());
final Map<String, String> disabledCommandsCopy = new HashMap<>(ess.getAlternativeCommandsHandler().disabledCommands());
// Further operations will be heavy IO
ess.runTaskAsynchronously(() -> {
@@ -265,12 +281,20 @@ public class Commandessentials extends EssentialsCommand {
boolean discord = false;
boolean kits = false;
boolean log = false;
boolean worth = false;
boolean tpr = false;
boolean spawns = false;
boolean commands = false;
for (final String arg : args) {
if (arg.equals("*")) {
if (arg.equals("*") || arg.equalsIgnoreCase("all")) {
config = true;
discord = true;
kits = true;
log = true;
worth = true;
tpr = true;
spawns = true;
commands = true;
break;
} else if (arg.equalsIgnoreCase("config")) {
config = true;
@@ -280,6 +304,14 @@ public class Commandessentials extends EssentialsCommand {
kits = true;
} else if (arg.equalsIgnoreCase("log")) {
log = true;
} else if (arg.equalsIgnoreCase("worth")) {
worth = true;
} else if (arg.equalsIgnoreCase("tpr")) {
tpr = true;
} else if (arg.equalsIgnoreCase("spawns")) {
spawns = true;
} else if (arg.equalsIgnoreCase("commands")) {
commands = true;
}
}
@@ -291,11 +323,11 @@ public class Commandessentials extends EssentialsCommand {
}
}
if (discord && essDiscord != null && essDiscord.isEnabled()) {
if (discord && essDiscord != null) {
try {
files.add(new PasteUtil.PasteFile("discord-config.yml",
new String(Files.readAllBytes(essDiscord.getDataFolder().toPath().resolve("config.yml")), StandardCharsets.UTF_8)
.replaceAll("[MN][A-Za-z\\d]{23}\\.[\\w-]{6}\\.[\\w-]{27}", "<censored token>")));
.replaceAll("[A-Za-z\\d]{24}\\.[\\w-]{6}\\.[\\w-]{27}", "<censored token>")));
} catch (IOException e) {
sender.sendMessage(tl("dumpErrorUpload", "discord-config.yml", e.getMessage()));
}
@@ -319,6 +351,40 @@ public class Commandessentials extends EssentialsCommand {
}
}
if (worth) {
try {
files.add(new PasteUtil.PasteFile("worth.yml", new String(Files.readAllBytes(ess.getWorth().getFile().toPath()), StandardCharsets.UTF_8)));
} catch (IOException e) {
sender.sendMessage(tl("dumpErrorUpload", "worth.yml", e.getMessage()));
}
}
if (tpr) {
try {
files.add(new PasteUtil.PasteFile("tpr.yml", new String(Files.readAllBytes(ess.getRandomTeleport().getFile().toPath()), StandardCharsets.UTF_8)));
} catch (IOException e) {
sender.sendMessage(tl("dumpErrorUpload", "tpr.yml", e.getMessage()));
}
}
if (spawns && essSpawn != null) {
try {
files.add(new PasteUtil.PasteFile("spawn.yml", new String(Files.readAllBytes(ess.getDataFolder().toPath().resolve("spawn.yml")), StandardCharsets.UTF_8)));
} catch (IOException e) {
sender.sendMessage(tl("dumpErrorUpload", "spawn.yml", e.getMessage()));
}
}
if (commands) {
try {
files.add(new PasteUtil.PasteFile("commands.yml", new String(Files.readAllBytes(Paths.get("commands.yml")), StandardCharsets.UTF_8)));
files.add(new PasteUtil.PasteFile("commandmap.json", CommandMapUtil.toJsonPretty(ess, knownCommandsCopy)));
files.add(new PasteUtil.PasteFile("commandoverride.json", disabledCommandsCopy.toString()));
} catch (IOException e) {
sender.sendMessage(tl("dumpErrorUpload", "commands.yml", e.getMessage()));
}
}
final CompletableFuture<PasteUtil.PasteResult> future = PasteUtil.createPaste(files);
future.thenAccept(result -> {
if (result != null) {
@@ -375,7 +441,7 @@ public class Commandessentials extends EssentialsCommand {
private void runMoo(final Server server, final CommandSource sender, final String command, final String[] args) {
if (args.length == 2 && args[1].equals("moo")) {
for (final String s : CONSOLE_MOO) {
logger.info(s);
ess.getLogger().info(s);
}
for (final Player player : ess.getOnlinePlayers()) {
player.sendMessage(PLAYER_MOO);
@@ -646,6 +712,9 @@ public class Commandessentials extends EssentialsCommand {
case DANGEROUS_FORK:
sender.sendMessage(ChatColor.DARK_RED + tl("serverUnsupportedDangerous"));
break;
case STUPID_PLUGIN:
sender.sendMessage(ChatColor.DARK_RED + tl("serverUnsupportedDumbPlugins"));
break;
case UNSTABLE:
sender.sendMessage(ChatColor.DARK_RED + tl("serverUnsupportedMods"));
break;
@@ -719,9 +788,9 @@ public class Commandessentials extends EssentialsCommand {
}
break;
case "dump":
final List<String> list = Lists.newArrayList("config", "kits", "log", "discord", "*");
final List<String> list = Lists.newArrayList("config", "kits", "log", "discord", "worth", "tpr", "spawns", "commands", "all");
for (String arg : args) {
if (arg.equals("*")) {
if (arg.equals("*") || arg.equalsIgnoreCase("all")) {
list.clear();
return list;
}
@@ -3,7 +3,6 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.NumberUtil;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Server;
@@ -57,7 +56,7 @@ public class Commandgc extends EssentialsCommand {
tileEntities += chunk.getTileEntities().length;
}
} catch (final java.lang.ClassCastException ex) {
Bukkit.getLogger().log(Level.SEVERE, "Corrupted chunk data on world " + w, ex);
ess.getLogger().log(Level.SEVERE, "Corrupted chunk data on world " + w, ex);
}
sender.sendMessage(tl("gcWorld", worldType, w.getName(), w.getLoadedChunks().length, w.getEntities().size(), tileEntities));
@@ -5,6 +5,7 @@ import com.earth2me.essentials.MetaItemStack;
import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists;
import org.bukkit.Material;
import org.bukkit.Server;
@@ -37,7 +38,7 @@ public class Commandgive extends EssentialsLoopCommand {
}
try {
if (args.length > 3 && NumberUtil.isInt(args[2]) && NumberUtil.isInt(args[3])) {
if (args.length > 3 && VersionUtil.PRE_FLATTENING && NumberUtil.isInt(args[2]) && NumberUtil.isInt(args[3])) {
stack.setAmount(Integer.parseInt(args[2]));
stack.setDurability(Short.parseShort(args[3]));
} else if (args.length > 2 && Integer.parseInt(args[2]) > 0) {
@@ -36,7 +36,7 @@ public class Commandhelpop extends EssentialsCommand {
throw new NotEnoughArgumentsException();
}
final String message = tl("helpOp", from, FormatUtil.stripFormat(getFinalArg(args, 0)));
server.getLogger().log(Level.INFO, message);
ess.getLogger().log(Level.INFO, message);
ess.broadcastMessage("essentials.helpop.receive", message);
return message;
}
@@ -40,7 +40,7 @@ public class Commandice extends EssentialsLoopCommand {
@Override
protected void updatePlayer(Server server, CommandSource sender, User user, String[] args) throws NotEnoughArgumentsException, PlayerExemptException, ChargeException, MaxMoneyException {
freezePlayer(user);
user.sendMessage(tl("iceOther", user.getDisplayName()));
sender.sendMessage(tl("iceOther", user.getDisplayName()));
}
private void freezePlayer(final IUser user) {
@@ -8,6 +8,8 @@ import org.bukkit.inventory.Inventory;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandinvsee extends EssentialsCommand {
public Commandinvsee() {
super("invsee");
@@ -21,6 +23,11 @@ public class Commandinvsee extends EssentialsCommand {
}
final User invUser = getPlayer(server, user, args, 0);
if (user == invUser) {
user.sendMessage(tl("invseeNoSelf"));
throw new NoChargeException();
}
final Inventory inv;
if (args.length > 1 && user.isAuthorized("essentials.invsee.equip")) {
@@ -40,7 +47,9 @@ public class Commandinvsee extends EssentialsCommand {
@Override
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
if (args.length == 1) {
return getPlayers(server, user);
final List<String> suggestions = getPlayers(server, user);
suggestions.remove(user.getName());
return suggestions;
} else {
//if (args.length == 2) {
// return Lists.newArrayList("equipped");
@@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import org.bukkit.Material;
@@ -36,7 +37,7 @@ public class Commanditemdb extends EssentialsCommand {
String itemId = "none";
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01)) {
if (VersionUtil.PRE_FLATTENING) {
itemId = itemStack.getType().getId() + ":" + itemStack.getDurability();
}
@@ -49,7 +50,7 @@ public class Commanditemdb extends EssentialsCommand {
if (itemHeld && itemStack.getType() != Material.AIR) {
final int maxuses = itemStack.getType().getMaxDurability();
final int durability = (maxuses + 1) - itemStack.getDurability();
final int durability = (maxuses + 1) - MaterialUtil.getDamage(itemStack);
if (maxuses != 0) {
sender.sendMessage(tl("durability", Integer.toString(durability)));
}
@@ -51,7 +51,7 @@ public class Commandkick extends EssentialsCommand {
target.getBase().kickPlayer(kickReason);
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.DISPLAY_NAME;
server.getLogger().log(Level.INFO, tl("playerKicked", senderDisplayName, target.getName(), kickReason));
ess.getLogger().log(Level.INFO, tl("playerKicked", senderDisplayName, target.getName(), kickReason));
ess.broadcastMessage("essentials.kick.notify", tl("playerKicked", senderDisplayName, target.getName(), kickReason));
}
@@ -3,7 +3,6 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.Kit;
import com.earth2me.essentials.User;
import com.earth2me.essentials.config.ConfigurateUtil;
import com.earth2me.essentials.utils.StringUtil;
import org.bukkit.Server;
@@ -101,7 +100,7 @@ public class Commandkit extends EssentialsCommand {
if (args.length == 1) {
final List<String> options = new ArrayList<>();
// TODO: Move all of this to its own method
for (final String kitName : ConfigurateUtil.getKeys(ess.getKits().getKits())) {
for (final String kitName : ess.getKits().getKitKeys()) {
if (!user.isAuthorized("essentials.kits." + kitName)) { // Only check perm, not time or money
continue;
}
@@ -118,7 +117,7 @@ public class Commandkit extends EssentialsCommand {
@Override
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
if (args.length == 1) {
return new ArrayList<>(ConfigurateUtil.getKeys(ess.getKits().getKits())); // TODO: Move this to its own method
return new ArrayList<>(ess.getKits().getKitKeys()); // TODO: Move this to its own method
} else if (args.length == 2) {
return getPlayers(server, sender);
} else {
@@ -2,7 +2,6 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.config.ConfigurateUtil;
import org.bukkit.Server;
import java.util.ArrayList;
@@ -59,7 +58,7 @@ public class Commandkitreset extends EssentialsCommand {
@Override
protected List<String> getTabCompleteOptions(Server server, CommandSource sender, String commandLabel, String[] args) {
if (args.length == 1) {
return new ArrayList<>(ConfigurateUtil.getKeys(ess.getKits().getKits()));
return new ArrayList<>(ess.getKits().getKitKeys());
} else if (args.length == 2 && sender.isAuthorized("essentials.kitreset.others", ess)) {
return getPlayers(server, sender);
} else {
@@ -152,7 +152,19 @@ public class Commandmail extends EssentialsCommand {
if (!user.isAuthorized("essentials.mail.sendall")) {
throw new Exception(tl("noPerm", "essentials.mail.sendall"));
}
ess.runTaskAsynchronously(new SendAll(user, FormatUtil.formatMessage(user, "essentials.mail", StringUtil.sanitizeString(FormatUtil.stripFormat(getFinalArg(args, 1))))));
ess.runTaskAsynchronously(new SendAll(user,
FormatUtil.formatMessage(user, "essentials.mail",
StringUtil.sanitizeString(FormatUtil.stripFormat(getFinalArg(args, 1)))), 0));
user.sendMessage(tl("mailSent"));
return;
}
if (args.length >= 3 && "sendtempall".equalsIgnoreCase(args[0])) {
if (!user.isAuthorized("essentials.mail.sendtempall")) {
throw new Exception(tl("noPerm", "essentials.mail.sendtempall"));
}
ess.runTaskAsynchronously(new SendAll(user,
FormatUtil.formatMessage(user, "essentials.mail",
StringUtil.sanitizeString(FormatUtil.stripFormat(getFinalArg(args, 2)))), DateUtil.parseDateDiff(args[1], true)));
user.sendMessage(tl("mailSent"));
return;
}
@@ -213,7 +225,12 @@ public class Commandmail extends EssentialsCommand {
sender.sendMessage(tl("mailSent"));
return;
} else if (args.length >= 2 && "sendall".equalsIgnoreCase(args[0])) {
ess.runTaskAsynchronously(new SendAll(Console.getInstance(), FormatUtil.replaceFormat(getFinalArg(args, 1))));
ess.runTaskAsynchronously(new SendAll(Console.getInstance(), FormatUtil.replaceFormat(getFinalArg(args, 1)), 0));
sender.sendMessage(tl("mailSent"));
return;
} else if (args.length >= 3 && "sendtempall".equalsIgnoreCase(args[0])) {
final long dateDiff = DateUtil.parseDateDiff(args[1], true);
ess.runTaskAsynchronously(new SendAll(Console.getInstance(), FormatUtil.replaceFormat(getFinalArg(args, 2)), dateDiff));
sender.sendMessage(tl("mailSent"));
return;
} else if (args.length >= 2) {
@@ -232,12 +249,14 @@ public class Commandmail extends EssentialsCommand {
}
private class SendAll implements Runnable {
IMessageRecipient messageRecipient;
String message;
private final IMessageRecipient messageRecipient;
private final String message;
private final long dateDiff;
SendAll(IMessageRecipient messageRecipient, String message) {
SendAll(IMessageRecipient messageRecipient, String message, long dateDiff) {
this.messageRecipient = messageRecipient;
this.message = message;
this.dateDiff = dateDiff;
}
@Override
@@ -245,7 +264,7 @@ public class Commandmail extends EssentialsCommand {
for (UUID userid : ess.getUserMap().getAllUniqueUsers()) {
final User user = ess.getUserMap().getUser(userid);
if (user != null) {
user.sendMail(messageRecipient, message);
user.sendMail(messageRecipient, message, dateDiff);
}
}
}
@@ -264,38 +283,47 @@ public class Commandmail extends EssentialsCommand {
if (user.isAuthorized("essentials.mail.sendall")) {
options.add("sendall");
}
if (user.isAuthorized("essentials.mail.sendtempall")) {
options.add("sendtempall");
}
return options;
} else if (args.length == 2 && ((args[0].equalsIgnoreCase("send") && user.isAuthorized("essentials.mail.send")) || (args[0].equalsIgnoreCase("sendtemp") && user.isAuthorized("essentials.mail.sendtemp")))) {
return getPlayers(server, user);
} else if (args.length == 2 && args[0].equalsIgnoreCase("read")) {
final ArrayList<MailMessage> mail = user.getMailMessages();
final int pages = mail != null ? (mail.size() / 9 + (mail.size() % 9 > 0 ? 1 : 0)) : 0;
if (pages == 0) {
return Lists.newArrayList("0");
} else {
final List<String> options = Lists.newArrayList("1");
if (pages > 1) {
options.add(String.valueOf(pages));
} else if (args.length == 2) {
if ((args[0].equalsIgnoreCase("send") && user.isAuthorized("essentials.mail.send")) || (args[0].equalsIgnoreCase("sendtemp") && user.isAuthorized("essentials.mail.sendtemp"))) {
return getPlayers(server, user);
} else if (args[0].equalsIgnoreCase("sendtempall") && user.isAuthorized("essentials.mail.sendtempall")) {
return COMMON_DATE_DIFFS;
} else if (args[0].equalsIgnoreCase("read")) {
final ArrayList<MailMessage> mail = user.getMailMessages();
final int pages = mail != null ? (mail.size() / 9 + (mail.size() % 9 > 0 ? 1 : 0)) : 0;
if (pages == 0) {
return Lists.newArrayList("0");
} else {
final List<String> options = Lists.newArrayList("1");
if (pages > 1) {
options.add(String.valueOf(pages));
}
return options;
}
return options;
}
} else if (args.length == 3 && args[0].equalsIgnoreCase("sendtemp") && user.isAuthorized("essentials.mail.sendtemp")) {
return COMMON_DATE_DIFFS;
} else {
return Collections.emptyList();
}
return Collections.emptyList();
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
if (args.length == 1) {
return Lists.newArrayList("send", "sendall");
} else if (args.length == 2 && (args[0].equalsIgnoreCase("send") || args[0].equalsIgnoreCase("sendtemp"))) {
return getPlayers(server, sender);
return Lists.newArrayList("send", "sendall", "sendtemp", "sendtempall");
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("send") || args[0].equalsIgnoreCase("sendtemp")) {
return getPlayers(server, sender);
} else if (args[0].equalsIgnoreCase("sendtempall")) {
return COMMON_DATE_DIFFS;
}
} else if (args.length == 3 && args[0].equalsIgnoreCase("sendtemp")) {
return COMMON_DATE_DIFFS;
} else {
return Collections.emptyList();
}
return Collections.emptyList();
}
}
@@ -4,6 +4,7 @@ import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.FormatUtil;
import net.essentialsx.api.v2.events.UserActionEvent;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
@@ -44,6 +45,7 @@ public class Commandme extends EssentialsCommand {
final String toSend = tl("action", user.getDisplayName(), message);
if (radius < 1) {
ess.broadcastMessage(user, toSend);
ess.getServer().getPluginManager().callEvent(new UserActionEvent(user, message, Collections.unmodifiableCollection(ess.getServer().getOnlinePlayers())));
return;
}
radius *= radius;
@@ -86,6 +88,7 @@ public class Commandme extends EssentialsCommand {
for (final Player onlinePlayer : outList) {
onlinePlayer.sendMessage(toSend);
}
ess.getServer().getPluginManager().callEvent(new UserActionEvent(user, message, Collections.unmodifiableCollection(outList)));
}
@Override
@@ -113,7 +113,7 @@ public class Commandmute extends EssentialsCommand {
message = tl("muteNotifyReason", sender.getSender().getName(), user.getName(), user.getMuteReason());
}
}
server.getLogger().log(Level.INFO, message);
ess.getLogger().log(Level.INFO, message);
ess.broadcastMessage("essentials.mute.notify", message);
} else {
sender.sendMessage(tl("unmutedPlayer", user.getDisplayName()));
@@ -3,7 +3,6 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.google.common.collect.Lists;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
@@ -109,7 +108,7 @@ public class Commandnear extends EssentialsCommand {
if (nearbyPlayer == null) {
continue;
}
output.append(nearbyPlayer.getDisplayName()).append(ChatColor.WHITE + "(" + ChatColor.RED).append((long) nearbyPlayer.getLocation().distance(loc)).append("m" + ChatColor.WHITE + ")");
output.append(tl("nearbyPlayersList", nearbyPlayer.getDisplayName(), (long)nearbyPlayer.getLocation().distance(loc)));
}
return output.length() > 1 ? output.toString() : tl("none");
@@ -24,9 +24,6 @@ public class Commandnick extends EssentialsLoopCommand {
if (args.length < 1) {
throw new NotEnoughArgumentsException();
}
if (!ess.getSettings().changeDisplayName()) {
throw new Exception(tl("nickDisplayName"));
}
if (args.length > 1 && user.isAuthorized("essentials.nick.others")) {
loopOfflinePlayers(server, user.getSource(), false, true, args[0], formatNickname(user, args[1]).split(" "));
@@ -41,9 +38,6 @@ public class Commandnick extends EssentialsLoopCommand {
if (args.length < 2) {
throw new NotEnoughArgumentsException();
}
if (!ess.getSettings().changeDisplayName()) {
throw new Exception(tl("nickDisplayName"));
}
loopOfflinePlayers(server, sender, false, true, args[0], formatNickname(null, args[1]).split(" "));
sender.sendMessage(tl("nickChanged"));
}
@@ -59,12 +53,12 @@ public class Commandnick extends EssentialsLoopCommand {
if (!target.getDisplayName().equalsIgnoreCase(target.getDisplayName())) {
target.sendMessage(tl("nickNoMore"));
}
target.sendMessage(tl("nickSet", target.getDisplayName()));
target.sendMessage(tl("nickSet", ess.getSettings().changeDisplayName() ? target.getDisplayName() : nick));
} else if (nickInUse(target, nick)) {
throw new NotEnoughArgumentsException(tl("nickInUse"));
} else {
setNickname(server, sender, target, nick);
target.sendMessage(tl("nickSet", target.getDisplayName()));
target.sendMessage(tl("nickSet", ess.getSettings().changeDisplayName() ? target.getDisplayName() : nick));
}
}
@@ -76,7 +70,7 @@ public class Commandnick extends EssentialsLoopCommand {
throw new Exception(tl("nickTooLong"));
} else if (FormatUtil.stripFormat(newNick).length() < 1) {
throw new Exception(tl("nickNamesAlpha"));
} else if (user != null && user.isAuthorized("essentials.nick.changecolors") && !user.isAuthorized("essentials.nick.changecolors.bypass") && !FormatUtil.stripFormat(newNick).equals(user.getName())) {
} else if (user != null && user.isAuthorized("essentials.nick.changecolors") && !user.isAuthorized("essentials.nick.changecolors.bypass") && !FormatUtil.stripFormat(newNick).equals(user.getName()) && !nick.equalsIgnoreCase("off")) {
throw new Exception(tl("nickNamesOnlyColorChanges"));
} else if (user != null && !user.isAuthorized("essentials.nick.blacklist.bypass") && isNickBanned(newNick)) {
throw new Exception(tl("nickNameBlacklist", nick));
@@ -0,0 +1,73 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IUser;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.Statistic;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandplaytime extends EssentialsCommand {
// For some reason, in 1.13 PLAY_ONE_MINUTE = ticks played = what used to be PLAY_ONE_TICK
// https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/b848d8ce633871b52115247b089029749c02f579
private static final Statistic PLAY_ONE_TICK = EnumUtil.getStatistic("PLAY_ONE_MINUTE", "PLAY_ONE_TICK");
public Commandplaytime() {
super("playtime");
}
@Override
protected void run(Server server, CommandSource sender, String commandLabel, String[] args) throws Exception {
String displayName;
long playtime;
final String key;
if (args.length > 0 && sender.isAuthorized("essentials.playtime.others", ess)) {
try {
final IUser user = getPlayer(server, sender, args, 0);
displayName = user.getDisplayName();
playtime = user.getBase().getStatistic(PLAY_ONE_TICK);
} catch (PlayerNotFoundException e) {
// The ability to get the statistics of offline players is only available in 1.15.2+
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_15_2_R01)) {
throw e;
}
final User user = getPlayer(server, args, 0, true, true);
displayName = user.getName(); // Vanished players will have their name as their display name
playtime = Bukkit.getOfflinePlayer(user.getBase().getUniqueId()).getStatistic(PLAY_ONE_TICK);
if (user.getBase().isOnline() && user.isVanished()) {
playtime = playtime - ((System.currentTimeMillis() - user.getLastVanishTime()) / 50L);
}
}
key = "playtimeOther";
} else if (sender.isPlayer()) {
//noinspection ConstantConditions
displayName = sender.getPlayer().getDisplayName();
playtime = sender.getPlayer().getStatistic(PLAY_ONE_TICK);
key = "playtime";
} else {
throw new NotEnoughArgumentsException();
}
final long playtimeMs = System.currentTimeMillis() - (playtime * 50L);
sender.sendMessage(tl(key, DateUtil.formatDateDiff(playtimeMs), displayName));
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
if (args.length == 1 && sender.isAuthorized("essentials.playtime.others", ess)) {
return getPlayers(server, sender);
} else {
return Collections.emptyList();
}
}
}
@@ -4,8 +4,8 @@ import com.earth2me.essentials.MetaItemStack;
import com.earth2me.essentials.Potions;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists;
import net.ess3.nms.refl.ReflUtil;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.ItemStack;
@@ -42,7 +42,7 @@ public class Commandpotion extends EssentialsCommand {
}
boolean holdingPotion = stack.getType() == Material.POTION;
if (!holdingPotion && ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_9_R1)) {
if (!holdingPotion && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01)) {
holdingPotion = stack.getType() == Material.SPLASH_POTION || stack.getType() == Material.LINGERING_POTION;
}
if (holdingPotion) {
@@ -117,7 +117,7 @@ public class Commandrecipe extends EssentialsCommand {
if (item == null) {
continue;
}
if (item.getDurability() == Short.MAX_VALUE) {
if (VersionUtil.PRE_FLATTENING && item.getDurability() == Short.MAX_VALUE) {
item.setDurability((short) 0);
}
view.getTopInventory().setItem(j * 3 + k + 1, item);
@@ -159,7 +159,7 @@ public class Commandrecipe extends EssentialsCommand {
final InventoryView view = user.getBase().openWorkbench(null, true);
for (int i = 0; i < ingredients.size(); i++) {
final ItemStack item = ingredients.get(i);
if (item.getDurability() == Short.MAX_VALUE) {
if (VersionUtil.PRE_FLATTENING && item.getDurability() == Short.MAX_VALUE) {
item.setDurability((short) 0);
}
view.setItem(i + 1, item);
@@ -3,6 +3,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists;
@@ -39,7 +40,7 @@ public class Commandrepair extends EssentialsCommand {
public void repairHand(final User user) throws Exception {
final ItemStack item = user.getItemInHand();
if (item == null || item.getType().isBlock() || item.getDurability() == 0) {
if (item == null || item.getType().isBlock() || MaterialUtil.getDamage(item) == 0) {
throw new Exception(tl("repairInvalidType"));
}
@@ -81,16 +82,16 @@ public class Commandrepair extends EssentialsCommand {
throw new Exception(tl("repairInvalidType"));
}
if (item.getDurability() == 0) {
if (MaterialUtil.getDamage(item) == 0) {
throw new Exception(tl("repairAlreadyFixed"));
}
item.setDurability((short) 0);
MaterialUtil.setDamage(item, 0);
}
private void repairItems(final ItemStack[] items, final IUser user, final List<String> repaired) throws Exception {
private void repairItems(final ItemStack[] items, final IUser user, final List<String> repaired) {
for (final ItemStack item : items) {
if (item == null || item.getType().isBlock() || item.getDurability() == 0) {
if (item == null || item.getType().isBlock() || MaterialUtil.getDamage(item) == 0) {
continue;
}
@@ -123,7 +124,7 @@ public class Commandrepair extends EssentialsCommand {
private Trade getCharge(final Material material) {
final String itemName = material.toString().toLowerCase(Locale.ENGLISH);
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01)) {
if (VersionUtil.PRE_FLATTENING) {
final int itemId = material.getId();
return new Trade("repair-" + itemName.replace('_', '-'), new Trade("repair-" + itemId, new Trade("repair-item", ess), ess), ess);
} else {
@@ -19,7 +19,7 @@ public class Commandrest extends EssentialsLoopCommand {
@Override
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01)) {
if (VersionUtil.PRE_FLATTENING) {
sender.sendMessage(tl("unsupportedFeature"));
return;
}
@@ -102,13 +102,16 @@ public class Commandseen extends EssentialsCommand {
user.setDisplayNick();
sender.sendMessage(tl("seenOnline", user.getDisplayName(), DateUtil.formatDateDiff(user.getLastLogin())));
sender.sendMessage(tl("whoisUuid", user.getBase().getUniqueId().toString()));
final List<String> history = ess.getUserMap().getUserHistory(user.getBase().getUniqueId());
if (history != null && history.size() > 1) {
sender.sendMessage(tl("seenAccounts", StringUtil.joinListSkip(", ", user.getName(), history)));
}
if (sender.isAuthorized("essentials.seen.uuid", ess)) {
sender.sendMessage(tl("whoisUuid", user.getBase().getUniqueId().toString()));
}
if (user.isAfk()) {
sender.sendMessage(tl("whoisAFK", tl("true")));
}
@@ -136,16 +139,18 @@ public class Commandseen extends EssentialsCommand {
user.setDisplayNick();
if (user.getLastLogout() > 0) {
sender.sendMessage(tl("seenOffline", user.getName(), DateUtil.formatDateDiff(user.getLastLogout())));
sender.sendMessage(tl("whoisUuid", user.getBase().getUniqueId()));
final List<String> history = ess.getUserMap().getUserHistory(user.getBase().getUniqueId());
if (history != null && history.size() > 1) {
sender.sendMessage(tl("seenAccounts", StringUtil.joinListSkip(", ", user.getName(), history)));
}
if (sender.isAuthorized("essentials.seen.uuid", ess)) {
sender.sendMessage(tl("whoisUuid", user.getBase().getUniqueId()));
}
} else {
sender.sendMessage(tl("userUnknown", user.getName()));
}
final List<String> history = ess.getUserMap().getUserHistory(user.getBase().getUniqueId());
if (history != null && history.size() > 1) {
sender.sendMessage(tl("seenAccounts", StringUtil.joinListSkip(", ", user.getName(), history)));
}
if (BanLookup.isBanned(ess, user)) {
final BanEntry banEntry = BanLookup.getBanEntry(ess, user.getName());
final String reason = showBan ? banEntry.getReason() : tl("true");
@@ -117,7 +117,7 @@ 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);
user.sendMessage(tl("itemSold", NumberUtil.displayCurrency(result, ess), amount, is.getType().toString().toLowerCase(Locale.ENGLISH), NumberUtil.displayCurrency(worth, ess)));
logger.log(Level.INFO, tl("itemSoldConsole", user.getName(), is.getType().toString().toLowerCase(Locale.ENGLISH), NumberUtil.displayCurrency(result, ess), amount, NumberUtil.displayCurrency(worth, ess), user.getDisplayName()));
ess.getLogger().log(Level.INFO, tl("itemSoldConsole", user.getName(), is.getType().toString().toLowerCase(Locale.ENGLISH), NumberUtil.displayCurrency(result, ess), amount, NumberUtil.displayCurrency(worth, ess), user.getDisplayName()));
return result;
}
@@ -51,7 +51,7 @@ public class Commandsethome extends EssentialsCommand {
}
final Location location = user.getLocation();
if (!ess.getSettings().isTeleportSafetyEnabled() && LocationUtil.isBlockUnsafeForUser(usersHome, location.getWorld(), location.getBlockX(), location.getBlockY(), location.getBlockZ())) {
if ((!ess.getSettings().isTeleportSafetyEnabled() || !ess.getSettings().isForceDisableTeleportSafety()) && LocationUtil.isBlockUnsafeForUser(ess, usersHome, location.getWorld(), location.getBlockX(), location.getBlockY(), location.getBlockZ())) {
throw new Exception(tl("unsafeTeleportDestination", location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()));
}
@@ -2,7 +2,6 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.Kit;
import com.earth2me.essentials.User;
import com.earth2me.essentials.config.ConfigurateUtil;
import org.bukkit.Server;
import java.util.ArrayList;
@@ -34,7 +33,7 @@ public class Commandshowkit extends EssentialsCommand {
@Override
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
if (args.length == 1) {
return new ArrayList<>(ConfigurateUtil.getKeys(ess.getKits().getKits())); // TODO: Move this to its own method
return new ArrayList<>(ess.getKits().getKitKeys()); // TODO: Move this to its own method
} else {
return Collections.emptyList();
}
@@ -42,7 +42,7 @@ public class Commandskull extends EssentialsCommand {
final SkullMeta metaSkull;
boolean spawn = false;
if (itemSkull != null && MaterialUtil.isPlayerHead(itemSkull.getType(), itemSkull.getDurability())) {
if (itemSkull != null && MaterialUtil.isPlayerHead(itemSkull)) {
metaSkull = (SkullMeta) itemSkull.getItemMeta();
} else if (user.isAuthorized("essentials.skull.spawn")) {
itemSkull = new ItemStack(SKULL_ITEM, 1, (byte) 3);
@@ -54,7 +54,7 @@ public class Commandtempban extends EssentialsCommand {
user.getBase().kickPlayer(tl("tempBanned", expiry, senderDisplayName, banReason));
final String message = tl("playerTempBanned", senderDisplayName, user.getName(), expiry, banReason);
server.getLogger().log(Level.INFO, message);
ess.getLogger().log(Level.INFO, message);
ess.broadcastMessage("essentials.ban.notify", message);
}
@@ -71,7 +71,7 @@ public class Commandtempbanip extends EssentialsCommand {
final String message = tl("playerTempBanIpAddress", senderDisplayName, ipAddress,
DateUtil.formatDateDiff(banTimestamp), banReason);
server.getLogger().log(Level.INFO, message);
ess.getLogger().log(Level.INFO, message);
ess.broadcastMessage("essentials.banip.notify", message);
}
@@ -15,6 +15,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tl;
@@ -84,6 +85,10 @@ public class Commandtogglejail extends EssentialsCommand {
player.setOnlineJailedTime(ess.getSettings().isJailOnlineTime() ? ((player.getBase().getStatistic(PLAY_ONE_TICK)) + (timeDiff / 50)) : 0);
}
sender.sendMessage(timeDiff > 0 ? tl("playerJailedFor", player.getName(), DateUtil.formatDateDiff(finalDisplayTime)) : tl("playerJailed", player.getName()));
final String notifyMessage = timeDiff > 0 ? tl("jailNotifyJailedFor", player.getName(), DateUtil.formatDateDiff(finalDisplayTime), sender.getSender().getName()) : tl("jailNotifyJailed", player.getName(), sender.getSender().getName());
ess.getLogger().log(Level.INFO, notifyMessage);
ess.broadcastMessage("essentials.jail.notify", notifyMessage);
}
});
if (player.getBase().isOnline()) {
@@ -107,6 +112,10 @@ public class Commandtogglejail extends EssentialsCommand {
player.setJailTimeout(timeDiff);
player.setOnlineJailedTime(ess.getSettings().isJailOnlineTime() ? ((player.getBase().getStatistic(PLAY_ONE_TICK)) + (timeDiff / 50)) : 0);
sender.sendMessage(tl("jailSentenceExtended", DateUtil.formatDateDiff(displayTimeDiff)));
final String notifyMessage = tl("jailNotifySentenceExtended", player.getName(), DateUtil.formatDateDiff(displayTimeDiff), sender.getSender().getName());
ess.getLogger().log(Level.INFO, notifyMessage);
ess.broadcastMessage("essentials.jail.notify", notifyMessage);
return;
}
@@ -22,13 +22,14 @@ 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 loc = LocationUtil.getSafeDestination(new Location(user.getWorld(), topX, user.getWorld().getMaxHeight(), topZ, yaw, pitch));
final Location unsafe = new Location(user.getWorld(), topX, ess.getWorldInfoProvider().getMaxHeight(user.getWorld()), topZ, yaw, pitch);
final Location safe = LocationUtil.getSafeDestination(ess, unsafe);
final CompletableFuture<Boolean> future = new CompletableFuture<>();
future.thenAccept(success -> {
if (success) {
user.sendMessage(tl("teleportTop", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
user.sendMessage(tl("teleportTop", safe.getWorld().getName(), safe.getBlockX(), safe.getBlockY(), safe.getBlockZ()));
}
});
user.getAsyncTeleport().teleport(loc, new Trade(this.getName(), ess), TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
user.getAsyncTeleport().teleport(safe, new Trade(this.getName(), ess), TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
}
}
@@ -37,11 +37,12 @@ public class Commandtpa extends EssentialsCommand {
if (user.getWorld() != player.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + player.getWorld().getName())) {
throw new Exception(tl("noPerm", "essentials.worlds." + player.getWorld().getName()));
}
// Don't let sender request teleport twice to the same player.
if (user.getConfigUUID().equals(player.getTeleportRequest()) && player.hasOutstandingTeleportRequest() // Check timeout
&& !player.isTpRequestHere()) { // Make sure the last teleport request was actually tpa and not tpahere
if (player.hasOutstandingTpaRequest(user.getName(), false)) {
throw new Exception(tl("requestSentAlready", player.getDisplayName()));
}
if (player.isAutoTeleportEnabled() && !player.isIgnoredPlayer(user)) {
final Trade charge = new Trade(this.getName(), ess);
final AsyncTeleport teleport = user.getAsyncTeleport();
@@ -54,7 +55,7 @@ public class Commandtpa extends EssentialsCommand {
user.sendMessage(tl("requestAcceptedFromAuto", player.getDisplayName()));
}
});
return;
throw new NoChargeException();
}
if (!player.isIgnoredPlayer(user)) {
@@ -71,6 +72,7 @@ public class Commandtpa extends EssentialsCommand {
player.sendMessage(tl("teleportRequestTimeoutInfo", ess.getSettings().getTpaAcceptCancellation()));
}
}
user.sendMessage(tl("requestSent", player.getDisplayName()));
if (user.isAuthorized("essentials.tpacancel")) {
user.sendMessage(tl("typeTpacancel"));
@@ -19,17 +19,17 @@ public class Commandtpaall extends EssentialsCommand {
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 1) {
if (sender.isPlayer()) {
teleportAAllPlayers(server, sender, ess.getUser(sender.getPlayer()));
tpaAll(sender, ess.getUser(sender.getPlayer()));
return;
}
throw new NotEnoughArgumentsException();
}
final User target = getPlayer(server, sender, args, 0);
teleportAAllPlayers(server, sender, target);
tpaAll(sender, target);
}
private void teleportAAllPlayers(final Server server, final CommandSource sender, final User target) {
private void tpaAll(final CommandSource sender, final User target) {
sender.sendMessage(tl("teleportAAll"));
for (final User player : ess.getOnlineUsers()) {
if (target == player) {
@@ -41,6 +41,7 @@ public class Commandtpaall extends EssentialsCommand {
if (sender.getSender().equals(target.getBase()) && target.getWorld() != player.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !target.isAuthorized("essentials.worlds." + target.getWorld().getName())) {
continue;
}
try {
final TPARequestEvent tpaEvent = new TPARequestEvent(sender, player, true);
ess.getServer().getPluginManager().callEvent(tpaEvent);
@@ -1,7 +1,6 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import org.bukkit.Server;
import static com.earth2me.essentials.I18n.tl;
@@ -15,20 +14,12 @@ public class Commandtpacancel extends EssentialsCommand {
/**
* Cancel {@link User}'s tp request if its {@code requester} is equal to the given {@code requester}.
*
* @param ess ess instance
* @param user user holding tp request
* @param requester tp requester
* @return whether tp was cancelled
*/
public static boolean cancelTeleportRequest(final IEssentials ess, final User user, final User requester) throws Exception {
if (user.getTeleportRequest() != null) {
final User userRequester = ess.getUser(user.getTeleportRequest());
if (requester.equals(userRequester)) {
user.requestTeleport(null, false);
return true;
}
}
return false;
public static boolean cancelTeleportRequest(final User user, final User requester) {
return user.removeTpaRequest(requester.getName()) != null;
}
@Override
@@ -37,7 +28,7 @@ public class Commandtpacancel extends EssentialsCommand {
int cancellations = 0;
for (final User onlineUser : ess.getOnlineUsers()) {
if (onlineUser == user) continue;
if (cancelTeleportRequest(ess, onlineUser, user)) {
if (cancelTeleportRequest(onlineUser, user)) {
cancellations++;
}
}
@@ -48,7 +39,7 @@ public class Commandtpacancel extends EssentialsCommand {
}
} else {
final User targetPlayer = getPlayer(server, user, args, 0);
if (cancelTeleportRequest(ess, targetPlayer, user)) {
if (cancelTeleportRequest(targetPlayer, user)) {
user.sendMessage(tl("teleportRequestSpecificCancelled", targetPlayer.getName()));
}
}
@@ -1,12 +1,18 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.AsyncTeleport;
import com.earth2me.essentials.IUser;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import net.essentialsx.api.v2.events.TeleportRequestResponseEvent;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static com.earth2me.essentials.I18n.tl;
@@ -18,36 +24,87 @@ public class Commandtpaccept extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final User requester;
try {
requester = ess.getUser(user.getTeleportRequest());
} catch (final Exception ex) {
final boolean acceptAll;
if (args.length > 0) {
acceptAll = args[0].equals("*") || args[0].equalsIgnoreCase("all");
} else {
acceptAll = false;
}
if (!user.hasPendingTpaRequests(true, acceptAll)) {
throw new Exception(tl("noPendingRequest"));
}
if (args.length > 0) {
if (acceptAll) {
acceptAllRequests(user, commandLabel);
throw new NoChargeException();
}
user.sendMessage(tl("requestAccepted"));
handleTeleport(user, user.getOutstandingTpaRequest(getPlayer(server, user, args, 0).getName(), true), commandLabel);
} else {
user.sendMessage(tl("requestAccepted"));
handleTeleport(user, user.getNextTpaRequest(true, false, false), commandLabel);
}
throw new NoChargeException();
}
private void acceptAllRequests(final User user, final String commandLabel) throws Exception {
IUser.TpaRequest request;
int count = 0;
while ((request = user.getNextTpaRequest(true, true, true)) != null) {
try {
handleTeleport(user, request, commandLabel);
count++;
} catch (Exception e) {
ess.showError(user.getSource(), e, commandLabel);
} finally {
user.removeTpaRequest(request.getName());
}
}
user.sendMessage(tl("requestAcceptedAll", count));
}
@Override
protected List<String> getTabCompleteOptions(Server server, User user, String commandLabel, String[] args) {
if (args.length == 1) {
final List<String> options = new ArrayList<>(user.getPendingTpaKeys());
options.add("*");
return options;
} else {
return Collections.emptyList();
}
}
private void handleTeleport(final User user, final IUser.TpaRequest request, String commandLabel) throws Exception {
if (request == null) {
throw new Exception(tl("noPendingRequest"));
}
final User requester = ess.getUser(request.getRequesterUuid());
if (!requester.getBase().isOnline()) {
user.removeTpaRequest(request.getName());
throw new Exception(tl("noPendingRequest"));
}
if (user.isTpRequestHere() && ((!requester.isAuthorized("essentials.tpahere") && !requester.isAuthorized("essentials.tpaall")) || (user.getWorld() != requester.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + user.getWorld().getName())))) {
if (request.isHere() && ((!requester.isAuthorized("essentials.tpahere") && !requester.isAuthorized("essentials.tpaall")) || (user.getWorld() != requester.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + user.getWorld().getName())))) {
throw new Exception(tl("noPendingRequest"));
}
if (!user.isTpRequestHere() && (!requester.isAuthorized("essentials.tpa") || (user.getWorld() != requester.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + requester.getWorld().getName())))) {
if (!request.isHere() && (!requester.isAuthorized("essentials.tpa") || (user.getWorld() != requester.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + requester.getWorld().getName())))) {
throw new Exception(tl("noPendingRequest"));
}
if (args.length > 0 && !requester.getName().contains(args[0])) {
throw new Exception(tl("noPendingRequest"));
}
if (!user.hasOutstandingTeleportRequest()) {
user.requestTeleport(null, false);
throw new Exception(tl("requestTimedOut"));
final TeleportRequestResponseEvent event = new TeleportRequestResponseEvent(user, requester, request, true);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("TPA accept cancelled by API for " + user.getName() + " (requested by " + requester.getName() + ")");
}
return;
}
final Trade charge = new Trade(this.getName(), ess);
user.sendMessage(tl("requestAccepted"));
requester.sendMessage(tl("requestAcceptedFrom", user.getDisplayName()));
final CompletableFuture<Boolean> future = getNewExceptionFuture(requester.getSource(), commandLabel);
@@ -55,8 +112,8 @@ public class Commandtpaccept extends EssentialsCommand {
user.sendMessage(tl("pendingTeleportCancelled"));
return false;
});
if (user.isTpRequestHere()) {
final Location loc = user.getTpRequestLocation();
if (request.isHere()) {
final Location loc = request.getLocation();
final AsyncTeleport teleport = requester.getAsyncTeleport();
teleport.setTpType(AsyncTeleport.TeleportType.TPA);
future.thenAccept(success -> {
@@ -64,14 +121,12 @@ public class Commandtpaccept extends EssentialsCommand {
requester.sendMessage(tl("teleporting", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
}
});
teleport.teleportPlayer(user, user.getTpRequestLocation(), charge, TeleportCause.COMMAND, future);
teleport.teleportPlayer(user, loc, charge, TeleportCause.COMMAND, future);
} else {
final AsyncTeleport teleport = requester.getAsyncTeleport();
teleport.setTpType(AsyncTeleport.TeleportType.TPA);
teleport.teleport(user.getBase(), charge, TeleportCause.COMMAND, future);
}
user.requestTeleport(null, false);
throw new NoChargeException();
user.removeTpaRequest(request.getName());
}
}
@@ -33,11 +33,12 @@ public class Commandtpahere extends EssentialsCommand {
if (user.getWorld() != player.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + user.getWorld().getName())) {
throw new Exception(tl("noPerm", "essentials.worlds." + user.getWorld().getName()));
}
// Don't let sender request teleport twice to the same player.
if (user.getConfigUUID().equals(player.getTeleportRequest()) && player.hasOutstandingTeleportRequest() // Check timeout
&& player.isTpRequestHere()) { // Make sure the last teleport request was actually tpahere and not tpa
if (player.hasOutstandingTpaRequest(user.getName(), true)) {
throw new Exception(tl("requestSentAlready", player.getDisplayName()));
}
if (!player.isIgnoredPlayer(user)) {
final TPARequestEvent tpaEvent = new TPARequestEvent(user.getSource(), player, true);
ess.getServer().getPluginManager().callEvent(tpaEvent);
@@ -1,8 +1,15 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.IUser;
import com.earth2me.essentials.User;
import net.essentialsx.api.v2.events.TeleportRequestResponseEvent;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandtpdeny extends EssentialsCommand {
@@ -12,16 +19,84 @@ public class Commandtpdeny extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
if (user.getTeleportRequest() == null) {
final boolean denyAll;
if (args.length > 0) {
denyAll = args[0].equals("*") || args[0].equalsIgnoreCase("all");
} else {
denyAll = false;
}
if (!user.hasPendingTpaRequests(false, false)) {
throw new Exception(tl("noPendingRequest"));
}
final User player = ess.getUser(user.getTeleportRequest());
if (player == null) {
final IUser.TpaRequest denyRequest;
if (args.length > 0) {
if (denyAll) {
denyAllRequests(user);
return;
}
denyRequest = user.getOutstandingTpaRequest(getPlayer(server, user, args, 0).getName(), false);
} else {
denyRequest = user.getNextTpaRequest(false, true, false);
}
if (denyRequest == null) {
throw new Exception(tl("noPendingRequest"));
}
final User player = ess.getUser(denyRequest.getRequesterUuid());
if (player == null || !player.getBase().isOnline()) {
throw new Exception(tl("noPendingRequest"));
}
if (sendEvent(user, player, denyRequest)) {
return;
}
user.sendMessage(tl("requestDenied"));
player.sendMessage(tl("requestDeniedFrom", user.getDisplayName()));
user.requestTeleport(null, false);
user.removeTpaRequest(denyRequest.getName());
}
private void denyAllRequests(User user) {
IUser.TpaRequest request;
int count = 0;
while ((request = user.getNextTpaRequest(false, true, false)) != null) {
final User player = ess.getUser(request.getRequesterUuid());
if (sendEvent(user, player, request)) {
continue;
}
if (player != null && player.getBase().isOnline()) {
player.sendMessage(tl("requestDeniedFrom", user.getDisplayName()));
}
user.removeTpaRequest(request.getName());
count++;
}
user.sendMessage(tl("requestDeniedAll", count));
}
private boolean sendEvent(User user, User player, IUser.TpaRequest request) {
final TeleportRequestResponseEvent event = new TeleportRequestResponseEvent(user, player, request, false);
Bukkit.getPluginManager().callEvent(event);
final boolean cancelled = event.isCancelled();
if (cancelled && ess.getSettings().isDebug()) {
ess.getLogger().info("TPA deny cancelled by API for " + user.getName() + " (requested by " + player.getName() + ")");
}
return event.isCancelled();
}
@Override
protected List<String> getTabCompleteOptions(Server server, User user, String commandLabel, String[] args) {
if (args.length == 1) {
final List<String> options = new ArrayList<>(user.getPendingTpaKeys());
options.add("*");
return options;
} else {
return Collections.emptyList();
}
}
}
@@ -26,9 +26,9 @@ public class Commandtppos extends EssentialsCommand {
throw new NotEnoughArgumentsException();
}
final double x = args[0].startsWith("~") ? user.getLocation().getX() + (args[0].length() > 1 ? Integer.parseInt(args[0].substring(1)) : 0) : Integer.parseInt(args[0]);
final double y = args[1].startsWith("~") ? user.getLocation().getY() + (args[1].length() > 1 ? Integer.parseInt(args[1].substring(1)) : 0) : Integer.parseInt(args[1]);
final double z = args[2].startsWith("~") ? user.getLocation().getZ() + (args[2].length() > 1 ? Integer.parseInt(args[2].substring(1)) : 0) : Integer.parseInt(args[2]);
final double x = args[0].startsWith("~") ? user.getLocation().getX() + (args[0].length() > 1 ? Double.parseDouble(args[0].substring(1)) : 0) : Double.parseDouble(args[0]);
final double y = args[1].startsWith("~") ? user.getLocation().getY() + (args[1].length() > 1 ? Double.parseDouble(args[1].substring(1)) : 0) : Double.parseDouble(args[1]);
final double z = args[2].startsWith("~") ? user.getLocation().getZ() + (args[2].length() > 1 ? Double.parseDouble(args[2].substring(1)) : 0) : Double.parseDouble(args[2]);
final Location loc = new Location(user.getWorld(), x, y, z, user.getLocation().getYaw(), user.getLocation().getPitch());
if (args.length == 4) {
final World w = ess.getWorld(args[3]);
@@ -38,7 +38,7 @@ public class Commandtree extends EssentialsCommand {
}
}
final Location loc = LocationUtil.getTarget(user.getBase()).add(0, 1, 0);
final Location loc = LocationUtil.getTarget(user.getBase(), ess.getSettings().getMaxTreeCommandRange()).add(0, 1, 0);
if (loc.getBlock().getType().isSolid()) {
throw new Exception(tl("treeFailure"));
}
@@ -37,7 +37,7 @@ public class Commandunban extends EssentialsCommand {
}
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.DISPLAY_NAME;
server.getLogger().log(Level.INFO, tl("playerUnbanned", senderDisplayName, name));
ess.getLogger().log(Level.INFO, tl("playerUnbanned", senderDisplayName, name));
ess.broadcastMessage("essentials.ban.notify", tl("playerUnbanned", senderDisplayName, name));
}
@@ -40,7 +40,7 @@ public class Commandunbanip extends EssentialsCommand {
ess.getServer().getBanList(BanList.Type.IP).pardon(ipAddress);
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.DISPLAY_NAME;
server.getLogger().log(Level.INFO, tl("playerUnbanIpAddress", senderDisplayName, ipAddress));
ess.getLogger().log(Level.INFO, tl("playerUnbanIpAddress", senderDisplayName, ipAddress));
ess.broadcastMessage("essentials.banip.notify", tl("playerUnbanIpAddress", senderDisplayName, ipAddress));
}
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.google.common.collect.Lists;
import org.bukkit.Server;
@@ -87,7 +88,7 @@ public class Commandworth extends EssentialsCommand {
}
final BigDecimal result = worth.multiply(BigDecimal.valueOf(amount));
sender.sendMessage(is.getDurability() != 0 ? tl("worthMeta", is.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", ""), is.getDurability(), NumberUtil.displayCurrency(result, ess), amount, NumberUtil.displayCurrency(worth, ess)) : tl("worth", is.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", ""), NumberUtil.displayCurrency(result, ess), amount, NumberUtil.displayCurrency(worth, ess)));
sender.sendMessage(MaterialUtil.getDamage(is) != 0 ? tl("worthMeta", is.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", ""), MaterialUtil.getDamage(is), NumberUtil.displayCurrency(result, ess), amount, NumberUtil.displayCurrency(worth, ess)) : tl("worth", is.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", ""), NumberUtil.displayCurrency(result, ess), amount, NumberUtil.displayCurrency(worth, ess)));
return result;
}
@@ -26,14 +26,12 @@ import java.util.Map;
import java.util.MissingResourceException;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
public abstract class EssentialsCommand implements IEssentialsCommand {
protected static final Logger logger = Logger.getLogger("Essentials");
/**
* Common time durations (in seconds), for use in tab completion.
*/
@@ -112,11 +110,15 @@ public abstract class EssentialsCommand implements IEssentialsCommand {
// Get online players - only show vanished if source has permission
protected User getPlayer(final Server server, final CommandSource sender, final String[] args, final int pos) throws PlayerNotFoundException, NotEnoughArgumentsException {
return getPlayer(server, sender, args, pos, false);
}
protected User getPlayer(final Server server, final CommandSource sender, final String[] args, final int pos, final boolean getOffline) throws PlayerNotFoundException, NotEnoughArgumentsException {
if (sender.isPlayer()) {
final User user = ess.getUser(sender.getPlayer());
return getPlayer(server, user, args, pos);
return getPlayer(server, user, args, pos, getOffline);
}
return getPlayer(server, args, pos, true, false);
return getPlayer(server, args, pos, true, getOffline);
}
// Get online players - only show vanished if source has permission
@@ -130,7 +132,11 @@ public abstract class EssentialsCommand implements IEssentialsCommand {
// Get online players - only show vanished if source has permission
protected User getPlayer(final Server server, final User user, final String[] args, final int pos) throws PlayerNotFoundException, NotEnoughArgumentsException {
return getPlayer(server, user, args, pos, user.canInteractVanished(), false);
return getPlayer(server, user, args, pos, false);
}
protected User getPlayer(final Server server, final User user, final String[] args, final int pos, final boolean getOffline) throws PlayerNotFoundException, NotEnoughArgumentsException {
return getPlayer(server, user, args, pos, user.canInteractVanished(), getOffline);
}
// Get online or offline players, this method allows for raw access
@@ -326,7 +332,7 @@ public abstract class EssentialsCommand implements IEssentialsCommand {
public void showError(final CommandSender sender, final Throwable throwable, final String commandLabel) {
sender.sendMessage(tl("errorWithMessage", throwable.getMessage()));
if (ess.getSettings().isDebug()) {
logger.log(Level.INFO, tl("errorCallingCommand", commandLabel), throwable);
ess.getLogger().log(Level.INFO, tl("errorCallingCommand", commandLabel), throwable);
throwable.printStackTrace();
}
}
@@ -1,5 +1,6 @@
package com.earth2me.essentials.config;
import com.earth2me.essentials.Essentials;
import org.spongepowered.configurate.CommentedConfigurationNode;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
@@ -7,8 +8,6 @@ import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import static com.earth2me.essentials.config.EssentialsConfiguration.LOGGER;
public class ConfigurationSaveTask implements Runnable {
private final YamlConfigurationLoader loader;
private final CommentedConfigurationNode node;
@@ -32,7 +31,7 @@ public class ConfigurationSaveTask implements Runnable {
try {
loader.save(node);
} catch (ConfigurateException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
} finally {
pendingWrites.decrementAndGet();
}
@@ -1,5 +1,6 @@
package com.earth2me.essentials.config;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.config.annotations.DeleteIfIncomplete;
import com.earth2me.essentials.config.annotations.DeleteOnEmpty;
import com.earth2me.essentials.config.entities.CommandCooldown;
@@ -44,12 +45,10 @@ import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
public class EssentialsConfiguration {
protected static final Logger LOGGER = Logger.getLogger("Essentials");
private static final ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
private static final ObjectMapper.Factory MAPPER_FACTORY = ObjectMapper.factoryBuilder()
.addProcessor(DeleteOnEmpty.class, (data, value) -> new DeleteOnEmptyProcessor())
@@ -133,7 +132,7 @@ public class EssentialsConfiguration {
try {
result.put(entry.getKey().toLowerCase(Locale.ENGLISH), jailNode.get(LazyLocation.class));
} catch (SerializationException e) {
LOGGER.log(Level.WARNING, "Error serializing key " + entry.getKey(), e);
Essentials.getWrappedLogger().log(Level.WARNING, "Error serializing key " + entry.getKey(), e);
}
}
return result;
@@ -147,7 +146,7 @@ public class EssentialsConfiguration {
try {
toSplitRoot(path, configurationNode).set(type, list);
} catch (SerializationException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
}
}
@@ -163,7 +162,7 @@ public class EssentialsConfiguration {
}
return list;
} catch (SerializationException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
return new ArrayList<>();
}
}
@@ -301,7 +300,7 @@ public class EssentialsConfiguration {
try {
node.set(null);
} catch (SerializationException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
}
}
}
@@ -310,7 +309,7 @@ public class EssentialsConfiguration {
try {
toSplitRoot(path, configurationNode).set(value);
} catch (SerializationException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
}
}
@@ -336,13 +335,13 @@ public class EssentialsConfiguration {
public synchronized void load() {
if (pendingWrites.get() != 0) {
LOGGER.log(Level.INFO, "Parsing config file {0} has been aborted due to {1} current pending write(s).", new Object[]{configFile, pendingWrites.get()});
Essentials.getWrappedLogger().log(Level.INFO, "Parsing config file {0} has been aborted due to {1} current pending write(s).", new Object[]{configFile, pendingWrites.get()});
return;
}
if (configFile.getParentFile() != null && !configFile.getParentFile().exists()) {
if (!configFile.getParentFile().mkdirs()) {
LOGGER.log(Level.SEVERE, tl("failedToCreateConfig", configFile.toString()));
Essentials.getWrappedLogger().log(Level.SEVERE, tl("failedToCreateConfig", configFile.toString()));
return;
}
}
@@ -354,10 +353,10 @@ public class EssentialsConfiguration {
convertAltFile();
} else if (templateName != null) {
try (final InputStream is = resourceClass.getResourceAsStream(templateName)) {
LOGGER.log(Level.INFO, tl("creatingConfigFromTemplate", configFile.toString()));
Essentials.getWrappedLogger().log(Level.INFO, tl("creatingConfigFromTemplate", configFile.toString()));
Files.copy(is, configFile.toPath());
} catch (IOException e) {
LOGGER.log(Level.SEVERE, tl("failedToWriteConfig", configFile.toString()), e);
Essentials.getWrappedLogger().log(Level.SEVERE, tl("failedToWriteConfig", configFile.toString()), e);
}
}
}
@@ -367,12 +366,12 @@ public class EssentialsConfiguration {
} catch (final ParsingException e) {
final File broken = new File(configFile.getAbsolutePath() + ".broken." + System.currentTimeMillis());
if (configFile.renameTo(broken)) {
LOGGER.log(Level.SEVERE, "The file " + configFile.toString() + " is broken, it has been renamed to " + broken.toString(), e.getCause());
Essentials.getWrappedLogger().log(Level.SEVERE, "The file " + configFile.toString() + " is broken, it has been renamed to " + broken.toString(), e.getCause());
return;
}
LOGGER.log(Level.SEVERE, "The file " + configFile.toString() + " is broken. A backup file has failed to be created", e.getCause());
Essentials.getWrappedLogger().log(Level.SEVERE, "The file " + configFile.toString() + " is broken. A backup file has failed to be created", e.getCause());
} catch (final ConfigurateException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
} finally {
// Something is wrong! We need a node! I hope the backup worked!
if (configurationNode == null) {
@@ -435,7 +434,7 @@ public class EssentialsConfiguration {
try {
delaySave().get();
} catch (final InterruptedException | ExecutionException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
}
}
@@ -1,5 +1,6 @@
package com.earth2me.essentials.config;
import com.earth2me.essentials.Essentials;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
@@ -43,7 +44,7 @@ public class EssentialsUserConfiguration extends EssentialsConfiguration {
//noinspection UnstableApiUsage
Files.move(file, new File(configFile.getParentFile(), uuid + ".yml"));
} catch (final IOException ex) {
LOGGER.log(Level.WARNING, "Failed to migrate user: " + username, ex);
Essentials.getWrappedLogger().log(Level.WARNING, "Failed to migrate user: " + username, ex);
}
setProperty("last-account-name", username);
@@ -68,7 +69,7 @@ public class EssentialsUserConfiguration extends EssentialsConfiguration {
//noinspection UnstableApiUsage
Files.move(getAltFile(), new File(configFile.getParentFile(), uuid + ".yml"));
} catch (final IOException ex) {
LOGGER.log(Level.WARNING, "Failed to migrate user: " + username, ex);
Essentials.getWrappedLogger().log(Level.WARNING, "Failed to migrate user: " + username, ex);
}
}
}
@@ -322,6 +322,16 @@ public class UserConfigHolder {
this.baltopExempt = value;
}
private @MonotonicNonNull Boolean shouting;
public Boolean shouting() {
return shouting;
}
public void shouting(final Boolean value) {
this.shouting = value;
}
private @NonNull Timestamps timestamps = new Timestamps();
public Timestamps timestamps() {
@@ -1,5 +1,6 @@
package com.earth2me.essentials.craftbukkit;
import com.earth2me.essentials.utils.VersionUtil;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@@ -15,15 +16,13 @@ import java.util.Map;
/*
* This class can be removed when https://github.com/Bukkit/CraftBukkit/pull/193 is accepted to CraftBukkit
*/
public final class InventoryWorkaround {
/*
Spigot 1.9, for whatever reason, decided to merge the armor and main player inventories without providing a way
to access the main inventory. There's lots of ugly code in here to work around that.
*/
private static final int USABLE_PLAYER_INV_SIZE = 36;
// Hot-ish code so cache
private static Boolean hasMainHandSupport = null;
private static final boolean IS_OFFHAND = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01);
private InventoryWorkaround() {
}
@@ -201,87 +200,45 @@ public final class InventoryWorkaround {
@SuppressWarnings("deprecation")
public static void setItemInMainHand(final Player p, final ItemStack item) {
if (hasMainHandSupport == null) {
try {
p.getInventory().setItemInMainHand(item);
hasMainHandSupport = true;
} catch (final Throwable e) {
p.setItemInHand(item);
hasMainHandSupport = false;
}
if (IS_OFFHAND) {
p.getInventory().setItemInMainHand(item);
} else {
if (hasMainHandSupport) {
p.getInventory().setItemInMainHand(item);
} else {
p.setItemInHand(item);
}
p.setItemInHand(item);
}
}
@SuppressWarnings("deprecation")
public static void setItemInMainHand(final EntityEquipment invent, final ItemStack item) {
if (hasMainHandSupport == null) {
try {
invent.setItemInMainHand(item);
hasMainHandSupport = true;
} catch (final Throwable e) {
invent.setItemInHand(item);
hasMainHandSupport = false;
}
if (IS_OFFHAND) {
invent.setItemInMainHand(item);
} else {
if (hasMainHandSupport) {
invent.setItemInMainHand(item);
} else {
invent.setItemInHand(item);
}
invent.setItemInHand(item);
}
}
@SuppressWarnings("deprecation")
public static void setItemInMainHandDropChance(final EntityEquipment invent, final float chance) {
if (hasMainHandSupport == null) {
try {
invent.setItemInMainHandDropChance(chance);
hasMainHandSupport = true;
} catch (final Throwable e) {
invent.setItemInHandDropChance(chance);
hasMainHandSupport = false;
}
if (IS_OFFHAND) {
invent.setItemInMainHandDropChance(chance);
} else {
if (hasMainHandSupport) {
invent.setItemInMainHandDropChance(chance);
} else {
invent.setItemInHandDropChance(chance);
}
invent.setItemInHandDropChance(chance);
}
}
public static void setItemInOffHand(final Player p, final ItemStack item) {
// This assumes that all builds that support a main hand also support an off hand.
if (hasMainHandSupport == null || hasMainHandSupport) {
try {
p.getInventory().setItemInOffHand(item);
hasMainHandSupport = true;
} catch (final Throwable e) {
hasMainHandSupport = false;
}
if (IS_OFFHAND) {
p.getInventory().setItemInOffHand(item);
}
}
public static int clearItemInOffHand(final Player p, final ItemStack item) {
// This should be added because if `/clear` itself is not initilized it will return an Error: null.
if (hasMainHandSupport == null || hasMainHandSupport) {
try {
int removedAmount = 0;
if (p.getInventory().getItemInOffHand().getType().equals(item.getType())) {
removedAmount = p.getInventory().getItemInOffHand().getAmount();
p.getInventory().setItemInOffHand(null);
}
hasMainHandSupport = true;
return removedAmount;
} catch (final Throwable e) {
hasMainHandSupport = false;
if (IS_OFFHAND) {
int removedAmount = 0;
if (p.getInventory().getItemInOffHand().getType().equals(item.getType())) {
removedAmount = p.getInventory().getItemInOffHand().getAmount();
p.getInventory().setItemInOffHand(null);
}
return removedAmount;
}
return 0;
}
@@ -19,7 +19,6 @@ import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A goddamn Vault adapter, what more do you want?
@@ -29,7 +28,6 @@ import java.util.logging.Logger;
* {@link com.earth2me.essentials.User}.
*/
public class VaultEconomyProvider implements Economy {
private static final Logger LOGGER = Logger.getLogger("Essentials");
private static final String WARN_NPC_RECREATE_1 = "Account creation was requested for NPC user {0}, but an account file with UUID {1} already exists.";
private static final String WARN_NPC_RECREATE_2 = "Essentials will create a new account as requested by the other plugin, but this is almost certainly a bug and should be reported.";
@@ -301,8 +299,8 @@ public class VaultEconomyProvider implements Economy {
}
final File npcFile = new File(folder, player.getUniqueId() + ".yml");
if (npcFile.exists()) {
LOGGER.log(Level.SEVERE, MessageFormat.format(WARN_NPC_RECREATE_1, player.getName(), player.getUniqueId().toString()), new RuntimeException());
LOGGER.log(Level.SEVERE, WARN_NPC_RECREATE_2);
ess.getLogger().log(Level.SEVERE, MessageFormat.format(WARN_NPC_RECREATE_1, player.getName(), player.getUniqueId().toString()), new RuntimeException());
ess.getLogger().log(Level.SEVERE, WARN_NPC_RECREATE_2);
}
final EssentialsUserConfiguration npcConfig = new EssentialsUserConfiguration(player.getName(), player.getUniqueId(), npcFile);
npcConfig.load();
@@ -317,7 +315,7 @@ public class VaultEconomyProvider implements Economy {
// Loading a v4 UUID that we somehow didn't track, mark it as a normal player and hope for the best, vault sucks :/
try {
if (ess.getSettings().isDebug()) {
LOGGER.info("Vault requested a player account creation for a v4 UUID: " + player);
ess.getLogger().info("Vault requested a player account creation for a v4 UUID: " + player);
}
ess.getUserMap().load(player);
return true;
@@ -23,6 +23,7 @@ import org.bukkit.inventory.meta.FireworkEffectMeta;
import org.bukkit.inventory.meta.FireworkMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.plugin.Plugin;
import org.bukkit.potion.Potion;
@@ -279,12 +280,22 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
serializeEffectMeta(sb, fireworkEffectMeta.getEffect());
}
} else if (MaterialUtil.isPotion(material)) {
final Potion potion = Potion.fromItemStack(is);
for (final PotionEffect e : potion.getEffects()) {
// long but needs to be effect:speed power:2 duration:120 in that order.
sb.append("splash:").append(potion.isSplash()).append(" ").append("effect:").append(e.getType().getName().toLowerCase()).append(" ").append("power:").append(e.getAmplifier()).append(" ").append("duration:").append(e.getDuration() / 20).append(" ");
final boolean splash;
final Collection<PotionEffect> effects;
if (VersionUtil.PRE_FLATTENING) {
final Potion potion = Potion.fromDamage(is.getDurability());
splash = potion.isSplash();
effects = potion.getEffects();
} else {
splash = is.getType() == Material.SPLASH_POTION;
effects = ((PotionMeta) is.getItemMeta()).getCustomEffects();
}
} else if (MaterialUtil.isPlayerHead(material, is.getData().getData())) {
for (final PotionEffect e : effects) {
// long but needs to be effect:speed power:2 duration:120 in that order.
sb.append("splash:").append(splash).append(" ").append("effect:").append(e.getType().getName().toLowerCase()).append(" ").append("power:").append(e.getAmplifier()).append(" ").append("duration:").append(e.getDuration() / 20).append(" ");
}
} else if (MaterialUtil.isPlayerHead(is)) {
// item stack with meta
final SkullMeta skullMeta = (SkullMeta) is.getItemMeta();
if (skullMeta != null && skullMeta.hasOwner()) {
@@ -23,13 +23,11 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import static com.earth2me.essentials.I18n.tl;
public class FlatItemDb extends AbstractItemDb {
protected static final Logger LOGGER = Logger.getLogger("Essentials");
private static final Gson gson = new Gson();
// Maps primary name to ItemData
@@ -54,7 +52,7 @@ public class FlatItemDb extends AbstractItemDb {
}
this.rebuild();
LOGGER.info(String.format("Loaded %s items from items.json.", listNames().size()));
ess.getLogger().info(String.format("Loaded %s items from items.json.", listNames().size()));
}
private void rebuild() {
@@ -100,7 +98,7 @@ public class FlatItemDb extends AbstractItemDb {
if (valid) {
allAliases.add(key);
} else {
LOGGER.warning(String.format("Failed to add item: \"%s\": %s", key, element.toString()));
ess.getLogger().warning(String.format("Failed to add item: \"%s\": %s", key, element.toString()));
}
}
}
@@ -115,7 +113,7 @@ public class FlatItemDb extends AbstractItemDb {
}
id = id.toLowerCase();
final String[] split = id.split(":");
final String[] split = id.split("(?<!^minecraft):");
final ItemData data = getByName(split[0]);
@@ -3,9 +3,9 @@ package com.earth2me.essentials.items;
import com.earth2me.essentials.ManagedFile;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
import net.ess3.nms.refl.ReflUtil;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
@@ -17,14 +17,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
public class LegacyItemDb extends AbstractItemDb {
protected static final Logger LOGGER = Logger.getLogger("Essentials");
private final transient Map<String, Integer> items = new HashMap<>();
private final transient Map<ItemData, List<String>> names = new HashMap<>();
private final transient Map<ItemData, String> primaryName = new HashMap<>();
@@ -68,10 +66,10 @@ public class LegacyItemDb extends AbstractItemDb {
final Matcher matcher = csvSplitPattern.matcher(line);
while (matcher.find()) {
String match = matcher.group(1);
if (StringUtils.stripToNull(match) == null) {
if (StringUtil.stripToNull(match) == null) {
continue;
}
match = StringUtils.strip(match.trim(), "\"");
match = StringUtil.strip(match.trim(), "\"");
switch (col) {
case 0:
itemName = match.toLowerCase(Locale.ENGLISH);
@@ -83,7 +81,7 @@ public class LegacyItemDb extends AbstractItemDb {
data = Short.parseShort(match);
break;
case 3:
nbt = StringUtils.stripToNull(match);
nbt = StringUtil.stripToNull(match);
break;
default:
continue;
@@ -119,7 +117,7 @@ public class LegacyItemDb extends AbstractItemDb {
nameList.sort(LengthCompare.INSTANCE);
}
LOGGER.info(String.format("Loaded %s items from items.csv.", listNames().size()));
ess.getLogger().info(String.format("Loaded %s items from items.csv.", listNames().size()));
ready = true;
}
@@ -204,7 +202,7 @@ public class LegacyItemDb extends AbstractItemDb {
}
retval = ess.getSpawnEggProvider().createEggItem(type);
} else if (mat.name().endsWith("POTION")
&& ReflUtil.getNmsVersionObject().isLowerThan(ReflUtil.V1_11_R1)) { // Only apply this to pre-1.11 as items.csv might only work in 1.11
&& 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);
} else {
retval.setDurability(metaData);
Loaded 100 of 263 files, more files were not shown because too many files have changed in this diff. Show more