Compare commits

...
604 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
md678685 f7cbb141f8 Release 2.16.0
🎉
2019-01-03 20:47:24 +00:00
md678685 5690952516 Implement missing OfflinePlayer methods 2019-01-03 20:42:03 +00:00
md678685 e94202c55a Use 1.8-friendly User#getItemInHand method in commands 2019-01-03 20:33:08 +00:00
md678685 aa6ad271a0 Remove redundant metricsEnabled field from Settings 2019-01-03 20:33:08 +00:00
md678685 3b41bb47b6 Improve Travis build script (#2338)
I've added a new script at `scripts/buildtools.sh` that is responsible for:
* Checking whether CraftBukkit 1.8 and 1.8.3 are already available in the local Maven repo
* Downloading BuildTools if not already present
* Running BuildTools if necessary

This improves Travis build times as it now doesn't run BuildTools twice for *every single build*, instead running it only if the Travis cache fails and CraftBukkit is missing for some other reason.
2019-01-01 16:13:50 +00:00
md678685 e7bdb7fabc Improve the wording of the README's "Building" section 2019-01-01 15:42:45 +00:00
md678685 110698223d Travis: make build prep script executable 2019-01-01 15:23:35 +00:00
md678685 437be593b9 Add new build preparation script 2019-01-01 15:10:59 +00:00
md678685 502d37b574 Update Lombok to compile on Java 9+ 2018-12-31 17:44:08 +00:00
md678685 df59f9f859 Merge remote-tracking branch 'origin/2.x' into 1.13 2018-12-31 14:59:12 +00:00
md678685 f436fbab6b Remove redundant BuildTools runs 2018-12-31 14:54:59 +00:00
seema84 8404720501 change typos (#2328) @seema84
* change typos

* format text

* remove double color
2018-12-31 13:08:57 +00:00
md678685 4431d452f1 Bump to 2.16-pre4
Pretty much there now.
2018-12-31 13:02:08 +00:00
md678685 6a529d6671 Update EssentialsX Protect with cross-version enum lookups 2018-12-31 12:54:43 +00:00
md678685 78fca9a67a Updates signs with cross-version enum lookups 2018-12-31 12:53:41 +00:00
md678685 0114b5e4f6 Update several commands with cross-version enum lookups 2018-12-31 12:53:23 +00:00
md678685 5a14a64b6c Add cross-version support to SpawnMob 2018-12-31 12:24:41 +00:00
md678685 b555ea6350 Add cross-version support to MobData 2018-12-31 12:20:05 +00:00
md678685 361ae1dd16 Use constant field for "harp"/"piano" sound 2018-12-31 12:19:22 +00:00
md678685 58117eba88 Remove redundant BuildTools instructions 2018-12-31 12:18:45 +00:00
md678685 6260b49b4f Restore item ID messages in /itemdb 2018-12-31 11:57:15 +00:00
md678685 988239267b Restore durability permissions checks in AntiBuild 2018-12-31 11:56:50 +00:00
md678685 19cffe3872 Restore ID-based charges in /repair 2018-12-31 11:39:08 +00:00
md678685 3b1cef918e Simplify item spawn permission checks; restore ID-based item spawn perms 2018-12-31 11:29:27 +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
md678685 3553328f7a Bump to 2.16-pre3 2018-12-29 21:22:08 +00:00
md678685 0202271f00 Add missing FakeWorld methods 2018-12-29 21:16:17 +00:00
md678685 d91d6a419c Update items.json
* Fix incorrect "cobblestone" and "stone" aliases
* Fix stripped log aliases not appearing
* Fix meat/fish aliases pointing to spawn eggs
2018-12-28 16:40:39 +00:00
md678685 5173090474 Update items.json
Adds more minecart, meat, fish and hay aliases.
2018-12-26 21:05:48 +00:00
md678685 c26df8318f Update items.json
* Add more shorter spawn egg aliases
* Add new trapdoor aliases
* Add new infested block aliases and stone brick variants
2018-12-26 19:24:50 +00:00
md678685 7b44f0088a Update items.json
* Add spawn eggs aliases
* Add new aliases for several items and blocks like beetroot, pumpkins and crafting tables
* Remove `WALL_` materials (these are unspawnable)
2018-12-26 18:05:55 +00:00
md678685 aa4d3cc9fd Bump to 2.16-pre2 2018-12-25 00:27:54 +00:00
md678685 246fd03265 Fix typo in README 2018-12-23 23:33:46 +00:00
md678685 55074872fe Add setting to enable item ID recognition on signs
Item IDs can now be enabled for existing signs by manually changing a config option, but there is no facility to create new signs with item IDs.
2018-12-23 23:02:36 +00:00
md678685 28559dda3a Lowercase the provided ID in FlatItemDb#get 2018-12-23 19:45:23 +00:00
md678685 cbcfad5b2e Merge branch '2.x' into 1.13 2018-12-23 19:33:20 +00:00
md678685 a9ad440860 Overhaul AbstractItemDb.serialize to use MaterialUtil methods 2018-12-23 19:32:10 +00:00
md678685 5104463593 Add MaterialUtil.getColorOf 2018-12-23 19:31:33 +00:00
md678685 4b1c51c21d Reword IItemDb#serialize docs 2018-12-23 18:02:38 +00:00
md678685 236ef52980 Improved README (#2293)
I've made several improvements to the README, including:
* Overall rewording to make phrasing feel less awkward
* Added links to Patreon
* More consistent images for links at top
* Consolidated "Why you should use it" and "Other info" into "Why use EssentialsX?"
* More specific about version support
* Moved "Support" section above "Building" and added explanation
* Removed redundant "Commit Guidelines" section
  - It has been totally ignored for years, and it doesn't make much sense to keep it
* Added a new "Contributing" section near the bottom
2018-12-23 17:21:31 +00:00
md678685 f220c5b406 Update Estonian sudoExempt message
Thanks to @Madis0 for [pointing this out and translating it](https://github.com/EssentialsX/Essentials/pull/2228#issuecomment-449586891).
2018-12-22 17:47:39 +00:00
Thomas 9415582fe1 Update messages_nl.properties (#2129) @DutchUser
* Update messages_nl.properties

* Update messages_nl.properties

* Update messages_nl.properties

* Update messages_nl.properties

* Update messages_nl.properties
2018-12-22 17:42:42 +00:00
Sprungente a5a3630727 [Finish] Improving German localization (#2198) @Sprungente
* Improving 

I found some stuff to improve the translation. I'm not done yet but i think it's ready to get an eye on it. 

Hope it will be used :)

Greets Sprungente/enterih

* mistake^^

^

* Part 2

Adding more Improvements
Hope it helps other serverowners^^

* Part 2 fixes

* Part 3 



Notice for me 
a-d finished
\u00f6 ö    \u00e4 ä  \u00fc ü

* Part 4

Notice for me 
a-i finished
\u00f6 ö    \u00e4 ä  \u00fc ü

* Last part 

is line 456
requiredBukkit=\u00a76* \! * Du brauchst mindestens CraftBukkit Build \#{0}, lade es von http\://dl.bukkit.org/downloads/craftbukkit/
still exist? If yes, could a reference to spigot be added?

It's ready to merge. Can i take care on it in the future?

* small polishing

* Update messages_de.properties

* Update messages_de.properties

* Adding new strings 

added strings from #2278
2018-12-22 17:39:44 +00:00
Madis f4c36d9c43 Estonian translation update (#2228)
* Initial improvements

* Half done

* Almost done

* Translation done

* Encode umlauts

* Additional refinements

* Minor fix

* Some more tweaks

* Minor wording change

* 1.13 strings
2018-12-22 17:36:47 +00: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 492005d00a Fix LegacyItemID method override 2018-12-15 19:11:41 +00:00
md678685 149d9b61cc Add methods to facilitate conversion from IDs to new Materials 2018-12-15 18:54:01 +00:00
md678685 77ffb6a3d5 Slightly simplify FlatItemDb 2018-12-15 18:53:06 +00:00
md678685 d95b632884 Merge branch '2.x' into 1.13 2018-12-11 14:31:42 +00:00
md678685 579f554edb Update nickname again after toggling AFK status 2018-12-11 13:26:15 +00:00
md678685 050287f306 Add 1.13 enchantments
Fixes #2254.
2018-12-11 10:04:38 +00:00
md678685 dafe156212 Merge branch '2.x' into 1.13 2018-12-09 15:25:31 +00:00
md678685 48bf264178 Fix discrepancies between default and EN locale 2018-12-09 15:21:07 +00:00
md678685 769dbe8852 Fix BukkitVersion's toString and equals 2018-12-09 15:16:44 +00:00
md678685 67bccb865a Remove colour codes from serverUnsupported in EN locale 2018-12-09 15:16:18 +00:00
md678685 d1e60de04a Ignore kits.yml created during tests 2018-12-09 15:15:55 +00:00
md678685 89d592ce43 Improve item-spawn-blacklist load logging 2018-12-09 14:58:56 +00:00
md678685 c06dda886d Actually use the force-enable-recipe option from the config 2018-12-09 14:58:36 +00:00
md678685 23d92fac63 Bump version to 2.16.0 and release 2.16-pre1 2018-12-09 14:33:53 +00:00
md678685 5922b85290 Move SHIELD to from MetaItemStack to MaterialUtil 2018-12-09 13:47:52 +00:00
md678685 814e5a643e Add SIGNS and SPAWNER to MaterialUtil 2018-12-09 13:47:22 +00:00
md678685 3db3a272d5 Update default kits.yml file
Item IDs are no longer supported in 1.13+, so remove them from the default kits section.
2018-12-09 13:07:11 +00:00
md678685 2d703fbc80 Add damage value support to FlatItemDb
...in case you wanted to give players broken swords, or something?
2018-12-09 13:04:21 +00:00
md678685 b49d3cc21c Remove unnecessary kits file
This is a leftover from dev environments and is *not* the one copied into the jar during build.
2018-12-09 13:02:44 +00:00
md678685 02b5d2357a Add missing FakeServer methods 2018-12-09 12:29:28 +00:00
md678685 1206178eca Use utility methods in MetaItemStack 2018-12-09 12:17:13 +00:00
md678685 3df3f8a812 Add several cross-version item type checks to MaterialUtil 2018-12-09 12:17:13 +00:00
md678685 7049952b07 Load forceEnableRecipe during Settings.reloadConfig 2018-12-09 12:17:13 +00:00
Mark Vadeika a18ce40921 Hiding display names (#2248) @AllTheMegahertz
Prevents a user's nickname from appearing if they are hidden, if `hide-displayname-in-vanish: true` in the config. Closes #2221.

* Does not return display name if user is hidden

* Added hide-displayname-in-vanish field

* Added hideDisplayNameInVanish()

* Changed to only hide display name if specified in config

* Changed hideDisplayNameInVanish to default to false if not specified in config.yml
2018-12-09 11:02:45 +00:00
md678685 6a6383462d Allow admins to force enable /recipe if they want
Add `force-enable-recipe`, which allows server admins to manually enable `/recipe` despite potential duplication exploits. Use this at your own risk!

Related: #1397
2018-12-08 16:41:24 +00:00
md678685 44301fae4f Fix Worth.setPrice on 1.13+; add Javadocs to Worth 2018-12-08 16:32:09 +00:00
md678685 6ee84510ea Update bStats-Metrics 2018-12-06 17:49:08 +00:00
md678685 6ecdc8d7fc Enu-moo-til 2018-12-06 17:44:22 +00:00
md678685 35a2a4d803 Add several version warning messages 2018-12-06 17:41:32 +00:00
md678685 7b67b3b858 Don't send empty line join/quit messages
GitHub meta: fixes #991 fixes #2289
2018-12-06 14:06:25 +00:00
md678685 4011810536 Correctly use LegacyItemDb after detecting version < 1.13 2018-11-19 22:51:07 +00:00
md678685 85ea07c97e Fix VersionUtil regex matching and BukkitVersion.toString 2018-11-19 22:48:33 +00:00
md678685 41b2449cdd Change /enchant's default level from -1 to 1 2018-11-19 21:11:25 +00:00
md678685 ec83a5fff2 Add EntityPickupItemEvent listener to AntiBuild 2018-11-19 20:20:10 +00:00
md678685 ded6f06ed2 Merge remote-tracking branch 'origin/2.x' into 1.13 2018-11-19 19:48:38 +00:00
md678685 2605e050a0 Deduplicate ItemDb code 2018-11-19 19:41:01 +00:00
md678685 19b1e19e42 Remove extraneous imports 2018-11-19 19:30:35 +00:00
md678685 f7a1149cac Port old ItemDb back 2018-11-19 14:13:05 +00:00
md678685 7dd52dab32 Add non-NMS VersionUtil
*Should* work on Glowstone. TODO: use this instead of ReflUtil where appropriate.
2018-11-19 14:12:10 +00:00
md678685 937aec600a Implement more FakeServer methods 2018-11-19 12:52:19 +00:00
md678685 4802053da6 Rename en-GB to en_GB for consistency 2018-11-19 12:51:26 +00:00
md678685 0105dff7ac Update AntiBuild default entries to enum names 2018-11-19 12:49:34 +00:00
md678685 8cc448efcf Remove meta/durability checks from AntiBuild 2018-11-19 11:38:50 +00:00
md678685 982b358bf8 Bump AntiBuild and Protect to api-version: 1.13 2018-11-19 11:28:31 +00:00
md678685 ffc80d61af Implement missing FakeWorld and OfflinePlayer methods 2018-11-19 11:26:05 +00:00
md678685 f55956612c Add messages_en-GB.properties (#2206)
Tins what it does on the say.
2018-11-19 08:38:37 +00:00
md678685 cd3b342d74 Target Bukkit 1.13.2 2018-10-31 15:00:54 +00:00
md678685 ba959586e2 Merge remote-tracking branch 'games647/java9' into 1.13 2018-10-31 14:53:49 +00:00
md678685 4c07e584b7 Default to max stack size 2018-10-31 14:47:45 +00:00
Banbeucmas 280d1215de Adding EssentialsWarpEvent (#1921) @Banbeucmas
* Adding EssentialsWarpEvent for checking if player is wrapping

* Spacing

* Adding Trade parameter

* Refactoring

* Adding #setWarp() to the Event

* Spacing

* Documenting the purpose of the Event

* Javadoc?
2018-10-28 18:53:52 +00:00
md678685 22538ba7c9 Merge branch '1.13' into 2.x_feature_jail_no_teleport 2018-10-28 18:46:53 +00:00
montlikadani a2a95ed840 Added acacia and dark oak tree types (#2001) @montlikadani
* Update Commandbigtree.java

* Update Commandbigtree.java

* Update Commandtree.java
2018-10-28 18:41:46 +00:00
md678685 4bd9461282 Rename help-.md to help.md 2018-10-28 10:54:01 +00:00
md678685 96adef5269 Update issue templates (#2045)
* Update issue templates

Add new issue templates - I didn't even know GitHub had these now

* Remove duplicate bug template

* Remove duplicate feature template

* Update help-.md

* Update report-a-bug.md

* Update request-a-feature.md

* Delete ISSUE_TEMPLATE.md
2018-10-27 15:42:56 +01:00
md678685 9576ea25a6 Use reflection-based detection for pickup listener in player listener (#2151)
Allows the plugin to start up on Glowstone correctly.

Tested on Spigot 1.12.2, Spigot 1.9.4 and Glowstone 2018.7.0, works correctly on all.
2018-10-27 15:37:29 +01:00
md678685 a7fcafb245 Filter out comment lines when loading items.json 2018-10-27 15:00:04 +01:00
md678685 73bb41d579 Merge branch '1.13-items' into 1.13 2018-10-26 15:59:51 +01:00
md678685 0a90d76493 Remove item IDs from Worth 2018-10-15 13:56:36 +01:00
md678685 010981d3c8 Remove ID-based charges in /repair 2018-10-15 13:51:04 +01:00
md678685 3353061e76 Remove ID-based permission checks in /more 2018-10-15 13:49:16 +01:00
md678685 79bc34047b Allow multiple item names in /clearinventory
Allow a comma-separated list of item names in /clearinventory.
2018-10-15 13:46:12 +01:00
md678685 60c90408e7 Remove ID-based permission checks in /give and /item 2018-10-15 13:16:10 +01:00
md678685 1218c3e226 Merge branch '1.13' into 1.13-items 2018-10-13 18:23:58 +01:00
md678685 a05fc9d08e Remove duplicated OfflinePlayer method 2018-10-13 17:14:10 +01:00
md678685 6906ef2154 Merge branch '1.13' into 1.13-items 2018-10-13 16:59:57 +01:00
md678685 7d25e84ebc Merge branch '2.x' into 1.13 2018-10-13 16:59:44 +01:00
md678685 121d935315 Implement missing FakeServer methods 2018-10-13 16:55:49 +01:00
md678685 2f66a866d8 Implement missing FakeWorld and OfflinePlayer methods 2018-10-13 16:55:42 +01:00
md678685 0e088c17a8 Remove IdProvider dependency 2018-10-13 16:45:20 +01:00
md678685 4cd8a6636b Log invalid JSON entries 2018-10-13 16:44:50 +01:00
md678685 5c7fc763fc Formatting 2018-10-13 16:44:24 +01:00
md678685 1e381a59be Throw meaningful exception when item not found 2018-10-13 16:32:21 +01:00
md678685 85111f25cb Use ItemData#equals when finding item name
Avoids accidentally causing an NPE while comparing potion data.
2018-10-13 16:09:45 +01:00
md678685 f78887a02e Remove item IDs from /itemdb 2018-10-13 15:59:25 +01:00
md678685 feba535637 Actually assign the ManagedFile to file 2018-10-13 15:38:45 +01:00
md678685 3262143c73 Implement missing FakeServer methods 2018-10-13 15:30:27 +01:00
md678685 18feb7967a Implement missing FakeWorld and OfflinePlayer methods 2018-10-13 15:26:58 +01:00
md678685 e9b1511117 Remove item ID support in Worth 2018-10-12 17:26:41 +01:00
md678685 177e5f62f7 Remove providers; move JSON support into ItemDb 2018-10-12 17:26:22 +01:00
md678685 f3f4395da7 Reset BuildTools work directory on Travis 2018-10-09 20:32:40 +01:00
md678685 442e46b012 Return to root after BuildTools on Travis 2018-10-09 20:25:36 +01:00
md678685 37d699d05b mkdir -p in Travis 2018-10-09 19:54:31 +01:00
md678685 77ed1e1d4a Ensure Travis runs BuildTools before mvn install 2018-10-09 19:52:42 +01:00
md678685 50e4cd67b5 Fix typo in Travis config 2018-10-09 19:47:57 +01:00
md678685 83a90eb553 Update .travis.yml 2018-10-09 19:45:28 +01:00
md678685 c29599d39a Create .travis.yml 2018-10-09 19:34:07 +01:00
mathias a9fe842242 Use chat instead of dispatchCommand 2018-09-18 16:39:58 +03:00
md678685 692e0adde4 Use MONSTER_EGG in SpawnEggRefl 2018-09-09 16:37:02 +01:00
md678685 cdba518bae Revert "Implement 1.13 item support (#2153)" 2018-09-09 16:35:20 +01:00
md678685 b70b67fa1f Remove unnecessary CraftBukkit dependency 2018-09-09 16:34:15 +01:00
md678685 ff0ca9bc7b Remove unnecessary CraftBukkit dependency 2018-09-05 19:20:18 +01:00
md678685 320bc25d94 Implement 1.13 item support (#2153)
Uses two distinct providers to support items on 1.13 while falling back to `items.csv` for previous versions of Minecraft.
2018-09-05 14:23:16 +01:00
md678685 425e955b5d Update items.json
Add some more aliases to the file
2018-09-05 14:19:09 +01:00
pop4959 33ae9a2597 Fix TropicalFish spawning (#2159)
The name can't have a space in it or it won't be matched by any commands.
2018-09-05 13:26:33 +01:00
pop4959 19913d3612 Implement abstract method Entity::getFacing in OfflinePlayer (#2157) @pop4959
Allows EssentialsX to compile against the latest Spigot version.

Reference: [https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/8ab814cd5c415258aa0ab7617051ee4ea9f4e7bd](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/8ab814cd5c415258aa0ab7617051ee4ea9f4e7bd)
2018-09-05 11:00:27 +01: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
pop4959 a3eb58724f Add a way to use unsafe nicknames (#2152) @pop4959
Pretty much what the title says. Closes #1630.

This is a fun little feature that I'm sure many people have always wanted. I can understand that the original authors of Essentials were probably concerned about users entering names that cannot display correctly in the chat, and that is understandable.

I have added a new permission "essentials.nick.allowunsafe", which must be given to anyone who is allowed to use characters outside of the alphanumeric set. The name of the permission is inspired from "essentials.enchantments.allowunsafe", which allows unsafe enchantment levels to be applied to items without guaranteed behaviour. Similarly, the permission "essentials.nick.allowunsafe" allows unsafe characters to be entered for the user's nickname without making any guarantee that those characters will show up in chat correctly.
2018-09-02 12:14:26 +01:00
md678685 0afa00779c Add some comments to LegacyItemDbProvider 2018-09-01 19:31:32 +01:00
md678685 17d5545804 Update items.json
Fix incorrect type for Uncraftable Potions
2018-09-01 16:46:55 +01:00
md678685 cd70662f01 Update items.json
Fixes some potions spawning incorrectly where the vanilla name didn't match the Bukkit enum name
2018-09-01 16:27:28 +01:00
md678685 a89c97409b Use potion data when looking up items 2018-09-01 15:48:14 +01:00
md678685 102cb6d949 Merge branch '1.13' into 1.13-items 2018-09-01 10:46:27 +01:00
md678685 6c9c9ad42a Use enum methods throughout plugin for cross-version enum lookups 2018-09-01 10:35:08 +01:00
md678685 acbc96fd55 Add enum utility helpers for Statistic and Material 2018-09-01 10:34:11 +01:00
md678685 ca721c1acb Add V1_13_R2 to ReflUtil 2018-08-27 21:29:30 +01:00
md678685 3bf669c42a ItemDbProvider#resolve returns ItemData
More useful than just returning the Material.
2018-08-27 21:21:06 +01:00
md678685 cdc5f75fcb Remove unnecessary equals method on abstract ItemData 2018-08-27 21:19:36 +01:00
md678685 d74f19970b Strip out legacy ItemDb code, pt 1928371236123897 2018-08-27 21:19:15 +01:00
md678685 2ddde37771 Improve FlatItemData#equals 2018-08-27 21:02:27 +01:00
md678685 c1c422e03d Update items.json 2018-08-27 21:00:57 +01:00
md678685 7608b7d658 Merge branch '1.13' into 1.13-items 2018-08-27 20:01:48 +01:00
md678685 d1d5ae814f Merge branch '2.x' into 1.13 2018-08-27 20:01:01 +01:00
md678685 452fa61717 Change tryProvider test values 2018-08-27 19:58:19 +01:00
md678685 825f697fd2 Update items.json 2018-08-27 19:30:05 +01:00
md678685 4ea71ae88e Implement missing methods in FakeWorld 2018-08-27 14:10:06 +01:00
md678685 bdb32f5878 Bump Bukkit version to 1.13.1 2018-08-27 13:10:15 +01:00
md678685 e3c726b8f6 Log total loaded items on reload 2018-08-27 13:06:27 +01:00
md678685 96c6c7b1ca Add per-provider implementations of ItemData 2018-08-27 11:23:47 +01:00
md678685 634d62f9ef Fix typo in /kickall 2018-08-27 10:30:29 +01:00
md678685 2806156cf4 Add "allow-world-in-broadcastworld" option
Allows players to send broadcasts to a specified world by running `/broadcastworld [world] <message>` if enabled.

This is disabled by default in old configs to avoid confusion between updates.
2018-08-27 10:26:54 +01:00
md678685 e642192461 Kick players in /banip
The four-year-old to-do has finally been done!

Closes #2143.
2018-08-26 22:54:00 +01:00
md678685 959c788f22 Don't kick exempt players when running /kickall 2018-08-26 21:03:17 +01:00
montlikadani cda520589a Revert "Doesn't kick all players if the player has permission (#2145) @montlikadani"
This reverts commit 5c1db129d3.
2018-08-26 20:59:46 +01:00
montlikadani 5c1db129d3 Doesn't kick all players if the player has permission (#2145) @montlikadani
So, if a player has permission (eg, an operator or more), they will not kick them out because of permission.
2018-08-26 20:13:05 +01:00
Leomixer17 c718962426 Update messages_it.properties (#2144) @Leomixer17 2018-08-26 17:07:05 +01:00
Thomas 575a11b645 Updated "createKitSuccess=" (#2133) @DutchUser
* Updated "createKitSuccess="

They have the old one, its now in the "kits.yml" not in "config.yml"

* Update messages_da.properties

* Update messages_de.properties

* Update messages_es.properties

* Update messages_en.properties

* Update messages_et.properties

* Updated "createKitSuccess="

* Updated "createKitSuccess="

* Updated "createKitSuccess=

* Updated "createKitSuccess=

* Updated "createKitSuccess=

* Updated "createKitSuccess=

* Updated "createKitSuccess="

* Updated "createKitSuccess="

* Updated "createKitSuccess="

* Updated "createKitSuccess="

* Updated "createKitSuccess="

* Updated "createKitSuccess="

* Updated "createKitSuccess="

* Updated "createKitSuccess="

* Updated "createKitSuccess="

* Updated "createKitSuccess="

* Update messages_vi.properties

Going add the other later today, 

* invalidItemFlagMeta
* noJailsDefined
* openingDisposal
* socialSpyMsgFormat
* socialSpyMutedPrefix
* tempbanJoin
* whoisUuid

* Update messages_vi.properties

* Update messages_vi.properties @md678685

I have no idea why this whole file is in `\u` codes

* Update messages.properties @md678685
2018-08-26 16:12:13 +01:00
Xeyame f97c5fc1ff Make /realname configurable (#1952) @Xeyame
Closes #1810.

@md678685: I've added colour codes to the `realName` messages by default, which was not originally part of this PR.
2018-08-26 15:39:37 +01:00
montlikadani 81397d98b8 Added editable messages (#2072) @montlikadani
**If it is accepted then I will add it to the other message files.**
2018-08-26 15:17:07 +01:00
Leomixer17 82b2ff0b3f Update messages_it.properties (#2142) @Leomixer17 2018-08-26 15:13:33 +01:00
md678685 05fcb7b1aa Refactor to allow items to be added after first load 2018-08-25 18:38:50 +01:00
md678685 c79db98978 Add more debug logging to Settings (#2140)
Adds debug logging for `getChatFormat` and `getCommandCooldownEntry`, which makes it much easier to track down issues with group formats in EssentialsX Chat and command cooldowns respectively.
2018-08-25 18:09:08 +01:00
md678685 303aa77901 Add missing import 2018-08-25 16:55:12 +01:00
md678685 65a4ef7ee5 Use items that actually exist in tryProvider 2018-08-25 16:54:50 +01:00
md678685 1be7fbd8a6 Remove hash comment when rebuilding JSON database 2018-08-25 16:54:09 +01:00
Max Roncace 935b5cfe0f Fix unbreakable attribute for kits (#2071) @caseif
This PR fixes the `unbreakable` attribute on kit items. Previously, Essentials was exclusively using an internal Spigot method to set this on `ItemMeta` objects; however, this solution seems to be non-functional on more recent Spigot builds (1.12.2).

I have altered the `MetaItemStack#setUnbreakable` method to use the native Bukkit method, available for [some time now](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/d986a3f), by default. Essentials will still use the old solution as a fallback in case of an older Bukkit version which does not have native support for the attribute.
2018-08-25 11:33:17 +01:00
md678685 bad02729db Allow /eco take to subtract a user's exact balance 2018-08-24 15:42:17 +01:00
md678685 80f7ded687 SPECTATOR mode is safe for teleporting everywhere. (#2049)
Teleporting in spectator mode is as safe as creative mode for every target.
2018-08-24 15:24:26 +01:00
Max Lee f569b89d8f Round down balance when converting to double (#2135) 2018-08-21 23:45:58 +01:00
md678685 fec655a29c Implement ItemDbProviders, pt 7
Implement getStack and resolve for FlatItemDbProvider
2018-08-19 23:12:27 +01:00
md678685 610774b0b9 Remove default getStack implementation 2018-08-19 23:11:30 +01:00
md678685 9487665fae Use Bukkit PotionData instead of our own 2018-08-19 23:10:23 +01:00
md678685 d5b43b7162 Include JSON files in jar at build time 2018-08-19 23:09:02 +01:00
md678685 718d9d9d3a Initialise provider and file during first reload 2018-08-19 21:55:29 +01:00
md678685 3705dbdd2b Add items.json
TODO: should we auto-download from the CI on build?
2018-08-19 21:43:53 +01:00
md678685 c37d516980 Use MONSTER_EGG in SpawnEggRefl 2018-08-19 21:16:16 +01:00
md678685 b27a6b5b8e Add additional timer marks 2018-08-19 21:11:51 +01:00
md678685 98809fafd7 Strip out legacy ItemDb code, pt 4 2018-08-19 21:10:54 +01:00
md678685 dd9a0de98d Implement ItemDbProviders, pt 6 2018-08-19 20:58:45 +01:00
md678685 de2298cf0a Strip out legacy ItemDb code, pt 3 2018-08-19 20:58:23 +01:00
md678685 56fb8b06cd Add listNames to abstract ItemDbProvider 2018-08-19 20:55:56 +01:00
md678685 3b1eb683e1 Merge branch 'patch-20' into 2.x @montlikadani 2018-08-19 20:17:32 +01:00
md678685 1029305382 Implement ItemDbProviders, pt 5 2018-08-19 19:23:20 +01:00
md678685 9b39509e88 Misc changes 2018-08-19 18:30:44 +01:00
md678685 9da58dde5c Strip out legacy ItemDb code, pt 2 2018-08-19 18:04:13 +01:00
md678685 e2507d2ff1 Implement ItemDbProviders, pt 4 2018-08-19 18:03:53 +01:00
md678685 b867f121c9 Implement ItemDbProviders, pt 3 2018-08-19 17:49:34 +01:00
montlikadani 3c6a869336 Fix iron armor bug (#2054) 2018-08-19 16:57:14 +01:00
RikoDEV f357e76980 Small corrections in the Polish translation (#2103) 2018-08-19 16:56:16 +01:00
gb2233 946a1fbb7c Fixed unicode characters in HU locale (#2130) 2018-08-19 16:55:14 +01:00
Oliver Ni 37acdc18f2 Fix Easter egg config typo (#2124) @oliver-ni
Left clicking mobs with a milk bucket turns them into a baby, not right clicking.
2018-08-16 20:24:53 +01:00
Ali Moghnieh 4dc1d2c50e Merge branch '2.x' into 1.13 2018-08-16 17:47:37 +01:00
Aerodog ed72d117a5 Add {ONLINE} variable to custom join message (#2043) 2018-08-16 17:42:14 +01:00
md678685 a302913130 Clean up unused files 2018-08-15 20:08:22 +01:00
md678685 659f1a271a Merge branch '1.13' into 1.13-items 2018-08-15 19:51:35 +01:00
md678685 3fb4b7958d Strip out legacy ItemDb code, pt 1 2018-08-15 19:50:15 +01:00
md678685 3ef0f20b0d Add tipped arrows support on 1.9/1.10
On a side note, need to investigate why the potion provider is only needed on 1.10 and below - I don't remember what changed in 1.11?
2018-08-15 19:42:12 +01:00
md678685 340baa9703 Add IEssentials#getItemDbProvider method 2018-08-15 19:40:35 +01:00
md678685 0e9232ba81 Remove breaking import 2018-08-15 19:40:08 +01:00
md678685 299afdc6a1 Add V1_13_R1 to ReflUtil 2018-08-15 18:05:44 +01:00
md678685 04feed8524 Add 1.13+ spawn egg provider
Not sure how necessary this is, but I've done it anyway
2018-08-15 17:46:55 +01:00
md678685 773979cb37 Provide ItemDb provider with other providers
Provide providers to the provider that needs the providers. Provider provider provider provide provider.
2018-08-15 16:56:46 +01:00
md678685 c27d05fd4b Fix dependency on IdProvider 2018-08-15 16:40:01 +01:00
md678685 52d814f2cc Properly fix inaccurate playtime measurement
https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/b848d8ce633871b52115247b089029749c02f579
2018-08-15 15:26:11 +01:00
md678685 5009b3b545 Revert "Fix playtime calculation"
This reverts commit 4e165d375c.
2018-08-15 15:15:30 +01:00
md678685 4e165d375c Fix playtime calculation 2018-08-14 19:29:28 +01:00
md678685 306f7a7872 Merge pull request #2119 from lagnat/1.13
Add missing methods for OfflinePlayer, FakeWorld, and FakeServer.
2018-08-14 19:20:21 +01:00
md678685 6c11569ac9 Merge branch '2.x' into 1.13 2018-08-14 18:58:06 +01:00
md678685 4be28ba193 Implement ItemDbProviders, pt 2 2018-08-14 18:57:47 +01:00
Steve Green a1e98f898b Add missing methods for OfflinePlayer, FakeWorld, and FakeServer. 2018-08-14 08:35:33 -04:00
md678685 c5376d3088 Implement ItemDbProviders, pt 1 2018-08-10 22:07:02 +01:00
md678685 3e1857b966 Add module for FlattenedProvider 2018-08-08 15:42:29 +01:00
md678685 b8a8232bc3 Wrap all constructScalar calls with reflection
Allows configs to function with both SnakeYAML 1.19 and 1.21.
2018-08-06 18:19:30 +01:00
md678685 504a7aef0f Add 1.13 mobs 2018-08-06 17:09:50 +01:00
md678685 1ddb1822ef Merge branch '2.x' into 1.13 2018-08-05 23:02:11 +01:00
md678685 d3cd4e356d Add missing OfflinePlayer 1.13 methods 2018-08-05 20:51:39 +01:00
md678685 bef440760a Remove deprecated economy libs and support
None of these economy plugins are supported any more, and removing these allows EssentialsX to be used as a dependency without locally `mvn install`ing the plugin.
2018-08-05 20:51:19 +01:00
Ali Moghnieh 768b92749f update bukkit to 1.13-R0.1-SNAPSHOT.
This commit just fixes compilation errors.
2018-07-29 17:39:32 +01:00
DoNotSpamPls 03b25a0f06 Set target to Java 8 (for 1.13) & update Maven plugins (#1922) @DoNotSpamPls
This is the same PR as the last one (PR #1823), but I messed that one up accidently, sorry for that!
2018-07-17 09:38:01 +01:00
md678685 a44775cafb Prevent users being duplicated in the ignore list
Fixes #2064, as well as alleviating the issue encountered in kangarko/ChatControl-Pro#627 for EssentialsX users.
2018-07-17 07:33:14 +01:00
montlikadani 187c4eb371 Update messages_hu.properties 2018-06-28 18:27:02 +02:00
montlikadani 49201b9945 Update messages_hu.properties 2018-06-28 17:48:27 +02:00
montlikadani 6225dc8ed1 Update messages_hu.properties 2018-06-21 14:39:25 +02:00
Brokkonaut aa622f8d27 SPECTATOR mode is safe for teleporting everywhere. 2018-06-18 23:38:54 +02:00
md678685 849efa9756 Merge branch '2.x' of https://github.com/EssentialsX/Essentials into 2.x-upstream 2018-06-15 19:44:45 +01:00
md678685 8aa764f69f Check whether nick equals "off" before formatting
Fixes #1910.
2018-06-15 19:41:56 +01:00
md678685 de57a8c602 Disable EssProtect emergency mode when Ess loads late (#1954)
Related: EssentialsX/Essentials#1951.
2018-06-15 19:21:18 +01:00
md678685 4873beb100 Allow updating the compass target to be optional (#1937)
If `compass-towards-home-perm` is enabled in the EssentialsX config, then the permission `essentials.home.compass` is checked before changing the player's compass target.

Closes #1918.
2018-06-15 19:20:06 +01:00
md678685 27d9f3725a Wrap constructScalar for SnakeYAML 1.21 (#2040)
In theory, fixes #1974, fixes #1975 and fixes #1976, and also means that
Spigot are free to upgrade SnakeYAML to 1.21 again when ready.
2018-06-15 19:18:55 +01:00
md678685 16b2c3dee3 Reset pending confirmations on login (#2033)
On login, resets any pending confirmations for the user. Fixes #2021,
closes #2023.
2018-06-15 19:09:27 +01:00
BaoKunVN 2ced9469d7 Vietnamese Translation (#1824) @BauKunVN 2018-06-13 21:23:00 +01:00
montlikadani 45c806128a Updated the messages_hu.properties file 2018-05-31 20:23:48 +02:00
md678685 3d60aa1747 Fix build errors (#2018)
Fixes build errors caused by the warp owner PRs (#1961 and #2017)
2018-05-28 12:21:23 -07:00
FlashLight34 967bb44d94 Update IWarps.java (#2017) @FlashLight34
Maybe the compilation fails because that :P
2018-05-27 07:33:37 +01:00
Xeyame 7298393ec9 Add permission to bypass other's msgtoggle (#1955) @Xeyame
* Add permission to bypass other's msgtoggle

Also thanks to MD for helping me with the code :)

* Correct comment

* Remove checking for console in favour of the already existing IUser check

* Fix comments, again

* Re add isIgnoreMsg() check

Accidently removed it, sorry

* Combine 2 checks
2018-05-26 20:43:31 +01:00
FlashLight34 817caf299f setwarp owner uuid in yml file (#1961) @FlashLight34
* Update Warps.java

its not a real change i dont know if user.getuuid() exist or onother possible cmd maybe

* Update Warps.java

* Update Commandsetwarp.java

* Update Warps.java

* Update Warps.java

* Update Commandsetwarp.java

* Update Warps.java

* Update Warps.java

* Update Commandsetwarp.java

* Update Warps.java
2018-05-26 20:42:51 +01:00
montlikadani 2ff29dab80 Update Commanddeljail.java (#2002) @montlikadani
When the user entered a word to delete the jail, deleted it, but removed anything because no jail existed.
2018-05-26 20:40:45 +01:00
Brokkonaut 030eb3375b Block ignite only for PvP, not for PvE (#1967) @Brokkonaut
Players with god mode enabled could not ignite mobs with bows while only igniting players should be blocked.
2018-05-26 20:34:31 +01:00
md678685 3237632eb4 Fix versioning of NMS modules (#1971)
Resolves numerous build errors that emerged in 613e852ffd and for some reason didn't cause a build error on ender.zone, but did everywhere else.

Fixes #1970
2018-05-18 01:23:20 -07:00
Joseph Hirschfeld b29f98c525 [Feature] Add world specific /back dest. perms (#1948) @Ichbinjoe
Adds world specific perms for whether a player may use /back to teleport
back to a given world. Adds logic to default
essentials.back.into.<world> permissions for loaded worlds to true to
maintain backwards compatibility.
2018-04-29 15:49:49 +01: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
md678685 b2a5280971 Avoid build version being overridden by Jenkins (#1936) 2018-03-29 14:19:19 -07:00
games647 c7000846cd Replace Reflection with setter implementation 2018-03-21 11:16:27 +01:00
games647 d24fbc9f55 Remove final modifier to fix illegal reflective access warning
Java 9 runtimes report warnings for reflective access on JRE
classes (in this case Field.modifiers). Future versions of Java
may deny the access completely.

Since we access our own code here, we could just remove the final modifier.
With it's current visibility (of private) it's unlikely that it will be
modified from somewhere else except our Settings class.
2018-03-13 16:46:25 +01:00
games647 7e40d13947 Update lombok and remove antrun to fix compiling with JDK9
* Lombok: Older version resulted in NoSuchFieldEx: pid (fixed since 1.16.8)

* JDK9 no longer has a tools.jar because of it's modular system, but ant is
no longer required. It was introduced in 3e9a2377a8
for GroupManager. Now GM is no longer maintained and removed in
    * 5ca02e6596 (calling the build.xml)
    * fa0bbde236 (removing the remaining module)
2018-03-13 16:06:39 +01: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
Trent Hensler ace361af60 Compile against 1.13 preview.
Still a lot of work to do. One thing to note is that I used LEGACY materials in a few spots where I didn't know what the new ones are as I'm not very familiar with the 1.13 update and what it changes.
2018-01-18 17:52:44 -08: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
Trent Hensler 1a820ad9b7 Initial removal of item IDs.
We do not rely on Bukkit's item ids anymore, though we still support them in commands via a mapping built off of the items.csv.
2017-12-12 22:06:25 -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
288 changed files with 50671 additions and 19559 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
@@ -1,41 +0,0 @@
<!--
Don't put anything inside this block, as it won't be included in the issue.
If you have a question about using EssentialsX, it may be more helpful to ask
in our Discord server: https://discord.gg/F7gexAQ
If you have a feature suggestion for EssentialsX, please delete the template.
Otherwise, if you are reporting a bug, read on:
1. Fill out the template, running the commands either in the console or
as a player. Don't simply put "latest" or we will ignore it.
2. When linking files, do not attach them to the post! Paste them on
https://gist.github.com/, then paste a link to them in the relevant parts
of the template. Avoid using Hastebin or Pastebin, as files are deleted
after a period of time.
3. If you are reporting an issue with lag, please include a timings report.
4. If you are reporting an issue with messages or in-game behaviour, please
include screenshots detailing the problem.
5. Include a description and any other details that may be helpful under the
Details section.
6. Delete this line and all above lines before posting your issue! -->
### Information
Full output of `/ess version`:
Server log (upload `logs/latest.log` to [Gist](https://gist.github.com/)):
EssentialsX config (upload `plugins/Essentials/config.yml` to [Gist](https://gist.github.com/)):
### Details
Describe your issue here.
+45
View File
@@ -0,0 +1,45 @@
---
name: Help!
about: Encountered a problem with EssentialsX? Not sure how to fix it?
---
<!-- EssentialsX help guide
Don't write inside the arrows as they will be hidden when you post your issue.
Want faster support? Come join our Discord server to get help sooner:
https://discord.gg/F7gexAQ
If you're happy to wait (or you were sent here from Discord), read on:
1. Fill out the template.
This will help us understand what problem you've encountered and help us
find a solution.
2. Check the Common Issues page.
Read through the wiki page to see if you've encountered a regular issue:
https://essentialsx.github.io/#/Common-Issues
3. Delete this line and all above lines before posting your issue! -->
### Information
Full output of `/ess version`:
<!-- Replace this with the command output -->
**Server log:** <!-- Upload `logs/latest.log` to https://gist.github.com/ -->
**EssentialsX config** <!-- Upload `plugins/Essentials/config.yml` to https://gist.github.com/ -->
### Help request
**Problem**
<!-- What problem did you encounter? -->
**What I have tried**
<!-- What have you tried so far? -->
**Screenshots**
<!-- If relevant, include any screenshots here. -->
+58
View File
@@ -0,0 +1,58 @@
---
name: Report a bug
about: Report an EssentialsX bug. Only use this if you're 100% sure there's something wrong with EssentialsX - otherwise, try "Help!".
---
<!-- EssentialsX bug reporting guide
Don't put anything inside this block, as it won't be included in the issue.
If you are reporting a bug, please follow the following steps:
1. Fill out the template in full.
Run the commands in the console. Don't just put "latest" as a version,
or we will ignore it.
2. When linking files, do not attach them to the post!
Copy and paste any logs into https://gist.github.com/, then paste a
link to them in the relevant parts of the template. Avoid using
Hastebin or Pastebin, as this makes providing support more difficult.
**DO NOT drag files into this box!**
3. If you are reporting a performance issue, please include a link to a
Timings and/or profiler report.
4. If you are reporting a bug with commands or something else in-game,
please include screenshots to help us diagnose the problem.
5. Make sure not to write between the arrows, as anything there will be
hidden.
6. Delete this line and all above lines before posting your issue! -->
### Information
**Full output of `/ess version`**:
```
<!-- Run the command in your console, and copy and paste the whole output here -->
```
**Server log**: <!-- Upload `logs/latest.log` to https://gist.github.com/, replace this with link -->
**EssentialsX config**: <!-- Upload `plugins/Essentials/config.yml` to https://gist.github.com/, replace this with link -->
### Details
**Description**
<!-- Replace this with a brief summary of the bug. -->
**Steps to reproduce**
<!-- Replace this with exactly what you did to cause the bug. -->
**Expected behavior**
<!-- Replace this with what you expected to happen. -->
**Screenshots**
<!-- Replace this with screenshots, if necessary. -->
@@ -0,0 +1,45 @@
---
name: Request a feature
about: Suggest a feature you want to see in EssentialsX!
---
<!-- EssentialsX feature request guide
Fill out the template. Don't write inside the arrows as they will be hidden
when you post your issue.
Not sure if your feature fits in EssentialsX? Feel free to ask on our Discord
server: https://discord.gg/F7gexAQ
If you have a feature suggestion for EssentialsX, read the following tips:
1. Fill out the template.
This will help us understand what you're requesting and why you want us
to add it.
2. Keep it simple.
Make sure it's easy to understand what you're requesting. A good way is
to keep it to one request per GitHub issue, as we can then easily track
feature requests.
3. Check whether it has already been asked or added.
You can search the issue tracker to see if your feature has already been
requested at https://github.com/EssentialsX/Essentials/issues. You can
also check the wiki at https://essentialsx.github.io/ to see if the
feature was recently added.
4. Ask yourself: "Does this belong in EssentialsX?"
There are lots of features that we reject because most servers won't
need or use them. If your feature is very specific or already exists in
another plugin, it might not be a good fit for EssentialsX.
5. Delete this line and all above lines before posting your issue! -->
### Feature request
**Feature description**
<!-- What feature are you suggesting? -->
**How the feature is useful**
<!-- How is the feature useful to players, server owners and/or developers? -->
+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 -52
View File
@@ -1,52 +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/
*.iml
*.classpath
*.project
*.settings/
target/
dependency-reduced-pom.xml
/Essentials/config.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/
-39
View File
@@ -1,39 +0,0 @@
# EssentialsX new Kit configuration.
# If you don't have any kits defined in this file, the plugin will try to copy them from the config.yml
# Note: All items MUST be followed by a quantity!
# All kit names should be lower case, and will be treated as lower in permissions/costs.
# Syntax: - itemID[:DataValue/Durability] Amount [Enchantment:Level].. [itemmeta:value]...
# For Item Meta information visit http://wiki.ess3.net/wiki/Item_Meta
# 'delay' refers to the cooldown between how often you can use each kit, measured in seconds.
# Set delay to -1 for a one time kit.
# For more information, visit http://wiki.ess3.net/wiki/Kits
kits:
tools:
delay: 10
items:
- 272 1
- 273 1
- 274 1
- 275 1
dtools:
delay: 600
items:
- 278 1 efficiency:1 durability:1 fortune:1 name:&4Gigadrill lore:The_drill_that_&npierces|the_heavens
- 277 1 digspeed:3 name:Dwarf lore:Diggy|Diggy|Hole
- 298 1 color:255,255,255 name:Top_Hat lore:Good_day,_Good_day
- 279:780 1
notch:
delay: 6000
items:
- 397:3 1 player:Notch
color:
delay: 6000
items:
- 387 1 title:&4Book_&9o_&6Colors author:KHobbits lore:Ingame_color_codes book:Colors
firework:
delay: 6000
items:
- 401 1 name:Angry_Creeper color:red fade:green type:creeper power:1
- 401 1 name:Starry_Night color:yellow,orange fade:blue type:star effect:trail,twinkle power:1
- 401 2 name:Solar_Wind color:yellow,orange fade:red shape:large effect:twinkle color:yellow,orange fade:red shape:ball effect:trail color:red,purple fade:pink shape:star effect:trail power:1
+33 -59
View File
@@ -6,25 +6,18 @@
<parent>
<groupId>net.ess3</groupId>
<artifactId>EssentialsXParent</artifactId>
<version>2.15.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>2.3.2</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>1.4</version>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
@@ -41,61 +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>BOSEconomy</groupId>
<artifactId>BOSEconomy</artifactId>
<version>v0.7.8.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/../lib/BOSEconomy.jar</systemPath>
</dependency>
<dependency>
<groupId>iConomy</groupId>
<artifactId>iConomy5</artifactId>
<version>5</version>
<scope>system</scope>
<systemPath>${project.basedir}/../lib/iCo5.jar</systemPath>
</dependency>
<dependency>
<groupId>iConomy</groupId>
<artifactId>iConomy6</artifactId>
<version>6</version>
<scope>system</scope>
<systemPath>${project.basedir}/../lib/iCo6.jar</systemPath>
</dependency>
<dependency>
<groupId>MultiCurrency</groupId>
<artifactId>MultiCurrency</artifactId>
<version>2.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/../lib/MultiCurrency.jar</systemPath>
</dependency>
<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.0.1</version>
<version>2.17.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.ess3</groupId>
<artifactId>UpdatedMetaProvider</artifactId>
<version>2.0.1</version>
<version>2.17.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.ess3</groupId>
<artifactId>1_8_R1Provider</artifactId>
<version>2.0.1</version>
<version>2.17.2</version>
<scope>compile</scope>
<exclusions>
<exclusion>
@@ -107,7 +87,7 @@
<dependency>
<groupId>net.ess3</groupId>
<artifactId>1_8_R2Provider</artifactId>
<version>2.0.1</version>
<version>2.17.2</version>
<scope>compile</scope>
<exclusions>
<exclusion>
@@ -119,26 +99,20 @@
<dependency>
<groupId>net.ess3</groupId>
<artifactId>LegacyProvider</artifactId>
<version>2.0.1</version>
<version>2.17.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.ess3</groupId>
<artifactId>ReflectionProvider</artifactId>
<version>2.0.1</version>
<version>2.17.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.ess3</groupId>
<artifactId>FlattenedProvider</artifactId>
<version>2.17.2</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
</exclusion>
</exclusions>
</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,6 +1,6 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.NumberUtil;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import java.util.HashMap;
@@ -13,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);
@@ -197,14 +198,77 @@ public class Enchantments {
ALIASENCHANTMENTS.put("sweeping", sweeping);
}
} catch (IllegalArgumentException ignored) {}
try { // 1.13
Enchantment loyalty = Enchantment.getByName("LOYALTY");
if (loyalty != null) {
ENCHANTMENTS.put("loyalty", loyalty);
ALIASENCHANTMENTS.put("loyal", loyalty);
ALIASENCHANTMENTS.put("return", loyalty);
}
Enchantment impaling = Enchantment.getByName("IMPALING");
if (impaling != null) {
ENCHANTMENTS.put("impaling", impaling);
ALIASENCHANTMENTS.put("impale", impaling);
ALIASENCHANTMENTS.put("oceandamage", impaling);
ALIASENCHANTMENTS.put("oceandmg", impaling);
}
Enchantment riptide = Enchantment.getByName("RIPTIDE");
if (riptide != null) {
ENCHANTMENTS.put("riptide", riptide);
ALIASENCHANTMENTS.put("rip", riptide);
ALIASENCHANTMENTS.put("tide", riptide);
ALIASENCHANTMENTS.put("launch", riptide);
}
Enchantment channelling = Enchantment.getByName("CHANNELING");
if (channelling != null) {
ENCHANTMENTS.put("channelling", channelling);
ALIASENCHANTMENTS.put("chanelling", channelling);
ALIASENCHANTMENTS.put("channeling", channelling);
ALIASENCHANTMENTS.put("chaneling", channelling);
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;
if (NumberUtil.isInt(name)) {
enchantment = Enchantment.getById(Integer.parseInt(name));
} else {
enchantment = Enchantment.getByName(name.toUpperCase(Locale.ENGLISH));
Enchantment enchantment = null;
if (isFlat) { // 1.13+ only
enchantment = Enchantment.getByKey(NamespacedKey.minecraft(name.toLowerCase()));
}
if (enchantment == null) {
enchantment = Enchantment.getByName(name.toUpperCase());
}
if (enchantment == null) {
enchantment = ENCHANTMENTS.get(name.toLowerCase(Locale.ENGLISH));
@@ -18,6 +18,10 @@
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;
import com.earth2me.essentials.perm.PermissionsHandler;
import com.earth2me.essentials.register.payment.Methods;
@@ -28,26 +32,33 @@ import com.earth2me.essentials.textreader.IText;
import com.earth2me.essentials.textreader.KeywordReplacer;
import com.earth2me.essentials.textreader.SimpleTextInput;
import com.earth2me.essentials.utils.DateUtil;
import com.google.common.base.Function;
import com.earth2me.essentials.utils.VersionUtil;
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;
import net.ess3.nms.flattened.FlatSpawnEggProvider;
import net.ess3.nms.legacy.LegacyPotionMetaProvider;
import net.ess3.nms.legacy.LegacySpawnEggProvider;
import net.ess3.nms.legacy.LegacySpawnerProvider;
import net.ess3.nms.refl.ReflSpawnEggProvider;
import net.ess3.nms.updatedmeta.BasePotionDataProvider;
import net.ess3.nms.updatedmeta.BlockMetaSpawnerProvider;
import net.ess3.nms.legacy.LegacySpawnEggProvider;
import net.ess3.nms.legacy.LegacySpawnerProvider;
import net.ess3.nms.v1_8_R1.v1_8_R1SpawnerProvider;
import net.ess3.nms.v1_8_R2.v1_8_R2SpawnerProvider;
import net.ess3.providers.ProviderFactory;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.block.Block;
@@ -60,6 +71,8 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
@@ -70,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;
@@ -90,7 +95,8 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private transient Worth worth;
private transient List<IConf> confList;
private transient Backup backup;
private transient ItemDb itemDb;
private transient AbstractItemDb itemDb;
private transient CustomItemResolver customItemResolver;
private transient final Methods paymentMethod = new Methods();
private transient PermissionsHandler permissionsHandler;
private transient AlternativeCommandsHandler alternativeCommandsHandler;
@@ -166,6 +172,10 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
Console.setInstance(this);
if (!VersionUtil.isServerSupported()) {
getLogger().severe(tl("serverUnsupported"));
}
final PluginManager pm = getServer().getPluginManager();
for (Plugin plugin : pm.getPlugins()) {
if (plugin.getDescription().getName().startsWith("Essentials") && !plugin.getDescription().getVersion().equals(this.getDescription().getVersion()) && !plugin.getDescription().getName().equals("EssentialsAntiCheat")) {
@@ -186,29 +196,50 @@ 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);
itemDb = new ItemDb(this);
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)");
spawnerProvider = new ProviderFactory<>(getLogger(),
Arrays.asList(
BlockMetaSpawnerProvider.class,
@@ -218,6 +249,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
), "mob spawner").getProvider();
spawnEggProvider = new ProviderFactory<>(getLogger(),
Arrays.asList(
FlatSpawnEggProvider.class,
ReflSpawnEggProvider.class,
LegacySpawnEggProvider.class
), "spawn egg").getProvider();
@@ -226,7 +258,12 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
BasePotionDataProvider.class,
LegacyPotionMetaProvider.class
), "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"));
@@ -246,8 +283,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
Economy.setEss(this);
execTimer.mark("RegHandler");
for (World w : Bukkit.getWorlds())
addDefaultBackPermissionsToWorld(w);
metrics = new Metrics(this);
if (!metrics.isOptOut()) {
if (metrics.isEnabled()) {
getLogger().info("Starting Metrics. Opt-out using the global bStats config.");
} else {
getLogger().info("Metrics disabled per bStats config.");
@@ -441,7 +481,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
return pc.execute(cSender, commandLabel, args);
} catch (final Exception ex) {
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
cSender.sendMessage(ChatColor.RED + "An internal error occurred while attempting to perform this command");
cSender.sendMessage(tl("internalError"));
return true;
}
}
@@ -459,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)});
}
@@ -843,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
@@ -867,6 +903,23 @@ 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();
Permission p = Bukkit.getPluginManager().getPermission(permName);
if (p == null) {
p = new Permission(permName,
"Allows access to /back when the destination location is within world " + w.getName(),
PermissionDefault.TRUE);
Bukkit.getPluginManager().addPermission(p);
}
}
private static class EssentialsWorldListener implements Listener, Runnable {
private transient final IEssentials ess;
@@ -876,6 +929,8 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
@EventHandler(priority = EventPriority.LOW)
public void onWorldLoad(final WorldLoadEvent event) {
addDefaultBackPermissionsToWorld(event.getWorld());
ess.getJails().onReload();
ess.getWarps().reloadConfig();
for (IConf iConf : ((Essentials) ess).confList) {
@@ -901,4 +956,22 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
ess.reload();
}
}
private AbstractItemDb getItemDbFromConfig() {
final String setting = settings.getItemDbType();
if (setting.equalsIgnoreCase("json")) {
return new FlatItemDb(this);
} else if (setting.equalsIgnoreCase("csv")) {
return new LegacyItemDb(this);
} else {
VersionUtil.BukkitVersion version = VersionUtil.getServerBukkitVersion();
if (version.isHigherThanOrEqualTo(VersionUtil.v1_13_0_R01)) {
return new FlatItemDb(this);
} else {
return new LegacyItemDb(this);
}
}
}
}
@@ -1,6 +1,8 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.LocationUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import net.ess3.api.IEssentials;
import org.bukkit.GameMode;
import org.bukkit.Material;
@@ -28,11 +30,12 @@ public class EssentialsBlockListener implements Listener {
// Do not rely on getItemInHand();
// http://leaky.bukkit.org/issues/663
final ItemStack is = LocationUtil.convertBlockToItem(event.getBlockPlaced());
if (is == null) {
return;
}
if (is.getType() == Material.MOB_SPAWNER && event.getItemInHand() != null && event.getPlayer() != null && event.getItemInHand().getType() == Material.MOB_SPAWNER) {
if (is.getType() == MaterialUtil.SPAWNER && event.getItemInHand() != null && event.getPlayer() != null && event.getItemInHand().getType() == MaterialUtil.SPAWNER) {
final BlockState blockState = event.getBlockPlaced().getState();
if (blockState instanceof CreatureSpawner) {
final CreatureSpawner spawner = (CreatureSpawner) blockState;
@@ -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));
}
}
@@ -124,7 +124,7 @@ public class EssentialsEntityListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void onEntityCombustByEntity(final EntityCombustByEntityEvent event) {
if (event.getCombuster() instanceof Arrow) {
if (event.getCombuster() instanceof Arrow && event.getEntity() instanceof Player) {
Arrow combuster = (Arrow) event.getCombuster();
if (combuster.getShooter() instanceof Player) {
final User srcCombuster = ess.getUser(((Player) combuster.getShooter()).getUniqueId());
@@ -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) {
@@ -6,14 +6,11 @@ import com.earth2me.essentials.textreader.TextInput;
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 net.ess3.nms.refl.ReflUtil;
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 (ReflUtil.getNmsVersionObject().isLowerThan(ReflUtil.V1_12_R1)) {
ess.getServer().getPluginManager().registerEvents(new PlayerListenerPre1_12(), ess);
if (isEntityPickupEvent()) {
ess.getServer().getPluginManager().registerEvents(new PickupListener1_12(), ess);
} else {
ess.getServer().getPluginManager().registerEvents(new PlayerListener1_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 {
@@ -138,10 +156,10 @@ public class EssentialsPlayerListener implements Listener {
}
return;
}
final Location afk = user.getAfkPosition();
if (afk == null || !event.getTo().getWorld().equals(afk.getWorld()) || afk.distanceSquared(event.getTo()) > 9) {
user.updateActivityOnMove(true);
}
final Location afk = user.getAfkPosition();
if (afk == null || !event.getTo().getWorld().equals(afk.getWorld()) || afk.distanceSquared(event.getTo()) > 9) {
user.updateActivityOnMove(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
@@ -152,7 +170,12 @@ public class EssentialsPlayerListener implements Listener {
event.setQuitMessage(null);
} else if (ess.getSettings().isCustomQuitMessage() && event.getQuitMessage() != null) {
final Player player = event.getPlayer();
event.setQuitMessage(ess.getSettings().getCustomQuitMessage().replace("{PLAYER}", player.getDisplayName()).replace("{USERNAME}", player.getName()));
final String msg = ess.getSettings().getCustomQuitMessage()
.replace("{PLAYER}", player.getDisplayName())
.replace("{USERNAME}", player.getName())
.replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size()));
event.setQuitMessage(msg.isEmpty() ? null : msg);
}
user.startTransaction();
@@ -176,7 +199,7 @@ public class EssentialsPlayerListener implements Listener {
}
}
user.updateActivityOnInteract(false);
user.updateActivity(false);
if (!user.isHidden()) {
user.setLastLogout(System.currentTimeMillis());
}
@@ -188,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);
}
@@ -214,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 {
@@ -257,9 +276,12 @@ 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()));
ess.getServer().broadcastMessage(msg);
.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);
}
} else if (ess.getSettings().allowSilentJoinQuit()) {
ess.getServer().broadcastMessage(message);
}
@@ -309,6 +331,9 @@ public class EssentialsPlayerListener implements Listener {
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();
user.stopTransaction();
}
@@ -350,7 +375,10 @@ public class EssentialsPlayerListener implements Listener {
}
// Makes the compass item ingame always point to the first essentials home. #EasterEgg
// EssentialsX: This can now optionally require a permission to enable, if set in the config.
private void updateCompass(final User user) {
if (ess.getSettings().isCompassTowardsHomePerm() && !user.isAuthorized("essentials.home.compass")) return;
Location loc = user.getHome(user.getLocation());
if (loc == null) {
loc = user.getBase().getBedSpawnLocation();
@@ -432,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);
}
}
@@ -457,8 +480,7 @@ public class EssentialsPlayerListener implements Listener {
if (spyer.isSocialSpyEnabled() && !player.equals(spyer.getBase())) {
if (user.isMuted() && ess.getSettings().getSocialSpyListenMutedPlayers()) {
spyer.sendMessage(tl("socialSpyMutedPrefix") + player.getDisplayName() + ": " + event.getMessage());
}
else {
} else {
spyer.sendMessage(tl("socialSpyPrefix") + player.getDisplayName() + ": " + event.getMessage());
}
}
@@ -473,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
@@ -492,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
@@ -539,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);
}
@@ -584,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() && event.getClickedBlock().getType() == Material.BED_BLOCK && ess.getSettings().getUpdateBedAtDaytime()) {
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;
@@ -605,13 +632,21 @@ public class EssentialsPlayerListener implements Listener {
case LEFT_CLICK_BLOCK:
if (event.getItem() != null && event.getItem().getType() != Material.AIR) {
final User user = ess.getUser(event.getPlayer());
if (user.hasPowerTools() && user.arePowerToolsEnabled() && usePowertools(user, event.getItem().getTypeId())) {
if (user.hasPowerTools() && user.arePowerToolsEnabled() && usePowertools(user, event.getItem().getType())) {
event.setCancelled(true);
}
}
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
@@ -628,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());
@@ -639,8 +674,8 @@ public class EssentialsPlayerListener implements Listener {
}
}
private boolean usePowertools(final User user, final int id) {
final List<String> commandList = user.getPowertool(id);
private boolean usePowertools(final User user, final Material material) {
final List<String> commandList = user.getPowertool(material);
if (commandList == null || commandList.isEmpty()) {
return false;
}
@@ -658,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));
}
}
@@ -713,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();
@@ -725,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);
}
}
@@ -765,23 +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 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()) {
@@ -791,9 +816,8 @@ 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) {
@@ -803,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) {
@@ -5,6 +5,7 @@ import com.earth2me.essentials.signs.EssentialsSign;
import com.earth2me.essentials.textreader.IText;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.EventPriority;
@@ -14,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;
@@ -95,7 +97,7 @@ public interface ISettings extends IConf {
int getProtectCreeperMaxHeight();
List<Integer> getProtectList(final String configName);
List<Material> getProtectList(final String configName);
boolean getProtectPreventSpawn(final String creatureName);
@@ -133,9 +135,12 @@ public interface ISettings extends IConf {
boolean isEcoDisabled();
@Deprecated
boolean isTradeInStacks(int id);
List<Integer> itemSpawnBlacklist();
boolean isTradeInStacks(Material type);
List<Material> itemSpawnBlacklist();
List<EssentialsSign> enabledSigns();
@@ -181,6 +186,8 @@ public interface ISettings extends IConf {
boolean cancelAfkOnInteract();
boolean sleepIgnoresAfkPlayers();
boolean isAfkListName();
String getAfkListName();
@@ -239,6 +246,8 @@ public interface ISettings extends IConf {
boolean ignoreColorsInMaxLength();
boolean hideDisplayNameInVanish();
int getMaxUserCacheCount();
boolean allowSilentJoinQuit();
@@ -306,4 +315,28 @@ public interface ISettings extends IConf {
List<String> getDefaultEnabledConfirmCommands();
boolean isConfirmCommandEnabledByDefault(String commandName);
boolean isTeleportBackWhenFreedFromJail();
boolean isCompassTowardsHomePerm();
boolean isAllowWorldInBroadcastworld();
String getItemDbType();
boolean isForceEnableRecipe();
boolean allowOldIdSigns();
boolean isWaterSafe();
boolean isSafeUsermap();
boolean logCommandBlockCommands();
Set<Predicate<String>> getNickBlacklist();
double getMaxProjectileSpeed();
boolean isSpawnIfNoHome();
}
@@ -4,6 +4,7 @@ import com.earth2me.essentials.commands.IEssentialsCommand;
import net.ess3.api.ITeleport;
import net.ess3.api.MaxMoneyException;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.math.BigDecimal;
@@ -21,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;
@@ -35,7 +38,7 @@ public interface IUser {
boolean canAfford(BigDecimal value);
Boolean canSpawnItem(final int itemId);
Boolean canSpawnItem(final Material material);
void setLastLocation();
@@ -183,5 +186,9 @@ public interface IUser {
void setPromptingClearConfirm(boolean prompt);
boolean isLastMessageReplyRecipient();
void setLastMessageReplyRecipient(boolean enabled);
Map<User, BigDecimal> getConfirmingPayments();
}
@@ -1,484 +0,0 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import net.ess3.api.IEssentials;
import net.ess3.nms.refl.ReflUtil;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.FireworkEffect;
import org.bukkit.Material;
import org.bukkit.block.Banner;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.*;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
public class ItemDb implements IConf, net.ess3.api.IItemDb {
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<>();
private final transient Map<String, Short> durabilities = new HashMap<>();
private final transient Map<String, String> nbtData = new HashMap<>();
private final transient ManagedFile file;
private final transient Pattern splitPattern = Pattern.compile("((.*)[:+',;.](\\d+))");
private final transient Pattern csvSplitPattern = Pattern.compile("(\"([^\"]*)\"|[^,]*)(,|$)");
public ItemDb(final IEssentials ess) {
this.ess = ess;
file = new ManagedFile("items.csv", ess);
}
@Override
public void reloadConfig() {
final List<String> lines = file.getLines();
if (lines.isEmpty()) {
return;
}
durabilities.clear();
items.clear();
names.clear();
primaryName.clear();
for (String line : lines) {
if (line.length() > 0 && line.charAt(0) == '#') {
continue;
}
String itemName = null;
int numeric = -1;
short data = 0;
String nbt = null;
int col = 0;
Matcher matcher = csvSplitPattern.matcher(line);
while (matcher.find()) {
String match = matcher.group(1);
if (StringUtils.stripToNull(match) == null) {
continue;
}
match = StringUtils.strip(match.trim(), "\"");
switch (col) {
case 0:
itemName = match.toLowerCase(Locale.ENGLISH);
break;
case 1:
numeric = Integer.parseInt(match);
break;
case 2:
data = Short.parseShort(match);
break;
case 3:
nbt = StringUtils.stripToNull(match);
break;
default:
continue;
}
col++;
}
// Invalid row
if (itemName == null || numeric < 0) {
continue;
}
durabilities.put(itemName, data);
items.put(itemName, numeric);
if (nbt != null) {
nbtData.put(itemName, nbt);
}
ItemData itemData = new ItemData(numeric, data);
if (names.containsKey(itemData)) {
List<String> nameList = names.get(itemData);
nameList.add(itemName);
} else {
List<String> nameList = new ArrayList<>();
nameList.add(itemName);
names.put(itemData, nameList);
primaryName.put(itemData, itemName);
}
}
for (List<String> nameList : names.values()) {
Collections.sort(nameList, LengthCompare.INSTANCE);
}
}
@Override
public ItemStack get(final String id, final int quantity) throws Exception {
final ItemStack retval = get(id.toLowerCase(Locale.ENGLISH));
retval.setAmount(quantity);
return retval;
}
@Override
public ItemStack get(final String id) throws Exception {
int itemid = 0;
String itemname;
short metaData = 0;
Matcher parts = splitPattern.matcher(id);
if (parts.matches()) {
itemname = parts.group(2);
metaData = Short.parseShort(parts.group(3));
} else {
itemname = id;
}
if (NumberUtil.isInt(itemname)) {
itemid = Integer.parseInt(itemname);
} else if (NumberUtil.isInt(id)) {
itemid = Integer.parseInt(id);
} else {
itemname = itemname.toLowerCase(Locale.ENGLISH);
}
if (itemid < 1) {
if (items.containsKey(itemname)) {
itemid = items.get(itemname);
if (durabilities.containsKey(itemname) && metaData == 0) {
metaData = durabilities.get(itemname);
}
} else if (Material.getMaterial(itemname.toUpperCase(Locale.ENGLISH)) != null) {
Material bMaterial = Material.getMaterial(itemname.toUpperCase(Locale.ENGLISH));
itemid = bMaterial.getId();
} else {
try {
Material bMaterial = Bukkit.getUnsafe().getMaterialFromInternalName(itemname.toLowerCase(Locale.ENGLISH));
itemid = bMaterial.getId();
} catch (Throwable throwable) {
throw new Exception(tl("unknownItemName", itemname), throwable);
}
}
}
if (itemid < 1) {
throw new Exception(tl("unknownItemName", itemname));
}
final Material mat = Material.getMaterial(itemid);
if (mat == null) {
throw new Exception(tl("unknownItemId", itemid));
}
ItemStack retval = new ItemStack(mat);
if (nbtData.containsKey(itemname)) {
String nbt = nbtData.get(itemname);
if (nbt.startsWith("*")) {
nbt = nbtData.get(nbt.substring(1));
}
retval = ess.getServer().getUnsafe().modifyItemStack(retval, nbt);
}
if (mat == Material.MOB_SPAWNER) {
if (metaData == 0) metaData = EntityType.PIG.getTypeId();
try {
retval = ess.getSpawnerProvider().setEntityType(retval, EntityType.fromId(metaData));
} catch (IllegalArgumentException e) {
throw new Exception("Can't spawn entity ID " + metaData + " from mob spawners.");
}
} else if (mat == Material.MONSTER_EGG) {
EntityType type;
try {
type = EntityType.fromId(metaData);
} catch (IllegalArgumentException e) {
throw new Exception("Can't spawn entity ID " + metaData + " from spawn eggs.");
}
retval = ess.getSpawnEggProvider().createEggItem(type);
} else if (mat.name().endsWith("POTION")
&& ReflUtil.getNmsVersionObject().isLowerThan(ReflUtil.V1_11_R1)) { // Only apply this to pre-1.11 as items.csv might only work in 1.11
retval = ess.getPotionMetaProvider().createPotionItem(mat, metaData);
} else {
retval.setDurability(metaData);
}
retval.setAmount(mat.getMaxStackSize());
return retval;
}
@Override
public List<ItemStack> getMatching(User user, String[] args) throws Exception {
List<ItemStack> is = new ArrayList<>();
if (args.length < 1) {
is.add(user.getItemInHand().clone());
} else if (args[0].equalsIgnoreCase("hand")) {
is.add(user.getItemInHand().clone());
} else if (args[0].equalsIgnoreCase("inventory") || args[0].equalsIgnoreCase("invent") || args[0].equalsIgnoreCase("all")) {
for (ItemStack stack : user.getBase().getInventory().getContents()) {
if (stack == null || stack.getType() == Material.AIR) {
continue;
}
is.add(stack.clone());
}
} else if (args[0].equalsIgnoreCase("blocks")) {
for (ItemStack stack : user.getBase().getInventory().getContents()) {
if (stack == null || stack.getTypeId() > 255 || stack.getType() == Material.AIR) {
continue;
}
is.add(stack.clone());
}
} else {
is.add(get(args[0]));
}
if (is.isEmpty() || is.get(0).getType() == Material.AIR) {
throw new Exception(tl("itemSellAir"));
}
return is;
}
@Override
public String names(ItemStack item) {
ItemData itemData = new ItemData(item.getTypeId(), item.getDurability());
List<String> nameList = names.get(itemData);
if (nameList == null) {
itemData = new ItemData(item.getTypeId(), (short) 0);
nameList = names.get(itemData);
if (nameList == null) {
return null;
}
}
if (nameList.size() > 15) {
nameList = nameList.subList(0, 14);
}
return StringUtil.joinList(", ", nameList);
}
@Override
public String name(ItemStack item) {
ItemData itemData = new ItemData(item.getTypeId(), item.getDurability());
String name = primaryName.get(itemData);
if (name == null) {
itemData = new ItemData(item.getTypeId(), (short) 0);
name = primaryName.get(itemData);
if (name == null) {
return null;
}
}
return name;
}
@Override
public String serialize(ItemStack is) {
String mat = is.getType().name();
if (is.getData().getData() != 0) {
mat = mat + ":" + is.getData().getData();
}
int quantity = is.getAmount();
StringBuilder sb = new StringBuilder(); // Add space AFTER you add something. We can trim at end.
sb.append(mat).append(" ").append(quantity).append(" ");
// ItemMeta applies to anything.
if (is.hasItemMeta()) {
ItemMeta meta = is.getItemMeta();
if (meta.hasDisplayName()) {
sb.append("name:").append(meta.getDisplayName().replaceAll(" ", "_")).append(" ");
}
if (meta.hasLore()) {
sb.append("lore:");
boolean first = true;
for (String s : meta.getLore()) {
// Add | before the line if it's not the first one. Easy but weird way
// to do this since we need each line separated by |
if (!first) {
sb.append("|");
}
first = false;
sb.append(s.replaceAll(" ", "_"));
}
sb.append(" ");
}
if (meta.hasEnchants()) {
for (Enchantment e : meta.getEnchants().keySet()) {
sb.append(e.getName().toLowerCase()).append(":").append(meta.getEnchantLevel(e)).append(" ");
}
}
Set<ItemFlag> flags = meta.getItemFlags();
if (flags != null && !flags.isEmpty()) {
sb.append("itemflags:");
boolean first = true;
for (ItemFlag flag : flags) {
if (!first) {
sb.append(",");
}
sb.append(flag.name());
first = false;
}
}
}
switch (is.getType()) {
case WRITTEN_BOOK:
// Everything from http://wiki.ess3.net/wiki/Item_Meta#Books in that order.
// Interesting as I didn't see a way to do pages or chapters.
BookMeta bookMeta = (BookMeta) is.getItemMeta();
if (bookMeta.hasTitle()) {
sb.append("title:").append(bookMeta.getTitle()).append(" ");
}
if (bookMeta.hasAuthor()) {
sb.append("author:").append(bookMeta.getAuthor()).append(" ");
}
// Only other thing it could have is lore but that's done up there ^^^
break;
case ENCHANTED_BOOK:
EnchantmentStorageMeta enchantmentStorageMeta = (EnchantmentStorageMeta) is.getItemMeta();
for (Enchantment e : enchantmentStorageMeta.getStoredEnchants().keySet()) {
sb.append(e.getName().toLowerCase()).append(":").append(enchantmentStorageMeta.getStoredEnchantLevel(e)).append(" ");
}
break;
case FIREWORK:
// Everything from http://wiki.ess3.net/wiki/Item_Meta#Fireworks in that order.
FireworkMeta fireworkMeta = (FireworkMeta) is.getItemMeta();
if (fireworkMeta.hasEffects()) {
for (FireworkEffect effect : fireworkMeta.getEffects()) {
if (effect.getColors() != null && !effect.getColors().isEmpty()) {
sb.append("color:");
boolean first = true;
for (Color c : effect.getColors()) {
if (!first) {
sb.append(","); // same thing as above.
}
sb.append(c.toString());
first = false;
}
sb.append(" ");
}
sb.append("shape: ").append(effect.getType().name()).append(" ");
if (effect.getFadeColors() != null && !effect.getFadeColors().isEmpty()) {
sb.append("fade:");
boolean first = true;
for (Color c : effect.getFadeColors()) {
if (!first) {
sb.append(","); // same thing as above.
}
sb.append(c.toString());
first = false;
}
sb.append(" ");
}
}
sb.append("power: ").append(fireworkMeta.getPower()).append(" ");
}
break;
case POTION:
Potion potion = Potion.fromItemStack(is);
for (PotionEffect e : potion.getEffects()) {
// long but needs to be effect:speed power:2 duration:120 in that order.
sb.append("splash:").append(potion.isSplash()).append(" ").append("effect:").append(e.getType().getName().toLowerCase()).append(" ").append("power:").append(e.getAmplifier()).append(" ").append("duration:").append(e.getDuration() / 20).append(" ");
}
break;
case SKULL_ITEM:
// item stack with meta
SkullMeta skullMeta = (SkullMeta) is.getItemMeta();
if (skullMeta != null && skullMeta.hasOwner()) {
sb.append("player:").append(skullMeta.getOwner()).append(" ");
}
break;
case LEATHER_HELMET:
case LEATHER_CHESTPLATE:
case LEATHER_LEGGINGS:
case LEATHER_BOOTS:
LeatherArmorMeta leatherArmorMeta = (LeatherArmorMeta) is.getItemMeta();
int rgb = leatherArmorMeta.getColor().asRGB();
sb.append("color:").append(rgb).append(" ");
break;
case BANNER:
BannerMeta bannerMeta = (BannerMeta) is.getItemMeta();
if (bannerMeta != null) {
int basecolor = bannerMeta.getBaseColor().getColor().asRGB();
sb.append("basecolor:").append(basecolor).append(" ");
for (org.bukkit.block.banner.Pattern p : bannerMeta.getPatterns()) {
String type = p.getPattern().getIdentifier();
int color = p.getColor().getColor().asRGB();
sb.append(type).append(",").append(color).append(" ");
}
}
break;
case SHIELD:
// Hacky fix for accessing Shield meta - https://github.com/drtshock/Essentials/pull/745#issuecomment-234843795
BlockStateMeta shieldMeta = (BlockStateMeta) is.getItemMeta();
Banner shieldBannerMeta = (Banner) shieldMeta.getBlockState();
int basecolor = shieldBannerMeta.getBaseColor().getColor().asRGB();
sb.append("basecolor:").append(basecolor).append(" ");
for (org.bukkit.block.banner.Pattern p : shieldBannerMeta.getPatterns()) {
String type = p.getPattern().getIdentifier();
int color = p.getColor().getColor().asRGB();
sb.append(type).append(",").append(color).append(" ");
}
break;
}
return sb.toString().trim().replaceAll("§", "&");
}
@Override
public Collection<String> listNames() {
return primaryName.values();
}
static class ItemData {
final private int itemNo;
final private short itemData;
ItemData(final int itemNo, final short itemData) {
this.itemNo = itemNo;
this.itemData = itemData;
}
public int getItemNo() {
return itemNo;
}
public short getItemData() {
return itemData;
}
@Override
public int hashCode() {
return (31 * itemNo) ^ itemData;
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (!(o instanceof ItemData)) {
return false;
}
ItemData pairo = (ItemData) o;
return this.itemNo == pairo.getItemNo() && this.itemData == pairo.getItemData();
}
}
static class LengthCompare implements java.util.Comparator<String> {
private static final LengthCompare INSTANCE = new LengthCompare();
public LengthCompare() {
super();
}
@Override
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
}
}
@@ -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);
}
}
}
@@ -3,13 +3,17 @@ package com.earth2me.essentials;
import com.earth2me.essentials.textreader.BookInput;
import com.earth2me.essentials.textreader.BookPager;
import com.earth2me.essentials.textreader.IText;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
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;
@@ -24,17 +28,12 @@ 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;
public class MetaItemStack {
private static final Map<String, DyeColor> colorMap = new HashMap<String, DyeColor>();
private static final Map<String, FireworkEffect.Type> fireworkShape = new HashMap<String, FireworkEffect.Type>();
private static final Map<String, DyeColor> colorMap = new HashMap<>();
private static final Map<String, FireworkEffect.Type> fireworkShape = new HashMap<>();
static {
for (DyeColor color : DyeColor.values()) {
@@ -97,10 +96,6 @@ public class MetaItemStack {
completePotion = true;
}
private boolean isPotion(Material type) {
return type.name().endsWith("POTION");
}
public boolean canSpawn(final IEssentials ess) {
try {
ess.getServer().getUnsafe().modifyItemStack(stack.clone(), "{}");
@@ -158,16 +153,7 @@ public class MetaItemStack {
return;
}
Material banner = null;
Material shield = null;
try {
// 1.8
banner = Material.valueOf("BANNER");
// 1.9
shield = Material.valueOf("SHIELD");
} catch(IllegalArgumentException ignored){}
Material WRITTEN_BOOK = EnumUtil.getMaterial("WRITTEN_BOOK");
if (split.length > 1 && split[0].equalsIgnoreCase("name") && hasMetaPermission(sender, "name", false, true, ess)) {
final String displayName = FormatUtil.replaceFormat(split[1].replace('_', ' '));
@@ -176,25 +162,23 @@ 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);
stack.setItemMeta(meta);
} else if (split[0].equalsIgnoreCase("unbreakable") && hasMetaPermission(sender, "unbreakable", false, true, ess)) {
boolean value = split.length > 1 ? Boolean.valueOf(split[1]) : true;
boolean value = split.length > 1 ? Boolean.valueOf(split[1]) : true;
setUnbreakable(stack, value);
} else if (split.length > 1 && (split[0].equalsIgnoreCase("player") || split[0].equalsIgnoreCase("owner")) && stack.getType() == Material.SKULL_ITEM && hasMetaPermission(sender, "head", false, true, ess)) {
if (stack.getDurability() == 3) {
} 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.setOwner(owner);
stack.setItemMeta(meta);
setSkullOwner(ess, stack, owner);
} else {
throw new Exception(tl("onlyPlayerSkulls"));
}
} else if (split.length > 1 && split[0].equalsIgnoreCase("book") && stack.getType() == Material.WRITTEN_BOOK && (hasMetaPermission(sender, "book", true, true, ess) || hasMetaPermission(sender, "chapter-" + split[1].toLowerCase(Locale.ENGLISH), true, true, ess))) {
} else if (split.length > 1 && split[0].equalsIgnoreCase("book") && stack.getType() == WRITTEN_BOOK && (hasMetaPermission(sender, "book", true, true, ess) || hasMetaPermission(sender, "chapter-" + split[1].toLowerCase(Locale.ENGLISH), true, true, ess))) {
final BookMeta meta = (BookMeta) stack.getItemMeta();
final IText input = new BookInput("book", true, ess);
final BookPager pager = new BookPager(input);
@@ -202,42 +186,48 @@ public class MetaItemStack {
List<String> pages = pager.getPages(split[1]);
meta.setPages(pages);
stack.setItemMeta(meta);
} else if (split.length > 1 && split[0].equalsIgnoreCase("author") && stack.getType() == Material.WRITTEN_BOOK && hasMetaPermission(sender, "author", false, true, ess)) {
} else if (split.length > 1 && split[0].equalsIgnoreCase("author") && stack.getType() == WRITTEN_BOOK && hasMetaPermission(sender, "author", false, true, ess)) {
final String author = FormatUtil.replaceFormat(split[1]);
final BookMeta meta = (BookMeta) stack.getItemMeta();
meta.setAuthor(author);
stack.setItemMeta(meta);
} else if (split.length > 1 && split[0].equalsIgnoreCase("title") && stack.getType() == Material.WRITTEN_BOOK && hasMetaPermission(sender, "title", false, true, ess)) {
} else if (split.length > 1 && split[0].equalsIgnoreCase("title") && stack.getType() == WRITTEN_BOOK && hasMetaPermission(sender, "title", false, true, ess)) {
final String title = FormatUtil.replaceFormat(split[1].replace('_', ' '));
final BookMeta meta = (BookMeta) stack.getItemMeta();
meta.setTitle(title);
stack.setItemMeta(meta);
} else if (split.length > 1 && split[0].equalsIgnoreCase("power") && stack.getType() == Material.FIREWORK && hasMetaPermission(sender, "firework-power", false, true, ess)) {
} else if (split.length > 1 && split[0].equalsIgnoreCase("power") && (MaterialUtil.isFirework(stack.getType()))&& hasMetaPermission(sender, "firework-power", false, true, ess)) {
final int power = NumberUtil.isInt(split[1]) ? Integer.parseInt(split[1]) : 0;
final FireworkMeta meta = (FireworkMeta) stack.getItemMeta();
meta.setPower(power > 3 ? 4 : power);
stack.setItemMeta(meta);
} else if (split.length > 1 && split[0].equalsIgnoreCase("itemflags") && hasMetaPermission(sender, "itemflags", false, true, ess)) {
addItemFlags(string);
} else if (stack.getType() == Material.FIREWORK) {//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 (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 (banner != null && stack.getType() == banner) { //WARNING - Meta for banners will be ignored after this point.
addBannerMeta(sender, false, string, ess);
} else if (shield != null && stack.getType() == shield) { //WARNING - Meta for shields will be ignored after this point.
addBannerMeta(sender, false, string, ess);
} else if (split.length > 1 && (split[0].equalsIgnoreCase("color") || split[0].equalsIgnoreCase("colour")) && (stack.getType() == Material.LEATHER_BOOTS || stack.getType() == Material.LEATHER_CHESTPLATE || stack.getType() == Material.LEATHER_HELMET || stack.getType() == Material.LEATHER_LEGGINGS)) {
} else if (MaterialUtil.isBanner(stack.getType())) {
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("#"))) { // int rgb and hex
if (color.length == 1 && (NumberUtil.isInt(color[0]) || color[0].startsWith("#"))) {
// Either integer or hexadecimal
final LeatherArmorMeta meta = (LeatherArmorMeta) stack.getItemMeta();
String input = color[0];
if(input.startsWith("#")) {
if (input.startsWith("#")) { // Hex
meta.setColor(Color.fromRGB(
Integer.valueOf(input.substring(1, 3), 16),
Integer.valueOf(input.substring(3, 5), 16),
Integer.valueOf(input.substring(5, 7), 16)));
} else {
} else { // Int
meta.setColor(Color.fromRGB(Integer.parseInt(input)));
}
stack.setItemMeta(meta);
@@ -281,7 +271,7 @@ public class MetaItemStack {
}
public void addFireworkMeta(final CommandSource sender, final boolean allowShortName, final String string, final IEssentials ess) throws Exception {
if (stack.getType() == Material.FIREWORK) {
if (MaterialUtil.isFirework(stack.getType())) {
final String[] split = splitPattern.split(string, 2);
if (split.length < 2) {
return;
@@ -353,7 +343,7 @@ public class MetaItemStack {
}
public void addPotionMeta(final CommandSource sender, final boolean allowShortName, final String string, final IEssentials ess) throws Exception {
if (isPotion(stack.getType())) {
if (MaterialUtil.isPotion(stack.getType())) {
final String[] split = splitPattern.split(string, 2);
if (split.length < 2) {
@@ -482,13 +472,13 @@ public class MetaItemStack {
}
public void addBannerMeta(final CommandSource sender, final boolean allowShortName, final String string, final IEssentials ess) throws Exception {
if (stack.getType() == Material.BANNER && string != null) {
if (MaterialUtil.isBanner(stack.getType()) && !stack.getType().toString().equals("SHIELD") && string != null) {
final String[] split = splitPattern.split(string, 2);
if (split.length < 2) {
throw new Exception(tl("invalidBanner", split[1]));
}
PatternType patternType = null;
try {
patternType = PatternType.valueOf(split[0]);
@@ -506,7 +496,7 @@ public class MetaItemStack {
}
stack.setItemMeta(meta);
} else if (stack.getType() == Material.SHIELD && string != null) {
} else if (stack.getType().toString().equals("SHIELD") && string != null) {
final String[] split = splitPattern.split(string, 2);
if (split.length < 2) {
@@ -554,25 +544,59 @@ public class MetaItemStack {
}
}
private static int bukkitUnbreakableSupport = -1;
private static Method spigotMethod;
private static Method setUnbreakableMethod;
private void setUnbreakable(ItemStack is, boolean unbreakable) {
ItemMeta meta = is.getItemMeta();
try {
if (spigotMethod == null) {
spigotMethod = meta.getClass().getDeclaredMethod("spigot");
spigotMethod.setAccessible(true);
if (bukkitUnbreakableSupport == -1) {
try {
ItemMeta.class.getDeclaredMethod("setUnbreakable", boolean.class);
bukkitUnbreakableSupport = 1;
} catch (NoSuchMethodException | SecurityException ex) {
bukkitUnbreakableSupport = 0;
}
}
Object itemStackSpigot = spigotMethod.invoke(meta);
if (setUnbreakableMethod == null) {
setUnbreakableMethod = itemStackSpigot.getClass().getDeclaredMethod("setUnbreakable", Boolean.TYPE);
setUnbreakableMethod.setAccessible(true);
if (bukkitUnbreakableSupport == 1) {
meta.setUnbreakable(unbreakable);
} else {
if (spigotMethod == null) {
spigotMethod = meta.getClass().getDeclaredMethod("spigot");
spigotMethod.setAccessible(true);
}
Object itemStackSpigot = spigotMethod.invoke(meta);
if (setUnbreakableMethod == null) {
setUnbreakableMethod = itemStackSpigot.getClass().getDeclaredMethod("setUnbreakable", Boolean.TYPE);
setUnbreakableMethod.setAccessible(true);
}
setUnbreakableMethod.invoke(itemStackSpigot, unbreakable);
}
setUnbreakableMethod.invoke(itemStackSpigot, unbreakable);
is.setItemMeta(meta);
} catch (Throwable t) {
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);
}
}
@@ -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;
@@ -75,6 +75,22 @@ public enum Mob {
HUSK("Husk", Enemies.ENEMY, "HUSK"),
ILLUSIONER("Illusioner", Enemies.ENEMY, "ILLUSIONER"),
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"),
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");
@@ -92,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();
}
}
}
@@ -1,6 +1,7 @@
package com.earth2me.essentials;
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.StringUtil;
import org.bukkit.DyeColor;
import org.bukkit.Material;
@@ -16,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),
@@ -53,25 +56,31 @@ public enum MobData {
BAY_HORSE("bay", EntityType.HORSE, Horse.Color.BROWN, true),
BROWN_HORSE("brown", EntityType.HORSE, Horse.Color.BROWN, false),
SADDLE_HORSE("saddle", EntityType.HORSE, Data.HORSESADDLE, true),
GOLD_ARMOR_HORSE("goldarmor", EntityType.HORSE, Material.GOLD_BARDING, true),
DIAMOND_ARMOR_HORSE("diamondarmor", EntityType.HORSE, Material.DIAMOND_BARDING, true),
ARMOR_HORSE("armor", EntityType.HORSE, Material.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),
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", 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),
GOLD_SWORD_ZOMBIE("goldsword", EntityType.ZOMBIE.getEntityClass(), Material.GOLD_SWORD, true),
GOLD_SWORD_ZOMBIE("goldsword", EntityType.ZOMBIE.getEntityClass(), EnumUtil.getMaterial("GOLDEN_SWORD", "GOLD_SWORD"), true),
IRON_SWORD_ZOMBIE("ironsword", EntityType.ZOMBIE.getEntityClass(), Material.IRON_SWORD, true),
STONE_SWORD_ZOMBIE("stonesword", EntityType.ZOMBIE.getEntityClass(), Material.STONE_SWORD, false),
SWORD_ZOMBIE("sword", EntityType.ZOMBIE.getEntityClass(), Material.STONE_SWORD, true),
DIAMOND_SWORD_SKELETON("diamondsword", EntityType.SKELETON, Material.DIAMOND_SWORD, true),
GOLD_SWORD_SKELETON("goldsword", EntityType.SKELETON, Material.GOLD_SWORD, true),
GOLD_SWORD_SKELETON("goldsword", EntityType.SKELETON, EnumUtil.getMaterial("GOLDEN_SWORD", "GOLD_SWORD"), true),
IRON_SWORD_SKELETON("ironsword", EntityType.SKELETON, Material.IRON_SWORD, true),
STONE_SWORD_SKELETON("stonesword", EntityType.SKELETON, Material.STONE_SWORD, false),
SWORD_SKELETON("sword", EntityType.SKELETON, Material.STONE_SWORD, true),
@@ -82,19 +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),
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)
;
@@ -114,6 +173,8 @@ public enum MobData {
SIZE
}
public static final Logger logger = Logger.getLogger("Essentials");
MobData(String n, Object type, Object value, boolean isPublic) {
@@ -144,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);
}
}
@@ -237,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);
@@ -250,8 +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 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());
}
}
}
@@ -8,10 +8,13 @@ import org.bukkit.advancement.AdvancementProgress;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.PistonMoveReaction;
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.*;
@@ -21,10 +24,13 @@ 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;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.RayTraceResult;
import org.bukkit.util.Vector;
import java.lang.reflect.InvocationTargetException;
@@ -104,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;
@@ -129,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
@@ -145,6 +169,15 @@ public class OfflinePlayer implements Player {
return -1;
}
public BlockFace getFacing() {
return null;
}
@Override
public Pose getPose() {
return null;
}
@Override
public boolean performCommand(String string) {
return false;
@@ -200,24 +233,34 @@ public class OfflinePlayer implements Player {
return Collections.emptyList();
}
@Override
public Block getTargetBlock(HashSet<Byte> hs, int i) {
return null;
}
@Override
public Block getTargetBlock(Set<Material> mat, int i) {
return null;
}
@Override
public List<Block> getLastTwoTargetBlocks(HashSet<Byte> hs, int i) {
public List<Block> getLastTwoTargetBlocks(Set<Material> mat, int i) {
return Collections.emptyList();
}
@Override
public List<Block> getLastTwoTargetBlocks(Set<Material> mat, int i) {
return Collections.emptyList();
public Block getTargetBlockExact(int maxDistance) {
return null;
}
@Override
public Block getTargetBlockExact(int maxDistance, FluidCollisionMode fluidCollisionMode) {
return null;
}
@Override
public RayTraceResult rayTraceBlocks(double maxDistance) {
return null;
}
@Override
public RayTraceResult rayTraceBlocks(double maxDistance, FluidCollisionMode fluidCollisionMode) {
return null;
}
@Override
@@ -243,6 +286,15 @@ public class OfflinePlayer implements Player {
return server;
}
@Override
public boolean isPersistent() {
return false;
}
@Override
public void setPersistent(boolean persistent) {
}
public Vector getMomentum() {
return getVelocity();
}
@@ -384,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) {
}
@@ -481,7 +520,8 @@ public class OfflinePlayer implements Player {
}
@Override
public void sendBlockChange(Location lctn, int i, byte b) {
public void sendBlockChange(Location loc, BlockData block) {
}
@Override
@@ -613,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;
@@ -653,6 +701,31 @@ public class OfflinePlayer implements Player {
public void setPlayerListName(String name) {
}
@Override
public String getPlayerListHeader() {
return null;
}
@Override
public String getPlayerListFooter() {
return null;
}
@Override
public void setPlayerListHeader(String header) {
}
@Override
public void setPlayerListFooter(String footer) {
}
@Override
public void setPlayerListHeaderFooter(String header, String footer) {
}
@Override
public String getPlayerListName() {
return name;
@@ -734,6 +807,21 @@ public class OfflinePlayer implements Player {
public void setBedSpawnLocation(Location lctn, boolean force) {
}
@Override
public boolean sleep(Location location, boolean force) {
return false;
}
@Override
public void wakeup(boolean setSpawnLocation) {
}
@Override
public Location getBedLocation() {
return null;
}
@Override
public void playEffect(EntityEffect ee) {
}
@@ -742,10 +830,20 @@ public class OfflinePlayer implements Player {
public void hidePlayer(Player player) {
}
@Override
public void hidePlayer(Plugin plugin, Player player) {
}
@Override
public void showPlayer(Player player) {
}
@Override
public void showPlayer(Plugin plugin, Player player) {
}
@Override
public boolean canSee(Player player) {
return false;
@@ -920,6 +1018,26 @@ public class OfflinePlayer implements Player {
return 0;
}
@Override
public boolean discoverRecipe(NamespacedKey recipe) {
return false;
}
@Override
public int discoverRecipes(Collection<NamespacedKey> recipes) {
return 0;
}
@Override
public boolean undiscoverRecipe(NamespacedKey recipe) {
return false;
}
@Override
public int undiscoverRecipes(Collection<NamespacedKey> recipes) {
return 0;
}
@Override
public boolean hasLineOfSight(Entity entity) {
return false;
@@ -1195,6 +1313,21 @@ public class OfflinePlayer implements Player {
public void setGliding(boolean b) {
}
@Override
public boolean isSwimming() {
return false;
}
@Override
public void setSwimming(boolean swimming) {
}
@Override
public boolean isRiptiding() {
return false;
}
@Override
public void setAI(boolean b) {
}
@@ -1213,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;
@@ -1222,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;
@@ -1412,6 +1560,11 @@ public class OfflinePlayer implements Player {
return null;
}
@Override
public int getClientViewDistance() {
return 0;
}
@Override
public String getLocale() {
return null;
@@ -1459,6 +1612,11 @@ public class OfflinePlayer implements Player {
return 0;
}
@Override
public BoundingBox getBoundingBox() {
return null;
}
@Override
public List<Entity> getPassengers() {
return null;
@@ -1478,4 +1636,17 @@ public class OfflinePlayer implements Player {
public PistonMoveReaction getPistonMoveReaction() {
return null;
}
@Override
public void updateCommands() {
}
@Override
public void openBook(ItemStack book) {
}
@Override
public PersistentDataContainer getPersistentDataContainer() {
return null;
}
}
@@ -11,8 +11,8 @@ import java.util.Set;
public class Potions {
private static final Map<String, PotionEffectType> POTIONS = new HashMap<String, PotionEffectType>();
private static final Map<String, PotionEffectType> ALIASPOTIONS = new HashMap<String, PotionEffectType>();
private static final Map<String, PotionEffectType> POTIONS = new HashMap<>();
private static final Map<String, PotionEffectType> ALIASPOTIONS = new HashMap<>();
static {
@@ -1,43 +1,53 @@
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;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.MemoryConfiguration;
import org.bukkit.event.EventPriority;
import org.bukkit.inventory.ItemStack;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
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;
private static final Logger logger = Logger.getLogger("Essentials");
private final transient IEssentials ess;
private boolean metricsEnabled = true;
public Settings(IEssentials ess) {
this.ess = ess;
@@ -429,9 +439,13 @@ 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);
}
if (isDebug()) {
ess.getLogger().info(String.format("Found format '%s' for group '%s'", mFormat, group));
}
return mFormat;
}
@@ -491,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();
@@ -533,19 +548,35 @@ 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<Integer> itemSpawnBl = new ArrayList<Integer>();
void _lateLoadItemSpawnBlacklist() {
itemSpawnBl = _getItemSpawnBlacklist();
}
private List<Material> itemSpawnBl = new ArrayList<>();
@Override
public List<Integer> itemSpawnBlacklist() {
public List<Material> itemSpawnBlacklist() {
return itemSpawnBl;
}
private List<Integer> _getItemSpawnBlacklist() {
final List<Integer> epItemSpwn = new ArrayList<Integer>();
if (ess.getItemDb() == null) {
logger.log(Level.FINE, "Aborting ItemSpawnBL read, itemDB not yet loaded.");
private List<Material> _getItemSpawnBlacklist() {
final List<Material> epItemSpwn = new ArrayList<>();
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;
}
for (String itemName : config.getString("item-spawn-blacklist", "").split(",")) {
@@ -554,10 +585,10 @@ public class Settings implements net.ess3.api.ISettings {
continue;
}
try {
final ItemStack iStack = ess.getItemDb().get(itemName);
epItemSpwn.add(iStack.getTypeId());
final ItemStack iStack = itemDb.get(itemName);
epItemSpwn.add(iStack.getType());
} catch (Exception ex) {
logger.log(Level.SEVERE, tl("unknownItemInList", itemName, "item-spawn-blacklist"));
logger.log(Level.SEVERE, tl("unknownItemInList", itemName, "item-spawn-blacklist"), ex);
}
}
return epItemSpwn;
@@ -643,10 +674,17 @@ public class Settings implements net.ess3.api.ISettings {
// #easteregg
@Override
@Deprecated
public boolean isTradeInStacks(int id) {
return config.getBoolean("trade-in-stacks-" + id, false);
}
// #easteregg
@Override
public boolean isTradeInStacks(Material type) {
return config.getBoolean("trade-in-stacks." + type.toString().toLowerCase().replace("_", ""), false);
}
// #easteregg
private boolean economyDisabled = false;
@@ -665,19 +703,27 @@ public class Settings implements net.ess3.api.ISettings {
}
@Override
public List<Integer> getProtectList(final String configName) {
final List<Integer> list = new ArrayList<Integer>();
public List<Material> getProtectList(final String configName) {
final List<Material> list = new ArrayList<>();
for (String itemName : config.getString(configName, "").split(",")) {
itemName = itemName.trim();
if (itemName.isEmpty()) {
continue;
}
ItemStack itemStack;
try {
itemStack = ess.getItemDb().get(itemName);
list.add(itemStack.getTypeId());
} 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;
@@ -865,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;
@@ -1091,6 +1148,11 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("ignore-colors-in-max-nick-length", false);
}
@Override
public boolean hideDisplayNameInVanish() {
return config.getBoolean("hide-displayname-in-vanish", false);
}
private boolean allowSilentJoin;
public boolean _allowSilentJoinQuit() {
@@ -1292,7 +1354,12 @@ public class Settings implements net.ess3.api.ISettings {
if (isCommandCooldownsEnabled()) {
for (Entry<Pattern, Long> entry : this.commandCooldowns.entrySet()) {
// Check if label matches current pattern (command-cooldown in config)
if (entry.getKey().matcher(label).matches()) {
boolean matches = entry.getKey().matcher(label).matches();
if (isDebug()) {
ess.getLogger().info(String.format("Checking command '%s' against cooldown '%s': %s", label, entry.getKey(), matches));
}
if (matches) {
return entry;
}
}
@@ -1334,24 +1401,8 @@ public class Settings implements net.ess3.api.ISettings {
DecimalFormat currencyFormat = new DecimalFormat(currencyFormatString, decimalFormatSymbols);
currencyFormat.setRoundingMode(RoundingMode.FLOOR);
// Updates NumberUtil#PRETTY_FORMAT field so that all of Essentials
// can follow a single format.
try {
Field field = NumberUtil.class.getDeclaredField("PRETTY_FORMAT");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, currencyFormat);
modifiersField.setAccessible(false);
field.setAccessible(false);
} catch (NoSuchFieldException | IllegalAccessException e) {
ess.getLogger().severe("Failed to apply custom currency format: " + e.getMessage());
if (isDebug()) {
e.printStackTrace();
}
}
// Updates NumberUtil#PRETTY_FORMAT field so that all of Essentials can follow a single format.
NumberUtil.internalSetPrettyFormat(currencyFormat);
return currencyFormat;
}
@@ -1439,4 +1490,143 @@ public class Settings implements net.ess3.api.ISettings {
public boolean isConfirmCommandEnabledByDefault(String commandName) {
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() {
return config.getBoolean("compass-towards-home-perm", false);
}
@Override
public boolean isCompassTowardsHomePerm() {
return isCompassTowardsHomePerm;
}
private boolean isAllowWorldInBroadcastworld;
private boolean _isAllowWorldInBroadcastworld() {
return config.getBoolean("allow-world-in-broadcastworld", false);
}
@Override
public boolean isAllowWorldInBroadcastworld() {
return isAllowWorldInBroadcastworld;
}
private String itemDbType; // #EasterEgg - admins can manually switch items provider if they want
private String _getItemDbType() {
return config.getString("item-db-type", "auto");
}
@Override
public String getItemDbType() {
return itemDbType;
}
private boolean forceEnableRecipe; // https://github.com/EssentialsX/Essentials/issues/1397
private boolean _isForceEnableRecipe() {
return config.getBoolean("force-enable-recipe", false);
}
@Override
public boolean isForceEnableRecipe() {
return forceEnableRecipe;
}
private boolean allowOldIdSigns;
private boolean _allowOldIdSigns() {
return config.getBoolean("allow-old-id-signs", false);
}
@Override
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,6 +2,7 @@ package com.earth2me.essentials;
import com.earth2me.essentials.Mob.MobException;
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.LocationUtil;
import com.earth2me.essentials.utils.StringUtil;
import net.ess3.api.IEssentials;
@@ -19,6 +20,13 @@ import static com.earth2me.essentials.I18n.tl;
public class SpawnMob {
private static final Material GOLDEN_HELMET = EnumUtil.getMaterial("GOLDEN_HELMET", "GOLD_HELMET");
private static final Material GOLDEN_CHESTPLATE = EnumUtil.getMaterial("GOLDEN_CHESTPLATE", "GOLD_CHESTPLATE");
private static final Material GOLDEN_LEGGINGS = EnumUtil.getMaterial("GOLDEN_LEGGINGS", "GOLD_LEGGINGS");
private static final Material GOLDEN_BOOTS = EnumUtil.getMaterial("GOLDEN_BOOTS", "GOLD_BOOTS");
private static final Material GOLDEN_SWORD = EnumUtil.getMaterial("GOLDEN_SWORD", "GOLD_SWORD");
public static String mobList(final User user) {
final Set<String> mobList = Mob.getMobList();
final Set<String> availableList = new HashSet<String>();
@@ -191,16 +199,16 @@ public class SpawnMob {
invent.setChestplate(new ItemStack(Material.DIAMOND_CHESTPLATE, 1));
invent.setHelmet(new ItemStack(Material.DIAMOND_HELMET, 1));
} else if (inputData.contains("gold")) {
invent.setBoots(new ItemStack(Material.GOLD_BOOTS, 1));
invent.setLeggings(new ItemStack(Material.GOLD_LEGGINGS, 1));
invent.setChestplate(new ItemStack(Material.GOLD_CHESTPLATE, 1));
invent.setHelmet(new ItemStack(Material.GOLD_HELMET, 1));
invent.setBoots(new ItemStack(GOLDEN_BOOTS, 1));
invent.setLeggings(new ItemStack(GOLDEN_LEGGINGS, 1));
invent.setChestplate(new ItemStack(GOLDEN_CHESTPLATE, 1));
invent.setHelmet(new ItemStack(GOLDEN_HELMET, 1));
} else if (inputData.contains("leather")) {
invent.setBoots(new ItemStack(Material.LEATHER_BOOTS, 1));
invent.setLeggings(new ItemStack(Material.LEATHER_LEGGINGS, 1));
invent.setChestplate(new ItemStack(Material.LEATHER_CHESTPLATE, 1));
invent.setHelmet(new ItemStack(Material.LEATHER_HELMET, 1));
} else {
} else if (inputData.contains("iron")) {
invent.setBoots(new ItemStack(Material.IRON_BOOTS, 1));
invent.setLeggings(new ItemStack(Material.IRON_LEGGINGS, 1));
invent.setChestplate(new ItemStack(Material.IRON_CHESTPLATE, 1));
@@ -228,7 +236,7 @@ public class SpawnMob {
InventoryWorkaround.setItemInMainHand(invent, new ItemStack(Material.BOW, 1));
InventoryWorkaround.setItemInMainHandDropChance(invent, 0.1f);
invent.setBoots(new ItemStack(Material.GOLD_BOOTS, 1));
invent.setBoots(new ItemStack(GOLDEN_BOOTS, 1));
invent.setBootsDropChance(0.0f);
}
@@ -237,10 +245,10 @@ public class SpawnMob {
setVillager(zombie, false);
final EntityEquipment invent = zombie.getEquipment();
InventoryWorkaround.setItemInMainHand(invent, new ItemStack(Material.GOLD_SWORD, 1));
InventoryWorkaround.setItemInMainHand(invent, new ItemStack(GOLDEN_SWORD, 1));
InventoryWorkaround.setItemInMainHandDropChance(invent, 0.1f);
invent.setBoots(new ItemStack(Material.GOLD_BOOTS, 1));
invent.setBoots(new ItemStack(GOLDEN_BOOTS, 1));
invent.setBootsDropChance(0.0f);
}
@@ -249,7 +257,7 @@ public class SpawnMob {
setVillager(zombie, false);
final EntityEquipment invent = zombie.getEquipment();
invent.setBoots(new ItemStack(Material.GOLD_BOOTS, 1));
invent.setBoots(new ItemStack(GOLDEN_BOOTS, 1));
invent.setBootsDropChance(0.0f);
}
@@ -2,8 +2,12 @@ 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;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerRespawnEvent;
@@ -16,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;
@@ -47,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.
@@ -122,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);
}
}
}
@@ -207,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 {
@@ -229,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) {
@@ -247,6 +284,13 @@ public class Teleport implements net.ess3.api.ITeleport {
//The warp function is a wrapper used to teleportPlayer a player to a /warp
@Override
public void warp(IUser teleportee, String warp, Trade chargeFor, TeleportCause cause) throws Exception {
UserWarpEvent event = new UserWarpEvent(teleportee, warp, chargeFor);
Bukkit.getServer().getPluginManager().callEvent(event);
if(event.isCancelled()) {
return;
}
warp = event.getWarp();
Location loc = ess.getWarps().getWarp(warp);
teleportee.sendMessage(tl("warpingTo", warp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
if (!teleportee.equals(teleportOwner)) {
@@ -258,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;
}
@@ -8,6 +8,7 @@ import com.earth2me.essentials.register.payment.Methods;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.events.AfkStatusChangeEvent;
@@ -18,6 +19,7 @@ import net.ess3.nms.refl.ReflUtil;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.ItemStack;
@@ -26,12 +28,7 @@ import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.WeakHashMap;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -100,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) {
@@ -119,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();
@@ -142,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)));
@@ -154,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"));
}
@@ -175,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);
}
@@ -222,8 +254,19 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
@Override
public Boolean canSpawnItem(final int itemId) {
return !ess.getSettings().itemSpawnBlacklist().contains(itemId);
public Boolean canSpawnItem(final Material material) {
if (ess.getSettings().permissionBasedItemSpawn()) {
final String name = material.toString().toLowerCase(Locale.ENGLISH).replace("_", "");
if (isAuthorized("essentials.itemspawn.item-all") || isAuthorized("essentials.itemspawn.item-" + name)) return true;
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01)) {
final int id = material.getId();
if (isAuthorized("essentials.itemspawn.item-" + id)) return true;
}
}
return isAuthorized("essentials.itemspawn.exempt") || !ess.getSettings().itemSpawnBlacklist().contains(material);
}
@Override
@@ -359,7 +402,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
public String getDisplayName() {
return super.getBase().getDisplayName() == null ? super.getBase().getName() : super.getBase().getDisplayName();
return super.getBase().getDisplayName() == null || (ess.getSettings().hideDisplayNameInVanish() && isHidden()) ? super.getBase().getName() : super.getBase().getDisplayName();
}
@Override
@@ -409,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.");
@@ -416,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();
@@ -457,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();
@@ -514,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;
@@ -538,6 +587,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
setMuteTimeout(0);
sendMessage(tl("canTalkAgain"));
setMuted(false);
setMuteReason(null);
return true;
}
}
@@ -871,7 +921,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
* Returns the {@link ItemStack} in the main hand or off-hand. If the main hand is empty then the offhand item is returned - also nullable.
*/
public ItemStack getItemInHand() {
if (ReflUtil.getNmsVersionObject().isLowerThan(ReflUtil.V1_9_R1)) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
return getBase().getInventory().getItemInHand();
} else {
PlayerInventory inventory = getBase().getInventory();
@@ -7,6 +7,7 @@ import net.ess3.api.IEssentials;
import net.ess3.api.InvalidWorldException;
import net.ess3.api.MaxMoneyException;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -16,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;
@@ -73,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();
@@ -92,6 +95,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
acceptingPay = _getAcceptingPay();
confirmPay = _getConfirmPay();
confirmClear = _getConfirmClear();
lastMessageReplyRecipient = _getLastMessageReplyRecipient();
}
private BigDecimal money;
@@ -231,28 +235,44 @@ public abstract class UserData extends PlayerExtension implements IConf {
config.save();
}
private List<Integer> unlimited;
private Set<Material> unlimited;
private List<Integer> _getUnlimited() {
return config.getIntegerList("unlimited");
private Set<Material> _getUnlimited() {
Set<Material> retlist = new HashSet<>();
List<String> configList = config.getStringList("unlimited");
for(String s : configList) {
Material mat = Material.matchMaterial(s);
if(mat != null) {
retlist.add(mat);
}
}
return retlist;
}
public List<Integer> getUnlimited() {
public Set<Material> getUnlimited() {
return unlimited;
}
public boolean hasUnlimited(ItemStack stack) {
return unlimited.contains(stack.getTypeId());
return unlimited.contains(stack.getType());
}
public void setUnlimited(ItemStack stack, boolean state) {
if (unlimited.contains(stack.getTypeId())) {
unlimited.remove(Integer.valueOf(stack.getTypeId()));
}
boolean wasUpdated;
if (state) {
unlimited.add(stack.getTypeId());
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();
}
@@ -262,7 +282,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
if (config.isConfigurationSection("powertools")) {
return config.getConfigurationSection("powertools").getValues(false);
}
return new HashMap<String, Object>();
return new HashMap<>();
}
public void clearAllPowertools() {
@@ -273,19 +293,19 @@ public abstract class UserData extends PlayerExtension implements IConf {
@SuppressWarnings("unchecked")
public List<String> getPowertool(ItemStack stack) {
return (List<String>) powertools.get("" + stack.getTypeId());
return (List<String>) powertools.get(stack.getType().name().toLowerCase(Locale.ENGLISH));
}
@SuppressWarnings("unchecked")
public List<String> getPowertool(int id) {
return (List<String>) powertools.get("" + id);
public List<String> getPowertool(Material material) {
return (List<String>) powertools.get(material.name().toLowerCase(Locale.ENGLISH));
}
public void setPowertool(ItemStack stack, List<String> commandList) {
if (commandList == null || commandList.isEmpty()) {
powertools.remove("" + stack.getTypeId());
powertools.remove(stack.getType().name().toLowerCase(Locale.ENGLISH));
} else {
powertools.put("" + stack.getTypeId(), commandList);
powertools.put(stack.getType().name().toLowerCase(Locale.ENGLISH), commandList);
}
config.setProperty("powertools", powertools);
config.save();
@@ -436,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() {
@@ -467,10 +503,11 @@ public abstract class UserData extends PlayerExtension implements IConf {
}
public void setIgnoredPlayer(IUser user, boolean set) {
final String entry = user.getName().toLowerCase(Locale.ENGLISH);
if (set) {
ignoredPlayers.add(user.getName().toLowerCase(Locale.ENGLISH));
if (!ignoredPlayers.contains(entry)) ignoredPlayers.add(entry);
} else {
ignoredPlayers.remove(user.getName().toLowerCase(Locale.ENGLISH));
ignoredPlayers.remove(entry);
}
setIgnoredPlayers(ignoredPlayers);
}
@@ -492,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);
@@ -511,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() {
@@ -748,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();
}
@@ -803,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;
}
@@ -930,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();
@@ -6,13 +6,11 @@ import net.ess3.api.InvalidNameException;
import net.ess3.api.InvalidWorldException;
import org.bukkit.Location;
import org.bukkit.Server;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tl;
@@ -57,6 +55,11 @@ public class Warps implements IConf, net.ess3.api.IWarps {
@Override
public void setWarp(String name, Location loc) throws Exception {
setWarp(null, name, loc);
}
@Override
public void setWarp(IUser user, String name, Location loc) throws Exception {
String filename = StringUtil.sanitizeFileName(name);
EssentialsConf conf = warpPoints.get(new StringIgnoreCase(name));
if (conf == null) {
@@ -69,13 +72,28 @@ public class Warps implements IConf, net.ess3.api.IWarps {
}
conf.setProperty(null, loc);
conf.setProperty("name", name);
if (user != null) conf.setProperty("lastowner", user.getBase().getUniqueId().toString());
try {
conf.saveWithError();
} catch (IOException ex) {
throw new IOException(tl("invalidWarpName"));
}
}
@Override
public UUID getLastOwner(String warp) throws WarpNotFoundException {
EssentialsConf conf = warpPoints.get(new StringIgnoreCase(warp));
if (conf == null) {
throw new WarpNotFoundException();
}
UUID uuid = null;
try {
uuid = UUID.fromString(conf.getString("lastowner"));
}
catch (Exception ex) {}
return uuid;
}
@Override
public void removeWarp(String name) throws Exception {
EssentialsConf conf = warpPoints.get(new StringIgnoreCase(name));
@@ -1,6 +1,7 @@
package com.earth2me.essentials;
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
import com.earth2me.essentials.utils.VersionUtil;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
@@ -21,57 +22,62 @@ public class Worth implements IConf {
config.load();
}
public BigDecimal getPrice(ItemStack itemStack) {
String itemname = itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
/**
* Get the value of an item stack from the config.
*
* @param ess The Essentials instance.
* @param itemStack The item stack to look up in the config.
* @return The price from the config.
*/
public BigDecimal getPrice(IEssentials ess, ItemStack itemStack) {
BigDecimal result;
//First check for matches with item name
String itemname = itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
// Check for matches with data value from stack
// Note that we always default to BigDecimal.ONE.negate(), equivalent to -1
result = config.getBigDecimal("worth." + itemname + "." + itemStack.getDurability(), BigDecimal.ONE.negate());
// Check for matches with data value 0
if (result.signum() < 0) {
final ConfigurationSection itemNameMatch = config.getConfigurationSection("worth." + itemname);
if (itemNameMatch != null && itemNameMatch.getKeys(false).size() == 1) {
result = config.getBigDecimal("worth." + itemname + ".0", BigDecimal.ONE.negate());
}
}
// Check for matches with data value wildcard
if (result.signum() < 0) {
result = config.getBigDecimal("worth." + itemname + ".*", BigDecimal.ONE.negate());
}
// Check for matches with item name alone
if (result.signum() < 0) {
result = config.getBigDecimal("worth." + itemname, BigDecimal.ONE.negate());
}
//Now we should check for item ID
if (result.signum() < 0) {
result = config.getBigDecimal("worth." + itemStack.getTypeId() + "." + itemStack.getDurability(), BigDecimal.ONE.negate());
}
if (result.signum() < 0) {
final ConfigurationSection itemNumberMatch = config.getConfigurationSection("worth." + itemStack.getTypeId());
if (itemNumberMatch != null && itemNumberMatch.getKeys(false).size() == 1) {
result = config.getBigDecimal("worth." + itemStack.getTypeId() + ".0", BigDecimal.ONE.negate());
}
}
if (result.signum() < 0) {
result = config.getBigDecimal("worth." + itemStack.getTypeId() + ".*", BigDecimal.ONE.negate());
}
if (result.signum() < 0) {
result = config.getBigDecimal("worth." + itemStack.getTypeId(), BigDecimal.ONE.negate());
}
//This is to match the old worth syntax
if (result.signum() < 0) {
result = config.getBigDecimal("worth-" + itemStack.getTypeId(), BigDecimal.ONE.negate());
}
if (result.signum() < 0) {
return null;
}
return result;
}
/**
* Get the amount of items to be sold from a player's inventory.
*
* @param ess The Essentials instance.
* @param user The user attempting to sell the item.
* @param is A stack of the item to search the inventory for.
* @param args The amount to try to sell.
* @param isBulkSell Whether or not to try and bulk sell all items.
* @return The amount of items to sell from the player's inventory.
* @throws Exception Thrown if trying to sell air or an invalid amount.
*/
public int getAmount(IEssentials ess, User user, ItemStack is, String[] args, boolean isBulkSell) throws Exception {
if (is == null || is.getType() == Material.AIR) {
throw new Exception(tl("itemSellAir"));
}
int id = is.getTypeId();
int amount = 0;
if (args.length > 1) {
@@ -86,7 +92,7 @@ public class Worth implements IConf {
}
boolean stack = args.length > 1 && args[1].endsWith("s");
boolean requireStack = ess.getSettings().isTradeInStacks(id);
boolean requireStack = ess.getSettings().isTradeInStacks(is.getType());
if (requireStack && !stack) {
throw new Exception(tl("itemMustBeStacked"));
@@ -123,14 +129,23 @@ public class Worth implements IConf {
return amount;
}
public void setPrice(ItemStack itemStack, double price) {
if (itemStack.getType().getData() == null) {
config.setProperty("worth." + itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", ""), price);
} else {
/**
* Set the price of an item and save it to the config.
*
* @param ess The Essentials instance.
* @param itemStack A stack of the item to save.
* @param price The new price of the item.
*/
public void setPrice(IEssentials ess, ItemStack itemStack, double price) {
String path = "worth." + itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
// Spigot 1.13+ throws an exception if a 1.13+ plugin even *attempts* to do set data.
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01) && itemStack.getType().getData() == null) {
// Bukkit-bug: getDurability still contains the correct value, while getData().getData() is 0.
config.setProperty("worth." + itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "") + "." + itemStack.getDurability(), price);
path = path + "." + itemStack.getDurability();
}
config.removeProperty("worth-" + itemStack.getTypeId());
config.setProperty(path, price);
config.save();
}
@@ -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;
}
/**
@@ -78,7 +97,14 @@ public class Economy {
*/
@Deprecated
public static double getMoney(String name) throws UserDoesNotExistException {
return getMoneyExact(name).doubleValue();
BigDecimal exactAmount = getMoneyExact(name);
double amount = exactAmount.doubleValue();
if (new BigDecimal(amount).compareTo(exactAmount) > 0) {
// closest double is bigger than the exact amount
// -> get the previous double value to not return more money than the user has
amount = Math.nextAfter(amount, Double.NEGATIVE_INFINITY);
}
return amount;
}
public static BigDecimal getMoneyExact(String name) throws UserDoesNotExistException {
@@ -119,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
}
@@ -178,7 +204,7 @@ public class Economy {
* Divides the balance of a user by a value
*
* @param name Name of the user
* @param value The balance is divided by this value
* @param amount The balance is divided by this value
*
* @throws UserDoesNotExistException If a user by that name does not exists
* @throws NoLoanPermittedException If the user is not allowed to have a negative balance
@@ -202,7 +228,7 @@ public class Economy {
* Multiplies the balance of a user by a value
*
* @param name Name of the user
* @param value The balance is multiplied by this value
* @param amount The balance is multiplied by this value
*
* @throws UserDoesNotExistException If a user by that name does not exists
* @throws NoLoanPermittedException If the user is not allowed to have a negative balance
@@ -1,24 +1,168 @@
package com.earth2me.essentials.api;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import net.ess3.api.IEssentials;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
public interface IItemDb {
ItemStack get(final String name, final int quantity) throws Exception;
/**
* Create a stack from the given name with the given quantity.
*
* @param name Item name to look up in the database
* @param quantity Quantity of the item stack
* @return The requested item stack
* @throws Exception if the item stack cannot be created
*/
default ItemStack get(final String name, final int quantity) throws Exception {
final ItemStack stack = get(name.toLowerCase(Locale.ENGLISH));
stack.setAmount(quantity);
return stack;
}
/**
* 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
*/
ItemStack get(final String name) throws Exception;
String names(ItemStack item);
/**
* Get a comma-separated string list of up to 15 aliases for the given stack.
*
* @param item Item stack whose names to find
* @return Comma-separated list of up to 15 item names
*/
default String names(ItemStack item) {
List<String> nameList = nameList(item);
if (nameList.size() > 15) {
nameList = nameList.subList(0, 14);
}
return StringUtil.joinList(", ", nameList);
};
/**
* Get a List of all aliases for the given item stack.
*
* @param item Item stack whose names to find
* @return List of all names
*/
List<String> nameList(ItemStack item);
/**
* Get the primary name for the given item stack.
*
* @param item Item stack whose name to find
* @return Primary name of the item
*/
String name(ItemStack item);
/**
* Get all stacks in a given User's inventory that matches the given arguments.
*
* @param user The user with the player inventory to search
* @param args Either an item name, or one of the following:
* hand (default), inventory/invent/all, blocks
* @return A List of all matching ItemStacks
* @throws Exception if the given args are invalid or no blocks are found
*/
List<ItemStack> getMatching(User user, String[] args) throws Exception;
/**
* Serialise an ItemStack into a format that can be decoded by
* {@link #get(String) get} and
* {@link com.earth2me.essentials.MetaItemStack#parseStringMeta(CommandSource, boolean, String[], int, IEssentials)} MetaItemStack#parseStringMeta}.
* Used to encode items for kits.
*
* @param is Stack to serialise
* @return Serialised stack
*/
String serialize(ItemStack is);
/**
* Return names recognised by the database, intended for tab-completion.
*
* @return Collection of all item names
*/
Collection<String> listNames();
/**
* Get the material matching the given legacy ID. Used for conversion from item IDs to
* modern names.
*
* @param id Legacy ID of material to find
* @return Updated material
*/
@Deprecated
default Material getFromLegacyId(int id) {
return getFromLegacy(id, (byte) 0);
}
/**
* Get the legacy ID for the given material.
*
* @param material Material to look up
* @return Legacy ID of given material
* @throws Exception if the ID cannot be looked up
* @deprecated Item IDs are no longer supported.
*/
@Deprecated
int getLegacyId(Material material) throws Exception;
/**
* Convert colon syntax (eg. "13", "1:5") legacy IDs to Material. Used for conversion from
* item IDs to modern names.
*
* @param item Legacy ID in colon syntax.
* @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;
if (split.length > 1 && NumberUtil.isInt(split[1])) {
damage = Byte.parseByte(split[1]);
}
return getFromLegacy(id, damage);
}
/**
* Convert legacy ID and damage value to Material. Used for conversion from item IDs to
* modern names.
*
* @param id Legacy ID
* @param damage Damage value
* @return Material
*/
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
*
@@ -1,11 +1,13 @@
package com.earth2me.essentials.api;
import com.earth2me.essentials.IConf;
import com.earth2me.essentials.IUser;
import com.earth2me.essentials.commands.WarpNotFoundException;
import org.bukkit.Location;
import java.io.File;
import java.util.Collection;
import java.util.UUID;
public interface IWarps extends IConf {
@@ -54,6 +56,25 @@ public interface IWarps extends IConf {
*/
void setWarp(String name, Location loc) throws Exception;
/**
* Set a warp
*
* @param user - User of warp
* @param name - Name of warp
* @param loc - Location of warp
*
* @throws Exception
*/
void setWarp(IUser user, String name, Location loc) throws Exception;
/**
* Gets Lastowner UUID
*
* @param name - Name of warp
*
* @throws WarpNotFoundException
*/
UUID getLastOwner(String warp) throws WarpNotFoundException;
/**
* Check to see if the file is empty
*
@@ -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"));
@@ -79,6 +75,7 @@ public class Commandafk extends EssentialsCommand {
if (!msg.isEmpty()) {
ess.broadcastMessage(user, msg);
}
user.setDisplayNick(); // Set this again after toggling
}
@Override
@@ -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,16 +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"));
}
if (user.getWorld() != user.getLastLocation().getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + user.getLastLocation().getWorld().getName())) {
throw new Exception(tl("noPerm", "essentials.worlds." + user.getLastLocation().getWorld().getName()));
String lastWorldName = user.getLastLocation().getWorld().getName();
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 (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);
}
}
}
}
@@ -6,6 +6,7 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import org.bukkit.BanList;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.List;
@@ -14,7 +15,6 @@ import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tl;
//TODO: Add kick to online players matching ip ban.
public class Commandbanip extends EssentialsCommand {
public Commandbanip() {
super("banip");
@@ -51,9 +51,17 @@ public class Commandbanip extends EssentialsCommand {
banReason = tl("defaultBanReason");
}
String banDisplay = tl("banFormat", banReason, senderName);
ess.getServer().getBanList(BanList.Type.IP).addBan(ipAddress, banReason, null, senderName);
server.getLogger().log(Level.INFO, tl("playerBanIpAddress", senderName, ipAddress, banReason));
for (Player player : ess.getServer().getOnlinePlayers()) {
if (player.getAddress().getAddress().getHostAddress().equalsIgnoreCase(ipAddress)) {
player.kickPlayer(banDisplay);
}
}
ess.broadcastMessage("essentials.banip.notify", tl("playerBanIpAddress", senderName, ipAddress, banReason));
}
@@ -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);
}
}
@@ -27,6 +27,8 @@ public class Commandbigtree extends EssentialsCommand {
tree = TreeType.BIG_TREE;
} else if (args.length > 0 && args[0].equalsIgnoreCase("jungle")) {
tree = TreeType.JUNGLE;
} else if (args.length > 0 && args[0].equalsIgnoreCase("darkoak")) {
tree = TreeType.DARK_OAK;
} else {
throw new NotEnoughArgumentsException();
}
@@ -44,7 +46,7 @@ public class Commandbigtree extends EssentialsCommand {
@Override
protected List<String> getTabCompleteOptions(Server server, User user, String commandLabel, String[] args) {
if (args.length == 1) {
return Lists.newArrayList("redwood", "tree", "jungle");
return Lists.newArrayList("redwood", "tree", "jungle", "darkoak");
} else {
return Collections.emptyList();
}
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
import com.earth2me.essentials.utils.EnumUtil;
import com.google.common.collect.Lists;
import org.bukkit.Material;
import org.bukkit.Server;
@@ -15,11 +16,13 @@ import static com.earth2me.essentials.I18n.tl;
public class Commandbook extends EssentialsCommand {
private static final Material WRITABLE_BOOK = EnumUtil.getMaterial("WRITABLE_BOOK", "BOOK_AND_QUILL");
public Commandbook() {
super("book");
}
//TODO: Translate this
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final ItemStack item = user.getItemInHand();
@@ -45,7 +48,7 @@ public class Commandbook extends EssentialsCommand {
}
} else {
if (isAuthor(bmeta, player) || user.isAuthorized("essentials.book.others")) {
ItemStack newItem = new ItemStack(Material.BOOK_AND_QUILL, item.getAmount());
ItemStack newItem = new ItemStack(WRITABLE_BOOK, item.getAmount());
newItem.setItemMeta(bmeta);
InventoryWorkaround.setItemInMainHand(user.getBase(), newItem);
user.sendMessage(tl("editBookContents"));
@@ -53,7 +56,7 @@ public class Commandbook extends EssentialsCommand {
throw new Exception(tl("denyBookEdit"));
}
}
} else if (item.getType() == Material.BOOK_AND_QUILL) {
} else if (item.getType() == WRITABLE_BOOK) {
BookMeta bmeta = (BookMeta) item.getItemMeta();
if (!user.isAuthorized("essentials.book.author")) {
bmeta.setAuthor(player);
@@ -27,7 +27,25 @@ public class Commandbroadcastworld extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
sendBroadcast(user.getWorld().getName(), user.getDisplayName(), getFinalArg(args, 0));
World world = user.getWorld();
String message = getFinalArg(args, 0);
if (args.length < 1) {
throw new NotEnoughArgumentsException();
} else if (args.length > 1 && ess.getSettings().isAllowWorldInBroadcastworld()) {
World argWorld = ess.getWorld(args[0]);
if (argWorld != null) {
world = argWorld;
message = getFinalArg(args, 1);
}
}
if (world == null) {
world = user.getWorld();
message = getFinalArg(args, 0);
}
sendBroadcast(world.getName(), user.getDisplayName(), message);
}
@Override
@@ -43,6 +61,9 @@ public class Commandbroadcastworld extends EssentialsCommand {
if (world == null) {
throw new Exception(tl("invalidWorld"));
}
if (message.isEmpty()) {
throw new NotEnoughArgumentsException();
}
sendToWorld(world, tl("broadcast", FormatUtil.replaceFormat(message).replace("\\n", "\n"), name));
}
@@ -63,7 +84,15 @@ public class Commandbroadcastworld extends EssentialsCommand {
@Override
protected List<String> getTabCompleteOptions(Server server, User user, String commandLabel, String[] args) {
return Collections.emptyList(); // The argument is only for non-players
if (args.length == 1 && ess.getSettings().isAllowWorldInBroadcastworld()) {
List<String> worlds = Lists.newArrayList();
for (World world : server.getWorlds()) {
worlds.add(world.getName());
}
return worlds;
} else {
return Collections.emptyList();
}
}
@Override
@@ -8,15 +8,12 @@ import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.*;
public class Commandclearinventory extends EssentialsCommand {
@@ -87,6 +84,7 @@ public class Commandclearinventory extends EssentialsCommand {
short data = -1;
int type = -1;
int amount = -1;
final Set<Material> mats = new HashSet<>();
if (args.length > (offset + 1) && NumberUtil.isInt(args[(offset + 1)])) {
amount = Integer.parseInt(args[(offset + 1)]);
@@ -95,15 +93,15 @@ public class Commandclearinventory extends EssentialsCommand {
if (args[offset].equalsIgnoreCase("**")) {
type = -2;
} else if (!args[offset].equalsIgnoreCase("*")) {
final String[] split = args[offset].split(":");
final ItemStack item = ess.getItemDb().get(split[0]);
type = item.getTypeId();
final String[] split = args[offset].split(",");
if (split.length > 1 && NumberUtil.isInt(split[1])) {
data = Short.parseShort(split[1]);
} else {
data = item.getDurability();
for (String name : split) {
try {
mats.add(ess.getItemDb().get(name).getType());
} catch (Exception ignored) {}
}
type = 1;
}
}
@@ -123,32 +121,27 @@ public class Commandclearinventory extends EssentialsCommand {
InventoryWorkaround.setItemInOffHand(player, null);
player.getInventory().setArmorContents(null);
} else {
if (data == -1) // data -1 means that all subtypes will be cleared
{
ItemStack stack = new ItemStack(type);
if (showExtended) {
sender.sendMessage(tl("inventoryClearingAllStack", stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName()));
}
player.getInventory().clear(type, data);
} else if (amount == -1) // amount -1 means all items will be cleared
{
ItemStack stack = new ItemStack(type, BASE_AMOUNT, data);
ItemStack removedStack = player.getInventory().removeItem(stack).get(0);
final int removedAmount = (BASE_AMOUNT - removedStack.getAmount());
if (removedAmount > 0 || showExtended) {
sender.sendMessage(tl("inventoryClearingStack", removedAmount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName()));
}
} else {
if (amount < 0) {
amount = 1;
}
ItemStack stack = new ItemStack(type, amount, data);
if (player.getInventory().containsAtLeast(stack, amount)) {
sender.sendMessage(tl("inventoryClearingStack", amount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName()));
player.getInventory().removeItem(stack);
for (Material mat : mats) {
if (amount == -1) // amount -1 means all items will be cleared
{
ItemStack stack = new ItemStack(mat, BASE_AMOUNT, data);
ItemStack removedStack = player.getInventory().removeItem(stack).get(0);
final int removedAmount = (BASE_AMOUNT - removedStack.getAmount());
if (removedAmount > 0 || showExtended) {
sender.sendMessage(tl("inventoryClearingStack", removedAmount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName()));
}
} else {
if (showExtended) {
sender.sendMessage(tl("inventoryClearFail", player.getDisplayName(), amount, stack.getType().toString().toLowerCase(Locale.ENGLISH)));
if (amount < 0) {
amount = 1;
}
ItemStack stack = new ItemStack(mat, amount);
if (player.getInventory().containsAtLeast(stack, amount)) {
sender.sendMessage(tl("inventoryClearingStack", amount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName()));
player.getInventory().removeItem(stack);
} else {
if (showExtended) {
sender.sendMessage(tl("inventoryClearFail", player.getDisplayName(), amount, stack.getType().toString().toLowerCase(Locale.ENGLISH)));
}
}
}
}
@@ -16,23 +16,23 @@ public class Commandcompass extends EssentialsCommand {
final int bearing = (int) (user.getLocation().getYaw() + 180 + 360) % 360;
String dir;
if (bearing < 23) {
dir = "N";
dir = tl("north");
} else if (bearing < 68) {
dir = "NE";
dir = tl("northEast");
} else if (bearing < 113) {
dir = "E";
dir = tl("east");
} else if (bearing < 158) {
dir = "SE";
dir = tl("southEast");
} else if (bearing < 203) {
dir = "S";
dir = tl("south");
} else if (bearing < 248) {
dir = "SW";
dir = tl("southWest");
} else if (bearing < 293) {
dir = "W";
dir = tl("west");
} else if (bearing < 338) {
dir = "NW";
dir = tl("northWest");
} else {
dir = "N";
dir = tl("north");
}
user.sendMessage(tl("compassBearing", dir, bearing));
}
@@ -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;
@@ -19,6 +19,10 @@ public class Commanddeljail extends EssentialsCommand {
throw new NotEnoughArgumentsException();
}
if (ess.getJails().getJail(args[0]) == null) {
throw new Exception(tl("jailNotExist"));
}
ess.getJails().removeJail(args[0]);
sender.sendMessage(tl("deleteJail", args[0]));
}
@@ -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:
@@ -71,11 +72,11 @@ public class Commandeco extends EssentialsLoopCommand {
private void take(BigDecimal amount, final User player, final CommandSource sender) throws ChargeException {
BigDecimal money = player.getMoney();
BigDecimal minBalance = ess.getSettings().getMinMoney();
if (money.subtract(amount).compareTo(minBalance) > 0) {
player.takeMoney(amount, sender);
if (money.subtract(amount).compareTo(minBalance) >= 0) {
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)));
@@ -46,7 +46,7 @@ public class Commandenchant extends EssentialsCommand {
throw new NotEnoughArgumentsException(tl("enchantments", StringUtil.joinList(enchantmentslist.toArray())));
}
int level = -1;
int level = 1;
if (args.length > 1) {
try {
level = Integer.parseInt(args[1]);
@@ -4,86 +4,146 @@ import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.EssentialsUpgrade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.UserMap;
import com.earth2me.essentials.metrics.Metrics;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.FloatUtil;
import com.earth2me.essentials.utils.NumberUtil;
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.io.IOException;
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 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"
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 static final List<String> officialPlugins = Arrays.asList(
"EssentialsAntiBuild",
"EssentialsChat",
"EssentialsGeoIP",
"EssentialsProtect",
"EssentialsSpawn",
"EssentialsXMPP"
);
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("opt-out")) {
run_optout(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>");
}
@@ -92,131 +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;
// Pop tarts.
private void runNya(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (currentTune != null) {
currentTune.cancel();
}
@Override
public void run() {
final String note = tune[i];
i++;
if (i >= tune.length) {
Commandessentials.this.stopTune();
}
if (note == null || note.isEmpty()) {
return;
}
Sound noteHarp;
try {
noteHarp = Sound.valueOf("NOTE_PIANO"); // pre-1.9, referenced internally as note.harp
} catch (IllegalArgumentException e) {
noteHarp = Sound.valueOf("BLOCK_NOTE_HARP"); // 1.9
}
for (Player onlinePlayer : ess.getOnlinePlayers()) {
onlinePlayer.playSound(onlinePlayer.getLocation(), noteHarp, 1, noteMap.get(note));
}
}
}, 20, 2);
currentTune = new TuneRunnable(NYAN_TUNE, NOTE_HARP, ess::getOnlinePlayers);
currentTune.runTaskTimer(ess, 20, 2);
}
private void stopTune() {
ess.getScheduler().cancelTask(taskid);
for (Block block : noteBlocks.values()) {
if (block.getType() == Material.NOTE_BLOCK) {
block.setType(Material.AIR);
}
}
noteBlocks.clear();
}
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;
try {
moo = Sound.valueOf("COW_IDLE"); // pre-1.9
} catch (IllegalArgumentException e) {
moo = Sound.valueOf("ENTITY_COW_MILK"); // 1.9
}
// 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_optout(final Server server, final CommandSource sender, final String command, final String args[]) {
final Metrics metrics = ess.getMetrics();
sender.sendMessage("Essentials collects simple metrics to highlight which features to concentrate work on in the future.");
if (metrics.isOptOut()) {
metrics.enable();
} else {
metrics.disable();
}
sender.sendMessage("Anonymous Metrics are now " + (metrics.isOptOut() ? "disabled" : "enabled") + " for EssentialsX until server restart.");
sender.sendMessage("To " + (metrics.isOptOut() ? "disable" : "enable") + " them for all plugins permanently, see the bStats config.");
}
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]);
@@ -224,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>");
}
@@ -313,16 +300,19 @@ 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;
boolean isVaultInstalled = false;
boolean isUnsupported = false;
final boolean isServerSupported = VersionUtil.isServerSupported();
final PluginManager pm = server.getPluginManager();
final String essVer = pm.getPlugin("Essentials").getDescription().getVersion();
sender.sendMessage("Server version: " + server.getBukkitVersion() + " " + server.getVersion());
sender.sendMessage("EssentialsX version: " + essVer);
sender.sendMessage(tl(isServerSupported ? "versionOutputFine" : "versionOutputWarn", "Server", server.getBukkitVersion() + " " + server.getVersion()));
sender.sendMessage(tl("versionOutputFine", "EssentialsX", essVer));
for (Plugin plugin : pm.getPlugins()) {
final PluginDescriptionFile desc = plugin.getDescription();
@@ -330,15 +320,28 @@ public class Commandessentials extends EssentialsCommand {
String version = desc.getVersion();
if (name.startsWith("Essentials") && !name.equalsIgnoreCase("Essentials")) {
if (!version.equalsIgnoreCase(essVer)) {
version = "\u00a7c" + version;
isMismatched = true;
if (officialPlugins.contains(name)) {
name = name.replace("Essentials", "EssentialsX");
if (!version.equalsIgnoreCase(essVer)) {
isMismatched = true;
sender.sendMessage(tl("versionOutputWarn", name, version));
} else {
sender.sendMessage(tl("versionOutputFine", name, version));
}
} else {
sender.sendMessage(tl("versionOutputUnsupported", name, version));
isUnsupported = true;
}
sender.sendMessage(name.replace("Essentials", "EssentialsX") + " version: " + version);
}
if (versionPlugins.contains(name)) {
sender.sendMessage(name + " version: " + version);
if (warnPlugins.contains(name)) {
sender.sendMessage(tl("versionOutputUnsupported", name, version));
isUnsupported = true;
} else {
sender.sendMessage(tl("versionOutputFine", name, version));
}
}
if (name.equals("Vault")) isVaultInstalled = true;
@@ -349,7 +352,15 @@ public class Commandessentials extends EssentialsCommand {
}
if (!isVaultInstalled) {
sender.sendMessage("Vault is not installed - chat and permissions may not work.");
sender.sendMessage(tl("versionOutputVaultMissing"));
}
if (isUnsupported) {
sender.sendMessage(tl("versionOutputUnsupportedPlugins"));
}
if (!VersionUtil.isServerSupported()) {
sender.sendMessage(tl("serverUnsupported"));
}
}
@@ -357,50 +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("opt-out");
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("opt-out")) {
// No args
} 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();
}
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.MetaItemStack;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.google.common.collect.Lists;
import org.bukkit.DyeColor;
@@ -43,8 +44,8 @@ public class Commandfirework extends EssentialsCommand {
@Override
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final ItemStack stack = user.getBase().getItemInHand();
if (stack.getType() == Material.FIREWORK) {
final ItemStack stack = user.getItemInHand();
if (MaterialUtil.isFirework(stack.getType())) {
if (args.length > 0) {
if (args[0].equalsIgnoreCase("clear")) {
FireworkMeta fmeta = (FireworkMeta) stack.getItemMeta();
@@ -31,9 +31,9 @@ public class Commandgive extends EssentialsCommand {
}
ItemStack stack = ess.getItemDb().get(args[1]);
final String itemname = stack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
if (sender.isPlayer() && (ess.getSettings().permissionBasedItemSpawn() ? (!ess.getUser(sender.getPlayer()).isAuthorized("essentials.itemspawn.item-all") && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.itemspawn.item-" + itemname) && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.itemspawn.item-" + stack.getTypeId())) : (!ess.getUser(sender.getPlayer()).isAuthorized("essentials.itemspawn.exempt") && !ess.getUser(sender.getPlayer()).canSpawnItem(stack.getTypeId())))) {
if (sender.isPlayer() && !ess.getUser(sender.getPlayer()).canSpawnItem(stack.getType())) {
throw new Exception(tl("cantSpawnItem", itemname));
}
@@ -33,8 +33,12 @@ public class Commandhat extends EssentialsCommand {
user.sendMessage(tl("hatRemoved"));
}
} else {
if (user.getBase().getItemInHand().getType() != Material.AIR) {
final ItemStack hand = user.getBase().getItemInHand();
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
@@ -25,12 +25,14 @@ public class Commanditem extends EssentialsCommand {
if (args.length < 1) {
throw new NotEnoughArgumentsException();
}
ItemStack stack = ess.getItemDb().get(args[0]);
final String itemname = stack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
if (ess.getSettings().permissionBasedItemSpawn() ? (!user.isAuthorized("essentials.itemspawn.item-all") && !user.isAuthorized("essentials.itemspawn.item-" + itemname) && !user.isAuthorized("essentials.itemspawn.item-" + stack.getTypeId())) : (!user.isAuthorized("essentials.itemspawn.exempt") && !user.canSpawnItem(stack.getTypeId()))) {
if (!user.canSpawnItem(stack.getType())) {
throw new Exception(tl("cantSpawnItem", itemname));
}
try {
if (args.length > 1 && Integer.parseInt(args[1]) > 0) {
stack.setAmount(Integer.parseInt(args[1]));
@@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.utils.VersionUtil;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.ItemStack;
@@ -21,9 +22,9 @@ public class Commanditemdb extends EssentialsCommand {
ItemStack itemStack = null;
boolean itemHeld = false;
if (args.length < 1) {
if (sender.isPlayer()) {
if (sender.isPlayer() && sender.getPlayer() != null) {
itemHeld = true;
itemStack = sender.getPlayer().getItemInHand();
itemStack = ess.getUser(sender.getPlayer()).getItemInHand();
}
if (itemStack == null) {
throw new NotEnoughArgumentsException();
@@ -31,7 +32,19 @@ public class Commanditemdb extends EssentialsCommand {
} else {
itemStack = ess.getItemDb().get(args[0]);
}
sender.sendMessage(tl("itemType", itemStack.getType().toString(), itemStack.getTypeId() + ":" + Integer.toString(itemStack.getDurability())));
String itemId = "none";
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01)) {
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));
}
if (itemHeld && itemStack.getType() != Material.AIR) {
int maxuses = itemStack.getType().getMaxDurability();
@@ -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));
}
}
@@ -20,7 +20,9 @@ public class Commandkickall extends EssentialsCommand {
for (Player onlinePlayer : ess.getOnlinePlayers()) {
if (!sender.isPlayer() || !onlinePlayer.getName().equalsIgnoreCase(sender.getPlayer().getName())) {
onlinePlayer.kickPlayer(kickReason);
if (!ess.getUser(onlinePlayer).isAuthorized("essentials.kickall.exempt")) {
onlinePlayer.kickPlayer(kickReason);
}
}
}
sender.sendMessage(tl("kickedAll"));
@@ -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) {
@@ -16,15 +16,16 @@ public class Commandmore extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final ItemStack stack = user.getBase().getItemInHand();
final ItemStack stack = user.getItemInHand();
if (stack == null) {
throw new Exception(tl("cantSpawnItem", "Air"));
}
if (stack.getAmount() >= ((user.isAuthorized("essentials.oversizedstacks")) ? ess.getSettings().getOversizedStackSize() : stack.getMaxStackSize())) {
throw new Exception(tl("fullStack"));
}
final String itemname = stack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
if (ess.getSettings().permissionBasedItemSpawn() ? (!user.isAuthorized("essentials.itemspawn.item-all") && !user.isAuthorized("essentials.itemspawn.item-" + itemname) && !user.isAuthorized("essentials.itemspawn.item-" + stack.getTypeId())) : (!user.isAuthorized("essentials.itemspawn.exempt") && !user.canSpawnItem(stack.getTypeId()))) {
if (!user.canSpawnItem(stack.getType())) {
throw new Exception(tl("cantSpawnItem", itemname));
}
if (user.isAuthorized("essentials.oversizedstacks")) {
@@ -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");
}
@@ -55,16 +55,16 @@ public class Commandnick extends EssentialsLoopCommand {
@Override
protected void updatePlayer(final Server server, final CommandSource sender, final User target, final String[] args) throws NotEnoughArgumentsException {
final String nick = args[0];
if (target.getName().equalsIgnoreCase(nick)) {
if ("off".equalsIgnoreCase(nick)) {
setNickname(server, sender, target, null);
target.sendMessage(tl("nickNoMore"));
} else if (target.getName().equalsIgnoreCase(nick)) {
String oldName = target.getDisplayName();
setNickname(server, sender, target, nick);
if (!target.getDisplayName().equalsIgnoreCase(oldName)) {
target.sendMessage(tl("nickNoMore"));
}
target.sendMessage(tl("nickSet", target.getDisplayName()));
} else if ("off".equalsIgnoreCase(nick)) {
setNickname(server, sender, target, null);
target.sendMessage(tl("nickNoMore"));
} else if (nickInUse(server, target, nick)) {
throw new NotEnoughArgumentsException(tl("nickInUse"));
} else {
@@ -75,7 +75,7 @@ public class Commandnick extends EssentialsLoopCommand {
private String formatNickname(final User user, final String nick) throws Exception {
String newNick = user == null ? FormatUtil.replaceFormat(nick) : FormatUtil.formatString(user, "essentials.nick", nick);
if (!newNick.matches("^[a-zA-Z_0-9\u00a7]+$")) {
if (!newNick.matches("^[a-zA-Z_0-9\u00a7]+$") && user != null && !user.isAuthorized("essentials.nick.allowunsafe")) {
throw new Exception(tl("nickNamesAlpha"));
} else if (getNickLength(newNick) > ess.getSettings().getMaxNickLength()) {
throw new Exception(tl("nickTooLong"));
@@ -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);
@@ -31,7 +31,7 @@ public class Commandrealname extends EssentialsCommand {
final String displayName = FormatUtil.stripFormat(u.getDisplayName()).toLowerCase(Locale.ENGLISH);
if (displayName.contains(whois)) {
foundUser = true;
sender.sendMessage(u.getDisplayName() + " " + tl("is") + " " + u.getName());
sender.sendMessage(tl("realName", u.getDisplayName(), u.getName()));
}
}
if (!foundUser) {
@@ -2,7 +2,9 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.*;
@@ -19,13 +21,20 @@ import net.ess3.nms.refl.ReflUtil;
public class Commandrecipe extends EssentialsCommand {
private static final Material FIREWORK_ROCKET = EnumUtil.getMaterial("FIREWORK_ROCKET", "FIREWORK");
private static final Material FIREWORK_STAR = EnumUtil.getMaterial("FIREWORK_STAR", "FIREWORK_CHARGE");
private static final Material GUNPOWDER = EnumUtil.getMaterial("GUNPOWDER", "SULPHUR");
public Commandrecipe() {
super("recipe");
}
private void disableCommandForVersion1_12() throws Exception {
if (ReflUtil.getNmsVersionObject().equals(ReflUtil.V1_12_R1)) {
throw new Exception("/recipe is temporarily disabled. Please use the recipe book in your inventory.");
VersionUtil.BukkitVersion version = VersionUtil.getServerBukkitVersion();
if (version.isHigherThanOrEqualTo(VersionUtil.v1_12_0_R01)
&& !ess.getSettings().isForceEnableRecipe()) {
throw new Exception("Please use the recipe book in your inventory.");
}
}
@@ -64,11 +73,11 @@ public class Commandrecipe extends EssentialsCommand {
} else if (selectedRecipe instanceof ShapedRecipe) {
shapedRecipe(sender, (ShapedRecipe) selectedRecipe, sender.isPlayer());
} else if (selectedRecipe instanceof ShapelessRecipe) {
if (recipesOfType.size() == 1 && itemType.getType() == Material.FIREWORK) {
if (recipesOfType.size() == 1 && (itemType.getType() == FIREWORK_ROCKET)) {
ShapelessRecipe shapelessRecipe = new ShapelessRecipe(itemType);
shapelessRecipe.addIngredient(Material.SULPHUR);
shapelessRecipe.addIngredient(GUNPOWDER);
shapelessRecipe.addIngredient(Material.PAPER);
shapelessRecipe.addIngredient(Material.FIREWORK_CHARGE);
shapelessRecipe.addIngredient(FIREWORK_STAR);
shapelessRecipe(sender, shapelessRecipe, sender.isPlayer());
} else {
shapelessRecipe(sender, (ShapelessRecipe) selectedRecipe, sender.isPlayer());
@@ -4,6 +4,7 @@ import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists;
import net.ess3.api.IUser;
import org.bukkit.Material;
@@ -38,7 +39,7 @@ public class Commandrepair extends EssentialsCommand {
}
public void repairHand(User user) throws Exception {
final ItemStack item = user.getBase().getItemInHand();
final ItemStack item = user.getItemInHand();
if (item == null || item.getType().isBlock() || item.getDurability() == 0) {
throw new Exception(tl("repairInvalidType"));
}
@@ -48,7 +49,7 @@ public class Commandrepair extends EssentialsCommand {
}
final String itemName = item.getType().toString().toLowerCase(Locale.ENGLISH);
final Trade charge = new Trade("repair-" + itemName.replace('_', '-'), new Trade("repair-" + item.getTypeId(), new Trade("repair-item", ess), ess), ess);
final Trade charge = getCharge(item.getType());
charge.isAffordableFor(user);
@@ -76,7 +77,7 @@ public class Commandrepair extends EssentialsCommand {
}
private void repairItem(final ItemStack item) throws Exception {
final Material material = Material.getMaterial(item.getTypeId());
final Material material = item.getType();
if (material.isBlock() || material.getMaxDurability() < 1) {
throw new Exception(tl("repairInvalidType"));
}
@@ -88,13 +89,15 @@ public class Commandrepair extends EssentialsCommand {
item.setDurability((short) 0);
}
private void repairItems(final ItemStack[] items, final IUser user, final List<String> repaired) {
private void repairItems(final ItemStack[] items, final IUser user, final List<String> repaired) throws Exception {
for (ItemStack item : items) {
if (item == null || item.getType().isBlock() || item.getDurability() == 0) {
continue;
}
final String itemName = item.getType().toString().toLowerCase(Locale.ENGLISH);
final Trade charge = new Trade("repair-" + itemName.replace('_', '-'), new Trade("repair-" + item.getTypeId(), new Trade("repair-item", ess), ess), ess);
final Trade charge = getCharge(item.getType());
try {
charge.isAffordableFor(user);
} catch (ChargeException ex) {
@@ -119,6 +122,16 @@ public class Commandrepair extends EssentialsCommand {
}
}
private Trade getCharge(final Material material) {
final String itemName = material.toString().toLowerCase(Locale.ENGLISH);
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01)) {
final int itemId = material.getId();
return new Trade("repair-" + itemName.replace('_', '-'), new Trade("repair-" + itemId, new Trade("repair-item", ess), ess), ess);
} else {
return new Trade("repair-" + itemName.replace('_', '-'), new Trade("repair-item", ess), ess);
}
}
@Override
protected List<String> getTabCompleteOptions(Server server, User user, String commandLabel, String[] args) {
if (args.length == 1) {
@@ -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;
@@ -69,7 +70,7 @@ public class Commandsell extends EssentialsCommand {
private BigDecimal sellItem(User user, ItemStack is, String[] args, boolean isBulkSell) throws Exception {
int amount = ess.getWorth().getAmount(ess, user, is, args, isBulkSell);
BigDecimal worth = ess.getWorth().getPrice(is);
BigDecimal worth = ess.getWorth().getPrice(ess, is);
if (worth == null) {
throw new Exception(tl("itemCannotBeSold"));
@@ -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;
@@ -36,7 +36,7 @@ public class Commandsetwarp extends EssentialsCommand {
}
if (warpLoc == null || user.isAuthorized("essentials.warp.overwrite." + StringUtil.safeString(args[0]))) {
warps.setWarp(args[0], loc);
warps.setWarp(user, args[0], loc);
} else {
throw new Exception(tl("warpOverwrite"));
}
@@ -31,7 +31,7 @@ public class Commandsetworth extends EssentialsCommand {
price = args[1];
}
ess.getWorth().setPrice(stack, FloatUtil.parseDouble(price));
ess.getWorth().setPrice(ess, stack, FloatUtil.parseDouble(price));
user.sendMessage(tl("worthSet"));
}
@@ -42,7 +42,7 @@ public class Commandsetworth extends EssentialsCommand {
}
ItemStack stack = ess.getItemDb().get(args[0]);
ess.getWorth().setPrice(stack, FloatUtil.parseDouble(args[1]));
ess.getWorth().setPrice(ess, stack, FloatUtil.parseDouble(args[1]));
sender.sendMessage(tl("worthSet"));
}
}
@@ -2,6 +2,8 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.google.common.collect.Lists;
import org.bukkit.Material;
import org.bukkit.Server;
@@ -14,6 +16,9 @@ import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandskull extends EssentialsCommand {
private static final Material SKULL_ITEM = EnumUtil.getMaterial("PLAYER_HEAD", "SKULL_ITEM");
public Commandskull() {
super("skull");
}
@@ -31,14 +36,14 @@ public class Commandskull extends EssentialsCommand {
owner = user.getName();
}
ItemStack itemSkull = user.getBase().getItemInHand();
ItemStack itemSkull = user.getItemInHand();
SkullMeta metaSkull = null;
boolean spawn = false;
if (itemSkull != null && itemSkull.getType() == Material.SKULL_ITEM && itemSkull.getDurability() == 3) {
if (itemSkull != null && MaterialUtil.isPlayerHead(itemSkull.getType(), itemSkull.getDurability())) {
metaSkull = (SkullMeta) itemSkull.getItemMeta();
} else if (user.isAuthorized("essentials.skull.spawn")) {
itemSkull = new ItemStack(Material.SKULL_ITEM, 1, (byte) 3);
itemSkull = new ItemStack(SKULL_ITEM, 1, (byte) 3);
metaSkull = (SkullMeta) itemSkull.getItemMeta();
spawn = true;
} else {
@@ -3,6 +3,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.Mob;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.LocationUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
@@ -28,7 +29,9 @@ public class Commandspawner extends EssentialsCommand {
}
final Location target = LocationUtil.getTarget(user.getBase());
if (target == null || target.getBlock().getType() != Material.MOB_SPAWNER) {
Material MOB_SPAWNER = EnumUtil.getMaterial("SPAWNER", "MOB_SPAWNER");
if (target == null || target.getBlock().getType() != MOB_SPAWNER) {
throw new Exception(tl("mobSpawnTarget"));
}
@@ -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()));
}
}
}
@@ -32,6 +32,10 @@ public class Commandtree extends EssentialsCommand {
}
if (args[0].equalsIgnoreCase("jungle")) {
tree = TreeType.SMALL_JUNGLE;
} else if (args[0].equalsIgnoreCase("acacia")) {
tree = TreeType.ACACIA;
} else if (args[0].equalsIgnoreCase("birch")) {
tree = TreeType.BIRCH;
}
if (tree == null) {
throw new NotEnoughArgumentsException();
@@ -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<Integer> itemList = target.getUnlimited();
final Set<Material> itemList = new HashSet<>(target.getUnlimited());
int index = 0;
while (itemList.size() > index) {
final Integer item = itemList.get(index);
if (toggleUnlimited(user, target, item.toString()) == false) {
index++;
}
for (Material m : itemList) {
toggleUnlimited(user, target, m.toString());
}
} else {
toggleUnlimited(user, target, args[0]);
@@ -50,16 +48,16 @@ public class Commandunlimited extends EssentialsCommand {
final StringBuilder output = new StringBuilder();
output.append(tl("unlimitedItems")).append(" ");
boolean first = true;
final List<Integer> items = target.getUnlimited();
final Set<Material> items = target.getUnlimited();
if (items.isEmpty()) {
output.append(tl("none"));
}
for (Integer integer : items) {
for (Material material : items) {
if (!first) {
output.append(", ");
}
first = false;
final String matname = Material.getMaterial(integer).toString().toLowerCase(Locale.ENGLISH).replace("_", "");
final String matname = material.toString().toLowerCase(Locale.ENGLISH).replace("_", "");
output.append(matname);
}
@@ -71,7 +69,7 @@ public class Commandunlimited extends EssentialsCommand {
stack.setAmount(Math.min(stack.getType().getMaxStackSize(), 2));
final String itemname = stack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
if (ess.getSettings().permissionBasedItemSpawn() && (!user.isAuthorized("essentials.unlimited.item-all") && !user.isAuthorized("essentials.unlimited.item-" + itemname) && !user.isAuthorized("essentials.unlimited.item-" + stack.getTypeId()) && !((stack.getType() == Material.WATER_BUCKET || stack.getType() == Material.LAVA_BUCKET) && user.isAuthorized("essentials.unlimited.item-bucket")))) {
if (ess.getSettings().permissionBasedItemSpawn() && (!user.isAuthorized("essentials.unlimited.item-all") && !user.isAuthorized("essentials.unlimited.item-" + itemname) && !((stack.getType() == Material.WATER_BUCKET || stack.getType() == Material.LAVA_BUCKET) && user.isAuthorized("essentials.unlimited.item-bucket")))) {
throw new Exception(tl("unlimitedItemPermission", itemname));
}
@@ -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);
@@ -4,6 +4,7 @@ import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.SetExpFix;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.NumberUtil;
import org.bukkit.Server;
import org.bukkit.Statistic;
@@ -16,6 +17,10 @@ import static com.earth2me.essentials.I18n.tl;
public class Commandwhois extends EssentialsCommand {
// For some reason, in 1.13 PLAY_ONE_MINUTE = ticks played = what used to be PLAY_ONE_TICK
// https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/b848d8ce633871b52115247b089029749c02f579
private static final Statistic PLAY_ONE_TICK = EnumUtil.getStatistic("PLAY_ONE_MINUTE", "PLAY_ONE_TICK");
public Commandwhois() {
super("whois");
}
@@ -36,7 +41,7 @@ public class Commandwhois extends EssentialsCommand {
sender.sendMessage(tl("whoisHunger", user.getBase().getFoodLevel(), user.getBase().getSaturation()));
sender.sendMessage(tl("whoisExp", SetExpFix.getTotalExperience(user.getBase()), user.getBase().getLevel()));
sender.sendMessage(tl("whoisLocation", user.getLocation().getWorld().getName(), user.getLocation().getBlockX(), user.getLocation().getBlockY(), user.getLocation().getBlockZ()));
long playtimeMs = System.currentTimeMillis() - (user.getBase().getStatistic(Statistic.PLAY_ONE_TICK) * 50);
long playtimeMs = System.currentTimeMillis() - (user.getBase().getStatistic(PLAY_ONE_TICK) * 50);
sender.sendMessage(tl("whoisPlaytime", DateUtil.formatDateDiff(playtimeMs)));
if (!ess.getSettings().isEcoDisabled()) {
sender.sendMessage(tl("whoisMoney", NumberUtil.displayCurrency(user.getMoney(), ess)));
@@ -58,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
Loaded 100 of 288 files, more files were not shown because too many files have changed in this diff. Show more