Compare commits

..
95 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
199 changed files with 9063 additions and 3457 deletions

No files matched your search

+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.
+4
View File
@@ -29,6 +29,10 @@ dependencies {
}
}
test {
testLogging.showStandardStreams = true
}
shadowJar {
dependencies {
include (dependency('io.papermc:paperlib'))
@@ -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;
@@ -95,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);
}
@@ -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");
@@ -66,11 +66,13 @@ import net.ess3.provider.PotionMetaProvider;
import net.ess3.provider.ProviderListener;
import net.ess3.provider.SerializationProvider;
import net.ess3.provider.ServerStateProvider;
import net.ess3.provider.SignDataProvider;
import net.ess3.provider.SpawnEggProvider;
import net.ess3.provider.SpawnerBlockProvider;
import net.ess3.provider.SpawnerItemProvider;
import net.ess3.provider.SyncCommandsProvider;
import net.ess3.provider.WorldInfoProvider;
import net.ess3.provider.providers.BaseLoggerProvider;
import net.ess3.provider.providers.BasePotionDataProvider;
import net.ess3.provider.providers.BlockMetaSpawnerItemProvider;
import net.ess3.provider.providers.BukkitMaterialTagProvider;
@@ -80,9 +82,10 @@ 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.ModernDataWorldInfoProvider;
import net.ess3.provider.providers.ModernSignDataProvider;
import net.ess3.provider.providers.PaperContainerProvider;
import net.ess3.provider.providers.PaperKnownCommandsProvider;
import net.ess3.provider.providers.PaperMaterialTagProvider;
@@ -91,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;
@@ -139,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;
@@ -175,6 +178,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
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;
@@ -201,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();
@@ -241,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);
@@ -259,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;
@@ -432,6 +443,10 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
worldInfoProvider = new FixedHeightWorldInfoProvider();
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_14_4_R01)) {
signDataProvider = new ModernSignDataProvider(this);
}
execTimer.mark("Init(Providers)");
reload();
@@ -466,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);
@@ -477,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.
@@ -625,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);
}
}
}
@@ -706,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;
@@ -726,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);
@@ -1041,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 {
@@ -1306,6 +1330,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
return worldInfoProvider;
}
@Override
public SignDataProvider getSignDataProvider() {
return signDataProvider;
}
@Override
public PluginCommand getPluginCommand(final String cmd) {
return this.getCommand(cmd);
@@ -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);
}
}
@@ -72,13 +72,11 @@ 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<>();
@@ -166,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();
@@ -198,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;
@@ -217,6 +215,10 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
to.setY(from.getY());
to.setZ(from.getZ());
try {
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);
@@ -258,6 +260,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
user.setGodModeEnabled(false);
}
if (user.isVanished()) {
user.setLeavingHidden(true);
user.setVanished(false);
}
user.setLogoutLocation();
@@ -332,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());
@@ -460,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());
}
}
}
@@ -622,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;
}
@@ -810,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);
}
}
}
@@ -834,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));
}
}
@@ -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,13 +425,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("updateUsersIgnoreListUUID", true);
doneFile.save();
LOGGER.info("Done converting ignore list.");
ess.getLogger().info("Done converting ignore list.");
}
public void convertKits() {
@@ -443,25 +441,25 @@ public class EssentialsUpgrade {
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());
@@ -14,8 +14,9 @@ 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;
@@ -165,5 +166,7 @@ public interface IEssentials extends Plugin {
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();
@@ -94,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();
@@ -261,12 +270,12 @@ public interface IUser {
* 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 performExpirations true if this method should not spend time validating time for all items in the queue and just return the first item in the queue.
* @param excludeHere true if /tphere requests should be ignored in fetching the next tpa request.
* @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 performExpirations, boolean excludeHere);
@Nullable TpaRequest getNextTpaRequest(boolean inform, boolean ignoreExpirations, boolean excludeHere);
/**
* Whether or not this {@link IUser} has any valid TPA requests in queue.
@@ -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;
});
@@ -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();
}
}
@@ -210,7 +210,7 @@ public class MetaItemStack {
final boolean value = split.length <= 1 || Boolean.parseBoolean(split[1]);
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 {
@@ -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());
}
}
@@ -206,4 +206,8 @@ public class RandomTeleport implements IConf {
private boolean isValidRandomLocation(final Location location) {
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);
}
@@ -1675,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;
@@ -1860,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);
}
});
@@ -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);
}
}
}
@@ -34,10 +34,11 @@ 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.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
@@ -47,13 +48,11 @@ 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;
@@ -69,6 +68,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
// User properties
private transient boolean vanished;
private boolean hidden = false;
private boolean leavingHidden = false;
private boolean rightClickJump = false;
private boolean invSee = false;
private boolean recipeSee = false;
@@ -89,8 +89,9 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
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);
@@ -109,6 +110,10 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
setBase(base);
}
public IEssentials getEssentials() {
return ess;
}
@Override
public boolean isAuthorized(final IEssentialsCommand cmd) {
return isAuthorized(cmd, "essentials.");
@@ -318,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;
}
@@ -349,11 +354,8 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
// Handle max queue size
teleportRequestQueue.remove(request.getName());
if (teleportRequestQueue.size() >= ess.getSettings().getTpaMaxRequests()) {
String lastKey = null;
for (Map.Entry<String, TpaRequest> entry : teleportRequestQueue.entrySet()) {
lastKey = entry.getKey();
}
teleportRequestQueue.remove(lastKey);
final List<String> keys = new ArrayList<>(teleportRequestQueue.keySet());
teleportRequestQueue.remove(keys.get(keys.size() - 1));
}
// Add request to queue
@@ -402,22 +404,24 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
@Override
public TpaRequest getNextTpaRequest(boolean inform, boolean performExpirations, boolean excludeHere) {
public TpaRequest getNextTpaRequest(boolean inform, boolean ignoreExpirations, boolean excludeHere) {
if (teleportRequestQueue.isEmpty()) {
return null;
}
final long timeout = ess.getSettings().getTpaAcceptCancellation();
final Iterator<Map.Entry<String, TpaRequest>> iterator = teleportRequestQueue.entrySet().iterator();
final List<String> keys = new ArrayList<>(teleportRequestQueue.keySet());
Collections.reverse(keys);
TpaRequest nextRequest = null;
while (iterator.hasNext()) {
final TpaRequest request = iterator.next().getValue();
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;
}
if (performExpirations) {
if (ignoreExpirations) {
return request;
} else if (nextRequest == null) {
nextRequest = request;
@@ -426,7 +430,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
if (inform) {
sendMessage(tl("requestTimedOutFrom", ess.getUser(request.getRequesterUuid()).getDisplayName()));
}
iterator.remove();
teleportRequestQueue.remove(key);
}
}
return nextRequest;
@@ -515,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.");
}
}
}
@@ -633,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();
@@ -678,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;
@@ -960,6 +974,7 @@ 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")) {
@@ -1186,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;
@@ -1198,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;
@@ -135,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;
}
@@ -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)) {
@@ -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("*") || 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;
}
}
@@ -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,7 +788,7 @@ public class Commandessentials extends EssentialsCommand {
}
break;
case "dump":
final List<String> list = Lists.newArrayList("config", "kits", "log", "discord", "all");
final List<String> list = Lists.newArrayList("config", "kits", "log", "discord", "worth", "tpr", "spawns", "commands", "all");
for (String arg : args) {
if (arg.equals("*") || arg.equalsIgnoreCase("all")) {
list.clear();
@@ -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));
}
@@ -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));
@@ -1,6 +1,7 @@
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;
@@ -39,9 +40,12 @@ public class Commandplaytime extends EssentialsCommand {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_15_2_R01)) {
throw e;
}
final IUser user = getPlayer(server, sender, args, 0, true);
displayName = user.getName();
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()) {
@@ -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;
}
@@ -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;
}
@@ -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);
}
@@ -87,7 +87,7 @@ public class Commandtogglejail extends EssentialsCommand {
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());
server.getLogger().log(Level.INFO, notifyMessage);
ess.getLogger().log(Level.INFO, notifyMessage);
ess.broadcastMessage("essentials.jail.notify", notifyMessage);
}
});
@@ -114,7 +114,7 @@ public class Commandtogglejail extends EssentialsCommand {
sender.sendMessage(tl("jailSentenceExtended", DateUtil.formatDateDiff(displayTimeDiff)));
final String notifyMessage = tl("jailNotifySentenceExtended", player.getName(), DateUtil.formatDateDiff(displayTimeDiff), sender.getSender().getName());
server.getLogger().log(Level.INFO, notifyMessage);
ess.getLogger().log(Level.INFO, notifyMessage);
ess.broadcastMessage("essentials.jail.notify", notifyMessage);
return;
}
@@ -55,7 +55,7 @@ public class Commandtpa extends EssentialsCommand {
user.sendMessage(tl("requestAcceptedFromAuto", player.getDisplayName()));
}
});
return;
throw new NoChargeException();
}
if (!player.isIgnoredPlayer(user)) {
@@ -99,7 +99,7 @@ public class Commandtpaccept extends EssentialsCommand {
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (ess.getSettings().isDebug()) {
logger.info("TPA accept cancelled by API for " + user.getName() + " (requested by " + requester.getName() + ")");
ess.getLogger().info("TPA accept cancelled by API for " + user.getName() + " (requested by " + requester.getName() + ")");
}
return;
}
@@ -84,7 +84,7 @@ public class Commandtpdeny extends EssentialsCommand {
Bukkit.getPluginManager().callEvent(event);
final boolean cancelled = event.isCancelled();
if (cancelled && ess.getSettings().isDebug()) {
logger.info("TPA deny cancelled by API for " + user.getName() + " (requested by " + player.getName() + ")");
ess.getLogger().info("TPA deny cancelled by API for " + user.getName() + " (requested by " + player.getName() + ")");
}
return event.isCancelled();
}
@@ -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.
*/
@@ -334,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.fromDamage(is.getDurability());
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 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;
}
@@ -1,5 +1,7 @@
package com.earth2me.essentials.perm;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.TriState;
import org.bukkit.entity.Player;
@@ -27,11 +29,11 @@ public interface IPermissionsHandler {
String getSuffix(Player base);
void registerContext(String context, Function<Player, Iterable<String>> calculator, Supplier<Iterable<String>> suggestions);
void registerContext(String context, Function<User, Iterable<String>> calculator, Supplier<Iterable<String>> suggestions);
void unregisterContexts();
String getBackendName();
boolean tryProvider();
boolean tryProvider(Essentials ess);
}
@@ -1,6 +1,7 @@
package com.earth2me.essentials.perm;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.User;
import com.earth2me.essentials.perm.impl.AbstractVaultHandler;
import com.earth2me.essentials.perm.impl.ConfigPermissionsHandler;
import com.earth2me.essentials.perm.impl.GenericVaultHandler;
@@ -105,7 +106,7 @@ public class PermissionsHandler implements IPermissionsHandler {
}
@Override
public void registerContext(final String context, final Function<Player, Iterable<String>> calculator, final Supplier<Iterable<String>> suggestions) {
public void registerContext(final String context, final Function<User, Iterable<String>> calculator, final Supplier<Iterable<String>> suggestions) {
handler.registerContext(context, calculator, suggestions);
}
@@ -120,7 +121,7 @@ public class PermissionsHandler implements IPermissionsHandler {
}
@Override
public boolean tryProvider() {
public boolean tryProvider(Essentials ess) {
return true;
}
@@ -135,7 +136,7 @@ public class PermissionsHandler implements IPermissionsHandler {
for (final Class<? extends IPermissionsHandler> providerClass : providerClazz) {
try {
final IPermissionsHandler provider = providerClass.newInstance();
if (provider.tryProvider()) {
if (provider.tryProvider(ess)) {
if (provider.getClass().isInstance(this.handler)) {
return;
}
@@ -170,7 +171,7 @@ public class PermissionsHandler implements IPermissionsHandler {
if (enabledPermsPlugin == null) enabledPermsPlugin = "generic";
ess.getLogger().info("Using Vault based permissions (" + enabledPermsPlugin + ")");
} else if (handler.getClass() == SuperpermsHandler.class) {
if (handler.tryProvider()) {
if (handler.tryProvider(ess)) {
ess.getLogger().warning("Detected supported permissions plugin " +
((SuperpermsHandler) handler).getEnabledPermsPlugin() + " without Vault installed.");
ess.getLogger().warning("Features such as chat prefixes/suffixes and group-related functionality will not " +
@@ -199,11 +200,11 @@ public class PermissionsHandler implements IPermissionsHandler {
}
private void initContexts() {
registerContext("essentials:afk", player -> Collections.singleton(String.valueOf(ess.getUser(player).isAfk())), () -> ImmutableSet.of("true", "false"));
registerContext("essentials:muted", player -> Collections.singleton(String.valueOf(ess.getUser(player).isMuted())), () -> ImmutableSet.of("true", "false"));
registerContext("essentials:vanished", player -> Collections.singleton(String.valueOf(ess.getUser(player).isHidden())), () -> ImmutableSet.of("true", "false"));
registerContext("essentials:jailed", player -> Collections.singleton(String.valueOf(ess.getUser(player).isJailed())), () -> ImmutableSet.of("true", "false"));
registerContext("essentials:jail", player -> Optional.ofNullable(ess.getUser(player).getJail()).map(Arrays::asList).orElse(Collections.emptyList()), () -> {
registerContext("essentials:afk", user -> Collections.singleton(String.valueOf(user.isAfk())), () -> ImmutableSet.of("true", "false"));
registerContext("essentials:muted", user -> Collections.singleton(String.valueOf(user.isMuted())), () -> ImmutableSet.of("true", "false"));
registerContext("essentials:vanished", user -> Collections.singleton(String.valueOf(user.isHidden())), () -> ImmutableSet.of("true", "false"));
registerContext("essentials:jailed", user -> Collections.singleton(String.valueOf(user.isJailed())), () -> ImmutableSet.of("true", "false"));
registerContext("essentials:jail", user -> Optional.ofNullable(user.getJail()).map(Arrays::asList).orElse(Collections.emptyList()), () -> {
try {
return ess.getJails().getList();
} catch (final Exception e) {
@@ -1,5 +1,6 @@
package com.earth2me.essentials.perm.impl;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.utils.TriState;
import net.ess3.api.IEssentials;
import org.bukkit.entity.Player;
@@ -35,7 +36,7 @@ public class ConfigPermissionsHandler extends SuperpermsHandler {
}
@Override
public boolean tryProvider() {
public boolean tryProvider(Essentials ess) {
return true;
}
}
@@ -1,8 +1,10 @@
package com.earth2me.essentials.perm.impl;
import com.earth2me.essentials.Essentials;
public class GenericVaultHandler extends AbstractVaultHandler {
@Override
public boolean tryProvider() {
public boolean tryProvider(Essentials ess) {
return super.canLoad();
}
}
@@ -1,5 +1,8 @@
package com.earth2me.essentials.perm.impl;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.User;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.context.ContextCalculator;
import net.luckperms.api.context.ContextConsumer;
@@ -16,40 +19,75 @@ import java.util.function.Supplier;
public class LuckPermsHandler extends ModernVaultHandler {
private LuckPerms luckPerms;
private Set<ContextCalculator<Player>> contextCalculators;
private Essentials ess;
private CombinedCalculator calculator;
@Override
public void registerContext(final String context, final Function<Player, Iterable<String>> calculator, final Supplier<Iterable<String>> suggestions) {
final ContextCalculator<Player> contextCalculator = new ContextCalculator<Player>() {
@Override
public void calculate(final Player target, final ContextConsumer consumer) {
calculator.apply(target).forEach(value -> consumer.accept(context, value));
}
@Override
public ContextSet estimatePotentialContexts() {
final ImmutableContextSet.Builder builder = ImmutableContextSet.builder();
suggestions.get().forEach(value -> builder.add(context, value));
return builder.build();
}
};
luckPerms.getContextManager().registerCalculator(contextCalculator);
contextCalculators.add(contextCalculator);
public void registerContext(final String context, final Function<User, Iterable<String>> calculator, final Supplier<Iterable<String>> suggestions) {
if (this.calculator == null) {
this.calculator = new CombinedCalculator();
this.luckPerms.getContextManager().registerCalculator(this.calculator);
}
this.calculator.calculators.add(new Calculator(context, calculator, suggestions));
}
@Override
public void unregisterContexts() {
contextCalculators.forEach(contextCalculator -> luckPerms.getContextManager().unregisterCalculator(contextCalculator));
contextCalculators.clear();
if (this.calculator != null) {
this.luckPerms.getContextManager().unregisterCalculator(this.calculator);
this.calculator = null;
}
}
@Override
public boolean tryProvider() {
public boolean tryProvider(Essentials ess) {
final RegisteredServiceProvider<LuckPerms> provider = Bukkit.getServicesManager().getRegistration(LuckPerms.class);
if (provider != null) {
luckPerms = provider.getProvider();
contextCalculators = new HashSet<>();
this.luckPerms = provider.getProvider();
this.ess = ess;
}
return luckPerms != null && super.tryProvider(ess);
}
private static final class Calculator {
private final String id;
private final Function<User, Iterable<String>> function;
private final Supplier<Iterable<String>> suggestions;
private Calculator(String id, Function<User, Iterable<String>> function, Supplier<Iterable<String>> suggestions) {
this.id = id;
this.function = function;
this.suggestions = suggestions;
}
}
// By combining all calculators into one, we only need to make one call to ess.getUser().
private class CombinedCalculator implements ContextCalculator<Player> {
private final Set<Calculator> calculators = new HashSet<>();
@Override
public void calculate(final Player target, final ContextConsumer consumer) {
// If the player doesn't exist in the UserMap, just skip
// Ess will cause performance problems for permissions checks if it attempts to
// perform i/o to load the user data otherwise.
if (!ess.getUserMap().userExists(target.getUniqueId())) {
return;
}
final User user = ess.getUser(target);
for (Calculator calculator : this.calculators) {
calculator.function.apply(user).forEach(value -> consumer.accept(calculator.id, value));
}
}
@Override
public ContextSet estimatePotentialContexts() {
final ImmutableContextSet.Builder builder = ImmutableContextSet.builder();
for (Calculator calculator : this.calculators) {
calculator.suggestions.get().forEach(value -> builder.add(calculator.id, value));
}
return builder.build();
}
return luckPerms != null && super.tryProvider();
}
}
@@ -1,5 +1,7 @@
package com.earth2me.essentials.perm.impl;
import com.earth2me.essentials.Essentials;
import org.bukkit.entity.Player;
import java.util.Arrays;
@@ -21,7 +23,7 @@ public class ModernVaultHandler extends AbstractVaultHandler {
}
@Override
public boolean tryProvider() {
public boolean tryProvider(Essentials ess) {
return super.canLoad() && supportedPlugins.contains(getEnabledPermsPlugin());
}
}
@@ -1,5 +1,7 @@
package com.earth2me.essentials.perm.impl;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.User;
import com.earth2me.essentials.perm.IPermissionsHandler;
import com.earth2me.essentials.utils.TriState;
import org.bukkit.Bukkit;
@@ -124,7 +126,7 @@ public class SuperpermsHandler implements IPermissionsHandler {
}
@Override
public void registerContext(final String context, final Function<Player, Iterable<String>> calculator, final Supplier<Iterable<String>> suggestions) {
public void registerContext(final String context, final Function<User, Iterable<String>> calculator, final Supplier<Iterable<String>> suggestions) {
}
@Override
@@ -137,7 +139,7 @@ public class SuperpermsHandler implements IPermissionsHandler {
}
@Override
public boolean tryProvider() {
public boolean tryProvider(Essentials ess) {
return getEnabledPermsPlugin() != null;
}
@@ -5,6 +5,7 @@ import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.MetaItemStack;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.IEssentials;
@@ -30,6 +31,7 @@ import java.util.Set;
import static com.earth2me.essentials.I18n.tl;
public class EssentialsSign {
private static final String SIGN_OWNER_KEY = "sign-owner";
protected static final BigDecimal MINTRANSACTION = new BigDecimal("0.01");
private static final Set<Material> EMPTY_SET = new HashSet<>();
protected transient final String signName;
@@ -60,15 +62,15 @@ public class EssentialsSign {
}
/**
* @deprecated, use {@link #isValidSign(IEssentials, ISign)} if possible
* @deprecated use {@link #isValidSign(IEssentials, ISign)} if possible
*/
@Deprecated
public static boolean isValidSign(final ISign sign) {
return sign.getLine(0).matches("§1\\[.*\\]");
return sign.getLine(0).matches("§1\\[.*]");
}
public static boolean isValidSign(final IEssentials ess, final ISign sign) {
if (!sign.getLine(0).matches("§1\\[.*\\]"))
if (!sign.getLine(0).matches("§1\\[.*]"))
return false;
// Validate that the sign is actually an essentials sign
@@ -119,6 +121,7 @@ public class EssentialsSign {
} catch (final ChargeException | SignException ex) {
showError(ess, user.getSource(), ex, signName);
}
setOwnerData(ess, user, sign);
// Return true, so the player sees the wrong sign.
return true;
}
@@ -154,6 +157,36 @@ public class EssentialsSign {
return user.getName().substring(0, Math.min(user.getName().length(), 13));
}
public void setOwner(final IEssentials ess, final User user, final ISign signProvider, final int nameIndex, final String namePrefix) {
setOwnerData(ess, user, signProvider);
signProvider.setLine(nameIndex, namePrefix + getUsername(user));
}
public void setOwnerData(final IEssentials ess, final User user, final ISign signProvider) {
if (ess.getSignDataProvider() == null) {
return;
}
final Sign sign = (Sign) signProvider.getBlock().getState();
ess.getSignDataProvider().setSignData(sign, SIGN_OWNER_KEY, user.getUUID().toString());
}
public boolean isOwner(final IEssentials ess, final User user, final ISign signProvider, final int nameIndex, final String namePrefix) {
final Sign sign = (Sign) signProvider.getBlock().getState();
if (ess.getSignDataProvider() == null || ess.getSignDataProvider().getSignData(sign, SIGN_OWNER_KEY) == null) {
final boolean isLegacyOwner = FormatUtil.stripFormat(signProvider.getLine(nameIndex)).equalsIgnoreCase(getUsername(user));
if (ess.getSignDataProvider() != null && isLegacyOwner) {
ess.getSignDataProvider().setSignData(sign, SIGN_OWNER_KEY, user.getUUID().toString());
}
return isLegacyOwner;
}
if (user.getUUID().toString().equals(ess.getSignDataProvider().getSignData(sign, SIGN_OWNER_KEY))) {
signProvider.setLine(nameIndex, namePrefix + getUsername(user));
return true;
}
return false;
}
protected final boolean onSignInteract(final Block block, final Player player, final IEssentials ess) {
final ISign sign = new BlockSign(block);
final User user = ess.getUser(player);
@@ -392,7 +425,7 @@ public class EssentialsSign {
}
protected final BigDecimal getMoney(final String line, final IEssentials ess) throws SignException {
final boolean isMoney = line.matches("^[^0-9-\\.]?[\\.0-9]+[^0-9-\\.]?$");
final boolean isMoney = line.matches("^[^0-9-.]?[.0-9]+[^0-9-.]?$");
return isMoney ? getBigDecimalPositive(line, ess) : null;
}
@@ -531,6 +564,7 @@ public class EssentialsSign {
@Override
public final void setLine(final int index, final String text) {
sign.setLine(index, text);
updateSign();
}
@Override
@@ -23,10 +23,8 @@ import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.SignChangeEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SignBlockListener implements Listener {
private static final Logger LOGGER = Logger.getLogger("Essentials");
private final transient IEssentials ess;
public SignBlockListener(final IEssentials ess) {
@@ -52,7 +50,7 @@ public class SignBlockListener implements Listener {
// prevent any signs be broken by destroying the block they are attached to
if (EssentialsSign.checkIfBlockBreaksSigns(block)) {
if (ess.getSettings().isDebug()) {
LOGGER.log(Level.INFO, "Prevented that a block was broken next to a sign.");
ess.getLogger().log(Level.INFO, "Prevented that a block was broken next to a sign.");
}
return true;
}
@@ -70,7 +68,7 @@ public class SignBlockListener implements Listener {
for (final EssentialsSign sign : ess.getSettings().enabledSigns()) {
if (sign.areHeavyEventRequired() && sign.getBlocks().contains(block.getType()) && !sign.onBlockBreak(block, player, ess)) {
LOGGER.log(Level.INFO, "A block was protected by a sign.");
ess.getLogger().log(Level.INFO, "A block was protected by a sign.");
return true;
}
}
@@ -5,7 +5,6 @@ import com.earth2me.essentials.Trade;
import com.earth2me.essentials.Trade.OverflowType;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
@@ -123,7 +122,7 @@ public class SignProtection extends EssentialsSign {
if (user.isAuthorized("essentials.signs.protection.override")) {
return SignProtectionState.OWNER;
}
if (FormatUtil.stripFormat(sign.getLine(3)).equalsIgnoreCase(username)) {
if (isOwner(user.getEssentials(), user, sign, 3, "§1")) {
return SignProtectionState.OWNER;
}
for (int i = 1; i <= 2; i++) {
@@ -5,6 +5,7 @@ import com.earth2me.essentials.Trade;
import com.earth2me.essentials.Trade.OverflowType;
import com.earth2me.essentials.Trade.TradeType;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
@@ -18,7 +19,7 @@ import static com.earth2me.essentials.I18n.tl;
//TODO: TL exceptions
public class SignTrade extends EssentialsSign {
private static int MAX_STOCK_LINE_LENGTH = 15;
private static final int MAX_STOCK_LINE_LENGTH = 15;
public SignTrade() {
super("Trade");
@@ -34,7 +35,7 @@ public class SignTrade extends EssentialsSign {
throw new SignException("You cannot trade for the same item type.");
}
trade.isAffordableFor(player);
sign.setLine(3, "§8" + username);
setOwner(ess, player, sign, 3, "§8");
trade.charge(player);
Trade.log("Sign", "Trade", "Create", username, trade, username, null, sign.getBlock().getLocation(), player.getMoney(), ess);
return true;
@@ -42,7 +43,7 @@ public class SignTrade extends EssentialsSign {
@Override
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException, ChargeException, MaxMoneyException {
if (sign.getLine(3).substring(2).equalsIgnoreCase(username)) {
if (isOwner(ess, player, sign, 3, "§8")) {
final Trade store = rechargeSign(sign, ess, player);
final Trade stored;
try {
@@ -83,7 +84,7 @@ public class SignTrade extends EssentialsSign {
private Trade rechargeSign(final ISign sign, final IEssentials ess, final User player) throws SignException, ChargeException {
final Trade trade = getTrade(sign, 2, AmountType.COST, false, true, ess);
if (trade.getItemStack() != null && player.getBase().getItemInHand() != null && trade.getItemStack().getType() == player.getBase().getItemInHand().getType() && trade.getItemStack().getDurability() == player.getBase().getItemInHand().getDurability() && trade.getItemStack().getEnchantments().equals(player.getBase().getItemInHand().getEnchantments())) {
if (trade.getItemStack() != null && player.getBase().getItemInHand() != null && trade.getItemStack().getType() == player.getBase().getItemInHand().getType() && MaterialUtil.getDamage(trade.getItemStack()) == MaterialUtil.getDamage(player.getBase().getItemInHand()) && trade.getItemStack().getEnchantments().equals(player.getBase().getItemInHand().getEnchantments())) {
final int amount = trade.getItemStack().getAmount();
if (player.getBase().getInventory().containsAtLeast(trade.getItemStack(), amount)) {
final ItemStack stack = player.getBase().getItemInHand().clone();
@@ -101,7 +102,7 @@ public class SignTrade extends EssentialsSign {
protected boolean onSignBreak(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException, MaxMoneyException {
final String signOwner = sign.getLine(3);
final boolean isOwner = signOwner.length() > 3 && signOwner.substring(2).equalsIgnoreCase(username);
final boolean isOwner = isOwner(ess, player, sign, 3, "§8");
final boolean canBreak = isOwner || player.isAuthorized("essentials.signs.trade.override");
final boolean canCollect = isOwner || player.isAuthorized("essentials.signs.trade.override.collect");
@@ -115,8 +116,8 @@ public class SignTrade extends EssentialsSign {
return true;
}
final Map<Integer, ItemStack> withdraw1 = stored1.pay(player, OverflowType.RETURN);
final Map<Integer, ItemStack> withdraw2 = stored2.pay(player, OverflowType.RETURN);
final Map<Integer, ItemStack> withdraw1 = stored1.pay(player, OverflowType.DROP);
final Map<Integer, ItemStack> withdraw2 = stored2.pay(player, OverflowType.DROP);
if (withdraw1 == null && withdraw2 == null) {
Trade.log("Sign", "Trade", "Break", signOwner.substring(2), stored2, username, stored1, sign.getBlock().getLocation(), player.getMoney(), ess);
@@ -205,7 +206,9 @@ public class SignTrade extends EssentialsSign {
if (!(split[1].equalsIgnoreCase("exp") || split[1].equalsIgnoreCase("xp")) && getItemStack(split[1], stackamount, ess).getType() == Material.AIR) {
throw new SignException(tl("moreThanZero"));
}
sign.setLine(index, stackamount + " " + split[1] + ":" + amount);
final String newline = stackamount + " " + split[1] + ":" + amount;
validateSignLength(newline);
sign.setLine(index, newline);
return;
}
throw new SignException(tl("invalidSignLine", index + 1));
@@ -235,27 +238,26 @@ public class SignTrade extends EssentialsSign {
}
if (split.length == 3) {
final int stackAmount = getIntegerPositive(split[0]);
if (split[1].equalsIgnoreCase("exp") || split[1].equalsIgnoreCase("xp")) {
final int stackamount = getIntegerPositive(split[0]);
int amount = getInteger(split[2]);
if (amountType == AmountType.ROUNDED) {
amount -= amount % stackamount;
amount -= amount % stackAmount;
}
if (notEmpty && (amount < 1 || stackamount < 1)) {
if (notEmpty && (amount < 1 || stackAmount < 1)) {
throw new SignException(tl("tradeSignEmpty"));
}
return new Trade(amountType == AmountType.COST ? stackamount : amount, ess);
return new Trade(amountType == AmountType.COST ? stackAmount : amount, ess);
} else {
final int stackamount = getIntegerPositive(split[0]);
final ItemStack item = getItemStack(split[1], stackamount, allowId, ess);
final ItemStack item = getItemStack(split[1], stackAmount, allowId, ess);
int amount = getInteger(split[2]);
if (amountType == AmountType.ROUNDED) {
amount -= amount % stackamount;
amount -= amount % stackAmount;
}
if (notEmpty && (amount < 1 || stackamount < 1 || item.getType() == Material.AIR || amount < stackamount)) {
if (notEmpty && (amount < 1 || stackAmount < 1 || item.getType() == Material.AIR || amount < stackAmount)) {
throw new SignException(tl("tradeSignEmpty"));
}
item.setAmount(amountType == AmountType.COST ? stackamount : amount);
item.setAmount(amountType == AmountType.COST ? stackAmount : amount);
return new Trade(item, ess);
}
}
@@ -334,20 +336,18 @@ public class SignTrade extends EssentialsSign {
}
if (split.length == 3) {
final int stackAmount = getIntegerPositive(split[0]);
if (split[1].equalsIgnoreCase("exp") || split[1].equalsIgnoreCase("xp")) {
final int stackamount = getIntegerPositive(split[0]);
final String newline = stackamount + " " + split[1] + ":" + value.intValueExact();
final String newline = stackAmount + " " + split[1] + ":" + value.intValueExact();
validateSignLength(newline);
sign.setLine(index, newline);
return;
} else {
final int stackamount = getIntegerPositive(split[0]);
getItemStack(split[1], stackamount, ess);
final String newline = stackamount + " " + split[1] + ":" + value.intValueExact();
getItemStack(split[1], stackAmount, ess);
final String newline = stackAmount + " " + split[1] + ":" + value.intValueExact();
validateSignLength(newline);
sign.setLine(index, newline);
return;
}
return;
}
throw new SignException(tl("invalidSignLine", index + 1));
}
@@ -15,12 +15,10 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
public class HelpInput implements IText {
private static final Logger logger = Logger.getLogger("Essentials");
private final transient List<String> lines = new ArrayList<>();
private final transient List<String> chapters = new ArrayList<>();
private final transient Map<String, Integer> bookmarks = new HashMap<>();
@@ -121,7 +119,7 @@ public class HelpInput implements IText {
} catch (final NullPointerException ignored) {
} catch (final Exception ex) {
if (!reported) {
logger.log(Level.WARNING, tl("commandHelpFailedForPlugin", pluginNameLow), ex);
ess.getLogger().log(Level.WARNING, tl("commandHelpFailedForPlugin", pluginNameLow), ex);
}
reported = true;
}
@@ -1,7 +1,6 @@
package com.earth2me.essentials.updatecheck;
import com.earth2me.essentials.Essentials;
import com.google.common.base.Charsets;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
@@ -13,6 +12,7 @@ import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@@ -23,6 +23,12 @@ public final class UpdateChecker {
private static final String REPO = "EssentialsX/Essentials";
private static final String BRANCH = "2.x";
private static final String LATEST_RELEASE_URL = "https://api.github.com/repos/" + REPO + "/releases/latest";
private static final String LATEST_RELEASE_PROXY_URL = "https://webapi.essentialsx.net/api/v1/github/essx-v2/releases/latest";
// 0 = base for comparison, 1 = head for comparison - *not* the same as what this class calls them
private static final String DISTANCE_URL = "https://api.github.com/repos/EssentialsX/Essentials/compare/{0}...{1}";
private static final String DISTANCE_PROXY_URL = "https://webapi.essentialsx.net/api/v1/github/essx-v2/compare/{0}/{1}";
private final Essentials ess;
private final String versionIdentifier;
private final String versionBranch;
@@ -70,11 +76,11 @@ public final class UpdateChecker {
return pendingDevFuture;
}
pendingDevFuture = new CompletableFuture<>();
new Thread(() -> {
ess.runTaskAsynchronously(() -> {
pendingDevFuture.complete(cachedDev = fetchDistance(BRANCH, getVersionIdentifier()));
pendingDevFuture = null;
lastFetchTime = System.currentTimeMillis();
}).start();
});
return pendingDevFuture;
}
return CompletableFuture.completedFuture(cachedDev);
@@ -86,24 +92,22 @@ public final class UpdateChecker {
return pendingReleaseFuture;
}
pendingReleaseFuture = new CompletableFuture<>();
new Thread(() -> {
ess.runTaskAsynchronously(() -> {
catchBlock:
try {
final HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + REPO + "/releases/latest").openConnection();
connection.connect();
final HttpURLConnection connection = tryRequestWithFallback(LATEST_RELEASE_URL, LATEST_RELEASE_PROXY_URL);
if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
// Locally built?
pendingReleaseFuture.complete(cachedRelease = new RemoteVersion(BranchStatus.UNKNOWN));
break catchBlock;
}
if (connection.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) {
// Github is down
} else if (connection.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR || connection.getResponseCode() == HttpURLConnection.HTTP_FORBIDDEN) {
// GitHub is down or rate limit exceeded
pendingReleaseFuture.complete(new RemoteVersion(BranchStatus.ERROR));
break catchBlock;
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
latestRelease = new Gson().fromJson(reader, JsonObject.class).get("tag_name").getAsString();
pendingReleaseFuture.complete(cachedRelease = fetchDistance(latestRelease, getVersionIdentifier()));
} catch (JsonSyntaxException | NumberFormatException e) {
@@ -116,7 +120,7 @@ public final class UpdateChecker {
}
pendingReleaseFuture = null;
lastFetchTime = System.currentTimeMillis();
}).start();
});
return pendingReleaseFuture;
}
return CompletableFuture.completedFuture(cachedRelease);
@@ -138,43 +142,64 @@ public final class UpdateChecker {
return latestRelease;
}
private HttpURLConnection tryRequestWithFallback(final String githubUrl, final String fallbackUrl) throws IOException {
HttpURLConnection connection = (HttpURLConnection) new URL(githubUrl).openConnection();
try {
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_INTERNAL_ERROR && connection.getResponseCode() != HttpURLConnection.HTTP_FORBIDDEN) {
// Connection succeeded without any errors from GitHub's side.
return connection;
}
} catch (IOException ignored) {
}
// Connection failed, GitHub's down or we hit a ratelimit, so use the fallback URL
// If the fallback fails, let the exception or error status bubble up
connection = (HttpURLConnection) new URL(fallbackUrl).openConnection();
connection.connect();
return connection;
}
private RemoteVersion tryProcessDistance(final HttpURLConnection connection) throws IOException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
final JsonObject obj = new Gson().fromJson(reader, JsonObject.class);
switch (obj.get("status").getAsString()) {
case "identical": {
return new RemoteVersion(BranchStatus.IDENTICAL, 0);
}
case "ahead": {
return new RemoteVersion(BranchStatus.AHEAD, 0);
}
case "behind": {
return new RemoteVersion(BranchStatus.BEHIND, obj.get("behind_by").getAsInt());
}
case "diverged": {
return new RemoteVersion(BranchStatus.DIVERGED, obj.get("behind_by").getAsInt());
}
default: {
return new RemoteVersion(BranchStatus.UNKNOWN);
}
}
} catch (JsonSyntaxException | NumberFormatException e) {
e.printStackTrace();
return new RemoteVersion(BranchStatus.ERROR);
}
}
private RemoteVersion fetchDistance(final String head, final String hash) {
try {
final HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + REPO + "/compare/" + head + "..." + hash).openConnection();
connection.connect();
final HttpURLConnection connection = tryRequestWithFallback(MessageFormat.format(DISTANCE_URL, head, hash), MessageFormat.format(DISTANCE_PROXY_URL, head, hash));
if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
// Locally built?
return new RemoteVersion(BranchStatus.UNKNOWN);
}
if (connection.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR || connection.getResponseCode() == HttpURLConnection.HTTP_FORBIDDEN) {
} else if (connection.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR || connection.getResponseCode() == HttpURLConnection.HTTP_FORBIDDEN) {
// GitHub is down or we hit a local rate limit
return new RemoteVersion(BranchStatus.ERROR);
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) {
final JsonObject obj = new Gson().fromJson(reader, JsonObject.class);
switch (obj.get("status").getAsString()) {
case "identical": {
return new RemoteVersion(BranchStatus.IDENTICAL, 0);
}
case "ahead": {
return new RemoteVersion(BranchStatus.AHEAD, 0);
}
case "behind": {
return new RemoteVersion(BranchStatus.BEHIND, obj.get("behind_by").getAsInt());
}
case "diverged": {
return new RemoteVersion(BranchStatus.DIVERGED, obj.get("behind_by").getAsInt());
}
default: {
return new RemoteVersion(BranchStatus.UNKNOWN);
}
}
} catch (JsonSyntaxException | NumberFormatException e) {
e.printStackTrace();
return new RemoteVersion(BranchStatus.ERROR);
}
return tryProcessDistance(connection);
} catch (IOException e) {
e.printStackTrace();
return new RemoteVersion(BranchStatus.ERROR);
@@ -0,0 +1,71 @@
package com.earth2me.essentials.utils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import net.ess3.api.IEssentials;
import org.bukkit.command.Command;
import org.bukkit.command.FormattedCommandAlias;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.plugin.Plugin;
import java.util.Map;
public final class CommandMapUtil {
private static final Gson GSON = new GsonBuilder()
.setPrettyPrinting()
.create();
private CommandMapUtil() {
throw new UnsupportedOperationException();
}
public static String toJsonPretty(IEssentials ess, Map<String, Command> knownCommandMap) {
final JsonObject json = toJson(ess, knownCommandMap);
return GSON.toJson(json);
}
public static JsonObject toJson(IEssentials ess, Map<String, Command> knownCommandMap) {
final JsonObject json = new JsonObject();
for (Map.Entry<String, Command> entry : knownCommandMap.entrySet()) {
json.add(entry.getKey(), toJson(ess, entry.getValue()));
}
return json;
}
public static JsonObject toJson(IEssentials ess, Command value) {
if (value == null) {
return null;
}
final JsonObject json = new JsonObject();
json.addProperty("name", value.getName());
json.addProperty("description", value.getDescription());
json.addProperty("type", value.getClass().getSimpleName());
json.addProperty("raw", value.toString());
if (value.getClass().getSimpleName().equals("VanillaCommandWrapper")) {
json.addProperty("source", "vanilla");
} else if (value.getClass().getName().contains("org.spigotmc")) {
json.addProperty("source", "spigot");
} else if (value instanceof PluginCommand) {
final Plugin plugin = ((PluginCommand) value).getPlugin();
json.addProperty("source", plugin.getName() + " " + plugin.getDescription().getVersion());
} else if (value instanceof BukkitCommand) {
json.addProperty("source", "bukkit");
} else if (value instanceof FormattedCommandAlias) {
json.addProperty("source", "commands.yml");
final JsonArray formatStrings = new JsonArray();
for (final String entry : ess.getFormattedCommandAliasProvider().getFormatStrings((FormattedCommandAlias) value)) {
formatStrings.add(new JsonPrimitive(entry));
}
json.add("bukkit_aliases", formatStrings);
}
return json;
}
}
@@ -27,6 +27,7 @@ public final class FormatUtil {
private static final Pattern URL_PATTERN = Pattern.compile("((?:(?:https?)://)?[\\w-_\\.]{2,})\\.([a-zA-Z]{2,3}(?:/\\S+)?)");
//Used to strip ANSI control codes from console
private static final Pattern ANSI_CONTROL_PATTERN = Pattern.compile("\u001B(?:\\[0?m|\\[38;2(?:;\\d{1,3}){3}m|\\[([0-9]{1,2}[;m]?){3})");
private static final Pattern PAPER_CONTROL_PATTERN = Pattern.compile("(?i)" + (char) 0x7f + "[0-9A-FK-ORX]");
private FormatUtil() {
}
@@ -54,6 +55,13 @@ public final class FormatUtil {
return stripColor(input, ANSI_CONTROL_PATTERN);
}
public static String stripPaper(final String input) {
if (input == null) {
return null;
}
return stripColor(input, PAPER_CONTROL_PATTERN);
}
//This is the general permission sensitive message format function, checks for urls.
public static String formatMessage(final IUser user, final String permBase, final String input) {
if (input == null) {
@@ -218,12 +226,12 @@ public final class FormatUtil {
final EnumSet<ChatColor> strip = EnumSet.complementOf(supported);
final boolean rgb = user.isAuthorized(permBase + ".rgb");
if (!supported.isEmpty() || rgb) {
message = replaceColor(message, supported, rgb);
}
if (!strip.isEmpty()) {
message = stripColor(message, strip);
}
if (!supported.isEmpty() || rgb) {
message = replaceColor(message, supported, rgb);
}
return message;
}
@@ -1,7 +1,6 @@
package com.earth2me.essentials.utils;
import com.earth2me.essentials.IEssentials;
import com.google.common.primitives.Ints;
import net.ess3.api.IUser;
import org.bukkit.GameMode;
import org.bukkit.Location;
@@ -32,6 +31,11 @@ public final class LocationUtil {
"FLOWING_LAVA", "LAVA", "STATIONARY_LAVA");
private static final Material PORTAL = EnumUtil.getMaterial("NETHER_PORTAL", "PORTAL");
private static final Material LIGHT = EnumUtil.getMaterial("LIGHT");
private static final Material PATH = EnumUtil.getMaterial("GRASS_PATH");
private static final Material FARMLAND = EnumUtil.getMaterial("FARMLAND");
// The player can stand inside these materials
private static final Set<Material> HOLLOW_MATERIALS = EnumSet.noneOf(Material.class);
private static final Set<Material> TRANSPARENT_MATERIALS = EnumSet.noneOf(Material.class);
@@ -50,6 +54,10 @@ public final class LocationUtil {
// Barrier is transparent, but solid
HOLLOW_MATERIALS.remove(Material.BARRIER);
// Path and farmland are transparent, but solid
HOLLOW_MATERIALS.remove(PATH);
HOLLOW_MATERIALS.remove(FARMLAND);
// Light blocks can be passed through and are not considered transparent for some reason
if (LIGHT != null) {
HOLLOW_MATERIALS.add(LIGHT);
@@ -85,9 +93,13 @@ public final class LocationUtil {
}
public static Location getTarget(final LivingEntity entity) throws Exception {
return getTarget(entity, 300);
}
public static Location getTarget(final LivingEntity entity, final int maxDistance) throws Exception {
Block block = null;
try {
block = entity.getTargetBlock(TRANSPARENT_MATERIALS, 300);
block = entity.getTargetBlock(TRANSPARENT_MATERIALS, maxDistance);
} catch (final NoSuchMethodError ignored) {
} // failing now :(
if (block == null) {
@@ -232,12 +244,12 @@ public final class LocationUtil {
i++;
if (i >= VOLUME.length) {
x = origX;
y = Ints.constrainToRange(origY + RADIUS, worldMinY, worldMaxY);
y = NumberUtil.constrainToRange(origY + RADIUS, worldMinY, worldMaxY);
z = origZ;
break;
}
x = origX + VOLUME[i].x;
y = Ints.constrainToRange(origY + VOLUME[i].y, worldMinY, worldMaxY);
y = NumberUtil.constrainToRange(origY + VOLUME[i].y, worldMinY, worldMaxY);
z = origZ + VOLUME[i].z;
}
while (isBlockUnsafe(ess, world, x, y, z)) {
@@ -267,6 +279,7 @@ public final class LocationUtil {
int y = (int) Math.round(loc.getY());
final int z = loc.getBlockZ();
int count = 0;
// Check whether more than 2 unsafe block are below player.
while (LocationUtil.isBlockUnsafe(ess, world, x, y, z) && y >= ess.getWorldInfoProvider().getMinHeight(world)) {
y--;
count++;
@@ -275,7 +288,8 @@ public final class LocationUtil {
}
}
return y < 0;
// If not then check if player is in the void
return y < ess.getWorldInfoProvider().getMinHeight(world);
}
public static class Vector3D {
@@ -3,6 +3,8 @@ package com.earth2me.essentials.utils;
import org.bukkit.Bukkit;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.material.MaterialData;
import java.lang.reflect.InvocationTargetException;
@@ -11,7 +13,6 @@ import java.util.EnumSet;
import java.util.Set;
public final class MaterialUtil {
public static final Material SPAWNER = EnumUtil.getMaterial("MOB_SPAWNER", "SPAWNER");
private static final Set<Material> BEDS;
private static final Set<Material> BANNERS;
@@ -81,13 +82,15 @@ public final class MaterialUtil {
"ACACIA_SIGN", "BIRCH_SIGN",
"DARK_OAK_SIGN", "JUNGLE_SIGN",
"OAK_SIGN", "SPRUCE_SIGN",
"CRIMSON_SIGN", "WARPED_SIGN");
"CRIMSON_SIGN", "WARPED_SIGN",
"MANGROVE_SIGN");
WALL_SIGNS = EnumUtil.getAllMatching(Material.class, "WALL_SIGN",
"ACACIA_WALL_SIGN", "BIRCH_WALL_SIGN",
"DARK_OAK_WALL_SIGN", "JUNGLE_WALL_SIGN",
"OAK_WALL_SIGN", "SPRUCE_WALL_SIGN",
"CRIMSON_WALL_SIGN", "WARPED_WALL_SIGN");
"CRIMSON_WALL_SIGN", "WARPED_WALL_SIGN",
"MANGROVE_WALL_SIGN");
}
private MaterialUtil() {
@@ -129,20 +132,12 @@ public final class MaterialUtil {
return LEATHER_ARMOR.contains(material);
}
public static boolean isMobHead(final Material material, final int durability) {
if (MOB_HEADS.contains(material)) {
public static boolean isPlayerHead(final ItemStack stack) {
if (PLAYER_HEADS.contains(stack.getType())) {
return true;
}
return LEGACY_SKULLS.contains(material) && (durability != 3);
}
public static boolean isPlayerHead(final Material material, final int durability) {
if (PLAYER_HEADS.contains(material)) {
return true;
}
return LEGACY_SKULLS.contains(material) && durability == 3;
return VersionUtil.PRE_FLATTENING && LEGACY_SKULLS.contains(stack.getType()) && stack.getDurability() == 3;
}
public static boolean isPotion(final Material material) {
@@ -166,13 +161,35 @@ public final class MaterialUtil {
}
public static boolean isSkull(final Material material) {
return isPlayerHead(material, -1) || isMobHead(material, -1);
return PLAYER_HEADS.contains(material) || LEGACY_SKULLS.contains(material);
}
public static boolean isAir(final Material material) {
return material == Material.AIR || (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_14_4_R01) && material.isAir());
}
public static int getDamage(final ItemStack stack) {
if (VersionUtil.PRE_FLATTENING) {
return stack.getDurability();
}
if (stack.getItemMeta() instanceof Damageable) {
return ((Damageable) stack.getItemMeta()).getDamage();
}
return 0;
}
public static void setDamage(final ItemStack stack, final int damage) {
if (VersionUtil.PRE_FLATTENING) {
stack.setDurability((short) damage);
} else {
if (stack.getItemMeta() instanceof Damageable) {
final Damageable damageable = (Damageable) stack.getItemMeta();
damageable.setDamage(damage);
stack.setItemMeta(damageable);
}
}
}
public static Material convertFromLegacy(final int id, final byte damage) {
for (final Material material : EnumSet.allOf(Material.class)) {
if (material.getId() == id) {
@@ -119,4 +119,20 @@ public final class NumberUtil {
}
return Integer.parseInt(sInt) > 0;
}
public static boolean isNumeric(final String sNum) {
for (final char sChar : sNum.toCharArray()) {
if (!Character.isDigit(sChar)) {
return false;
}
}
return true;
}
/**
* Backport from Guava.
*/
public static int constrainToRange(int value, int min, int max) {
return Math.min(Math.max(value, min), max);
}
}
@@ -1,8 +1,12 @@
package com.earth2me.essentials.utils;
import com.google.common.primitives.Chars;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.function.Function;
import java.util.regex.Pattern;
public final class StringUtil {
@@ -85,4 +89,49 @@ public final class StringUtil {
return null;
}
public static String abbreviate(final String input, final int length) {
if (input == null) return null;
if (length < 4) throw new IllegalArgumentException("Invalid length " + length);
if (input.length() <= length) return input;
return input.substring(0, length - 3) + "...";
}
// Replacement for org.apache.commons.lang3.StringUtils.stripToNull(String)
public static String stripToNull(final String input) {
if (input == null) return null;
final String result = strip(input);
return result.isEmpty() ? null : result;
}
// Replacement for org.apache.commons.lang3.StringUtils.strip(String)
public static String strip(final String input) {
return strip(input, Character::isWhitespace);
}
// Replacement for org.apache.commons.lang3.StringUtils.strip(String, String)
public static String strip(final String input, final String stripChars) {
if (stripChars == null) return strip(input);
final List<Character> toStrip = Chars.asList(stripChars.toCharArray());
return strip(input, toStrip::contains);
}
public static String strip(final String input, Function<Character, Boolean> shouldStrip) {
if (input == null) return null;
int startIndex = 0;
int endIndex = input.length();
for (; startIndex < endIndex; startIndex++) {
if (!shouldStrip.apply(input.charAt(startIndex))) break;
}
for (; endIndex > startIndex; endIndex--) {
if (!shouldStrip.apply(input.charAt(endIndex - 1))) break;
}
return input.substring(startIndex, endIndex);
}
}
@@ -34,9 +34,13 @@ public final class VersionUtil {
public static final BukkitVersion v1_16_5_R01 = BukkitVersion.fromString("1.16.5-R0.1-SNAPSHOT");
public static final BukkitVersion v1_17_R01 = BukkitVersion.fromString("1.17-R0.1-SNAPSHOT");
public static final BukkitVersion v1_17_1_R01 = BukkitVersion.fromString("1.17.1-R0.1-SNAPSHOT");
public static final BukkitVersion v1_18_1_R01 = BukkitVersion.fromString("1.18.1-R0.1-SNAPSHOT");
public static final BukkitVersion v1_18_2_R01 = BukkitVersion.fromString("1.18.2-R0.1-SNAPSHOT");
public static final BukkitVersion v1_19_R01 = BukkitVersion.fromString("1.19-R0.1-SNAPSHOT");
public static final BukkitVersion v1_19_2_R01 = BukkitVersion.fromString("1.19.2-R0.1-SNAPSHOT");
private static final Set<BukkitVersion> supportedVersions = ImmutableSet.of(v1_8_8_R01, v1_9_4_R01, v1_10_2_R01, v1_11_2_R01, v1_12_2_R01, v1_13_2_R01, v1_14_4_R01, v1_15_2_R01, v1_16_5_R01, v1_17_1_R01, v1_18_1_R01);
private static final Set<BukkitVersion> supportedVersions = ImmutableSet.of(v1_8_8_R01, v1_9_4_R01, v1_10_2_R01, v1_11_2_R01, v1_12_2_R01, v1_13_2_R01, v1_14_4_R01, v1_15_2_R01, v1_16_5_R01, v1_17_1_R01, v1_18_2_R01, v1_19_2_R01);
public static final boolean PRE_FLATTENING = VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01);
private static final Map<String, SupportStatus> unsupportedServerClasses;
@@ -57,6 +61,10 @@ public final class VersionUtil {
// KibblePatcher - Dangerous bytecode editor snakeoil whose only use is to break plugins
builder.put("net.kibblelands.server.FastMath", SupportStatus.DANGEROUS_FORK);
// Brain-dead chat signing bypass that break EssentialsChat
builder.put("ml.tcoded.nochatreports.NoChatReportsSpigot", SupportStatus.STUPID_PLUGIN);
builder.put("me.doclic.noencryption.NoEncryption", SupportStatus.STUPID_PLUGIN);
// Akarin - Dangerous patch history;
// * Potentially unsafe saving of nms.JsonList
builder.put("io.akarin.server.Config", SupportStatus.DANGEROUS_FORK);
@@ -184,7 +192,7 @@ public final class VersionUtil {
if (!Bukkit.getName().equals("Essentials Fake Server")) {
throw new IllegalArgumentException(string + " is not in valid version format. e.g. 1.8.8-R0.1");
}
matcher = VERSION_PATTERN.matcher(v1_14_R01.toString());
matcher = VERSION_PATTERN.matcher(v1_16_1_R01.toString());
Preconditions.checkArgument(matcher.matches(), string + " is not in valid version format. e.g. 1.8.8-R0.1");
}
@@ -320,6 +328,7 @@ public final class VersionUtil {
FULL(true),
LIMITED(true),
DANGEROUS_FORK(false),
STUPID_PLUGIN(false),
NMS_CLEANROOM(false),
UNSTABLE(false),
OUTDATED(false)
@@ -52,8 +52,8 @@ public class LocalChatSpyEvent extends Event implements Cancellable {
}
/**
* Gets the format to use to display this chat message. When this event finishes execution, the first format
* parameter is the {@link Player#getDisplayName()} and the second parameter is {@link #getMessage()}
* Gets the format to use to display this chat message to spy recipients. When this event finishes execution, the
* first format parameter is the {@link Player#getDisplayName()} and the second parameter is {@link #getMessage()}
*
* @return {@link String#format(String, Object...)} compatible format string
*/
@@ -62,8 +62,8 @@ public class LocalChatSpyEvent extends Event implements Cancellable {
}
/**
* Sets the format to use to display this chat message. When this event finishes execution, the first format
* parameter is the {@link Player#getDisplayName()} and the second parameter is {@link #getMessage()}
* Sets the format to use to display this chat message to spy recipients. When this event finishes execution, the
* first format parameter is the {@link Player#getDisplayName()} and the second parameter is {@link #getMessage()}
*
* @param format {@link String#format(String, Object...)} compatible format string
* @throws IllegalFormatException if the underlying API throws the exception
+12
View File
@@ -593,6 +593,9 @@ repair-enchanted: true
# Warning: Mixing and overleveling some enchantments can cause issues with clients, servers and plugins.
unsafe-enchantments: false
# The maximum range from the player that the /tree and /bigtree commands can spawn trees.
tree-command-range-limit: 300
#Do you want Essentials to keep track of previous location for /back in the teleport listener?
#If you set this to true any plugin that uses teleport will have the previous location registered.
register-back-in-listener: false
@@ -918,6 +921,15 @@ chat:
# plots: "&dP&r"
# creative: "&eC&r"
# Whether players should be placed into shout mode by default.
shout-default: false
# Whether a player's shout mode should persist restarts.
persist-shout: false
# Whether chat questions should be enabled or not.
question-enabled: true
############################################################
# +------------------------------------------------------+ #
# | EssentialsX Protect | #
Loaded 100 of 199 files, more files were not shown because too many files have changed in this diff. Show more