Compare commits

...
349 Commits
Author SHA1 Message Date
md678685 279d6f16e1 Bump version to 2.17.2
\o/
2020-02-22 10:05:14 +00:00
md678685 a747eccaa3 Fix /fireball on 1.8.8 (#3027)
Dragon fireballs were added in 1.9 and so this previously caused an
error. This PR fixes that (and adds tridents as throwables). Fixes #3016.
2020-02-22 10:03:43 +00:00
md678685 0bafbc3184 Reduce permission check calls in PlayerCommandSendEvent (#3026)
This reduces permissions checks by only checking each command once, not checking each command for each alias.

The impact of this is a near-tenfold reduction in permission checks during this listener, which should slightly improve performance when using LuckPerms (and provide significant improvements on older inefficient permissions plugins).
2020-02-22 10:02:53 +00:00
Edward Wang 8069370b8c Clarify easter egg config description (#3028) 2020-02-21 13:12:09 -08:00
Jason 46f4b92ff7 Update config.yml group-formats (#3025)
Since most (if not all) modern permission plugins only use lowercase group names, the examples should also be lowercase. A note has also been added explaining that group names are case-sensitive.
2020-02-21 12:24:49 +00:00
md678685 d92f5ce71c Add 1.14/1.15 item aliases and fallbacks
Short term replacement for #2897 until ItemDbGenerator is complete:

* Closes #2934 by adding 1.15 items
* Closes #2790 by adding minecraft:sign fallbacks and a "sign" alias
* Closes #2732 by adding aliases and fallbacks for cactus green/green dye, dandelion yellow/yellow dye and rose red/red dye.
2020-02-21 11:11:35 +00:00
Josh Roy 2314bf8bd4 Fix CustomItemResolver causing a StackOverflowError (#3022)
CustomItemResolver was fetching the custom item from the item database instead of the resolved custom item which caused a StackOverflowError.

Fixes #3018.
2020-02-18 20:20:53 +00:00
Jasonandmd678685 7808b21496 Explain how to add commands to kits (#2980)
* Explain how to add commands to kits

* Update Essentials/src/kits.yml

Co-Authored-By: md678685 <1917406+md678685@users.noreply.github.com>

Co-authored-by: md678685 <1917406+md678685@users.noreply.github.com>
2020-02-16 15:39:28 +00:00
triagonal 18ef412211 Add beezooka command (#3003)
This PR introduces the `/beezooka` command as suggested in #2975. The command acts similarly to `/kittycannon` with the exception of the Bee being tamed, instead flying around for a small amount of time before exploding.

Sample usage:
![beezooka](https://user-images.githubusercontent.com/10545540/74099459-11804880-4b78-11ea-9c3d-499b06d912fb.gif)

As Bees do not exist below version 1.15, an error will display when attempting to run the command on such a version:
![image](https://user-images.githubusercontent.com/10545540/74099477-4d1b1280-4b78-11ea-91c2-fa675994a85f.png)

Closes #2975.
2020-02-10 11:46:41 +00:00
md678685 0678328253 Update funding to include Ko-fi link 2020-02-10 11:34:59 +00:00
md678685 5503e1e14c Revert "Split plugin compatibility report into own class"
Revert 6fa5b80c0a, which broke `/ess version`, until this can be fixed.
2020-02-10 09:05:32 +00:00
triagonal 9e89cfa4ed Implement missing FakeWorld methods (#3002) 2020-02-08 21:10:49 -08:00
imDaniX 13f454a022 Properly escape pipe character on item lore (#2994)
Using negative lookbehind instead of negated characters set.

Fixes #2962, fixes #2984
2020-02-07 10:10:54 +00:00
pop4959 129650dade Update FakeServer (#2997) 2020-02-07 12:08:29 +11:00
md678685 6fa5b80c0a Split plugin compatibility report into own class 2020-02-01 21:46:53 +00:00
pop4959 04dfcd0965 Bump supported version to 1.15.2 2020-01-22 09:14:41 +00:00
pop4959 2e818ac709 Properly register entity transform event depending on version (#2942)
Fixes the problem mentioned in #2931 which was introduced in #2836. This is caused as a result of EntityTransformEvent being a relatively new event introduced in Spigot [856adc3e6af](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/856adc3e6afc3e9c0495ac27e38b96b144e54b1e), which was after the update to 1.13.2 in Spigot [f311182396b](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/f311182396bd74b106efebc926ea4d0b92cfba80).

Closes #2931.
2020-01-14 07:54:51 +00:00
pop4959 32ef61197f Fix bed spawn message on 1.15+ (#2943)
Closes #2893

**Tests**
![2020-01-13_14 08 12](https://user-images.githubusercontent.com/17698576/72297425-be66b480-3610-11ea-8421-1ac6881259b8.png)
![2020-01-13_14 10 02](https://user-images.githubusercontent.com/17698576/72297431-c32b6880-3610-11ea-89fc-bdda2d0cec89.png)
2020-01-14 07:50:48 +00:00
md678685 fa06cd8253 Fix Java 9 breakage causing issues on Java 8 2020-01-11 17:03:33 +00:00
pop4959 5020983af5 Update GeoIP (#2926)
This implements the fix suggested by @Bobcat00 in #2919

Users of GeoIP will now be required to register a MaxMind account and create a license to download the database required by the plugin. This license is entered into the new license-key field in the configuration.

---

* Update GeoIP

* Simplify branch

* Update old config detection

* Update geoIpLicenseMissing to point to the EssX wiki
2020-01-11 07:10:40 +00:00
pop4959 f4496b6977 Update FakeWorld again (#2925)
Spigot added some new methods.
2020-01-04 12:32:40 +00:00
pop4959 552dcb56a1 Improvements for delkit (#2908)
3 improvements for delkit within this PR:

1) Cleaned up unused imports
2) Show actual kit name when deleting instead of memory address (this is the reason originally for making this)
3) Implement tab completion

I've tested to make sure the changes are properly functioning. See below:

Before:
![2019-12-29_01 12 09](https://user-images.githubusercontent.com/17698576/71555204-4bd5c200-29de-11ea-9fe3-eb88db08ef48.png)

After:
![2019-12-29_01 48 50](https://user-images.githubusercontent.com/17698576/71555207-56905700-29de-11ea-9277-271bb0656d64.png)
![2019-12-29_01 48 25](https://user-images.githubusercontent.com/17698576/71555208-58f2b100-29de-11ea-8257-742fa7bb3150.png)
2019-12-31 16:10:38 +00:00
montlikadani e158a65603 Improve scheduler methods to use Java 1.8 lambdas (#2700)
* Update EssentialsPlayerListener.java

* Update Backup.java
2019-12-31 13:58:09 +00:00
CmdrKittens b694e8aaa2 Don't attempt to modify a Map value view (#2910)
md dun goofed
2019-12-29 19:41:17 +00:00
md678685 a2e09121ba Slightly nicer AntiBuild messages 2019-12-26 16:17:10 +00:00
md678685 4ce7dfa8f0 Minor refactor of permissions handlers
* Move `essentials.build` perm check from AntiBuild into default SuperPerms handler
* Don't emulate wildcards for LuckPerms or PEX
* Add `build: true` meta support for LuckPerms (+ other plugins as needed)
2019-12-26 15:08:07 +00:00
md678685 1c4ce7b4bd Don't assume primary group is always present
Fixes a potential issue with PEX 2.0 (and 1.x) where users may not have a primary group.
Closes #2901.
2019-12-26 13:08:38 +00:00
md678685 8a04c1e232 Fix custom_items.yml generation 2019-12-24 23:02:07 +00:00
md678685 6e5d378324 Add methods to set/remove custom aliases 2019-12-24 09:36:15 +00:00
md678685 8e1f3617fd Add custom_items.yml file 2019-12-24 09:36:15 +00:00
Mark Vadeikaandmd678685 2549ed830f Enable control of entity transformations in EssentialsProtect (#2836)
This allows users to prevent any of the following transformations:

- Creeper charging
- Villager infected by zombie villagers
- Villager being cured
- Villagers turning into witches
- Pigs turning into zombie pigmen
- Zombies turning into Drowned (and husks turning into Zombies)
- Mooshrooms switching colors

Configurations are in a new subsection, `protect.prevent.transformation`. All options are disabled by default.

---

* Allow for control of transformations

* Undid removal of villager checking

* Undid removal of villager checking

* Documentation for transformation configs

Co-Authored-By: md678685 <1917406+md678685@users.noreply.github.com>

* Removed duplicate configuration lines

* Updated info about husks drowning

* Changed config names

Co-authored-by: md678685 <1917406+md678685@users.noreply.github.com>
2019-12-23 13:55:05 +00:00
Josh Roy 0ebd64d314 Add a cause enum to UserBalanceUpdateEvent (#2824)
Basically, I just needed this for one of my plugins; otherwise, this could be useful for people using this event who want to see where the user's balance is being updated from.

---

* Add UserBalanceUpdateEvent.Cause
* Add special cause enum
* Add API Cause
2019-12-23 13:16:34 +00:00
Mark Vadeika 843ecb4a42 Escape pipe character on item lore (#2831)
I just adjusted the regex used to split the item lore into multiple lines in order to allow escaping of the pipe character using \|.

Fixes #2830.
2019-12-23 13:15:26 +00:00
md678685 a1a0d34940 Attempt to parse input as UUID in loop commands (#2606)
Related: #2424
2019-12-23 13:06:15 +00:00
md678685 15bb978dab Remove unused VersionUtil constants 2019-12-22 23:55:25 +00:00
md678685 6a7cf39548 Fix wrong filename in ManagedFile error message 2019-12-22 23:53:36 +00:00
pop4959 8ccb70d07d Add phantoms to protect.prevent.spawn (#2806)
Closes #2733.
2019-12-22 22:13:26 +00:00
dashaw92 45461a93b0 Correct unbanip's permission for broadcasts 2019-12-22 22:11:44 +00:00
Joe Hirschfeld b3a54a78bc Save materials in unlimited by name
There was a mistake where materials in unlimited would instead be saved
as a bukkit Material instead of its name. Instead, save it by the name.
2019-12-22 22:10:30 +00:00
AgentTroll a4182b5ff9 Correct check for command cooldowns list in userdata 2019-12-20 12:44:10 +00:00
pop4959 215dcde4b9 Update to 1.15.1 2019-12-19 12:38:18 +00:00
md678685 67b2a9a4f4 Build with GitHub Actions (#2800)
* Add GitHub Actions workflow

* Update workflow

* Run BuildTools in workflow

* Update build.yml

* Add distributionManagement to pom.xml

* Add GitHub registry Maven credentials

* Remove Travis CI config

* mkdir -p

* Remove GitHub package registry push

Didn't work anyway

* Remove distributionManagement

* Cache Maven repo

* Fix step order

* Use JitPack for VaultAPI
2019-12-16 14:23:00 +00:00
Johnny Cao 3b51b23ac2 Block gamemode changes for jailed players (#2875)
Blocks players from experiencing any gamemode changes while they are jailed.

Fixes #1996.
2019-12-12 07:37:13 +00:00
Johnny Cao e0f19f8121 Allow players to set single word AFK message - fixes #2712 (#2876)
Allows players with "essentials.afk.others" to toggle afk themselves with a single word message
2019-12-11 19:20:56 +00:00
Madis Otenurm e720fb528a Crowdin in readme (#2877)
* Crowdin for readme

* Update README.md
2019-12-11 19:04:12 +00:00
md678685 518a5454c6 Add missing FakeWorld methods 2019-12-11 08:48:45 +00:00
Josh Roy 2d9c846084 Update to 1.15 (#2873)
* Compile against 1.15

* Remove achievement related methods for OfflinePlayer

* Add 1.15 to VersionUtil

* Revert "Remove achievement related methods for OfflinePlayer"

This reverts commit d0ab84e0

* Add 1.15 Mobs

* Remove Achievement related methods from OfflinePlayer

This needs more work as this currently breaks > 1.15 support

* Actually this isn't a problem
2019-12-11 07:47:56 +00:00
md678685 59e30f05fc Merge pull request #2871 from AgentTroll/patch-mockito
Update Mockito to allow tests to pass in newer versions of Java
2019-12-10 07:48:07 +00:00
AgentTroll 0f1085a02d Update Mockito to allow tests to pass in newer versions of Java 2019-12-09 20:55:55 -05:00
Glare 882699919e Reimplement spawn-if-no-home config option (#2757)
This reimplements the `spawn-if-no-home` config option from the original Essentials plugin. If set to true, running `/home` without having set a home will send the player to spawn (previous behaviour). If set to false, running `/home` will instead show an error message and not teleport the player anywhere.

Closes #1452.
2019-10-20 09:12:53 +01:00
Ryan f6a70a542e Implements missing createExplosion methods in FakeWorld (#2818) 2019-10-13 14:35:38 -07:00
triagonal bae909ba10 implement missing OfflinePlayer methods 2019-09-24 15:51:43 +01:00
triagonal dbb9757a9f add {USERNAME} placeholder to chat format 2019-09-23 06:20:28 +01:00
md678685 deaeb46ce9 Implement missing FakeWorld methods 2019-08-28 21:14:06 +01:00
md678685 219012bc35 Set item meta in setSkullOwner before returning
*Should* address #2765.
2019-08-28 15:26:23 +01:00
md678685 5f9eb22d23 Fix player head meta on versions below 1.13 2019-08-24 10:05:26 +01:00
md678685 2c33fb6834 Correctly return null for invalid IDs when doing legacy conversion 2019-08-13 15:12:04 +01:00
md678685 8bcef6022b Add max-projectile-speed option
Projectils can load chunks pretty intensively if too fast.
2019-08-05 19:56:25 +01:00
md678685 93d36779f0 Implement regex-based nickname blacklist
Adds `nick-blacklist` list to config which takes phrases or regexes. Users with essentials.nick.blacklist.bypass can bypass the blacklist.
2019-08-05 19:01:48 +01:00
Glare 2502f5e6f2 Check if user has a permission to block putting X item on their head. (#2574)
Closes #2550. 

* Check if user has a permission to block putting X item on their head.
* Forced the material name to be lower case.
* Fixed a typo in the message.
* Updated permission node and added check to the EssentialsPlayerListener.
2019-08-05 16:19:03 +01:00
triagonal 95f2852cf3 Implement toggle for command block logging (#2599)
Just a simple config toggle for whether or not command block commands should be logged.

closes #1153, closes #162

---

* Add toggle for command block logs
* update setting name
2019-08-05 16:17:22 +01:00
md678685 ff9f712d65 Add per-projectile permissions and speed argument to /fireball 2019-08-05 16:12:32 +01:00
Mickey42302 60c4e75a1c Add Dragon Fireballs to "/fireball". 2019-08-05 16:12:32 +01:00
md678685 ccf7c48bf1 Add aliases to /delkit 2019-08-05 15:35:32 +01:00
md678685 65d81eb31e Clean up /essentials 2019-08-05 15:25:55 +01:00
md678685 b97eb12dfc Implement /delkit command
Closes #2709, closes #2719.
2019-08-05 14:06:37 +01:00
md678685 d2724d77df URGENT: critical bug fix 2019-08-02 16:05:41 +01:00
md678685 119b21ac67 Check plugin equals rather than name equals in autocomplete listener 2019-08-01 14:57:48 +01:00
md678685 1ff73b3837 Bump version to 2.17.1 2019-07-30 18:10:27 +01:00
Glare d98f8b3467 Fixed dupe on new builds. (#2696)
Fixes #2695.
2019-07-30 12:56:46 +01:00
md678685 ac8b8861cb Merge remote-tracking branch 'origin/2.x' into 2.x 2019-07-28 16:18:00 +01:00
md678685 22dc5dcebd Fix /r not showing in 1.13+ tab complete
Fixes #2659.
2019-07-28 15:00:49 +01:00
Josh Roy 3c09e72ce4 Bump supported 1.14.x version to 1.14.4 (#2681) 2019-07-20 00:48:13 -07:00
pop4959 fffc3fcac7 Implement missing methods in FakeWorld (#2679) 2019-07-18 11:56:00 -07:00
md678685 bcdbbe9546 Fix wall sign protection on 1.12.2 and below
Fixes #2635.
2019-06-27 15:50:04 +01:00
md678685 19f03cd70e Add missing /tpauto messages
Add messages from #2310 to the `messages.properties` file. Fixes #2634.
2019-06-27 12:00:47 +01:00
md678685 9b7858b830 Update README.md 2019-06-26 22:13:10 +01:00
md678685 8bc55387dd Bump version to 2.17.0 2019-06-26 16:50:11 +01:00
md678685 0584353bfa Bump version to 2.17-pre1 2019-06-26 15:32:08 +01:00
md678685 2938330222 Load and save kit use timestamps consistently
Fixes #2301.

The kit's name was previously sanitised/lowercased when accessed but not when saved. This fixes that. ensuring the kit delay will be reported correctly.

Tested on 1.14.3 - does not appear to break existing kit delays.
2019-06-26 12:54:19 +01:00
md678685 ef7393036e Update to 1.14.3 2019-06-26 11:49:10 +01:00
Josh Roy 0409f5bc4a Update 1.14.3 version string (#2624)
Closes #2624.
2019-06-26 11:48:50 +01:00
Josh Roy 8ff1ebd7c2 Fix version regex on 1.14.3 (#2622) @JRoy 2019-06-25 07:18:16 +01:00
md678685 9089fe8be3 Attempt to fall back to Material.getMaterial(int) below 1.13
Fixes #2615.
2019-06-24 09:41:33 +01:00
Johnny Cao 74d96ce624 Fixes #2121 - Allow players to teleport into a location with water if configured (#2520)
# Description of #2520
This is a continuation of #2457, accidentally hit rebase and recommitted a load of commits from the 2.x log into my repo...

I've reverted the code and added the configuration option, modifying the `LocationUtil#HOLLOW_MATERIALS` as necessary when the config is loaded.

New demo: streamable.com/pm50r
```
[16:01:00 INFO]: Server version: 1.13.2-R0.1-SNAPSHOT git-Spigot-3cb9dcb-77ca7ca (MC: 1.13.2)
[16:01:00 INFO]: EssentialsX version: 2.16.1.154
[16:01:00 INFO]: Vault is not installed. Chat and permissions may not work.
```

# Description of #2457
Fixes #2121.

Prior to the addition of this patch, teleporting from another world through commands such as `/spawn` and `/home` would cause players to be teleported to the surface of the water. After this patch, using the same command will correctly teleport them to the original location.

In seeing that the addition of water would cause the `HOLLOW_MATERIALS` set to be identical to the `TRANSPARENT_MATERIALS`, I have removed the latter's usage and simply added water to the former.

I'm not exactly sure if adding water to `HOLLOW_MATERIALS` is the right decision, but it fixes the issue, and I personally don't really see any point in not having water in the list. I imagine some people might use this as a way to drop players on the surface of the water, but they can fix that issue quite easily by actually going to the surface and setting the location there. I also can see that water is not necessarily a "safe" location because players can drown, but I really see no other alternative. 

The only reason it works like normal in the same world is because the safe location method exempts locations in the same world as the teleporting player, and thus this check is never even performed in the first place for those players anyway.

**Demo**
```
[16:22:49 INFO]: CONSOLE issued server command: /ess version
[16:22:49 INFO]: Server version: 1.13.2-R0.1-SNAPSHOT git-Paper-"16db0e6a" (MC: 1.13.2)
[16:22:49 INFO]: EssentialsX version: 2.16.1.9
[16:22:49 INFO]: LuckPerms version: 4.3.73
[16:22:49 INFO]: Vault is not installed. Chat and permissions may not work.
```
https://streamable.com/71072
2019-06-17 11:28:12 +01:00
md678685 8b7bcbb880 Don't update user activity on physical interactions
Fixes #2578.
2019-06-17 11:06:45 +01:00
md678685 dbd86155fb Only accept square recipes in /condense
Fixes #1194.
2019-06-16 13:28:02 +01:00
md678685 9b77c0802b Switch Travis to openjdk8 2019-06-16 11:25:25 +01:00
md678685 cd7fa79560 Don't warn about CloudNet SLPEs
Fixes #2592.
2019-06-16 11:13:32 +01:00
md678685 10e9879a64 Update to 1.14.x (#2510)
Add support for Spigot/Paper 1.14.2.
2019-06-16 10:15:12 +01:00
md678685 d1dcc47a27 Specify Java 8 for Travis build
Required due to BuildTools not supporting Java 9 or above for MC 1.8.x.
2019-06-16 10:12:35 +01:00
Pokechu22 7a73301a37 Add permissions for individual colors (#1441)
* Add tests for existing format behavior

* Replace formatting implementation

* Add permissions for individual color codes

Resolves #415

* Use format code names

* Fix escaping

* Mockito: test scope only

* Explicitly check the .magic permission

Once I switch to checking if a perm's set in the loop, the explicit check is needed for an * perm.

* Add support for removing individual colors

* Use `obfuscated` as the name for §k

`magic` is still accepted as the group name, so this is not a breaking change.
2019-06-09 15:56:58 +01:00
md678685 e1dec7d9e7 Fix items.json merging 2019-06-09 15:34:24 +01:00
md678685 99fefdb47d Re-add header to items.json 2019-06-09 15:18:16 +01:00
md678685 5ebce8965e Merge 1.13 and 1.14 items.json together
In 2.17.0, [essx-scripts genItemsFlat](https://github.com/md678685/essx-scripts/blob/master/src/genItemsFlat.js) is being replaced with [ItemDbGenerator](https://github.com/md678685/ItemDbGenerator). To ease migration, this is a file generated by merging the 1.14 entries from the new generator into the existing 1.13 file. This will be replaced by an items.json generated entirely by ItemDbGenerator eventually.
2019-06-09 15:10:12 +01:00
md678685 5a0b7285d4 Add FUNDING.yml Patreon link 2019-06-09 13:04:51 +01:00
md678685 829110e89a Implement missing OfflinePlayer methods 2019-06-09 12:59:32 +01:00
md678685 dc1a0b65fa Merge branch 'mc/1.14' of https://github.com/EssentialsX/Essentials into mc/1.14 2019-06-09 12:58:06 +01:00
md678685 b140826e60 Remove unused import in MaterialUtil 2019-06-09 12:21:40 +01:00
md678685 0d9387458d Remove unused import in AFK event 2019-06-09 12:21:25 +01:00
md678685 f2447a9134 Add fallbacks property to ItemData
Allows items.json to specify fallback names for materials on older versions.

Additionally make non-API methods inaccessible, as they shouldn't be needed by other plugins.
2019-05-31 15:57:51 +01:00
md678685 2ea3d8943e Update outdated meme 2019-05-30 19:34:18 +01:00
Drew Mitchell e4cc78a750 Implement PR #1682 - TPA Event (#1727) @DrewAMitchell
* Attempts to implement #1682 - TPARequestEvent
Awaiting further feedback. I've implemented the event, and elected to send a message to the requester of the TPA when the event gets cancelled.
* Fix formatting
* Fix up l18s errors, remove todos
* Clean up for merge
2019-05-30 19:17:57 +01:00
md678685 a08832cfc8 Implement /itemname command (#2573)
Implement /itemname command, across three PRs. Originally implemented by SupaHam, and updated by zsturgess and myself.
2019-05-30 19:16:43 +01:00
md678685 c97918df24 Add safe-usermap-names option to control usermap key sanitisation
This is necessary to stop players with Chinese characters in their username losing their balances.
2019-05-30 18:50:51 +01:00
Glare e9833d1cd2 Implement essentials.balancetop.exclude permission (#2499)
Closes #595.
2019-05-30 15:20:30 +01:00
md678685 111a18585d Allow clearing item names + add locale messages for /itemname 2019-05-30 15:12:52 +01:00
Zac Sturgess 155d3ec938 Update /itemname in plugin.yml
This contains changes from #2555 squashed into one commit.

Closes #2555.
2019-05-30 14:53:15 +01:00
Ali Moghnieh 8bafacbd51 Create /itemname command that names held items.
This contains changes from #672 minus messages, squashed into one commit.

Closes #672.
2019-05-30 14:53:06 +01:00
montlikadani 0e3f48ee54 Improve disposal, /bigtree and /fireball (#2461) @montlikadani
* Allow the Disposal inventory title to be configurable
* Add darkoak to `/bigtree`'s usage message
* Allow potions to be fired with `/fireball`

## Commits
* Update plugin.yml
* Update Commanddisposal.java
* Update messages.properties
* Update Commandfireball.java
* Update SignDisposal.java
* Fix import
* Remove colour code from disposal message
2019-05-30 14:03:12 +01:00
Trent Hensler b566b4a0c6 Update translations from Crowdin (#2571)
* New translations messages.properties (German)
* New translations messages.properties (Romanian)
* New translations messages.properties (Korean)
* New translations messages.properties (Latvian)
* New translations messages.properties (Lithuanian)
* New translations messages.properties (Norwegian)
* New translations messages.properties (Polish)
* New translations messages.properties (Portuguese)
* New translations messages.properties (Portuguese, Brazilian)
* New translations messages.properties (Russian)
* New translations messages.properties (Italian)
* New translations messages.properties (Serbian (Cyrillic))
* New translations messages.properties (Serbian (Latin))
* New translations messages.properties (Slovak)
* New translations messages.properties (Spanish)
* New translations messages.properties (Swedish)
* New translations messages.properties (Thai)
* New translations messages.properties (Turkish)
* New translations messages.properties (Japanese)
* New translations messages.properties (Icelandic)
* New translations messages.properties (Dutch)
* New translations messages.properties (Bulgarian)
* New translations messages.properties (Vietnamese)
* New translations messages.properties (French)
* New translations messages.properties (Hungarian)
* New translations messages.properties (English, United Kingdom)
* New translations messages.properties (English, United States)
* New translations messages.properties (Basque)
* New translations messages.properties (Bosnian)
* New translations messages.properties (Chinese Simplified)
* New translations messages.properties (Hebrew)
* New translations messages.properties (Chinese Traditional)
* New translations messages.properties (Chinese Traditional, Hong Kong)
* New translations messages.properties (Croatian)
* New translations messages.properties (Czech)
* New translations messages.properties (Danish)
* New translations messages.properties (Estonian)
* New translations messages.properties (Finnish)
* New translations messages.properties (Greek)
* New translations messages.properties (Ukrainian)
2019-05-28 17:56:17 +01:00
md678685 a9ed66d5e0 Add essentials.keepinv to plugin.yml 2019-05-28 12:24:07 +01:00
Josh Roy 94131edb32 Bump Bukkit to 1.14.2 (#2569)
* Bump to API 1.14.2

* Update v1_14_2_R01 as latest supported 1.14 build
2019-05-27 23:12:23 +01:00
md678685 e21863956c Fix checking for attached wall signs 2019-05-27 11:51:56 +01:00
md678685 4201e6ef85 Make all events async when not on primary thread
Fixes #2566, fixes #2556, fixes #2545.
2019-05-26 12:08:58 +01:00
Trent Hensler 5deb1de555 Allow AFK status test to pass. 2019-05-22 12:06:27 -07:00
md678685 c65534ebb1 Only make AfkStatusChangeEvent async when off primary thread 2019-05-22 11:39:26 +01:00
md678685 f22efce3ca Use MobCompat entries for other 1.11+ mobs 2019-05-18 23:51:40 +01:00
md678685 5f0909047d Use MobCompat.CAT throughout MobData 2019-05-18 22:45:43 +01:00
md678685 7cc4dc2f07 Make AfkStatusChangeEvent async 2019-05-18 20:56:57 +01:00
md678685 60ebe9e738 Add llama colour support; improve support for old game versions
Fixes issues with /spawnmob on older versions of the game.

(Also add llama colours, which were missing from the 1.11 update.)
2019-05-18 20:56:34 +01:00
minksuki a1297feb9d adds a permission node that keeps a player's inventory on death (#2531) @minksuki
Closes #2524.

Adds a permission node, `essentials.keepinv` so on player death their inventory will not be wiped.
2019-05-15 07:59:48 +01:00
Josh Roy 09598d0173 Update Bukkit to 1.14.1 (#2544)
* Update v1_14_1_R01 as latest supported 1.14 build

* Bump to API 1.14.1
2019-05-14 09:00:22 +01:00
md678685 35fc845040 Fix Metrics plugin name reporting 2019-05-13 19:15:33 +01:00
md678685 e59950966f Fix Metrics package name 2019-05-13 19:14:01 +01:00
md678685 98cc5b33a3 Update bStats Metrics to latest version
Now featuring server brand support!
2019-05-12 16:17:00 +01:00
Julian van Doorn d107d00ac3 Fix spawning shields with enchantments (#2515) @Argetan
* Moved comment to newline for style consistency.
* Fixed issue 2507 by checking if an enchantment is being applied.
* Added a couple newlines for readability.
* Removed faulty ifs).
2019-05-12 13:50:35 +01:00
md678685 ccc000a416 Add Villager variants, pt 2 2019-05-09 22:20:45 +01:00
md678685 7790f8818b Add Villager variants, pt 1 2019-05-09 15:12:51 +01:00
JRoy 72ca629cf1 Add 1.14 Enchantments 2019-05-09 13:36:09 +01:00
md678685 65017d7f5c Fix /kittycannon
The most important command of all!

(This hasn't been tested with 1.13 or below yet.)
2019-05-08 23:29:55 +01:00
md678685 6d4f7afc79 Improve VersionUtil prerelease handling
Actually includes updated regex this time! (I have no idea how I forgot to update it in cfba203981 - I had already written out the regex)

Incorporates part of https://github.com/EssentialsX/Essentials/pull/2523 - thanks @JRoy.
2019-05-08 23:26:40 +01:00
md678685 4fcb032791 Update FakeServer 2019-05-08 23:23:15 +01:00
md678685 0e668fa0f2 Fix plural suffixes for fish and foxes 2019-05-08 23:06:50 +01:00
md678685 68b933a501 Add Ocelot.Type fallbacks for all MobCompat.CatTypes 2019-05-08 23:06:28 +01:00
md678685 5236ad9f64 Remove redundant BABY_FOX 2019-05-08 22:56:25 +01:00
md678685 937c18fe1d Update FakeWorld 2019-05-08 22:43:57 +01:00
md678685 fb48aaba9d Initial cross-version mob compatibility
Incorporates part of https://github.com/EssentialsX/Essentials/pull/2523 - thanks @JRoy.
2019-05-08 22:40:51 +01:00
md678685 365efe4f2d Implement missing FakeWorld and OfflinePlayer methods 2019-05-08 13:49:54 +01:00
md678685 78b2dba42a Bump to API 1.14 2019-05-08 13:49:35 +01:00
Julian van Doorn f793b7607f OS X compatible buildtools.sh (#2513) @Argetan
* OS X compatible buildtools.sh

* Update buildtools.sh
2019-04-30 07:55:54 +01:00
md678685 c567bc22e9 Compile against 1.14-pre5 2019-04-24 14:30:53 +01:00
md678685 d282462547 Use MaterialUtil to check signs 2019-04-24 14:28:15 +01:00
md678685 af4cfd3fe9 Update bStats Metrics to use Gson 2019-04-24 13:54:33 +01:00
md678685 cfba203981 Add prerelease support to VersionUtil 2019-04-24 13:37:43 +01:00
Glare Masters d680ed7363 Check /tpacancel permissions before sending message (#2498)
Fixes #1354.
2019-04-23 09:22:50 +01:00
md678685 69232c0717 Fix missing formatting code in geoipCantFind 2019-04-22 15:24:31 +01:00
latiku b4baa28f01 fix geoip country returning "." if the user is joining from localhost (#2494) @latiku
Implements a check to see if the user's address is `localhost` or `127.0.0.1`, and if so return that the country is unknown.

**Edit by @md678685: fixes #2471.**
2019-04-22 09:38:06 +01:00
md678685 0aa11b58b9 Update items.json
Updated to md678685/essx-scripts@e6394a2884

* Fix overlapping armor/wooden pressure plate aliases
2019-04-19 15:10:10 +01:00
md678685 7b60b562b9 Update items.json
Update items.json to md678685/essx-scripts@581db130ef

Changes:
* Add pressure plate aliases
* Add "mushroomcow" aliases for mooshroom spawners
* Add zombie pigman spawner aliases
2019-04-19 14:49:36 +01:00
montlikadani 6377cbfb2b Remove stale messages and add/change formatting in others (#2486) 2019-04-18 13:25:25 -04:00
montlikadani 3f5f9cc717 Fixed when the mail has already cleared (#2063) 2019-04-18 13:18:42 -04:00
Johnny Cao eac1e9b574 Fixes #1928 - Auto-AFK issue: AFK timer not reset on disconnect (#2458)
Update activity regardless of cancel-afk-on-interact setting
2019-04-17 20:45:07 -04:00
Glare Masters 26d63da7aa [Feature] Implemented a message to say teleporting to home. (#2489)
[Feature] Implemented a message to say teleporting to home.
2019-04-17 19:14:44 -04:00
Joseph Hirschfeld 722181439e Merge pull request #1953 from Xeyame/#1899
Expand /exp command
2019-04-17 12:18:58 -04:00
Joseph Hirschfeld ddcb7041f1 Merge pull request #2455 from AgentTroll/patch-94
Fixes #94 - Player with same first letters conflict
2019-04-17 02:46:20 -04:00
Joseph Hirschfeld 8af33e0ae2 Merge pull request #2166 from mathiascode/commandevents
Use chat instead of dispatchCommand
2019-04-17 02:33:29 -04:00
Joseph Hirschfeld d01e12ac14 Merge pull request #2158 from pop4959/near-fix
Sort /near by nearest player.
2019-04-17 02:31:38 -04:00
Joseph Hirschfeld 8c0aa840ab Merge pull request #1949 from Ichbinjoe/2.x_feature_jail_no_teleport
[Feature] Add config optn. to disable jail free tp
2019-04-17 02:04:16 -04:00
md678685 05118e9498 Merge pull request #2484 from Xeyame/2.x
Allow using environment variable to set xmx flag in buildtools.sh
2019-04-16 15:47:23 +01:00
Xeyame 7838adf833 Allow using environment variable to set xmx flag 2019-04-16 16:34:57 +02:00
md678685 e230cee91e Add new item database API (#2472)
* Allow resolver functions to be added to item databases

* Allow resolvers to add item names to list

* Make getResolverNames package-private
2019-04-15 10:09:16 +01:00
md678685 8e4fc77244 Merge pull request #2469 from N3FS/feature/command-send
Add PlayerCommandSendEvent listener to hide commands in autocomplete
2019-04-15 10:07:49 +01:00
md678685 0d572036f8 New Crowdin translations (#2476)
* New translations messages.properties (English, United States)

* New translations messages.properties (Russian)

* New translations messages.properties (Korean)

* New translations messages.properties (Lithuanian)

* New translations messages.properties (Polish)

* New translations messages.properties (Portuguese)

* New translations messages.properties (Portuguese, Brazilian)

* New translations messages.properties (Romanian)

* New translations messages.properties (Serbian (Cyrillic))

* New translations messages.properties (Italian)

* New translations messages.properties (Serbian (Latin))

* New translations messages.properties (Slovak)

* New translations messages.properties (Spanish)

* New translations messages.properties (Swedish)

* New translations messages.properties (Thai)

* New translations messages.properties (Turkish)

* New translations messages.properties (Ukrainian)

* New translations messages.properties (Japanese)

* New translations messages.properties (Hungarian)

* New translations messages.properties (English, United Kingdom)

* New translations messages.properties (Chinese Traditional, Hong Kong)

* New translations messages.properties (German)

* New translations messages.properties (Norwegian)

* New translations messages.properties (Bulgarian)

* New translations messages.properties (Basque)

* New translations messages.properties (Bosnian)

* New translations messages.properties (Chinese Simplified)

* New translations messages.properties (Chinese Traditional)

* New translations messages.properties (Croatian)

* New translations messages.properties (Hebrew)

* New translations messages.properties (Czech)

* New translations messages.properties (Danish)

* New translations messages.properties (Dutch)

* New translations messages.properties (Estonian)

* New translations messages.properties (Finnish)

* New translations messages.properties (French)

* New translations messages.properties (Greek)

* New translations messages.properties (Vietnamese)
2019-04-07 21:21:29 +01:00
md678685 26fdd0ff6b Fix playerMutedFor[Reason] formatting codes 2019-04-07 21:19:45 +01:00
Trent Hensler 70a4aee930 New translations messages.properties (Vietnamese) 2019-04-07 13:11:55 -07:00
Trent Hensler 3631323aa7 New translations messages.properties (Greek) 2019-04-07 13:11:53 -07:00
Trent Hensler 1fd7d18056 New translations messages.properties (French) 2019-04-07 13:11:51 -07:00
Trent Hensler a60f67cd0a New translations messages.properties (Finnish) 2019-04-07 13:11:49 -07:00
Trent Hensler 5ba781d00e New translations messages.properties (Estonian) 2019-04-07 13:11:46 -07:00
Trent Hensler 17c5d25996 New translations messages.properties (Dutch) 2019-04-07 13:11:44 -07:00
Trent Hensler bd9f271eff New translations messages.properties (Danish) 2019-04-07 13:11:42 -07:00
Trent Hensler 89b4bd2405 New translations messages.properties (Czech) 2019-04-07 13:11:40 -07:00
Trent Hensler 4da9095c59 New translations messages.properties (Hebrew) 2019-04-07 13:11:37 -07:00
Trent Hensler 75e84a5797 New translations messages.properties (Croatian) 2019-04-07 13:11:35 -07:00
Trent Hensler 54d64dbb5f New translations messages.properties (Chinese Traditional) 2019-04-07 13:11:32 -07:00
Trent Hensler 03e746953c New translations messages.properties (Chinese Simplified) 2019-04-07 13:11:30 -07:00
Trent Hensler ec8a51b06c New translations messages.properties (Bosnian) 2019-04-07 13:11:28 -07:00
Trent Hensler 369c08a624 New translations messages.properties (Basque) 2019-04-07 13:11:26 -07:00
Trent Hensler 7a8e5e92d9 New translations messages.properties (Bulgarian) 2019-04-07 13:11:23 -07:00
Trent Hensler 185ec7ff2b New translations messages.properties (Norwegian) 2019-04-07 13:11:21 -07:00
Trent Hensler af986cc7b2 New translations messages.properties (German) 2019-04-07 13:11:18 -07:00
Trent Hensler 25d96ccfa7 New translations messages.properties (Chinese Traditional, Hong Kong) 2019-04-07 13:11:16 -07:00
Trent Hensler b45c42ef22 New translations messages.properties (English, United Kingdom) 2019-04-07 13:11:14 -07:00
Trent Hensler ea2ac3d483 New translations messages.properties (Hungarian) 2019-04-07 13:11:12 -07:00
Trent Hensler 873df96d0d New translations messages.properties (Japanese) 2019-04-07 13:11:10 -07:00
Trent Hensler d69495baa7 New translations messages.properties (Ukrainian) 2019-04-07 13:11:08 -07:00
Trent Hensler 06ff8f24fe New translations messages.properties (Turkish) 2019-04-07 13:11:06 -07:00
Trent Hensler b996608455 New translations messages.properties (Thai) 2019-04-07 13:11:04 -07:00
Trent Hensler 6c1c22132e New translations messages.properties (Swedish) 2019-04-07 13:11:02 -07:00
Trent Hensler 8b326d5852 New translations messages.properties (Spanish) 2019-04-07 13:11:00 -07:00
Trent Hensler dd34f65c98 New translations messages.properties (Slovak) 2019-04-07 13:10:58 -07:00
Trent Hensler 0bd0f853f3 New translations messages.properties (Serbian (Latin)) 2019-04-07 13:10:55 -07:00
Trent Hensler e7a75efaff New translations messages.properties (Italian) 2019-04-07 13:10:53 -07:00
Trent Hensler 2904b50061 New translations messages.properties (Serbian (Cyrillic)) 2019-04-07 13:10:51 -07:00
Trent Hensler 3b6ac632d9 New translations messages.properties (Romanian) 2019-04-07 13:10:48 -07:00
Trent Hensler 9ad3f0e0d7 New translations messages.properties (Portuguese, Brazilian) 2019-04-07 13:10:45 -07:00
Trent Hensler 9529a4ba02 New translations messages.properties (Portuguese) 2019-04-07 13:10:42 -07:00
Trent Hensler 69b9ab097b New translations messages.properties (Polish) 2019-04-07 13:10:40 -07:00
Trent Hensler 4b14c4bcc6 New translations messages.properties (Lithuanian) 2019-04-07 13:10:38 -07:00
Trent Hensler 5154c670c0 New translations messages.properties (Korean) 2019-04-07 13:10:36 -07:00
Trent Hensler 09b699cc9c New translations messages.properties (Russian) 2019-04-07 13:10:34 -07:00
Trent Hensler f2a212e3a4 New translations messages.properties (English, United States) 2019-04-07 13:10:31 -07:00
md678685 19ca946e3b Add Estonian alias to Crowdin config 2019-04-07 21:08:30 +01:00
md678685 e21be39c13 Add Basque alias to Crowdin config 2019-04-07 21:02:42 +01:00
md678685 8fcfff7abd Update Crowdin config 2019-04-07 21:01:22 +01:00
md678685 bcc150a014 Update l10n configs 2019-04-07 20:22:48 +01:00
md678685 3d97e93831 Implement missing OfflinePlayer location methods 2019-04-07 17:06:17 +01:00
md678685 9d93d4db54 Only log removed commands is debug enabled 2019-04-07 17:03:56 +01:00
md678685 0d8aec7eea Add PlayerCommandSendEvent listener to hide commands in autocomplete 2019-03-31 20:35:47 +01:00
md678685 7b165c6c2c Merge pull request #2450 from AgentTroll/patch-2414
Fixes #2414 - Warp signs no permission message
2019-03-15 12:11:17 +00:00
md678685 d3cee314c6 Merge pull request #2451 from AgentTroll/patch-2403
Fixes #2403 - Ability to execute /back for another player
2019-03-15 12:10:33 +00:00
md678685 4395245aab Merge pull request #2454 from AgentTroll/patch-2415
Fixes #2415 - Command for last reply message option
2019-03-15 12:10:10 +00:00
md678685 9d4b0a13c5 Merge remote-tracking branch 'origin/pr/1557' into 2.x 2019-03-15 11:59:35 +00:00
md678685 c908290c27 Simplify willMute condition 2019-03-15 11:58:30 +00:00
md678685 f5c21d1089 Merge branch '2.x' into final_mute_reason_issue#385 2019-03-15 11:52:50 +00:00
Johnny Cao 883fc75f47 Clarifies the last recipient config key 2019-03-10 01:42:10 -08:00
AgentTroll eaac3049af Fix getPlayer(...) for offline players having similar names 2019-03-09 18:50:55 -08:00
AgentTroll f68fb52af1 Add command to toggle reply player functionality 2019-03-09 15:39:45 -08:00
AgentTroll 863bd5a89e Add /back target capability 2019-03-08 22:41:59 -08:00
AgentTroll 50225624a5 Add message for failing sign warp permission check 2019-03-08 15:53:04 -08:00
md678685 25ddaef423 Merge pull request #2329 from triagonal/issue-2311
Implement config option for sleep ignoring AFK players
2019-03-08 22:15:53 +00:00
md678685 585f2bef07 Merge pull request #2310 from pop4959/command-tpauto
Implement tpauto command
2019-03-08 17:19:31 +00:00
md678685 017ea1a4fe Remove unnecessary types 2019-03-08 11:24:42 +00:00
md678685 3b4b5bcd8e Remove Lombok
Remove the (already minimal) usage of Lombok. This will ease development for people who don't already have their IDE set up for Lombok support.

It's also totally unnecessary - it took less than 60 seconds to generate the code needed to replace Lombok annotations in Jails and Spawns.
2019-03-08 11:24:42 +00:00
md678685 f57557b43a Bump version to 2.16.1 2019-03-01 22:45:25 +00:00
md678685 0711fd6f9e Add #version line to allow automatic items.json updates 2019-03-01 12:04:08 +00:00
md678685 b5ecbd1739 Remove Vault repo
Fixes Travis builds and slow builds - Maven pauses while trying to reach the repo and so Travis assumes that the build has failed.
2019-03-01 11:41:29 +00:00
md678685 dda5e4e333 Merge pull request #2402 from Techno3600/patch-1
Pull Request for #2282
2019-03-01 11:32:46 +00:00
pop4959 74b0e71015 More efficient distance calculation 2019-02-26 19:54:19 -08:00
md678685 dde4a36df0 Economy API: Attempt to find users by UUID if username not present (#2432)
Attempt to find user by UUID if username not present. Fixes (maybe) #2400.

https://github.com/EssentialsX/Essentials/issues/2400#issuecomment-466043896
2019-02-22 18:10:36 +00:00
triagonal 31b98fb9f3 allow console to use color codes when sending mail (#2435) @triagonal 2019-02-22 14:34:56 +00:00
kashike 289d34d96c Relocate PaperLib in EssentialsXSpawn too
fixes #2433
2019-02-22 09:58:02 +00:00
md678685 eafd110ed0 Update items.json
Add spawner aliases that end in "spawner".
2019-02-20 14:50:43 +00:00
md678685 e72644abf4 Update items.json
* Add mooshroom spawners
* Add new aliases for red sandstone, sandstone, stone and prismarine variants
2019-02-20 14:42:22 +00:00
md678685 b267103274 Remove getMap(short) method from FakeServer 2019-02-20 12:45:37 +00:00
DoNotSpamPls 3856a690eb Use PaperLib to load chunks and teleport players async (#2409)
* Remove outdated permission plugin handlers, minor test fixes

* Re-add PermissionEX handler

* Use PaperLib to load chunks async whenever possible

* Revert "Use PaperLib to load chunks async whenever possible"

This reverts commit db4df6f3cf.

* Use PaperLib to load chunks and teleport players async

* Resolve some PR issues

* Update PaperLib, return teleport causes

* Remove useless PaperLib usage in LocationUtil

* Fix FakeServer spacing
2019-02-20 12:25:05 +00:00
md678685 f214696664 Check Protect/AntiBuild config materials against Material enum (#2431) 2019-02-20 12:24:30 +00:00
md678685 9e73c29b40 Fix creating and using kits on legacy versions (#2428)
* Attempt to look up legacy items in Material enum
* Use name method when serializing ItemStacks
* Make name uppercase before looking up in Material enum
2019-02-20 12:24:07 +00:00
md678685 aca83bd462 Switch Vault dependency to VaultAPI (#2430)
* Switch Vault dependency to VaultAPI
* Remove direct Vault class usage from VaultEco
2019-02-20 11:28:20 +00:00
md678685 189d6a23c6 Add README section about depending on EssX 2019-02-19 21:58:43 +00:00
md678685 441f88deea Implement missing FakeServer methods 2019-02-17 19:01:47 +00:00
Wiz_Techno 6d6666dace Pull Request for #2282
"Obsolete entries in items.csv should be removed"
2019-01-31 23:14:21 -05:00
Rafał Pokrywka fb779533e6 Replace nbsp with a space when formatting messages (#2394) @ravkr 2019-01-27 12:15:03 +00:00
DoNotSpamPls 7325113a8c Remove outdated permission plugin handlers, minor test fixes (#2367) @DoNotSpamPls
* Remove outdated permission plugin handlers, minor test fixes

* Re-add PermissionEX handler

* Use PaperLib to load chunks async whenever possible

* Revert "Use PaperLib to load chunks async whenever possible"

This reverts commit db4df6f3cf.
2019-01-27 12:14:16 +00:00
Glare Masters 827217823e Add the ability to make spectator gamemode signs (#2386) @darbyjack
Fixes #2383.
2019-01-20 10:14:20 +00:00
md678685 060dfc69f4 Update items.json
Fixed regression of unspawnable items not being marked as such, impacting the alias generation process. This fix also retains the ability to specify non-item blocks in the EssentialsX Protect material lists.
2019-01-12 22:07:03 +00:00
md678685 b831713737 Check whether item is spawnable in FlatItemDb 2019-01-12 21:43:36 +00:00
md678685 7da90b3a6b Load item spawn blacklist after item DB
Partially resolves #2360.
2019-01-12 21:43:36 +00:00
md678685 32540c23ab Add IItemDb#isReady to check if item database is available 2019-01-12 21:43:36 +00:00
md678685 d24b0616f8 Hide ServerListPingEvent exceptions thrown by CB's LegacyPingHandler (#2378)
Fixes #2327.
2019-01-12 17:19:11 +00:00
md678685 9aef2ef883 Update items.json
Add several new aliases. Closes #2348.
2019-01-09 15:10:38 +00:00
md678685 727d473319 Fix Enchantments on 1.12.2 and lower 2019-01-09 14:23:55 +00:00
md678685 8225e51867 Fix XMPP metrics reporting
The XMPP config was being reported as valid when it wasn't valid.
2019-01-09 13:57:18 +00:00
md678685 1ba6c2a596 Properly fix language mappings 2019-01-08 22:19:16 +00:00
md678685 60a166aeb0 Fix language mapping in Crowdin config 2019-01-08 21:45:46 +00:00
md678685 65c2155bca Update Crowdin config
Map most locales to the existing locale files.
2019-01-08 21:36:16 +00:00
md678685 6031c01584 Update Crowdin config
Fix file placement and map locale codes to existing translations
2019-01-08 21:21:35 +00:00
md678685 da8e8c8a25 Update Crowdin config
Crowdin should only use `messages.properties` as the "source" and this file will get copied to all the other language files like `messages_de.properties` for the German translation, `messages_ro.properties` for the Romanian translation etc.
2019-01-08 21:14:56 +00:00
Trent Hensler 70a750a32d Update Crowdin configuration file 2019-01-08 12:48:25 -08:00
md678685 7c63324504 Fix allow-old-id-signs allowing creation of signs with IDs 2019-01-07 22:38:13 +00:00
md678685 dd41b10522 attempt to fix Essentials overriding Skulls (#2356) @kennyrkun 2019-01-05 18:48:33 +00:00
triagonal 7948e764d4 disallow setting bed homes in non-overworld dimensions (#2335) @triagonal 2019-01-05 18:43:27 +00:00
DoNotSpamPls 82ede4530a Lots of little fixes in the Essentials modules (#2337) @DoNotSpamPls
Look at changed files for the changes
2019-01-05 18:42:09 +00:00
md678685 e8ab2db8e8 Improve ServerListPingEvent warning handling 2019-01-05 18:12:04 +00:00
md678685 8882e0214c Add bStats metrics for each EssentialsX module (#2333)
Does what it says on the tin.
2019-01-05 17:48:44 +00:00
md678685 4adb669cdd Add support for spawners with entities on 1.13+ 2019-01-05 17:35:29 +00:00
md678685 7e1d258dd3 Cache BukkitVersion in getServerBukkitVersion 2019-01-05 16:29:11 +00:00
md678685 417fe29e21 Remove duplicated item IDs in messages 2019-01-05 16:28:53 +00:00
md678685 bd8ef2a25d Only show available warps in tab complete
Fixes #2353 by only displaying warps where the player has the permission `essentials.warps.<warp>`.
2019-01-05 15:45:34 +00:00
md678685 fd01b75c33 Wrap UnsafeValues.fromLegacy() in try/catch for older versions
Should address #2352.
2019-01-05 15:27:07 +00:00
md678685 1388755d2a Wrap Enchantment.getByKey in try/catch for older versions
Should address #2351.
2019-01-05 15:17:58 +00:00
md678685 97cc3d0066 Update items.json
* Fix wrong harming potion mapping (fixes #2349)
* Add mob spawner aliases (not complete, related to #2347)
* Closes #2348:
  - Fix log aliases mistakenly pointing to stripped logs
  - Fix sandstone alias
  - Add shorter concrete powder aliases
2019-01-05 15:04:59 +00:00
md678685 694cf7a79e Revert 1.13 API hacks in LegacyItemDb
Earlier changes broke the items.csv database on older versions - this should now be fixed.
2019-01-04 15:01:18 +00:00
md678685 da89efb79f Make VersionUtil not explode when patch is not present 2019-01-03 22:16:14 +00:00
md678685 04ec013407 Update README to reflect 1.13 support 2019-01-03 21:25:48 +00:00
md678685 023cf6a1aa Merge pull request #2278 from EssentialsX/1.13
Full 1.13 support + 2.16.0 release
2019-01-03 20:56:14 +00:00
triagonal 3d004d2a81 change config setting name 2018-12-31 16:42:42 +11:00
triagonal d1bbebad3a updated config comments 2018-12-30 20:49:58 +11:00
triagonal 42714ff8af implement config toggle for afk users bypassing sleep 2018-12-30 20:38:34 +11:00
pop4959 64930e3771 Fix messages & add warning 2018-12-21 01:58:44 -08:00
pop4959 16381234e0 Implement tpauto command 2018-12-19 02:50:30 -08:00
md678685 22538ba7c9 Merge branch '1.13' into 2.x_feature_jail_no_teleport 2018-10-28 18:46:53 +00:00
mathias a9fe842242 Use chat instead of dispatchCommand 2018-09-18 16:39:58 +03:00
pop4959 0432546746 use less dependencies 2018-09-04 16:53:01 -07:00
pop4959 3395bab928 Sort /near by nearest player. 2018-09-02 23:09:22 -07:00
Joseph Hirschfeld 70387f73f6 [Feature] Add config optn. to disable jail free tp
Adds the teleport-back-when-freed-from-jail configuration option. When
set to true (default), as with previous versions will teleport the
player which was jailed back to their previous position when freed. When
false, Essentials will not teleport the player anywhere, leaving them
where they are.

Closes #1947
2018-04-03 01:27:09 -04:00
Xeyame 7adb931ea8 Expand /exp command 2018-04-02 14:29:43 +02:00
Taylor 5f7d226158 Merge pull request #17 from delbertina/mutes385test
Sorted messages files with the -f option and other tweaks ...
2018-01-21 17:02:26 -06:00
delbertina 0897ca57ff Removed redundant line in mute time try-catch. 2018-01-20 22:46:55 -06:00
delbertina cfcdb47529 One last tweak. New line at the end of the fr file. 2018-01-18 22:04:35 -06:00
delbertina 76f845f5f4 More tweaks. Newlines and ordering switches. 2018-01-18 22:02:39 -06:00
delbertina c65b7b6462 Fixed error in sorting with number in message name and newlines at end of files. 2018-01-18 21:52:30 -06:00
delbertina 67528b25a8 Sorted messages files with the -f option 2018-01-18 15:18:22 -06:00
CreedTheFreak b096ee9703 Merge remote-tracking branch 'delbertina/mutes385test' into final_mute_reason_issue#385
Merged changes into local branch for pushing up to the pull request of
mute reason.
2018-01-16 17:49:49 -08:00
delbertina 9e2bb0b277 Rebase with sorted messages 2018-01-16 19:27:45 -06:00
CreedTheFreak b8df59ae46 Updated the former pull request to include the specified formatting changes, and small edits to the hasMuteReason and Commandmute dealing with the muteReason. I also included the ability to see the mute reason from the seenOffline method which is identical to the seenOnline code. 2018-01-16 18:21:31 -06:00
delbertina 98f42c6974 Added reason stuff to msg command and deleted reference line in seen command. Oops! 2018-01-16 18:16:34 -06:00
delbertina db19788e21 Added 8 new messages for "...Reason" versions of mute messages and implemented em. 2018-01-16 18:16:33 -06:00
delbertina 67d17472e0 Fixed logic error in hasMuteReason and errors being thrown from seen and whois. 2018-01-16 18:04:22 -06:00
delbertina f68a6eb00d Added space before reason when a muted player tries to talk. 2018-01-16 18:04:22 -06:00
delbertina b5a6df4fe2 Added space when adding reason to string. 2018-01-16 18:04:21 -06:00
delbertina 290379651d Added space when adding reason to string. Dirty :/ 2018-01-16 17:59:14 -06:00
delbertina 6ffbb86169 Changed if else blocks to ternary operators. Not sure if way to avoid weird empty string usage. 2018-01-16 17:54:50 -06:00
delbertina d8b6f87087 Added method hasMuteReason in UserData. 2018-01-16 17:54:50 -06:00
delbertina 7aad95ec08 Changed muteFormat to muteReason.
Removed space at beginning of muteReason.
2018-01-16 17:54:49 -06:00
delbertina 574e1bc1e7 Fixed easy style issues. 2018-01-16 17:48:12 -06:00
CreedTheFreak 081c6f0263 Update plugin.yml mute command usage 2018-01-16 17:48:11 -06:00
delbertina fc590f82a2 Added check to display mute reason when notifying 2018-01-16 17:48:10 -06:00
delbertina 729af4bb4d Added mute format to all msg files 2018-01-16 17:48:09 -06:00
CreedTheFreak c8cb9b3735 fixed some wonky commit thing that happened, thus the following modifications are brought to you by Delbertina. 2018-01-16 17:21:54 -06:00
CreedTheFreak 4f8ea06db1 We have added the ability for the Mute to contain a reason, which is stored for the duration of the mute in the user's data file. Currently we need to add in the mute reason code into some other commands such as /afk and /me and /seen ect. We will also need to fix a problem with the reason when we dont add in a time frame for the mute, which should mute the player indefinatly rather then cancelling the mute and throwing a DataFormat exception. 2018-01-16 17:21:53 -06:00
CreedTheFreak 9378df0ff2 Started work on implementing the mute reason, and decided to write it to the UserData just like the Ban and TempBan reasons 2018-01-16 17:21:52 -06:00
CreedTheFreak 3444c8b0d6 Merge branch 'mute_reason_changes' into final_mute_reason_issue#385
Updating local changes made on mute_reason_changes into the final branch
2017-12-26 17:20:40 -08:00
CreedTheFreak 822315a279 Updated the former pull request to include the specified formatting changes, and small edits to the hasMuteReason and Commandmute dealing with the muteReason. I also included the ability to see the mute reason from the seenOffline method which is identical to the seenOnline code. 2017-12-26 16:09:46 -08:00
CreedTheFreak 732da86710 Merge remote-tracking branch 'magnarisa/final_mute_reason_issue#385' into mute_reason_changes
Updated a clean branch with the changes we have made so far.
2017-12-26 08:23:53 -08:00
CreedTheFreak 5fbc412542 Merge remote-tracking branch 'upstream/2.x' into final_mute_reason_issue#385 2017-12-26 08:16:46 -08:00
CreedTheFreak f0b262cbd5 Merge pull request #15 from delbertina/mutes385
Added 8 new messages for "...Reason" versions of mute messages
2017-12-23 22:13:57 -08:00
delbertina ff37ef3bc5 Added reason stuff to msg command and deleted reference line in seen command. Oops! 2017-12-24 00:03:36 -06:00
CreedTheFreak 68fab2c328 Merge branch 'mutes385' of https://github.com/delbertina/Essentials into final_mute_reason_issue#385
Testing PR Changes
2017-12-23 22:03:01 -08:00
CreedTheFreak f9d81c4302 Merge branch 'mutes385' of https://github.com/delbertina/Essentials into final_mute_reason_issue#385
Testing PR
2017-12-23 21:51:21 -08:00
delbertina 3d33bbc33d Added 8 new messages for "...Reason" versions of mute messages and implemented em. 2017-12-20 00:35:51 -06:00
CreedTheFreak 53c604c1b5 Merge pull request #14 from delbertina/mutes385
Fixed spacing
2017-12-18 18:53:57 -08:00
CreedTheFreak 2975118e5b Merge branch 'mutes385' of https://github.com/delbertina/Essentials into final_mute_reason_issue#385 2017-12-18 18:40:27 -08:00
delbertina e3ee9cb4c7 Fixed logic error in hasMuteReason and errors being thrown from seen and whois. 2017-12-18 20:37:34 -06:00
CreedTheFreak 297a616460 Merge branch 'mutes385' of https://github.com/delbertina/Essentials into final_mute_reason_issue#385 2017-12-16 23:48:27 -08:00
delbertina afe0ff0ca7 Added space before reason when a muted player tries to talk. 2017-12-17 01:46:43 -06:00
CreedTheFreak adf1bc291c Merge branch 'mutes385' of https://github.com/delbertina/Essentials into final_mute_reason_issue#385 2017-12-16 22:27:52 -08:00
delbertina 034ffbd0bc Added space when adding reason to string. 2017-12-17 00:16:06 -06:00
delbertina 127a7bb2ce Merge branch 'mutes385' of https://github.com/delbertina/Essentials into mutes385
Updated local copy
Conflicts:
	Essentials/src/com/earth2me/essentials/commands/Commandafk.java
	Essentials/src/com/earth2me/essentials/commands/Commandmail.java
	Essentials/src/com/earth2me/essentials/commands/Commandme.java
	Essentials/src/com/earth2me/essentials/commands/Commandr.java
	Essentials/src/com/earth2me/essentials/commands/Commandseen.java
	Essentials/src/com/earth2me/essentials/commands/Commandwhois.java
2017-12-17 00:02:52 -06:00
delbertina e8bfac0790 Added space when adding reason to string. Dirty :/ 2017-12-16 23:26:09 -06:00
CreedTheFreak 62d5dd3516 Merge remote-tracking branch 'magnarisa/final_mute_reason_issue#385' into final_mute_reason_issue#385
Updated my local repos for testing purposes
2017-12-16 19:43:56 -08:00
CreedTheFreak bcd66fec39 Merge pull request #12 from delbertina/mutes385
Address requested changes to formatting and logic
2017-12-16 19:40:27 -08:00
delbertina 849b329213 Changed if else blocks to ternary operators. Not sure if way to avoid weird empty string usage. 2017-12-02 20:35:44 -06:00
delbertina d555c1b081 Added method hasMuteReason in UserData. 2017-12-02 19:46:46 -06:00
delbertina 43cbab37f0 Changed muteFormat to muteReason.
Removed space at beginning of muteReason.
2017-11-26 01:32:22 -06:00
delbertina 6f7af90488 Fixed easy style issues. 2017-11-26 00:55:05 -06:00
CreedTheFreak fcda6c3b3b Merge pull request #11 from CreedTheFreak/final_mute_reason_issue#385
Update plugin.yml mute command usage
2017-09-17 15:39:01 -07:00
CreedTheFreak 910ef26c79 Update plugin.yml mute command usage 2017-09-17 15:36:06 -07:00
Taylor 1664da55a4 Merge pull request #10 from CreedTheFreak/commit_squashing
Final Implementation and the squasing of many commits
2017-09-17 16:55:14 -05:00
CreedTheFreak f8ea7f5e1f Implemented the ability to add a reason while muting a
player. The form of the mute is /mute [Player] [Time] [Reason] or /mute
[Player] [Reason] or /mute [Player] [Time] or /mute [Player]. These are
the various forms of the mute command and acts exactly like the old
command just with a reason.

The final adjustments to the MuteReason
2017-09-16 22:27:34 -07:00
delbertina b0205b9499 Added check to display mute reason when notifying 2017-09-03 23:02:56 -05:00
Taylor e05796f80e Merge pull request #4 from delbertina/msgs385
Added mute format to all msg files
2017-09-03 22:10:19 -05:00
delbertina a70fa78267 Added mute format to all msg files 2017-09-03 22:03:17 -05:00
CreedTheFreak e20693de60 Merge pull request #3 from CreedTheFreak/update_branch
Modifications Brought To you by Delbertina
2017-09-03 19:54:20 -07:00
CreedTheFreak f10a766442 fixed some wonky commit thing that happened, thus the following modifications are brought to you by Delbertina. 2017-09-03 19:49:57 -07:00
CreedTheFreak 86315fed8d Merge pull request #1 from CreedTheFreak/mute/jail_reason_issue#385
Mute reason issue#385
2017-09-03 14:46:40 -07:00
CreedTheFreak 4ff9fe8666 We have added the ability for the Mute to contain a reason, which is stored for the duration of the mute in the user's data file. Currently we need to add in the mute reason code into some other commands such as /afk and /me and /seen ect. We will also need to fix a problem with the reason when we dont add in a time frame for the mute, which should mute the player indefinatly rather then cancelling the mute and throwing a DataFormat exception. 2017-09-03 14:41:32 -07:00
CreedTheFreak 3512c4c8e6 Started work on implementing the mute reason, and decided to write it to the UserData just like the Ban and TempBan reasons 2017-09-02 20:04:25 -07:00
234 changed files with 47294 additions and 36929 deletions

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
# Currently used
patreon: EssentialsX
ko_fi: essentialsx
# Currently not used
#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
#open_collective: # Replace with a single Open Collective username
#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
#liberapay: # Replace with a single Liberapay username
#issuehunt: # Replace with a single IssueHunt username
#otechie: # Replace with a single Otechie username
#custom: # Replace with a single custom sponsorship URL
+41
View File
@@ -0,0 +1,41 @@
name: Build EssentialsX
on:
push:
branches:
- 2.x
- mc/*
pull_request:
branches:
- 2.x
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Git repo
uses: actions/checkout@v1
- name: Restore Maven cache
uses: actions/cache@v1
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Run BuildTools
if: steps.cache.outputs.cache-hit != 'true'
run: chmod +x scripts/buildtools.sh && ./scripts/buildtools.sh
- name: Build with Maven
run: mvn package --file pom.xml
- name: Copy artifacts
run: mkdir -p ./out/ && cp -t ./out/ **/target/Essentials*.jar
- uses: actions/upload-artifact@master
with:
name: Plugin jars
path: out/
+18 -54
View File
@@ -1,54 +1,18 @@
.DS_Store
/BuildAll/nbproject/private/
/EssentialsProtect/nbproject/private/
/EssentialsChat/nbproject/private/
/EssentialsGroupBridge/nbproject/private/
/EssentialsGeoIP/nbproject/private/
/EssentialsSpawn/nbproject/private/
/EssentialsXMPP/nbproject/private/
/BuildAll/build/
/EssentialsGroupBridge/dist/
/EssentialsGroupBridge/build/
/EssentialsGeoIP/dist/
/EssentialsGeoIP/build/
/BuildAll/dist/
/EssentialsChat/build/
/EssentialsChat/dist/
/EssentialsSpawn/build/
/EssentialsSpawn/dist/
/EssentialsXMPP/dist/
/EssentialsXMPP/build/
/EssentialsProtect/dist/
/EssentialsProtect/build/
/EssentialsPermissionsCommands/nbproject/private/
/EssentialsPermissionsCommands/build/
/EssentialsPermissionsCommands/dist/
/Essentials/nbproject/private/
/Essentials/dist/
/Essentials/build/
/YamlAnnotations/
/EssentialsUpdate/nbproject/private/
/EssentialsRelease/
/EssentialsUpdate/dist/
/EssentialsUpdate/build/
/WebPush/apikey.php
/WebPush/nbproject/private
/EssentialsAntiBuild/nbproject/private/
/EssentialsAntiBuild/dist/
/EssentialsAntiBuild/build/
/jars
/out
.idea/
.buildtools/
*.iml
*.classpath
*.project
*.settings/
target/
dependency-reduced-pom.xml
/Essentials/config.yml
/Essentials/kits.yml
/Essentials/userdata/testplayer1.yml
/Essentials/usermap.csv
/Essentials/userdata
/EssentialsGroupManager/target/
# IDE files
*.classpath
*.project
*.settings/
.idea/
*.iml
.DS_Store
# Essentials files
/Essentials/userdata
/Essentials/config.yml
/Essentials/kits.yml
/Essentials/userdata/testplayer1.yml
/Essentials/usermap.csv
# Build files
target/
jars/
-10
View File
@@ -1,10 +0,0 @@
language: java
cache:
directories:
- .buildtools
- $HOME/.m2
before_install:
- chmod +x scripts/buildtools.sh
- scripts/buildtools.sh
+28 -32
View File
@@ -6,25 +6,18 @@
<parent>
<groupId>net.ess3</groupId>
<artifactId>EssentialsXParent</artifactId>
<version>2.16.0</version>
<version>2.17.2</version>
</parent>
<artifactId>EssentialsX</artifactId>
<licenses>
<license>
<name>GPLv3</name>
<url>http://www.gnu.org/copyleft/gpl.html</url>
</license>
</licenses>
<build>
<finalName>EssentialsX-${full.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<version>3.8.0</version>
<configuration>
<showDeprecation>false</showDeprecation>
</configuration>
@@ -32,7 +25,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
@@ -41,33 +34,48 @@
</goals>
</execution>
</executions>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>io.papermc.lib</pattern>
<shadedPattern>com.earth2me.essentials.paperlib</shadedPattern>
</relocation>
</relocations>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>net.milkbowl.vault</groupId>
<artifactId>Vault</artifactId>
<version>1.5.6</version>
<groupId>com.github.milkbowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.papermc</groupId>
<artifactId>paperlib</artifactId>
<version>1.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.ess3</groupId>
<artifactId>NMSProvider</artifactId>
<version>2.16.0</version>
<version>2.17.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.ess3</groupId>
<artifactId>UpdatedMetaProvider</artifactId>
<version>2.16.0</version>
<version>2.17.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.ess3</groupId>
<artifactId>1_8_R1Provider</artifactId>
<version>2.16.0</version>
<version>2.17.2</version>
<scope>compile</scope>
<exclusions>
<exclusion>
@@ -79,7 +87,7 @@
<dependency>
<groupId>net.ess3</groupId>
<artifactId>1_8_R2Provider</artifactId>
<version>2.16.0</version>
<version>2.17.2</version>
<scope>compile</scope>
<exclusions>
<exclusion>
@@ -91,32 +99,20 @@
<dependency>
<groupId>net.ess3</groupId>
<artifactId>LegacyProvider</artifactId>
<version>2.16.0</version>
<version>2.17.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.ess3</groupId>
<artifactId>ReflectionProvider</artifactId>
<version>2.16.0</version>
<version>2.17.2</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.ess3</groupId>
<artifactId>FlattenedProvider</artifactId>
<version>2.16.0</version>
<version>2.17.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>vault-repo</id>
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
</repository>
</repositories>
</project>
@@ -25,12 +25,7 @@ public class Backup implements Runnable {
this.ess = ess;
server = ess.getServer();
if (!ess.getOnlinePlayers().isEmpty()) {
ess.runTaskAsynchronously(new Runnable() {
@Override
public void run() {
startTask();
}
});
ess.runTaskAsynchronously(this::startTask);
}
}
@@ -1,7 +1,5 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.NumberUtil;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
@@ -15,6 +13,7 @@ import java.util.Set;
public class Enchantments {
private static final Map<String, Enchantment> ENCHANTMENTS = new HashMap<String, Enchantment>();
private static final Map<String, Enchantment> ALIASENCHANTMENTS = new HashMap<String, Enchantment>();
private static boolean isFlat;
static {
ENCHANTMENTS.put("alldamage", Enchantment.DAMAGE_ALL);
@@ -231,10 +230,43 @@ public class Enchantments {
ALIASENCHANTMENTS.put("channel", channelling);
}
} catch (IllegalArgumentException ignored) {}
try { // 1.14
Enchantment multishot = Enchantment.getByName("MULTISHOT");
if (multishot != null) {
ENCHANTMENTS.put("multishot", multishot);
ALIASENCHANTMENTS.put("tripleshot", multishot);
}
Enchantment quickCharge = Enchantment.getByName("QUICK_CHARGE");
if (quickCharge != null) {
ENCHANTMENTS.put("quickcharge", quickCharge);
ALIASENCHANTMENTS.put("quickdraw", quickCharge);
ALIASENCHANTMENTS.put("fastcharge", quickCharge);
ALIASENCHANTMENTS.put("fastdraw", quickCharge);
}
Enchantment piercing = Enchantment.getByName("PIERCING");
if (piercing != null) {
ENCHANTMENTS.put("piercing", piercing);
}
} catch (IllegalArgumentException ignored) {}
try {
Class<?> namespacedKeyClass = Class.forName("org.bukkit.NamespacedKey");
Class<?> enchantmentClass = Class.forName("org.bukkit.enchantments.Enchantment");
enchantmentClass.getDeclaredMethod("getByKey", namespacedKeyClass);
isFlat = true;
} catch (ClassNotFoundException | NoSuchMethodException e) {
isFlat = false;
}
}
public static Enchantment getByName(String name) {
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(name.toLowerCase()));
Enchantment enchantment = null;
if (isFlat) { // 1.13+ only
enchantment = Enchantment.getByKey(NamespacedKey.minecraft(name.toLowerCase()));
}
if (enchantment == null) {
enchantment = Enchantment.getByName(name.toUpperCase());
}
@@ -19,6 +19,7 @@ package com.earth2me.essentials;
import com.earth2me.essentials.commands.*;
import com.earth2me.essentials.items.AbstractItemDb;
import com.earth2me.essentials.items.CustomItemResolver;
import com.earth2me.essentials.items.FlatItemDb;
import com.earth2me.essentials.items.LegacyItemDb;
import com.earth2me.essentials.metrics.Metrics;
@@ -32,12 +33,18 @@ import com.earth2me.essentials.textreader.KeywordReplacer;
import com.earth2me.essentials.textreader.SimpleTextInput;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import net.ess3.api.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import net.ess3.api.IEssentials;
import net.ess3.api.ISettings;
import net.ess3.api.*;
import net.ess3.nms.PotionMetaProvider;
import net.ess3.nms.SpawnEggProvider;
import net.ess3.nms.SpawnerProvider;
@@ -76,14 +83,6 @@ import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import org.yaml.snakeyaml.error.YAMLException;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
@@ -97,6 +96,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private transient List<IConf> confList;
private transient Backup backup;
private transient AbstractItemDb itemDb;
private transient CustomItemResolver customItemResolver;
private transient final Methods paymentMethod = new Methods();
private transient PermissionsHandler permissionsHandler;
private transient AlternativeCommandsHandler alternativeCommandsHandler;
@@ -196,27 +196,46 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
final EssentialsUpgrade upgrade = new EssentialsUpgrade(this);
upgrade.beforeSettings();
execTimer.mark("Upgrade");
confList = new ArrayList<>();
settings = new Settings(this);
confList.add(settings);
execTimer.mark("Settings");
userMap = new UserMap(this);
confList.add(userMap);
execTimer.mark("Init(Usermap)");
kits = new Kits(this);
confList.add(kits);
upgrade.convertKits();
execTimer.mark("Kits");
upgrade.afterSettings();
execTimer.mark("Upgrade2");
warps = new Warps(getServer(), this.getDataFolder());
confList.add(warps);
execTimer.mark("Init(Spawn/Warp)");
execTimer.mark("Init(Warp)");
worth = new Worth(this.getDataFolder());
confList.add(worth);
execTimer.mark("Init(Worth)");
itemDb = getItemDbFromConfig();
confList.add(itemDb);
execTimer.mark("Init(Worth/ItemDB)");
execTimer.mark("Init(ItemDB)");
customItemResolver = new CustomItemResolver(this);
try {
itemDb.registerResolver(this, "custom_items", customItemResolver);
confList.add(customItemResolver);
} catch (Exception e) {
e.printStackTrace();
customItemResolver = null;
}
execTimer.mark("Init(CustomItemResolver)");
jails = new Jails(this);
confList.add(jails);
execTimer.mark("Init(Jails)");
@@ -241,6 +260,10 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
), "potion meta").getProvider();
execTimer.mark("Init(Providers)");
reload();
// The item spawn blacklist is loaded with all other settings, before the item
// DB, but it depends on the item DB, so we need to reload it again here:
((Settings) settings)._lateLoadItemSpawnBlacklist();
} catch (YAMLException exception) {
if (pm.getPlugin("EssentialsUpdate") != null) {
LOGGER.log(Level.SEVERE, tl("essentialsHelp2"));
@@ -476,7 +499,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
if (bSenderBlock != null) {
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)});
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)});
}
} else if (user == null) {
Bukkit.getLogger().log(Level.INFO, "{0} issued server command: /{1} {2}", new Object[]{cSender.getName(), commandLabel, EssentialsCommand.getFinalArg(args, 0)});
}
@@ -860,13 +885,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
@Override
public Iterable<User> getOnlineUsers() {
return Iterables.transform(getOnlinePlayers(), new Function<Player, User>() {
@Override
public User apply(Player player) {
return getUser(player);
}
});
return getOnlinePlayers().stream().map(this::getUser).collect(Collectors.toList());
}
@Override
@@ -884,6 +903,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
return potionMetaProvider;
}
@Override
public CustomItemResolver getCustomItemResolver() {
return customItemResolver;
}
private static void addDefaultBackPermissionsToWorld(World w) {
String permName = "essentials.back.into." + w.getName();
@@ -1,25 +1,31 @@
package com.earth2me.essentials;
import com.google.common.io.Files;
import net.ess3.api.InvalidWorldException;
import org.bukkit.*;
import org.bukkit.OfflinePlayer;
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 static com.earth2me.essentials.I18n.tl;
import java.io.*;
import com.google.common.io.Files;
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.util.*;
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;
@@ -28,8 +34,18 @@ 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;
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;
public class EssentialsConf extends YamlConfiguration {
@@ -108,20 +124,21 @@ public class EssentialsConf extends YamlConfiguration {
if (length > buffer.remaining()) {
ByteBuffer resize = ByteBuffer.allocate(buffer.capacity() + length - buffer.remaining());
int resizePosition = buffer.position();
buffer.rewind();
// 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.rewind();
((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.rewind();
data.clear();
((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);
@@ -134,7 +151,7 @@ public class EssentialsConf extends YamlConfiguration {
decoder.flush(data);
}
final int end = data.position();
data.rewind();
((Buffer) data).rewind();
super.loadFromString(data.subSequence(0, end).toString());
}
} catch (IOException ex) {
@@ -92,7 +92,7 @@ public class EssentialsEntityListener implements Listener {
class PowerToolInteractTask implements Runnable {
@Override
public void run() {
attacker.getServer().dispatchCommand(attacker.getBase(), command);
attacker.getBase().chat("/" + command);
LOGGER.log(Level.INFO, String.format("[PT] %s issued server command: /%s", attacker.getName(), command));
}
}
@@ -159,6 +159,15 @@ public class EssentialsEntityListener implements Listener {
}
}
@EventHandler(priority = EventPriority.LOW)
public void onPlayerDeathInvEvent(final PlayerDeathEvent event) {
final User user = ess.getUser(event.getEntity());
if (user.isAuthorized("essentials.keepinv")) {
event.setKeepInventory(true);
event.getDrops().clear();
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onFoodLevelChange(final FoodLevelChangeEvent event) {
if (event.getEntity() instanceof Player) {
@@ -7,13 +7,10 @@ import com.earth2me.essentials.textreader.TextPager;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.LocationUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.VersionUtil;
import io.papermc.lib.PaperLib;
import net.ess3.api.IEssentials;
import org.bukkit.BanEntry;
import org.bukkit.BanList;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.*;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
@@ -34,11 +31,7 @@ import org.bukkit.inventory.PlayerInventory;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.*;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -55,12 +48,35 @@ public class EssentialsPlayerListener implements Listener {
this.ess = parent;
}
private static boolean isEntityPickupEvent() {
try {
Class.forName("org.bukkit.event.entity.EntityPickupItemEvent");
return true;
} catch (ClassNotFoundException ignored) {
return false;
}
}
private static boolean isCommandSendEvent() {
try {
Class.forName("org.bukkit.event.player.PlayerCommandSendEvent");
return true;
} catch (ClassNotFoundException ignored) {
return false;
}
}
public void registerEvents() {
ess.getServer().getPluginManager().registerEvents(this, ess);
if (isEntityPickupEvent()) {
ess.getServer().getPluginManager().registerEvents(new PlayerListener1_12(), ess);
ess.getServer().getPluginManager().registerEvents(new PickupListener1_12(), ess);
} else {
ess.getServer().getPluginManager().registerEvents(new PlayerListenerPre1_12(), ess);
ess.getServer().getPluginManager().registerEvents(new PickupListenerPre1_12(), ess);
}
if (isCommandSendEvent()) {
ess.getServer().getPluginManager().registerEvents(new CommandSendListener(), ess);
}
}
@@ -80,7 +96,9 @@ public class EssentialsPlayerListener implements Listener {
final User user = ess.getUser(event.getPlayer());
if (user.isMuted()) {
event.setCancelled(true);
user.sendMessage(tl("voiceSilenced"));
user.sendMessage(user.hasMuteReason() ? tl("voiceSilencedReason", user.getMuteReason()) : tl("voiceSilenced"));
LOGGER.info(tl("mutedUserSpeaks", user.getName(), event.getMessage()));
}
try {
@@ -156,7 +174,7 @@ public class EssentialsPlayerListener implements Listener {
.replace("{PLAYER}", player.getDisplayName())
.replace("{USERNAME}", player.getName())
.replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size()));
event.setQuitMessage(msg.isEmpty() ? null : msg);
}
@@ -181,7 +199,7 @@ public class EssentialsPlayerListener implements Listener {
}
}
user.updateActivityOnInteract(false);
user.updateActivity(false);
if (!user.isHidden()) {
user.setLastLogout(System.currentTimeMillis());
}
@@ -193,12 +211,8 @@ public class EssentialsPlayerListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerJoin(final PlayerJoinEvent event) {
final String joinMessage = event.getJoinMessage();
ess.runTaskAsynchronously(new Runnable() {
@Override
public void run() {
delayedJoin(event.getPlayer(), joinMessage);
}
});
ess.runTaskAsynchronously(() -> delayedJoin(event.getPlayer(), joinMessage));
if (ess.getSettings().allowSilentJoinQuit() || ess.getSettings().isCustomJoinMessage()) {
event.setJoinMessage(null);
}
@@ -219,7 +233,7 @@ public class EssentialsPlayerListener implements Listener {
final long currentTime = System.currentTimeMillis();
dUser.checkMuteTimeout(currentTime);
dUser.updateActivityOnInteract(false);
dUser.updateActivity(false);
dUser.stopTransaction();
class DelayJoinTask implements Runnable {
@@ -262,9 +276,9 @@ public class EssentialsPlayerListener implements Listener {
//NOOP
} else if (ess.getSettings().isCustomJoinMessage()) {
String msg = ess.getSettings().getCustomJoinMessage()
.replace("{PLAYER}", player.getDisplayName()).replace("{USERNAME}", player.getName())
.replace("{UNIQUE}", NumberFormat.getInstance().format(ess.getUserMap().getUniqueUsers()))
.replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size()));
.replace("{PLAYER}", player.getDisplayName()).replace("{USERNAME}", player.getName())
.replace("{UNIQUE}", NumberFormat.getInstance().format(ess.getUserMap().getUniqueUsers()))
.replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size()));
if (!msg.isEmpty()) {
ess.getServer().broadcastMessage(msg);
}
@@ -316,7 +330,7 @@ public class EssentialsPlayerListener implements Listener {
user.setGodModeEnabled(false);
ess.getLogger().log(Level.INFO, "Set god mode to false for {0} because they had it enabled without permission.", user.getName());
}
user.setConfirmingClearCommand(null);
user.getConfirmingPayments().clear();
@@ -446,12 +460,7 @@ public class EssentialsPlayerListener implements Listener {
final User user = ess.getUser(event.getPlayer());
if (user.hasUnlimited(new ItemStack(event.getBucket()))) {
event.getItemStack().setType(event.getBucket());
ess.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
user.getBase().updateInventory();
}
});
ess.scheduleSyncDelayedTask(user.getBase()::updateInventory);
}
}
@@ -486,7 +495,7 @@ public class EssentialsPlayerListener implements Listener {
LOGGER.info(tl("mutedUserSpeaks", player.getName(), event.getMessage()));
return;
}
boolean broadcast = true; // whether to broadcast the updated activity
boolean update = true; // Only modified when the command is afk
@@ -505,16 +514,16 @@ public class EssentialsPlayerListener implements Listener {
}
if (ess.getSettings().isCommandCooldownsEnabled() && pluginCommand != null
&& !user.isAuthorized("essentials.commandcooldowns.bypass")) {
&& !user.isAuthorized("essentials.commandcooldowns.bypass")) {
int argStartIndex = event.getMessage().indexOf(" ");
String args = argStartIndex == -1 ? "" // No arguments present
: " " + event.getMessage().substring(argStartIndex); // arguments start at argStartIndex; substring from there.
String args = argStartIndex == -1 ? "" // No arguments present
: " " + event.getMessage().substring(argStartIndex); // arguments start at argStartIndex; substring from there.
String fullCommand = pluginCommand.getName() + args;
// Used to determine whether a user already has an existing cooldown
// If so, no need to check for (and write) new ones.
boolean cooldownFound = false;
// Iterate over a copy of getCommandCooldowns in case of concurrent modifications
for (Entry<Pattern, Long> entry : new HashMap<>(user.getCommandCooldowns()).entrySet()) {
// Remove any expired cooldowns
@@ -552,8 +561,8 @@ public class EssentialsPlayerListener implements Listener {
final User user = ess.getUser(event.getPlayer());
if (user.getBase().getGameMode() != GameMode.CREATIVE
// COMPAT: String compare for 1.7.10
&& !user.getBase().getGameMode().name().equals("SPECTATOR")
&& !user.isAuthorized("essentials.fly")) {
&& !user.getBase().getGameMode().name().equals("SPECTATOR")
&& !user.isAuthorized("essentials.fly")) {
user.getBase().setFallDistance(0f);
user.getBase().setAllowFlight(false);
}
@@ -597,13 +606,18 @@ public class EssentialsPlayerListener implements Listener {
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerInteract(final PlayerInteractEvent event) {
boolean updateActivity = true;
switch (event.getAction()) {
case RIGHT_CLICK_BLOCK:
if (!event.isCancelled() && MaterialUtil.isBed(event.getClickedBlock().getType()) && ess.getSettings().getUpdateBedAtDaytime()) {
User player = ess.getUser(event.getPlayer());
if (player.isAuthorized("essentials.sethome.bed")) {
if (player.isAuthorized("essentials.sethome.bed") && player.getWorld().getEnvironment().equals(World.Environment.NORMAL)) {
player.getBase().setBedSpawnLocation(event.getClickedBlock().getLocation());
player.sendMessage(tl("bedSet", player.getLocation().getWorld().getName(), player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()));
// In 1.15 and above, vanilla sends its own bed spawn message.
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_15_R01)) {
player.sendMessage(tl("bedSet", player.getLocation().getWorld().getName(), player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()));
}
}
}
break;
@@ -623,8 +637,16 @@ public class EssentialsPlayerListener implements Listener {
}
}
break;
case PHYSICAL:
updateActivity = false;
break;
default:
break;
}
if (updateActivity) {
ess.getUser(event.getPlayer()).updateActivityOnInteract(true);
}
}
// This method allows the /jump lock feature to work, allows teleporting while flying #EasterEgg
@@ -641,7 +663,7 @@ public class EssentialsPlayerListener implements Listener {
while (LocationUtil.isBlockDamaging(loc.getWorld(), loc.getBlockX(), loc.getBlockY() - 1, loc.getBlockZ())) {
loc.setY(loc.getY() + 1d);
}
user.getBase().teleport(loc, TeleportCause.PLUGIN);
PaperLib.teleportAsync(user.getBase(), loc, TeleportCause.PLUGIN);
}
}
ess.scheduleSyncDelayedTask(new DelayedClickJumpTask());
@@ -671,7 +693,7 @@ public class EssentialsPlayerListener implements Listener {
class PowerToolUseTask implements Runnable {
@Override
public void run() {
user.getServer().dispatchCommand(user.getBase(), command);
user.getBase().chat("/" + command);
LOGGER.log(Level.INFO, String.format("[PT] %s issued server command: /%s", user.getName(), command));
}
}
@@ -726,8 +748,9 @@ public class EssentialsPlayerListener implements Listener {
}
} else if (clickedInventory != null && clickedInventory.getType() == InventoryType.PLAYER) {
if (ess.getSettings().isDirectHatAllowed() && event.getClick() == ClickType.LEFT && event.getSlot() == 39
&& event.getCursor().getType() != Material.AIR && event.getCursor().getType().getMaxDurability() == 0
&& ess.getUser(event.getWhoClicked()).isAuthorized("essentials.hat")) {
&& event.getCursor().getType() != Material.AIR && event.getCursor().getType().getMaxDurability() == 0
&& !MaterialUtil.isSkull(event.getCursor().getType())
&& ess.getUser(event.getWhoClicked()).isAuthorized("essentials.hat") && !ess.getUser(event.getWhoClicked()).isAuthorized("essentials.hat.prevent-type." + event.getCursor().getType().name().toLowerCase())) {
event.setCancelled(true);
final PlayerInventory inv = (PlayerInventory) clickedInventory;
final ItemStack head = inv.getHelmet();
@@ -738,12 +761,7 @@ public class EssentialsPlayerListener implements Listener {
if (refreshPlayer != null) {
final Player player = refreshPlayer;
ess.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
player.updateInventory();
}
}, 1);
ess.scheduleSyncDelayedTask(player::updateInventory, 1);
}
}
@@ -778,32 +796,17 @@ public class EssentialsPlayerListener implements Listener {
if (refreshPlayer != null) {
final Player player = refreshPlayer;
ess.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
player.updateInventory();
}
}, 1);
ess.scheduleSyncDelayedTask(player::updateInventory, 1);
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerFishEvent(final PlayerFishEvent event) {
final User user = ess.getUser(event.getPlayer());
user.updateActivityOnInteract(true);
user.updateActivityOnInteract(true);
}
private static boolean isEntityPickupEvent() {
try {
Class.forName("org.bukkit.event.entity.EntityPickupItemEvent");
return true;
} catch (ClassNotFoundException ignored) {
return false;
}
}
private final class PlayerListenerPre1_12 implements Listener {
private final class PickupListenerPre1_12 implements Listener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerPickupItem(final org.bukkit.event.player.PlayerPickupItemEvent event) {
if (ess.getSettings().getDisableItemPickupWhileAfk()) {
@@ -814,8 +817,7 @@ public class EssentialsPlayerListener implements Listener {
}
}
private final class PlayerListener1_12 implements Listener {
private final class PickupListener1_12 implements Listener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerPickupItem(final org.bukkit.event.entity.EntityPickupItemEvent event) {
if (ess.getSettings().getDisableItemPickupWhileAfk() && event.getEntity() instanceof Player) {
@@ -825,4 +827,46 @@ public class EssentialsPlayerListener implements Listener {
}
}
}
private final class CommandSendListener implements Listener {
@EventHandler(priority = EventPriority.NORMAL)
public void onCommandSend(final PlayerCommandSendEvent event) {
User user = ess.getUser(event.getPlayer());
Set<PluginCommand> checked = new HashSet<>();
Set<PluginCommand> toRemove = new HashSet<>();
event.getCommands().removeIf(label -> {
if (isEssentialsCommand(label)) {
PluginCommand command = ess.getServer().getPluginCommand(label);
if (!checked.contains(command)) {
checked.add(command);
if (!user.isAuthorized(command.getName().equals("r") ? "essentials.msg" : "essentials." + command.getName())) {
toRemove.add(command);
}
}
return toRemove.contains(command);
}
return false;
});
if (ess.getSettings().isDebug()) {
ess.getLogger().info("Removed commands: " + toRemove.toString());
}
}
/**
* Returns true if all of the following are true:
* - The command is a plugin command
* - The plugin command is from Essentials
* - There is no known alternative OR the alternative is overridden by Essentials
*/
private boolean isEssentialsCommand(String label) {
PluginCommand command = ess.getServer().getPluginCommand(label);
return command != null
&& command.getPlugin() == ess
&& (ess.getSettings().isCommandOverridden(label) || (ess.getAlternativeCommandsHandler().getAlternative(label) == null));
}
}
}
@@ -10,12 +10,18 @@ import org.bukkit.event.server.ServerListPingEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
public class EssentialsServerListener implements Listener {
private static List<String> ignoredSLPECallers = Arrays.asList(
".LegacyPingHandler.channelRead(", // CB responding to pings from pre-Netty clients
"de.dytanic.cloudnet.bridge.BukkitBootstrap" // CloudNet v2 doing... something
);
private final transient IEssentials ess;
private boolean unsupportedLogged = false;
private boolean npeWarned = false;
@@ -31,13 +37,13 @@ public class EssentialsServerListener implements Listener {
setSampleText = ReflUtil.getMethodCached(ServerListPingEvent.class, "setSampleText", List.class);
getSampleText = ReflUtil.getMethodCached(ServerListPingEvent.class, "getSampleText");
if (setSampleText != null && getSampleText != null) {
ess.getLogger().info("Using Paper 1.12+ ServerListPingEvent methods");
ess.getLogger().info("ServerListPingEvent: Paper 1.12.2 setSampleText API");
isPaperSample = true;
return;
}
}
ess.getLogger().info("Using Spigot 1.7.10+ ServerListPingEvent iterator");
ess.getLogger().info("ServerListPingEvent: Spigot iterator API");
isPaperSample = false;
}
@@ -46,22 +52,16 @@ public class EssentialsServerListener implements Listener {
if (isPaperSample) {
try {
List<String> playerNames = (List<String>) getSampleText.invoke(event, null);
Iterator<String> iterator = playerNames.iterator();
while (iterator.hasNext()) {
String player = iterator.next();
if (ess.getUser(player).isVanished()) {
iterator.remove();
}
}
playerNames.removeIf(player -> ess.getUser(player).isVanished());
setSampleText.invoke(event, playerNames);
} catch (IllegalAccessException | InvocationTargetException | ClassCastException e) {
if (!unsupportedLogged) {
if (!unsupportedLogged && shouldWarnSLPECaller(e)) {
ess.getLogger().log(Level.WARNING, "Unable to hide players from server list ping "
+ "using Paper 1.12+ method!", e);
+ "using Paper 1.12 method!", e);
unsupportedLogged = true;
}
} catch (NullPointerException e) {
if (!npeWarned) {
if (!npeWarned && shouldWarnSLPECaller(e)) {
npeWarned = true;
Exception ex = new Exception("A plugin has fired a ServerListPingEvent "
+ "without implementing Paper's methods. Point the author to https://git.io/v7Xzl.");
@@ -79,12 +79,38 @@ public class EssentialsServerListener implements Listener {
}
}
} catch (UnsupportedOperationException e) {
if (!unsupportedLogged) {
ess.getLogger().warning("Current server implementation does not support "
+ "hiding players from server list ping. Update or contact the maintainers.");
if (!unsupportedLogged && shouldWarnSLPECaller(e)) {
ess.getLogger().log(Level.WARNING, "Could not hide vanished players while handling " + event.getClass().getName(), e);
unsupportedLogged = true;
}
}
}
}
/**
* Should we warn about this SLPE caller, or should we silently ignore it?
* This checks against the ignoredSLPECallers strings, and if it matches one of those, we
* return false.
*
* @param throwable A throwable caught by a catch block
* @return Whether or not to send a warning about this particular caller
*/
private boolean shouldWarnSLPECaller(Throwable throwable) {
final int maxStackDepth = 20; // Limit the depth when searching through the stack trace
int depth = 0;
for (StackTraceElement element : throwable.getStackTrace()) {
depth++;
if (depth > maxStackDepth) {
break;
}
for (String ignoredString : ignoredSLPECallers) {
if (element.toString().contains(ignoredString)) {
return false; // We know about this error and should ignore it, so don't warn
}
}
}
return true; // We don't know for certain that we can ignore this, so warn just to be safe
}
}
@@ -93,7 +93,7 @@ public class I18n implements net.ess3.api.II18n {
}
messageFormatCache.put(format, messageFormat);
}
return messageFormat.format(objects);
return messageFormat.format(objects).replace(' ', ' '); // replace nbsp with a space
}
public void updateLocale(final String loc) {
@@ -15,6 +15,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Pattern;
@@ -185,6 +186,8 @@ public interface ISettings extends IConf {
boolean cancelAfkOnInteract();
boolean sleepIgnoresAfkPlayers();
boolean isAfkListName();
String getAfkListName();
@@ -313,6 +316,8 @@ public interface ISettings extends IConf {
boolean isConfirmCommandEnabledByDefault(String commandName);
boolean isTeleportBackWhenFreedFromJail();
boolean isCompassTowardsHomePerm();
boolean isAllowWorldInBroadcastworld();
@@ -322,4 +327,16 @@ public interface ISettings extends IConf {
boolean isForceEnableRecipe();
boolean allowOldIdSigns();
boolean isWaterSafe();
boolean isSafeUsermap();
boolean logCommandBlockCommands();
Set<Predicate<String>> getNickBlacklist();
double getMaxProjectileSpeed();
boolean isSpawnIfNoHome();
}
@@ -22,6 +22,8 @@ public interface IUser {
boolean isAuthorized(IEssentialsCommand cmd, String permissionPrefix);
boolean isPermissionSet(String node);
void healCooldown() throws Exception;
void giveMoney(BigDecimal value) throws MaxMoneyException;
@@ -184,5 +186,9 @@ public interface IUser {
void setPromptingClearConfirm(boolean prompt);
boolean isLastMessageReplyRecipient();
void setLastMessageReplyRecipient(boolean enabled);
Map<User, BigDecimal> getConfirmingPayments();
}
@@ -16,10 +16,7 @@ import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.*;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.plugin.PluginManager;
@@ -203,6 +200,14 @@ public class Jails extends AsyncStorageObjectHolder<com.earth2me.essentials.sett
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onJailPlayerGameModeChange(PlayerGameModeChangeEvent event) {
final User user = ess.getUser(event.getPlayer());
if (user.isJailed()) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onJailPlayerRespawn(final PlayerRespawnEvent event) {
final User user = ess.getUser(event.getPlayer());
@@ -79,6 +79,12 @@ public class Kits implements IConf {
config.save();
}
public void removeKit(String name) {
config.set("kits." + name, null);
kits = _getKits();
config.save();
}
public String listKits(final net.ess3.api.IEssentials ess, final User user) throws Exception {
try {
final ConfigurationSection kits = config.getConfigurationSection("kits");
@@ -1,8 +1,5 @@
package com.earth2me.essentials;
import net.ess3.api.IEssentials;
import org.bukkit.Bukkit;
import java.io.*;
import java.math.BigInteger;
import java.security.DigestInputStream;
@@ -13,6 +10,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.stream.Collectors;
import net.ess3.api.IEssentials;
import org.bukkit.Bukkit;
import static com.earth2me.essentials.I18n.tl;
@@ -38,7 +38,7 @@ public class ManagedFile {
try {
copyResourceAscii("/" + filename, file);
} catch (IOException ex) {
Bukkit.getLogger().log(Level.SEVERE, tl("itemsCsvNotLoaded"), ex);
Bukkit.getLogger().log(Level.SEVERE, tl("itemsCsvNotLoaded", filename), ex);
}
}
}
@@ -8,10 +8,12 @@ import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.google.common.base.Joiner;
import java.lang.reflect.Method;
import java.util.*;
import java.util.logging.Level;
import java.util.regex.Pattern;
import net.ess3.api.IEssentials;
import net.ess3.nms.refl.ReflUtil;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.FireworkEffect;
@@ -26,11 +28,6 @@ import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import java.lang.reflect.Method;
import java.util.*;
import java.util.logging.Level;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
@@ -165,8 +162,8 @@ public class MetaItemStack {
stack.setItemMeta(meta);
} else if (split.length > 1 && (split[0].equalsIgnoreCase("lore") || split[0].equalsIgnoreCase("desc")) && hasMetaPermission(sender, "lore", false, true, ess)) {
final List<String> lore = new ArrayList<String>();
for (String line : split[1].split("\\|")) {
lore.add(FormatUtil.replaceFormat(line.replace('_', ' ')));
for (String line : split[1].split("(?<!\\\\)\\|")) {
lore.add(FormatUtil.replaceFormat(line.replace('_', ' ').replace("\\|", "|")));
}
final ItemMeta meta = stack.getItemMeta();
meta.setLore(lore);
@@ -177,9 +174,7 @@ public class MetaItemStack {
} 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())) {
final String owner = split[1];
final SkullMeta meta = (SkullMeta) stack.getItemMeta();
meta.setOwningPlayer(ess.getServer().getOfflinePlayer(owner));
stack.setItemMeta(meta);
setSkullOwner(ess, stack, owner);
} else {
throw new Exception(tl("onlyPlayerSkulls"));
}
@@ -208,13 +203,19 @@ public class MetaItemStack {
stack.setItemMeta(meta);
} else if (split.length > 1 && split[0].equalsIgnoreCase("itemflags") && hasMetaPermission(sender, "itemflags", false, true, ess)) {
addItemFlags(string);
} else if (MaterialUtil.isFirework(stack.getType())) {//WARNING - Meta for fireworks will be ignored after this point.
} else if (MaterialUtil.isFirework(stack.getType())) {
//WARNING - Meta for fireworks will be ignored after this point.
addFireworkMeta(sender, false, string, ess);
} else if (MaterialUtil.isPotion(stack.getType())) { //WARNING - Meta for potions will be ignored after this point.
} else if (MaterialUtil.isPotion(stack.getType())) {
//WARNING - Meta for potions will be ignored after this point.
addPotionMeta(sender, false, string, ess);
} else if (MaterialUtil.isBanner(stack.getType())) {
//WARNING - Meta for banners will be ignored after this point.
addBannerMeta(sender, false, string, ess);
if (stack.getType().toString().equals("SHIELD") && Enchantments.getByName(split[0]) != null) {
parseEnchantmentStrings(sender, allowUnsafe, split, ess);
} else {
//WARNING - Meta for banners will be ignored after this point.
addBannerMeta(sender, false, string, ess);
}
} else if (split.length > 1 && (split[0].equalsIgnoreCase("color") || split[0].equalsIgnoreCase("colour")) && MaterialUtil.isLeatherArmor(stack.getType())) {
final String[] color = split[1].split("(\\||,)");
if (color.length == 1 && (NumberUtil.isInt(color[0]) || color[0].startsWith("#"))) {
@@ -578,4 +579,24 @@ public class MetaItemStack {
t.printStackTrace();
}
}
private static boolean useNewSkullMethod = true;
private static void setSkullOwner(final IEssentials ess, final ItemStack stack, final String owner) {
if (!(stack.getItemMeta() instanceof SkullMeta)) return;
SkullMeta meta = (SkullMeta) stack.getItemMeta();
if (useNewSkullMethod) {
try {
meta.setOwningPlayer(ess.getServer().getOfflinePlayer(owner));
stack.setItemMeta(meta);
return;
} catch (NoSuchMethodError e) {
useNewSkullMethod = false;
}
}
meta.setOwner(owner);
stack.setItemMeta(meta);
}
}
+22 -13
View File
@@ -1,10 +1,10 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.EnumUtil;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.*;
import java.util.*;
import java.util.logging.Level;
@@ -77,12 +77,20 @@ public enum Mob {
PARROT("Parrot", Enemies.NEUTRAL, "PARROT"),
TURTLE("Turtle", Enemies.NEUTRAL, "TURTLE"),
PHANTOM("Phantom", Enemies.ENEMY, "PHANTOM"),
COD("Cod", Enemies.NEUTRAL, "COD"),
SALMON("Salmon", Enemies.NEUTRAL, "SALMON"),
PUFFERFISH("Pufferfish", Enemies.NEUTRAL, "PUFFERFISH"),
TROPICAL_FISH("TropicalFish", Enemies.NEUTRAL, "TROPICAL_FISH"),
COD("Cod", Enemies.NEUTRAL, "", "COD"),
SALMON("Salmon", Enemies.NEUTRAL, "", "SALMON"),
PUFFERFISH("Pufferfish", Enemies.NEUTRAL, "", "PUFFERFISH"),
TROPICAL_FISH("TropicalFish", Enemies.NEUTRAL, "", "TROPICAL_FISH"),
DROWNED("Drowned", Enemies.ENEMY, "DROWNED"),
DOLPHIN("Dolphin", Enemies.NEUTRAL, "DOLPHIN"),
CAT("Cat", Enemies.FRIENDLY, "CAT"),
FOX("Fox", Enemies.FRIENDLY, "es", "FOX"),
PANDA("Panda", Enemies.NEUTRAL, "PANDA"),
PILLAGER("Pillager", Enemies.ENEMY, "PILLAGER"),
RAVAGER("Ravager", Enemies.ENEMY, "RAVAGER"),
TRADER_LLAMA("TraderLlama", Enemies.FRIENDLY, "TRADER_LLAMA"),
WANDERING_TRADER("WanderingTrader", Enemies.FRIENDLY, "WANDERING_TRADER"),
BEE("Bee", Enemies.NEUTRAL, "BEE")
;
public static final Logger logger = Logger.getLogger("Essentials");
@@ -100,16 +108,17 @@ public enum Mob {
this.bukkitType = type;
}
Mob(String n, Enemies en, String s, String typeName) {
this.suffix = s;
this.name = n;
this.type = en;
bukkitType = EnumUtil.getEntityType(typeName);
}
Mob(String n, Enemies en, String typeName) {
this.name = n;
this.type = en;
EntityType entityType;
try {
entityType = EntityType.valueOf(typeName);
} catch (IllegalArgumentException ignored) {
entityType = null;
}
bukkitType = entityType;
bukkitType = EnumUtil.getEntityType(typeName);
}
public String suffix = "s";
@@ -0,0 +1,224 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.EnumUtil;
import net.ess3.nms.refl.ReflUtil;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Ocelot;
import org.bukkit.entity.Villager;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static com.earth2me.essentials.utils.EnumUtil.getEntityType;
public class MobCompat {
// Constants for mobs added in later versions
public static final EntityType LLAMA = getEntityType("LLAMA");
public static final EntityType PARROT = getEntityType("PARROT");
public static final EntityType TROPICAL_FISH = getEntityType("TROPICAL_FISH");
public static final EntityType PANDA = getEntityType("PANDA");
public static final EntityType TRADER_LLAMA = getEntityType("TRADER_LLAMA");
// Constants for mobs that have changed since earlier versions
public static final EntityType CAT = getEntityType("CAT", "OCELOT");
public enum CatType {
// These are (loosely) Mojang names for the cats
SIAMESE("SIAMESE", "SIAMESE_CAT"),
WHITE("WHITE", "SIAMESE_CAT"),
RED("RED", "RED_CAT"),
TABBY("TABBY", "RED_CAT"),
TUXEDO("BLACK", "BLACK_CAT"),
BRITISH_SHORTHAIR("BRITISH_SHORTHAIR", "SIAMESE_CAT"),
CALICO("CALICO", "RED_CAT"),
PERSIAN("PERSIAN", "RED_CAT"),
RAGDOLL("RAGDOLL", "SIAMESE_CAT"),
JELLIE("JELLIE", "SIAMESE_CAT"),
BLACK("ALL_BLACK", "BLACK_CAT"),
;
private final String catTypeName;
private final String ocelotTypeName;
CatType(final String catTypeName, final String ocelotTypeName) {
this.catTypeName = catTypeName;
this.ocelotTypeName = ocelotTypeName;
}
}
public enum VillagerProfession {
// These are 1.14+ villager professions mapped to their respective pre-V&P profession and career
NONE("FARMER", "FARMER", "NONE"),
ARMORER("BLACKSMITH", "ARMORER"),
BUTCHER("FARMER", "BUTCHER"),
CARTOGRAPHER("LIBRARIAN", "CARTOGRAPHER"),
CLERIC("PRIEST", "CLERIC"),
FARMER("FARMER", "FARMER"),
FISHERMAN("FARMER", "FISHERMAN"),
FLETCHER("FARMER", "FLETCHER"),
LEATHERWORKER("BUTCHER", "LEATHERWORKER"),
LIBRARIAN("LIBRARIAN", "LIBRARIAN"),
MASON(null, null, "MASON"),
NITWIT("NITWIT", "NITWIT"),
SHEPHERD("FARMER", "SHEPHERD"),
TOOLSMITH("BLACKSMITH", "TOOL_SMITH", "TOOLSMITH"),
WEAPONSMITH("BLACKSMITH", "WEAPON_SMITH", "WEAPONSMITH")
;
private String oldProfession;
private String oldCareer;
private String newProfession;
VillagerProfession(final String oldProfession, final String career) {
this.oldProfession = oldProfession;
this.oldCareer = career;
this.newProfession = career;
}
VillagerProfession(final String oldProfession, final String oldCareer, final String newProfession) {
this.oldProfession = oldProfession;
this.oldCareer = oldCareer;
this.newProfession = newProfession;
}
private Villager.Profession asEnum() {
return EnumUtil.valueOf(Villager.Profession.class, newProfession, oldProfession);
}
}
// Older cats are Ocelots, whereas 1.14+ cats are Cats
private static Class catClass = ReflUtil.getClassCached("org.bukkit.entity.Cat");
private static Class catTypeClass = ReflUtil.getClassCached("org.bukkit.entity.Cat.Type");
private static Method catSetTypeMethod = (catClass == null || catTypeClass == null) ? null : ReflUtil.getMethodCached(catClass, "setCatType", catTypeClass);
private static boolean isNewCat() {
return (catClass != null && catTypeClass != null && catSetTypeMethod != null);
}
public static void setCatType(final Entity entity, final CatType type) {
if (isNewCat()) {
try {
catSetTypeMethod.invoke(entity, EnumUtil.valueOf(catTypeClass, type.catTypeName));
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
} else {
((Ocelot) entity).setCatType(Ocelot.Type.valueOf(type.ocelotTypeName));
}
}
// Older villagers have professions and careers, 1.14+ villagers only have professions
private static Class villagerCareerClass = ReflUtil.getClassCached("org.bukkit.entity.Villager.Career");
private static Method villagerSetCareerMethod = (villagerCareerClass == null) ? null : ReflUtil.getMethodCached(Villager.class, "setCareer", villagerCareerClass);
private static boolean isCareerVillager() {
return (villagerCareerClass != null && villagerSetCareerMethod != null);
}
public static void setVillagerProfession(final Entity entity, final VillagerProfession profession) {
if (!isCareerVillager()) {
((Villager) entity).setProfession(profession.asEnum());
} else {
((Villager) entity).setProfession(profession.asEnum());
try {
villagerSetCareerMethod.invoke(entity, EnumUtil.valueOf(villagerCareerClass, profession.oldCareer));
} catch (Exception e) {
e.printStackTrace();
}
}
}
// Only 1.14+ villagers have biome variants
public static void setVillagerType(final Entity entity, final String type) {
Class typeEnum = ReflUtil.getClassCached("org.bukkit.entity.Villager.Type");
if (typeEnum == null) return;
Method villagerSetTypeMethod = ReflUtil.getMethodCached(Villager.class, "setVillagerType", typeEnum);
try {
villagerSetTypeMethod.invoke(entity, EnumUtil.valueOf(typeEnum, type));
} catch (Exception e) {
e.printStackTrace();
}
}
// Llamas only exist in 1.11+
public static void setLlamaColor(final Entity entity, final String color) {
Class llamaClass = ReflUtil.getClassCached("org.bukkit.entity.Llama");
if (llamaClass == null) return;
Class colorEnum = ReflUtil.getClassCached("org.bukkit.entity.Llama.Color");
Method setVariantMethod = ReflUtil.getMethodCached(llamaClass, "setColor");
try {
setVariantMethod.invoke(entity, EnumUtil.valueOf(colorEnum, color));
} catch (Exception e) {
e.printStackTrace();
}
}
// Parrots only exist in 1.12+
public static void setParrotVariant(final Entity entity, final String variant) {
Class parrotClass = ReflUtil.getClassCached("org.bukkit.entity.Parrot");
if (parrotClass == null) return;
Class variantEnum = ReflUtil.getClassCached("org.bukkit.entity.Parrot.Variant");
Method setVariantMethod = ReflUtil.getMethodCached(parrotClass, "setVariant");
try {
setVariantMethod.invoke(entity, EnumUtil.valueOf(variantEnum, variant));
} catch (Exception e) {
e.printStackTrace();
}
}
// Tropical fish only exist in 1.13+
public static void setTropicalFishPattern(final Entity entity, final String pattern) {
Class tropicalFishClass = ReflUtil.getClassCached("org.bukkit.entity.TropicalFish");
if (tropicalFishClass == null) return;
Class patternEnum = ReflUtil.getClassCached("org.bukkit.entity.TropicalFish.Pattern");
Method setPatternMethod = ReflUtil.getMethodCached(tropicalFishClass, "setPattern");
try {
setPatternMethod.invoke(entity, EnumUtil.valueOf(patternEnum, pattern));
} catch (Exception e) {
e.printStackTrace();
}
}
// Mushroom cow variant API only exists in 1.14+
public static void setMooshroomVariant(final Entity entity, final String variant) {
Class mushroomCowClass = ReflUtil.getClassCached("org.bukkit.entity.MushroomCow");
Class variantEnum = ReflUtil.getClassCached("org.bukkit.entity.MushroomCow.Variant");
if (mushroomCowClass == null || variantEnum == null) return;
Method setVariantMethod = ReflUtil.getMethodCached(mushroomCowClass, "setVariant");
try {
setVariantMethod.invoke(entity, EnumUtil.valueOf(variantEnum, variant));
} catch (Exception e) {
e.printStackTrace();
}
}
// Pandas only exists in 1.14+
public static void setPandaGene(final Entity entity, final String gene, final boolean mainGene) {
Class pandaClass = ReflUtil.getClassCached("org.bukkit.entity.Panda");
if (pandaClass == null) return;
Class geneEnum = ReflUtil.getClassCached("org.bukkit.entity.Panda.Gene");
Method setGeneMethod;
if (mainGene) {
setGeneMethod = ReflUtil.getMethodCached(pandaClass, "setMainGene");
} else {
setGeneMethod = ReflUtil.getMethodCached(pandaClass, "setHiddenGene");
}
try {
setGeneMethod.invoke(entity, EnumUtil.valueOf(geneEnum, gene));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -17,8 +17,10 @@ import static com.earth2me.essentials.I18n.tl;
public enum MobData {
BABY_AGEABLE("baby", Ageable.class, Data.BABY, true),
ADULT_AGEABLE("adult", Ageable.class, Data.ADULT, true),
BABY_CAT("kitten", MobCompat.CAT, Data.BABY, false),
BABY_PIG("piglet", EntityType.PIG, Data.BABY, false),
BABY_WOLF("puppy", EntityType.WOLF, Data.BABY, false),
BABY_CHICKEN("chick", EntityType.CHICKEN, Data.BABY, false),
@@ -57,13 +59,19 @@ public enum MobData {
GOLD_ARMOR_HORSE("goldarmor", EntityType.HORSE, EnumUtil.getMaterial("GOLDEN_HORSE_ARMOR", "GOLD_BARDING"), true),
DIAMOND_ARMOR_HORSE("diamondarmor", EntityType.HORSE, EnumUtil.getMaterial("DIAMOND_HORSE_ARMOR", "DIAMOND_BARDING"), true),
ARMOR_HORSE("armor", EntityType.HORSE, EnumUtil.getMaterial("IRON_HORSE_ARMOR", "IRON_BARDING"), true),
SIAMESE_CAT("siamese", EntityType.OCELOT, Ocelot.Type.SIAMESE_CAT, true),
WHITE_CAT("white", EntityType.OCELOT, Ocelot.Type.SIAMESE_CAT, false),
RED_CAT("red", EntityType.OCELOT, Ocelot.Type.RED_CAT, true),
ORANGE_CAT("orange", EntityType.OCELOT, Ocelot.Type.RED_CAT, false),
TABBY_CAT("tabby", EntityType.OCELOT, Ocelot.Type.RED_CAT, false),
BLACK_CAT("black", EntityType.OCELOT, Ocelot.Type.BLACK_CAT, true),
TUXEDO_CAT("tuxedo", EntityType.OCELOT, Ocelot.Type.BLACK_CAT, false),
SIAMESE_CAT("siamese", MobCompat.CAT, MobCompat.CatType.SIAMESE, true),
WHITE_CAT("white", MobCompat.CAT, MobCompat.CatType.WHITE, false),
RED_CAT("red", MobCompat.CAT, MobCompat.CatType.RED, true),
ORANGE_CAT("orange", MobCompat.CAT, MobCompat.CatType.RED, false),
TABBY_CAT("tabby", MobCompat.CAT, MobCompat.CatType.TABBY, true),
BLACK_CAT("black", MobCompat.CAT, MobCompat.CatType.BLACK, true),
TUXEDO_CAT("tuxedo", MobCompat.CAT, MobCompat.CatType.TUXEDO, true),
BRITISH_SHORTHAIR_CAT("britishshorthair", MobCompat.CAT, MobCompat.CatType.BRITISH_SHORTHAIR, true),
CALICO_CAT("calico", MobCompat.CAT, MobCompat.CatType.CALICO, true),
PERSIAN_CAT("persian", MobCompat.CAT, MobCompat.CatType.PERSIAN, true),
RAGDOLL_CAT("ragdoll", MobCompat.CAT, MobCompat.CatType.RAGDOLL, true),
JELLIE_CAT("jellie", MobCompat.CAT, MobCompat.CatType.JELLIE, true),
ALL_BLACK_CAT("allblack", MobCompat.CAT, MobCompat.CatType.BLACK, true),
BABY_ZOMBIE("baby", EntityType.ZOMBIE.getEntityClass(), Data.BABYZOMBIE, true),
ADULT_ZOMBIE("adult", EntityType.ZOMBIE.getEntityClass(), Data.ADULTZOMBIE, true),
DIAMOND_SWORD_ZOMBIE("diamondsword", EntityType.ZOMBIE.getEntityClass(), Material.DIAMOND_SWORD, true),
@@ -83,31 +91,69 @@ public enum MobData {
SADDLE_PIG("saddle", EntityType.PIG, Data.PIGSADDLE, true),
ANGRY_WOLF("angry", EntityType.WOLF, Data.ANGRY, true),
RABID_WOLF("rabid", EntityType.WOLF, Data.ANGRY, false),
FARMER_VILLAGER("farmer", EntityType.VILLAGER, Villager.Profession.FARMER, true),
LIBRARIAN_VILLAGER("librarian", EntityType.VILLAGER, Villager.Profession.LIBRARIAN, true),
PRIEST_VILLAGER("priest", EntityType.VILLAGER, Villager.Profession.PRIEST, true),
FATHER_VILLAGER("father", EntityType.VILLAGER, Villager.Profession.PRIEST, false),
SMITH_VILLAGER("smith", EntityType.VILLAGER, Villager.Profession.BLACKSMITH, true),
BUTCHER_VILLAGER("butcher", EntityType.VILLAGER, Villager.Profession.BUTCHER, true),
VILLAGER("villager", EntityType.VILLAGER, MobCompat.VillagerProfession.NONE, true),
ARMORER_VILLAGER("armorer", EntityType.VILLAGER, MobCompat.VillagerProfession.ARMORER, true),
BUTCHER_VILLAGER("butcher", EntityType.VILLAGER, MobCompat.VillagerProfession.BUTCHER, true),
CARTOGRAPHER_VILLAGER("cartographer", EntityType.VILLAGER, MobCompat.VillagerProfession.CARTOGRAPHER, true),
CLERIC_VILLAGER("cleric", EntityType.VILLAGER, MobCompat.VillagerProfession.CLERIC, true),
FARMER_VILLAGER("farmer", EntityType.VILLAGER, MobCompat.VillagerProfession.FARMER, true),
FISHERMAN_VILLAGER("fisherman", EntityType.VILLAGER, MobCompat.VillagerProfession.FISHERMAN, true),
FLETCHER_VILLAGER("fletcher", EntityType.VILLAGER, MobCompat.VillagerProfession.FLETCHER, true),
LEATHERWORKER_VILLAGER("leatherworker", EntityType.VILLAGER, MobCompat.VillagerProfession.LEATHERWORKER, true),
LIBRARIAN_VILLAGER("librarian", EntityType.VILLAGER, MobCompat.VillagerProfession.LIBRARIAN, true),
MASON_VILLAGER("mason", EntityType.VILLAGER, MobCompat.VillagerProfession.MASON, true),
NITWIT_VILLAGER("nitwit", EntityType.VILLAGER, MobCompat.VillagerProfession.NITWIT, true),
SHEPHERD_VILLAGER("shepherd", EntityType.VILLAGER, MobCompat.VillagerProfession.SHEPHERD, true),
TOOLSMITH_VILLAGER("toolsmith", EntityType.VILLAGER, MobCompat.VillagerProfession.TOOLSMITH, true),
WEAPONSMITH_VILLAGER("weaponsmith", EntityType.VILLAGER, MobCompat.VillagerProfession.WEAPONSMITH, true),
DESERT_VILLAGER("desert", EntityType.VILLAGER, "villagertype:DESERT", true),
JUNGLE_VILLAGER("jungle", EntityType.VILLAGER, "villagertype:JUNGLE", true),
PLAINS_VILLAGER("plains", EntityType.VILLAGER, "villagertype:PLAINS", true),
SAVANNA_VILLAGER("savanna", EntityType.VILLAGER, "villagertype:SAVANNA", true),
SNOWY_VILLAGER("snowy", EntityType.VILLAGER, "villagertype:SNOWY", true),
SWAMP_VILLAGER("swamp", EntityType.VILLAGER, "villagertype:SWAMP", true),
TAIGA_VILLAGER("taiga", EntityType.VILLAGER, "villagertype:TAIGA", true),
SIZE_SLIME("", "<1-100>", EntityType.SLIME.getEntityClass(), Data.SIZE, true),
NUM_EXPERIENCE_ORB("", "<1-2000000000>", EntityType.EXPERIENCE_ORB, Data.EXP, true),
RED_PARROT("red", EntityType.PARROT, Parrot.Variant.RED, true),
GREEN_PARROT("green", EntityType.PARROT, Parrot.Variant.GREEN, true),
BLUE_PARROT("blue", EntityType.PARROT, Parrot.Variant.BLUE, true),
CYAN_PARROT("cyan", EntityType.PARROT, Parrot.Variant.CYAN, true),
GRAY_PARROT("gray", EntityType.PARROT, Parrot.Variant.GRAY, true),
KOB_TROPICAL_FISH("kob", EntityType.TROPICAL_FISH, TropicalFish.Pattern.KOB, true),
SUNSTREAK_TROPICAL_FISH("sunstreak", EntityType.TROPICAL_FISH, TropicalFish.Pattern.SUNSTREAK, true),
SNOOPER_TROPICAL_FISH("snooper", EntityType.TROPICAL_FISH, TropicalFish.Pattern.SNOOPER, true),
DASHER_TROPICAL_FISH("dasher", EntityType.TROPICAL_FISH, TropicalFish.Pattern.DASHER, true),
BRINELY_TROPICAL_FISH("brinely", EntityType.TROPICAL_FISH, TropicalFish.Pattern.BRINELY, true),
SPOTTY_TROPICAL_FISH("spotty", EntityType.TROPICAL_FISH, TropicalFish.Pattern.SPOTTY, true),
FLOPPER_TROPICAL_FISH("flopper", EntityType.TROPICAL_FISH, TropicalFish.Pattern.FLOPPER, true),
STRIPEY_TROPICAL_FISH("stripey", EntityType.TROPICAL_FISH, TropicalFish.Pattern.STRIPEY, true),
GLITTER_TROPICAL_FISH("glitter", EntityType.TROPICAL_FISH, TropicalFish.Pattern.GLITTER, true),
BLOCKFISH_TROPICAL_FISH("blockfish", EntityType.TROPICAL_FISH, TropicalFish.Pattern.BLOCKFISH, true),
BETTY_TROPICAL_FISH("betty", EntityType.TROPICAL_FISH, TropicalFish.Pattern.BETTY, true),
CLAYFISH_TROPICAL_FISH("clayfish", EntityType.TROPICAL_FISH, TropicalFish.Pattern.CLAYFISH, true);
RED_PARROT("red", MobCompat.PARROT, "parrot:RED", true),
GREEN_PARROT("green", MobCompat.PARROT, "parrot:GREEN", true),
BLUE_PARROT("blue", MobCompat.PARROT, "parrot:BLUE", true),
CYAN_PARROT("cyan", MobCompat.PARROT, "parrot:CYAN", true),
GRAY_PARROT("gray", MobCompat.PARROT, "parrot:GRAY", true),
KOB_TROPICAL_FISH("kob", MobCompat.TROPICAL_FISH, "tropicalfish:KOB", true),
SUNSTREAK_TROPICAL_FISH("sunstreak", MobCompat.TROPICAL_FISH, "tropicalfish:SUNSTREAK", true),
SNOOPER_TROPICAL_FISH("snooper", MobCompat.TROPICAL_FISH, "tropicalfish:SNOOPER", true),
DASHER_TROPICAL_FISH("dasher", MobCompat.TROPICAL_FISH, "tropicalfish:DASHER", true),
BRINELY_TROPICAL_FISH("brinely", MobCompat.TROPICAL_FISH, "tropicalfish:BRINELY", true),
SPOTTY_TROPICAL_FISH("spotty", MobCompat.TROPICAL_FISH, "tropicalfish:SPOTTY", true),
FLOPPER_TROPICAL_FISH("flopper", MobCompat.TROPICAL_FISH, "tropicalfish:FLOPPER", true),
STRIPEY_TROPICAL_FISH("stripey", MobCompat.TROPICAL_FISH, "tropicalfish:STRIPEY", true),
GLITTER_TROPICAL_FISH("glitter", MobCompat.TROPICAL_FISH, "tropicalfish:GLITTER", true),
BLOCKFISH_TROPICAL_FISH("blockfish", MobCompat.TROPICAL_FISH, "tropicalfish:BLOCKFISH", true),
BETTY_TROPICAL_FISH("betty", MobCompat.TROPICAL_FISH, "tropicalfish:BETTY", true),
CLAYFISH_TROPICAL_FISH("clayfish", MobCompat.TROPICAL_FISH, "tropicalfish:CLAYFISH", true),
BROWN_MUSHROOM_COW("brown", EntityType.MUSHROOM_COW, "mooshroom:BROWN", true),
RED_MUSHROOM_COW("red", EntityType.MUSHROOM_COW, "mooshroom:RED", true),
AGGRESSIVE_PANDA_MAIN("aggressive", MobCompat.PANDA, "pandamain:AGGRESSIVE", true),
LAZY_PANDA_MAIN("lazy", MobCompat.PANDA, "pandamain:LAZY", true),
WORRIED_PANDA_MAIN("worried", MobCompat.PANDA, "pandamain:WORRIED", true),
PLAYFUL_PANDA_MAIN("playful", MobCompat.PANDA, "pandamain:PLAYFUL", true),
BROWN_PANDA_MAIN("brown", MobCompat.PANDA, "pandamain:BROWN", true),
WEAK_PANDA_MAIN("weak", MobCompat.PANDA, "pandamain:WEAK", true),
AGGRESSIVE_PANDA_HIDDEN("aggressive_hidden", MobCompat.PANDA, "pandahidden:AGGRESSIVE", true),
LAZY_PANDA_HIDDEN("lazy_hidden", MobCompat.PANDA, "pandahidden:LAZY", true),
WORRIED_PANDA_HIDDEN("worried_hidden", MobCompat.PANDA, "pandahidden:WORRIED", true),
PLAYFUL_PANDA_HIDDEN("playful_hidden", MobCompat.PANDA, "pandahidden:PLAYFUL", true),
BROWN_PANDA_HIDDEN("brown_hidden", MobCompat.PANDA, "pandahidden:BROWN", true),
WEAK_PANDA_HIDDEN("weak_hidden", MobCompat.PANDA, "pandahidden:WEAK", true),
CREAMY_LLAMA("creamy", MobCompat.LLAMA, "llama:CREAMY", true),
WHITE_LLAMA("white", MobCompat.LLAMA, "llama:WHITE", true),
BROWN_LLAMA("brown", MobCompat.LLAMA, "llama:BROWN", true),
GRAY_LLAMA("gray", MobCompat.LLAMA, "llama:GRAY", true),
CREAMY_TRADER_LLAMA("creamy", MobCompat.TRADER_LLAMA, "llama:CREAMY", true),
WHITE_TRADER_LLAMA("white", MobCompat.TRADER_LLAMA, "llama:WHITE", true),
BROWN_TRADER_LLAMA("brown", MobCompat.TRADER_LLAMA, "llama:BROWN", true),
GRAY_TRADER_LLAMA("gray", MobCompat.TRADER_LLAMA, "llama:GRAY", true)
;
@@ -127,6 +173,8 @@ public enum MobData {
SIZE
}
public static final Logger logger = Logger.getLogger("Essentials");
MobData(String n, Object type, Object value, boolean isPublic) {
@@ -157,9 +205,11 @@ public enum MobData {
public static LinkedHashMap<String, MobData> getPossibleData(final Entity spawned, boolean publicOnly) {
LinkedHashMap<String, MobData> mobList = new LinkedHashMap<String, MobData>();
for (MobData data : MobData.values()) {
if (data.type instanceof EntityType && spawned.getType().equals(data.type) && ((publicOnly && data.isPublic) || !publicOnly)) {
if (data.type == null || (publicOnly && !data.isPublic)) continue;
if (data.type instanceof EntityType && spawned.getType().equals(data.type)) {
mobList.put(data.nickname.toLowerCase(Locale.ENGLISH), data);
} else if (data.type instanceof Class && ((Class) data.type).isAssignableFrom(spawned.getClass()) && ((publicOnly && data.isPublic) || !publicOnly)) {
} else if (data.type instanceof Class && ((Class) data.type).isAssignableFrom(spawned.getClass())) {
mobList.put(data.nickname.toLowerCase(Locale.ENGLISH), data);
}
}
@@ -250,10 +300,10 @@ public enum MobData {
((Horse) spawned).setColor((Horse.Color) this.value);
} else if (this.value instanceof Horse.Style) {
((Horse) spawned).setStyle((Horse.Style) this.value);
} else if (this.value instanceof Ocelot.Type) {
((Ocelot) spawned).setCatType((Ocelot.Type) this.value);
} else if (this.value instanceof Villager.Profession) {
((Villager) spawned).setProfession((Villager.Profession) this.value);
} else if (this.value instanceof MobCompat.CatType) {
MobCompat.setCatType(spawned, (MobCompat.CatType) this.value);
} else if (this.value instanceof MobCompat.VillagerProfession) {
MobCompat.setVillagerProfession(spawned, (MobCompat.VillagerProfession) this.value);
} else if (this.value instanceof Material) {
if (this.type.equals(EntityType.HORSE)) {
((Horse) spawned).setTamed(true);
@@ -263,10 +313,33 @@ public enum MobData {
InventoryWorkaround.setItemInMainHand(invent, new ItemStack((Material) this.value, 1));
InventoryWorkaround.setItemInMainHandDropChance(invent, 0.1f);
}
} else if (this.value instanceof Parrot.Variant) {
((Parrot) spawned).setVariant((Parrot.Variant) this.value);
} else if (this.value instanceof TropicalFish.Pattern) {
((TropicalFish) spawned).setPattern((TropicalFish.Pattern) this.value);
} else if (this.value instanceof String) {
final String[] split = ((String) this.value).split(":");
switch (split[0]) {
case "parrot":
MobCompat.setParrotVariant(spawned, split[1]);
break;
case "tropicalfish":
MobCompat.setTropicalFishPattern(spawned, split[1]);
break;
case "mooshroom":
MobCompat.setMooshroomVariant(spawned, split[1]);
break;
case "pandamain":
MobCompat.setPandaGene(spawned, split[1], true);
break;
case "pandahidden":
MobCompat.setPandaGene(spawned, split[1], false);
break;
case "llama":
MobCompat.setLlamaColor(spawned, split[1]);
break;
case "villagertype":
MobCompat.setVillagerType(spawned, split[1]);
break;
}
} else {
logger.warning("Unknown mob data type: " + this.toString());
}
}
}
@@ -14,6 +14,7 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.conversations.Conversation;
import org.bukkit.conversations.ConversationAbandonedEvent;
import org.bukkit.entity.*;
import org.bukkit.entity.memory.MemoryKey;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.*;
@@ -23,6 +24,7 @@ import org.bukkit.metadata.MetadataValue;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.plugin.Plugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
@@ -108,6 +110,15 @@ public class OfflinePlayer implements Player {
public void setHealth(double d) {
}
@Override
public double getAbsorptionAmount() {
return 0;
}
@Override
public void setAbsorptionAmount(double v) {
}
@Override
public boolean isInsideVehicle() {
return false;
@@ -133,15 +144,24 @@ public class OfflinePlayer implements Player {
return world;
}
@Override
public void setRotation(float yaw, float pitch) {
location.setYaw(yaw);
location.setPitch(pitch);
}
public void setLocation(Location loc) {
location = loc;
world = loc.getWorld();
}
public void teleportTo(Location lctn) {
location = lctn;
world = location.getWorld();
}
public void teleportTo(Entity entity) {
teleportTo(entity.getLocation());
}
@Override
@@ -153,6 +173,11 @@ public class OfflinePlayer implements Player {
return null;
}
@Override
public Pose getPose() {
return null;
}
@Override
public boolean performCommand(String string) {
return false;
@@ -411,19 +436,6 @@ public class OfflinePlayer implements Player {
return true;
}
@Override
public void awardAchievement(Achievement a) {
}
@Override
public void removeAchievement(Achievement achievement) {
}
@Override
public boolean hasAchievement(Achievement achievement) {
return false;
}
@Override
public void incrementStatistic(Statistic ststc) {
}
@@ -641,6 +653,14 @@ public class OfflinePlayer implements Player {
public void setTotalExperience(int i) {
}
@Override
public void sendExperienceChange(float v) {
}
@Override
public void sendExperienceChange(float v, int i) {
}
@Override
public float getExhaustion() {
return 0F;
@@ -1326,6 +1346,16 @@ public class OfflinePlayer implements Player {
return false;
}
@Override
public <T> T getMemory(MemoryKey<T> memoryKey) {
return null;
}
@Override
public <T> void setMemory(MemoryKey<T> memoryKey, T t) {
}
@Override
public <T extends Projectile> T launchProjectile(Class<? extends T> type, Vector vector) {
return null;
@@ -1335,6 +1365,11 @@ public class OfflinePlayer implements Player {
public void sendSignChange(Location arg0, String[] arg1) throws IllegalArgumentException {
}
@Override
public void sendSignChange(Location loc, String[] lines, DyeColor dyeColor) throws IllegalArgumentException {
}
@Override
public Location getBedSpawnLocation() {
return null;
@@ -1605,4 +1640,13 @@ public class OfflinePlayer implements Player {
@Override
public void updateCommands() {
}
@Override
public void openBook(ItemStack book) {
}
@Override
public PersistentDataContainer getPersistentDataContainer() {
return null;
}
}
@@ -1,13 +1,15 @@
package com.earth2me.essentials;
import com.earth2me.essentials.api.IItemDb;
import com.earth2me.essentials.commands.IEssentialsCommand;
import com.earth2me.essentials.signs.EssentialsSign;
import com.earth2me.essentials.signs.Signs;
import com.earth2me.essentials.textreader.IText;
import com.earth2me.essentials.textreader.SimpleTextInput;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.LocationUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.IEssentials;
import org.bukkit.ChatColor;
import org.bukkit.Material;
@@ -22,15 +24,25 @@ import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
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 final transient EssentialsConf config;
@@ -427,6 +439,7 @@ public class Settings implements net.ess3.api.ISettings {
mFormat = mFormat.replace("{TEAMNAME}", "{5}");
mFormat = mFormat.replace("{PREFIX}", "{6}");
mFormat = mFormat.replace("{SUFFIX}", "{7}");
mFormat = mFormat.replace("{USERNAME}", "{8}");
mFormat = "§r".concat(mFormat);
chatFormats.put(group, mFormat);
}
@@ -492,6 +505,7 @@ public class Settings implements net.ess3.api.ISettings {
cancelAfkOnInteract = _cancelAfkOnInteract();
cancelAfkOnMove = _cancelAfkOnMove();
getFreezeAfkPlayers = _getFreezeAfkPlayers();
sleepIgnoresAfkPlayers = _sleepIgnoresAfkPlayers();
afkListName = _getAfkListName();
isAfkListName = !afkListName.equalsIgnoreCase("none");
itemSpawnBl = _getItemSpawnBlacklist();
@@ -534,14 +548,24 @@ public class Settings implements net.ess3.api.ISettings {
currencyFormat = _getCurrencyFormat();
unprotectedSigns = _getUnprotectedSign();
defaultEnabledConfirmCommands = _getDefaultEnabledConfirmCommands();
teleportBackWhenFreedFromJail = _isTeleportBackWhenFreedFromJail();
isCompassTowardsHomePerm = _isCompassTowardsHomePerm();
isAllowWorldInBroadcastworld = _isAllowWorldInBroadcastworld();
itemDbType = _getItemDbType();
forceEnableRecipe = _isForceEnableRecipe();
allowOldIdSigns = _allowOldIdSigns();
isWaterSafe = _isWaterSafe();
isSafeUsermap = _isSafeUsermap();
logCommandBlockCommands = _logCommandBlockCommands();
nickBlacklist = _getNickBlacklist();
maxProjectileSpeed = _getMaxProjectileSpeed();
}
private List<Material> itemSpawnBl = new ArrayList<Material>();
void _lateLoadItemSpawnBlacklist() {
itemSpawnBl = _getItemSpawnBlacklist();
}
private List<Material> itemSpawnBl = new ArrayList<>();
@Override
public List<Material> itemSpawnBlacklist() {
@@ -550,7 +574,8 @@ public class Settings implements net.ess3.api.ISettings {
private List<Material> _getItemSpawnBlacklist() {
final List<Material> epItemSpwn = new ArrayList<>();
if (ess.getItemDb() == null) {
final IItemDb itemDb = ess.getItemDb();
if (itemDb == null || !itemDb.isReady()) {
logger.log(Level.FINE, "Skipping item spawn blacklist read; item DB not yet loaded.");
return epItemSpwn;
}
@@ -560,7 +585,7 @@ public class Settings implements net.ess3.api.ISettings {
continue;
}
try {
final ItemStack iStack = ess.getItemDb().get(itemName);
final ItemStack iStack = itemDb.get(itemName);
epItemSpwn.add(iStack.getType());
} catch (Exception ex) {
logger.log(Level.SEVERE, tl("unknownItemInList", itemName, "item-spawn-blacklist"), ex);
@@ -685,12 +710,20 @@ public class Settings implements net.ess3.api.ISettings {
if (itemName.isEmpty()) {
continue;
}
ItemStack itemStack;
try {
itemStack = ess.getItemDb().get(itemName);
list.add(itemStack.getType());
} catch (Exception ex) {
Material mat = EnumUtil.getMaterial(itemName.toUpperCase());
if (mat == null) {
try {
ItemStack itemStack = ess.getItemDb().get(itemName);
mat = itemStack.getType();
} catch (Exception ignored) {}
}
if (mat == null) {
logger.log(Level.SEVERE, tl("unknownItemInList", itemName, configName));
} else {
list.add(mat);
}
}
return list;
@@ -878,6 +911,17 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("cancel-afk-on-interact", true);
}
private boolean sleepIgnoresAfkPlayers;
@Override
public boolean sleepIgnoresAfkPlayers() {
return sleepIgnoresAfkPlayers;
}
private boolean _sleepIgnoresAfkPlayers() {
return config.getBoolean("sleep-ignores-afk-players", true);
}
private String afkListName;
private boolean isAfkListName;
@@ -1447,6 +1491,17 @@ public class Settings implements net.ess3.api.ISettings {
return getDefaultEnabledConfirmCommands().contains(commandName.toLowerCase());
}
private boolean teleportBackWhenFreedFromJail;
private boolean _isTeleportBackWhenFreedFromJail() {
return config.getBoolean("teleport-back-when-freed-from-jail", true);
}
@Override
public boolean isTeleportBackWhenFreedFromJail() {
return teleportBackWhenFreedFromJail;
}
private boolean isCompassTowardsHomePerm;
private boolean _isCompassTowardsHomePerm() {
@@ -1501,4 +1556,77 @@ public class Settings implements net.ess3.api.ISettings {
public boolean allowOldIdSigns() {
return allowOldIdSigns;
}
private boolean isWaterSafe;
private boolean _isWaterSafe() {
boolean _isWaterSafe = config.getBoolean("is-water-safe", false);
LocationUtil.setIsWaterSafe(_isWaterSafe);
return _isWaterSafe;
}
@Override
public boolean isWaterSafe() {
return isWaterSafe;
}
private boolean isSafeUsermap;
private boolean _isSafeUsermap() {
return config.getBoolean("safe-usermap-names", true);
}
@Override
public boolean isSafeUsermap() {
return isSafeUsermap;
}
private boolean logCommandBlockCommands;
private boolean _logCommandBlockCommands() {
return config.getBoolean("log-command-block-commands", true);
}
@Override
public boolean logCommandBlockCommands() {
return logCommandBlockCommands;
}
private Set<Predicate<String>> nickBlacklist;
private Set<Predicate<String>> _getNickBlacklist() {
Set<Predicate<String>> blacklist = new HashSet<>();
config.getStringList("nick-blacklist").forEach(entry -> {
try {
blacklist.add(Pattern.compile(entry).asPredicate());
} catch (PatternSyntaxException e) {
logger.warning("Invalid nickname blacklist regex: " + entry);
}
});
return blacklist;
}
@Override
public Set<Predicate<String>> getNickBlacklist() {
return nickBlacklist;
}
private double maxProjectileSpeed;
private double _getMaxProjectileSpeed() {
return config.getDouble("max-projectile-speed", 8);
}
@Override
public double getMaxProjectileSpeed() {
return maxProjectileSpeed;
}
@Override
public boolean isSpawnIfNoHome() {
return config.getBoolean("spawn-if-no-home", true);
}
}
@@ -2,7 +2,9 @@ package com.earth2me.essentials;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.LocationUtil;
import io.papermc.lib.PaperLib;
import net.ess3.api.IEssentials;
import net.ess3.api.ITeleport;
import net.ess3.api.IUser;
import net.ess3.api.events.UserWarpEvent;
import org.bukkit.Bukkit;
@@ -18,7 +20,7 @@ import java.util.GregorianCalendar;
import static com.earth2me.essentials.I18n.tl;
public class Teleport implements net.ess3.api.ITeleport {
public class Teleport implements ITeleport {
private final IUser teleportOwner;
private final IEssentials ess;
private TimedTeleport timedTeleport;
@@ -49,7 +51,7 @@ public class Teleport implements net.ess3.api.ITeleport {
final long earliestLong = earliestTime.getTimeInMillis();
// When was the last teleportPlayer used?
final Long lastTime = teleportOwner.getLastTeleportTimestamp();
final long lastTime = teleportOwner.getLastTeleportTimestamp();
if (lastTime > time.getTimeInMillis()) {
// This is to make sure time didn't get messed up on last teleportPlayer use.
@@ -124,21 +126,21 @@ public class Teleport implements net.ess3.api.ITeleport {
if (LocationUtil.isBlockUnsafeForUser(teleportee, loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
if (ess.getSettings().isTeleportSafetyEnabled()) {
if (ess.getSettings().isForceDisableTeleportSafety()) {
teleportee.getBase().teleport(loc, cause);
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
} else {
teleportee.getBase().teleport(LocationUtil.getSafeDestination(ess, teleportee, loc), cause);
PaperLib.teleportAsync(teleportee.getBase(), LocationUtil.getSafeDestination(ess, teleportee, loc), cause);
}
} else {
throw new Exception(tl("unsafeTeleportDestination", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
}
} else {
if (ess.getSettings().isForceDisableTeleportSafety()) {
teleportee.getBase().teleport(loc, cause);
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
} else {
if (ess.getSettings().isTeleportToCenterLocation()) {
loc = LocationUtil.getRoundedDestination(loc);
}
teleportee.getBase().teleport(loc, cause);
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
}
}
}
@@ -209,6 +211,39 @@ public class Teleport implements net.ess3.api.ITeleport {
initTimer((long) (delay * 1000.0), teleportee, target, cashCharge, cause, false);
}
private void teleportOther(IUser teleporter, IUser teleportee, ITarget target, Trade chargeFor, TeleportCause cause) throws Exception {
double delay = ess.getSettings().getTeleportDelay();
Trade cashCharge = chargeFor;
if (teleporter != null && chargeFor != null) {
chargeFor.isAffordableFor(teleporter);
//This code is to make sure that commandcosts are checked in the initial world, and not in the resulting world.
if (!chargeFor.getCommandCost(teleporter).equals(BigDecimal.ZERO)) {
//By converting a command cost to a regular cost, the command cost permission isn't checked when executing the charge after teleport.
cashCharge = new Trade(chargeFor.getCommandCost(teleporter), ess);
}
}
cooldown(true);
if (delay <= 0 || teleporter == null
|| teleporter.isAuthorized("essentials.teleport.timer.bypass")
|| teleportOwner.isAuthorized("essentials.teleport.timer.bypass")
|| teleportee.isAuthorized("essentials.teleport.timer.bypass")) {
cooldown(false);
now(teleportee, target, cause);
if (teleporter != null && cashCharge != null) {
cashCharge.charge(teleporter);
}
return;
}
cancel(false);
warnUser(teleportee, delay);
initTimer((long) (delay * 1000.0), teleportee, target, cashCharge, cause, false);
}
//The respawn function is a wrapper used to handle tp fallback, on /jail and /home
@Override
public void respawn(final Trade chargeFor, TeleportCause cause) throws Exception {
@@ -231,7 +266,7 @@ public class Teleport implements net.ess3.api.ITeleport {
initTimer((long) (delay * 1000.0), teleportOwner, null, chargeFor, cause, true);
}
protected void respawnNow(IUser teleportee, TeleportCause cause) throws Exception {
void respawnNow(IUser teleportee, TeleportCause cause) throws Exception {
final Player player = teleportee.getBase();
Location bed = player.getBedSpawnLocation();
if (bed != null) {
@@ -267,10 +302,16 @@ public class Teleport implements net.ess3.api.ITeleport {
//The back function is a wrapper used to teleportPlayer a player /back to their previous location.
@Override
public void back(Trade chargeFor) throws Exception {
back(teleportOwner, chargeFor);
}
//This function is a wrapper over the other back function for cases where another player performs back for them
@Override
public void back(IUser teleporter, Trade chargeFor) throws Exception {
tpType = TeleportType.BACK;
final Location loc = teleportOwner.getLastLocation();
teleportOwner.sendMessage(tl("backUsageMsg", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
teleport(teleportOwner, new LocationTarget(loc), chargeFor, TeleportCause.COMMAND);
teleportOther(teleporter, teleportOwner, new LocationTarget(loc), chargeFor, TeleportCause.COMMAND);
}
//This function is used to throw a user back after a jail sentence
@@ -16,9 +16,9 @@ public class TimedTeleport implements Runnable {
private final IEssentials ess;
private final Teleport teleport;
private final UUID timer_teleportee;
private int timer_task = -1;
private final long timer_started; // time this task was initiated
private final long timer_delay; // how long to delay the teleportPlayer
private int timer_task;
private final long timer_started; // time this task was initiated
private final long timer_delay; // how long to delay the teleportPlayer
private double timer_health;
// note that I initially stored a clone of the location for reference, but...
// when comparing locations, I got incorrect mismatches (rounding errors, looked like)
@@ -32,8 +32,7 @@ public class TimedTeleport implements Runnable {
private final Trade timer_chargeFor;
private final TeleportCause timer_cause;
public TimedTeleport(IUser user, IEssentials ess, Teleport teleport, long delay, IUser teleportUser, ITarget target, Trade chargeFor, TeleportCause cause, boolean respawn) {
TimedTeleport(IUser user, IEssentials ess, Teleport teleport, long delay, IUser teleportUser, ITarget target, Trade chargeFor, TeleportCause cause, boolean respawn) {
this.teleportOwner = user;
this.ess = ess;
this.teleport = teleport;
@@ -111,8 +110,7 @@ public class TimedTeleport implements Runnable {
if (timer_chargeFor != null) {
timer_chargeFor.charge(teleportOwner);
}
} catch (Exception ex) {
}
} catch (Exception ignored) {}
} catch (Exception ex) {
ess.showError(teleportOwner.getSource(), ex, "\\ teleport");
@@ -124,7 +122,7 @@ public class TimedTeleport implements Runnable {
}
//If we need to cancelTimer a pending teleportPlayer call this method
public void cancelTimer(boolean notifyUser) {
void cancelTimer(boolean notifyUser) {
if (timer_task == -1) {
return;
}
@@ -97,6 +97,11 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return result;
}
@Override
public boolean isPermissionSet(final String node) {
return isPermSetCheck(node);
}
private boolean isAuthorizedCheck(final String node) {
if (base instanceof OfflinePlayer) {
@@ -116,6 +121,24 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
}
private boolean isPermSetCheck(final String node) {
if (base instanceof OfflinePlayer) {
return false;
}
try {
return ess.getPermissionsHandler().isPermissionSet(base, node);
} catch (Exception ex) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.SEVERE, "Permission System Error: " + ess.getPermissionsHandler().getName() + " returned: " + ex.getMessage(), ex);
} else {
ess.getLogger().log(Level.SEVERE, "Permission System Error: " + ess.getPermissionsHandler().getName() + " returned: " + ex.getMessage());
}
return false;
}
}
@Override
public void healCooldown() throws Exception {
final Calendar now = new GregorianCalendar();
@@ -139,10 +162,14 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public void giveMoney(final BigDecimal value, final CommandSource initiator) throws MaxMoneyException {
giveMoney(value, initiator, UserBalanceUpdateEvent.Cause.UNKNOWN);
}
public void giveMoney(final BigDecimal value, final CommandSource initiator, UserBalanceUpdateEvent.Cause cause) throws MaxMoneyException {
if (value.signum() == 0) {
return;
}
setMoney(getMoney().add(value));
setMoney(getMoney().add(value), cause);
sendMessage(tl("addedToAccount", NumberUtil.displayCurrency(value, ess)));
if (initiator != null) {
initiator.sendMessage(tl("addedToOthersAccount", NumberUtil.displayCurrency(value, ess), this.getDisplayName(), NumberUtil.displayCurrency(getMoney(), ess)));
@@ -151,6 +178,10 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public void payUser(final User reciever, final BigDecimal value) throws Exception {
payUser(reciever, value, UserBalanceUpdateEvent.Cause.UNKNOWN);
}
public void payUser(final User reciever, final BigDecimal value, UserBalanceUpdateEvent.Cause cause) throws Exception {
if (value.compareTo(BigDecimal.ZERO) < 1) {
throw new Exception(tl("payMustBePositive"));
}
@@ -172,11 +203,15 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public void takeMoney(final BigDecimal value, final CommandSource initiator) {
takeMoney(value, initiator, UserBalanceUpdateEvent.Cause.UNKNOWN);
}
public void takeMoney(final BigDecimal value, final CommandSource initiator, UserBalanceUpdateEvent.Cause cause) {
if (value.signum() == 0) {
return;
}
try {
setMoney(getMoney().subtract(value));
setMoney(getMoney().subtract(value), cause);
} catch (MaxMoneyException ex) {
ess.getLogger().log(Level.WARNING, "Invalid call to takeMoney, total balance can't be more than the max-money limit.", ex);
}
@@ -417,6 +452,10 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public void setMoney(final BigDecimal value) throws MaxMoneyException {
setMoney(value, UserBalanceUpdateEvent.Cause.UNKNOWN);
}
public void setMoney(final BigDecimal value, UserBalanceUpdateEvent.Cause cause) throws MaxMoneyException {
if (ess.getSettings().isEcoDisabled()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("Internal economy functions disabled, aborting balance change.");
@@ -424,11 +463,11 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return;
}
final BigDecimal oldBalance = _getMoney();
UserBalanceUpdateEvent updateEvent = new UserBalanceUpdateEvent(this.getBase(), oldBalance, value);
UserBalanceUpdateEvent updateEvent = new UserBalanceUpdateEvent(this.getBase(), oldBalance, value, cause);
ess.getServer().getPluginManager().callEvent(updateEvent);
BigDecimal newBalance = updateEvent.getNewBalance();
if (Methods.hasMethod()) {
try {
final Method method = Methods.getMethod();
@@ -465,7 +504,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return;
}
this.getBase().setSleepingIgnored(this.isAuthorized("essentials.sleepingignored") ? true : set);
this.getBase().setSleepingIgnored(this.isAuthorized("essentials.sleepingignored") || set && ess.getSettings().sleepIgnoresAfkPlayers());
if (set && !isAfk()) {
afkPosition = this.getLocation();
this.afkSince = System.currentTimeMillis();
@@ -522,12 +561,14 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
setJailed(false);
sendMessage(tl("haveBeenReleased"));
setJail(null);
try {
getTeleport().back();
} catch (Exception ex) {
if (ess.getSettings().isTeleportBackWhenFreedFromJail()) {
try {
getTeleport().respawn(null, TeleportCause.PLUGIN);
} catch (Exception ex1) {
getTeleport().back();
} catch (Exception ex) {
try {
getTeleport().respawn(null, TeleportCause.PLUGIN);
} catch (Exception ex1) {
}
}
}
return true;
@@ -546,6 +587,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
setMuteTimeout(0);
sendMessage(tl("canTalkAgain"));
setMuted(false);
setMuteReason(null);
return true;
}
}
@@ -17,6 +17,7 @@ import java.math.BigDecimal;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static com.earth2me.essentials.I18n.tl;
@@ -74,6 +75,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
godmode = _getGodModeEnabled();
muted = _getMuted();
muteTimeout = _getMuteTimeout();
muteReason = _getMuteReason();
jailed = _getJailed();
jailTimeout = _getJailTimeout();
lastLogin = _getLastLogin();
@@ -93,6 +95,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
acceptingPay = _getAcceptingPay();
confirmPay = _getConfirmPay();
confirmClear = _getConfirmClear();
lastMessageReplyRecipient = _getLastMessageReplyRecipient();
}
private BigDecimal money;
@@ -232,10 +235,10 @@ public abstract class UserData extends PlayerExtension implements IConf {
config.save();
}
private List<Material> unlimited;
private Set<Material> unlimited;
private List<Material> _getUnlimited() {
List<Material> retlist = new ArrayList<>();
private Set<Material> _getUnlimited() {
Set<Material> retlist = new HashSet<>();
List<String> configList = config.getStringList("unlimited");
for(String s : configList) {
Material mat = Material.matchMaterial(s);
@@ -247,7 +250,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
return retlist;
}
public List<Material> getUnlimited() {
public Set<Material> getUnlimited() {
return unlimited;
}
@@ -256,13 +259,20 @@ public abstract class UserData extends PlayerExtension implements IConf {
}
public void setUnlimited(ItemStack stack, boolean state) {
if (unlimited.contains(stack.getType())) {
unlimited.remove(stack.getType());
}
boolean wasUpdated;
if (state) {
unlimited.add(stack.getType());
wasUpdated = unlimited.add(stack.getType());
} else {
wasUpdated = unlimited.remove(stack.getType());
}
config.setProperty("unlimited", unlimited);
if (wasUpdated) {
applyUnlimited();
}
}
private void applyUnlimited() {
config.setProperty("unlimited", unlimited.stream().map(Enum::name).collect(Collectors.toList()));
config.save();
}
@@ -446,6 +456,22 @@ public abstract class UserData extends PlayerExtension implements IConf {
config.save();
}
private boolean autoTeleportEnabled;
private boolean _getAutoTeleportEnabled() {
return config.getBoolean("teleportauto", false);
}
public boolean isAutoTeleportEnabled() {
return autoTeleportEnabled;
}
public void setAutoTeleportEnabled(boolean set) {
autoTeleportEnabled = set;
config.setProperty("teleportauto", set);
config.save();
}
private List<String> ignoredPlayers;
public List<String> _getIgnoredPlayers() {
@@ -503,6 +529,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
}
private boolean muted;
private String muteReason;
public boolean _getMuted() {
return config.getBoolean("muted", false);
@@ -522,6 +549,29 @@ public abstract class UserData extends PlayerExtension implements IConf {
config.save();
}
public String _getMuteReason() {
return config.getString("muteReason");
}
public String getMuteReason() {
return muteReason;
}
public void setMuteReason(String reason) {
if (reason == null) {
config.removeProperty("muteReason");
muteReason = null;
} else {
muteReason = reason;
config.setProperty("muteReason", reason);
}
config.save();
}
public boolean hasMuteReason(){
return muteReason != null;
}
private long muteTimeout;
private long _getMuteTimeout() {
@@ -759,15 +809,16 @@ public abstract class UserData extends PlayerExtension implements IConf {
}
public long getKitTimestamp(String name) {
name = name.replace('.', '_').replace('/', '_');
name = name.replace('.', '_').replace('/', '_').toLowerCase(Locale.ENGLISH);
if (kitTimestamps != null && kitTimestamps.containsKey(name)) {
return kitTimestamps.get(name);
}
return 0l;
return 0L;
}
public void setKitTimestamp(final String name, final long time) {
kitTimestamps.put(name.toLowerCase(Locale.ENGLISH), time);
public void setKitTimestamp(String name, final long time) {
name = name.replace('.', '_').replace('/', '_').toLowerCase(Locale.ENGLISH);
kitTimestamps.put(name, time);
config.setProperty("timestamps.kits", kitTimestamps);
config.save();
}
@@ -814,7 +865,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
private Map<Pattern, Long> commandCooldowns;
private Map<Pattern, Long> _getCommandCooldowns() {
if (!config.isConfigurationSection("timestamps.command-cooldowns")) {
if (!config.contains("timestamps.command-cooldowns")) {
return null;
}
@@ -941,6 +992,22 @@ public abstract class UserData extends PlayerExtension implements IConf {
save();
}
private boolean lastMessageReplyRecipient;
private boolean _getLastMessageReplyRecipient() {
return config.getBoolean("last-message-reply-recipient", ess.getSettings().isLastMessageReplyRecipient());
}
public boolean isLastMessageReplyRecipient() {
return this.lastMessageReplyRecipient;
}
public void setLastMessageReplyRecipient(boolean enabled) {
this.lastMessageReplyRecipient = enabled;
config.setProperty("last-message-reply-recipient", enabled);
save();
}
public UUID getConfigUUID() {
return config.uuid;
}
@@ -123,7 +123,7 @@ public class UserMap extends CacheLoader<String, User> implements IConf {
if (uuid != null) {
keys.add(uuid);
if (name != null && name.length() > 0) {
final String keyName = StringUtil.safeString(name);
final String keyName = ess.getSettings().isSafeUsermap() ? StringUtil.safeString(name) : name;
if (!names.containsKey(keyName)) {
names.put(keyName, uuid);
uuidMap.writeUUIDMap();
@@ -8,6 +8,8 @@ import com.earth2me.essentials.utils.StringUtil;
import com.google.common.base.Charsets;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.events.UserBalanceUpdateEvent;
import org.bukkit.entity.Player;
import java.io.File;
import java.math.BigDecimal;
@@ -18,7 +20,7 @@ import java.util.logging.Logger;
/**
* Instead of using this api directly, we recommend to use the register plugin: http://bit.ly/RegisterMethod
* You should use Vault instead of directly using this class.
*/
public class Economy {
public Economy() {
@@ -64,7 +66,24 @@ public class Economy {
if (name == null) {
throw new RuntimeException("Economy username cannot be null");
}
return ess.getUser(name);
User user = ess.getUser(name);
if (user == null) {
/*
Attempt lookup using UUID - this prevents balance resets when accessing economy
via Vault during player join.
See: https://github.com/EssentialsX/Essentials/issues/2400
*/
Player player = ess.getServer().getPlayerExact(name);
if (player != null) {
user = ess.getUser(player.getUniqueId());
if (user != null) {
logger.info(String.format("[Economy] Found player %s by UUID %s but not by their actual name - they may have changed their username", name, player.getUniqueId().toString()));
}
}
}
return user;
}
/**
@@ -126,7 +145,7 @@ public class Economy {
throw new NoLoanPermittedException();
}
try {
user.setMoney(balance);
user.setMoney(balance, UserBalanceUpdateEvent.Cause.API);
} catch (MaxMoneyException ex) {
//TODO: Update API to show max balance errors
}
@@ -33,6 +33,9 @@ public interface IItemDb {
/**
* Create a stack from the given name with the maximum stack size for that material.
*
* Note that this will always check against resolver functions from other plugins as well.
* To avoid this behaviour, use net.ess3.api.IItemDb#get(String name, boolean useResolvers).
*
* @param name Item name to look up in the database
* @return The requested item stack with the maximum stack size
* @throws Exception if the item stack cannot be created
@@ -127,11 +130,13 @@ public interface IItemDb {
* item IDs to modern names.
*
* @param item Legacy ID in colon syntax.
* @return
* @return Material if an appropriate material exists, else null.
*/
default Material getFromLegacy(String item) {
final String[] split = item.split(":");
if (!NumberUtil.isInt(split[0])) return null;
final int id = Integer.parseInt(split[0]);
byte damage = 0;
@@ -153,4 +158,11 @@ public interface IItemDb {
default Material getFromLegacy(final int id, final byte damage) {
return MaterialUtil.convertFromLegacy(id, damage);
}
/**
* Check whether the item database is loaded and ready for use.
*
* @return Whether items have finished loading
*/
boolean isReady();
}
@@ -110,6 +110,19 @@ public interface ITeleport {
*/
void back(Trade chargeFor) throws Exception;
/**
* Teleport wrapper used to handle /back teleports that
* are executed by a different player with this
* instance of teleport as a target.
*
* @param teleporter - The user performing the /back command.
* This value may be {@code null} to indicate console.
* @param chargeFor - What the {@code teleporter} will be charged if teleportPlayer is successful
*
* @throws Exception
*/
void back(IUser teleporter, Trade chargeFor) throws Exception;
/**
* Teleport wrapper used to handle throwing user home after a jail sentence
*
@@ -24,10 +24,6 @@ public class Commandafk extends EssentialsCommand {
afkUser = getPlayer(server, user, args, 0);
message = args.length > 1 ? getFinalArg(args, 1) : null;
} catch (PlayerNotFoundException e) {
// If only one arg is passed, assume the command executor is targeting another player.
if (args.length == 1) {
throw e;
}
message = getFinalArg(args, 0);
}
toggleAfk(user, afkUser, message);
@@ -51,7 +47,7 @@ public class Commandafk extends EssentialsCommand {
private void toggleAfk(User sender, User user, String message) throws Exception {
if (message != null && sender != null) {
if (sender.isMuted()) {
throw new Exception(tl("voiceSilenced"));
throw new Exception(sender.hasMuteReason() ? tl("voiceSilencedReason", sender.getMuteReason()) : tl("voiceSilenced"));
}
if (!sender.isAuthorized("essentials.afk.message")) {
throw new Exception(tl("noPermToAFKMessage"));
@@ -1,8 +1,15 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
@@ -13,24 +20,82 @@ public class Commandback extends EssentialsCommand {
}
@Override
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
protected void run(Server server, User user, String commandLabel, String[] args) throws Exception {
CommandSource sender = user.getSource();
if (args.length > 0 && user.isAuthorized("essentials.back.others")) {
this.parseCommand(server, sender, args, true);
return;
}
teleportBack(sender, user);
}
@Override
protected void run(Server server, CommandSource sender, String commandLabel, String[] args) throws Exception {
if (args.length < 1) {
throw new NotEnoughArgumentsException();
}
this.parseCommand(server, sender, args, true);
}
private void parseCommand(Server server, CommandSource sender, String[] args, boolean allowOthers) throws Exception {
Collection<Player> players = new ArrayList<>();
if (allowOthers && args.length > 0 && args[0].trim().length() > 2) {
players = server.matchPlayer(args[0].trim());
}
if (players.size() < 1) {
throw new PlayerNotFoundException();
}
for (Player player : players) {
sender.sendMessage(tl("backOther", player.getName()));
teleportBack(sender, ess.getUser(player));
}
}
private void teleportBack(CommandSource sender, User user) throws Exception {
if (user.getLastLocation() == null) {
throw new Exception(tl("noLocationFound"));
}
String lastWorldName = user.getLastLocation().getWorld().getName();
if (user.getWorld() != user.getLastLocation().getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + lastWorldName)) {
throw new Exception(tl("noPerm", "essentials.worlds." + lastWorldName));
User requester = null;
if (sender.isPlayer()) {
requester = ess.getUser(sender.getPlayer());
if (user.getWorld() != user.getLastLocation().getWorld() && this.ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + lastWorldName)) {
throw new Exception(tl("noPerm", "essentials.worlds." + lastWorldName));
}
if (!requester.isAuthorized("essentials.back.into." + lastWorldName)) {
throw new Exception(tl("noPerm", "essentials.back.into." + lastWorldName));
}
}
if (!user.isAuthorized("essentials.back.into." + lastWorldName)) {
throw new Exception(tl("noPerm", "essentials.back.into." + lastWorldName));
if (requester == null) {
user.getTeleport().back(null, null);
} else if (!requester.equals(user)) {
Trade charge = new Trade(this.getName(), this.ess);
charge.isAffordableFor(requester);
user.getTeleport().back(requester, charge);
} else {
Trade charge = new Trade(this.getName(), this.ess);
charge.isAffordableFor(user);
user.getTeleport().back(charge);
}
final Trade charge = new Trade(this.getName(), ess);
charge.isAffordableFor(user);
user.getTeleport().back(charge);
throw new NoChargeException();
}
@Override
protected List<String> getTabCompleteOptions(Server server, User user, String commandLabel, String[] args) {
if (user.isAuthorized("essentials.back.others") && args.length == 1) {
return getPlayers(server, user);
} else {
return Collections.emptyList();
}
}
}
@@ -102,11 +102,13 @@ public class Commandbalancetop extends EssentialsCommand {
// Don't list NPCs in output
continue;
}
final BigDecimal userMoney = user.getMoney();
user.updateMoneyCache(userMoney);
totalMoney = totalMoney.add(userMoney);
final String name = user.isHidden() ? user.getName() : user.getDisplayName();
balances.put(name, userMoney);
if (!user.isAuthorized("essentials.balancetop.exclude")) {
final BigDecimal userMoney = user.getMoney();
user.updateMoneyCache(userMoney);
totalMoney = totalMoney.add(userMoney);
final String name = user.isHidden() ? user.getName() : user.getDisplayName();
balances.put(name, userMoney);
}
}
}
}
@@ -0,0 +1,35 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.Mob;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.VersionUtil;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.entity.Entity;
import static com.earth2me.essentials.I18n.tl;
public class Commandbeezooka extends EssentialsCommand {
public Commandbeezooka() {
super("beezooka");
}
@Override
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_15_R01)) {
user.sendMessage(tl("unsupportedFeature"));
return;
}
final Entity bee = Mob.BEE.spawn(user.getWorld(), server, user.getBase().getEyeLocation());
bee.setVelocity(user.getBase().getEyeLocation().getDirection().multiply(2));
ess.scheduleSyncDelayedTask(() -> {
final Location loc = bee.getLocation();
bee.remove();
loc.getWorld().createExplosion(loc, 0F);
}, 20);
}
}
@@ -135,6 +135,10 @@ public class Commandcondense extends EssentialsCommand {
if (recipe instanceof ShapedRecipe) {
ShapedRecipe sRecipe = (ShapedRecipe) recipe;
if (sRecipe.getShape().length != sRecipe.getShape()[0].length()) {
// Only accept square recipes
return null;
}
inputList = sRecipe.getIngredientMap().values();
} else if (recipe instanceof ShapelessRecipe) {
ShapelessRecipe slRecipe = (ShapelessRecipe) recipe;
@@ -0,0 +1,45 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.Kit;
import com.google.common.collect.Lists;
import org.bukkit.Server;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commanddelkit extends EssentialsCommand {
public Commanddelkit() {
super("delkit");
}
@Override
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 1) {
final String kitList = ess.getKits().listKits(ess, null);
sender.sendMessage(kitList.length() > 0 ? tl("kits", kitList) : tl("noKits"));
throw new NoChargeException();
} else {
final String kitName = args[0];
final Kit kit = new Kit(kitName, ess);
if (sender.getPlayer() != null) {
kit.checkPerms(ess.getUser(sender.getPlayer()));
}
ess.getKits().removeKit(kitName);
sender.sendMessage(tl("deleteKit", kitName));
}
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
if (args.length == 1) {
return Lists.newArrayList(ess.getKits().getKits().getKeys(false));
}
return Collections.emptyList();
}
}
@@ -14,7 +14,7 @@ public class Commanddisposal extends EssentialsCommand {
@Override
protected void run(Server server, User user, String commandLabel, String[] args) throws Exception {
user.sendMessage(tl("openingDisposal"));
user.getBase().openInventory(ess.getServer().createInventory(user.getBase(), 36, "Disposal"));
user.getBase().openInventory(ess.getServer().createInventory(user.getBase(), 36, tl("disposal")));
}
}
@@ -6,6 +6,7 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.NumberUtil;
import com.google.common.collect.Lists;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.events.UserBalanceUpdateEvent;
import org.bukkit.Server;
import java.math.BigDecimal;
@@ -54,7 +55,7 @@ public class Commandeco extends EssentialsLoopCommand {
protected void updatePlayer(final Server server, final CommandSource sender, final User player, final String[] args) throws NotEnoughArgumentsException, ChargeException, MaxMoneyException {
switch (cmd) {
case GIVE:
player.giveMoney(amount, sender);
player.giveMoney(amount, sender, UserBalanceUpdateEvent.Cause.COMMAND_ECO);
break;
case TAKE:
@@ -72,10 +73,10 @@ public class Commandeco extends EssentialsLoopCommand {
BigDecimal money = player.getMoney();
BigDecimal minBalance = ess.getSettings().getMinMoney();
if (money.subtract(amount).compareTo(minBalance) >= 0) {
player.takeMoney(amount, sender);
player.takeMoney(amount, sender, UserBalanceUpdateEvent.Cause.COMMAND_ECO);
} else if (sender == null) {
try {
player.setMoney(minBalance);
player.setMoney(minBalance, UserBalanceUpdateEvent.Cause.COMMAND_ECO);
} catch (MaxMoneyException ex) {
// Take shouldn't be able to throw a max money exception
}
@@ -90,7 +91,7 @@ public class Commandeco extends EssentialsLoopCommand {
BigDecimal maxBalance = ess.getSettings().getMaxMoney();
boolean underMinimum = (amount.compareTo(minBalance) < 0);
boolean aboveMax = (amount.compareTo(maxBalance) > 0);
player.setMoney(underMinimum ? minBalance : aboveMax ? maxBalance : amount);
player.setMoney(underMinimum ? minBalance : aboveMax ? maxBalance : amount, UserBalanceUpdateEvent.Cause.COMMAND_ECO);
player.sendMessage(tl("setBal", NumberUtil.displayCurrency(player.getMoney(), ess)));
if (sender != null) {
sender.sendMessage(tl("setBalOthers", player.getDisplayName(), NumberUtil.displayCurrency(player.getMoney(), ess)));
@@ -6,96 +6,144 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.UserMap;
import com.earth2me.essentials.utils.*;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginManager;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.*;
import java.util.function.Supplier;
import static com.earth2me.essentials.I18n.tl;
// This command has 4 undocumented behaviours #EasterEgg
public class Commandessentials extends EssentialsCommand {
private final Sound NOTE_HARP = EnumUtil.valueOf(Sound.class, "BLOCK_NOTE_HARP", "NOTE_PIANO");
private static final Sound NOTE_HARP = EnumUtil.valueOf(Sound.class, "BLOCK_NOTE_BLOCK_HARP", "BLOCK_NOTE_HARP", "NOTE_PIANO");
private static final Sound MOO_SOUND = EnumUtil.valueOf(Sound.class, "COW_IDLE", "ENTITY_COW_MILK");
private static final String NYAN_TUNE = "1D#,1E,2F#,,2A#,1E,1D#,1E,2F#,2B,2D#,2E,2D#,2A#,2B,,2F#,,1D#,1E,2F#,2B,2C#,2A#,2B,2C#,2E,2D#,2E,2C#,,2F#,,2G#,,1D,1D#,,1C#,1D,1C#,1B,,1B,,1C#,,1D,,1D,1C#,1B,1C#,1D#,2F#,2G#,1D#,2F#,1C#,1D#,1B,1C#,1B,1D#,,2F#,,2G#,1D#,2F#,1C#,1D#,1B,1D,1D#,1D,1C#,1B,1C#,1D,,1B,1C#,1D#,2F#,1C#,1D,1C#,1B,1C#,,1B,,1C#,,2F#,,2G#,,1D,1D#,,1C#,1D,1C#,1B,,1B,,1C#,,1D,,1D,1C#,1B,1C#,1D#,2F#,2G#,1D#,2F#,1C#,1D#,1B,1C#,1B,1D#,,2F#,,2G#,1D#,2F#,1C#,1D#,1B,1D,1D#,1D,1C#,1B,1C#,1D,,1B,1C#,1D#,2F#,1C#,1D,1C#,1B,1C#,,1B,,1B,,1B,,1F#,1G#,1B,,1F#,1G#,1B,1C#,1D#,1B,1E,1D#,1E,2F#,1B,,1B,,1F#,1G#,1B,1E,1D#,1C#,1B,,,,1F#,1B,,1F#,1G#,1B,,1F#,1G#,1B,1B,1C#,1D#,1B,1F#,1G#,1F#,1B,,1B,1A#,1B,1F#,1G#,1B,1E,1D#,1E,2F#,1B,,1A#,,1B,,1F#,1G#,1B,,1F#,1G#,1B,1C#,1D#,1B,1E,1D#,1E,2F#,1B,,1B,,1F#,1G#,1B,1F#,1E,1D#,1C#,1B,,,,1F#,1B,,1F#,1G#,1B,,1F#,1G#,1B,1B,1C#,1D#,1B,1F#,1G#,1F#,1B,,1B,1A#,1B,1F#,1G#,1B,1E,1D#,1E,2F#,1B,,1A#,,1B,,1F#,1G#,1B,,1F#,1G#,1B,1C#,1D#,1B,1E,1D#,1E,2F#,1B,,1B,,1F#,1G#,1B,1F#,1E,1D#,1C#,1B,,,,1F#,1B,,1F#,1G#,1B,,1F#,1G#,1B,1B,1C#,1D#,1B,1F#,1G#,1F#,1B,,1B,1A#,1B,1F#,1G#,1B,1E,1D#,1E,2F#,1B,,1A#,,1B,,1F#,1G#,1B,,1F#,1G#,1B,1C#,1D#,1B,1E,1D#,1E,2F#,1B,,1B,,1F#,1G#,1B,1F#,1E,1D#,1C#,1B,,,,1F#,1B,,1F#,1G#,1B,,1F#,1G#,1B,1B,1C#,1D#,1B,1F#,1G#,1F#,1B,,1B,1A#,1B,1F#,1G#,1B,1E,1D#,1E,2F#,1B,,1A#,,1B,,1F#,1G#,1B,,1F#,1G#,1B,1C#,1D#,1B,1E,1D#,1E,2F#,1B,,1B,,1F#,1G#,1B,1F#,1E,1D#,1C#,1B,,,,1F#,1B,,1F#,1G#,1B,,1F#,1G#,1B,1B,1C#,1D#,1B,1F#,1G#,1F#,1B,,1B,1A#,1B,1F#,1G#,1B,1E,1D#,1E,2F#,1B,,1B,,";
private static final String[] CONSOLE_MOO = new String[]{" (__)", " (oo)", " /------\\/", " / | ||", " * /\\---/\\", " ~~ ~~", "....\"Have you mooed today?\"..."};
private static final String[] PLAYER_MOO = new String[]{" (__)", " (oo)", " /------\\/", " / | | |", " * /\\---/\\", " ~~ ~~", "....\"Have you mooed today?\"..."};
public Commandessentials() {
super("essentials");
}
private transient int taskid;
private final transient Map<Player, Block> noteBlocks = new HashMap<Player, Block>();
private transient TuneRunnable currentTune = null;
private final List<String> versionPlugins = Arrays.asList(
"Vault",
"LuckPerms",
"PermissionsEx",
"GroupManager"
private static final List<String> versionPlugins = Arrays.asList(
"Vault", // API
"Reserve", // API
"PlaceholderAPI", // API
"CMI", // potential for issues
"Towny", // past issues; admins should ensure latest
"ChestShop", // past issues; admins should ensure latest
"Citizens", // fires player events
"LuckPerms", // permissions (recommended)
"UltraPermissions",
"PermissionsEx", // permissions (unsupported)
"GroupManager", // permissions (unsupported)
"bPermissions" // permissions (unsupported)
);
private final List<String> officialPlugins = Arrays.asList(
"EssentialsAntiBuild",
"EssentialsChat",
"EssentialsGeoIP",
"EssentialsProtect",
"EssentialsSpawn",
"EssentialsXMPP"
private static final List<String> officialPlugins = Arrays.asList(
"EssentialsAntiBuild",
"EssentialsChat",
"EssentialsGeoIP",
"EssentialsProtect",
"EssentialsSpawn",
"EssentialsXMPP"
);
private final List<String> warnPlugins = Arrays.asList(
"PermissionsEx",
"GroupManager"
private static final List<String> warnPlugins = Arrays.asList(
"PermissionsEx",
"GroupManager",
"bPremissions"
);
@Override
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length == 0) {
run_disabled(server, sender, commandLabel, args);
} else if (args[0].equalsIgnoreCase("debug")) {
run_debug(server, sender, commandLabel, args);
} else if (args[0].equalsIgnoreCase("nya")) {
run_nya(server, sender, commandLabel, args);
} else if (args[0].equalsIgnoreCase("moo")) {
run_moo(server, sender, commandLabel, args);
} else if (args[0].equalsIgnoreCase("reset")) {
run_reset(server, sender, commandLabel, args);
} else if (args[0].equalsIgnoreCase("cleanup")) {
run_cleanup(server, sender, commandLabel, args);
} else if (args[0].equalsIgnoreCase("uuidconvert")) {
run_uuidconvert(server, sender, commandLabel, args);
} else if (args[0].equalsIgnoreCase("uuidtest")) {
run_uuidtest(server, sender, commandLabel, args);
} else if (args[0].equalsIgnoreCase("version")) {
run_version(server, sender, commandLabel, args);
} else {
run_reload(server, sender, commandLabel, args);
showUsage(sender);
}
switch(args[0]) {
// Info commands
case "debug":
case "verbose":
runDebug(server, sender, commandLabel, args);
break;
case "ver":
case "version":
runVersion(server, sender, commandLabel, args);
break;
case "cmd":
case "commands":
runCommands(server, sender, commandLabel, args);
break;
// Data commands
case "reload":
runReload(server, sender, commandLabel, args);
break;
case "reset":
runReset(server, sender, commandLabel, args);
break;
case "cleanup":
runCleanup(server, sender, commandLabel, args);
break;
case "uuidconvert":
runUUIDConvert(server, sender, commandLabel, args);
break;
case "uuidtest":
runUUIDTest(server, sender, commandLabel, args);
break;
// "#EasterEgg"
case "nya":
case "nyan":
runNya(server, sender, commandLabel, args);
break;
case "moo":
runMoo(server, sender, commandLabel, args);
break;
default:
showUsage(sender);
}
}
//If you do not supply an argument this command will list 'overridden' commands.
private void run_disabled(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
sender.sendMessage("/<command> <reload/debug>");
// Displays the command's usage.
private void showUsage(final CommandSource sender) throws Exception {
throw new NotEnoughArgumentsException("/<command> <reload/debug/commands>");
}
// Lists commands that are being handed over to other plugins.
private void runCommands(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
final StringBuilder disabledCommands = new StringBuilder();
for (Map.Entry<String, String> entry : ess.getAlternativeCommandsHandler().disabledCommands().entrySet()) {
if (disabledCommands.length() > 0) {
disabledCommands.append(", ");
disabledCommands.append("\n");
}
disabledCommands.append(entry.getKey()).append(" => ").append(entry.getValue());
}
if (disabledCommands.length() > 0) {
sender.sendMessage(tl("blockList"));
sender.sendMessage(disabledCommands.toString());
} else {
sender.sendMessage(tl("blockListEmpty"));
}
}
private void run_reset(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
// Resets the given player's user data.
private void runReset(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 2) {
throw new Exception("/<command> reset <player>");
}
@@ -104,108 +152,59 @@ public class Commandessentials extends EssentialsCommand {
sender.sendMessage("Reset Essentials userdata for player: " + user.getDisplayName());
}
private void run_debug(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
// Toggles debug mode.
private void runDebug(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
ess.getSettings().setDebug(!ess.getSettings().isDebug());
sender.sendMessage("Essentials " + ess.getDescription().getVersion() + " debug mode " + (ess.getSettings().isDebug() ? "enabled" : "disabled"));
}
private void run_reload(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
// Reloads all reloadable configs.
private void runReload(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
ess.reload();
sender.sendMessage(tl("essentialsReload", ess.getDescription().getVersion()));
}
private void run_nya(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
final Map<String, Float> noteMap = new HashMap<String, Float>();
noteMap.put("1F#", 0.5f);
noteMap.put("1G", 0.53f);
noteMap.put("1G#", 0.56f);
noteMap.put("1A", 0.6f);
noteMap.put("1A#", 0.63f);
noteMap.put("1B", 0.67f);
noteMap.put("1C", 0.7f);
noteMap.put("1C#", 0.76f);
noteMap.put("1D", 0.8f);
noteMap.put("1D#", 0.84f);
noteMap.put("1E", 0.9f);
noteMap.put("1F", 0.94f);
noteMap.put("2F#", 1.0f);
noteMap.put("2G", 1.06f);
noteMap.put("2G#", 1.12f);
noteMap.put("2A", 1.18f);
noteMap.put("2A#", 1.26f);
noteMap.put("2B", 1.34f);
noteMap.put("2C", 1.42f);
noteMap.put("2C#", 1.5f);
noteMap.put("2D", 1.6f);
noteMap.put("2D#", 1.68f);
noteMap.put("2E", 1.78f);
noteMap.put("2F", 1.88f);
final String tuneStr = "1D#,1E,2F#,,2A#,1E,1D#,1E,2F#,2B,2D#,2E,2D#,2A#,2B,,2F#,,1D#,1E,2F#,2B,2C#,2A#,2B,2C#,2E,2D#,2E,2C#,,2F#,,2G#,,1D,1D#,,1C#,1D,1C#,1B,,1B,,1C#,,1D,,1D,1C#,1B,1C#,1D#,2F#,2G#,1D#,2F#,1C#,1D#,1B,1C#,1B,1D#,,2F#,,2G#,1D#,2F#,1C#,1D#,1B,1D,1D#,1D,1C#,1B,1C#,1D,,1B,1C#,1D#,2F#,1C#,1D,1C#,1B,1C#,,1B,,1C#,,2F#,,2G#,,1D,1D#,,1C#,1D,1C#,1B,,1B,,1C#,,1D,,1D,1C#,1B,1C#,1D#,2F#,2G#,1D#,2F#,1C#,1D#,1B,1C#,1B,1D#,,2F#,,2G#,1D#,2F#,1C#,1D#,1B,1D,1D#,1D,1C#,1B,1C#,1D,,1B,1C#,1D#,2F#,1C#,1D,1C#,1B,1C#,,1B,,1B,,1B,,1F#,1G#,1B,,1F#,1G#,1B,1C#,1D#,1B,1E,1D#,1E,2F#,1B,,1B,,1F#,1G#,1B,1E,1D#,1C#,1B,,,,1F#,1B,,1F#,1G#,1B,,1F#,1G#,1B,1B,1C#,1D#,1B,1F#,1G#,1F#,1B,,1B,1A#,1B,1F#,1G#,1B,1E,1D#,1E,2F#,1B,,1A#,,1B,,1F#,1G#,1B,,1F#,1G#,1B,1C#,1D#,1B,1E,1D#,1E,2F#,1B,,1B,,1F#,1G#,1B,1F#,1E,1D#,1C#,1B,,,,1F#,1B,,1F#,1G#,1B,,1F#,1G#,1B,1B,1C#,1D#,1B,1F#,1G#,1F#,1B,,1B,1A#,1B,1F#,1G#,1B,1E,1D#,1E,2F#,1B,,1A#,,1B,,1F#,1G#,1B,,1F#,1G#,1B,1C#,1D#,1B,1E,1D#,1E,2F#,1B,,1B,,1F#,1G#,1B,1F#,1E,1D#,1C#,1B,,,,1F#,1B,,1F#,1G#,1B,,1F#,1G#,1B,1B,1C#,1D#,1B,1F#,1G#,1F#,1B,,1B,1A#,1B,1F#,1G#,1B,1E,1D#,1E,2F#,1B,,1A#,,1B,,1F#,1G#,1B,,1F#,1G#,1B,1C#,1D#,1B,1E,1D#,1E,2F#,1B,,1B,,1F#,1G#,1B,1F#,1E,1D#,1C#,1B,,,,1F#,1B,,1F#,1G#,1B,,1F#,1G#,1B,1B,1C#,1D#,1B,1F#,1G#,1F#,1B,,1B,1A#,1B,1F#,1G#,1B,1E,1D#,1E,2F#,1B,,1A#,,1B,,1F#,1G#,1B,,1F#,1G#,1B,1C#,1D#,1B,1E,1D#,1E,2F#,1B,,1B,,1F#,1G#,1B,1F#,1E,1D#,1C#,1B,,,,1F#,1B,,1F#,1G#,1B,,1F#,1G#,1B,1B,1C#,1D#,1B,1F#,1G#,1F#,1B,,1B,1A#,1B,1F#,1G#,1B,1E,1D#,1E,2F#,1B,,1B,,";
final String[] tune = tuneStr.split(",");
taskid = ess.scheduleSyncRepeatingTask(new Runnable() {
int i = 0;
@Override
public void run() {
final String note = tune[i];
i++;
if (i >= tune.length) {
Commandessentials.this.stopTune();
}
if (note == null || note.isEmpty()) {
return;
}
for (Player onlinePlayer : ess.getOnlinePlayers()) {
onlinePlayer.playSound(onlinePlayer.getLocation(), NOTE_HARP, 1, noteMap.get(note));
}
}
}, 20, 2);
}
private void stopTune() {
ess.getScheduler().cancelTask(taskid);
for (Block block : noteBlocks.values()) {
if (block.getType() == Material.NOTE_BLOCK) {
block.setType(Material.AIR);
}
// Pop tarts.
private void runNya(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (currentTune != null) {
currentTune.cancel();
}
noteBlocks.clear();
currentTune = new TuneRunnable(NYAN_TUNE, NOTE_HARP, ess::getOnlinePlayers);
currentTune.runTaskTimer(ess, 20, 2);
}
private final String[] consoleMoo = new String[]{" (__)", " (oo)", " /------\\/", " / | ||", " * /\\---/\\", " ~~ ~~", "....\"Have you mooed today?\"..."};
private final String[] playerMoo = new String[]{" (__)", " (oo)", " /------\\/", " / | | |", " * /\\---/\\", " ~~ ~~", "....\"Have you mooed today?\"..."};
private void run_moo(final Server server, final CommandSource sender, final String command, final String args[]) {
Sound moo = EnumUtil.valueOf(Sound.class, "COW_IDLE", "ENTITY_COW_MILK");
// Cow farts.
private void runMoo(final Server server, final CommandSource sender, final String command, final String args[]) {
if (args.length == 2 && args[1].equals("moo")) {
for (String s : consoleMoo) {
for (String s : CONSOLE_MOO) {
logger.info(s);
}
for (Player player : ess.getOnlinePlayers()) {
player.sendMessage(playerMoo);
player.playSound(player.getLocation(), moo, 1, 1.0f);
player.sendMessage(PLAYER_MOO);
player.playSound(player.getLocation(), MOO_SOUND, 1, 1.0f);
}
} else {
if (sender.isPlayer()) {
sender.getSender().sendMessage(playerMoo);
sender.getSender().sendMessage(PLAYER_MOO);
final Player player = sender.getPlayer();
player.playSound(player.getLocation(), moo, 1, 1.0f);
player.playSound(player.getLocation(), MOO_SOUND, 1, 1.0f);
} else {
sender.getSender().sendMessage(consoleMoo);
sender.getSender().sendMessage(CONSOLE_MOO);
}
}
}
private void run_cleanup(final Server server, final CommandSource sender, final String command, final String args[]) throws Exception {
// Cleans up inactive users.
private void runCleanup(final Server server, final CommandSource sender, final String command, final String args[]) throws Exception {
if (args.length < 2 || !NumberUtil.isInt(args[1])) {
sender.sendMessage("This sub-command will delete users who havent logged in in the last <days> days.");
sender.sendMessage("Optional parameters define the minium amount required to prevent deletion.");
sender.sendMessage("Unless you define larger default values, this command wil ignore people who have more than 0 money/homes.");
sender.sendMessage("This sub-command will delete users who haven't logged in in the last <days> days.");
sender.sendMessage("Optional parameters define the minimum amount required to prevent deletion.");
sender.sendMessage("Unless you define larger default values, this command will ignore people who have more than 0 money/homes.");
throw new Exception("/<command> cleanup <days> [money] [homes]");
}
sender.sendMessage(tl("cleaning"));
final long daysArg = Long.parseLong(args[1]);
@@ -213,59 +212,58 @@ public class Commandessentials extends EssentialsCommand {
final int homesArg = args.length >= 4 && NumberUtil.isInt(args[3]) ? Integer.parseInt(args[3]) : 0;
final UserMap userMap = ess.getUserMap();
ess.runTaskAsynchronously(new Runnable() {
@Override
public void run() {
Long currTime = System.currentTimeMillis();
for (UUID u : userMap.getAllUniqueUsers()) {
final User user = ess.getUserMap().getUser(u);
if (user == null) {
continue;
}
long lastLog = user.getLastLogout();
if (lastLog == 0) {
lastLog = user.getLastLogin();
}
if (lastLog == 0) {
user.setLastLogin(currTime);
}
if (user.isNPC()) {
continue;
}
long timeDiff = currTime - lastLog;
long milliDays = daysArg * 24L * 60L * 60L * 1000L;
int homeCount = user.getHomes().size();
double moneyCount = user.getMoney().doubleValue();
if ((lastLog == 0) || (timeDiff < milliDays) || (homeCount > homesArg) || (moneyCount > moneyArg)) {
continue;
}
if (ess.getSettings().isDebug()) {
ess.getLogger().info("Deleting user: " + user.getName() + " Money: " + moneyCount + " Homes: " + homeCount + " Last seen: " + DateUtil.formatDateDiff(lastLog));
}
user.reset();
ess.runTaskAsynchronously(() -> {
Long currTime = System.currentTimeMillis();
for (UUID u : userMap.getAllUniqueUsers()) {
final User user = ess.getUserMap().getUser(u);
if (user == null) {
continue;
}
sender.sendMessage(tl("cleaned"));
long lastLog = user.getLastLogout();
if (lastLog == 0) {
lastLog = user.getLastLogin();
}
if (lastLog == 0) {
user.setLastLogin(currTime);
}
if (user.isNPC()) {
continue;
}
long timeDiff = currTime - lastLog;
long milliDays = daysArg * 24L * 60L * 60L * 1000L;
int homeCount = user.getHomes().size();
double moneyCount = user.getMoney().doubleValue();
if ((lastLog == 0) || (timeDiff < milliDays) || (homeCount > homesArg) || (moneyCount > moneyArg)) {
continue;
}
if (ess.getSettings().isDebug()) {
ess.getLogger().info("Deleting user: " + user.getName() + " Money: " + moneyCount + " Homes: " + homeCount + " Last seen: " + DateUtil.formatDateDiff(lastLog));
}
user.reset();
}
sender.sendMessage(tl("cleaned"));
});
}
private void run_uuidconvert(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
sender.sendMessage("Starting Essentials UUID userdata conversion, this may lag the server.");
// Forces a rerun of userdata UUID conversion.
private void runUUIDConvert(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
sender.sendMessage("Starting Essentials UUID userdata conversion; this may lag the server.");
Boolean ignoreUFCache = (args.length > 2 && args[1].toLowerCase(Locale.ENGLISH).contains("ignore"));
EssentialsUpgrade.uuidFileConvert(ess, ignoreUFCache);
sender.sendMessage("UUID conversion complete, check your server log for more information.");
sender.sendMessage("UUID conversion complete. Check your server log for more information.");
}
private void run_uuidtest(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
// Looks up various UUIDs for a user.
private void runUUIDTest(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 2) {
throw new Exception("/<command> uuidtest <name>");
}
@@ -302,7 +300,8 @@ public class Commandessentials extends EssentialsCommand {
sender.sendMessage("Offline Mode UUID: " + offlineuuid.toString());
}
private void run_version(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
// Displays versions of EssentialsX and related plugins.
private void runVersion(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.version")) return;
boolean isMismatched = false;
@@ -369,47 +368,101 @@ public class Commandessentials extends EssentialsCommand {
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
if (args.length == 1) {
List<String> options = Lists.newArrayList();
options.add("reload");
options.add("debug");
//options.add("nya");
//options.add("moo");
options.add("commands");
options.add("version");
options.add("reload");
options.add("reset");
options.add("cleanup");
//options.add("uuidconvert");
//options.add("uuidtest");
options.add("version");
//options.add("nya");
//options.add("moo");
return options;
} else if (args[0].equalsIgnoreCase("debug")) {
// No args
} else if (args[0].equalsIgnoreCase("nya")) {
// No args
} else if (args[0].equalsIgnoreCase("moo")) {
if (args.length == 2) {
return Lists.newArrayList("moo");
}
} else if (args[0].equalsIgnoreCase("reset")) {
if (args.length == 2) {
return getPlayers(server, sender);
}
} else if (args[0].equalsIgnoreCase("cleanup")) {
if (args.length == 2) {
return COMMON_DURATIONS;
} else if (args.length == 3 || args.length == 4) {
return Lists.newArrayList("-1", "0");
}
} else if (args[0].equalsIgnoreCase("uuidconvert")) {
if (args.length == 2) {
return Lists.newArrayList("ignoreUFCache");
}
} else if (args[0].equalsIgnoreCase("uuidtest")) {
if (args.length == 2) {
return getPlayers(server, sender);
}
} else if (args[0].equalsIgnoreCase("version")) {
// No args
} else {
// No args
}
switch (args[0]) {
case "moo":
if (args.length == 2) {
return Lists.newArrayList("moo");
}
break;
case "reset":
case "uuidtest":
if (args.length == 2) {
return getPlayers(server, sender);
}
break;
case "cleanup":
if (args.length == 2) {
return COMMON_DURATIONS;
} else if (args.length == 3 || args.length == 4) {
return Lists.newArrayList("-1", "0");
}
break;
case "uuidconvert":
if (args.length == 2) {
return Lists.newArrayList("ignoreUFCache");
}
break;
}
return Collections.emptyList();
}
private static class TuneRunnable extends BukkitRunnable {
private static final Map<String, Float> noteMap = ImmutableMap.<String, Float>builder()
.put("1F#", 0.5f)
.put("1G", 0.53f)
.put("1G#", 0.56f)
.put("1A", 0.6f)
.put("1A#", 0.63f)
.put("1B", 0.67f)
.put("1C", 0.7f)
.put("1C#", 0.76f)
.put("1D", 0.8f)
.put("1D#", 0.84f)
.put("1E", 0.9f)
.put("1F", 0.94f)
.put("2F#", 1.0f)
.put("2G", 1.06f)
.put("2G#", 1.12f)
.put("2A", 1.18f)
.put("2A#", 1.26f)
.put("2B", 1.34f)
.put("2C", 1.42f)
.put("2C#", 1.5f)
.put("2D", 1.6f)
.put("2D#", 1.68f)
.put("2E", 1.78f)
.put("2F", 1.88f)
.build();
private final String[] tune;
private final Sound sound;
private final Supplier<Collection<Player>> players;
private int i = 0;
TuneRunnable(final String tuneStr, final Sound sound, final Supplier<Collection<Player>> players) {
this.tune = tuneStr.split(",");
this.sound = sound;
this.players = players;
}
@Override
public void run() {
final String note = tune[i];
i++;
if (i >= tune.length) {
cancel();
}
if (note == null || note.isEmpty()) {
return;
}
for (Player onlinePlayer : players.get()) {
onlinePlayer.playSound(onlinePlayer.getLocation(), sound, 1, noteMap.get(note));
}
}
}
}
@@ -36,6 +36,18 @@ public class Commandexp extends EssentialsCommand {
} else {
setExp(user.getSource(), user, args[1], true);
}
} else if (args.length > 1 && args[0].equalsIgnoreCase("take") && user.isAuthorized("essentials.exp.take")) {
if (args.length == 3 && user.isAuthorized("essentials.exp.take.others")) {
expMatch(server, user.getSource(), args[1], "-" + args[2], true);
} else {
setExp(user.getSource(), user, "-" + args[1], true);
}
} else if (args.length < 3 && args[0].equalsIgnoreCase("reset") && user.isAuthorized("essentials.exp.reset")) {
if (args.length == 2 && user.isAuthorized("essentials.exp.reset.others")) {
expMatch(server, user.getSource(), args[1], "0", false);
} else {
setExp(user.getSource(), user, "0", false);
}
} else if (args[0].equalsIgnoreCase("show")) {
if (args.length >= 2 && user.isAuthorized("essentials.exp.others")) {
String match = args[1].trim();
@@ -159,6 +171,12 @@ public class Commandexp extends EssentialsCommand {
if (user.isAuthorized("essentials.exp.give")) {
options.add("give");
}
if (user.isAuthorized("essentials.exp.take")) {
options.add("take");
}
if (user.isAuthorized("essentials.exp.reset")) {
options.add("reset");
}
return options;
} else if (args.length == 2) {
if ((args[0].equalsIgnoreCase("set") && user.isAuthorized("essentials.exp.set")) || (args[0].equalsIgnoreCase("give") && user.isAuthorized("essentials.exp.give"))) {
@@ -184,7 +202,7 @@ public class Commandexp extends EssentialsCommand {
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
if (args.length == 1) {
// TODO: This seems somewhat buggy, both setting and showing - right now, ignoring that
return Lists.newArrayList("set", "give", "show");
return Lists.newArrayList("set", "give", "show", "take", "reset");
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("set") || args[0].equalsIgnoreCase("give")) {
String levellessArg = args[1].toLowerCase(Locale.ENGLISH).replace("l", "");
@@ -1,6 +1,9 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FloatUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.bukkit.Server;
import org.bukkit.entity.*;
@@ -8,44 +11,86 @@ import org.bukkit.util.Vector;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.earth2me.essentials.I18n.tl;
public class Commandfireball extends EssentialsCommand {
private static final Map<String, Class<? extends Projectile>> types;
static {
ImmutableMap.Builder<String, Class<? extends Projectile>> builder = ImmutableMap.<String, Class<? extends Projectile>>builder()
.put("fireball", Fireball.class)
.put("small", SmallFireball.class)
.put("large", LargeFireball.class)
.put("arrow", Arrow.class)
.put("skull", WitherSkull.class)
.put("egg", Egg.class)
.put("snowball", Snowball.class)
.put("expbottle", ThrownExpBottle.class)
.put("splashpotion", SplashPotion.class)
.put("lingeringpotion", LingeringPotion.class);
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01)) {
builder.put("dragon", DragonFireball.class);
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_13_0_R01)) {
builder.put("trident", Trident.class);
}
types = builder.build();
}
public Commandfireball() {
super("fireball");
}
@Override
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
Class<? extends Entity> type = Fireball.class;
Projectile projectile;
int speed = 2;
if (args.length > 0) {
if (args[0].equalsIgnoreCase("small")) {
type = SmallFireball.class;
} else if (args[0].equalsIgnoreCase("arrow")) {
type = Arrow.class;
} else if (args[0].equalsIgnoreCase("skull")) {
type = WitherSkull.class;
} else if (args[0].equalsIgnoreCase("egg")) {
type = Egg.class;
} else if (args[0].equalsIgnoreCase("snowball")) {
type = Snowball.class;
} else if (args[0].equalsIgnoreCase("expbottle")) {
type = ThrownExpBottle.class;
} else if (args[0].equalsIgnoreCase("large")) {
type = LargeFireball.class;
String type = "fireball";
double speed = 2;
boolean ride = false;
if (args.length > 0 && types.containsKey(args[0])) {
type = args[0];
}
if (args.length > 1) {
try {
speed = FloatUtil.parseDouble(args[1]);
speed = Double.max(0, Double.min(speed, ess.getSettings().getMaxProjectileSpeed()));
} catch (Exception ignored) {
}
}
if (args.length > 2 && args[2].equalsIgnoreCase("ride") && user.isAuthorized("essentials.fireball.ride")) {
ride = true;
}
if (!user.isAuthorized("essentials.fireball." + type)) {
throw new Exception(tl("noPerm", "essentials.fireball." + type));
}
final Vector direction = user.getBase().getEyeLocation().getDirection().multiply(speed);
projectile = (Projectile) user.getWorld().spawn(user.getBase().getEyeLocation().add(direction.getX(), direction.getY(), direction.getZ()), type);
Projectile projectile = user.getWorld().spawn(user.getBase().getEyeLocation().add(direction.getX(), direction.getY(), direction.getZ()), types.get(type));
projectile.setShooter(user.getBase());
projectile.setVelocity(direction);
if (ride) {
projectile.addPassenger(user.getBase());
}
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
if (args.length == 1) {
return Lists.newArrayList("small", "arrow", "skull", "egg", "snowball", "expbottle", "large");
return types.keySet().stream()
.filter(type -> user.isAuthorized("essentials.fireball." + type))
.collect(Collectors.toList());
} else if (args.length == 2) {
return Lists.newArrayList("1", "2", "3", "4", "5");
} else {
return Collections.emptyList();
}
@@ -35,6 +35,10 @@ public class Commandhat extends EssentialsCommand {
} else {
final ItemStack hand = user.getItemInHand();
if (hand != null && hand.getType() != Material.AIR) {
if (user.isAuthorized("essentials.hat.prevent-type." + hand.getType().name().toLowerCase())) {
user.sendMessage(tl("hatFail"));
return;
}
if (hand.getType().getMaxDurability() == 0) {
final PlayerInventory inv = user.getBase().getInventory();
final ItemStack head = inv.getHelmet();
@@ -53,7 +53,11 @@ public class Commandhome extends EssentialsCommand {
Location bed = player.getBase().getBedSpawnLocation();
final List<String> homes = player.getHomes();
if (homes.isEmpty() && player.equals(user)) {
user.getTeleport().respawn(charge, TeleportCause.COMMAND);
if (ess.getSettings().isSpawnIfNoHome()) {
user.getTeleport().respawn(charge, TeleportCause.COMMAND);
} else {
throw new Exception(tl("noHomeSetPlayer"));
}
} else if (homes.isEmpty()) {
throw new Exception(tl("noHomeSetPlayer"));
} else if (homes.size() == 1 && player.equals(user)) {
@@ -95,6 +99,7 @@ public class Commandhome extends EssentialsCommand {
throw new Exception(tl("noPerm", "essentials.worlds." + loc.getWorld().getName()));
}
user.getTeleport().teleport(loc, charge, TeleportCause.COMMAND);
user.sendMessage(tl("teleportHome", home));
}
@Override
@@ -33,10 +33,16 @@ public class Commanditemdb extends EssentialsCommand {
itemStack = ess.getItemDb().get(args[0]);
}
sender.sendMessage(tl("itemType", itemStack.getType().toString()));
String itemId = "none";
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01)) {
final String itemId = itemStack.getType().getId() + ":" + itemStack.getDurability();
itemId = itemStack.getType().getId() + ":" + itemStack.getDurability();
}
sender.sendMessage(tl("itemType", itemStack.getType().toString(), itemId));
// Don't send IDs twice
if (!tl("itemType").contains("{1}") && !itemId.equals("none")) {
sender.sendMessage(tl("itemId", itemId));
}
@@ -0,0 +1,40 @@
package com.earth2me.essentials.commands;
import static com.earth2me.essentials.I18n.tl;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.I18n;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Locale;
public class Commanditemname extends EssentialsCommand {
public Commanditemname() {
super("itemname");
}
@Override
protected void run(Server server, User user, String commandLabel, String[] args) throws Exception {
ItemStack item = user.getBase().getItemInHand();
if (item.getType().name().contains("AIR")) {
user.sendMessage(tl("itemnameInvalidItem", item.getType().toString().toLowerCase(Locale.ENGLISH).replace('_', ' ')));
return;
}
String name = FormatUtil.formatString(user, "essentials.itemname", getFinalArg(args, 0)).trim();
if (name.isEmpty()) name = null;
ItemMeta im = item.getItemMeta();
im.setDisplayName(name);
item.setItemMeta(im);
user.sendMessage(name == null ? tl("itemnameClear") : tl("itemnameSuccess", name));
}
}
@@ -4,7 +4,11 @@ import com.earth2me.essentials.Mob;
import com.earth2me.essentials.User;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Cat;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Ocelot;
import org.bukkit.entity.Tameable;
import java.util.Random;
@@ -18,16 +22,7 @@ public class Commandkittycannon extends EssentialsCommand {
@Override
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final Mob cat = Mob.OCELOT;
final Ocelot ocelot = (Ocelot) cat.spawn(user.getWorld(), server, user.getBase().getEyeLocation());
if (ocelot == null) {
return;
}
final int i = random.nextInt(Ocelot.Type.values().length);
ocelot.setCatType(Ocelot.Type.values()[i]);
ocelot.setTamed(true);
ocelot.setBaby();
ocelot.setVelocity(user.getBase().getEyeLocation().getDirection().multiply(2));
final Entity ocelot = Mob.CAT.getType() == null ? spawnOcelot(user.getWorld(), server, user) : spawnCat(user.getWorld(), server, user);
class KittyCannonExplodeTask implements Runnable {
@Override
@@ -40,4 +35,32 @@ public class Commandkittycannon extends EssentialsCommand {
ess.scheduleSyncDelayedTask(new KittyCannonExplodeTask(), 20);
}
private static Ocelot spawnOcelot(World world, Server server, User user) throws Mob.MobException {
final Ocelot ocelot = (Ocelot) Mob.OCELOT.spawn(user.getWorld(), server, user.getBase().getEyeLocation());
if (ocelot == null) {
return null;
}
final int i = random.nextInt(Ocelot.Type.values().length);
ocelot.setCatType(Ocelot.Type.values()[i]);
((Tameable) ocelot).setTamed(true);
ocelot.setBaby();
ocelot.setVelocity(user.getBase().getEyeLocation().getDirection().multiply(2));
return ocelot;
}
private static Entity spawnCat(World world, Server server, User user) throws Mob.MobException {
final Cat cat = (Cat) Mob.CAT.spawn(user.getWorld(), server, user.getBase().getEyeLocation());
if (cat == null) {
return null;
}
final int i = random.nextInt(Cat.Type.values().length);
cat.setCatType(Cat.Type.values()[i]);
cat.setTamed(true);
cat.setBaby();
cat.setVelocity(user.getBase().getEyeLocation().getDirection().multiply(2));
return cat;
}
}
@@ -48,7 +48,7 @@ public class Commandmail extends EssentialsCommand {
}
if (user.isMuted()) {
throw new Exception(tl("voiceSilenced"));
throw new Exception(user.hasMuteReason() ? tl("voiceSilencedReason", user.getMuteReason()) : tl("voiceSilenced"));
}
User u = getPlayer(server, args[1], true, true);
@@ -87,6 +87,11 @@ public class Commandmail extends EssentialsCommand {
return;
}
if (args.length >= 1 && "clear".equalsIgnoreCase(args[0])) {
if (user.getMails() == null || user.getMails().isEmpty()) {
user.sendMessage(tl("noMail"));
throw new NoChargeException();
}
user.setMails(null);
user.sendMessage(tl("mailCleared"));
return;
@@ -105,11 +110,11 @@ public class Commandmail extends EssentialsCommand {
if (u == null) {
throw new Exception(tl("playerNeverOnServer", args[1]));
}
u.addMail(tl("mailFormat", "Server", getFinalArg(args, 2)));
u.addMail(tl("mailFormat", "Server", FormatUtil.replaceFormat(getFinalArg(args, 2))));
sender.sendMessage(tl("mailSent"));
return;
} else if (args.length >= 2 && "sendall".equalsIgnoreCase(args[0])) {
ess.runTaskAsynchronously(new SendAll(tl("mailFormat", "Server", getFinalArg(args, 1))));
ess.runTaskAsynchronously(new SendAll(tl("mailFormat", "Server", FormatUtil.replaceFormat(getFinalArg(args, 1)))));
sender.sendMessage(tl("mailSent"));
return;
} else if (args.length >= 2) {
@@ -118,7 +123,7 @@ public class Commandmail extends EssentialsCommand {
if (u == null) {
throw new Exception(tl("playerNeverOnServer", args[0]));
}
u.addMail(tl("mailFormat", "Server", getFinalArg(args, 1)));
u.addMail(tl("mailFormat", "Server", FormatUtil.replaceFormat(getFinalArg(args, 1))));
sender.sendMessage(tl("mailSent"));
return;
}
@@ -24,7 +24,7 @@ public class Commandme extends EssentialsCommand {
@Override
public void run(Server server, User user, String commandLabel, String[] args) throws Exception {
if (user.isMuted()) {
throw new Exception(tl("voiceSilenced"));
throw new Exception(user.hasMuteReason() ? tl("voiceSilencedReason", user.getMuteReason()) : tl("voiceSilenced"));
}
if (args.length < 1) {
@@ -29,7 +29,7 @@ public class Commandmsg extends EssentialsLoopCommand {
if (sender.isPlayer()) {
User user = ess.getUser(sender.getPlayer());
if (user.isMuted()) {
throw new Exception(tl("voiceSilenced"));
throw new Exception(user.hasMuteReason() ? tl("voiceSilencedReason", user.getMuteReason()) : tl("voiceSilenced"));
}
message = FormatUtil.formatMessage(user, "essentials.msg", message);
canWildcard = user.isAuthorized("essentials.msg.multiple");
@@ -41,7 +41,7 @@ public class Commandmute extends EssentialsCommand {
}
}
final boolean willMute = (args.length > 1) ? true : !user.getMuted();
final boolean willMute = (args.length > 1) || !user.getMuted();
final User controller = sender.isPlayer() ? ess.getUser(sender.getPlayer()) : null;
final MuteStatusChangeEvent event = new MuteStatusChangeEvent(user, controller, willMute);
ess.getServer().getPluginManager().callEvent(event);
@@ -50,11 +50,22 @@ public class Commandmute extends EssentialsCommand {
long muteTimestamp = 0;
if (args.length > 1) {
final String time = getFinalArg(args, 1);
muteTimestamp = DateUtil.parseDateDiff(time, true);
final String time = args[1];
String muteReason;
try {
muteTimestamp = DateUtil.parseDateDiff(time, true);
muteReason = getFinalArg(args, 2);
} catch (Exception e) {
muteReason = getFinalArg(args, 1);
}
user.setMuteReason(muteReason.isEmpty() ? null : muteReason);
user.setMuted(true);
} else {
user.setMuted(!user.getMuted());
if (!user.getMuted()) {
user.setMuteReason(null);
}
}
user.setMuteTimeout(muteTimestamp);
final boolean muted = user.getMuted();
@@ -66,17 +77,35 @@ public class Commandmute extends EssentialsCommand {
if (muted) {
if (muteTimestamp > 0) {
sender.sendMessage(tl("mutedPlayerFor", user.getDisplayName(), muteTime));
user.sendMessage(tl("playerMutedFor", muteTime));
if (!user.hasMuteReason()) {
sender.sendMessage(tl("mutedPlayerFor", user.getDisplayName(), muteTime));
user.sendMessage(tl("playerMutedFor", muteTime));
} else {
sender.sendMessage(tl("mutedPlayerForReason", user.getDisplayName(), muteTime, user.getMuteReason()));
user.sendMessage(tl("playerMutedForReason", muteTime, user.getMuteReason()));
}
} else {
sender.sendMessage(tl("mutedPlayer", user.getDisplayName()));
user.sendMessage(tl("playerMuted"));
if (!user.hasMuteReason()) {
sender.sendMessage(tl("mutedPlayer", user.getDisplayName()));
user.sendMessage(tl("playerMuted"));
} else {
sender.sendMessage(tl("mutedPlayerReason", user.getDisplayName(), user.getMuteReason()));
user.sendMessage(tl("playerMutedReason", user.getMuteReason()));
}
}
final String message;
if (muteTimestamp > 0) {
message = tl("muteNotifyFor", sender.getSender().getName(), user.getName(), muteTime);
if (!user.hasMuteReason()) {
message = tl("muteNotifyFor", sender.getSender().getName(), user.getName(), muteTime);
} else {
message = tl("muteNotifyForReason", sender.getSender().getName(), user.getName(), muteTime, user.getMuteReason());
}
} else {
message = tl("muteNotify", sender.getSender().getName(), user.getName());
if (!user.hasMuteReason()) {
message = tl("muteNotify", sender.getSender().getName(), user.getName());
} else {
message = tl("muteNotifyReason", sender.getSender().getName(), user.getName(), user.getMuteReason());
}
}
server.getLogger().log(Level.INFO, message);
ess.broadcastMessage("essentials.mute.notify", message);
@@ -9,6 +9,8 @@ import org.bukkit.World;
import java.util.Collections;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import static com.earth2me.essentials.I18n.tl;
@@ -83,6 +85,8 @@ public class Commandnear extends EssentialsCommand {
final long radiusSquared = radius * radius;
boolean showHidden = user.canInteractVanished();
Queue<User> nearbyPlayers = new PriorityQueue<>((o1, o2) -> (int) (o1.getLocation().distanceSquared(loc) - o2.getLocation().distanceSquared(loc)));
for (User player : ess.getOnlineUsers()) {
if (!player.equals(user) && (!player.isHidden(user.getBase()) || showHidden || user.getBase().canSee(player.getBase()))) {
final Location playerLoc = player.getLocation();
@@ -92,13 +96,19 @@ public class Commandnear extends EssentialsCommand {
final long delta = (long) playerLoc.distanceSquared(loc);
if (delta < radiusSquared) {
if (output.length() > 0) {
output.append(", ");
}
output.append(player.getDisplayName()).append("§f(§4").append((long) Math.sqrt(delta)).append("m§f)");
nearbyPlayers.offer(player);
}
}
}
while (!nearbyPlayers.isEmpty()) {
if (output.length() > 0) {
output.append(", ");
}
User nearbyPlayer = nearbyPlayers.poll();
output.append(nearbyPlayer.getDisplayName()).append("§f(§4").append((long) nearbyPlayer.getLocation().distance(loc)).append("m§f)");
}
return output.length() > 1 ? output.toString() : tl("none");
}
@@ -83,10 +83,17 @@ public class Commandnick extends EssentialsLoopCommand {
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())) {
throw new Exception(tl("nickNamesOnlyColorChanges"));
} else if (user != null && !user.isAuthorized("essentials.nick.blacklist.bypass") && isNickBanned(newNick)) {
throw new Exception(tl("nickNameBlacklist", nick));
}
return newNick;
}
private boolean isNickBanned(String newNick) {
return ess.getSettings().getNickBlacklist().stream()
.anyMatch(entry -> entry.test(newNick));
}
private int getNickLength(final String nick) {
return ess.getSettings().ignoreColorsInMaxLength() ? ChatColor.stripColor(nick).length() : nick.length();
}
@@ -9,6 +9,7 @@ import com.earth2me.essentials.utils.StringUtil;
import com.google.common.collect.Lists;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.events.UserBalanceUpdateEvent;
import org.bukkit.Server;
import java.math.BigDecimal;
@@ -73,7 +74,7 @@ public class Commandpay extends EssentialsLoopCommand {
user.getConfirmingPayments().put(player, amount);
return;
}
user.payUser(player, amount);
user.payUser(player, amount, UserBalanceUpdateEvent.Cause.COMMAND_PAY);
user.getConfirmingPayments().remove(player);
Trade.log("Command", "Pay", "Player", user.getName(), new Trade(amount, ess), player.getName(), new Trade(amount, ess), user.getLocation(), ess);
} catch (MaxMoneyException ex) {
@@ -28,7 +28,7 @@ public class Commandr extends EssentialsCommand {
User user = ess.getUser(sender.getPlayer());
if (user.isMuted()) {
throw new Exception(tl("voiceSilenced"));
throw new Exception(user.hasMuteReason() ? tl("voiceSilencedReason", user.getMuteReason()) : tl("voiceSilenced"));
}
message = FormatUtil.formatMessage(user, "essentials.msg", message);
@@ -0,0 +1,37 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import org.bukkit.Server;
import static com.earth2me.essentials.I18n.tl;
public class Commandrtoggle extends EssentialsToggleCommand {
public Commandrtoggle() {
super("rtoggle", "essentials.rtoggle.others");
}
@Override
public void run(Server server, User user, String commandLabel, String[] args) throws Exception {
handleToggleWithArgs(server, user, args);
}
@Override
public void run(Server server, CommandSource sender, String commandLabel, String[] args) throws Exception {
toggleOtherPlayers(server, sender, args);
}
@Override
void togglePlayer(CommandSource sender, User user, Boolean enabled) throws NotEnoughArgumentsException {
if (enabled == null) {
enabled = !user.isLastMessageReplyRecipient();
}
user.setLastMessageReplyRecipient(enabled);
user.sendMessage(!enabled ? tl("replyLastRecipientDisabled") : tl("replyLastRecipientEnabled"));
if (!sender.isPlayer() || !user.getBase().equals(sender.getPlayer())) {
sender.sendMessage(!enabled ? tl("replyLastRecipientDisabledFor", user.getDisplayName()) : tl("replyLastRecipientEnabledFor", user.getDisplayName()));
}
}
}
@@ -117,7 +117,12 @@ public class Commandseen extends EssentialsCommand {
sender.sendMessage(tl("whoisJail", (user.getJailTimeout() > 0 ? DateUtil.formatDateDiff(user.getJailTimeout()) : tl("true"))));
}
if (user.isMuted()) {
sender.sendMessage(tl("whoisMuted", (user.getMuteTimeout() > 0 ? DateUtil.formatDateDiff(user.getMuteTimeout()) : tl("true"))));
long muteTimeout = user.getMuteTimeout();
if (!user.hasMuteReason()) {
sender.sendMessage(tl("whoisMuted", (muteTimeout > 0 ? DateUtil.formatDateDiff(muteTimeout) : tl("true"))));
} else {
sender.sendMessage(tl("whoisMutedReason", (muteTimeout > 0 ? DateUtil.formatDateDiff(muteTimeout) : tl("true")), user.getMuteReason()));
}
}
final String location = user.getGeoLocation();
if (location != null && (!(sender.isPlayer()) || ess.getUser(sender.getPlayer()).isAuthorized("essentials.geoip.show"))) {
@@ -159,6 +164,15 @@ public class Commandseen extends EssentialsCommand {
}
}
if (user.isMuted()) {
long muteTimeout = user.getMuteTimeout();
if (!user.hasMuteReason()) {
sender.sendMessage(tl("whoisMuted", (muteTimeout > 0 ? DateUtil.formatDateDiff(muteTimeout) : tl("true"))));
} else {
sender.sendMessage(tl("whoisMutedReason", (muteTimeout > 0 ? DateUtil.formatDateDiff(muteTimeout) : tl("true")), user.getMuteReason()));
}
}
final String location = user.getGeoLocation();
if (location != null && (!(sender.isPlayer()) || ess.getUser(sender.getPlayer()).isAuthorized("essentials.geoip.show"))) {
sender.sendMessage(tl("whoisGeoLocation", location));
@@ -4,6 +4,7 @@ import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.NumberUtil;
import com.google.common.collect.Lists;
import net.ess3.api.events.UserBalanceUpdateEvent;
import org.bukkit.Server;
import org.bukkit.inventory.ItemStack;
@@ -94,7 +95,7 @@ public class Commandsell extends EssentialsCommand {
user.getBase().getInventory().removeItem(ris);
user.getBase().updateInventory();
Trade.log("Command", "Sell", "Item", user.getName(), new Trade(ris, ess), user.getName(), new Trade(result, ess), user.getLocation(), ess);
user.giveMoney(result);
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.getDisplayName(), is.getType().toString().toLowerCase(Locale.ENGLISH), NumberUtil.displayCurrency(result, ess), amount, NumberUtil.displayCurrency(worth, ess)));
return result;
@@ -56,7 +56,7 @@ public class Commandsudo extends EssentialsLoopCommand {
@Override
public void run() {
try {
ess.getServer().dispatchCommand(user.getBase(), command);
user.getBase().chat("/" + command);
} catch (Exception e) {
sender.sendMessage(tl("errorCallingCommand", command));
}
@@ -1,7 +1,11 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.Teleport;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import net.ess3.api.events.TPARequestEvent;
import org.bukkit.Server;
import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.Collections;
import java.util.List;
@@ -32,11 +36,25 @@ public class Commandtpa extends EssentialsCommand {
}
// Don't let sender request teleport twice to the same player.
if (user.getConfigUUID().equals(player.getTeleportRequest()) && player.hasOutstandingTeleportRequest() // Check timeout
&& player.isTpRequestHere() == false) { // Make sure the last teleport request was actually tpa and not tpahere
&& !player.isTpRequestHere()) { // Make sure the last teleport request was actually tpa and not tpahere
throw new Exception(tl("requestSentAlready", player.getDisplayName()));
}
if (player.isAutoTeleportEnabled() && !player.isIgnoredPlayer(user)) {
final Trade charge = new Trade(this.getName(), ess);
Teleport teleport = user.getTeleport();
teleport.setTpType(Teleport.TeleportType.TPA);
teleport.teleport(player.getBase(), charge, PlayerTeleportEvent.TeleportCause.COMMAND);
player.sendMessage(tl("requestAcceptedAuto", user.getDisplayName()));
user.sendMessage(tl("requestAcceptedFromAuto", player.getDisplayName()));
return;
}
if (!player.isIgnoredPlayer(user)) {
TPARequestEvent tpaEvent = new TPARequestEvent(user.getSource(), player, false);
ess.getServer().getPluginManager().callEvent(tpaEvent);
if (tpaEvent.isCancelled()) {
throw new Exception(tl("teleportRequestCancelled", player.getDisplayName()));
}
player.requestTeleport(user, false);
player.sendMessage(tl("teleportRequest", user.getDisplayName()));
player.sendMessage(tl("typeTpaccept"));
@@ -46,7 +64,9 @@ public class Commandtpa extends EssentialsCommand {
}
}
user.sendMessage(tl("requestSent", player.getDisplayName()));
user.sendMessage(tl("typeTpacancel"));
if (user.isAuthorized("essentials.tpacancel")) {
user.sendMessage(tl("typeTpacancel"));
}
}
@Override
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import net.ess3.api.events.TPARequestEvent;
import org.bukkit.Server;
import java.util.Collections;
@@ -42,6 +43,12 @@ public class Commandtpaall extends EssentialsCommand {
continue;
}
try {
TPARequestEvent tpaEvent = new TPARequestEvent(sender, player, true);
ess.getServer().getPluginManager().callEvent(tpaEvent);
if (tpaEvent.isCancelled()) {
sender.sendMessage(tl("teleportRequestCancelled", player.getDisplayName()));
continue;
}
player.requestTeleport(target, true);
player.sendMessage(tl("teleportHereRequest", target.getDisplayName()));
player.sendMessage(tl("typeTpaccept"));
@@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.api.events.TPARequestEvent;
import org.bukkit.Server;
import java.util.Collections;
@@ -32,10 +33,15 @@ public class Commandtpahere extends EssentialsCommand {
}
// Don't let sender request teleport twice to the same player.
if (user.getConfigUUID().equals(player.getTeleportRequest()) && player.hasOutstandingTeleportRequest() // Check timeout
&& player.isTpRequestHere() == true) { // Make sure the last teleport request was actually tpahere and not tpa
&& player.isTpRequestHere()) { // Make sure the last teleport request was actually tpahere and not tpa
throw new Exception(tl("requestSentAlready", player.getDisplayName()));
}
if (!player.isIgnoredPlayer(user)) {
TPARequestEvent tpaEvent = new TPARequestEvent(user.getSource(), player, true);
ess.getServer().getPluginManager().callEvent(tpaEvent);
if (tpaEvent.isCancelled()) {
throw new Exception(tl("teleportRequestCancelled", player.getDisplayName()));
}
player.requestTeleport(user, true);
player.sendMessage(tl("teleportHereRequest", user.getDisplayName()));
player.sendMessage(tl("typeTpaccept"));
@@ -0,0 +1,41 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import org.bukkit.Server;
import static com.earth2me.essentials.I18n.tl;
public class Commandtpauto extends EssentialsToggleCommand {
public Commandtpauto() {
super("tpauto", "essentials.tpauto.others");
}
@Override
protected void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
toggleOtherPlayers(server, sender, args);
}
@Override
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
handleToggleWithArgs(server, user, args);
}
@Override
void togglePlayer(CommandSource sender, User user, Boolean enabled) {
if (enabled == null) {
enabled = !user.isAutoTeleportEnabled();
}
user.setAutoTeleportEnabled(enabled);
user.sendMessage(enabled ? tl("autoTeleportEnabled") : tl("autoTeleportDisabled"));
if (enabled && !user.isTeleportEnabled()) {
user.sendMessage(tl("teleportationDisabledWarning"));
}
if (!sender.isPlayer() || !user.getBase().equals(sender.getPlayer())) {
sender.sendMessage(enabled ? tl("autoTeleportEnabledFor", user.getDisplayName()) : tl("autoTeleportDisabledFor", user.getDisplayName()));
}
}
}
@@ -44,6 +44,6 @@ public class Commandunbanip extends EssentialsCommand {
final String senderName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.NAME;
server.getLogger().log(Level.INFO, tl("playerUnbanIpAddress", senderName, ipAddress));
ess.broadcastMessage("essentials.ban.notify", tl("playerUnbanIpAddress", senderName, ipAddress));
ess.broadcastMessage("essentials.banip.notify", tl("playerUnbanIpAddress", senderName, ipAddress));
}
}
@@ -5,8 +5,10 @@ import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.ItemStack;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import static com.earth2me.essentials.I18n.tl;
@@ -32,14 +34,10 @@ public class Commandunlimited extends EssentialsCommand {
final String list = getList(target);
user.sendMessage(list);
} else if (args[0].equalsIgnoreCase("clear")) {
final List<Material> itemList = target.getUnlimited();
final Set<Material> itemList = new HashSet<>(target.getUnlimited());
int index = 0;
while (itemList.size() > index) {
final Material item = itemList.get(index);
if (!toggleUnlimited(user, target, item.toString())) {
index++;
}
for (Material m : itemList) {
toggleUnlimited(user, target, m.toString());
}
} else {
toggleUnlimited(user, target, args[0]);
@@ -50,7 +48,7 @@ public class Commandunlimited extends EssentialsCommand {
final StringBuilder output = new StringBuilder();
output.append(tl("unlimitedItems")).append(" ");
boolean first = true;
final List<Material> items = target.getUnlimited();
final Set<Material> items = target.getUnlimited();
if (items.isEmpty()) {
output.append(tl("none"));
}
@@ -13,9 +13,9 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
import static com.earth2me.essentials.I18n.tl;
@@ -64,17 +64,8 @@ public class Commandwarp extends EssentialsCommand {
//TODO: Use one of the new text classes, like /help ?
private void warpList(final CommandSource sender, final String[] args, final IUser user) throws Exception {
final IWarps warps = ess.getWarps();
final List<String> warpNameList = new ArrayList<>(warps.getList());
final List<String> warpNameList = getAvailableWarpsFor(user);
if (user != null) {
final Iterator<String> iterator = warpNameList.iterator();
while (iterator.hasNext()) {
final String warpName = iterator.next();
if (ess.getSettings().getPerWarpPermission() && !user.isAuthorized("essentials.warps." + warpName)) {
iterator.remove();
}
}
}
if (warpNameList.isEmpty()) {
throw new Exception(tl("noWarpsDefined"));
}
@@ -112,10 +103,20 @@ public class Commandwarp extends EssentialsCommand {
owner.getTeleport().warp(user, name, charge, TeleportCause.COMMAND);
}
private List<String> getAvailableWarpsFor(final IUser user) {
if (ess.getSettings().getPerWarpPermission() && user != null) {
return ess.getWarps().getList().stream()
.filter(warpName -> user.isAuthorized("essentials.warps." + warpName))
.collect(Collectors.toList());
}
return new ArrayList<>(ess.getWarps().getList());
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
if (args.length == 1 && user.isAuthorized("essentials.warp.list")) {
return new ArrayList<>(ess.getWarps().getList());
return getAvailableWarpsFor(user);
} else if (args.length == 2 && (user.isAuthorized("essentials.warp.otherplayers") || user.isAuthorized("essentials.warp.others"))) {
//TODO: Remove 'otherplayers' permission.
return getPlayers(server, user);
@@ -63,8 +63,14 @@ public class Commandwhois extends EssentialsCommand {
sender.sendMessage(tl("whoisAFK", tl("false")));
}
sender.sendMessage(tl("whoisJail", (user.isJailed() ? user.getJailTimeout() > 0 ? DateUtil.formatDateDiff(user.getJailTimeout()) : tl("true") : tl("false"))));
sender.sendMessage(tl("whoisMuted", (user.isMuted() ? user.getMuteTimeout() > 0 ? DateUtil.formatDateDiff(user.getMuteTimeout()) : tl("true") : tl("false"))));
long muteTimeout = user.getMuteTimeout();
if (!user.hasMuteReason()) {
sender.sendMessage(tl("whoisMuted", (user.isMuted() ? (muteTimeout > 0 ? DateUtil.formatDateDiff(muteTimeout) : tl("true")) : tl("false"))));
} else {
sender.sendMessage(tl("whoisMutedReason", (user.isMuted() ? (muteTimeout > 0 ? DateUtil.formatDateDiff(muteTimeout) : tl("true")) : tl("false")),
user.getMuteReason()));
}
}
@Override
@@ -104,7 +104,11 @@ public abstract class EssentialsCommand implements IEssentialsCommand {
try {
exPlayer = server.getPlayer(UUID.fromString(searchTerm));
} catch (IllegalArgumentException ex) {
exPlayer = server.getPlayer(searchTerm);
if (getOffline) {
exPlayer = server.getPlayerExact(searchTerm);
} else {
exPlayer = server.getPlayer(searchTerm);
}
}
if (exPlayer != null) {
@@ -4,6 +4,7 @@ import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.StringUtil;
import net.ess3.api.MaxMoneyException;
import org.bukkit.Server;
import org.bukkit.entity.Player;
@@ -23,7 +24,11 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
throw new PlayerNotFoundException();
}
if (matchWildcards && searchTerm.contentEquals("**")) {
final UUID uuid = StringUtil.toUUID(searchTerm);
if (uuid != null) {
final User matchedUser = ess.getUser(uuid);
updatePlayer(server, sender, matchedUser, commandArgs);
} else if (matchWildcards && searchTerm.contentEquals("**")) {
for (UUID sUser : ess.getUserMap().getAllUniqueUsers()) {
final User matchedUser = ess.getUser(sUser);
updatePlayer(server, sender, matchedUser, commandArgs);
@@ -18,6 +18,7 @@ import org.bukkit.util.Vector;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Predicate;
@@ -112,7 +113,7 @@ public class FakeWorld implements World {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
//@Override
public boolean unloadChunk(int i, int i1, boolean bln, boolean bln1) {
throw new UnsupportedOperationException("Not supported yet.");
}
@@ -122,7 +123,7 @@ public class FakeWorld implements World {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
//@Override
public boolean unloadChunkRequest(int i, int i1, boolean bln) {
throw new UnsupportedOperationException("Not supported yet.");
}
@@ -152,6 +153,31 @@ public class FakeWorld implements World {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean addPluginChunkTicket(int i, int i1, Plugin plugin) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean removePluginChunkTicket(int i, int i1, Plugin plugin) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void removePluginChunkTickets(Plugin plugin) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Collection<Plugin> getPluginChunkTickets(int i, int i1) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Map<Plugin, Collection<Chunk>> getPluginChunkTickets() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Item dropItem(Location lctn, ItemStack is) {
throw new UnsupportedOperationException("Not supported yet.");
@@ -168,7 +194,7 @@ public class FakeWorld implements World {
}
@Override
public <T extends Arrow> T spawnArrow(Location location, Vector vector, float v, float v1, Class<T> aClass) {
public <T extends AbstractArrow> T spawnArrow(Location location, Vector direction, float speed, float spread, Class<T> clazz) {
throw new UnsupportedOperationException("Not supported yet.");
}
@@ -351,6 +377,21 @@ public class FakeWorld implements World {
public boolean createExplosion(Location lctn, float f, boolean bln) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean createExplosion(double d, double d1, double d2, float f, boolean bln, boolean bln1, Entity entity) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean createExplosion(Location lctn, float f, boolean bln, boolean bln1) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean createExplosion(Location lctn, float f, boolean bln, boolean bln1, Entity entity) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public <T extends Entity> T spawn(Location lctn, Class<T> type) throws IllegalArgumentException {
@@ -407,21 +448,56 @@ public class FakeWorld implements World {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int getHighestBlockYAt(int i, int i1, HeightMap heightMap) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int getHighestBlockYAt(Location location, HeightMap heightMap) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Block getHighestBlockAt(int i, int i1, HeightMap heightMap) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Block getHighestBlockAt(Location location, HeightMap heightMap) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Biome getBiome(int i, int i1) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Biome getBiome(int i, int i1, int i2) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public double getTemperature(int i, int i1) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public double getTemperature(int i, int i1, int i2) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public double getHumidity(int i, int i1) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public double getHumidity(int i, int i1, int i2) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean unloadChunk(Chunk chunk) {
throw new UnsupportedOperationException("Not supported yet.");
@@ -497,6 +573,16 @@ public class FakeWorld implements World {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean isHardcore() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setHardcore(boolean hardcore) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public long getTicksPerAnimalSpawns() {
throw new UnsupportedOperationException("Not supported yet.");
@@ -562,6 +648,11 @@ public class FakeWorld implements World {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setBiome(int i, int i1, int i2, Biome biome) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int getMonsterSpawnLimit() {
throw new UnsupportedOperationException("Not supported yet.");
@@ -742,6 +833,16 @@ public class FakeWorld implements World {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Raid locateNearestRaid(Location location, int radius) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public List<Raid> getRaids() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public List<Entity> getNearbyEntities(Location loc, double x, double y, double z) {
throw new UnsupportedOperationException("Not supported yet.");
@@ -1,32 +1,114 @@
package com.earth2me.essentials.items;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.IConf;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.FireworkEffect;
import org.bukkit.Material;
import net.ess3.api.IEssentials;
import net.ess3.api.PluginKey;
import org.bukkit.*;
import org.bukkit.block.Banner;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.*;
import org.bukkit.plugin.Plugin;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.earth2me.essentials.I18n.tl;
public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
protected final IEssentials ess;
protected boolean ready = false;
private Map<PluginKey, ItemResolver> resolverMap = new HashMap<>();
AbstractItemDb(IEssentials ess) {
this.ess = ess;
}
@Override
public void registerResolver(Plugin plugin, String name, ItemResolver resolver) throws Exception {
PluginKey key = PluginKey.fromKey(plugin, name);
if (resolverMap.containsKey(key)) {
throw new Exception("Tried to add a duplicate resolver with name " + key.toString());
}
resolverMap.put(key, resolver);
}
@Override
public void unregisterResolver(Plugin plugin, String name) throws Exception {
PluginKey key = PluginKey.fromKey(plugin, name);
if (!resolverMap.containsKey(key)) {
throw new Exception("Tried to remove nonexistent resolver with name " + key.toString());
}
resolverMap.remove(key);
}
@Override
public boolean isResolverPresent(Plugin plugin, String name) {
return resolverMap.containsKey(PluginKey.fromKey(plugin, name));
}
@Override
public Map<PluginKey, ItemResolver> getResolvers() {
return new HashMap<>(resolverMap);
}
@Override
public Map<PluginKey, ItemResolver> getResolvers(Plugin plugin) {
Map<PluginKey, ItemResolver> matchingResolvers = new HashMap<>();
for (PluginKey key : resolverMap.keySet()) {
if (key.getPlugin().equals(plugin)) {
matchingResolvers.put(key, resolverMap.get(key));
}
}
return matchingResolvers;
}
@Override
public ItemResolver getResolver(Plugin plugin, String name) {
return resolverMap.get(PluginKey.fromKey(plugin, name));
}
@Override
public ItemStack get(String id) throws Exception {
return get(id, true);
}
ItemStack tryResolvers(String id) {
for (PluginKey key : resolverMap.keySet()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info(String.format("Trying resolver '%s' for item '%s'...", key, id));
}
Function<String, ItemStack> resolver = resolverMap.get(key);
ItemStack stack = resolver.apply(id);
if (stack != null) {
return stack;
}
}
return null;
}
Collection<String> getResolverNames() {
return resolverMap.values().stream()
.map(ItemResolver::getNames)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
@Override
public List<ItemStack> getMatching(User user, String[] args) throws Exception {
List<ItemStack> is = new ArrayList<>();
@@ -62,7 +144,7 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
@Override
public String serialize(ItemStack is) {
String mat = is.getType().name();
String mat = name(is);
if (VersionUtil.getServerBukkitVersion().isLowerThanOrEqualTo(VersionUtil.v1_12_2_R01) && is.getData().getData() != 0) {
mat = mat + ":" + is.getData().getData();
}
@@ -224,4 +306,9 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
return sb.toString().trim().replaceAll("§", "&");
}
@Override
public boolean isReady() {
return ready;
}
}
@@ -0,0 +1,89 @@
package com.earth2me.essentials.items;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.EssentialsConf;
import com.earth2me.essentials.IConf;
import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import net.ess3.api.IItemDb;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
public class CustomItemResolver implements IItemDb.ItemResolver, IConf {
private final EssentialsConf config;
private final Essentials ess;
private final HashMap<String, String> map = new HashMap<>();
public CustomItemResolver(Essentials ess) {
config = new EssentialsConf(new File(ess.getDataFolder(), "custom_items.yml"));
this.ess = ess;
config.setTemplateName("/custom_items.yml");
}
@Override
public ItemStack apply(String item) {
if (map.containsKey(item)) {
try {
return ess.getItemDb().get(map.get(item));
} catch (Exception ignored) {}
}
return null;
}
@Override
public Collection<String> getNames() {
return map.keySet();
}
@Override
public void reloadConfig() {
map.clear();
config.load();
ConfigurationSection section = config.getConfigurationSection("aliases");
if (section == null || section.getKeys(false).isEmpty()) {
ess.getLogger().warning("No aliases found in custom_items.yml.");
return;
}
for (String alias : section.getKeys(false)) {
if (!section.isString(alias)) continue;
String target = section.getString(alias);
if (target != null && !section.contains(target) && existsInItemDb(target)) {
map.put(alias, target);
}
}
}
public void setAlias(String alias, String target) {
if (map.containsKey(alias) && map.get(alias).equalsIgnoreCase(target)) {
return;
}
map.put(alias, target);
save();
}
public void removeAlias(String alias) {
if (map.remove(alias) != null) {
save();
}
}
private void save() {
config.setProperty("aliases", map);
config.save();
}
private boolean existsInItemDb(String item) {
try {
ess.getItemDb().get(item);
return true;
} catch (Exception e) {
return false;
}
}
}
@@ -1,6 +1,7 @@
package com.earth2me.essentials.items;
import com.earth2me.essentials.ManagedFile;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
@@ -8,11 +9,11 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import net.ess3.api.IEssentials;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.inventory.meta.Repairable;
import org.bukkit.potion.PotionData;
import java.util.*;
@@ -24,8 +25,6 @@ import static com.earth2me.essentials.I18n.tl;
public class FlatItemDb extends AbstractItemDb {
protected static final Logger LOGGER = Logger.getLogger("Essentials");
private final transient IEssentials ess;
private static Gson gson = new Gson();
// Maps primary name to ItemData
@@ -40,7 +39,7 @@ public class FlatItemDb extends AbstractItemDb {
private transient ManagedFile file = null;
public FlatItemDb(final IEssentials ess) {
this.ess = ess;
super(ess);
}
@Override
@@ -57,19 +56,22 @@ public class FlatItemDb extends AbstractItemDb {
this.reset();
String json = file.getLines().stream()
.filter(line -> !line.startsWith("#"))
.collect(Collectors.joining());
.filter(line -> !line.startsWith("#"))
.collect(Collectors.joining());
this.loadJSON(String.join("\n", json));
ready = true;
}
private void reset() {
ready = false;
items.clear();
itemAliases.clear();
allAliases.clear();
}
public void loadJSON(String source) {
private void loadJSON(String source) {
JsonObject map = (new JsonParser()).parse(source).getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : map.entrySet()) {
@@ -98,7 +100,14 @@ public class FlatItemDb extends AbstractItemDb {
}
@Override
public ItemStack get(String id) throws Exception {
public ItemStack get(String id, boolean useResolvers) throws Exception {
if (useResolvers) {
ItemStack resolved = tryResolvers(id);
if (resolved != null) {
return resolved;
}
}
id = id.toLowerCase();
final String[] split = id.split(":");
@@ -108,12 +117,14 @@ public class FlatItemDb extends AbstractItemDb {
throw new Exception(tl("unknownItemName", id));
}
PotionData potionData = data.getPotionData();
Material material = data.getMaterial();
if (!material.isItem()) throw new Exception(tl("unableToSpawnItem", id));
ItemStack stack = new ItemStack(material);
stack.setAmount(material.getMaxStackSize());
PotionData potionData = data.getPotionData();
ItemMeta meta = stack.getItemMeta();
if (potionData != null && meta instanceof PotionMeta) {
@@ -130,6 +141,13 @@ public class FlatItemDb extends AbstractItemDb {
stack.setItemMeta(meta);
// The spawner provider will update the meta again, so we need to call it after
// setItemMeta to prevent a race condition
EntityType entity = data.getEntity();
if (entity != null && material.toString().contains("SPAWNER")) {
ess.getSpawnerProvider().setEntityType(stack, entity);
}
return stack;
}
@@ -161,14 +179,7 @@ public class FlatItemDb extends AbstractItemDb {
@Override
public String name(ItemStack item) {
Material type = item.getType();
PotionData potion = null;
if (MaterialUtil.isPotion(type) && item.getItemMeta() instanceof PotionMeta) {
potion = ((PotionMeta) item.getItemMeta()).getBasePotionData();
}
ItemData data = new ItemData(type, potion);
ItemData data = lookup(item);
for (Map.Entry<String, ItemData> entry : items.entrySet()) {
if (entry.getValue().equals(data)) {
@@ -181,24 +192,51 @@ public class FlatItemDb extends AbstractItemDb {
@Override
@Deprecated
public int getLegacyId(Material material) throws Exception {
public int getLegacyId(Material material) {
throw new UnsupportedOperationException("Legacy IDs aren't supported on this version.");
}
private ItemData lookup(ItemStack item) {
Material type = item.getType();
if (MaterialUtil.isPotion(type) && item.getItemMeta() instanceof PotionMeta) {
PotionData potion = ((PotionMeta) item.getItemMeta()).getBasePotionData();
return new ItemData(type, potion);
} else if (type.toString().contains("SPAWNER")) {
EntityType entity = ess.getSpawnerProvider().getEntityType(item);
return new ItemData(type, entity);
} else {
return new ItemData(type);
}
}
@Override
public Collection<String> listNames() {
return Collections.unmodifiableSet(allAliases);
Set<String> names = new HashSet<>(allAliases);
names.addAll(getResolverNames());
return names;
}
public static class ItemData {
private Material material;
private PotionData potionData;
private String[] fallbacks = null;
private PotionData potionData = null;
private EntityType entity = null;
public ItemData(Material material, PotionData potionData) {
ItemData(Material material) {
this.material = material;
}
ItemData(Material material, PotionData potionData) {
this.material = material;
this.potionData = potionData;
}
ItemData(Material material, EntityType entity) {
this.material = material;
this.entity = entity;
}
@Override
public int hashCode() {
return (31 * material.hashCode()) ^ potionData.hashCode();
@@ -213,10 +251,15 @@ public class FlatItemDb extends AbstractItemDb {
return false;
}
ItemData that = (ItemData) o;
return this.material == that.getMaterial() && potionDataEquals(that);
return this.getMaterial() == that.getMaterial() && potionDataEquals(that) && entityEquals(that);
}
public Material getMaterial() {
if (material == null && fallbacks != null) {
material = EnumUtil.getMaterial(fallbacks);
fallbacks = null; // If fallback fails, don't keep trying to look up fallbacks
}
return material;
}
@@ -224,6 +267,10 @@ public class FlatItemDb extends AbstractItemDb {
return this.potionData;
}
public EntityType getEntity() {
return this.entity;
}
private boolean potionDataEquals(ItemData o) {
if (this.potionData == null && o.getPotionData() == null) {
return true;
@@ -233,5 +280,15 @@ public class FlatItemDb extends AbstractItemDb {
return false;
}
}
private boolean entityEquals(ItemData o) {
if (this.entity == null && o.getEntity() == null) { // neither have an entity
return true;
} else if (this.entity != null && o.getEntity() != null) { // both have an entity; check if it's the same one
return this.entity.equals(o.getEntity());
} else { // one has an entity but the other doesn't, so they can't be equal
return false;
}
}
}
}
@@ -20,7 +20,6 @@ import static com.earth2me.essentials.I18n.tl;
public class LegacyItemDb extends AbstractItemDb {
protected static final Logger LOGGER = Logger.getLogger("Essentials");
private final transient IEssentials ess;
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<>();
@@ -32,7 +31,7 @@ public class LegacyItemDb extends AbstractItemDb {
private final transient Pattern csvSplitPattern = Pattern.compile("(\"([^\"]*)\"|[^,]*)(,|$)");
public LegacyItemDb(final IEssentials ess) {
this.ess = ess;
super(ess);
file = new ManagedFile("items.csv", ess);
}
@@ -44,6 +43,7 @@ public class LegacyItemDb extends AbstractItemDb {
return;
}
ready = false;
durabilities.clear();
items.clear();
names.clear();
@@ -90,18 +90,13 @@ public class LegacyItemDb extends AbstractItemDb {
continue;
}
Material material = Material.matchMaterial(itemName);
if (material == null) {
LOGGER.warning(String.format("Failed to find material for %s", itemName));
continue;
}
durabilities.put(itemName, data);
items.put(itemName, numeric);
if (nbt != null) {
nbtData.put(itemName, nbt);
}
ItemData itemData = new ItemData(material, numeric, data);
ItemData itemData = new ItemData(numeric, data);
if (names.containsKey(itemData)) {
List<String> nameList = names.get(itemData);
nameList.add(itemName);
@@ -120,10 +115,19 @@ public class LegacyItemDb extends AbstractItemDb {
}
LOGGER.info(String.format("Loaded %s items from items.csv.", listNames().size()));
ready = true;
}
@Override
public ItemStack get(final String id) throws Exception {
public ItemStack get(final String id, final boolean useResolvers) throws Exception {
if (useResolvers) {
ItemStack resolved = tryResolvers(id);
if (resolved != null) {
return resolved;
}
}
int itemid = 0;
String itemname;
short metaData = 0;
@@ -152,6 +156,13 @@ public class LegacyItemDb extends AbstractItemDb {
}
}
if (itemid < 1) {
Material matFromName = EnumUtil.getMaterial(itemname.toUpperCase());
if (matFromName != null) {
itemid = matFromName.getId();
}
}
if (itemid < 1) {
throw new Exception(tl("unknownItemName", itemname));
}
@@ -161,7 +172,7 @@ public class LegacyItemDb extends AbstractItemDb {
throw new Exception(tl("unknownItemId", itemid));
}
Material mat = data.getMaterial();
Material mat = getFromLegacy(itemid, (byte) metaData);
ItemStack retval = new ItemStack(mat);
if (nbtData.containsKey(itemname)) {
String nbt = nbtData.get(itemname);
@@ -198,10 +209,10 @@ public class LegacyItemDb extends AbstractItemDb {
@Override
public List<String> nameList(ItemStack item) {
ItemData itemData = new ItemData(item.getType(), item.getDurability());
ItemData itemData = new ItemData(item.getType().getId(), item.getDurability());
List<String> nameList = names.get(itemData);
if (nameList == null) {
itemData = new ItemData(item.getType(), (short) 0);
itemData = new ItemData(item.getType().getId(), (short) 0);
nameList = names.get(itemData);
if (nameList == null) {
return null;
@@ -213,10 +224,10 @@ public class LegacyItemDb extends AbstractItemDb {
@Override
public String name(ItemStack item) {
ItemData itemData = new ItemData(item.getType(), item.getDurability());
ItemData itemData = new ItemData(item.getType().getId(), item.getDurability());
String name = primaryName.get(itemData);
if (name == null) {
itemData = new ItemData(item.getType(), (short) 0);
itemData = new ItemData(item.getType().getId(), (short) 0);
name = primaryName.get(itemData);
if (name == null) {
return null;
@@ -225,16 +236,6 @@ public class LegacyItemDb extends AbstractItemDb {
return name;
}
@Override
public Material getFromLegacy(final int id, final byte damage) {
ItemData data = this.legacyIds.get(id);
if (data == null) {
return null;
}
return data.getMaterial();
}
@Override
public int getLegacyId(Material material) throws Exception {
for(Map.Entry<String, Integer> entry : items.entrySet()) {
@@ -248,33 +249,22 @@ public class LegacyItemDb extends AbstractItemDb {
@Override
public Collection<String> listNames() {
return primaryName.values();
Collection<String> values = new ArrayList<>(primaryName.values());
values.addAll(getResolverNames());
return values;
}
static class ItemData {
final private Material material;
private int legacyId;
private int itemNo;
final private short itemData;
ItemData(Material material, short itemData) {
this.material = material;
ItemData(final int itemNo, final short itemData) {
this.itemNo = itemNo;
this.itemData = itemData;
}
@Deprecated
ItemData(Material material, final int legacyId, final short itemData) {
this.material = material;
this.legacyId = legacyId;
this.itemData = itemData;
}
public Material getMaterial() {
return material;
}
@Deprecated
public int getItemNo() {
return legacyId;
return itemNo;
}
public short getItemData() {
@@ -283,7 +273,7 @@ public class LegacyItemDb extends AbstractItemDb {
@Override
public int hashCode() {
return (31 * material.hashCode()) ^ itemData;
return (31 * itemNo) ^ itemData;
}
@Override
@@ -295,7 +285,7 @@ public class LegacyItemDb extends AbstractItemDb {
return false;
}
ItemData pairo = (ItemData) o;
return this.material == pairo.getMaterial() && this.itemData == pairo.getItemData();
return this.itemNo == pairo.getItemNo() && this.itemData == pairo.getItemData();
}
}
@@ -1,14 +1,13 @@
package com.earth2me.essentials.messaging;
import static com.earth2me.essentials.I18n.tl;
import com.earth2me.essentials.Console;
import com.earth2me.essentials.IEssentials;
import com.earth2me.essentials.IUser;
import com.earth2me.essentials.User;
import java.lang.ref.WeakReference;
import static com.earth2me.essentials.I18n.tl;
/**
* Represents a simple reusable implementation of {@link IMessageRecipient}. This class provides functionality for the following methods:
* <ul>
@@ -120,11 +119,13 @@ public class SimpleMessageRecipient implements IMessageRecipient {
User user = getUser(this);
boolean afk = false;
boolean isLastMessageReplyRecipient = ess.getSettings().isLastMessageReplyRecipient();
if (user != null) {
if (user.isIgnoreMsg() && sender instanceof IUser && !((IUser) sender).isAuthorized("essentials.msgtoggle.bypass")) { // Don't ignore console and senders with permission
return MessageResponse.MESSAGES_IGNORED;
if (user.isIgnoreMsg() && sender instanceof IUser && !((IUser) sender).isAuthorized("essentials.msgtoggle.bypass")) { // Don't ignore console and senders with permission
return MessageResponse.MESSAGES_IGNORED;
}
afk = user.isAfk();
isLastMessageReplyRecipient = user.isLastMessageReplyRecipient();
// Check whether this recipient ignores the sender, only if the sender is not the console.
if (sender instanceof IUser && user.isIgnoredPlayer((IUser) sender)) {
return MessageResponse.SENDER_IGNORED;
@@ -133,7 +134,7 @@ public class SimpleMessageRecipient implements IMessageRecipient {
// Display the formatted message to this recipient.
sendMessage(tl("msgFormat", sender.getDisplayName(), tl("me"), message));
if (ess.getSettings().isLastMessageReplyRecipient()) {
if (isLastMessageReplyRecipient) {
// If this recipient doesn't have a reply recipient, initiate by setting the first
// message sender to this recipient's replyRecipient.
long timeout = ess.getSettings().getLastMessageReplyRecipientTimeout() * 1000;
@@ -1,13 +1,14 @@
package com.earth2me.essentials.metrics;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import javax.net.ssl.HttpsURLConnection;
import java.io.*;
@@ -186,24 +187,24 @@ public class Metrics {
*
* @return The plugin specific data.
*/
public JSONObject getPluginData() {
JSONObject data = new JSONObject();
public JsonObject getPluginData() {
JsonObject data = new JsonObject();
String pluginName = "EssentialsX";
String pluginName = plugin.getDescription().getName().replace("Essentials", "EssentialsX");
String pluginVersion = plugin.getDescription().getVersion();
data.put("pluginName", pluginName); // Append the name of the plugin
data.put("pluginVersion", pluginVersion); // Append the version of the plugin
JSONArray customCharts = new JSONArray();
data.addProperty("pluginName", pluginName); // Append the name of the plugin
data.addProperty("pluginVersion", pluginVersion); // Append the version of the plugin
JsonArray customCharts = new JsonArray();
for (CustomChart customChart : charts) {
// Add the data of the custom charts
JSONObject chart = customChart.getRequestJsonObject();
JsonObject chart = customChart.getRequestJsonObject();
if (chart == null) { // If the chart is null, we skip it
continue;
}
customCharts.add(chart);
}
data.put("customCharts", customCharts);
data.add("customCharts", customCharts);
return data;
}
@@ -213,7 +214,7 @@ public class Metrics {
*
* @return The server specific data.
*/
private JSONObject getServerData() {
private JsonObject getServerData() {
// Minecraft specific data
int playerAmount;
try {
@@ -228,6 +229,7 @@ public class Metrics {
}
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
String bukkitVersion = Bukkit.getVersion();
String bukkitName = Bukkit.getName();
// OS/Java specific data
String javaVersion = System.getProperty("java.version");
@@ -236,19 +238,20 @@ public class Metrics {
String osVersion = System.getProperty("os.version");
int coreCount = Runtime.getRuntime().availableProcessors();
JSONObject data = new JSONObject();
JsonObject data = new JsonObject();
data.put("serverUUID", serverUUID);
data.addProperty("serverUUID", serverUUID);
data.put("playerAmount", playerAmount);
data.put("onlineMode", onlineMode);
data.put("bukkitVersion", bukkitVersion);
data.addProperty("playerAmount", playerAmount);
data.addProperty("onlineMode", onlineMode);
data.addProperty("bukkitVersion", bukkitVersion);
data.addProperty("bukkitName", bukkitName);
data.put("javaVersion", javaVersion);
data.put("osName", osName);
data.put("osArch", osArch);
data.put("osVersion", osVersion);
data.put("coreCount", coreCount);
data.addProperty("javaVersion", javaVersion);
data.addProperty("osName", osName);
data.addProperty("osArch", osArch);
data.addProperty("osVersion", osVersion);
data.addProperty("coreCount", coreCount);
return data;
}
@@ -257,9 +260,9 @@ public class Metrics {
* Collects the data and sends it afterwards.
*/
private void submitData() {
final JSONObject data = getServerData();
final JsonObject data = getServerData();
JSONArray pluginData = new JSONArray();
JsonArray pluginData = new JsonArray();
// Search for all other bStats Metrics classes to get their plugin data
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
@@ -267,26 +270,43 @@ public class Metrics {
for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
try {
pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider()));
Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
if (plugin instanceof JsonObject) {
pluginData.add((JsonObject) plugin);
} else { // old bstats version compatibility
try {
Class<?> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) {
Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
jsonStringGetter.setAccessible(true);
String jsonString = (String) jsonStringGetter.invoke(plugin);
JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
pluginData.add(object);
}
} catch (ClassNotFoundException e) {
// minecraft version 1.14+
if (logFailedRequests) {
this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception", e);
}
continue; // continue looping since we cannot do any other thing.
}
}
} catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { }
}
} catch (NoSuchFieldException ignored) { }
}
data.put("plugins", pluginData);
data.add("plugins", pluginData);
// Create a new thread for the connection to the bStats server
new Thread(new Runnable() {
@Override
public void run() {
try {
// Send the data
sendData(plugin, data);
} catch (Exception e) {
// Something went wrong! :(
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
}
new Thread(() -> {
try {
// Send the data
sendData(plugin, data);
} catch (Exception e) {
// Something went wrong! :(
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
}
}
}).start();
@@ -299,7 +319,7 @@ public class Metrics {
* @param data The data to send.
* @throws Exception If the request failed.
*/
private static void sendData(Plugin plugin, JSONObject data) throws Exception {
private static void sendData(Plugin plugin, JsonObject data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("Data cannot be null!");
}
@@ -382,16 +402,16 @@ public class Metrics {
this.chartId = chartId;
}
private JSONObject getRequestJsonObject() {
JSONObject chart = new JSONObject();
chart.put("chartId", chartId);
private JsonObject getRequestJsonObject() {
JsonObject chart = new JsonObject();
chart.addProperty("chartId", chartId);
try {
JSONObject data = getChartData();
JsonObject data = getChartData();
if (data == null) {
// If the data is null we don't send the chart.
return null;
}
chart.put("data", data);
chart.add("data", data);
} catch (Throwable t) {
if (logFailedRequests) {
Bukkit.getLogger().log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
@@ -401,7 +421,7 @@ public class Metrics {
return chart;
}
protected abstract JSONObject getChartData() throws Exception;
protected abstract JsonObject getChartData() throws Exception;
}
@@ -424,14 +444,14 @@ public class Metrics {
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
protected JsonObject getChartData() throws Exception {
JsonObject data = new JsonObject();
String value = callable.call();
if (value == null || value.isEmpty()) {
// Null = skip the chart
return null;
}
data.put("value", value);
data.addProperty("value", value);
return data;
}
}
@@ -455,9 +475,9 @@ public class Metrics {
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
protected JsonObject getChartData() throws Exception {
JsonObject data = new JsonObject();
JsonObject values = new JsonObject();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
@@ -469,13 +489,13 @@ public class Metrics {
continue; // Skip this invalid
}
allSkipped = false;
values.put(entry.getKey(), entry.getValue());
values.addProperty(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
data.put("values", values);
data.add("values", values);
return data;
}
}
@@ -499,9 +519,9 @@ public class Metrics {
}
@Override
public JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
public JsonObject getChartData() throws Exception {
JsonObject data = new JsonObject();
JsonObject values = new JsonObject();
Map<String, Map<String, Integer>> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
@@ -509,22 +529,22 @@ public class Metrics {
}
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JSONObject value = new JSONObject();
JsonObject value = new JsonObject();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
value.put(valueEntry.getKey(), valueEntry.getValue());
value.addProperty(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
if (!allSkipped) {
reallyAllSkipped = false;
values.put(entryValues.getKey(), value);
values.add(entryValues.getKey(), value);
}
}
if (reallyAllSkipped) {
// Null = skip the chart
return null;
}
data.put("values", values);
data.add("values", values);
return data;
}
}
@@ -548,14 +568,14 @@ public class Metrics {
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
protected JsonObject getChartData() throws Exception {
JsonObject data = new JsonObject();
int value = callable.call();
if (value == 0) {
// Null = skip the chart
return null;
}
data.put("value", value);
data.addProperty("value", value);
return data;
}
@@ -580,9 +600,9 @@ public class Metrics {
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
protected JsonObject getChartData() throws Exception {
JsonObject data = new JsonObject();
JsonObject values = new JsonObject();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
@@ -594,13 +614,13 @@ public class Metrics {
continue; // Skip this invalid
}
allSkipped = false;
values.put(entry.getKey(), entry.getValue());
values.addProperty(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
data.put("values", values);
data.add("values", values);
return data;
}
@@ -625,20 +645,20 @@ public class Metrics {
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
protected JsonObject getChartData() throws Exception {
JsonObject data = new JsonObject();
JsonObject values = new JsonObject();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
JSONArray categoryValues = new JSONArray();
JsonArray categoryValues = new JsonArray();
categoryValues.add(entry.getValue());
values.put(entry.getKey(), categoryValues);
values.add(entry.getKey(), categoryValues);
}
data.put("values", values);
data.add("values", values);
return data;
}
@@ -663,9 +683,9 @@ public class Metrics {
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
protected JsonObject getChartData() throws Exception {
JsonObject data = new JsonObject();
JsonObject values = new JsonObject();
Map<String, int[]> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
@@ -677,17 +697,17 @@ public class Metrics {
continue; // Skip this invalid
}
allSkipped = false;
JSONArray categoryValues = new JSONArray();
JsonArray categoryValues = new JsonArray();
for (int categoryValue : entry.getValue()) {
categoryValues.add(categoryValue);
}
values.put(entry.getKey(), categoryValues);
values.add(entry.getKey(), categoryValues);
}
if (allSkipped) {
// Null = skip the chart
return null;
}
data.put("values", values);
data.add("values", values);
return data;
}
}
@@ -16,6 +16,9 @@ public interface IPermissionsHandler {
boolean hasPermission(Player base, String node);
// Does not check for * permissions
boolean isPermissionSet(Player base, String node);
String getPrefix(Player base);
String getSuffix(Player base);
@@ -13,7 +13,7 @@ public class PermissionsHandler implements IPermissionsHandler {
private transient IPermissionsHandler handler = null;
private transient String defaultGroup = "default";
private final transient Essentials ess;
private transient boolean useSuperperms = false;
private transient boolean useSuperperms;
private Class<?> lastHandler = null;
@@ -62,6 +62,11 @@ public class PermissionsHandler implements IPermissionsHandler {
return handler.hasPermission(base, node);
}
@Override
public boolean isPermissionSet(final Player base, final String node) {
return handler.isPermissionSet(base, node);
}
@Override
public String getPrefix(final Player base) {
final long start = System.nanoTime();
@@ -92,10 +97,7 @@ public class PermissionsHandler implements IPermissionsHandler {
public void checkPermissions() {
// load and assign a handler
List<Class<? extends SuperpermsHandler>> providerClazz = Arrays.asList(
BPermissions2Handler.class,
PermissionsExHandler.class,
PrivilegesHandler.class,
SimplyPermsHandler.class,
ModernVaultHandler.class,
GenericVaultHandler.class,
SuperpermsHandler.class
);
@@ -158,7 +160,4 @@ public class PermissionsHandler implements IPermissionsHandler {
}
}
private void checkPermLag(long start) {
checkPermLag(start, "not defined");
}
}
@@ -13,7 +13,7 @@ public abstract class AbstractVaultHandler extends SuperpermsHandler {
protected static Permission perms = null;
protected static Chat chat = null;
public boolean setupProviders() {
private boolean setupProviders() {
try {
Class.forName("net.milkbowl.vault.permission.Permission");
Class.forName("net.milkbowl.vault.chat.Chat");
@@ -46,26 +46,34 @@ public abstract class AbstractVaultHandler extends SuperpermsHandler {
@Override
public String getPrefix(final Player base) {
String playerPrefix = chat.getPlayerPrefix(base);
if (playerPrefix == null) {
String playerGroup = perms.getPrimaryGroup(base);
return chat.getGroupPrefix(base.getWorld().getName(), playerGroup);
} else {
if (playerPrefix != null) {
return playerPrefix;
}
String playerGroup = perms.getPrimaryGroup(base);
if (playerGroup != null) {
return chat.getGroupPrefix(base.getWorld().getName(), playerGroup);
}
return null;
}
@Override
public String getSuffix(final Player base) {
String playerSuffix = chat.getPlayerSuffix(base);
if (playerSuffix == null) {
String playerGroup = perms.getPrimaryGroup(base);
return chat.getGroupSuffix(base.getWorld().getName(), playerGroup);
} else {
if (playerSuffix != null) {
return playerSuffix;
}
String playerGroup = perms.getPrimaryGroup(base);
if (playerGroup != null) {
return chat.getGroupSuffix(base.getWorld().getName(), playerGroup);
}
return null;
}
protected boolean canLoad() {
boolean canLoad() {
if (Bukkit.getPluginManager().getPlugin("Vault") == null) return false;
try {
return setupProviders();
@@ -1,17 +0,0 @@
package com.earth2me.essentials.perm.impl;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class BPermissions2Handler extends AbstractVaultHandler {
@Override
public boolean canBuild(final Player base, final String group) {
return hasPermission(base, "bPermissions.build");
}
@Override
public boolean tryProvider() {
return super.canLoad() && Bukkit.getPluginManager().getPlugin("bPermissions") != null;
}
}
@@ -0,0 +1,26 @@
package com.earth2me.essentials.perm.impl;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import org.bukkit.entity.Player;
public class ModernVaultHandler extends AbstractVaultHandler {
private final List<String> supportedPlugins = Arrays.asList("PermissionsEx", "LuckPerms");
@Override
protected boolean emulateWildcards() {
return false;
}
@Override
public boolean canBuild(final Player base, final String group) {
Objects.requireNonNull(base, "Can't check build override for nonexistent player!");
return super.canBuild(base, group) || chat.getPlayerInfoBoolean(base.getWorld().getName(), base, "build", false);
}
@Override
public boolean tryProvider() {
return super.canLoad() && supportedPlugins.contains(getEnabledPermsPlugin());
}
}
@@ -1,16 +0,0 @@
package com.earth2me.essentials.perm.impl;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class PermissionsExHandler extends AbstractVaultHandler {
@Override
public boolean canBuild(final Player base, final String group) {
return base != null && chat.getPlayerInfoBoolean(base.getWorld().getName(), base, "build", false);
}
@Override
public boolean tryProvider() {
return super.canLoad() && Bukkit.getPluginManager().getPlugin("PermissionsEx") != null;
}
}
@@ -1,16 +0,0 @@
package com.earth2me.essentials.perm.impl;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class PrivilegesHandler extends AbstractVaultHandler {
@Override
public boolean canBuild(Player base, String group) {
return hasPermission(base, "privileges.build");
}
@Override
public boolean tryProvider() {
return super.canLoad() && Bukkit.getPluginManager().getPlugin("Privileges") != null;
}
}
@@ -1,16 +0,0 @@
package com.earth2me.essentials.perm.impl;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class SimplyPermsHandler extends AbstractVaultHandler {
@Override
public boolean canBuild(Player base, String group) {
return hasPermission(base, "permissions.allow.build");
}
@Override
public boolean tryProvider() {
return super.canLoad() && Bukkit.getPluginManager().getPlugin("SimplyPerms") != null;
}
}
@@ -10,6 +10,10 @@ import java.util.List;
public class SuperpermsHandler implements IPermissionsHandler {
protected boolean emulateWildcards() {
return true;
}
@Override
public String getGroup(final Player base) {
return null;
@@ -22,7 +26,7 @@ public class SuperpermsHandler implements IPermissionsHandler {
@Override
public boolean canBuild(final Player base, final String group) {
return false;
return hasPermission(base, "essentials.build");
}
@Override
@@ -32,6 +36,10 @@ public class SuperpermsHandler implements IPermissionsHandler {
@Override
public boolean hasPermission(final Player base, String node) {
if (!emulateWildcards()) {
return base.hasPermission(node);
}
String permCheck = node;
int index;
while (true) {
@@ -49,6 +57,11 @@ public class SuperpermsHandler implements IPermissionsHandler {
}
}
@Override
public boolean isPermissionSet(final Player base, final String node) {
return base.isPermissionSet(node);
}
@Override
public String getPrefix(final Player base) {
return null;
@@ -5,10 +5,10 @@ import org.bukkit.plugin.Plugin;
/**
* Interface to be implemented by a payment method.
* Copyright (C) 2011
* AOL license <http://aol.nexua.org>
*
* @author Nijikokun <nijikokun@shortmail.com> (@nijikokun)
* @copyright Copyright (C) 2011
* @license AOL license <http://aol.nexua.org>
*/
public interface Method {
/**
@@ -22,7 +22,7 @@ import java.util.Set;
* preferred: "iConomy"
* </pre></blockquote>
*
* @author: Nijikokun <nijikokun@shortmail.com> (@nijikokun) @copyright: Copyright (C) 2011 @license: AOL license
* @author Nijikokun <nijikokun@shortmail.com> (@nijikokun) @copyright: Copyright (C) 2011 @license: AOL license
* <http://aol.nexua.org>
*/
public class Methods {
@@ -30,9 +30,9 @@ public class Methods {
private static boolean self = false;
private static Method Method = null;
private static String preferred = "";
private static final Set<Method> Methods = new HashSet<Method>();
private static final Set<String> Dependencies = new HashSet<String>();
private static final Set<Method> Attachables = new HashSet<Method>();
private static final Set<Method> Methods = new HashSet<>();
private static final Set<String> Dependencies = new HashSet<>();
private static final Set<Method> Attachables = new HashSet<>();
static {
_init();
@@ -79,7 +79,7 @@ public class Methods {
*
* @return <code>Set<String></code> - Array of payment methods that are loaded.
*
* @see #setMethod(org.bukkit.plugin.Plugin)
* @see #setMethod(PluginManager)
*/
public static Set<String> getDependencies() {
return Dependencies;
@@ -114,8 +114,8 @@ public class Methods {
*
* @return <code>boolean</code>
*
* @see #setMethod(org.bukkit.plugin.Plugin)
* @see #checkDisabled(org.bukkit.plugin.Plugin)
* @see #setMethod(PluginManager)
* @see #checkDisabled(Plugin)
*/
public static boolean hasMethod() {
return (Method != null);
@@ -124,7 +124,7 @@ public class Methods {
/**
* Checks Plugin Class against a multitude of checks to verify it's usability as a payment method.
*
* @param <code>PluginManager</code> the plugin manager for the server
* @param manager the plugin manager for the server
*
* @return <code>boolean</code> True on success, False on failure.
*/
@@ -140,7 +140,7 @@ public class Methods {
int count = 0;
boolean match = false;
Plugin plugin = null;
Plugin plugin;
for (String name : getDependencies()) {
if (hasMethod()) {
@@ -1,18 +1,17 @@
package com.earth2me.essentials.register.payment.methods;
import com.earth2me.essentials.register.payment.Method;
import net.milkbowl.vault.Vault;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
public class VaultEco implements Method {
private Vault vault;
private Plugin vault;
private Economy economy;
@Override
public Vault getPlugin() {
public Plugin getPlugin() {
return this.vault;
}
@@ -108,17 +107,15 @@ public class VaultEco implements Method {
public boolean isCompatible(Plugin plugin) {
try {
RegisteredServiceProvider<Economy> ecoPlugin = plugin.getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
return plugin instanceof Vault && ecoPlugin != null && !ecoPlugin.getProvider().getName().equals("Essentials Economy");
} catch (LinkageError e) {
return false;
} catch (Exception e) {
return plugin.getName().equals("Vault") && ecoPlugin != null && !ecoPlugin.getProvider().getName().equals("Essentials Economy");
} catch (LinkageError | Exception e) {
return false;
}
}
@Override
public void setPlugin(Plugin plugin) {
this.vault = (Vault) plugin;
this.vault = plugin;
RegisteredServiceProvider<Economy> economyProvider = this.vault.getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
if (economyProvider != null) {
this.economy = economyProvider.getProvider();
@@ -130,7 +127,7 @@ public class VaultEco implements Method {
private final String name;
private final Economy economy;
public VaultAccount(String name, Economy economy) {
VaultAccount(String name, Economy economy) {
this.name = name;
this.economy = economy;
}
@@ -2,15 +2,39 @@ package com.earth2me.essentials.settings;
import com.earth2me.essentials.storage.MapValueType;
import com.earth2me.essentials.storage.StorageObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.bukkit.Location;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@Data @EqualsAndHashCode(callSuper = false) public class Jails implements StorageObject {
public class Jails implements StorageObject {
@MapValueType(Location.class)
private Map<String, Location> jails = new HashMap<String, Location>();
private Map<String, Location> jails = new HashMap<>();
public Map<String, Location> getJails() {
return jails;
}
public void setJails(Map<String, Location> jails) {
this.jails = jails;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Jails jails1 = (Jails) o;
return Objects.equals(jails, jails1.jails);
}
@Override
public int hashCode() {
return Objects.hash(jails);
}
}
@@ -2,14 +2,38 @@ package com.earth2me.essentials.settings;
import com.earth2me.essentials.storage.MapValueType;
import com.earth2me.essentials.storage.StorageObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.bukkit.Location;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@Data @EqualsAndHashCode(callSuper = false) public class Spawns implements StorageObject {
public class Spawns implements StorageObject {
@MapValueType(Location.class)
private Map<String, Location> spawns = new HashMap<>();
public Map<String, Location> getSpawns() {
return spawns;
}
public void setSpawns(Map<String, Location> spawns) {
this.spawns = spawns;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Spawns spawns1 = (Spawns) o;
return Objects.equals(spawns, spawns1.spawns);
}
@Override
public int hashCode() {
return Objects.hash(spawns);
}
}
@@ -1,7 +1,7 @@
package com.earth2me.essentials.signs;
import com.earth2me.essentials.*;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
@@ -13,6 +13,7 @@ import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;
import org.bukkit.block.data.type.WallSign;
import org.bukkit.entity.Player;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.inventory.ItemStack;
@@ -26,7 +27,6 @@ import static com.earth2me.essentials.I18n.tl;
public class EssentialsSign {
private static final Material SIGN_POST = EnumUtil.getMaterial("SIGN", "SIGN_POST");
private static final Set<Material> EMPTY_SET = new HashSet<Material>();
protected static final BigDecimal MINTRANSACTION = new BigDecimal("0.01");
protected transient final String signName;
@@ -206,16 +206,15 @@ public class EssentialsSign {
protected static boolean checkIfBlockBreaksSigns(final Block block) {
final Block sign = block.getRelative(BlockFace.UP);
if (sign.getType() == SIGN_POST && isValidSign(new BlockSign(sign))) {
if (MaterialUtil.isSignPost(sign.getType()) && isValidSign(new BlockSign(sign))) {
return true;
}
final BlockFace[] directions = new BlockFace[]{BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST};
for (BlockFace blockFace : directions) {
final Block signblock = block.getRelative(blockFace);
if (signblock.getType() == Material.WALL_SIGN) {
final Block signBlock = block.getRelative(blockFace);
if (MaterialUtil.isWallSign(signBlock.getType())) {
try {
final org.bukkit.material.Sign signMat = (org.bukkit.material.Sign) signblock.getState().getData();
if (signMat != null && signMat.getFacing() == blockFace && isValidSign(new BlockSign(signblock))) {
if (getWallSignFacing(signBlock) == blockFace && isValidSign(new BlockSign(signBlock))) {
return true;
}
} catch (NullPointerException ex) {
@@ -297,12 +296,16 @@ public class EssentialsSign {
}
protected final Trade getTrade(final ISign sign, final int amountIndex, final int itemIndex, final User player, final IEssentials ess) throws SignException {
return getTrade(sign, amountIndex, itemIndex, player, false, ess);
}
protected final Trade getTrade(final ISign sign, final int amountIndex, final int itemIndex, final User player, final boolean allowId, final IEssentials ess) throws SignException {
final String itemType = getSignText(sign, itemIndex);
if (itemType.equalsIgnoreCase("exp") || itemType.equalsIgnoreCase("xp")) {
final int amount = getIntegerPositive(getSignText(sign, amountIndex));
return new Trade(amount, ess);
}
final ItemStack item = getItemStack(itemType, 1, true, ess);
final ItemStack item = getItemStack(itemType, 1, allowId, ess);
final int amount = Math.min(getIntegerPositive(getSignText(sign, amountIndex)), item.getType().getMaxStackSize() * player.getBase().getInventory().getSize());
if (item.getType() == Material.AIR || amount < 1) {
throw new SignException(tl("moreThanZero"));
@@ -402,6 +405,10 @@ public class EssentialsSign {
}
protected final Trade getTrade(final ISign sign, final int index, final int decrement, final IEssentials ess) throws SignException {
return getTrade(sign, index, decrement, false, ess);
}
protected final Trade getTrade(final ISign sign, final int index, final int decrement, final boolean allowId, final IEssentials ess) throws SignException {
final String line = getSignText(sign, index);
if (line.isEmpty()) {
return new Trade(signName.toLowerCase(Locale.ENGLISH) + "sign", ess);
@@ -424,7 +431,7 @@ public class EssentialsSign {
sign.setLine(index, quantity + " exp");
return new Trade(quantity, ess);
} else {
final ItemStack stack = getItemStack(item, quantity, true, ess);
final ItemStack stack = getItemStack(item, quantity, allowId, ess);
sign.setLine(index, quantity + " " + item);
return new Trade(stack, ess);
}
@@ -437,6 +444,16 @@ public class EssentialsSign {
ess.showError(sender, exception, "\\ sign: " + signName);
}
private static BlockFace getWallSignFacing(Block block) {
try {
final WallSign signData = (WallSign) block.getState().getBlockData();
return signData.getFacing();
} catch (NoClassDefFoundError | NoSuchMethodError e) {
final org.bukkit.material.Sign signMat = (org.bukkit.material.Sign) block.getState().getData();
return signMat.getFacing();
}
}
static class EventSign implements ISign {
private final transient SignChangeEvent event;
@@ -4,6 +4,7 @@ import com.earth2me.essentials.I18n;
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;
import org.bukkit.ChatColor;
@@ -22,8 +23,6 @@ import java.util.logging.Logger;
public class SignBlockListener implements Listener {
private static final Logger LOGGER = Logger.getLogger("Essentials");
private static final Material WALL_SIGN = Material.WALL_SIGN;
private static final Material SIGN_POST = EnumUtil.getMaterial("SIGN", "SIGN_POST");
private final transient IEssentials ess;
public SignBlockListener(IEssentials ess) {
@@ -55,7 +54,7 @@ public class SignBlockListener implements Listener {
}
final Material mat = block.getType();
if (mat == SIGN_POST || mat == WALL_SIGN) {
if (MaterialUtil.isSign(mat)) {
final Sign csign = (Sign) block.getState();
for (EssentialsSign sign : ess.getSettings().enabledSigns()) {
@@ -143,12 +142,12 @@ public class SignBlockListener implements Listener {
}
final Block against = event.getBlockAgainst();
if ((against.getType() == WALL_SIGN || against.getType() == SIGN_POST) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(against))) {
if (MaterialUtil.isSign(against.getType()) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(against))) {
event.setCancelled(true);
return;
}
final Block block = event.getBlock();
if (block.getType() == WALL_SIGN || block.getType() == SIGN_POST) {
if (MaterialUtil.isSign(block.getType())) {
return;
}
for (EssentialsSign sign : ess.getSettings().enabledSigns()) {
@@ -167,7 +166,7 @@ public class SignBlockListener implements Listener {
}
final Block block = event.getBlock();
if (((block.getType() == WALL_SIGN || block.getType() == SIGN_POST) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
if ((MaterialUtil.isSign(block.getType()) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
event.setCancelled(true);
return;
}
@@ -187,7 +186,7 @@ public class SignBlockListener implements Listener {
}
final Block block = event.getBlock();
if (((block.getType() == WALL_SIGN || block.getType() == SIGN_POST) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
if ((MaterialUtil.isSign(block.getType()) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
event.setCancelled(true);
return;
}
@@ -207,7 +206,7 @@ public class SignBlockListener implements Listener {
}
for (Block block : event.getBlocks()) {
if (((block.getType() == WALL_SIGN || block.getType() == SIGN_POST) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
if ((MaterialUtil.isSign(block.getType()) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
event.setCancelled(true);
return;
}
@@ -232,7 +231,7 @@ public class SignBlockListener implements Listener {
final Block[] affectedBlocks = new Block[]{pistonBaseBlock, pistonBaseBlock.getRelative(event.getDirection()), event.getRetractLocation().getBlock()};
for (Block block : affectedBlocks) {
if (((block.getType() == WALL_SIGN || block.getType() == SIGN_POST) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
if ((MaterialUtil.isSign(block.getType()) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
event.setCancelled(true);
return;
}
@@ -3,6 +3,8 @@ package com.earth2me.essentials.signs;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import static com.earth2me.essentials.I18n.tl;
public class SignDisposal extends EssentialsSign {
public SignDisposal() {
@@ -11,7 +13,7 @@ public class SignDisposal extends EssentialsSign {
@Override
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) {
player.getBase().openInventory(ess.getServer().createInventory(player.getBase(), 36, "Disposal"));
player.getBase().openInventory(ess.getServer().createInventory(player.getBase(), 36, tl("disposal")));
return true;
}
}
@@ -1,6 +1,7 @@
package com.earth2me.essentials.signs;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import net.ess3.api.IEssentials;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -13,7 +14,6 @@ import org.bukkit.event.entity.EntityExplodeEvent;
public class SignEntityListener implements Listener {
private static final Material SIGN_POST = EnumUtil.getMaterial("SIGN", "SIGN_POST");
private final transient IEssentials ess;
public SignEntityListener(final IEssentials ess) {
@@ -28,7 +28,7 @@ public class SignEntityListener implements Listener {
}
for (Block block : event.blockList()) {
if (((block.getType() == Material.WALL_SIGN || block.getType() == SIGN_POST) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
if ((MaterialUtil.isSign(block.getType()) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
event.setCancelled(true);
return;
}
@@ -49,7 +49,7 @@ public class SignEntityListener implements Listener {
}
final Block block = event.getBlock();
if (((block.getType() == Material.WALL_SIGN || block.getType() == SIGN_POST) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
if ((MaterialUtil.isSign(block.getType()) && EssentialsSign.isValidSign(ess, new EssentialsSign.BlockSign(block))) || EssentialsSign.checkIfBlockBreaksSigns(block)) {
event.setCancelled(true);
return;
}
@@ -54,6 +54,8 @@ public class SignGameMode extends EssentialsSign {
player.setGameMode(GameMode.CREATIVE);
} else if (mode.contains("advent") || mode.equalsIgnoreCase("2")) {
player.setGameMode(GameMode.ADVENTURE);
} else if (mode.contains("spec") || mode.equalsIgnoreCase("3")) {
player.setGameMode(GameMode.SPECTATOR);
} else {
throw new SignException(tl("invalidSignLine", 2));
}
@@ -75,7 +75,7 @@ public class SignProtection extends EssentialsSign {
final Block sign = entry.getKey().getBlock();
if (!hasAdjacentBlock(sign, block)) {
block.setType(Material.AIR);
final Trade trade = new Trade(new ItemStack(Material.SIGN, 1), ess);
final Trade trade = new Trade(new ItemStack(sign.getType(), 1), ess);
trade.pay(player, OverflowType.DROP);
}
}
@@ -26,8 +26,8 @@ public class SignTrade extends EssentialsSign {
protected boolean onSignCreate(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException, ChargeException {
validateTrade(sign, 1, false, ess);
validateTrade(sign, 2, true, ess);
final Trade trade = getTrade(sign, 2, AmountType.ROUNDED, true, ess);
final Trade charge = getTrade(sign, 1, AmountType.ROUNDED, false, ess);
final Trade trade = getTrade(sign, 2, AmountType.ROUNDED, true, true, ess);
final Trade charge = getTrade(sign, 1, AmountType.ROUNDED, false, true, ess);
if (trade.getType() == charge.getType() && (trade.getType() != TradeType.ITEM || trade.getItemStack().isSimilar(charge.getItemStack()))) {
throw new SignException("You cannot trade for the same item type.");
}
@@ -44,7 +44,7 @@ public class SignTrade extends EssentialsSign {
final Trade store = rechargeSign(sign, ess, player);
Trade stored;
try {
stored = getTrade(sign, 1, AmountType.TOTAL, true, ess);
stored = getTrade(sign, 1, AmountType.TOTAL, true, true, ess);
subtractAmount(sign, 1, stored, ess);
Map<Integer, ItemStack> withdraw = stored.pay(player, OverflowType.RETURN);
@@ -62,8 +62,8 @@ public class SignTrade extends EssentialsSign {
}
Trade.log("Sign", "Trade", "Deposit", username, store, username, null, sign.getBlock().getLocation(), ess);
} else {
final Trade charge = getTrade(sign, 1, AmountType.COST, false, ess);
final Trade trade = getTrade(sign, 2, AmountType.COST, true, ess);
final Trade charge = getTrade(sign, 1, AmountType.COST, false, true, ess);
final Trade trade = getTrade(sign, 2, AmountType.COST, true, true, ess);
charge.isAffordableFor(player);
addAmount(sign, 1, charge, ess);
subtractAmount(sign, 2, trade, ess);
@@ -80,7 +80,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, ess);
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())) {
int amount = player.getBase().getItemInHand().getAmount();
amount -= amount % trade.getItemStack().getAmount();
@@ -106,8 +106,8 @@ public class SignTrade extends EssentialsSign {
if (canBreak) {
try {
final Trade stored1 = getTrade(sign, 1, AmountType.TOTAL, false, ess);
final Trade stored2 = getTrade(sign, 2, AmountType.TOTAL, false, ess);
final Trade stored1 = getTrade(sign, 1, AmountType.TOTAL, false, true, ess);
final Trade stored2 = getTrade(sign, 2, AmountType.TOTAL, false, true, ess);
if (!canCollect) {
Trade.log("Sign", "Trade", "Destroy", signOwner, stored2, username, stored1, sign.getBlock().getLocation(), ess);
@@ -206,6 +206,10 @@ public class SignTrade extends EssentialsSign {
}
protected final Trade getTrade(final ISign sign, final int index, final AmountType amountType, final boolean notEmpty, final IEssentials ess) throws SignException {
return getTrade(sign, index, amountType, notEmpty, false, ess);
}
protected final Trade getTrade(final ISign sign, final int index, final AmountType amountType, final boolean notEmpty, final boolean allowId, final IEssentials ess) throws SignException {
final String line = sign.getLine(index).trim();
if (line.isEmpty()) {
throw new SignException("Empty line");
@@ -237,7 +241,7 @@ public class SignTrade extends EssentialsSign {
return new Trade((amountType == AmountType.COST ? stackamount : amount), ess);
} else {
final int stackamount = getIntegerPositive(split[0]);
final ItemStack item = getItemStack(split[1], stackamount, true, ess);
final ItemStack item = getItemStack(split[1], stackamount, allowId, ess);
int amount = getInteger(split[2]);
if (amountType == AmountType.ROUNDED) {
amount -= amount % stackamount;
@@ -40,16 +40,24 @@ public class SignWarp extends EssentialsSign {
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException, ChargeException {
final String warpName = sign.getLine(1);
final String group = sign.getLine(2);
if ((!group.isEmpty() && ("§2Everyone".equals(group) || player.inGroup(group))) || (group.isEmpty() && (!ess.getSettings().getPerWarpPermission() || player.isAuthorized("essentials.warps." + warpName)))) {
final Trade charge = getTrade(sign, 3, ess);
try {
player.getTeleport().warp(player, warpName, charge, TeleportCause.PLUGIN);
Trade.log("Sign", "Warp", "Interact", username, null, username, charge, sign.getBlock().getLocation(), ess);
} catch (Exception ex) {
throw new SignException(ex.getMessage(), ex);
if (!group.isEmpty()) {
if (!"§2Everyone".equals(group) && !player.inGroup(group)) {
throw new SignException(tl("warpUsePermission"));
}
} else {
if (ess.getSettings().getPerWarpPermission() && !player.isAuthorized("essentials.warps." + warpName)) {
throw new SignException(tl("warpUsePermission"));
}
return true;
}
return false;
final Trade charge = getTrade(sign, 3, ess);
try {
player.getTeleport().warp(player, warpName, charge, TeleportCause.PLUGIN);
Trade.log("Sign", "Warp", "Interact", username, null, username, charge, sign.getBlock().getLocation(), ess);
} catch (Exception ex) {
throw new SignException(ex.getMessage(), ex);
}
return true;
}
}
@@ -2,6 +2,7 @@ package com.earth2me.essentials.utils;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.entity.EntityType;
import java.lang.reflect.Field;
import java.util.HashSet;
@@ -12,7 +13,7 @@ public class EnumUtil {
/**
* Returns the field matching the first provided enum name that exists within the given
* enum class.
* enum class. If no field is found, this method returns null.
*
* @param enumClass The class to search through
* @param names The names of the fields to search for
@@ -78,4 +79,7 @@ public class EnumUtil {
return valueOf(Statistic.class, names);
}
public static EntityType getEntityType(String... names) {
return valueOf(EntityType.class, names);
}
}
Loaded 100 of 234 files, more files were not shown because too many files have changed in this diff. Show more