mirror of
https://github.com/EssentialsX/Essentials.git
synced 2026-11-05 01:00:13 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8724e26ef | ||
|
|
e70bdb817c | ||
|
|
2dbd63adf8 | ||
|
|
cfb6f12da3 | ||
|
|
49a2f10071 | ||
|
|
43cb76a888 | ||
|
|
4600c72fd9 | ||
|
|
d5dc7e3a64 | ||
|
|
8013feb70c | ||
|
|
83aaf8cb37 | ||
|
|
966bc999e3 | ||
|
|
382de4ff3b | ||
|
|
f6f13fdee8 | ||
|
|
d2a7e0f99d | ||
|
|
64cfb10954 | ||
|
|
ee9f6f944a | ||
|
|
776f7094a8 | ||
|
|
28eb89fb02 | ||
|
|
ff54e64909 | ||
|
|
15ec9a2589 | ||
|
|
38f1b4ddde | ||
|
|
37ce087a71 | ||
|
|
e604c9f2ae | ||
|
|
49cc72ced2 | ||
|
|
5e95c87fdf | ||
|
|
c28c654b1e | ||
|
|
26a54475ad | ||
|
|
b303bf90d6 | ||
|
|
100f575293 | ||
|
|
c5a25bb79c | ||
|
|
5baf2391b3 | ||
|
|
c38c9256e9 | ||
|
|
79d67e98c3 | ||
|
|
5db483b548 | ||
|
|
39bc0fe224 | ||
|
|
1a9cba913b | ||
|
|
24b7285e42 | ||
|
|
5c45ee2169 | ||
|
|
87bde72678 | ||
|
|
97fd5609b4 | ||
|
|
936a2c0c62 | ||
|
|
3d03cf35df | ||
|
|
57a8c596f8 | ||
|
|
b594358545 | ||
|
|
e9f3677b95 | ||
|
|
678bacfee5 | ||
|
|
7f37b5e0f3 | ||
|
|
f39bc91ef5 | ||
|
|
63e7c4d259 | ||
|
|
1038b3a597 | ||
|
|
fb669aa9fd | ||
|
|
add5eb7cbf | ||
|
|
ddaadf2099 | ||
|
|
4db09f2a2e | ||
|
|
00b4a5b3bd | ||
|
|
73aa65733e | ||
|
|
86621cd90e | ||
|
|
236ce8837e | ||
|
|
f5fc4305c9 | ||
|
|
08b7fe3bb8 | ||
|
|
0845ea6f08 | ||
|
|
5a78df5494 | ||
|
|
716a61eb16 | ||
|
|
637ac8f4ee | ||
|
|
218e004108 | ||
|
|
c26909e2b8 | ||
|
|
5d535dcbe4 | ||
|
|
8e3b24fdba | ||
|
|
d7452bfcc7 | ||
|
|
482175e6c2 | ||
|
|
302653a77c | ||
|
|
9d70fdb263 | ||
|
|
297d0e4606 | ||
|
|
9c833336fb | ||
|
|
5abe8b61ef | ||
|
|
b8acd9c3ab | ||
|
|
f080f815fa | ||
|
|
18549a718a | ||
|
|
e9b8343751 | ||
|
|
99f7a49f28 | ||
|
|
bc6acfe1dc | ||
|
|
d16aec1525 | ||
|
|
787f539921 | ||
|
|
6ab56d2fe8 | ||
|
|
e5c9074b7c | ||
|
|
77756620cf | ||
|
|
0bd4c24c8b | ||
|
|
18233d3f04 | ||
|
|
5ed1d1e04a | ||
|
|
9ad754b6d9 | ||
|
|
68c304e6b6 | ||
|
|
ac666186f5 | ||
|
|
b34951757b | ||
|
|
000e6c551d | ||
|
|
b0ef56802a | ||
|
|
faa02b5c49 | ||
|
|
0fa6f70b13 | ||
|
|
af44749256 | ||
|
|
87dfe3793a | ||
|
|
9f57b3e476 | ||
|
|
9985dbdd3a | ||
|
|
bb47c45a60 | ||
|
|
150dabbe24 | ||
|
|
adf77dc4ba | ||
|
|
321c911222 | ||
|
|
264b0ed660 | ||
|
|
4dabeb57db | ||
|
|
8982aaec1d | ||
|
|
22b497558a | ||
|
|
65120e9d2c | ||
|
|
893bae02e6 | ||
|
|
ca7f3b5d5d | ||
|
|
973e5f8b27 | ||
|
|
37e10546ea | ||
|
|
0aa25c80b9 | ||
|
|
ca07b531e4 | ||
|
|
e08606432c | ||
|
|
364c87986f | ||
|
|
427f60eb57 | ||
|
|
efbcfb3bd6 | ||
|
|
19f7e99d95 | ||
|
|
e9da11624a | ||
|
|
81ac6f7283 | ||
|
|
7bc91f1c65 | ||
|
|
7c89592bbc | ||
|
|
302dd3fe35 | ||
|
|
69fd7bc8ff | ||
|
|
5ed43f339b | ||
|
|
8ba7a44a7d | ||
|
|
e0e8d4432a | ||
|
|
2ccfad189b | ||
|
|
58726fbc90 | ||
|
|
025ca4895f | ||
|
|
8bcf03d61b | ||
|
|
689c35fb23 | ||
|
|
03d89380cc | ||
|
|
790644b1ab | ||
|
|
334c5a4884 | ||
|
|
d402f17318 | ||
|
|
636bb097fe | ||
|
|
74337fff0f | ||
|
|
b36d43380c | ||
|
|
eb781a192b | ||
|
|
16f643a41f | ||
|
|
c01ba4eec4 | ||
|
|
f4cd1c92e2 | ||
|
|
d002c34fe8 | ||
|
|
ff7c952715 | ||
|
|
0417624bda | ||
|
|
9ef4fc34c3 | ||
|
|
73da278b02 | ||
|
|
e04f4888cd | ||
|
|
dfd83cfb0b | ||
|
|
cc25a798fc | ||
|
|
e39b61447b | ||
|
|
b996a9f143 | ||
|
|
3563b41556 | ||
|
|
ed3c9b83b5 | ||
|
|
6ad737d87a | ||
|
|
8d44d1ae7e | ||
|
|
dae9e3d091 | ||
|
|
573aae01ee | ||
|
|
c43ad269a8 | ||
|
|
e3b4e7723f | ||
|
|
6100cedc58 | ||
|
|
e6b8493749 | ||
|
|
fa4c6b66d5 | ||
|
|
715589c071 | ||
|
|
4a06fd1138 | ||
|
|
25f2f76302 | ||
|
|
ff1b8b8615 | ||
|
|
31ea9036cf | ||
|
|
2796399268 | ||
|
|
4057326b4f | ||
|
|
b44a9b2256 | ||
|
|
4ab3bbca95 | ||
|
|
f5c06b9676 | ||
|
|
997f600c15 | ||
|
|
d42347fb09 | ||
|
|
e836747244 | ||
|
|
3d28d82709 | ||
|
|
3a5c7c44b8 | ||
|
|
aebe851bff | ||
|
|
3fe1495fdb | ||
|
|
3b0c229e78 | ||
|
|
d137031a0a | ||
|
|
a58db237a4 | ||
|
|
fe430174a1 | ||
|
|
3f5b12294f | ||
|
|
be3e641c62 | ||
|
|
84552120c1 | ||
|
|
2bb44386c7 | ||
|
|
06c886ca69 | ||
|
|
f3a1b2b495 | ||
|
|
c7ff994d18 | ||
|
|
f09541cfa6 | ||
|
|
0cb387fb05 | ||
|
|
dabe68701d | ||
|
|
50b696bc07 | ||
|
|
cb6187bbf2 | ||
|
|
40540ebb3d | ||
|
|
46ba679c02 |
No files matched your search
@@ -0,0 +1,270 @@
|
||||
---
|
||||
name: mc-update
|
||||
description: Update EssentialsX for a new Minecraft version. Use when the user asks to update to, bump, or support a new Minecraft or Paper version (for example "update to 26.4", "add 26.3 mobs", "bump supported version"), or asks what must be checked for new mobs, items, wood types, armor, enchantments, potions, or Bukkit API changes.
|
||||
---
|
||||
|
||||
# Minecraft update
|
||||
|
||||
This checklist comes from every Minecraft update PR from 1.14 to 26.3, and from the fix PRs that followed them.
|
||||
|
||||
Paths are relative to the repository root. `ESS` means `Essentials/src/main/java/com/earth2me/essentials`.
|
||||
|
||||
## Procedure
|
||||
|
||||
1. Find the old and new `paper-api` jars in `~/.gradle/caches/modules-2/files-2.1/io.papermc.paper/paper-api/`. If the new jar is not there, set `paperVersion` in `build-logic/src/main/kotlin/essentials.base-conventions.gradle.kts` and run `./gradlew :EssentialsX:compileJava` to download it.
|
||||
2. Diff the constants of these classes between the two jars: `org.bukkit.entity.EntityType`, `org.bukkit.Material`, `org.bukkit.enchantments.Enchantment`, `org.bukkit.potion.PotionEffectType`, `org.bukkit.potion.PotionType`, `org.bukkit.TreeType`, and each `*$Variant` class under `org.bukkit.entity`. Use this command for each class:
|
||||
|
||||
```sh
|
||||
unzip -p <jar> org/bukkit/entity/EntityType.class > /tmp/x.class && javap -p /tmp/x.class | grep 'public static final'
|
||||
```
|
||||
|
||||
3. Sort each added, removed, or renamed constant into a section of part 2 or part 3 below.
|
||||
4. Do part 1. Then do each section that applies.
|
||||
5. Apply part 4 to every line you write.
|
||||
6. Run `./gradlew :EssentialsX:compileJava`. Fix errors.
|
||||
7. Do not commit unless the user asks.
|
||||
8. Report per section: what changed, and what you skipped and why.
|
||||
|
||||
---
|
||||
|
||||
## 1. Every update
|
||||
|
||||
### 1.1 Version constants
|
||||
|
||||
1. Open `ESS/utils/VersionUtil.java`.
|
||||
2. Add a constant `vXX_Y_R01 = BukkitVersion.fromString("XX.Y-R0.1-SNAPSHOT")`.
|
||||
- For a patch release, change the string of the existing minor constant. Example: `v26_1_R01` holds `26.1.2`.
|
||||
- For a minor release, add a new constant. Do not rename or delete an old constant. Old constants gate features. Deleting `v1_20_4_R01` caused #6460.
|
||||
3. Add the constant to `supportedVersions`. Keep the `ImmutableSet.of(...)` syntax. `build-logic/src/main/kotlin/VersionDataTask.kt` parses it with a regex.
|
||||
4. Start a server. Confirm `BukkitVersion.fromString(Bukkit.getBukkitVersion())` parses. Spigot 1.14.3 and Paper 26.1 both changed the string format.
|
||||
|
||||
### 1.2 Documentation
|
||||
|
||||
1. Update the supported versions sentence in `README.md`.
|
||||
2. Regenerate `items.json` with ItemDbGenerator.
|
||||
|
||||
---
|
||||
|
||||
## 2. New content
|
||||
|
||||
### 2.1 New mob
|
||||
|
||||
1. Add an entry to `ESS/Mob.java`: `NAME("CamelName", Enemies.X, "ENTITY_TYPE")`.
|
||||
- Use the string constructor. Do not use `EntityType.X`. The constant does not exist on old servers.
|
||||
- Set the plural suffix if it is not `s`. Fish use `""`. Fox uses `es`.
|
||||
- The display name must not contain a space.
|
||||
- Boats and rafts are also `Mob` entries.
|
||||
2. Add `EntityType` constant to `ESS/MobCompat.java` only if `MobData` needs it.
|
||||
3. Add the mob to `protect.prevent.spawn` in `Essentials/src/main/resources/config.yml`.
|
||||
4. Check `entityToDisplayName` in `providers/BaseProviders/.../SpawnerItemProvider.java` if the enum name does not title-case well.
|
||||
|
||||
### 2.2 New mob variant or data
|
||||
|
||||
1. Add entries to `ESS/MobData.java`. Use the string form `"kind:VARIANT"`. Example: `"wolf:PALE"`.
|
||||
2. Add a `case "kind":` to the `setData` switch.
|
||||
3. Add `setKindVariant(Entity, String)` to `MobCompat.java`. Gate it with `VersionUtil.getServerBukkitVersion().isLowerThan(vXX_Y_R01)`.
|
||||
4. Use `RegistryUtil.valueOf(Variant.class, name)` for registry types. Do not use `Enum.valueOf`.
|
||||
5. Do not call `NewClass.Variant.values()` in an enum initializer. Axolotl did this. It threw `NoClassDefFoundError` on 1.16 (#4376).
|
||||
6. Catch `Throwable` around reflective lookups. Cow variant threw NPE on old servers (#6121).
|
||||
7. For a boolean flag, add a `Data` constant and a branch in `setData`. Example: `GOAT_SCREAMING`.
|
||||
|
||||
### 2.3 New rideable or saddle mob
|
||||
|
||||
1. Add `SADDLE_<MOB>` to `MobData.java` with a `Data.<MOB>SADDLE` constant.
|
||||
2. Add `set<Mob>Saddle(Entity, Player)` to `MobCompat.java`. Tame the mob. Set the owner. Set the saddle.
|
||||
3. Check `ESS/craftbukkit/Inventories.java` if the mob adds a player inventory slot. Body and saddle slots (41, 42) broke `/clearinventory` in 1.21.6 (#6218).
|
||||
|
||||
### 2.4 New item or block
|
||||
|
||||
1. Check each `MaterialUtil` set that lists names by hand. See table.
|
||||
2. Check `ESS/utils/LocationUtil.java`:
|
||||
- Add a block that hurts a standing player to `DAMAGING_TYPES`. Magma, campfire, berry bush and wither rose were missed for 2 years (#3537).
|
||||
- `HOLLOW_MATERIALS` comes from `Material.isTransparent()`. Add a passable block that is not transparent. Example: `LIGHT` (#4601). Remove a transparent block that is solid. Examples: `BARRIER`, `DIRT_PATH`, `FARMLAND`.
|
||||
3. Check for a new event that reveals player position. Sculk sensor needed vanish handling in `EssentialsPlayerListener` (#5262).
|
||||
|
||||
| `ESS/utils/MaterialUtil.java` set | Add when |
|
||||
|---|---|
|
||||
| `HELMETS`, `CHESTPLATES`, `LEGGINGS`, `BOOTS` | New armor tier |
|
||||
| `LEATHER_ARMOR` | New dyeable armor |
|
||||
| `BEDS` | New bed. `STRAW_BED` in 26.3. |
|
||||
| `BANNERS` | New banner colour |
|
||||
| `SIGN_POSTS`, `WALL_SIGNS`, `HANGING_SIGNS`, `HANGING_WALL_SIGNS` | New wood type |
|
||||
| `MOB_HEADS` | New head. `PIGLIN_HEAD` in 1.20. |
|
||||
| `POTIONS` | New potion container |
|
||||
| `EDITABLE_BOOKS` | New book type |
|
||||
| `FIREWORKS`, `FIREWORK_CHARGE` | New firework item |
|
||||
|
||||
`EnumUtil.getAllMatching` skips a name that does not exist. Adding a name is safe on old servers.
|
||||
|
||||
### 2.5 Renamed item, block or entity
|
||||
|
||||
1. Grep `ESS` for `Material.OLD_NAME` and `EntityType.OLD_NAME`. Replace with `EnumUtil.getMaterial("NEW", "OLD")` or a `MobCompat` constant. `EntityType.PIG_ZOMBIE` in a static map broke 1.16 (#3412). `EntityType.FIREWORK` broke `/firework` in 1.20.6.
|
||||
2. For a renamed `EntityType`, add `getEntityType("NEW", "OLD")` to `MobCompat.java`. Update `Mob.java`, `MobData.java` and `SpawnMob.java`.
|
||||
|
||||
### 2.6 New wood type
|
||||
|
||||
1. Add `<WOOD>_SIGN`, `<WOOD>_WALL_SIGN`, `<WOOD>_HANGING_SIGN`, `<WOOD>_WALL_HANGING_SIGN` to the four sign sets in `MaterialUtil.java`. Crimson and warped were missed in 1.16 (#3487).
|
||||
2. Add `<WOOD>_BOAT` to `Mob.java`. Boats are separate entity types since 1.21.3.
|
||||
3. Add `<WOOD>` to `MobCompat.BoatVariant` for servers before 1.21.3.
|
||||
4. Add `<WOOD>_BOAT` to `MobData.java`.
|
||||
5. Add `<WOOD>_CHEST_BOAT` to `Mob.java`.
|
||||
|
||||
### 2.7 New tree type
|
||||
|
||||
1. `Commandtree` reads `TreeType.values()`. It needs no code change.
|
||||
2. Add the name to `treeCommandUsage` and `treeCommandUsage1` in `messages.properties`.
|
||||
3. `Commandbigtree` has four hard-coded types. Add a case if the tree has a big variant.
|
||||
4. Bukkit adds `TreeType` late. 26.3-pre-2 has no `POPLAR`.
|
||||
|
||||
### 2.8 New armor tier
|
||||
|
||||
1. Add the four pieces to `HELMETS`, `CHESTPLATES`, `LEGGINGS`, `BOOTS` in `MaterialUtil.java`.
|
||||
2. Add a branch to the armor keyword chain in `ESS/SpawnMob.java`. The chain has `netherite`, `copper`, `diamond`, `gold`, `leather`, `iron`.
|
||||
3. For horse armor, add `<TIER>_HORSE_ARMOR` to `MobData.java`. Example: `NETHERITE_HORSE_ARMOR`.
|
||||
|
||||
### 2.9 New enchantment
|
||||
|
||||
1. Add a `try { // XX.Y }` block to `ESS/Enchantments.java`.
|
||||
2. Look up by name: `Enchantment.getByName("NAME")`. Check for null. Do not use `Enchantment.NAME`.
|
||||
3. Add `ENCHANTMENTS.put("name", e)` and `ALIASENCHANTMENTS.put("alias", e)`.
|
||||
4. Swift sneak (1.19) and lunge (1.21.11) were missed. Contributors added them months later.
|
||||
5. Display and permission names come from `Enchantments.getRealName()`. It uses the key on 1.13+.
|
||||
|
||||
### 2.10 New potion effect or potion type
|
||||
|
||||
1. Add a `try { // XX.Y }` block to `ESS/Potions.java`. Catch `Throwable`.
|
||||
2. Add `POTIONS.put("name", PotionEffectType.NAME)` and `ALIASPOTIONS.put(...)`.
|
||||
3. `ModernPotionMetaProvider` maps `LONG_` and `STRONG_` prefixes. Check a new potion follows that pattern.
|
||||
|
||||
### 2.11 New banner pattern
|
||||
|
||||
No code change. `PatternTypeProvider` reads the registry.
|
||||
|
||||
### 2.12 New colour family
|
||||
|
||||
Check `MaterialUtil.getColorOf` for a colour name that is not a `DyeColor`.
|
||||
|
||||
### 2.13 New spawn egg
|
||||
|
||||
No code change. `FlatSpawnEggProvider` derives the egg from `EntityType.name() + "_SPAWN_EGG"`.
|
||||
|
||||
### 2.14 New command for new content
|
||||
|
||||
1. Gate the command with `VersionUtil`. Return `tl("unsupportedFeature")` on old servers. Examples: `/beezooka`, `/ice`.
|
||||
2. Add the command to `plugin.yml` and `messages.properties`. Check message parameters. `iceOther` shipped without `{0}`.
|
||||
|
||||
---
|
||||
|
||||
## 3. API changes
|
||||
|
||||
### 3.1 Enum becomes a registry
|
||||
|
||||
Enchantment, PotionEffectType, Sound, PatternType, Villager.Profession, Cat.Type, Biome and Boat.Type all changed.
|
||||
|
||||
1. Replace `EnumUtil.valueOf` with `RegistryUtil.valueOf(Class, names...)`. Replace `.values()` with `RegistryUtil.values(Class)`.
|
||||
2. If a static method moved from an enum to an interface, code compiled against the new API throws `IncompatibleClassChangeError` on old servers. `catch (Exception)` does not catch it. `PatternType.getByIdentifier` did this (#6553).
|
||||
3. For such a case, add a provider pair:
|
||||
- Interface in `providers/BaseProviders/src/main/java/net/ess3/provider/`.
|
||||
- `Modern*Provider` in BaseProviders with `@ProviderData(weight = 1)` and a `@ProviderTest`.
|
||||
- `Legacy*Provider` in `providers/1_12Provider` or `providers/1_8Provider`. These compile against the old API.
|
||||
- Register with `providerFactory.registerProvider(Legacy.class, Modern.class)` in `Essentials.java`.
|
||||
4. In a `@ProviderTest`, use `getMethod`, not `getDeclaredMethod`. 1.21 moved spawner methods to a super-interface (80bdc5269).
|
||||
|
||||
### 3.2 Removed API class
|
||||
|
||||
`PotionData`, `Potion`, `BannerMeta.setBaseColor` and `Achievement` were removed.
|
||||
|
||||
1. Move code that uses the removed class to a provider in `1_12Provider` or `1_8Provider`.
|
||||
2. Add a modern provider in BaseProviders.
|
||||
3. Remove the method from `OfflinePlayer`, `FakeWorld` and `FakeServer` if it was an override.
|
||||
|
||||
### 3.3 Changed method signature
|
||||
|
||||
1. Read the Bukkit diff for changed return types on methods EssentialsX calls.
|
||||
2. A changed return type changes the call descriptor. The call throws `NoSuchMethodError` on old servers. `PlayerPickupArrowEvent#getArrow` did this (#3175). `InventoryView` becoming an interface did this (#5851).
|
||||
3. Use a provider or reflection for the changed call.
|
||||
|
||||
### 3.4 New API methods on Player, World, Server
|
||||
|
||||
1. Add stubs to `providers/1_8Provider/.../OfflinePlayer.java` and `providers/1_12Provider/.../FakeWorld.java` if they fail to compile.
|
||||
2. Tests use MockBukkit since 1.21.6. `FakeServer` no longer needs updates.
|
||||
|
||||
### 3.5 New event
|
||||
|
||||
1. Put the handler in a separate `*Listener_XX_Y` class.
|
||||
2. Register it behind a `VersionUtil` check or `Class.forName`.
|
||||
3. Do not put a new event in a listener that loads on old servers. `EntityTransformEvent` failed on 1.13.1 (#2942).
|
||||
|
||||
### 3.6 Spigot NMS obfuscation
|
||||
|
||||
1. Add `VXX_Y_RN` to `providers/NMSReflectionProvider/.../ReflUtil.java` if Spigot bumps the NMS revision.
|
||||
2. Update the obfuscated `MinecraftServer#isRunning` name table in `ReflServerStateProvider.java`. This broke on 1.18, 1.19, 1.19.3, 1.20.6 and 1.21.10.
|
||||
3. Paper uses `PaperServerStateProvider`. Test on Spigot to see this fail.
|
||||
|
||||
### 3.7 Paper internal classes
|
||||
|
||||
Paper config classes move. `ReflOnlineModeProvider` broke on 1.19 when config moved to `io.papermc.paper.configuration.GlobalConfiguration`. Check every reflective Paper access.
|
||||
|
||||
### 3.8 World height
|
||||
|
||||
1. Do not hard-code `0`, `-1`, `128` or `256` as a Y bound.
|
||||
2. Use `WorldInfoProvider.getMinHeight`, `getMaxHeight` and `getLogicalHeight`.
|
||||
3. Grep `LocationUtil`, `RandomTeleport`, `Commandtop`, `Commandsethome`, `Teleport`, `AsyncTeleport` and `SpawnMob`. 1.18 needed three fix PRs (#4657, #4667, #4715).
|
||||
|
||||
### 3.9 Item data components
|
||||
|
||||
1. Check `MetaItemStack.parseStringMeta`. The `[...]` component branch calls `UnsafeValues#modifyItemStack`. Its argument shape changed in 1.20.5 and again in 26.1 (#6570).
|
||||
2. Check `Commandbook`. Writable and written books have separate meta since 1.20.6 (#6064).
|
||||
3. Check `Commandskull`. Skull owner needs a resolved profile since 1.20.4 (#6188).
|
||||
4. Check `MetaItemStack.canSpawn()`.
|
||||
|
||||
### 3.10 Vanilla messages
|
||||
|
||||
Check the vanilla changelog for a new client message that duplicates an EssentialsX message. 1.15 added "Respawn point set". `EssentialsPlayerListener` now gates `bedSet` (#2943).
|
||||
|
||||
### 3.11 Version string format
|
||||
|
||||
1. `BukkitVersion.VERSION_PATTERN` in `VersionUtil.java` must parse the new string.
|
||||
2. Supported suffixes: `-snapshot-N`, `-pre-N`, `-rc-N`, `.build.N-channel`, `.local`, `-R0.1-SNAPSHOT`.
|
||||
3. `compareDevSpecifier` orders `snapshot < pre < rc < release`.
|
||||
4. `isSupportedVersion` compares major, minor and patch. A patch release needs a constant change.
|
||||
5. 26.1 needed four fix PRs for this (#6480, #6483, #6500, #6501).
|
||||
|
||||
### 3.12 Adventure and Paper native paths
|
||||
|
||||
Each Paper API shift produced a gate:
|
||||
- `Essentials.initAdventureFacet` gates the Paper facet at `v1_18_2_R01` (#6562).
|
||||
- `EssentialsSpawnPlayerListener` gates `getRespawnLocation` at `v1_20_4_R01` (#6460).
|
||||
- `EssentialsPlayerListener` gates configuration events at `v1_21_8_R01`.
|
||||
|
||||
Check each gate against the new version.
|
||||
|
||||
---
|
||||
|
||||
## 4. Compatibility rules
|
||||
|
||||
EssentialsX runs on 1.8.8 through the current version. Every update PR must keep that.
|
||||
|
||||
1. Do not reference a new `Material`, `EntityType`, `Enchantment` or `PotionEffectType` constant in a static field or enum initializer. Use `EnumUtil.getMaterial`, `EnumUtil.getEntityType` or a name lookup.
|
||||
2. Catch `Throwable`, not `Exception`, around reflective lookups and provider selection. A swallowed `NoSuchFieldError` selected the wrong provider (7d6195375).
|
||||
3. Use only Guava and Gson methods that exist in 1.8.8. `Ints.constrainToRange` and `JsonArray#add(String)` do not (#4708, 576866540).
|
||||
4. Compile legacy providers in `1_8Provider` or `1_12Provider`. Code compiled against the new API can carry the wrong bytecode.
|
||||
5. Gate with `isLowerThan(<next major>)`, not `isLowerThanOrEqualTo(<patch>)`. Forks use nonstandard revision numbers (43eff69a2).
|
||||
6. Do not delete a `VersionUtil` constant.
|
||||
7. Test on Paper latest, Spigot latest, 1.12.2 and 1.8.8. Most follow-up fixes in this history came from old servers.
|
||||
|
||||
---
|
||||
|
||||
## 5. Test
|
||||
|
||||
1. Run `./gradlew test`.
|
||||
2. Run `./gradlew runServer`.
|
||||
3. Run `/ess version`. Confirm the support status is FULL.
|
||||
4. Run `/spawnmob <newmob>`, `/spawnmob <mob>:<variant>`.
|
||||
5. Run `/give @s <newitem>`, `/give @s minecraft:<newitem>`.
|
||||
6. Run `/enchant <newenchant>`, `/potion <neweffect>`.
|
||||
7. Place an EssentialsX sign on each new sign type.
|
||||
8. Run `/tree <newtree>` if Bukkit has the `TreeType`.
|
||||
9. Run `/kit` with the new armor. Confirm auto-equip.
|
||||
10. Teleport onto each new damaging block. Confirm `/tp` refuses.
|
||||
11. Repeat on Spigot for `ReflServerStateProvider`.
|
||||
@@ -32,8 +32,8 @@ body:
|
||||
- type: input
|
||||
attributes:
|
||||
label: Error log (if applicable)
|
||||
description: If you are reporting a console error, upload any relevant log excerpts to either https://paste.gg or https://gist.github.com, save and the paste the link in this box. If you included those files in the same paste as your startup log, paste the same link here.
|
||||
placeholder: "Example: https://paste.gg/p/anonymous/109dd6a10a734a3aa430d5a351ea5210"
|
||||
description: If you are reporting a console error, upload any relevant log excerpts to either https://pastes.dev or https://gist.github.com, save and the paste the link in this box. If you included those files in the same paste as your startup log, paste the same link here.
|
||||
placeholder: "Example: https://pastes.dev/UYL3ASLsee"
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
||||
@@ -80,7 +80,7 @@ Java version:
|
||||
bug fix on. If this feature does not apply to a server, strike through the server software using ~~strikethrough~~. If you have tested on other
|
||||
environments, add a new line with relevant details.
|
||||
-->
|
||||
- [ ] Most recent Paper version (1.XX.Y, git-Paper-BUILD)
|
||||
- [ ] Most recent Paper version (XX.YY.Z, git-Paper-BUILD)
|
||||
- [ ] CraftBukkit/Spigot/Paper 1.12.2
|
||||
- [ ] CraftBukkit 1.8.8
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ Java version:
|
||||
bug fix on. If this feature does not apply to a server, strike through the server software using ~~strikethrough~~. If you have tested on other
|
||||
environments, add a new line with relevant details.
|
||||
-->
|
||||
- [ ] Most recent Paper version (1.XX.Y, git-Paper-BUILD)
|
||||
- [ ] Most recent Paper version (XX.YY.Z, git-Paper-BUILD)
|
||||
- [ ] CraftBukkit/Spigot/Paper 1.12.2
|
||||
- [ ] CraftBukkit 1.8.8
|
||||
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK 17
|
||||
- name: Set up JDK 25
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
java-version: 25
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/gradle-build-action@v3
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
@@ -35,17 +35,71 @@ jobs:
|
||||
./gradlew build --stacktrace
|
||||
|
||||
- name: Publish JUnit report
|
||||
uses: mikepenz/action-junit-report@v4
|
||||
uses: mikepenz/action-junit-report@v5
|
||||
if: success() || failure() # Run even if the previous step fails
|
||||
with:
|
||||
report_paths: '**/build/test-results/test*/TEST-*.xml'
|
||||
|
||||
- name: Archive plugin jars on GitHub
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: EssentialsX plugin jars
|
||||
path: jars/
|
||||
|
||||
- name: Upload EssentialsX jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsX-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXAntiBuild jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXAntiBuild-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXChat jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXChat-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXDiscord jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXDiscord-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXDiscordLink jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXDiscordLink-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXGeoIP jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXGeoIP-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXProtect jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXProtect-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXSpawn jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXSpawn-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXXMPP jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXXMPP-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Deploy to Maven repo
|
||||
if: ${{ success() && github.event_name == 'push' && github.repository == 'EssentialsX/Essentials' && github.ref == 'refs/heads/2.x' }}
|
||||
env:
|
||||
@@ -67,7 +121,7 @@ jobs:
|
||||
cp -r EssentialsXMPP/build/docs/javadoc/ javadocs/EssentialsXMPP/
|
||||
|
||||
- name: Archive Javadocs
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: javadocs
|
||||
path: javadocs/
|
||||
@@ -82,10 +136,10 @@ jobs:
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 22
|
||||
|
||||
- name: Download Javadocs
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: javadocs
|
||||
path: javadocs/
|
||||
|
||||
@@ -10,6 +10,8 @@ on:
|
||||
- 2.x
|
||||
- mc/*
|
||||
- dev/*
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
|
||||
permissions:
|
||||
checks: write
|
||||
@@ -25,14 +27,14 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK 17
|
||||
- name: Set up JDK 25
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
java-version: 25
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/gradle-build-action@v3
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
@@ -46,7 +48,61 @@ jobs:
|
||||
report_paths: '**/build/test-results/test*/TEST-*.xml'
|
||||
|
||||
- name: Archive plugin jars on GitHub
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: EssentialsX plugin jars
|
||||
path: jars/
|
||||
|
||||
- name: Upload EssentialsX jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsX-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXAntiBuild jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXAntiBuild-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXChat jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXChat-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXDiscord jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXDiscord-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXDiscordLink jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXDiscordLink-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXGeoIP jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXGeoIP-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXProtect jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXProtect-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXSpawn jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXSpawn-*.jar
|
||||
archive: false
|
||||
|
||||
- name: Upload EssentialsXXMPP jar
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: jars/EssentialsXXMPP-*.jar
|
||||
archive: false
|
||||
@@ -0,0 +1,112 @@
|
||||
name: Mirror EssentialsX dumps to Gist
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited, closed]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
|
||||
env:
|
||||
DUMP_REGEX: 'https?://essentialsx\.net/dump\?bytebin=([A-Za-z0-9_-]+)'
|
||||
GIST_LINK_FMT: 'https://essentialsx.net/dump?gist='
|
||||
|
||||
jobs:
|
||||
handle-dump:
|
||||
if: github.event.action != 'closed'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Mirror dump to a private Gist
|
||||
id: mirror
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GIST_TOKEN }}
|
||||
script: |
|
||||
const issue = context.payload.issue ?? context.payload.comment.issue;
|
||||
const bodySrc = context.payload.comment ? context.payload.comment.body : issue.body || '';
|
||||
|
||||
const regex = new RegExp(process.env.DUMP_REGEX);
|
||||
const m = bodySrc.match(regex);
|
||||
if (!m) {
|
||||
core.info('No EssentialsX dump link found – abort.');
|
||||
return;
|
||||
}
|
||||
|
||||
const key = m[1];
|
||||
const dump = await fetch(`https://api.pastes.dev/${key}`);
|
||||
if (!dump.ok) throw new Error(`pastes.dev fetch failed (${dump.status})`);
|
||||
const text = await dump.text();
|
||||
|
||||
const { data: gist } = await github.rest.gists.create({
|
||||
files: { [`${key}.txt`]: { content: text } },
|
||||
description: `EssentialsX dump for issue #${issue.number}`,
|
||||
public: false
|
||||
});
|
||||
|
||||
core.setOutput('link', `${process.env.GIST_LINK_FMT}${gist.id}`);
|
||||
core.setOutput('issue_number', issue.number);
|
||||
|
||||
- name: Comment gist link on issue
|
||||
if: steps.mirror.outputs.link != ''
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: ${{ steps.mirror.outputs.issue_number }},
|
||||
body: `📋 Essentials Dump Backup → ${{ steps.mirror.outputs.link }}`
|
||||
});
|
||||
|
||||
cleanup-gist:
|
||||
if: github.event_name == 'issues' && github.event.action == 'closed'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Delete gist and hide bot comment
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GIST_TOKEN }}
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
|
||||
const comments = await github.paginate(
|
||||
github.rest.issues.listComments,
|
||||
{ owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number, per_page: 100 }
|
||||
);
|
||||
|
||||
const re = /https?:\/\/essentialsx\.net\/dump\?gist=([A-Za-z0-9]+)/;
|
||||
const hit = comments.reverse().find(c => re.test(c.body || ''));
|
||||
|
||||
if (!hit) {
|
||||
core.info('No gist link comment found – nothing to clean up.');
|
||||
return;
|
||||
}
|
||||
|
||||
const gistId = (hit.body.match(re))[1];
|
||||
const commentNodeId = hit.node_id;
|
||||
|
||||
try {
|
||||
await github.request('DELETE /gists/{gist_id}', { gist_id: gistId });
|
||||
core.info(`Deleted Gist ${gistId}`);
|
||||
} catch (err) {
|
||||
core.warning(`Could not delete Gist ${gistId}: ${err.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
await github.graphql(
|
||||
`mutation($id:ID!){
|
||||
minimizeComment(input:{subjectId:$id, classifier:OUTDATED}) {
|
||||
minimizedComment { id }
|
||||
}
|
||||
}`,
|
||||
{ id: commentNodeId }
|
||||
);
|
||||
core.info(`Minimised comment ${hit.id} as OUTDATED`);
|
||||
} catch (err) {
|
||||
core.warning(`Could not minimise comment: ${err.message}`);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
name: Command and Permissions Data
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 2.x
|
||||
|
||||
jobs:
|
||||
data:
|
||||
name: Generate and Upload
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Git Repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
|
||||
- name: Generate Data
|
||||
run: |
|
||||
chmod +x gradlew
|
||||
./gradlew commandData
|
||||
./gradlew versionData
|
||||
|
||||
- name: Upload Data
|
||||
uses: ryand56/r2-upload-action@v1
|
||||
with:
|
||||
r2-account-id: ${{ secrets.R2_ACCOUNT_ID }}
|
||||
r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||
r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||
r2-bucket: ${{ secrets.R2_BUCKET }}
|
||||
source-dir: generated
|
||||
destination-dir: ./
|
||||
|
||||
|
||||
@@ -21,10 +21,15 @@
|
||||
# Build files
|
||||
.gradle/
|
||||
/jars/
|
||||
generated/
|
||||
out/
|
||||
build/
|
||||
target/
|
||||
*.class
|
||||
build-logic/.kotlin/
|
||||
build-logic/bin/
|
||||
bin/
|
||||
test-tmp/
|
||||
|
||||
# Run directory
|
||||
/run/
|
||||
Generated
+2
-2
@@ -11,8 +11,8 @@
|
||||
</option>
|
||||
<option name="locations">
|
||||
<list>
|
||||
<ConfigurationLocation id="bundled-sun-checks" type="BUNDLED" scope="All" description="Sun Checks">(bundled)</ConfigurationLocation>
|
||||
<ConfigurationLocation id="bundled-google-checks" type="BUNDLED" scope="All" description="Google Checks">(bundled)</ConfigurationLocation>
|
||||
<ConfigurationLocation id="bundled-sun-checks" type="BUNDLED" scope="All" description="Sun Checks">bundled-sun-checks</ConfigurationLocation>
|
||||
<ConfigurationLocation id="bundled-google-checks" type="BUNDLED" scope="All" description="Google Checks">bundled-google-checks</ConfigurationLocation>
|
||||
<ConfigurationLocation id="321e5753-4201-4d2c-bf31-6232011122fd" type="PROJECT_RELATIVE" scope="All" description="EssentialsX">
|
||||
$PROJECT_DIR$/.checkstyle/checkstyle.xml
|
||||
<option name="properties">
|
||||
|
||||
+29
-10
@@ -3,7 +3,7 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly('com.github.milkbowl:VaultAPI:1.7') {
|
||||
compileOnly('net.essentialsx.deps:VaultAPI:1.7') {
|
||||
exclude group: "org.bukkit", module: "bukkit"
|
||||
}
|
||||
compileOnly 'net.luckperms:api:5.3'
|
||||
@@ -14,21 +14,25 @@ dependencies {
|
||||
implementation 'org.checkerframework:checker-qual:3.49.0'
|
||||
implementation 'nu.studer:java-ordered-properties:1.0.4'
|
||||
|
||||
implementation 'net.kyori:adventure-api:4.19.0'
|
||||
implementation 'net.kyori:adventure-text-minimessage:4.19.0'
|
||||
implementation 'net.kyori:adventure-platform-bukkit:4.3.4'
|
||||
implementation 'net.kyori:adventure-api:4.25.0'
|
||||
implementation 'net.kyori:adventure-text-minimessage:4.25.0'
|
||||
implementation 'net.kyori:adventure-platform-bukkit:4.4.1'
|
||||
|
||||
// Providers
|
||||
api project(':providers:BaseProviders')
|
||||
api project(path: ':providers:PaperProvider', configuration: 'shadow')
|
||||
api(project(':providers:BaseProviders')) {
|
||||
exclude(module: 'spigot-api')
|
||||
}
|
||||
api(project(path: ':providers:PaperProvider', configuration: 'shadow')){
|
||||
exclude(module: 'paper-api')
|
||||
}
|
||||
api(project(':providers:NMSReflectionProvider')) {
|
||||
exclude group: "org.bukkit", module: "bukkit"
|
||||
exclude(module: 'bukkit')
|
||||
}
|
||||
api(project(':providers:1_8Provider')) {
|
||||
exclude group: "org.spigotmc", module: "spigot"
|
||||
exclude(module: 'spigot-api')
|
||||
}
|
||||
api(project(':providers:1_12Provider')) {
|
||||
exclude group: "org.bukkit", module: "bukkit"
|
||||
exclude(module: 'bukkit')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +40,10 @@ test {
|
||||
testLogging.showStandardStreams = true
|
||||
}
|
||||
|
||||
tasks.register('versionData', VersionDataTask) {
|
||||
destination.set(rootProject.layout.projectDirectory.dir("generated").file("version-data.json"))
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
dependencies {
|
||||
include (dependency('io.papermc:paperlib'))
|
||||
@@ -68,6 +76,17 @@ shadowJar {
|
||||
include (project(':providers:NMSReflectionProvider'))
|
||||
include (project(':providers:1_8Provider'))
|
||||
include (project(':providers:1_12Provider'))
|
||||
|
||||
// Paper in-dev adventure versions (for snapshot/pre-releases)
|
||||
include (dependency('io.papermc.adventure:adventure-api'))
|
||||
include (dependency('io.papermc.adventure:adventure-key'))
|
||||
include (dependency('io.papermc.adventure:adventure-nbt'))
|
||||
include (dependency('io.papermc.adventure:adventure-text-serializer-gson'))
|
||||
include (dependency('io.papermc.adventure:adventure-text-serializer-gson-legacy-impl'))
|
||||
include (dependency('io.papermc.adventure:adventure-text-serializer-json'))
|
||||
include (dependency('io.papermc.adventure:adventure-text-serializer-json-legacy-impl'))
|
||||
include (dependency('io.papermc.adventure:adventure-text-serializer-legacy'))
|
||||
include (dependency('io.papermc.adventure:adventure-text-minimessage'))
|
||||
}
|
||||
relocate 'io.papermc.lib', 'com.earth2me.essentials.paperlib'
|
||||
relocate 'org.bstats', 'com.earth2me.essentials.libs.bstats'
|
||||
@@ -76,7 +95,7 @@ shadowJar {
|
||||
relocate 'io.leangen.geantyref', 'com.earth2me.essentials.libs.geantyref'
|
||||
relocate 'org.checkerframework', 'com.earth2me.essentials.libs.checkerframework'
|
||||
relocate 'net.kyori', 'com.earth2me.essentials.libs.kyori'
|
||||
relocate 'net.essentialsx.temp.adventure', 'net.kyori.adventure'
|
||||
relocate 'net.essentialsx.temp.adventure', 'net.kyori.adventure' // Undo temporary relocation for Paper Provider
|
||||
|
||||
minimize {
|
||||
include(dependency('org.checkerframework:checker-qual'))
|
||||
|
||||
@@ -116,6 +116,8 @@ public class AlternativeCommandsHandler {
|
||||
}
|
||||
|
||||
// return the first command that is not an alias
|
||||
Command firstAlias = null;
|
||||
|
||||
final Iterator<WeakReference<Command>> iterator = commands.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final Command cmd = iterator.next().get();
|
||||
@@ -127,10 +129,14 @@ public class AlternativeCommandsHandler {
|
||||
if (cmd.getName().equalsIgnoreCase(label)) {
|
||||
return cmd;
|
||||
}
|
||||
|
||||
if (firstAlias == null) {
|
||||
firstAlias = cmd;
|
||||
}
|
||||
}
|
||||
|
||||
// return the first alias
|
||||
return commands.get(0).get();
|
||||
// return the first alias, or null if every reference in this bucket has been collected
|
||||
return firstAlias;
|
||||
}
|
||||
|
||||
public void executed(final String label, final Command pc) {
|
||||
|
||||
@@ -457,6 +457,10 @@ public class AsyncTeleport implements IAsyncTeleport {
|
||||
nowAsync(teleportOwner, new LocationTarget(teleportOwner.getLastLocation()), TeleportCause.COMMAND, future);
|
||||
}
|
||||
|
||||
public TeleportType getTpType() {
|
||||
return this.tpType;
|
||||
}
|
||||
|
||||
public void setTpType(final TeleportType tpType) {
|
||||
this.tpType = tpType;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.IUser;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.IUser;
|
||||
import net.essentialsx.api.v2.events.TeleportWarmupCancelledEvent;
|
||||
import net.essentialsx.api.v2.events.TeleportWarmupCancelledEvent.CancelReason;
|
||||
|
||||
public class AsyncTimedTeleport implements Runnable {
|
||||
private static final double MOVE_CONSTANT = 0.3;
|
||||
private final IUser teleportOwner;
|
||||
@@ -149,6 +152,14 @@ public class AsyncTimedTeleport implements Runnable {
|
||||
}
|
||||
try {
|
||||
ess.getServer().getScheduler().cancelTask(timer_task);
|
||||
|
||||
final IUser teleportUser = ess.getUser(this.timer_teleportee);
|
||||
if (teleportUser != null && teleportUser.getBase() != null) {
|
||||
final TeleportWarmupCancelledEvent.CancelReason cancelReason = teleportUser.getBase().isOnline() ? CancelReason.MOVE : CancelReason.LEAVE;
|
||||
final TeleportWarmupCancelledEvent event = new TeleportWarmupCancelledEvent(teleportUser.getBase(), this.teleport.getTpType(), cancelReason, notifyUser);
|
||||
ess.getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
|
||||
if (notifyUser) {
|
||||
teleportOwner.sendTl("pendingTeleportCancelled");
|
||||
if (timer_teleportee != null && !timer_teleportee.equals(teleportOwner.getBase().getUniqueId())) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -80,7 +79,7 @@ public class Backup implements Runnable {
|
||||
taskLock.complete(new Object());
|
||||
return;
|
||||
}
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("backupStarted")));
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("backupStarted")));
|
||||
final CommandSender cs = server.getConsoleSender();
|
||||
server.dispatchCommand(cs, "save-all");
|
||||
server.dispatchCommand(cs, "save-off");
|
||||
@@ -119,7 +118,7 @@ public class Backup implements Runnable {
|
||||
}
|
||||
active = false;
|
||||
taskLock.complete(new Object());
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("backupFinished")));
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("backupFinished")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,10 @@ public class BalanceTopImpl implements BalanceTop {
|
||||
}
|
||||
final LinkedHashMap<UUID, Entry> sortedMap = new LinkedHashMap<>();
|
||||
entries.sort((entry1, entry2) -> entry2.getBalance().compareTo(entry1.getBalance()));
|
||||
for (Entry entry : entries) {
|
||||
final int entryLimit = ess.getSettings().getBaltopEntryLimit();
|
||||
final int limit = entryLimit == -1 ? entries.size() : Math.min(entryLimit, entries.size());
|
||||
for (int i = 0; i < limit; i++) {
|
||||
final Entry entry = entries.get(i);
|
||||
sortedMap.put(entry.getUuid(), entry);
|
||||
}
|
||||
topCache = sortedMap;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import com.earth2me.essentials.adventure.ComponentHolder;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -37,7 +35,7 @@ public class CommandSource {
|
||||
|
||||
final String translation = tlLiteral(tlKey, args);
|
||||
if (!translation.isEmpty()) {
|
||||
sendComponent(AdventureUtil.miniMessage().deserialize(translation));
|
||||
sendComponent(ess.getAdventureFacet().deserializeMiniMessage(translation));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,18 +47,17 @@ public class CommandSource {
|
||||
return tlLiteral(tlKey, args);
|
||||
}
|
||||
|
||||
public Component tlComponent(final String tlKey, final Object... args) {
|
||||
public ComponentHolder tlComponent(final String tlKey, final Object... args) {
|
||||
if (isPlayer()) {
|
||||
//noinspection ConstantConditions
|
||||
return getUser().tlComponent(tlKey, args);
|
||||
}
|
||||
final String translation = tlLiteral(tlKey, args);
|
||||
return AdventureUtil.miniMessage().deserialize(translation);
|
||||
return ess.getAdventureFacet().deserializeMiniMessage(translation);
|
||||
}
|
||||
|
||||
public void sendComponent(final Component component) {
|
||||
final BukkitAudiences audiences = ess.getBukkitAudience();
|
||||
audiences.sender(sender).sendMessage(component);
|
||||
public void sendComponent(final ComponentHolder component) {
|
||||
ess.getAdventureFacet().send(sender, component);
|
||||
}
|
||||
|
||||
public final net.ess3.api.IUser getUser() {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.adventure.AdventureFacet;
|
||||
import com.earth2me.essentials.messaging.IMessageRecipient;
|
||||
import com.earth2me.essentials.messaging.SimpleMessageRecipient;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -15,7 +13,11 @@ import static com.earth2me.essentials.I18n.tlLiteral;
|
||||
|
||||
public final class Console implements IMessageRecipient {
|
||||
public static final String NAME = "Console";
|
||||
public static final String DISPLAY_NAME = tlLiteral("consoleName");
|
||||
|
||||
public static String displayName() {
|
||||
return tlLiteral("consoleName");
|
||||
}
|
||||
|
||||
private static Console instance; // Set in essentials
|
||||
|
||||
private final IEssentials ess;
|
||||
@@ -58,7 +60,7 @@ public final class Console implements IMessageRecipient {
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return Console.DISPLAY_NAME;
|
||||
return displayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,10 +75,8 @@ public final class Console implements IMessageRecipient {
|
||||
return;
|
||||
}
|
||||
|
||||
final Audience consoleAudience = ((Essentials) ess).getBukkitAudience().sender(getCommandSender());
|
||||
final Component component = AdventureUtil.miniMessage()
|
||||
.deserialize(translation);
|
||||
consoleAudience.sendMessage(component);
|
||||
final AdventureFacet adventureFacet = ess.getAdventureFacet();
|
||||
adventureFacet.send(getCommandSender(), adventureFacet.deserializeMiniMessage(translation));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,13 +17,13 @@ public final class Enchantments {
|
||||
|
||||
static {
|
||||
final Enchantment SHARPNESS = RegistryUtil.valueOf(Enchantment.class, "DAMAGE_ALL", "SHARPNESS");
|
||||
|
||||
|
||||
ENCHANTMENTS.put("alldamage", SHARPNESS);
|
||||
ALIASENCHANTMENTS.put("alldmg", SHARPNESS);
|
||||
ENCHANTMENTS.put("sharpness", SHARPNESS);
|
||||
ALIASENCHANTMENTS.put("sharp", SHARPNESS);
|
||||
ALIASENCHANTMENTS.put("dal", SHARPNESS);
|
||||
|
||||
|
||||
final Enchantment BANE_OF_ARTHROPODS = RegistryUtil.valueOf(Enchantment.class, "DAMAGE_ARTHROPODS", "BANE_OF_ARTHROPODS");
|
||||
|
||||
ENCHANTMENTS.put("ardmg", BANE_OF_ARTHROPODS);
|
||||
@@ -31,13 +31,13 @@ public final class Enchantments {
|
||||
ALIASENCHANTMENTS.put("baneofarthropod", BANE_OF_ARTHROPODS);
|
||||
ALIASENCHANTMENTS.put("arthropod", BANE_OF_ARTHROPODS);
|
||||
ALIASENCHANTMENTS.put("dar", BANE_OF_ARTHROPODS);
|
||||
|
||||
|
||||
final Enchantment SMITE = RegistryUtil.valueOf(Enchantment.class, "DAMAGE_UNDEAD", "SMITE");
|
||||
|
||||
ENCHANTMENTS.put("undeaddamage", SMITE);
|
||||
ENCHANTMENTS.put("smite", SMITE);
|
||||
ALIASENCHANTMENTS.put("du", SMITE);
|
||||
|
||||
|
||||
final Enchantment EFFICIENCY = RegistryUtil.valueOf(Enchantment.class, "DIG_SPEED", "EFFICIENCY");
|
||||
|
||||
ENCHANTMENTS.put("digspeed", EFFICIENCY);
|
||||
@@ -46,7 +46,7 @@ public final class Enchantments {
|
||||
ALIASENCHANTMENTS.put("cutspeed", EFFICIENCY);
|
||||
ALIASENCHANTMENTS.put("ds", EFFICIENCY);
|
||||
ALIASENCHANTMENTS.put("eff", EFFICIENCY);
|
||||
|
||||
|
||||
final Enchantment UNBREAKING = RegistryUtil.valueOf(Enchantment.class, "DURABILITY", "UNBREAKING");
|
||||
|
||||
ENCHANTMENTS.put("durability", UNBREAKING);
|
||||
@@ -70,21 +70,21 @@ public final class Enchantments {
|
||||
ALIASENCHANTMENTS.put("kback", Enchantment.KNOCKBACK);
|
||||
ALIASENCHANTMENTS.put("kb", Enchantment.KNOCKBACK);
|
||||
ALIASENCHANTMENTS.put("k", Enchantment.KNOCKBACK);
|
||||
|
||||
|
||||
final Enchantment FORTUNE = RegistryUtil.valueOf(Enchantment.class, "LOOT_BONUS_BLOCKS", "FORTUNE");
|
||||
|
||||
ALIASENCHANTMENTS.put("blockslootbonus", FORTUNE);
|
||||
ENCHANTMENTS.put("fortune", FORTUNE);
|
||||
ALIASENCHANTMENTS.put("fort", FORTUNE);
|
||||
ALIASENCHANTMENTS.put("lbb", FORTUNE);
|
||||
|
||||
|
||||
final Enchantment LOOTING = RegistryUtil.valueOf(Enchantment.class, "LOOT_BONUS_MOBS", "LOOTING");
|
||||
|
||||
ALIASENCHANTMENTS.put("mobslootbonus", LOOTING);
|
||||
ENCHANTMENTS.put("mobloot", LOOTING);
|
||||
ENCHANTMENTS.put("looting", LOOTING);
|
||||
ALIASENCHANTMENTS.put("lbm", LOOTING);
|
||||
|
||||
|
||||
final Enchantment RESPIRATION = RegistryUtil.valueOf(Enchantment.class, "OXYGEN", "RESPIRATION");
|
||||
|
||||
ALIASENCHANTMENTS.put("oxygen", RESPIRATION);
|
||||
@@ -92,14 +92,14 @@ public final class Enchantments {
|
||||
ALIASENCHANTMENTS.put("breathing", RESPIRATION);
|
||||
ENCHANTMENTS.put("breath", RESPIRATION);
|
||||
ALIASENCHANTMENTS.put("o", RESPIRATION);
|
||||
|
||||
|
||||
final Enchantment PROTECTION = RegistryUtil.valueOf(Enchantment.class, "PROTECTION_ENVIRONMENTAL", "PROTECTION");
|
||||
|
||||
ENCHANTMENTS.put("protection", PROTECTION);
|
||||
ALIASENCHANTMENTS.put("prot", PROTECTION);
|
||||
ENCHANTMENTS.put("protect", PROTECTION);
|
||||
ALIASENCHANTMENTS.put("p", PROTECTION);
|
||||
|
||||
|
||||
final Enchantment BLAST_PROTECTION = RegistryUtil.valueOf(Enchantment.class, "PROTECTION_EXPLOSIONS", "BLAST_PROTECTION");
|
||||
|
||||
ALIASENCHANTMENTS.put("explosionsprotection", BLAST_PROTECTION);
|
||||
@@ -110,7 +110,7 @@ public final class Enchantments {
|
||||
ALIASENCHANTMENTS.put("bprotect", BLAST_PROTECTION);
|
||||
ENCHANTMENTS.put("blastprotect", BLAST_PROTECTION);
|
||||
ALIASENCHANTMENTS.put("pe", BLAST_PROTECTION);
|
||||
|
||||
|
||||
final Enchantment FEATHER_FALLING = RegistryUtil.valueOf(Enchantment.class, "PROTECTION_FALL", "FEATHER_FALLING");
|
||||
|
||||
ALIASENCHANTMENTS.put("fallprotection", FEATHER_FALLING);
|
||||
@@ -118,7 +118,7 @@ public final class Enchantments {
|
||||
ENCHANTMENTS.put("featherfall", FEATHER_FALLING);
|
||||
ALIASENCHANTMENTS.put("featherfalling", FEATHER_FALLING);
|
||||
ALIASENCHANTMENTS.put("pfa", FEATHER_FALLING);
|
||||
|
||||
|
||||
final Enchantment FIRE_PROTECTION = RegistryUtil.valueOf(Enchantment.class, "PROTECTION_FIRE", "FIRE_PROTECTION");
|
||||
|
||||
ALIASENCHANTMENTS.put("fireprotection", FIRE_PROTECTION);
|
||||
@@ -128,7 +128,7 @@ public final class Enchantments {
|
||||
ENCHANTMENTS.put("fireprot", FIRE_PROTECTION);
|
||||
ALIASENCHANTMENTS.put("flameprot", FIRE_PROTECTION);
|
||||
ALIASENCHANTMENTS.put("pf", FIRE_PROTECTION);
|
||||
|
||||
|
||||
final Enchantment PROJECTILE_PROTECTION = RegistryUtil.valueOf(Enchantment.class, "PROTECTION_PROJECTILE", "PROJECTILE_PROTECTION");
|
||||
|
||||
ENCHANTMENTS.put("projectileprotection", PROJECTILE_PROTECTION);
|
||||
@@ -138,28 +138,28 @@ public final class Enchantments {
|
||||
ENCHANTMENTS.put("silktouch", Enchantment.SILK_TOUCH);
|
||||
ALIASENCHANTMENTS.put("softtouch", Enchantment.SILK_TOUCH);
|
||||
ALIASENCHANTMENTS.put("st", Enchantment.SILK_TOUCH);
|
||||
|
||||
|
||||
final Enchantment AQUA_AFFINITY = RegistryUtil.valueOf(Enchantment.class, "WATER_WORKER", "AQUA_AFFINITY");
|
||||
|
||||
ENCHANTMENTS.put("waterworker", AQUA_AFFINITY);
|
||||
ENCHANTMENTS.put("aquaaffinity", AQUA_AFFINITY);
|
||||
ALIASENCHANTMENTS.put("watermine", AQUA_AFFINITY);
|
||||
ALIASENCHANTMENTS.put("ww", AQUA_AFFINITY);
|
||||
|
||||
|
||||
final Enchantment FLAME = RegistryUtil.valueOf(Enchantment.class, "ARROW_FIRE", "FLAME");
|
||||
|
||||
ALIASENCHANTMENTS.put("firearrow", FLAME);
|
||||
ENCHANTMENTS.put("flame", FLAME);
|
||||
ENCHANTMENTS.put("flamearrow", FLAME);
|
||||
ALIASENCHANTMENTS.put("af", FLAME);
|
||||
|
||||
|
||||
final Enchantment POWER = RegistryUtil.valueOf(Enchantment.class, "ARROW_DAMAGE", "POWER");
|
||||
|
||||
ENCHANTMENTS.put("arrowdamage", POWER);
|
||||
ENCHANTMENTS.put("power", POWER);
|
||||
ALIASENCHANTMENTS.put("arrowpower", POWER);
|
||||
ALIASENCHANTMENTS.put("ad", POWER);
|
||||
|
||||
|
||||
final Enchantment PUNCH = RegistryUtil.valueOf(Enchantment.class, "ARROW_KNOCKBACK", "PUNCH");
|
||||
|
||||
ENCHANTMENTS.put("arrowknockback", PUNCH);
|
||||
@@ -167,7 +167,7 @@ public final class Enchantments {
|
||||
ENCHANTMENTS.put("punch", PUNCH);
|
||||
ALIASENCHANTMENTS.put("arrowpunch", PUNCH);
|
||||
ALIASENCHANTMENTS.put("ak", PUNCH);
|
||||
|
||||
|
||||
final Enchantment INFINITY = RegistryUtil.valueOf(Enchantment.class, "ARROW_INFINITE", "INFINITY");
|
||||
|
||||
ALIASENCHANTMENTS.put("infinitearrows", INFINITY);
|
||||
@@ -177,7 +177,7 @@ public final class Enchantments {
|
||||
ALIASENCHANTMENTS.put("unlimited", INFINITY);
|
||||
ALIASENCHANTMENTS.put("unlimitedarrows", INFINITY);
|
||||
ALIASENCHANTMENTS.put("ai", INFINITY);
|
||||
|
||||
|
||||
final Enchantment LUCK_OF_THE_SEA = RegistryUtil.valueOf(Enchantment.class, "LUCK", "LUCK_OF_THE_SEA");
|
||||
|
||||
ENCHANTMENTS.put("luck", LUCK_OF_THE_SEA);
|
||||
@@ -313,7 +313,7 @@ public final class Enchantments {
|
||||
ENCHANTMENTS.put("density", density);
|
||||
}
|
||||
final Enchantment windBurst = Enchantment.getByName("WIND_BURST");
|
||||
if (breach != null) {
|
||||
if (windBurst != null) {
|
||||
ENCHANTMENTS.put("windburst", windBurst);
|
||||
ALIASENCHANTMENTS.put("wind", windBurst);
|
||||
ALIASENCHANTMENTS.put("burst", windBurst);
|
||||
@@ -321,6 +321,14 @@ public final class Enchantments {
|
||||
} catch (final IllegalArgumentException ignored) {
|
||||
}
|
||||
|
||||
try { // 1.21.11
|
||||
final Enchantment lunge = Enchantment.getByName("LUNGE");
|
||||
if (lunge != null) {
|
||||
ENCHANTMENTS.put("lunge", lunge);
|
||||
}
|
||||
} catch (final IllegalArgumentException ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
final Class<?> namespacedKeyClass = Class.forName("org.bukkit.NamespacedKey");
|
||||
final Class<?> enchantmentClass = Class.forName("org.bukkit.enchantments.Enchantment");
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
*/
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.adventure.AdventureFacet;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.ComponentHolder;
|
||||
import com.earth2me.essentials.adventure.PaperAdventureFacet;
|
||||
import com.earth2me.essentials.adventure.SpigotAdventureFacet;
|
||||
import com.earth2me.essentials.commands.EssentialsCommand;
|
||||
import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import com.earth2me.essentials.commands.NoChargeException;
|
||||
@@ -40,11 +45,13 @@ import com.earth2me.essentials.textreader.KeywordReplacer;
|
||||
import com.earth2me.essentials.textreader.SimpleTextInput;
|
||||
import com.earth2me.essentials.updatecheck.UpdateChecker;
|
||||
import com.earth2me.essentials.userstorage.ModernUserMap;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.utils.ModernPaperEnvironment;
|
||||
import com.earth2me.essentials.utils.PasteUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.ess3.api.Economy;
|
||||
import com.earth2me.essentials.config.EssentialsConfiguration;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.IItemDb;
|
||||
import net.ess3.api.IJails;
|
||||
@@ -66,13 +73,16 @@ import net.ess3.provider.ProviderListener;
|
||||
import net.ess3.provider.ServerStateProvider;
|
||||
import net.ess3.provider.providers.BaseBannerDataProvider;
|
||||
import net.ess3.provider.providers.BaseInventoryViewProvider;
|
||||
import net.ess3.provider.providers.BaseLoggerProvider;
|
||||
import net.ess3.provider.providers.BlockMetaSpawnerItemProvider;
|
||||
import net.ess3.provider.providers.BukkitMaterialTagProvider;
|
||||
import net.ess3.provider.providers.BukkitSpawnerBlockProvider;
|
||||
import net.ess3.provider.providers.BukkitTileEntityProvider;
|
||||
import net.ess3.provider.providers.FixedHeightWorldInfoProvider;
|
||||
import net.ess3.provider.providers.FlatSpawnEggProvider;
|
||||
import net.ess3.provider.providers.LegacyBannerDataProvider;
|
||||
import net.ess3.provider.providers.LegacyBiomeNameProvider;
|
||||
import net.ess3.provider.providers.LegacyPatternTypeProvider;
|
||||
import net.ess3.provider.providers.ModernPatternTypeProvider;
|
||||
import net.ess3.provider.providers.LegacyDamageEventProvider;
|
||||
import net.ess3.provider.providers.LegacyInventoryViewProvider;
|
||||
import net.ess3.provider.providers.LegacyItemUnbreakableProvider;
|
||||
@@ -95,11 +105,10 @@ import net.ess3.provider.providers.PaperRecipeBookListener;
|
||||
import net.ess3.provider.providers.PaperSerializationProvider;
|
||||
import net.ess3.provider.providers.PaperServerStateProvider;
|
||||
import net.ess3.provider.providers.PaperTickCountProvider;
|
||||
import net.ess3.provider.providers.PaperTileEntityProvider;
|
||||
import net.ess3.provider.providers.PrehistoricPotionMetaProvider;
|
||||
import net.essentialsx.api.v2.services.BalanceTop;
|
||||
import net.essentialsx.api.v2.services.mail.MailService;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
@@ -120,18 +129,13 @@ import org.bukkit.event.player.PlayerEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.plugin.InvalidDescriptionException;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -146,6 +150,8 @@ import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tlLiteral;
|
||||
import static com.earth2me.essentials.I18n.tlLocale;
|
||||
@@ -181,58 +187,17 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
private transient Kits kits;
|
||||
private transient RandomTeleport randomTeleport;
|
||||
private transient UpdateChecker updateChecker;
|
||||
private transient BukkitAudiences bukkitAudience;
|
||||
private transient AdventureFacet adventureFacet;
|
||||
|
||||
static {
|
||||
EconomyLayers.init();
|
||||
}
|
||||
|
||||
public Essentials() {
|
||||
}
|
||||
|
||||
protected Essentials(final JavaPluginLoader loader, final PluginDescriptionFile description, final File dataFolder, final File file) {
|
||||
super(loader, description, dataFolder, file);
|
||||
}
|
||||
|
||||
public Essentials(final Server server) {
|
||||
super(new JavaPluginLoader(server), new PluginDescriptionFile("Essentials", "", "com.earth2me.essentials.Essentials"), null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISettings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
public void setupForTesting(final Server server) throws IOException, InvalidDescriptionException {
|
||||
TESTING = true;
|
||||
LOGGER = new BaseLoggerProvider(this, BUKKIT_LOGGER);
|
||||
final File dataFolder = File.createTempFile("essentialstest", "");
|
||||
if (!dataFolder.delete()) {
|
||||
throw new IOException();
|
||||
}
|
||||
if (!dataFolder.mkdir()) {
|
||||
throw new IOException();
|
||||
}
|
||||
i18n = new I18n(this);
|
||||
i18n.onEnable();
|
||||
i18n.updateLocale("en");
|
||||
Console.setInstance(this);
|
||||
|
||||
LOGGER.log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("usingTempFolderForTesting")));
|
||||
LOGGER.log(Level.INFO, dataFolder.toString());
|
||||
settings = new Settings(this);
|
||||
mail = new MailServiceImpl(this);
|
||||
userMap = new ModernUserMap(this);
|
||||
balanceTop = new BalanceTopImpl(this);
|
||||
permissionsHandler = new PermissionsHandler(this, false);
|
||||
Economy.setEss(this);
|
||||
confList = new ArrayList<>();
|
||||
jails = new Jails(this);
|
||||
registerListeners(server.getPluginManager());
|
||||
kits = new Kits(this);
|
||||
bukkitAudience = BukkitAudiences.create(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
try {
|
||||
@@ -253,6 +218,8 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
LOGGER = EssentialsLogger.getLoggerProvider(this);
|
||||
EssentialsLogger.updatePluginLogger(this);
|
||||
|
||||
initAdventureFacet();
|
||||
|
||||
execTimer = new ExecuteTimer();
|
||||
execTimer.start();
|
||||
|
||||
@@ -268,33 +235,41 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
|
||||
switch (VersionUtil.getServerSupportStatus()) {
|
||||
case NMS_CLEANROOM:
|
||||
getLogger().severe(AdventureUtil.miniToLegacy(tlLiteral("serverUnsupportedCleanroom")));
|
||||
getLogger().severe(getAdventureFacet().miniToLegacy(tlLiteral("serverUnsupportedCleanroom")));
|
||||
break;
|
||||
case DANGEROUS_FORK:
|
||||
getLogger().severe(AdventureUtil.miniToLegacy(tlLiteral("serverUnsupportedDangerous")));
|
||||
getLogger().severe(getAdventureFacet().miniToLegacy(tlLiteral("serverUnsupportedDangerous")));
|
||||
break;
|
||||
case STUPID_PLUGIN:
|
||||
getLogger().severe(AdventureUtil.miniToLegacy(tlLiteral("serverUnsupportedDumbPlugins")));
|
||||
getLogger().severe(getAdventureFacet().miniToLegacy(tlLiteral("serverUnsupportedDumbPlugins")));
|
||||
break;
|
||||
case UNSTABLE:
|
||||
getLogger().severe(AdventureUtil.miniToLegacy(tlLiteral("serverUnsupportedMods")));
|
||||
getLogger().severe(getAdventureFacet().miniToLegacy(tlLiteral("serverUnsupportedMods")));
|
||||
break;
|
||||
case OUTDATED:
|
||||
getLogger().severe(AdventureUtil.miniToLegacy(tlLiteral("serverUnsupported")));
|
||||
getLogger().severe(getAdventureFacet().miniToLegacy(tlLiteral("serverUnsupported")));
|
||||
break;
|
||||
case LIMITED:
|
||||
getLogger().info(AdventureUtil.miniToLegacy(tlLiteral("serverUnsupportedLimitedApi")));
|
||||
getLogger().info(getAdventureFacet().miniToLegacy(tlLiteral("serverUnsupportedLimitedApi")));
|
||||
break;
|
||||
}
|
||||
|
||||
if (VersionUtil.getSupportStatusClass() != null) {
|
||||
getLogger().info(AdventureUtil.miniToLegacy(tlLiteral("serverUnsupportedClass", VersionUtil.getSupportStatusClass())));
|
||||
getLogger().info(getAdventureFacet().miniToLegacy(tlLiteral("serverUnsupportedClass", VersionUtil.getSupportStatusClass())));
|
||||
}
|
||||
|
||||
if (VersionUtil.getServerBukkitVersion().isSnapshot()) {
|
||||
getLogger().severe(getAdventureFacet().miniToLegacy(tlLiteral("serverSnapshot")));
|
||||
}
|
||||
|
||||
if (PaperLib.isPaper() && !PaperLib.isVersion(13) && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_13_0_R01)) {
|
||||
PaperLib.setCustomEnvironment(new ModernPaperEnvironment());
|
||||
}
|
||||
|
||||
final PluginManager pm = getServer().getPluginManager();
|
||||
for (final Plugin plugin : pm.getPlugins()) {
|
||||
if (plugin.getDescription().getName().startsWith("Essentials") && !plugin.getDescription().getVersion().equals(this.getDescription().getVersion()) && !plugin.getDescription().getName().equals("EssentialsAntiCheat")) {
|
||||
getLogger().warning(AdventureUtil.miniToLegacy(tlLiteral("versionMismatch", plugin.getDescription().getName())));
|
||||
getLogger().warning(getAdventureFacet().miniToLegacy(tlLiteral("versionMismatch", plugin.getDescription().getName())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,6 +350,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
//Banner Meta Provider
|
||||
providerFactory.registerProvider(LegacyBannerDataProvider.class, BaseBannerDataProvider.class);
|
||||
|
||||
// Pattern Type Provider
|
||||
providerFactory.registerProvider(LegacyPatternTypeProvider.class, ModernPatternTypeProvider.class);
|
||||
|
||||
// Server State Provider
|
||||
providerFactory.registerProvider(ReflServerStateProvider.class, PaperServerStateProvider.class);
|
||||
|
||||
@@ -420,13 +398,21 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
// Inventory View Provider
|
||||
providerFactory.registerProvider(LegacyInventoryViewProvider.class, BaseInventoryViewProvider.class);
|
||||
|
||||
// Biome Name Provider
|
||||
providerFactory.registerProvider(LegacyBiomeNameProvider.class);
|
||||
|
||||
// Biome Key Provider
|
||||
providerFactory.registerProvider(PaperBiomeKeyProvider.class);
|
||||
|
||||
// Tile Entity Provider
|
||||
providerFactory.registerProvider(BukkitTileEntityProvider.class, PaperTileEntityProvider.class);
|
||||
|
||||
// Tick Count Provider
|
||||
providerFactory.registerProvider(PaperTickCountProvider.class);
|
||||
|
||||
providerFactory.finalizeRegistration();
|
||||
if (!TESTING) {
|
||||
providerFactory.finalizeRegistration();
|
||||
}
|
||||
|
||||
// Event Providers
|
||||
if (PaperLib.isPaper()) {
|
||||
@@ -464,15 +450,17 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
PermissionsDefaults.registerAllBackDefaults();
|
||||
PermissionsDefaults.registerAllHatDefaults();
|
||||
|
||||
updateChecker = new UpdateChecker(this);
|
||||
runTaskAsynchronously(() -> {
|
||||
getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("versionFetching")));
|
||||
for (final Component component : updateChecker.getVersionMessages(false, true, new CommandSource(this, Bukkit.getConsoleSender()))) {
|
||||
getLogger().log(getSettings().isUpdateCheckEnabled() ? Level.WARNING : Level.INFO, AdventureUtil.adventureToLegacy(component));
|
||||
}
|
||||
});
|
||||
if (!TESTING) {
|
||||
updateChecker = new UpdateChecker(this);
|
||||
runTaskAsynchronously(() -> {
|
||||
getLogger().log(Level.INFO, getAdventureFacet().miniToLegacy(tlLiteral("versionFetching")));
|
||||
for (final ComponentHolder component : updateChecker.getVersionMessages(false, true, new CommandSource(this, Bukkit.getConsoleSender()))) {
|
||||
getLogger().log(getSettings().isUpdateCheckEnabled() ? Level.WARNING : Level.INFO, getAdventureFacet().adventureToLegacy(component));
|
||||
}
|
||||
});
|
||||
|
||||
metrics = new MetricsWrapper(this, 858, true);
|
||||
metrics = new MetricsWrapper(this, 858, true);
|
||||
}
|
||||
|
||||
execTimer.mark("Init(External)");
|
||||
|
||||
@@ -486,7 +474,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
handleCrash(ex);
|
||||
throw ex;
|
||||
}
|
||||
getBackup().setPendingShutdown(false);
|
||||
if (!TESTING) {
|
||||
getBackup().setPendingShutdown(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns our provider logger if available
|
||||
@@ -554,11 +544,19 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
final boolean stopping = provider(ServerStateProvider.class).isStopping();
|
||||
if (!stopping) {
|
||||
LOGGER.log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("serverReloading")));
|
||||
if (adventureFacet != null) {
|
||||
adventureFacet.close();
|
||||
}
|
||||
getBackup().setPendingShutdown(true);
|
||||
|
||||
final boolean stopping = TESTING || provider(ServerStateProvider.class).isStopping();
|
||||
if (!stopping) {
|
||||
LOGGER.log(Level.SEVERE, getAdventureFacet().miniToLegacy(tlLiteral("serverReloading")));
|
||||
}
|
||||
|
||||
if (!TESTING) {
|
||||
getBackup().setPendingShutdown(true);
|
||||
}
|
||||
|
||||
for (final User user : getOnlineUsers()) {
|
||||
if (user.isVanished()) {
|
||||
user.setVanished(false);
|
||||
@@ -575,8 +573,8 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
}
|
||||
}
|
||||
cleanupOpenInventories();
|
||||
if (getBackup().getTaskLock() != null && !getBackup().getTaskLock().isDone()) {
|
||||
LOGGER.log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("backupInProgress")));
|
||||
if (!TESTING && getBackup().getTaskLock() != null && !getBackup().getTaskLock().isDone()) {
|
||||
LOGGER.log(Level.SEVERE, getAdventureFacet().miniToLegacy(tlLiteral("backupInProgress")));
|
||||
getBackup().getTaskLock().join();
|
||||
}
|
||||
if (i18n != null) {
|
||||
@@ -586,12 +584,18 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
backup.stopTask();
|
||||
}
|
||||
|
||||
this.getPermissionsHandler().unregisterContexts();
|
||||
if (!TESTING) {
|
||||
this.getPermissionsHandler().unregisterContexts();
|
||||
}
|
||||
|
||||
Economy.setEss(null);
|
||||
Trade.closeLog();
|
||||
getUsers().shutdown();
|
||||
|
||||
EssentialsConfiguration.shutdownExecutor();
|
||||
PasteUtil.shutdownExecutor();
|
||||
getServer().getScheduler().cancelTasks(this);
|
||||
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
@@ -599,11 +603,6 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
public void reload() {
|
||||
Trade.closeLog();
|
||||
|
||||
if (bukkitAudience != null) {
|
||||
bukkitAudience.close();
|
||||
bukkitAudience = null;
|
||||
}
|
||||
|
||||
for (final IConf iConf : confList) {
|
||||
iConf.reloadConfig();
|
||||
execTimer.mark("Reload(" + iConf.getClass().getSimpleName() + ")");
|
||||
@@ -613,16 +612,31 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
for (final String commandName : this.getDescription().getCommands().keySet()) {
|
||||
final Command command = this.getCommand(commandName);
|
||||
if (command != null) {
|
||||
command.setDescription(AdventureUtil.miniToLegacy(tlLiteral(commandName + "CommandDescription")));
|
||||
command.setUsage(AdventureUtil.miniToLegacy(tlLiteral(commandName + "CommandUsage")));
|
||||
command.setDescription(getAdventureFacet().miniToLegacy(tlLiteral(commandName + "CommandDescription")));
|
||||
command.setUsage(getAdventureFacet().miniToLegacy(tlLiteral(commandName + "CommandUsage")));
|
||||
}
|
||||
}
|
||||
|
||||
final PluginManager pm = getServer().getPluginManager();
|
||||
registerListeners(pm);
|
||||
|
||||
AdventureUtil.setEss(this);
|
||||
bukkitAudience = BukkitAudiences.create(this);
|
||||
initAdventureFacet();
|
||||
}
|
||||
|
||||
private void initAdventureFacet() {
|
||||
if (adventureFacet != null) {
|
||||
adventureFacet.close();
|
||||
}
|
||||
|
||||
// Paper only started bundling a modern enough native Adventure (with the MiniMessage TagResolver API)
|
||||
// in 1.18.2, so older versions must continue using our bundled Adventure via the Spigot facet.
|
||||
if (VersionUtil.isPaper() && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_18_2_R01)) {
|
||||
adventureFacet = new PaperAdventureFacet(getSettings() != null ? getSettings().getPrimaryColor() : null, getSettings() != null ? getSettings().getSecondaryColor() : null);
|
||||
} else {
|
||||
adventureFacet = new SpigotAdventureFacet(this);
|
||||
}
|
||||
|
||||
AdventureUtil.setAdventureFacet(adventureFacet);
|
||||
}
|
||||
|
||||
private IEssentialsCommand loadCommand(final String path, final String name, final IEssentialsModule module, final ClassLoader classLoader) throws Exception {
|
||||
@@ -687,7 +701,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
cmd = loadCommand(commandPath, command.getName(), module, classLoader);
|
||||
} catch (final Exception ex) {
|
||||
sender.sendTl("commandNotLoaded", commandLabel);
|
||||
LOGGER.log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("commandNotLoaded", commandLabel)), ex);
|
||||
LOGGER.log(Level.SEVERE, getAdventureFacet().miniToLegacy(tlLiteral("commandNotLoaded", commandLabel)), ex);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -710,11 +724,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
} catch (final Exception ex) {
|
||||
showError(sender, ex, commandLabel);
|
||||
// Tab completion shouldn't fail
|
||||
LOGGER.log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("commandFailed", commandLabel)), ex);
|
||||
LOGGER.log(Level.SEVERE, getAdventureFacet().miniToLegacy(tlLiteral("commandFailed", commandLabel)), ex);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
} catch (final Throwable ex) {
|
||||
LOGGER.log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("commandFailed", commandLabel)), ex);
|
||||
LOGGER.log(Level.SEVERE, getAdventureFacet().miniToLegacy(tlLiteral("commandFailed", commandLabel)), ex);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -741,7 +755,8 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
|
||||
if (cSender instanceof Player) {
|
||||
final PlayerLocaleProvider localeProvider = provider(PlayerLocaleProvider.class);
|
||||
getBukkitAudience().sender(cSender).sendMessage(AdventureUtil.miniMessage().deserialize(tlLocale(I18n.getLocale(localeProvider.getLocale((Player) cSender)), "internalError")));
|
||||
final String miniMessageStr = tlLocale(I18n.getLocale(localeProvider.getLocale((Player) cSender)), "internalError");
|
||||
getAdventureFacet().send(cSender, getAdventureFacet().deserializeMiniMessage(miniMessageStr));
|
||||
} else {
|
||||
cSender.sendMessage(tlLiteral("internalError"));
|
||||
}
|
||||
@@ -766,7 +781,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
LOGGER.log(Level.INFO, "CommandBlock at " + bSenderBlock.getX() + "," + bSenderBlock.getY() + "," + bSenderBlock.getZ() + " issued server command: /" + commandLabel + " " + EssentialsCommand.getFinalArg(args, 0));
|
||||
}
|
||||
} else if (user == null) {
|
||||
LOGGER.log(Level.INFO, cSender.getName()+ " issued server command: /" + commandLabel + " " + EssentialsCommand.getFinalArg(args, 0));
|
||||
if (getSettings().logConsoleCommands()) {
|
||||
LOGGER.log(Level.INFO, cSender.getName()+ " issued server command: /" + commandLabel + " " + EssentialsCommand.getFinalArg(args, 0));
|
||||
}
|
||||
}
|
||||
|
||||
final CommandSource sender = new CommandSource(this, cSender);
|
||||
@@ -797,13 +814,13 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
cmd = loadCommand(commandPath, command.getName(), module, classLoader);
|
||||
} catch (final Exception ex) {
|
||||
sender.sendTl("commandNotLoaded", commandLabel);
|
||||
LOGGER.log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("commandNotLoaded", commandLabel)), ex);
|
||||
LOGGER.log(Level.SEVERE, getAdventureFacet().miniToLegacy(tlLiteral("commandNotLoaded", commandLabel)), ex);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check authorization
|
||||
if (user != null && !user.isAuthorized(cmd, permissionPrefix)) {
|
||||
LOGGER.log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("deniedAccessCommand", user.getName())));
|
||||
LOGGER.log(Level.INFO, getAdventureFacet().miniToLegacy(tlLiteral("deniedAccessCommand", user.getName())));
|
||||
user.sendTl("noAccessCommand");
|
||||
return true;
|
||||
}
|
||||
@@ -837,14 +854,14 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
sender.sendTl("commandHelpLine2", description);
|
||||
sender.sendTl("commandHelpLine3");
|
||||
for (Map.Entry<String, String> usage : cmd.getUsageStrings().entrySet()) {
|
||||
sender.sendTl("commandHelpLineUsage", AdventureUtil.parsed(usage.getKey().replace("<command>", commandLabel)), AdventureUtil.parsed(usage.getValue()));
|
||||
sender.sendTl("commandHelpLineUsage", AdventureUtil.parsed(usage.getKey().replace("<command>", commandLabel)), AdventureUtil.parsed(sender.tl(usage.getValue())));
|
||||
}
|
||||
} else {
|
||||
sender.sendMessage(command.getDescription());
|
||||
sender.sendMessage(command.getUsage().replace("<command>", commandLabel));
|
||||
}
|
||||
if (!ex.getMessage().isEmpty()) {
|
||||
sender.sendComponent(AdventureUtil.miniMessage().deserialize(ex.getMessage()));
|
||||
sender.sendComponent(getAdventureFacet().deserializeMiniMessage(ex.getMessage()));
|
||||
}
|
||||
if (ex.getCause() != null && settings.isDebug()) {
|
||||
ex.getCause().printStackTrace();
|
||||
@@ -858,7 +875,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
return true;
|
||||
}
|
||||
} catch (final Throwable ex) {
|
||||
LOGGER.log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("commandFailed", commandLabel)), ex);
|
||||
LOGGER.log(Level.SEVERE, getAdventureFacet().miniToLegacy(tlLiteral("commandFailed", commandLabel)), ex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -894,7 +911,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
sender.sendTl("errorWithMessage", exception.getMessage());
|
||||
}
|
||||
if (getSettings().isDebug()) {
|
||||
LOGGER.log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("errorCallingCommand", commandLabel)), exception);
|
||||
LOGGER.log(Level.INFO, getAdventureFacet().miniToLegacy(tlLiteral("errorCallingCommand", commandLabel)), exception);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -903,6 +920,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
return this.getServer().getScheduler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Player> getJailedPlayers() {
|
||||
return getUsers().getAllUserUUIDs().stream().map(this::getUser).filter(Objects::nonNull).filter(User::isJailed).map(User::getBase).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IJails getJails() {
|
||||
return jails;
|
||||
@@ -979,13 +1001,23 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
final User user;
|
||||
Player exPlayer;
|
||||
|
||||
if (sourceUser != null && (searchTerm.equals("@p") || searchTerm.equals("@s"))) {
|
||||
return sourceUser;
|
||||
}
|
||||
|
||||
try {
|
||||
exPlayer = server.getPlayer(UUID.fromString(searchTerm));
|
||||
} catch (final IllegalArgumentException ex) {
|
||||
// Prefer exact online name match first always
|
||||
if (getOffline) {
|
||||
// When offline lookups are allowed, do not pick partial online matches here; allow exact offline match later
|
||||
exPlayer = server.getPlayerExact(searchTerm);
|
||||
} else {
|
||||
exPlayer = server.getPlayer(searchTerm);
|
||||
exPlayer = server.getPlayerExact(searchTerm);
|
||||
if (exPlayer == null) {
|
||||
// Only consider partial/prefix online match when not explicitly doing an offline-capable lookup
|
||||
exPlayer = server.getPlayer(searchTerm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1022,6 +1054,16 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Prefer exact username match among the matched players
|
||||
for (final Player player : matches) {
|
||||
if (player.getName().equalsIgnoreCase(searchTerm)) {
|
||||
final User userMatch = getUser(player);
|
||||
if (getHidden || canInteractWith(sourceUser, userMatch)) {
|
||||
return userMatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Then prefer display name/prefix match as before
|
||||
for (final Player player : matches) {
|
||||
final User userMatch = getUser(player);
|
||||
if (userMatch.getDisplayName().startsWith(searchTerm) && (getHidden || canInteractWith(sourceUser, userMatch))) {
|
||||
@@ -1143,7 +1185,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
final Collection<Player> players = getOnlinePlayers();
|
||||
for (final Player player : players) {
|
||||
final User user = getUser(player);
|
||||
if ((permission == null && (sender == null || !user.isIgnoredPlayer(sender))) || (permission != null && user.isAuthorized(permission))) {
|
||||
if (permission == null && (sender == null || !user.isIgnoredPlayer(sender)) || permission != null && user.isAuthorized(permission)) {
|
||||
if (shouldExclude != null && shouldExclude.test(user)) {
|
||||
continue;
|
||||
}
|
||||
@@ -1315,8 +1357,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
return this.getCommand(cmd);
|
||||
}
|
||||
|
||||
public BukkitAudiences getBukkitAudience() {
|
||||
return bukkitAudience;
|
||||
@Override
|
||||
public AdventureFacet getAdventureFacet() {
|
||||
return adventureFacet;
|
||||
}
|
||||
|
||||
private AbstractItemDb getItemDbFromConfig() {
|
||||
|
||||
@@ -156,7 +156,7 @@ public class EssentialsEntityListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onPlayerDeathEvent(final PlayerDeathEvent event) {
|
||||
final Entity entity = event.getEntity();
|
||||
if (entity.hasMetadata("NPC")) {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.destroystokyo.paper.ClientOption;
|
||||
import com.earth2me.essentials.adventure.ComponentHolder;
|
||||
import com.earth2me.essentials.commands.Commandfireball;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.textreader.IText;
|
||||
import com.earth2me.essentials.textreader.KeywordReplacer;
|
||||
import com.earth2me.essentials.textreader.TextInput;
|
||||
import com.earth2me.essentials.textreader.TextPager;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.userstorage.ModernUserMap;
|
||||
import com.earth2me.essentials.utils.CommonPlaceholders;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
@@ -14,6 +16,9 @@ import com.earth2me.essentials.utils.LocationUtil;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import io.papermc.paper.ban.BanListType;
|
||||
import io.papermc.paper.event.connection.configuration.AsyncPlayerConnectionConfigureEvent;
|
||||
import io.papermc.paper.event.player.PlayerServerFullCheckEvent;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.events.AfkStatusChangeEvent;
|
||||
import net.ess3.provider.CommandSendListenerProvider;
|
||||
@@ -23,8 +28,8 @@ import net.ess3.provider.KnownCommandsProvider;
|
||||
import net.ess3.provider.TickCountProvider;
|
||||
import net.ess3.provider.providers.BukkitCommandSendListenerProvider;
|
||||
import net.ess3.provider.providers.PaperCommandSendListenerProvider;
|
||||
import net.essentialsx.PaperAdventureSmuggler;
|
||||
import net.essentialsx.api.v2.events.AsyncUserDataLoadEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.BanEntry;
|
||||
import org.bukkit.BanList;
|
||||
import org.bukkit.GameMode;
|
||||
@@ -43,17 +48,19 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
|
||||
import org.bukkit.event.player.PlayerBucketEmptyEvent;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerEggThrowEvent;
|
||||
import org.bukkit.event.player.PlayerFishEvent;
|
||||
import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
@@ -73,17 +80,19 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tlLiteral;
|
||||
|
||||
public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
public class EssentialsPlayerListener implements Listener {
|
||||
private final transient IEssentials ess;
|
||||
private final ConcurrentHashMap<UUID, Integer> pendingMotdTasks = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -158,6 +167,14 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
} else if (isCommandSendEvent()) {
|
||||
ess.getServer().getPluginManager().registerEvents(new BukkitCommandSendListenerProvider(new CommandSendFilter()), ess);
|
||||
}
|
||||
|
||||
if (VersionUtil.isPaper() && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_21_8_R01)) {
|
||||
ess.getServer().getPluginManager().registerEvents(new LoginListener1_21(), ess);
|
||||
ess.getServer().getPluginManager().registerEvents(new JoinListener1_21(), ess);
|
||||
} else {
|
||||
ess.getServer().getPluginManager().registerEvents(new LoginListenerPre1_21(), ess);
|
||||
ess.getServer().getPluginManager().registerEvents(new JoinListenerPre1_21(), ess);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
@@ -176,23 +193,8 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isMuted()) {
|
||||
event.setCancelled(true);
|
||||
|
||||
final String dateDiff = user.getMuteTimeout() > 0 ? DateUtil.formatDateDiff(user.getMuteTimeout()) : null;
|
||||
if (dateDiff == null) {
|
||||
if (user.hasMuteReason()) {
|
||||
user.sendTl("voiceSilencedReason", user.getMuteReason());
|
||||
} else {
|
||||
user.sendTl("voiceSilenced");
|
||||
}
|
||||
} else {
|
||||
if (user.hasMuteReason()) {
|
||||
user.sendTl("voiceSilencedReasonTime", dateDiff, user.getMuteReason());
|
||||
} else {
|
||||
user.sendTl("voiceSilencedTime", dateDiff);
|
||||
}
|
||||
}
|
||||
|
||||
ess.getLogger().info(AdventureUtil.miniToLegacy(tlLiteral("mutedUserSpeaks", user.getName(), event.getMessage())));
|
||||
user.notifyMuted();
|
||||
ess.getLogger().info(ess.getAdventureFacet().miniToLegacy(tlLiteral("mutedUserSpeaks", user.getName(), event.getMessage())));
|
||||
}
|
||||
try {
|
||||
final Iterator<Player> it = event.getRecipients().iterator();
|
||||
@@ -277,7 +279,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
ess.getScheduler().cancelTask(pendingId);
|
||||
}
|
||||
|
||||
if (hideJoinQuitMessages() || (ess.getSettings().allowSilentJoinQuit() && user.isAuthorized("essentials.silentquit"))) {
|
||||
if (hideJoinQuitMessages() || ess.getSettings().allowSilentJoinQuit() && user.isAuthorized("essentials.silentquit")) {
|
||||
event.setQuitMessage(null);
|
||||
} else if (ess.getSettings().isCustomQuitMessage() && event.getQuitMessage() != null) {
|
||||
final Player player = event.getPlayer();
|
||||
@@ -324,8 +326,72 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
user.dispose();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerJoin(final PlayerJoinEvent event) {
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
private final class JoinListener1_21 implements Listener {
|
||||
private final Map<UUID, String> newUserLocales = new ConcurrentHashMap<>();
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerConfigure(final AsyncPlayerConnectionConfigureEvent event) {
|
||||
ess.getBackup().onPlayerJoin();
|
||||
final User dUser = ess.getUser(event.getConnection().getProfile().getId());
|
||||
|
||||
// Force loading of the locale bundle while we are async to ensure it's ready when the player joins.
|
||||
final String locale = event.getConnection().getClientOption(ClientOption.LOCALE);
|
||||
ess.getI18n().blockingLoadBundle(I18n.getLocale(locale));
|
||||
|
||||
// This is a first time join, we have to wait until the bukkit Player object is created to create the User object.
|
||||
// So we store the locale here and apply it when the PlayerJoinEvent is fired.
|
||||
if (dUser == null) {
|
||||
newUserLocales.put(event.getConnection().getProfile().getId(), locale);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the locale for player to preload the language bundle.
|
||||
dUser.getPlayerLocale(locale);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerJoin(final PlayerJoinEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user == null) {
|
||||
legacyJoinFlow(event);
|
||||
return;
|
||||
}
|
||||
|
||||
user.update(event.getPlayer());
|
||||
|
||||
// If this is a new user, we set their locale that we stored earlier.
|
||||
final String locale = newUserLocales.remove(user.getUUID());
|
||||
if (locale != null) {
|
||||
user.getPlayerLocale(locale);
|
||||
}
|
||||
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
user.startTransaction();
|
||||
if (user.isNPC()) {
|
||||
user.setNPC(false);
|
||||
}
|
||||
|
||||
user.checkMuteTimeout(currentTime);
|
||||
user.updateActivity(false, AfkStatusChangeEvent.Cause.JOIN);
|
||||
user.stopTransaction();
|
||||
|
||||
joinFlow(user, currentTime, event.getJoinMessage(), event::setJoinMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private final class JoinListenerPre1_21 implements Listener {
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerJoin(final PlayerJoinEvent event) {
|
||||
legacyJoinFlow(event);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hideJoinQuitMessages() {
|
||||
return ess.getSettings().hasJoinQuitMessagePlayerCount() && ess.getServer().getOnlinePlayers().size() > ess.getSettings().getJoinQuitMessagePlayerCount();
|
||||
}
|
||||
|
||||
private void legacyJoinFlow(final PlayerJoinEvent event) {
|
||||
final String joinMessage = event.getJoinMessage();
|
||||
ess.runTaskAsynchronously(() -> delayedJoin(event.getPlayer(), joinMessage));
|
||||
|
||||
@@ -334,17 +400,185 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hideJoinQuitMessages() {
|
||||
return ess.getSettings().hasJoinQuitMessagePlayerCount() && ess.getServer().getOnlinePlayers().size() > ess.getSettings().getJoinQuitMessagePlayerCount();
|
||||
private void joinFlow(final User user, final long currentTime, final String message, final Consumer<String> joinMessageConsumer) {
|
||||
user.startTransaction();
|
||||
|
||||
final String lastAccountName = user.getLastAccountName(); // For comparison
|
||||
user.setLastAccountName(user.getBase().getName());
|
||||
|
||||
final boolean newUsername = lastAccountName != null && !lastAccountName.equals(user.getBase().getName());
|
||||
|
||||
// A null last account name means EssentialsX has never recorded this player before, i.e. it's their first join.
|
||||
// We rely on EssentialsX's own user data here rather than Player#hasPlayedBefore(), which is unreliable on modern
|
||||
// server platforms that persist player data during the login/configuration phase.
|
||||
// See https://github.com/EssentialsX/Essentials/issues/6466, https://github.com/EssentialsX/Essentials/issues/6464
|
||||
final boolean firstJoin = lastAccountName == null;
|
||||
|
||||
// If the Minecraft account name changed, reset the nickname so the old one doesn't persist
|
||||
if (ess.getSettings().isResetNickOnNameChange() && newUsername && user.getNickname() != null) {
|
||||
user.setNickname(null);
|
||||
}
|
||||
|
||||
user.setLastLogin(currentTime);
|
||||
user.setDisplayNick();
|
||||
updateCompass(user);
|
||||
user.setLeavingHidden(false);
|
||||
|
||||
if (!ess.getVanishedPlayersNew().isEmpty() && !user.isAuthorized("essentials.vanish.see")) {
|
||||
for (final String p : ess.getVanishedPlayersNew()) {
|
||||
final Player toVanish = ess.getServer().getPlayerExact(p);
|
||||
if (toVanish != null && toVanish.isOnline()) {
|
||||
user.getBase().hidePlayer(toVanish);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Hiding vanished player: " + p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (user.isAuthorized("essentials.sleepingignored")) {
|
||||
user.getBase().setSleepingIgnored(true);
|
||||
}
|
||||
|
||||
final String effectiveMessage;
|
||||
if (ess.getSettings().allowSilentJoinQuit() && (user.isAuthorized("essentials.silentjoin") || user.isAuthorized("essentials.silentjoin.vanish"))) {
|
||||
if (user.isAuthorized("essentials.silentjoin.vanish")) {
|
||||
user.setVanished(true);
|
||||
}
|
||||
effectiveMessage = null;
|
||||
} else if (message == null || hideJoinQuitMessages()) {
|
||||
effectiveMessage = null;
|
||||
} else if (ess.getSettings().isCustomJoinMessage()) {
|
||||
final String msg = (newUsername && ess.getSettings().isCustomNewUsernameMessage() ? ess.getSettings().getCustomNewUsernameMessage() : ess.getSettings().getCustomJoinMessage())
|
||||
.replace("{PLAYER}", user.getDisplayName()).replace("{USERNAME}", user.getName())
|
||||
.replace("{UNIQUE}", NumberFormat.getInstance().format(ess.getUsers().getUserCount()))
|
||||
.replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size()))
|
||||
.replace("{UPTIME}", DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime()))
|
||||
.replace("{PREFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getPrefix(user.getBase())))
|
||||
.replace("{SUFFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getSuffix(user.getBase())))
|
||||
.replace("{OLDUSERNAME}", lastAccountName == null ? "" : lastAccountName);
|
||||
effectiveMessage = msg.isEmpty() ? null : msg;
|
||||
} else if (ess.getSettings().allowSilentJoinQuit()) {
|
||||
effectiveMessage = message;
|
||||
} else {
|
||||
effectiveMessage = message;
|
||||
}
|
||||
|
||||
// Only change the vanilla join message if it's different to avoid nuking client translation
|
||||
if (effectiveMessage != null && !effectiveMessage.equals(message) || message != null && effectiveMessage == null) {
|
||||
joinMessageConsumer.accept(effectiveMessage);
|
||||
}
|
||||
|
||||
ess.runTaskAsynchronously(() -> ess.getServer().getPluginManager().callEvent(new AsyncUserDataLoadEvent(user, effectiveMessage, firstJoin)));
|
||||
|
||||
if (ess.getSettings().getMotdDelay() >= 0) {
|
||||
final int motdDelay = ess.getSettings().getMotdDelay() / 50;
|
||||
final Runnable motdTask = () -> motdFlow(user);
|
||||
if (motdDelay > 0) {
|
||||
pendingMotdTasks.put(user.getUUID(), ess.scheduleSyncDelayedTask(motdTask, motdDelay));
|
||||
} else {
|
||||
motdTask.run();
|
||||
}
|
||||
}
|
||||
|
||||
if (!ess.getSettings().isCommandDisabled("mail") && user.isAuthorized("essentials.mail")) {
|
||||
if (user.getUnreadMailAmount() == 0) {
|
||||
if (ess.getSettings().isNotifyNoNewMail()) {
|
||||
user.sendTl("noNewMail"); // Only notify if they want us to.
|
||||
}
|
||||
} else {
|
||||
user.notifyOfMail();
|
||||
}
|
||||
}
|
||||
|
||||
if (user.isAuthorized("essentials.updatecheck")) {
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
for (final ComponentHolder component : ess.getUpdateChecker().getVersionMessages(false, false, user.getSource())) {
|
||||
user.sendComponent(component);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final boolean restoreFly = user.isFlyModeEnabled() && user.isAuthorized("essentials.fly");
|
||||
if (restoreFly) {
|
||||
user.getBase().setAllowFlight(true);
|
||||
if (ess.getSettings().isSendFlyEnableOnJoin()) {
|
||||
user.sendTl("flyMode", CommonPlaceholders.enableDisable(user.getSource(), true), user.getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
if (user.isAuthorized("essentials.fly.safelogin")) {
|
||||
user.getBase().setFallDistance(0);
|
||||
final boolean inWater = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_17_R01) && user.getBase().isInWater();
|
||||
if (!inWater && LocationUtil.shouldFly(ess, user.getLocation())) {
|
||||
user.getBase().setAllowFlight(true);
|
||||
user.getBase().setFlying(true);
|
||||
if (!restoreFly && ess.getSettings().isSendFlyEnableOnJoin()) {
|
||||
user.sendTl("flyMode", CommonPlaceholders.enableDisable(user.getSource(), true), user.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!user.isAuthorized("essentials.speed")) {
|
||||
user.getBase().setFlySpeed(0.1f);
|
||||
user.getBase().setWalkSpeed(0.2f);
|
||||
}
|
||||
|
||||
if (user.isSocialSpyEnabled() && !user.isAuthorized("essentials.socialspy")) {
|
||||
user.setSocialSpyEnabled(false);
|
||||
ess.getLogger().log(Level.INFO, "Set socialspy to false for {0} because they had it enabled without permission.", user.getName());
|
||||
}
|
||||
|
||||
if (user.isFlyModeEnabled() && !user.isAuthorized("essentials.fly")) {
|
||||
user.setFlyModeEnabled(false);
|
||||
ess.getLogger().log(Level.INFO, "Set fly mode to false for {0} because they had it enabled without permission.", user.getName());
|
||||
}
|
||||
|
||||
if (user.isGodModeEnabled() && !user.isAuthorized("essentials.god")) {
|
||||
user.setGodModeEnabled(false);
|
||||
ess.getLogger().log(Level.INFO, "Set god mode to false for {0} because they had it enabled without permission.", user.getName());
|
||||
}
|
||||
|
||||
user.setConfirmingClearCommand(null);
|
||||
user.getConfirmingPayments().clear();
|
||||
|
||||
user.stopTransaction();
|
||||
}
|
||||
|
||||
public void delayedJoin(final Player player, final String message) {
|
||||
private void motdFlow(final User user) {
|
||||
pendingMotdTasks.remove(user.getUUID());
|
||||
|
||||
IText tempInput = null;
|
||||
|
||||
if (!ess.getSettings().isCommandDisabled("motd")) {
|
||||
try {
|
||||
tempInput = new TextInput(user.getSource(), "motd", true, ess);
|
||||
} catch (final IOException ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.WARNING, ex.getMessage(), ex);
|
||||
} else {
|
||||
ess.getLogger().log(Level.WARNING, ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final IText input = tempInput;
|
||||
|
||||
if (input != null && !input.getLines().isEmpty() && user.isAuthorized("essentials.motd")) {
|
||||
final IText output = new KeywordReplacer(input, user.getSource(), ess);
|
||||
final TextPager pager = new TextPager(output, true);
|
||||
pager.showPage("1", null, "motd", user.getSource());
|
||||
}
|
||||
}
|
||||
|
||||
private void delayedJoin(final Player player, final String message) {
|
||||
if (!player.isOnline()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ess.getBackup().onPlayerJoin();
|
||||
final User dUser = ess.getUser(player);
|
||||
((ModernUserMap) ess.getUsers()).getOnlineUserCache().put(player.getUniqueId(), dUser);
|
||||
dUser.update(player);
|
||||
|
||||
dUser.startTransaction();
|
||||
@@ -357,170 +591,19 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
dUser.updateActivity(false, AfkStatusChangeEvent.Cause.JOIN);
|
||||
dUser.stopTransaction();
|
||||
|
||||
class DelayJoinTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
final User user = ess.getUser(player);
|
||||
ess.scheduleSyncDelayedTask(() -> {
|
||||
final User user = ess.getUser(player);
|
||||
|
||||
if (!user.getBase().isOnline()) {
|
||||
return;
|
||||
}
|
||||
|
||||
user.startTransaction();
|
||||
|
||||
final String lastAccountName = user.getLastAccountName(); // For comparison
|
||||
user.setLastAccountName(user.getBase().getName());
|
||||
user.setLastLogin(currentTime);
|
||||
user.setDisplayNick();
|
||||
updateCompass(user);
|
||||
user.setLeavingHidden(false);
|
||||
|
||||
// Check for new username. If they don't want the message, let's just say it's false.
|
||||
final boolean newUsername = ess.getSettings().isCustomNewUsernameMessage() && lastAccountName != null && !lastAccountName.equals(user.getBase().getName());
|
||||
|
||||
if (!ess.getVanishedPlayersNew().isEmpty() && !user.isAuthorized("essentials.vanish.see")) {
|
||||
for (final String p : ess.getVanishedPlayersNew()) {
|
||||
final Player toVanish = ess.getServer().getPlayerExact(p);
|
||||
if (toVanish != null && toVanish.isOnline()) {
|
||||
user.getBase().hidePlayer(toVanish);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Hiding vanished player: " + p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (user.isAuthorized("essentials.sleepingignored")) {
|
||||
user.getBase().setSleepingIgnored(true);
|
||||
}
|
||||
|
||||
final String effectiveMessage;
|
||||
if (ess.getSettings().allowSilentJoinQuit() && (user.isAuthorized("essentials.silentjoin") || user.isAuthorized("essentials.silentjoin.vanish"))) {
|
||||
if (user.isAuthorized("essentials.silentjoin.vanish")) {
|
||||
user.setVanished(true);
|
||||
}
|
||||
effectiveMessage = null;
|
||||
} else if (message == null || hideJoinQuitMessages()) {
|
||||
effectiveMessage = null;
|
||||
} else if (ess.getSettings().isCustomJoinMessage()) {
|
||||
final String msg = (newUsername ? ess.getSettings().getCustomNewUsernameMessage() : ess.getSettings().getCustomJoinMessage())
|
||||
.replace("{PLAYER}", player.getDisplayName()).replace("{USERNAME}", player.getName())
|
||||
.replace("{UNIQUE}", NumberFormat.getInstance().format(ess.getUsers().getUserCount()))
|
||||
.replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size()))
|
||||
.replace("{UPTIME}", DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime()))
|
||||
.replace("{PREFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getPrefix(player)))
|
||||
.replace("{SUFFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getSuffix(player)))
|
||||
.replace("{OLDUSERNAME}", lastAccountName == null ? "" : lastAccountName);
|
||||
if (!msg.isEmpty()) {
|
||||
ess.getServer().broadcastMessage(msg);
|
||||
}
|
||||
effectiveMessage = msg.isEmpty() ? null : msg;
|
||||
} else if (ess.getSettings().allowSilentJoinQuit()) {
|
||||
ess.getServer().broadcastMessage(message);
|
||||
effectiveMessage = message;
|
||||
} else {
|
||||
effectiveMessage = message;
|
||||
}
|
||||
|
||||
ess.runTaskAsynchronously(() -> ess.getServer().getPluginManager().callEvent(new AsyncUserDataLoadEvent(user, effectiveMessage)));
|
||||
|
||||
if (ess.getSettings().getMotdDelay() >= 0) {
|
||||
final int motdDelay = ess.getSettings().getMotdDelay() / 50;
|
||||
final DelayMotdTask motdTask = new DelayMotdTask(user);
|
||||
if (motdDelay > 0) {
|
||||
pendingMotdTasks.put(user.getUUID(), ess.scheduleSyncDelayedTask(motdTask, motdDelay));
|
||||
} else {
|
||||
motdTask.run();
|
||||
}
|
||||
}
|
||||
|
||||
if (!ess.getSettings().isCommandDisabled("mail") && user.isAuthorized("essentials.mail")) {
|
||||
if (user.getUnreadMailAmount() == 0) {
|
||||
if (ess.getSettings().isNotifyNoNewMail()) {
|
||||
user.sendTl("noNewMail"); // Only notify if they want us to.
|
||||
}
|
||||
} else {
|
||||
user.notifyOfMail();
|
||||
}
|
||||
}
|
||||
|
||||
if (user.isAuthorized("essentials.updatecheck")) {
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
for (final Component component : ess.getUpdateChecker().getVersionMessages(false, false, user.getSource())) {
|
||||
user.sendComponent(component);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (user.isAuthorized("essentials.fly.safelogin")) {
|
||||
user.getBase().setFallDistance(0);
|
||||
if (LocationUtil.shouldFly(ess, user.getLocation())) {
|
||||
user.getBase().setAllowFlight(true);
|
||||
user.getBase().setFlying(true);
|
||||
if (ess.getSettings().isSendFlyEnableOnJoin()) {
|
||||
user.sendTl("flyMode", CommonPlaceholders.enableDisable(user.getSource(), true), user.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!user.isAuthorized("essentials.speed")) {
|
||||
user.getBase().setFlySpeed(0.1f);
|
||||
user.getBase().setWalkSpeed(0.2f);
|
||||
}
|
||||
|
||||
if (user.isSocialSpyEnabled() && !user.isAuthorized("essentials.socialspy")) {
|
||||
user.setSocialSpyEnabled(false);
|
||||
ess.getLogger().log(Level.INFO, "Set socialspy to false for {0} because they had it enabled without permission.", user.getName());
|
||||
}
|
||||
|
||||
if (user.isGodModeEnabled() && !user.isAuthorized("essentials.god")) {
|
||||
user.setGodModeEnabled(false);
|
||||
ess.getLogger().log(Level.INFO, "Set god mode to false for {0} because they had it enabled without permission.", user.getName());
|
||||
}
|
||||
|
||||
user.setConfirmingClearCommand(null);
|
||||
user.getConfirmingPayments().clear();
|
||||
|
||||
user.stopTransaction();
|
||||
if (!user.getBase().isOnline()) {
|
||||
return;
|
||||
}
|
||||
|
||||
class DelayMotdTask implements Runnable {
|
||||
private final User user;
|
||||
|
||||
DelayMotdTask(final User user) {
|
||||
this.user = user;
|
||||
joinFlow(user, currentTime, message, msg -> {
|
||||
if (msg != null && !msg.isEmpty()) {
|
||||
ess.getServer().broadcastMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
pendingMotdTasks.remove(user.getUUID());
|
||||
|
||||
IText tempInput = null;
|
||||
|
||||
if (!ess.getSettings().isCommandDisabled("motd")) {
|
||||
try {
|
||||
tempInput = new TextInput(user.getSource(), "motd", true, ess);
|
||||
} catch (final IOException ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.WARNING, ex.getMessage(), ex);
|
||||
} else {
|
||||
ess.getLogger().log(Level.WARNING, ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final IText input = tempInput;
|
||||
|
||||
if (input != null && !input.getLines().isEmpty() && user.isAuthorized("essentials.motd")) {
|
||||
final IText output = new KeywordReplacer(input, user.getSource(), ess);
|
||||
final TextPager pager = new TextPager(output, true);
|
||||
pager.showPage("1", null, "motd", user.getSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ess.scheduleSyncDelayedTask(new DelayJoinTask());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Makes the compass item ingame always point to the first essentials home. #EasterEgg
|
||||
@@ -540,38 +623,95 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
user.getBase().setCompassTarget(loc);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerLoginBanned(final PlayerLoginEvent event) {
|
||||
if (event.getResult() == Result.KICK_BANNED) {
|
||||
BanEntry banEntry = ess.getServer().getBanList(BanList.Type.NAME).getBanEntry(event.getPlayer().getName());
|
||||
if (banEntry != null) {
|
||||
final Date banExpiry = banEntry.getExpiration();
|
||||
if (banExpiry != null) {
|
||||
final String expiry = DateUtil.formatDateDiff(banExpiry.getTime());
|
||||
event.setKickMessage(AdventureUtil.miniToLegacy(tlLiteral("tempbanJoin", expiry, banEntry.getReason())));
|
||||
} else {
|
||||
event.setKickMessage(AdventureUtil.miniToLegacy(tlLiteral("banJoin", banEntry.getReason())));
|
||||
}
|
||||
} else {
|
||||
banEntry = ess.getServer().getBanList(BanList.Type.IP).getBanEntry(event.getAddress().getHostAddress());
|
||||
private final class LoginListenerPre1_21 implements Listener {
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerLoginBanned(final PlayerLoginEvent event) {
|
||||
if (event.getResult() == PlayerLoginEvent.Result.KICK_BANNED) {
|
||||
BanEntry banEntry = ess.getServer().getBanList(BanList.Type.NAME).getBanEntry(event.getPlayer().getName());
|
||||
if (banEntry != null) {
|
||||
event.setKickMessage(AdventureUtil.miniToLegacy(tlLiteral("banIpJoin", banEntry.getReason())));
|
||||
final Date banExpiry = banEntry.getExpiration();
|
||||
if (banExpiry != null) {
|
||||
final String expiry = DateUtil.formatDateDiff(banExpiry.getTime());
|
||||
event.setKickMessage(ess.getAdventureFacet().miniToLegacy(tlLiteral("tempbanJoin", expiry, banEntry.getReason())));
|
||||
} else {
|
||||
event.setKickMessage(ess.getAdventureFacet().miniToLegacy(tlLiteral("banJoin", banEntry.getReason())));
|
||||
}
|
||||
} else {
|
||||
banEntry = ess.getServer().getBanList(BanList.Type.IP).getBanEntry(event.getAddress().getHostAddress());
|
||||
if (banEntry != null) {
|
||||
final Date banExpiry = banEntry.getExpiration();
|
||||
if (banExpiry != null) {
|
||||
final String expiry = DateUtil.formatDateDiff(banExpiry.getTime());
|
||||
event.setKickMessage(ess.getAdventureFacet().miniToLegacy(tlLiteral("tempbanIpJoin", expiry, banEntry.getReason())));
|
||||
} else {
|
||||
event.setKickMessage(ess.getAdventureFacet().miniToLegacy(tlLiteral("banIpJoin", banEntry.getReason())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerLogin(final PlayerLoginEvent event) {
|
||||
if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL) {
|
||||
final User kfuser = ess.getUser(event.getPlayer());
|
||||
kfuser.update(event.getPlayer());
|
||||
if (kfuser.isAuthorized("essentials.joinfullserver")) {
|
||||
event.allow();
|
||||
return;
|
||||
}
|
||||
if (ess.getSettings().isCustomServerFullMessage()) {
|
||||
event.disallow(PlayerLoginEvent.Result.KICK_FULL, tlLiteral("serverFull"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerLogin(final PlayerLoginEvent event) {
|
||||
if (event.getResult() == Result.KICK_FULL) {
|
||||
final User kfuser = ess.getUser(event.getPlayer());
|
||||
kfuser.update(event.getPlayer());
|
||||
if (kfuser.isAuthorized("essentials.joinfullserver")) {
|
||||
event.allow();
|
||||
private final class LoginListener1_21 implements Listener {
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerListFull(final PlayerServerFullCheckEvent event) {
|
||||
if (ess.getPermissionsHandler().isOfflinePermissionSet(event.getPlayerProfile().getId(), "essentials.joinfullserver")) {
|
||||
event.allow(true);
|
||||
return;
|
||||
}
|
||||
if (ess.getSettings().isCustomServerFullMessage()) {
|
||||
event.disallow(Result.KICK_FULL, tlLiteral("serverFull"));
|
||||
|
||||
if (!event.isAllowed() && ess.getSettings().isCustomServerFullMessage()) {
|
||||
PaperAdventureSmuggler.smugglePlayerServerFullCheckEvent(event, ess.getAdventureFacet().miniToLegacy(tlLiteral("serverFull")));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerKickBanned(final AsyncPlayerPreLoginEvent event) {
|
||||
if (event.getLoginResult() == AsyncPlayerPreLoginEvent.Result.KICK_BANNED) {
|
||||
BanEntry<?> banEntry = ess.getServer().getBanList(BanListType.PROFILE).getBanEntry(event.getPlayerProfile());
|
||||
if (banEntry != null) {
|
||||
final Date banExpiry = banEntry.getExpiration();
|
||||
if (banExpiry != null) {
|
||||
final String expiry = DateUtil.formatDateDiff(banExpiry.getTime());
|
||||
event.setKickMessage(ess.getAdventureFacet().miniToLegacy(tlLiteral("tempbanJoin", expiry, banEntry.getReason())));
|
||||
} else {
|
||||
event.setKickMessage(ess.getAdventureFacet().miniToLegacy(tlLiteral("banJoin", banEntry.getReason())));
|
||||
}
|
||||
} else {
|
||||
banEntry = ess.getServer().getBanList(BanListType.IP).getBanEntry(event.getAddress());
|
||||
if (banEntry != null) {
|
||||
final Date banExpiry = banEntry.getExpiration();
|
||||
if (banExpiry != null) {
|
||||
final String expiry = DateUtil.formatDateDiff(banExpiry.getTime());
|
||||
event.setKickMessage(ess.getAdventureFacet().miniToLegacy(tlLiteral("tempbanIpJoin", expiry, banEntry.getReason())));
|
||||
} else {
|
||||
event.setKickMessage(ess.getAdventureFacet().miniToLegacy(tlLiteral("banIpJoin", banEntry.getReason())));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (event.getLoginResult() == AsyncPlayerPreLoginEvent.Result.KICK_WHITELIST) {
|
||||
if (ess.getPermissionsHandler().isOfflinePermissionSet(event.getUniqueId(), "essentials.whitelist.bypass")) {
|
||||
event.allow();
|
||||
return;
|
||||
}
|
||||
if (ess.getSettings().isCustomWhitelistMessage()) {
|
||||
event.setKickMessage(ess.getAdventureFacet().miniToLegacy(tlLiteral("whitelistKick")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -655,16 +795,18 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
|
||||
if (ess.getSettings().getSocialSpyCommands().contains(cmd) || ess.getSettings().getSocialSpyCommands().contains("*")) {
|
||||
if (pluginCommand == null
|
||||
|| (!pluginCommand.getName().equals("msg") && !pluginCommand.getName().equals("r"))) { // /msg and /r are handled in SimpleMessageRecipient
|
||||
|| !pluginCommand.getName().equals("msg") && !pluginCommand.getName().equals("r")) { // /msg and /r are handled in SimpleMessageRecipient
|
||||
final User user = ess.getUser(player);
|
||||
if (!user.isAuthorized("essentials.chat.spy.exempt")) {
|
||||
final String playerName = ess.getSettings().isSocialSpyDisplayNames() ? player.getDisplayName() : player.getName();
|
||||
for (final User spyer : ess.getOnlineUsers()) {
|
||||
if (spyer.isSocialSpyEnabled() && !player.equals(spyer.getBase())) {
|
||||
final Component base = (user.isMuted() && ess.getSettings().getSocialSpyListenMutedPlayers())
|
||||
final ComponentHolder base = (user.isMuted() && ess.getSettings().getSocialSpyListenMutedPlayers())
|
||||
? spyer.tlComponent("socialSpyMutedPrefix")
|
||||
: spyer.tlComponent("socialSpyPrefix");
|
||||
spyer.sendComponent(base.append(AdventureUtil.legacyToAdventure(playerName)).append(Component.text(": " + event.getMessage())));
|
||||
final ComponentHolder formatted = ess.getAdventureFacet().deserializeMiniMessage(spyer.playerTl("socialSpyCmdFormat", playerName, event.getMessage()));
|
||||
|
||||
spyer.sendComponent(ess.getAdventureFacet().append(base, formatted));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -674,21 +816,8 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
final User user = ess.getUser(player);
|
||||
if (user.isMuted() && (ess.getSettings().getMuteCommands().contains(cmd) || ess.getSettings().getMuteCommands().contains("*"))) {
|
||||
event.setCancelled(true);
|
||||
final String dateDiff = user.getMuteTimeout() > 0 ? DateUtil.formatDateDiff(user.getMuteTimeout()) : null;
|
||||
if (dateDiff == null) {
|
||||
if (user.hasMuteReason()) {
|
||||
user.sendTl("voiceSilencedReason", user.getMuteReason());
|
||||
} else {
|
||||
user.sendTl("voiceSilenced");
|
||||
}
|
||||
} else {
|
||||
if (user.hasMuteReason()) {
|
||||
user.sendTl("voiceSilencedReasonTime", dateDiff, user.getMuteReason());
|
||||
} else {
|
||||
user.sendTl("voiceSilencedTime", dateDiff);
|
||||
}
|
||||
}
|
||||
ess.getLogger().info(AdventureUtil.miniToLegacy(tlLiteral("mutedUserSpeaks", player.getName(), event.getMessage())));
|
||||
user.notifyMuted();
|
||||
ess.getLogger().info(ess.getAdventureFacet().miniToLegacy(tlLiteral("mutedUserSpeaks", player.getName(), event.getMessage())));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -984,6 +1113,26 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
return false;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onInventoryDragEvent(final InventoryDragEvent event) {
|
||||
final InventoryViewProvider provider = ess.provider(InventoryViewProvider.class);
|
||||
final Inventory top = provider.getTopInventory(event.getView());
|
||||
if (top.getType() != InventoryType.PLAYER) {
|
||||
return;
|
||||
}
|
||||
final User user = ess.getUser((Player) event.getWhoClicked());
|
||||
if (!user.isInvSee()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int slot : event.getNewItems().keySet()) {
|
||||
if (Inventories.isBottomInventorySlot(slot)) {
|
||||
event.setCancelled(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onInventoryCloseEvent(final InventoryCloseEvent event) {
|
||||
Player refreshPlayer = null;
|
||||
@@ -1021,10 +1170,35 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onPlayerFishEvent(final PlayerFishEvent event) {
|
||||
if (!ess.getSettings().cancelAfkOnFish()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
user.updateActivityOnInteract(true);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPlayerGameModeChange(final PlayerGameModeChangeEvent event) {
|
||||
if (!ess.getSettings().isGamemodeChangePreserveFlying()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (!user.isAuthorized("essentials.fly")) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Player player = event.getPlayer();
|
||||
if (player.isFlying() && player.getAllowFlight() && user.isAuthorized("essentials.fly")) {
|
||||
// The gamemode change happens after the event, so we need to delay the flight enable
|
||||
ess.scheduleSyncDelayedTask(() -> {
|
||||
player.setAllowFlight(true);
|
||||
player.setFlying(true);
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ArrowPickupListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onArrowPickup(final org.bukkit.event.player.PlayerPickupArrowEvent event) {
|
||||
@@ -1039,10 +1213,12 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
public void onPlayerPickupItem(final org.bukkit.event.player.PlayerPickupItemEvent event) {
|
||||
if (event.getItem().hasMetadata(Commandfireball.FIREBALL_META_KEY)) {
|
||||
event.setCancelled(true);
|
||||
} else if (ess.getSettings().getDisableItemPickupWhileAfk()) {
|
||||
if (ess.getUser(event.getPlayer()).isAfk()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if ((ess.getSettings().getDisableItemPickupWhileAfk() && user.isAfk())
|
||||
|| (user.isVanished() && !user.isAuthorizedCached("essentials.vanish.pickup"))) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1050,8 +1226,10 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
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) {
|
||||
if (ess.getUser((Player) event.getEntity()).isAfk()) {
|
||||
if (event.getEntity() instanceof Player) {
|
||||
final User user = ess.getUser((Player) event.getEntity());
|
||||
if ((ess.getSettings().getDisableItemPickupWhileAfk() && user.isAfk())
|
||||
|| (user.isVanished() && !user.isAuthorizedCached("essentials.vanish.pickup"))) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
@@ -1070,6 +1248,10 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
private final class CommandSendFilter implements CommandSendListenerProvider.Filter {
|
||||
@Override
|
||||
public Predicate<String> apply(Player player) {
|
||||
// There is no event for op status changes, but the command list is resent when
|
||||
// a player is opped/deopped, so we invalidate cached permissions here.
|
||||
ess.getPermissionsHandler().invalidatePermissionCache(player.getUniqueId());
|
||||
|
||||
final User user = ess.getUser(player);
|
||||
final Set<PluginCommand> checked = new HashSet<>();
|
||||
final Set<PluginCommand> toRemove = new HashSet<>();
|
||||
@@ -1100,12 +1282,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
|
||||
return command != null
|
||||
&& (command.getPlugin() == ess || command.getPlugin().getClass().getName().startsWith("com.earth2me.essentials") || command.getPlugin().getClass().getName().startsWith("net.essentialsx"))
|
||||
&& (ess.getSettings().isCommandOverridden(label) || (ess.getAlternativeCommandsHandler().getAlternative(label) == null));
|
||||
&& (ess.getSettings().isCommandOverridden(label) || ess.getAlternativeCommandsHandler().getAlternative(label) == null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getUser(Player player) {
|
||||
ess.getUser(player);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import com.earth2me.essentials.config.EssentialsUserConfiguration;
|
||||
import com.earth2me.essentials.config.entities.LazyLocation;
|
||||
import com.earth2me.essentials.craftbukkit.BanLookup;
|
||||
import com.earth2me.essentials.userstorage.ModernUUIDCache;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
@@ -72,7 +71,7 @@ public class EssentialsUpgrade {
|
||||
doneFile.load();
|
||||
}
|
||||
|
||||
public static void uuidFileConvert(final IEssentials ess, final Boolean ignoreUFCache) {
|
||||
private static void uuidFileConvert(final IEssentials ess, final Boolean ignoreUFCache) {
|
||||
ess.getLogger().info("Starting Essentials UUID userdata conversion");
|
||||
|
||||
final File userdir = new File(ess.getDataFolder(), "userdata");
|
||||
@@ -157,7 +156,7 @@ public class EssentialsUpgrade {
|
||||
ess.getLogger().info("To rerun the conversion type /essentials uuidconvert");
|
||||
}
|
||||
|
||||
public void updateRandomTeleport() {
|
||||
private void updateRandomTeleport() {
|
||||
if (doneFile.getBoolean("updateRandomTeleport", false)) {
|
||||
return;
|
||||
}
|
||||
@@ -192,7 +191,7 @@ public class EssentialsUpgrade {
|
||||
ess.getLogger().info("Done converting random teleport config.");
|
||||
}
|
||||
|
||||
public void convertMailList() {
|
||||
private void convertMailList() {
|
||||
if (doneFile.getBoolean("updateUsersMailList", false)) {
|
||||
return;
|
||||
}
|
||||
@@ -232,7 +231,7 @@ public class EssentialsUpgrade {
|
||||
ess.getLogger().info("Done converting mail list.");
|
||||
}
|
||||
|
||||
public void convertStupidCamelCaseUserdataKeys() {
|
||||
private void convertStupidCamelCaseUserdataKeys() {
|
||||
if (doneFile.getBoolean("updateUsersStupidLegacyPathNames", false)) {
|
||||
return;
|
||||
}
|
||||
@@ -312,7 +311,7 @@ public class EssentialsUpgrade {
|
||||
* horrible economy code, as any operation which loads all user data into memory will load all these NPC accounts
|
||||
* and spam the console with warnings."
|
||||
*/
|
||||
public void purgeBrokenNpcAccounts() {
|
||||
private void purgeBrokenNpcAccounts() {
|
||||
if (doneFile.getBoolean("updatePurgeBrokenNpcAccounts", false)) {
|
||||
return;
|
||||
}
|
||||
@@ -423,7 +422,7 @@ public class EssentialsUpgrade {
|
||||
ess.getLogger().info("#===========================================================================#");
|
||||
}
|
||||
|
||||
public void convertIgnoreList() {
|
||||
private void convertIgnoreList() {
|
||||
final Pattern pattern = Pattern.compile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
|
||||
if (doneFile.getBoolean("updateUsersIgnoreListUUID", false)) {
|
||||
return;
|
||||
@@ -474,6 +473,10 @@ public class EssentialsUpgrade {
|
||||
}
|
||||
|
||||
public void convertKits() {
|
||||
if (Essentials.TESTING) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Kits kits = ess.getKits();
|
||||
final EssentialsConfiguration config = kits.getRootConfig();
|
||||
if (doneFile.getBoolean("kitsyml", false)) {
|
||||
@@ -531,7 +534,7 @@ public class EssentialsUpgrade {
|
||||
doneFile.setProperty("move" + name + "ToFile", true);
|
||||
doneFile.save();
|
||||
} catch (final IOException e) {
|
||||
ess.getLogger().log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("upgradingFilesError")), e);
|
||||
ess.getLogger().log(Level.SEVERE, ess.getAdventureFacet().miniToLegacy(tlLiteral("upgradingFilesError")), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,15 +697,15 @@ public class EssentialsUpgrade {
|
||||
final File tmpFile = new File(listOfFile.getParentFile(), sanitizedFilename + ".tmp");
|
||||
final File newFile = new File(listOfFile.getParentFile(), sanitizedFilename);
|
||||
if (!listOfFile.renameTo(tmpFile)) {
|
||||
ess.getLogger().log(Level.WARNING, AdventureUtil.miniToLegacy(tlLiteral("userdataMoveError", filename, sanitizedFilename)));
|
||||
ess.getLogger().log(Level.WARNING, ess.getAdventureFacet().miniToLegacy(tlLiteral("userdataMoveError", filename, sanitizedFilename)));
|
||||
continue;
|
||||
}
|
||||
if (newFile.exists()) {
|
||||
ess.getLogger().log(Level.WARNING, AdventureUtil.miniToLegacy(tlLiteral("duplicatedUserdata", filename, sanitizedFilename)));
|
||||
ess.getLogger().log(Level.WARNING, ess.getAdventureFacet().miniToLegacy(tlLiteral("duplicatedUserdata", filename, sanitizedFilename)));
|
||||
continue;
|
||||
}
|
||||
if (!tmpFile.renameTo(newFile)) {
|
||||
ess.getLogger().log(Level.WARNING, AdventureUtil.miniToLegacy(tlLiteral("userdataMoveBackError", sanitizedFilename, sanitizedFilename)));
|
||||
ess.getLogger().log(Level.WARNING, ess.getAdventureFacet().miniToLegacy(tlLiteral("userdataMoveBackError", sanitizedFilename, sanitizedFilename)));
|
||||
}
|
||||
}
|
||||
doneFile.setProperty("sanitizeAllUserFilenames", true);
|
||||
@@ -718,7 +721,7 @@ public class EssentialsUpgrade {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Location getFakeLocation(final CommentedConfigurationNode config, final String path) {
|
||||
private Location getFakeLocation(final CommentedConfigurationNode config, final String path) {
|
||||
final String worldName = config.getString((path != null ? path + "." : "") + "world");
|
||||
if (worldName == null || worldName.isEmpty()) {
|
||||
return null;
|
||||
@@ -882,7 +885,7 @@ public class EssentialsUpgrade {
|
||||
doneFile.save();
|
||||
}
|
||||
|
||||
public void banFormatChange() {
|
||||
private void banFormatChange() {
|
||||
if (doneFile.getBoolean("banFormatChange", false)) {
|
||||
return;
|
||||
}
|
||||
@@ -952,7 +955,7 @@ public class EssentialsUpgrade {
|
||||
Bukkit.getBanList(BanList.Type.NAME).addBan(playerName, banReason, banTimeout == 0 ? null : new Date(banTimeout), Console.NAME);
|
||||
}
|
||||
|
||||
public void generateUidCache() {
|
||||
private void generateUidCache() {
|
||||
if (doneFile.getBoolean("newUidCacheBuilt", false)) {
|
||||
return;
|
||||
}
|
||||
@@ -992,7 +995,7 @@ public class EssentialsUpgrade {
|
||||
if (name != null) {
|
||||
if (nameToUuidMap.containsKey(name)) {
|
||||
final UUID oldUuid = nameToUuidMap.get(name);
|
||||
if (oldUuid.version() < uuid.version() || (oldUuid.version() == uuid.version() && uuids.get(oldUuid) < time)) {
|
||||
if (oldUuid.version() < uuid.version() || oldUuid.version() == uuid.version() && uuids.get(oldUuid) < time) {
|
||||
ess.getLogger().warning("New UUID found for " + name + ": " + uuid + " (old: " + oldUuid + "). Replacing.");
|
||||
uuids.remove(oldUuid);
|
||||
} else {
|
||||
@@ -1060,7 +1063,7 @@ public class EssentialsUpgrade {
|
||||
properties.load(Files.newReader(backup, Charsets.UTF_8));
|
||||
for (final String key : properties.stringPropertyNames()) {
|
||||
final String value = properties.getProperty(key);
|
||||
properties.setProperty(key, AdventureUtil.legacyToMini(AdventureUtil.miniMessage().escapeTags(value), true));
|
||||
properties.setProperty(key, ess.getAdventureFacet().legacyToMini(ess.getAdventureFacet().escapeTags(value), true));
|
||||
}
|
||||
properties.store(Files.newWriter(newFile, Charsets.UTF_8), null);
|
||||
}
|
||||
@@ -1079,6 +1082,10 @@ public class EssentialsUpgrade {
|
||||
}
|
||||
|
||||
public void beforeSettings() {
|
||||
if (Essentials.TESTING) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ess.getDataFolder().exists()) {
|
||||
ess.getDataFolder().mkdirs();
|
||||
}
|
||||
@@ -1087,10 +1094,17 @@ public class EssentialsUpgrade {
|
||||
}
|
||||
|
||||
public void preModules() {
|
||||
if (Essentials.TESTING) {
|
||||
return;
|
||||
}
|
||||
generateUidCache();
|
||||
}
|
||||
|
||||
public void afterSettings() {
|
||||
if (Essentials.TESTING) {
|
||||
return;
|
||||
}
|
||||
|
||||
sanitizeAllUserFilenames();
|
||||
updateUsersPowerToolsFormat();
|
||||
updateUsersHomesFormat();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.ResourceBundle;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -35,7 +36,7 @@ import java.util.regex.Pattern;
|
||||
public class I18n implements net.ess3.api.II18n {
|
||||
private static final String MESSAGES = "messages";
|
||||
private static final Pattern NODOUBLEMARK = Pattern.compile("''");
|
||||
private static final ExecutorService BUNDLE_LOADER_EXECUTOR = Executors.newFixedThreadPool(2);
|
||||
private static volatile ExecutorService BUNDLE_LOADER_EXECUTOR = Executors.newFixedThreadPool(2);
|
||||
private static final ResourceBundle NULL_BUNDLE = new ResourceBundle() {
|
||||
@SuppressWarnings("NullableProblems")
|
||||
public Enumeration<String> getKeys() {
|
||||
@@ -92,7 +93,7 @@ public class I18n implements net.ess3.api.II18n {
|
||||
if (objects.length == 0) {
|
||||
return NODOUBLEMARK.matcher(instance.translate(locale, tlKey)).replaceAll("'");
|
||||
} else {
|
||||
return instance.format(tlKey, objects);
|
||||
return instance.format(locale, tlKey, objects);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +107,29 @@ public class I18n implements net.ess3.api.II18n {
|
||||
|
||||
public void onDisable() {
|
||||
instance = null;
|
||||
shutdownExecutor();
|
||||
}
|
||||
|
||||
private static synchronized ExecutorService getExecutor() {
|
||||
if (BUNDLE_LOADER_EXECUTOR == null || BUNDLE_LOADER_EXECUTOR.isShutdown() || BUNDLE_LOADER_EXECUTOR.isTerminated()) {
|
||||
BUNDLE_LOADER_EXECUTOR = Executors.newFixedThreadPool(2);
|
||||
}
|
||||
return BUNDLE_LOADER_EXECUTOR;
|
||||
}
|
||||
|
||||
private static synchronized void shutdownExecutor() {
|
||||
final ExecutorService exec = BUNDLE_LOADER_EXECUTOR;
|
||||
if (exec == null) {
|
||||
return;
|
||||
}
|
||||
exec.shutdown();
|
||||
try {
|
||||
if (!exec.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
exec.shutdownNow();
|
||||
}
|
||||
} catch (final InterruptedException ignored) {
|
||||
exec.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,19 +148,8 @@ public class I18n implements net.ess3.api.II18n {
|
||||
synchronized (loadingBundles) {
|
||||
if (!loadingBundles.contains(locale)) {
|
||||
loadingBundles.add(locale);
|
||||
BUNDLE_LOADER_EXECUTOR.submit(() -> {
|
||||
ResourceBundle bundle;
|
||||
try {
|
||||
bundle = ResourceBundle.getBundle(MESSAGES, locale, new FileResClassLoader(I18n.class.getClassLoader(), ess), new UTF8PropertiesControl());
|
||||
} catch (MissingResourceException ex) {
|
||||
try {
|
||||
bundle = ResourceBundle.getBundle(MESSAGES, locale, new UTF8PropertiesControl());
|
||||
} catch (MissingResourceException ex2) {
|
||||
bundle = NULL_BUNDLE;
|
||||
}
|
||||
}
|
||||
|
||||
loadedBundles.put(locale, bundle);
|
||||
getExecutor().submit(() -> {
|
||||
blockingLoadBundle(locale);
|
||||
synchronized (loadingBundles) {
|
||||
loadingBundles.remove(locale);
|
||||
}
|
||||
@@ -147,6 +160,23 @@ public class I18n implements net.ess3.api.II18n {
|
||||
}
|
||||
}
|
||||
|
||||
public void blockingLoadBundle(final Locale locale) {
|
||||
if (!loadedBundles.containsKey(locale)) {
|
||||
ResourceBundle bundle;
|
||||
try {
|
||||
bundle = ResourceBundle.getBundle(MESSAGES, locale, new FileResClassLoader(I18n.class.getClassLoader(), ess), new UTF8PropertiesControl());
|
||||
} catch (MissingResourceException ex) {
|
||||
try {
|
||||
bundle = ResourceBundle.getBundle(MESSAGES, locale, new UTF8PropertiesControl());
|
||||
} catch (MissingResourceException ex2) {
|
||||
bundle = NULL_BUNDLE;
|
||||
}
|
||||
}
|
||||
|
||||
loadedBundles.put(locale, bundle);
|
||||
}
|
||||
}
|
||||
|
||||
private String translate(final Locale locale, final String string) {
|
||||
try {
|
||||
try {
|
||||
@@ -162,10 +192,6 @@ public class I18n implements net.ess3.api.II18n {
|
||||
}
|
||||
}
|
||||
|
||||
private String format(final String string, final Object... objects) {
|
||||
return format(currentLocale, string, objects);
|
||||
}
|
||||
|
||||
private String format(final Locale locale, final String string, final Object... objects) {
|
||||
String format = translate(locale, string);
|
||||
|
||||
@@ -185,7 +211,7 @@ public class I18n implements net.ess3.api.II18n {
|
||||
if (arg instanceof AdventureUtil.ParsedPlaceholder) {
|
||||
return arg.toString();
|
||||
}
|
||||
return AdventureUtil.legacyToMini(AdventureUtil.miniMessage().escapeTags(arg.toString()));
|
||||
return ess.getAdventureFacet().legacyToMini(ess.getAdventureFacet().escapeTags(arg.toString()));
|
||||
});
|
||||
|
||||
return messageFormat.format(processedArgs).replace(' ', ' '); // replace nbsp with a space
|
||||
@@ -281,7 +307,7 @@ public class I18n implements net.ess3.api.II18n {
|
||||
* Reads .properties files as UTF-8 instead of ISO-8859-1, which is the default on Java 8/below.
|
||||
* Java 9 fixes this by defaulting to UTF-8 for .properties files.
|
||||
*/
|
||||
private static class UTF8PropertiesControl extends ResourceBundle.Control {
|
||||
private static final class UTF8PropertiesControl extends ResourceBundle.Control {
|
||||
public ResourceBundle newBundle(final String baseName, final Locale locale, final String format, final ClassLoader loader, final boolean reload) throws IOException {
|
||||
final String resourceName = toResourceName(toBundleName(baseName, locale), "properties");
|
||||
ResourceBundle bundle = null;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.adventure.AdventureFacet;
|
||||
import com.earth2me.essentials.api.IItemDb;
|
||||
import com.earth2me.essentials.api.IJails;
|
||||
import com.earth2me.essentials.api.IWarps;
|
||||
@@ -81,6 +82,8 @@ public interface IEssentials extends Plugin {
|
||||
|
||||
BukkitScheduler getScheduler();
|
||||
|
||||
List<Player> getJailedPlayers();
|
||||
|
||||
IJails getJails();
|
||||
|
||||
IWarps getWarps();
|
||||
@@ -146,4 +149,6 @@ public interface IEssentials extends Plugin {
|
||||
default <P extends Provider> P provider(final Class<P> providerClass) {
|
||||
return getProviders().get(providerClass);
|
||||
}
|
||||
|
||||
AdventureFacet getAdventureFacet();
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import com.earth2me.essentials.signs.EssentialsSign;
|
||||
import com.earth2me.essentials.textreader.IText;
|
||||
import net.essentialsx.api.v2.ChatType;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.spongepowered.configurate.CommentedConfigurationNode;
|
||||
@@ -95,6 +94,8 @@ public interface ISettings extends IConf {
|
||||
|
||||
String getNicknamePrefix();
|
||||
|
||||
boolean isResetNickOnNameChange();
|
||||
|
||||
String getOperatorColor() throws Exception;
|
||||
|
||||
boolean getPerWarpPermission();
|
||||
@@ -135,6 +136,8 @@ public interface ISettings extends IConf {
|
||||
|
||||
boolean isAlwaysTeleportSafety();
|
||||
|
||||
boolean isConsiderWorldHeightForTeleportSafety();
|
||||
|
||||
boolean isTeleportPassengerDismount();
|
||||
|
||||
boolean isForcePassengerTeleport();
|
||||
@@ -184,6 +187,8 @@ public interface ISettings extends IConf {
|
||||
|
||||
boolean isEcoLogEnabled();
|
||||
|
||||
boolean isEcoLogUUIDEnabled();
|
||||
|
||||
boolean isEcoLogUpdateEnabled();
|
||||
|
||||
boolean realNamesOnList();
|
||||
@@ -208,7 +213,9 @@ public interface ISettings extends IConf {
|
||||
|
||||
long getAutoAfk();
|
||||
|
||||
long getAutoAfkKick();
|
||||
long getAutoAfkTimeout();
|
||||
|
||||
List<String> getAfkTimeoutCommands();
|
||||
|
||||
boolean getFreezeAfkPlayers();
|
||||
|
||||
@@ -218,6 +225,8 @@ public interface ISettings extends IConf {
|
||||
|
||||
boolean cancelAfkOnChat();
|
||||
|
||||
boolean cancelAfkOnFish();
|
||||
|
||||
boolean sleepIgnoresAfkPlayers();
|
||||
|
||||
boolean sleepIgnoresVanishedPlayers();
|
||||
@@ -316,6 +325,8 @@ public interface ISettings extends IConf {
|
||||
|
||||
boolean isCustomServerFullMessage();
|
||||
|
||||
boolean isCustomWhitelistMessage();
|
||||
|
||||
boolean isNotifyNoNewMail();
|
||||
|
||||
boolean isDropItemsIfFull();
|
||||
@@ -350,6 +361,8 @@ public interface ISettings extends IConf {
|
||||
|
||||
boolean isWorldChangePreserveFlying();
|
||||
|
||||
boolean isGamemodeChangePreserveFlying();
|
||||
|
||||
boolean isWorldChangeSpeedResetEnabled();
|
||||
|
||||
long getCommandCooldownMs(String label);
|
||||
@@ -406,6 +419,8 @@ public interface ISettings extends IConf {
|
||||
|
||||
boolean logCommandBlockCommands();
|
||||
|
||||
boolean logConsoleCommands();
|
||||
|
||||
Set<Predicate<String>> getNickBlacklist();
|
||||
|
||||
double getMaxProjectileSpeed();
|
||||
@@ -424,18 +439,22 @@ public interface ISettings extends IConf {
|
||||
|
||||
boolean showZeroBaltop();
|
||||
|
||||
String getNickRegex();
|
||||
|
||||
BigDecimal getMultiplier(final User user);
|
||||
|
||||
int getMaxItemLore();
|
||||
|
||||
Tag getPrimaryColor();
|
||||
String getPrimaryColor();
|
||||
|
||||
Tag getSecondaryColor();
|
||||
String getSecondaryColor();
|
||||
|
||||
BigDecimal getBaltopMinBalance();
|
||||
|
||||
long getBaltopMinPlaytime();
|
||||
|
||||
int getBaltopEntryLimit();
|
||||
|
||||
enum KeepInvPolicy {
|
||||
KEEP,
|
||||
DELETE,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.adventure.ComponentHolder;
|
||||
import com.earth2me.essentials.api.IAsyncTeleport;
|
||||
import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import com.earth2me.essentials.config.entities.CommandCooldown;
|
||||
@@ -7,8 +8,6 @@ import net.ess3.api.MaxMoneyException;
|
||||
import net.ess3.api.events.AfkStatusChangeEvent;
|
||||
import net.essentialsx.api.v2.services.mail.MailMessage;
|
||||
import net.essentialsx.api.v2.services.mail.MailSender;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentLike;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
@@ -33,6 +32,8 @@ import java.util.regex.Pattern;
|
||||
public interface IUser {
|
||||
boolean isAuthorized(String node);
|
||||
|
||||
boolean isAuthorizedCached(String node);
|
||||
|
||||
boolean isAuthorized(IEssentialsCommand cmd);
|
||||
|
||||
boolean isAuthorized(IEssentialsCommand cmd, String permissionPrefix);
|
||||
@@ -138,9 +139,9 @@ public interface IUser {
|
||||
|
||||
void sendMessage(String message);
|
||||
|
||||
void sendComponent(ComponentLike component);
|
||||
void sendComponent(ComponentHolder component);
|
||||
|
||||
Component tlComponent(String tlKey, Object... args);
|
||||
ComponentHolder tlComponent(String tlKey, Object... args);
|
||||
|
||||
String playerTl(String tlKey, Object... args);
|
||||
|
||||
@@ -177,6 +178,17 @@ public interface IUser {
|
||||
|
||||
String getFormattedJailTime();
|
||||
|
||||
/**
|
||||
* Returns last activity time.
|
||||
* <p>
|
||||
* It is used internally to determine if user's afk status should be set to
|
||||
* true because of ACTIVITY {@link AfkStatusChangeEvent.Cause}, or the player
|
||||
* should be kicked for being afk too long.
|
||||
*
|
||||
* @return Last activity time (Epoch Milliseconds)
|
||||
*/
|
||||
long getLastActivityTime();
|
||||
|
||||
@Deprecated
|
||||
List<String> getMails();
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.earth2me.essentials;
|
||||
import com.earth2me.essentials.config.ConfigurateUtil;
|
||||
import com.earth2me.essentials.config.EssentialsConfiguration;
|
||||
import com.earth2me.essentials.config.entities.LazyLocation;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.IUser;
|
||||
import net.ess3.api.TranslatableException;
|
||||
@@ -273,9 +272,9 @@ public class Jails implements net.ess3.api.IJails {
|
||||
event.setRespawnLocation(getJail(user.getJail()));
|
||||
} catch (final Exception ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())), ex);
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())), ex);
|
||||
} else {
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())));
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,9 +294,9 @@ public class Jails implements net.ess3.api.IJails {
|
||||
event.setTo(getJail(user.getJail()));
|
||||
} catch (final Exception ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())), ex);
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())), ex);
|
||||
} else {
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())));
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())));
|
||||
}
|
||||
}
|
||||
user.sendTl("jailMessage");
|
||||
@@ -319,9 +318,9 @@ public class Jails implements net.ess3.api.IJails {
|
||||
final CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
future.exceptionally(ex -> {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())), ex);
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())), ex);
|
||||
} else {
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())));
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())));
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.textreader.IText;
|
||||
import com.earth2me.essentials.textreader.KeywordReplacer;
|
||||
import com.earth2me.essentials.textreader.SimpleTextInput;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
@@ -26,6 +25,7 @@ import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tlLiteral;
|
||||
@@ -174,10 +174,11 @@ public class Kit {
|
||||
final boolean allowUnsafe = ess.getSettings().allowUnsafeEnchantments();
|
||||
final boolean autoEquip = ess.getSettings().isKitAutoEquip();
|
||||
final List<ItemStack> itemList = new ArrayList<>();
|
||||
final Map<Integer, ItemStack> itemsWithSlot = new HashMap<>();
|
||||
final List<String> commandQueue = new ArrayList<>();
|
||||
final List<String> moneyQueue = new ArrayList<>();
|
||||
final String currencySymbol = ess.getSettings().getCurrencySymbol().isEmpty() ? "$" : ess.getSettings().getCurrencySymbol();
|
||||
for (final String kitItem : output.getLines()) {
|
||||
for (String kitItem : output.getLines()) {
|
||||
if (kitItem.startsWith("$") || kitItem.startsWith(currencySymbol)) {
|
||||
moneyQueue.add(NumberUtil.sanitizeCurrencyString(kitItem, ess));
|
||||
continue;
|
||||
@@ -191,12 +192,22 @@ public class Kit {
|
||||
continue;
|
||||
}
|
||||
|
||||
int itemSlot = -1;
|
||||
if (kitItem.startsWith("slot:")) {
|
||||
final int spaceIndex = kitItem.indexOf(" ");
|
||||
if (spaceIndex != -1) {
|
||||
final String slotStr = kitItem.substring("slot:".length(), spaceIndex);
|
||||
itemSlot = NumberUtil.isInt(slotStr) ? Integer.parseInt(slotStr) : -1;
|
||||
kitItem = kitItem.substring(spaceIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
final ItemStack stack;
|
||||
final SerializationProvider serializationProvider = ess.provider(SerializationProvider.class);
|
||||
|
||||
if (kitItem.startsWith("@")) {
|
||||
if (serializationProvider == null) {
|
||||
ess.getLogger().log(Level.WARNING, AdventureUtil.miniToLegacy(tlLiteral("kitError3", kitName, user.getName())));
|
||||
ess.getLogger().log(Level.WARNING, ess.getAdventureFacet().miniToLegacy(tlLiteral("kitError3", kitName, user.getName())));
|
||||
continue;
|
||||
}
|
||||
stack = serializationProvider.deserializeItem(Base64Coder.decodeLines(kitItem.substring(1)));
|
||||
@@ -218,22 +229,35 @@ public class Kit {
|
||||
stack = metaStack.getItemStack();
|
||||
}
|
||||
|
||||
itemList.add(stack);
|
||||
if (itemSlot == -1 || itemsWithSlot.containsKey(itemSlot)) {
|
||||
itemList.add(stack);
|
||||
} else {
|
||||
itemsWithSlot.put(itemSlot, stack);
|
||||
}
|
||||
}
|
||||
|
||||
final int maxStackSize = user.isAuthorized("essentials.oversizedstacks") ? ess.getSettings().getOversizedStackSize() : 0;
|
||||
final boolean isDropItemsIfFull = ess.getSettings().isDropItemsIfFull();
|
||||
|
||||
final KitPreExpandItemsEvent itemsEvent = new KitPreExpandItemsEvent(user, kitName, itemList);
|
||||
final List<ItemStack> totalItems = new ArrayList<>(itemList);
|
||||
totalItems.addAll(itemsWithSlot.values());
|
||||
|
||||
final KitPreExpandItemsEvent itemsEvent = new KitPreExpandItemsEvent(user, kitName, totalItems);
|
||||
Bukkit.getPluginManager().callEvent(itemsEvent);
|
||||
|
||||
final ItemStack[] itemArray = itemList.toArray(new ItemStack[0]);
|
||||
|
||||
if (!isDropItemsIfFull && !Inventories.hasSpace(user.getBase(), maxStackSize, autoEquip, itemArray)) {
|
||||
final ItemStack[] totalItemsArray = totalItems.toArray(new ItemStack[0]);
|
||||
if (!isDropItemsIfFull && !Inventories.hasSpace(user.getBase(), maxStackSize, autoEquip, totalItemsArray)) {
|
||||
user.sendTl("kitInvFullNoDrop");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Map.Entry<Integer, ItemStack> itemWithSlot : itemsWithSlot.entrySet()) {
|
||||
final ItemStack leftover = Inventories.addItem(user.getBase(), maxStackSize, itemWithSlot.getValue(), itemWithSlot.getKey());
|
||||
if (leftover != null) {
|
||||
itemList.add(leftover);
|
||||
}
|
||||
}
|
||||
|
||||
final ItemStack[] itemArray = itemList.toArray(new ItemStack[0]);
|
||||
final Map<Integer, ItemStack> leftover = Inventories.addItem(user.getBase(), maxStackSize, autoEquip, itemArray);
|
||||
if (!isDropItemsIfFull && !leftover.isEmpty()) {
|
||||
// Inventories#hasSpace should prevent this state from EVER being reached; If it does, something has gone terribly wrong, and we should just give up and hope people report it :(
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
@@ -46,7 +45,7 @@ public class ManagedFile {
|
||||
try {
|
||||
copyResourceAscii("/" + filename, file);
|
||||
} catch (final IOException ex) {
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("itemsCsvNotLoaded", filename)), ex);
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, ess.getAdventureFacet().miniToLegacy(tlLiteral("itemsCsvNotLoaded", filename)), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.items.transform.PluginItemTransformer;
|
||||
import com.earth2me.essentials.textreader.BookInput;
|
||||
import com.earth2me.essentials.textreader.BookPager;
|
||||
import com.earth2me.essentials.textreader.IText;
|
||||
@@ -12,6 +13,7 @@ import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.TranslatableException;
|
||||
import net.ess3.provider.BannerDataProvider;
|
||||
import net.ess3.provider.ItemUnbreakableProvider;
|
||||
import net.ess3.provider.PatternTypeProvider;
|
||||
import net.ess3.provider.PotionMetaProvider;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.DyeColor;
|
||||
@@ -20,6 +22,8 @@ import org.bukkit.Material;
|
||||
import org.bukkit.block.Banner;
|
||||
import org.bukkit.block.banner.PatternType;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.BannerMeta;
|
||||
@@ -32,6 +36,10 @@ import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.bukkit.inventory.meta.ArmorMeta;
|
||||
import org.bukkit.inventory.meta.trim.ArmorTrim;
|
||||
import org.bukkit.inventory.meta.trim.TrimMaterial;
|
||||
import org.bukkit.inventory.meta.trim.TrimPattern;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
@@ -47,6 +55,7 @@ import java.util.regex.Pattern;
|
||||
public class MetaItemStack {
|
||||
private static final Map<String, DyeColor> colorMap = new HashMap<>();
|
||||
private static final Map<String, FireworkEffect.Type> fireworkShape = new HashMap<>();
|
||||
private static final transient Map<String, PluginItemTransformer> itemTransformers = new HashMap<>();
|
||||
private static boolean useNewSkullMethod = true;
|
||||
|
||||
static {
|
||||
@@ -78,6 +87,32 @@ public class MetaItemStack {
|
||||
this.stack = stack.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an item transformer, belonging to a plugin, that can manipulate certain item metadata.
|
||||
* @param key the key for the transformer.
|
||||
* @param itemTransformer the actual transformer.
|
||||
*/
|
||||
public static void registerItemTransformer(final String key, final PluginItemTransformer itemTransformer) {
|
||||
//Warn people if they're trying to register over top of someone else.
|
||||
if (itemTransformers.containsKey(key)) {
|
||||
Essentials.getWrappedLogger().log(Level.WARNING, String.format("Plugin transformer registered to \"%s\" attempted to register already existing item transformer \"%s\" belonging to \"%s\"!",
|
||||
itemTransformer.getPlugin().getName(),
|
||||
key,
|
||||
itemTransformers.get(key).getPlugin().getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
itemTransformers.put(key, itemTransformer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a certain item transformer under key "key".
|
||||
* @param key the transformer key.
|
||||
*/
|
||||
public static void unregisterItemTransformer(final String key) {
|
||||
itemTransformers.remove(key);
|
||||
}
|
||||
|
||||
private static void setSkullOwner(final IEssentials ess, final ItemStack stack, final String owner) {
|
||||
if (!(stack.getItemMeta() instanceof SkullMeta)) return;
|
||||
|
||||
@@ -173,8 +208,13 @@ public class MetaItemStack {
|
||||
|
||||
try {
|
||||
final String components = Joiner.on(' ').join(Arrays.asList(string).subList(fromArg, string.length));
|
||||
// modifyItemStack requires that the item namespaced key is prepended to the components for some reason
|
||||
stack = ess.getServer().getUnsafe().modifyItemStack(stack, stack.getType().getKey() + components);
|
||||
// From 1.20.6 through 1.21.11, modifyItemStack parses its argument as a full item string, so the item's
|
||||
// namespaced key must be prepended to the components. As of 26.1, the implementation prepends the item
|
||||
// key itself, so prepending it here would produce a malformed (double-namespaced) item string.
|
||||
final String itemString = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v26_1_R01)
|
||||
? components
|
||||
: stack.getType().getKey() + components;
|
||||
stack = ess.getServer().getUnsafe().modifyItemStack(stack, itemString);
|
||||
} catch (final NullPointerException npe) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Itemstack is invalid", npe);
|
||||
@@ -274,8 +314,14 @@ public class MetaItemStack {
|
||||
final BookMeta meta = (BookMeta) stack.getItemMeta();
|
||||
meta.setTitle(title);
|
||||
stack.setItemMeta(meta);
|
||||
} else if (split.length > 1 && split[0].startsWith("page") && split[0].length() > 4 && MaterialUtil.isEditableBook(stack.getType()) && hasMetaPermission(sender, "page", false, true, ess)) {
|
||||
final int page = NumberUtil.isInt(split[0].substring(4)) ? (Integer.parseInt(split[0].substring(4)) - 1) : 0;
|
||||
} else if (split.length > 1 && split[0].startsWith("page") && split[0].length() > 4
|
||||
&& MaterialUtil.isEditableBook(stack.getType())
|
||||
&& hasMetaPermission(sender, "page", false, true, ess)) {
|
||||
final int page = NumberUtil.isInt(split[0].substring(4)) ? (Integer.parseInt(split[0].substring(4)) - 1)
|
||||
: 0;
|
||||
if (page > 100) {
|
||||
throw new TranslatableException("pageLimitExceeded");
|
||||
}
|
||||
final BookMeta meta = (BookMeta) stack.getItemMeta();
|
||||
final List<String> pages = meta.hasPages() ? new ArrayList<>(meta.getPages()) : new ArrayList<>();
|
||||
final List<String> lines = new ArrayList<>();
|
||||
@@ -343,11 +389,37 @@ public class MetaItemStack {
|
||||
} else {
|
||||
throw new TranslatableException("leatherSyntax");
|
||||
}
|
||||
} else if (MaterialUtil.isArmor(stack.getType()) && split.length > 1 && split[0].equalsIgnoreCase("trim")) {
|
||||
final ArmorMeta armorMeta = (ArmorMeta) stack.getItemMeta();
|
||||
final String[] trimData = split[1].split("\\|");
|
||||
final TrimPattern pattern = Registry.TRIM_PATTERN.getOrThrow(NamespacedKey.minecraft(trimData[0].toLowerCase()));
|
||||
final TrimMaterial material = Registry.TRIM_MATERIAL.getOrThrow(NamespacedKey.minecraft(trimData[1].toLowerCase()));
|
||||
|
||||
armorMeta.setTrim(new ArmorTrim(material, pattern));
|
||||
|
||||
stack.setItemMeta(armorMeta);
|
||||
} else if (split.length > 1 && itemTransformers.containsKey(split[0])) {
|
||||
transformItem(split[0], split[1]);
|
||||
} else {
|
||||
parseEnchantmentStrings(sender, allowUnsafe, split, ess);
|
||||
}
|
||||
}
|
||||
|
||||
private void transformItem(final String key, final String data){
|
||||
final PluginItemTransformer transformer = itemTransformers.get(key);
|
||||
|
||||
//Ignore, the plugin is disabled.
|
||||
if (!transformer.getPlugin().isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
stack = transformer.apply(data, stack);
|
||||
} catch(final Throwable thr) {
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, String.format("Error applying data \"%s\" to itemstack! Plugin: %s, Key: %s", data, transformer.getPlugin().getName(), key), thr);
|
||||
}
|
||||
}
|
||||
|
||||
public void addItemFlags(final String string) throws Exception {
|
||||
final String[] separate = splitPattern.split(string, 2);
|
||||
if (separate.length != 2) {
|
||||
@@ -549,7 +621,8 @@ public class MetaItemStack {
|
||||
} else if (split[0].equalsIgnoreCase("duration") || (allowShortName && split[0].equalsIgnoreCase("d"))) {
|
||||
if (NumberUtil.isInt(split[1])) {
|
||||
validPotionDuration = true;
|
||||
duration = Integer.parseInt(split[1]) * 20; //Duration is in ticks by default, converted to seconds
|
||||
final int parsed = Integer.parseInt(split[1]);
|
||||
duration = parsed == -1 ? -1 : parsed * 20; //Duration is in ticks by default, converted to seconds
|
||||
} else {
|
||||
throw new TranslatableException("invalidPotionMeta", split[1]);
|
||||
}
|
||||
@@ -645,22 +718,15 @@ public class MetaItemStack {
|
||||
throw new TranslatableException("invalidBanner", split[1]);
|
||||
}
|
||||
|
||||
PatternType patternType = null;
|
||||
try {
|
||||
//noinspection removal
|
||||
patternType = PatternType.getByIdentifier(split[0]);
|
||||
} catch (final Exception ignored) {
|
||||
}
|
||||
final PatternType patternType = ess.provider(PatternTypeProvider.class).getPatternTypeByIdentifier(split[0]);
|
||||
|
||||
final BannerMeta meta = (BannerMeta) stack.getItemMeta();
|
||||
if (split[0].equalsIgnoreCase("basecolor")) {
|
||||
final Color color = Color.fromRGB(Integer.parseInt(split[1]));
|
||||
ess.provider(BannerDataProvider.class).setBaseColor(stack, DyeColor.getByColor(color));
|
||||
} else if (patternType != null) {
|
||||
//noinspection removal
|
||||
final PatternType type = PatternType.getByIdentifier(split[0]);
|
||||
final DyeColor color = DyeColor.getByColor(Color.fromRGB(Integer.parseInt(split[1])));
|
||||
final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type);
|
||||
final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, patternType);
|
||||
meta.addPattern(pattern);
|
||||
}
|
||||
|
||||
@@ -672,12 +738,7 @@ public class MetaItemStack {
|
||||
throw new TranslatableException("invalidBanner", split[1]);
|
||||
}
|
||||
|
||||
PatternType patternType = null;
|
||||
try {
|
||||
//noinspection removal
|
||||
patternType = PatternType.getByIdentifier(split[0]);
|
||||
} catch (final Exception ignored) {
|
||||
}
|
||||
final PatternType patternType = ess.provider(PatternTypeProvider.class).getPatternTypeByIdentifier(split[0]);
|
||||
|
||||
// Hacky fix for accessing Shield meta - https://github.com/drtshock/Essentials/pull/745#issuecomment-234843795
|
||||
final BlockStateMeta meta = (BlockStateMeta) stack.getItemMeta();
|
||||
@@ -686,10 +747,8 @@ public class MetaItemStack {
|
||||
final Color color = Color.fromRGB(Integer.parseInt(split[1]));
|
||||
banner.setBaseColor(DyeColor.getByColor(color));
|
||||
} else if (patternType != null) {
|
||||
//noinspection removal
|
||||
final PatternType type = PatternType.getByIdentifier(split[0]);
|
||||
final DyeColor color = DyeColor.getByColor(Color.fromRGB(Integer.parseInt(split[1])));
|
||||
final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type);
|
||||
final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, patternType);
|
||||
banner.addPattern(pattern);
|
||||
}
|
||||
banner.update();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
@@ -60,6 +60,7 @@ public enum Mob {
|
||||
CHERRY_BOAT("CherryBoat", Enemies.NEUTRAL, "CHERRY_BOAT"),
|
||||
BAMBOO_RAFT("BambooRaft", Enemies.NEUTRAL, "BAMBOO_RAFT"),
|
||||
PALE_OAK_BOAT("PaleOakBoat", Enemies.NEUTRAL, "PALE_OAK_BOAT"),
|
||||
POPLAR_BOAT("PoplarBoat", Enemies.NEUTRAL, "POPLAR_BOAT"),
|
||||
MINECART("Minecart", Enemies.NEUTRAL, EntityType.MINECART),
|
||||
MINECART_CHEST("ChestMinecart", Enemies.NEUTRAL, MobCompat.CHEST_MINECART),
|
||||
MINECART_FURNACE("FurnaceMinecart", Enemies.NEUTRAL, MobCompat.FURNACE_MINECART),
|
||||
@@ -118,13 +119,31 @@ public enum Mob {
|
||||
FROG("Frog", Enemies.FRIENDLY, "FROG"),
|
||||
TADPOLE("Tadpole", Enemies.FRIENDLY, "TADPOLE"),
|
||||
WARDEN("Warden", Enemies.ENEMY, "WARDEN"),
|
||||
CHEST_BOAT("ChestBoat", Enemies.NEUTRAL, "CHEST_BOAT"),
|
||||
CHEST_BOAT("ChestBoat", Enemies.NEUTRAL, MobCompat.OAK_CHEST_BOAT),
|
||||
ACACIA_CHEST_BOAT("AcaciaChestBoat", Enemies.NEUTRAL, "ACACIA_CHEST_BOAT"),
|
||||
DARK_OAK_CHEST_BOAT("DarkOakChestBoat", Enemies.NEUTRAL, "DARK_OAK_CHEST_BOAT"),
|
||||
BIRCH_CHEST_BOAT("BirchChestBoat", Enemies.NEUTRAL, "BIRCH_CHEST_BOAT"),
|
||||
JUNGLE_CHEST_BOAT("JungleChestBoat", Enemies.NEUTRAL, "JUNGLE_CHEST_BOAT"),
|
||||
SPRUCE_CHEST_BOAT("SpruceChestBoat", Enemies.NEUTRAL, "SPRUCE_CHEST_BOAT"),
|
||||
MANGROVE_CHEST_BOAT("MangroveChestBoat", Enemies.NEUTRAL, "MANGROVE_CHEST_BOAT"),
|
||||
CHERRY_CHEST_BOAT("CherryChestBoat", Enemies.NEUTRAL, "CHERRY_CHEST_BOAT"),
|
||||
BAMBOO_CHEST_RAFT("BambooChestRaft", Enemies.NEUTRAL, "BAMBOO_CHEST_RAFT"),
|
||||
PALE_OAK_CHEST_BOAT("PaleOakChestBoat", Enemies.NEUTRAL, "PALE_OAK_CHEST_BOAT"),
|
||||
POPLAR_CHEST_BOAT("PoplarChestBoat", Enemies.NEUTRAL, "POPLAR_CHEST_BOAT"),
|
||||
CAMEL("Camel", Enemies.FRIENDLY, "CAMEL"),
|
||||
SNIFFER("Sniffer", Enemies.FRIENDLY, "SNIFFER"),
|
||||
ARMADILLO("Armadillo", Enemies.FRIENDLY, "ARMADILLO"),
|
||||
BREEZE("Breeze", Enemies.ENEMY, "BREEZE"),
|
||||
BOGGED("Bogged", Enemies.ENEMY, "BOGGED"),
|
||||
CREAKING("Creaking", Enemies.ENEMY, "CREAKING")
|
||||
CREAKING("Creaking", Enemies.ENEMY, "CREAKING"),
|
||||
HAPPY_GHAST("HappyGhast", Enemies.FRIENDLY, "HAPPY_GHAST"),
|
||||
COPPER_GOLEM("CopperGolem", Enemies.FRIENDLY, "COPPER_GOLEM"),
|
||||
CAMEL_HUSK("CamelHusk", Enemies.NEUTRAL, "CAMEL_HUSK"),
|
||||
NAUTILUS("Nautilus", Enemies.NEUTRAL, "NAUTILUS"),
|
||||
ZOMBIE_NAUTILUS("ZombieNautilus", Enemies.NEUTRAL, "ZOMBIE_NAUTILUS"),
|
||||
PARCHED("Parched", Enemies.ENEMY, "PARCHED"),
|
||||
SULFUR_CUBE("SulfurCube", Enemies.FRIENDLY, "SULFUR_CUBE"),
|
||||
CUSHION("Cushion", Enemies.FRIENDLY, "CUSHION")
|
||||
;
|
||||
|
||||
private static final Map<String, Mob> hashMap = new HashMap<>();
|
||||
@@ -185,7 +204,7 @@ public enum Mob {
|
||||
public Entity spawn(final World world, final Server server, final Location loc) throws MobException {
|
||||
final Entity entity = world.spawn(loc, this.bukkitType.getEntityClass());
|
||||
if (entity == null) {
|
||||
Essentials.getWrappedLogger().log(Level.WARNING, AdventureUtil.miniToLegacy(tlLiteral("unableToSpawnMob")));
|
||||
Essentials.getWrappedLogger().log(Level.WARNING, AdventureUtil.getAdventureFacet().miniToLegacy(tlLiteral("unableToSpawnMob")));
|
||||
throw new MobException();
|
||||
}
|
||||
return entity;
|
||||
|
||||
@@ -6,9 +6,12 @@ import com.earth2me.essentials.utils.VersionUtil;
|
||||
import net.ess3.nms.refl.ReflUtil;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.TreeSpecies;
|
||||
import org.bukkit.entity.AbstractNautilus;
|
||||
import org.bukkit.entity.Axolotl;
|
||||
import org.bukkit.entity.Boat;
|
||||
import org.bukkit.entity.Camel;
|
||||
import org.bukkit.entity.Chicken;
|
||||
import org.bukkit.entity.Cow;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Fox;
|
||||
@@ -18,13 +21,18 @@ import org.bukkit.entity.MushroomCow;
|
||||
import org.bukkit.entity.Ocelot;
|
||||
import org.bukkit.entity.Panda;
|
||||
import org.bukkit.entity.Parrot;
|
||||
import org.bukkit.entity.Pig;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Salmon;
|
||||
import org.bukkit.entity.TropicalFish;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.bukkit.entity.Wolf;
|
||||
import org.bukkit.entity.ZombieNautilus;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static com.earth2me.essentials.utils.EnumUtil.getEntityType;
|
||||
@@ -32,8 +40,21 @@ import static com.earth2me.essentials.utils.EnumUtil.getEntityType;
|
||||
public final class MobCompat {
|
||||
|
||||
// Constants for mob interfaces added in later versions
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static final Class RAIDER = ReflUtil.getClassCached("org.bukkit.entity.Raider");
|
||||
public static final Class<?> RAIDER = ReflUtil.getClassCached("org.bukkit.entity.Raider");
|
||||
|
||||
// Stupid hacks to avoid Commodore rewrites.
|
||||
private static final Class<?> COW = ReflUtil.getClassCached("org.bukkit.entity.Cow");
|
||||
private static final Class<?> COW_VARIANT = ReflUtil.getClassCached("org.bukkit.entity.Cow$Variant");
|
||||
private static final MethodHandle COW_VARIANT_HANDLE;
|
||||
|
||||
static {
|
||||
MethodHandle handle = null;
|
||||
try {
|
||||
handle = MethodHandles.lookup().findVirtual(COW, "setVariant", MethodType.methodType(void.class, COW_VARIANT));
|
||||
} catch (final Throwable ignored) {
|
||||
}
|
||||
COW_VARIANT_HANDLE = handle;
|
||||
}
|
||||
|
||||
// Constants for mobs added in later versions
|
||||
public static final EntityType LLAMA = getEntityType("LLAMA");
|
||||
@@ -50,6 +71,9 @@ public final class MobCompat {
|
||||
public static final EntityType FROG = getEntityType("FROG");
|
||||
public static final EntityType CAMEL = getEntityType("CAMEL");
|
||||
public static final EntityType SALMON = getEntityType("SALMON");
|
||||
public static final EntityType CAMEL_HUSK = getEntityType("CAMEL_HUSK");
|
||||
public static final EntityType NAUTILUS = getEntityType("NAUTILUS");
|
||||
public static final EntityType ZOMBIE_NAUTILUS = getEntityType("ZOMBIE_NAUTILUS");
|
||||
|
||||
// Constants for mobs that have changed since earlier versions
|
||||
public static final EntityType CAT = getEntityType("CAT", "OCELOT");
|
||||
@@ -64,6 +88,7 @@ public final class MobCompat {
|
||||
public static final EntityType END_CRYSTAL = getEntityType("END_CRYSTAL", "ENDER_CRYSTAL");
|
||||
public static final EntityType FIREWORK_ROCKET = getEntityType("FIREWORK_ROCKET", "FIREWORK");
|
||||
public static final EntityType OAK_BOAT = getEntityType("BOAT", "OAK_BOAT");
|
||||
public static final EntityType OAK_CHEST_BOAT = getEntityType("CHEST_BOAT", "OAK_CHEST_BOAT");
|
||||
|
||||
private MobCompat() {
|
||||
}
|
||||
@@ -250,6 +275,65 @@ public final class MobCompat {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setCowVariant(final Entity spawned, final String variant) {
|
||||
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_21_5_R01) || COW_VARIANT_HANDLE == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (spawned instanceof Cow) {
|
||||
try {
|
||||
COW_VARIANT_HANDLE.invoke(spawned, RegistryUtil.valueOf(COW_VARIANT, variant));
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setChickenVariant(final Entity spawned, final String variant) {
|
||||
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_21_5_R01)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (spawned instanceof Chicken) {
|
||||
//noinspection DataFlowIssue
|
||||
((Chicken) spawned).setVariant(RegistryUtil.valueOf(Chicken.Variant.class, variant));
|
||||
}
|
||||
}
|
||||
|
||||
public static void setPigVariant(final Entity spawned, final String variant) {
|
||||
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_21_5_R01)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (spawned instanceof Pig) {
|
||||
//noinspection DataFlowIssue
|
||||
((Pig) spawned).setVariant(RegistryUtil.valueOf(Pig.Variant.class, variant));
|
||||
}
|
||||
}
|
||||
|
||||
public static void setZombieNautilusVariant(final Entity spawned, final String variant) {
|
||||
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_21_11_R01)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (spawned instanceof ZombieNautilus) {
|
||||
//noinspection DataFlowIssue
|
||||
((ZombieNautilus) spawned).setVariant(RegistryUtil.valueOf(ZombieNautilus.Variant.class, variant));
|
||||
}
|
||||
}
|
||||
|
||||
public static void setNautilusSaddle(final Entity entity, final Player target) {
|
||||
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_21_11_R01)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity instanceof AbstractNautilus) {
|
||||
final AbstractNautilus nautilus = (AbstractNautilus) entity;
|
||||
nautilus.setTamed(true);
|
||||
nautilus.setOwner(target);
|
||||
nautilus.getInventory().setSaddle(new ItemStack(Material.SADDLE, 1));
|
||||
}
|
||||
}
|
||||
|
||||
public enum CatType {
|
||||
// These are (loosely) Mojang names for the cats
|
||||
SIAMESE("SIAMESE", "SIAMESE_CAT"),
|
||||
@@ -326,6 +410,7 @@ public final class MobCompat {
|
||||
OAK("GENERIC", "OAK"),
|
||||
SPRUCE("REDWOOD", "SPRUCE"),
|
||||
MANGROVE("GENERIC", "MANGROVE"),
|
||||
POPLAR("GENERIC", "POPLAR"),
|
||||
;
|
||||
|
||||
private final String treeSpecies;
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.entity.Ageable;
|
||||
import org.bukkit.entity.Boat;
|
||||
import org.bukkit.entity.ChestedHorse;
|
||||
import org.bukkit.entity.Chicken;
|
||||
import org.bukkit.entity.Creeper;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
@@ -54,8 +55,8 @@ public enum MobData {
|
||||
BABY_VILLAGER("child", EntityType.VILLAGER, Data.BABY, false),
|
||||
TAMED_TAMEABLE("tamed", Tameable.class, Data.TAMED, true),
|
||||
TAME_TAMEABLE("tame", Tameable.class, Data.TAMED, false),
|
||||
RANDOM_SHEEP("random", EntityType.SHEEP, Data.COLORABLE, true),
|
||||
COLORABLE_SHEEP("", Arrays.stream(DyeColor.values()).map(color -> color.name().toLowerCase(Locale.ENGLISH)).collect(Collectors.toList()), EntityType.SHEEP, Data.COLORABLE, true),
|
||||
RANDOM_COLORABLE("random", Colorable.class, Data.COLORABLE, true),
|
||||
COLORABLE("", Arrays.stream(DyeColor.values()).map(color -> color.name().toLowerCase(Locale.ENGLISH)).collect(Collectors.toList()), Colorable.class, Data.COLORABLE, true),
|
||||
POLKA_HORSE("polka", EntityType.HORSE, Horse.Style.BLACK_DOTS, true),
|
||||
SOOTY_HORSE("sooty", EntityType.HORSE, Horse.Style.BLACK_DOTS, false),
|
||||
BLAZE_HORSE("blaze", EntityType.HORSE, Horse.Style.WHITE, true),
|
||||
@@ -81,6 +82,7 @@ public enum MobData {
|
||||
SADDLE_HORSE("saddle", EntityType.HORSE, Data.HORSESADDLE, true),
|
||||
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),
|
||||
NETHERITE_HORSE_ARMOR("netheritearmor", EntityType.HORSE, EnumUtil.getMaterial("NETHERITE_HORSE_ARMOR"), 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),
|
||||
@@ -179,8 +181,6 @@ public enum MobData {
|
||||
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),
|
||||
RANDOM_SHULKER("random", MobCompat.SHULKER, Data.COLORABLE, true),
|
||||
COLORABLE_SHULKER("", Arrays.stream(DyeColor.values()).map(color -> color.name().toLowerCase(Locale.ENGLISH)).collect(Collectors.toList()), MobCompat.SHULKER, Data.COLORABLE, true),
|
||||
RED_FOX("red", MobCompat.FOX, "fox:RED", true),
|
||||
SNOW_FOX("snow", MobCompat.FOX, "fox:SNOW", true),
|
||||
SIZE_PHANTOM("", Collections.singletonList("<1-100>"), MobCompat.PHANTOM, Data.SIZE, true),
|
||||
@@ -206,12 +206,13 @@ public enum MobData {
|
||||
JUNGLE_BOAT("jungle", Boat.class, MobCompat.BoatVariant.JUNGLE, true),
|
||||
REDWOOD_BOAT("redwood", Boat.class, MobCompat.BoatVariant.REDWOOD, true),
|
||||
MANGROVE_BOAT("mangrove", Boat.class, MobCompat.BoatVariant.MANGROVE, true),
|
||||
POPLAR_BOAT("poplar", Boat.class, MobCompat.BoatVariant.POPLAR, true),
|
||||
OAK_BOAT("oak", Boat.class, MobCompat.BoatVariant.OAK, true),
|
||||
SPRUCE_BOAT("spruce", Boat.class, MobCompat.BoatVariant.SPRUCE, true),
|
||||
SADDLE_CAMEL("saddle", MobCompat.CAMEL, Data.CAMELSADDLE, true),
|
||||
PALE_WOLF("pale", EntityType.WOLF, "wolf:PALE", true),
|
||||
SPOTTED_WOLF("spotted", EntityType.WOLF, "wolf:PALE", true),
|
||||
SNOWY_WOLF("snowy", EntityType.WOLF, "wolf:PALE", true),
|
||||
SPOTTED_WOLF("spotted", EntityType.WOLF, "wolf:SPOTTED", true),
|
||||
SNOWY_WOLF("snowy", EntityType.WOLF, "wolf:SNOWY", true),
|
||||
BLACK_WOLF("black", EntityType.WOLF, "wolf:BLACK", true),
|
||||
ASHEN_WOLF("ashen", EntityType.WOLF, "wolf:ASHEN", true),
|
||||
RUSTY_WOLF("rusty", EntityType.WOLF, "wolf:RUSTY", true),
|
||||
@@ -221,6 +222,20 @@ public enum MobData {
|
||||
SMALL_SALMON("small", MobCompat.SALMON, "salmon:SMALL", true),
|
||||
MEDIUM_SALMON("medium", MobCompat.SALMON, "salmon:MEDIUM", true),
|
||||
LARGE_SALMON("large", MobCompat.SALMON, "salmon:LARGE", true),
|
||||
TEMPERATE_COW("temperate", EntityType.COW.getEntityClass(), "cow:TEMPERATE", true),
|
||||
WARM_COW("warm", EntityType.COW.getEntityClass(), "cow:WARM", true),
|
||||
COLD_COW("cold", EntityType.COW.getEntityClass(), "cow:COLD", true),
|
||||
TEMPERATE_CHICKEN("temperate", Chicken.class, "chicken:TEMPERATE", true),
|
||||
WARM_CHICKEN("warm", Chicken.class, "chicken:WARM", true),
|
||||
COLD_CHICKEN("cold", Chicken.class, "chicken:COLD", true),
|
||||
TEMPERATE_PIG("temperate", Pig.class, "pig:TEMPERATE", true),
|
||||
WARM_PIG("warm", Pig.class, "pig:WARM", true),
|
||||
COLD_PIG("cold", Pig.class, "pig:COLD", true),
|
||||
SADDLE_CAMEL_HUSK("saddle", MobCompat.CAMEL_HUSK, Data.CAMELHUSKSADDLE, true),
|
||||
TEMPERATE_ZOMBIE_NAUTILUS("temperate", MobCompat.ZOMBIE_NAUTILUS, "zombienautilus:TEMPERATE", true),
|
||||
WARM_ZOMBIE_NAUTILUS("warm", MobCompat.ZOMBIE_NAUTILUS, "zombienautilus:WARM", true),
|
||||
SADDLE_NAUTILUS("saddle", MobCompat.NAUTILUS, Data.NAUTILUSSADDLE, true),
|
||||
SADDLE_ZOMBIE_NAUTILUS("saddle", MobCompat.ZOMBIE_NAUTILUS, Data.NAUTILUSSADDLE, true)
|
||||
;
|
||||
|
||||
final private String nickname;
|
||||
@@ -401,6 +416,12 @@ public enum MobData {
|
||||
((Goat) spawned).setScreaming(true);
|
||||
} else if (this.value.equals(Data.CAMELSADDLE)) {
|
||||
MobCompat.setCamelSaddle(spawned, target);
|
||||
} else if (this.value.equals(Data.CAMELHUSKSADDLE)) {
|
||||
MobCompat.setCamelSaddle(spawned, target);
|
||||
} else if (this.value.equals(Data.NAUTILUSSADDLE)) {
|
||||
MobCompat.setNautilusSaddle(spawned, target);
|
||||
} else if (this.value.equals(Data.ZOMBIENAUTILUSSADDLE)) {
|
||||
MobCompat.setNautilusSaddle(spawned, target);
|
||||
} else if (this.value instanceof MobCompat.BoatVariant) {
|
||||
MobCompat.setBoatVariant(spawned, (MobCompat.BoatVariant) this.value);
|
||||
} else if (this.value instanceof String) {
|
||||
@@ -442,6 +463,18 @@ public enum MobData {
|
||||
case "salmon":
|
||||
MobCompat.setSalmonSize(spawned, split[1]);
|
||||
break;
|
||||
case "cow":
|
||||
MobCompat.setCowVariant(spawned, split[1]);
|
||||
break;
|
||||
case "chicken":
|
||||
MobCompat.setChickenVariant(spawned, split[1]);
|
||||
break;
|
||||
case "pig":
|
||||
MobCompat.setPigVariant(spawned, split[1]);
|
||||
break;
|
||||
case "zombienautilus":
|
||||
MobCompat.setZombieNautilusVariant(spawned, split[1]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
Essentials.getWrappedLogger().warning("Unknown mob data type: " + this.toString());
|
||||
@@ -467,5 +500,8 @@ public enum MobData {
|
||||
FISH_PATTERN_COLOR,
|
||||
GOAT_SCREAMING,
|
||||
CAMELSADDLE,
|
||||
CAMELHUSKSADDLE,
|
||||
NAUTILUSSADDLE,
|
||||
ZOMBIENAUTILUSSADDLE,
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import net.ess3.api.TranslatableException;
|
||||
@@ -39,7 +38,7 @@ public final class PlayerList {
|
||||
groupString.append(tlLiteral("listHiddenTag"));
|
||||
}
|
||||
user.setDisplayNick();
|
||||
groupString.append(AdventureUtil.legacyToMini(user.getDisplayName()));
|
||||
groupString.append(ess.getAdventureFacet().legacyToMini(user.getDisplayName()));
|
||||
|
||||
final String strippedNick = FormatUtil.stripFormat(user.getNickname());
|
||||
if (ess.getSettings().realNamesOnList() && strippedNick != null && !strippedNick.equals(user.getName())) {
|
||||
|
||||
@@ -161,6 +161,14 @@ public final class Potions {
|
||||
ALIASPOTIONS.put("wind", PotionEffectType.WIND_CHARGED);
|
||||
} catch (final Throwable ignored) {
|
||||
}
|
||||
|
||||
// 1.21.11
|
||||
try {
|
||||
POTIONS.put("breathofthenautilus", PotionEffectType.BREATH_OF_THE_NAUTILUS);
|
||||
ALIASPOTIONS.put("nautilusbreath", PotionEffectType.BREATH_OF_THE_NAUTILUS);
|
||||
ALIASPOTIONS.put("nautilus", PotionEffectType.BREATH_OF_THE_NAUTILUS);
|
||||
} catch (final Throwable ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private Potions() {
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.earth2me.essentials.utils.LocationUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.ess3.provider.BiomeKeyProvider;
|
||||
import net.ess3.provider.BiomeNameProvider;
|
||||
import net.ess3.provider.WorldInfoProvider;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -68,6 +69,8 @@ public class RandomTeleport implements IConf {
|
||||
public void setCenter(final String name, final Location center) {
|
||||
config.setProperty(locationKey(name, "center"), center);
|
||||
config.save();
|
||||
// Clear cached locations since center changed
|
||||
this.getCachedLocations(name).clear();
|
||||
}
|
||||
|
||||
public double getMinRange(final String name) {
|
||||
@@ -77,6 +80,8 @@ public class RandomTeleport implements IConf {
|
||||
public void setMinRange(final String name, final double minRange) {
|
||||
config.setProperty(locationKey(name, "min-range"), minRange);
|
||||
config.save();
|
||||
// Clear cached locations since min range changed
|
||||
this.getCachedLocations(name).clear();
|
||||
}
|
||||
|
||||
public double getMaxRange(final String name) {
|
||||
@@ -86,6 +91,8 @@ public class RandomTeleport implements IConf {
|
||||
public void setMaxRange(final String name, final double maxRange) {
|
||||
config.setProperty(locationKey(name, "max-range"), maxRange);
|
||||
config.save();
|
||||
// Clear cached locations since max range changed
|
||||
this.getCachedLocations(name).clear();
|
||||
}
|
||||
|
||||
public String getDefaultLocation() {
|
||||
@@ -238,8 +245,9 @@ public class RandomTeleport implements IConf {
|
||||
|
||||
// Exclude biome if enum or namespaced key matches
|
||||
private boolean isExcludedBiome(final Location location) {
|
||||
final BiomeNameProvider biomeNameProvider = ess.provider(BiomeNameProvider.class);
|
||||
final Set<String> excluded = getExcludedBiomes();
|
||||
final String enumKey = location.getBlock().getBiome().name().toLowerCase();
|
||||
final String enumKey = biomeNameProvider.getBiomeName(location.getBlock());
|
||||
// Try with good old bukkit enum
|
||||
if (excluded.contains(enumKey)) {
|
||||
return true;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.api.IItemDb;
|
||||
import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import com.earth2me.essentials.config.ConfigurateUtil;
|
||||
@@ -8,7 +9,6 @@ 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.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.utils.LocationUtil;
|
||||
@@ -18,8 +18,6 @@ import net.ess3.provider.KnownCommandsProvider;
|
||||
import net.ess3.provider.SyncCommandsProvider;
|
||||
import net.essentialsx.api.v2.ChatType;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
@@ -46,6 +44,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Predicate;
|
||||
@@ -59,8 +58,8 @@ import static com.earth2me.essentials.I18n.tlLiteral;
|
||||
public class Settings implements net.ess3.api.ISettings {
|
||||
private static final BigDecimal DEFAULT_MAX_MONEY = new BigDecimal("10000000000000");
|
||||
private static final BigDecimal DEFAULT_MIN_MONEY = new BigDecimal("-10000000000000");
|
||||
private static final Tag DEFAULT_PRIMARY_COLOR = Tag.styling(NamedTextColor.GOLD);
|
||||
private static final Tag DEFAULT_SECONDARY_COLOR = Tag.styling(NamedTextColor.RED);
|
||||
private static final String DEFAULT_PRIMARY_COLOR = NamedTextColor.GOLD.toString();
|
||||
private static final String DEFAULT_SECONDARY_COLOR = NamedTextColor.RED.toString();
|
||||
private final transient EssentialsConfiguration config;
|
||||
private final transient IEssentials ess;
|
||||
private final transient AtomicInteger reloadCount = new AtomicInteger(0);
|
||||
@@ -92,6 +91,7 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
private BigDecimal maxMoney = DEFAULT_MAX_MONEY;
|
||||
private BigDecimal minMoney = DEFAULT_MIN_MONEY;
|
||||
private boolean economyLog = false;
|
||||
private boolean economyLogUUID = false;
|
||||
// #easteregg
|
||||
private boolean economyLogUpdate = false;
|
||||
private boolean changeDisplayName = true;
|
||||
@@ -145,14 +145,17 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
private boolean isWaterSafe;
|
||||
private boolean isSafeUsermap;
|
||||
private boolean logCommandBlockCommands;
|
||||
private boolean logConsoleCommands;
|
||||
private Set<Predicate<String>> nickBlacklist;
|
||||
private boolean resetNickOnNameChange;
|
||||
private double maxProjectileSpeed;
|
||||
private boolean removeEffectsOnHeal;
|
||||
private Map<String, String> worldAliases;
|
||||
private Tag primaryColor = DEFAULT_PRIMARY_COLOR;
|
||||
private Tag secondaryColor = DEFAULT_SECONDARY_COLOR;
|
||||
private String primaryColor = DEFAULT_PRIMARY_COLOR;
|
||||
private String secondaryColor = DEFAULT_SECONDARY_COLOR;
|
||||
private Set<String> multiplierPerms;
|
||||
private BigDecimal defaultMultiplier;
|
||||
private List<String> afkTimeoutCommands = Collections.emptyList();
|
||||
|
||||
public Settings(final IEssentials ess) {
|
||||
this.ess = ess;
|
||||
@@ -294,6 +297,11 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
return config.getBoolean("force-safe-teleport-location", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConsiderWorldHeightForTeleportSafety() {
|
||||
return config.getBoolean("consider-world-height-for-teleport-safety", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTeleportPassengerDismount() {
|
||||
return config.getBoolean("teleport-passenger-dismount", true);
|
||||
@@ -506,11 +514,20 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
return config.getString("nickname-prefix", "~");
|
||||
}
|
||||
|
||||
private boolean _resetNickOnNameChange() {
|
||||
return config.getBoolean("reset-nick-on-name-change", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNicknamePrefix() {
|
||||
return nicknamePrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResetNickOnNameChange() {
|
||||
return resetNickOnNameChange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTeleportCooldown() {
|
||||
return config.getDouble("teleport-cooldown", 0);
|
||||
@@ -884,6 +901,7 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
}
|
||||
|
||||
nicknamePrefix = _getNicknamePrefix();
|
||||
resetNickOnNameChange = _resetNickOnNameChange();
|
||||
operatorColor = _getOperatorColor();
|
||||
changePlayerListName = _changePlayerListName();
|
||||
configDebug = _isDebug();
|
||||
@@ -903,6 +921,7 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
permissionsLagWarning = _getPermissionsLagWarning();
|
||||
economyLagWarning = _getEconomyLagWarning();
|
||||
economyLog = _isEcoLogEnabled();
|
||||
economyLogUUID = _isEcoLogUUIDEnabled();
|
||||
economyLogUpdate = _isEcoLogUpdateEnabled();
|
||||
economyDisabled = _isEcoDisabled();
|
||||
allowSilentJoin = _allowSilentJoinQuit();
|
||||
@@ -927,6 +946,7 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
isWaterSafe = _isWaterSafe();
|
||||
isSafeUsermap = _isSafeUsermap();
|
||||
logCommandBlockCommands = _logCommandBlockCommands();
|
||||
logConsoleCommands = _logConsoleCommands();
|
||||
nickBlacklist = _getNickBlacklist();
|
||||
maxProjectileSpeed = _getMaxProjectileSpeed();
|
||||
removeEffectsOnHeal = _isRemovingEffectsOnHeal();
|
||||
@@ -938,6 +958,7 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
secondaryColor = _getSecondaryColor();
|
||||
multiplierPerms = _getMultiplierPerms();
|
||||
defaultMultiplier = _getDefaultMultiplier();
|
||||
afkTimeoutCommands = _getAfkTimeoutCommands();
|
||||
|
||||
reloadCount.incrementAndGet();
|
||||
}
|
||||
@@ -968,7 +989,7 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
final ItemStack iStack = itemDb.get(itemName);
|
||||
epItemSpwn.add(iStack.getType());
|
||||
} catch (final Exception ex) {
|
||||
ess.getLogger().log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("unknownItemInList", itemName, "item-spawn-blacklist")), ex);
|
||||
ess.getLogger().log(Level.SEVERE, ess.getAdventureFacet().miniToLegacy(tlLiteral("unknownItemInList", itemName, "item-spawn-blacklist")), ex);
|
||||
}
|
||||
}
|
||||
return epItemSpwn;
|
||||
@@ -996,7 +1017,7 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
try {
|
||||
newSigns.add(Signs.valueOf(signName).getSign());
|
||||
} catch (final Exception ex) {
|
||||
ess.getLogger().log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("unknownItemInList", signName, "enabledSigns")));
|
||||
ess.getLogger().log(Level.SEVERE, ess.getAdventureFacet().miniToLegacy(tlLiteral("unknownItemInList", signName, "enabledSigns")));
|
||||
continue;
|
||||
}
|
||||
signsEnabled = true;
|
||||
@@ -1124,7 +1145,7 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
}
|
||||
|
||||
if (mat == null) {
|
||||
ess.getLogger().log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("unknownItemInList", itemName, configName)));
|
||||
ess.getLogger().log(Level.SEVERE, ess.getAdventureFacet().miniToLegacy(tlLiteral("unknownItemInList", itemName, configName)));
|
||||
} else {
|
||||
list.add(mat);
|
||||
}
|
||||
@@ -1173,6 +1194,14 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
return config.getBoolean("economy-log-enabled", false);
|
||||
}
|
||||
|
||||
public boolean _isEcoLogUUIDEnabled() {
|
||||
return config.getBoolean("economy-log-uuids", false);
|
||||
}
|
||||
|
||||
public boolean isEcoLogUUIDEnabled() {
|
||||
return economyLogUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEcoLogUpdateEnabled() {
|
||||
return economyLogUpdate;
|
||||
@@ -1262,8 +1291,17 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAutoAfkKick() {
|
||||
return config.getLong("auto-afk-kick", -1);
|
||||
public long getAutoAfkTimeout() {
|
||||
return config.getLong("auto-afk-timeout", config.getLong("auto-afk-kick", -1));
|
||||
}
|
||||
|
||||
private List<String> _getAfkTimeoutCommands() {
|
||||
return new ArrayList<>(config.getList("afk-timeout-commands", String.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAfkTimeoutCommands() {
|
||||
return afkTimeoutCommands;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1298,6 +1336,11 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
return config.getBoolean("cancel-afk-on-chat", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancelAfkOnFish() {
|
||||
return config.getBoolean("cancel-afk-on-fish", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sleepIgnoresAfkPlayers() {
|
||||
return sleepIgnoresAfkPlayers;
|
||||
@@ -1619,6 +1662,11 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
return config.getBoolean("use-custom-server-full-message", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomWhitelistMessage() {
|
||||
return config.getBoolean("use-custom-whitelist-message", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJoinQuitMessagePlayerCount() {
|
||||
return config.getInt("hide-join-quit-messages-above", -1);
|
||||
@@ -1872,7 +1920,7 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
try {
|
||||
newSigns.add(Signs.valueOf(signName).getSign());
|
||||
} catch (final Exception ex) {
|
||||
ess.getLogger().log(Level.SEVERE, AdventureUtil.miniToLegacy(tlLiteral("unknownItemInList", signName, "unprotected-sign-names")));
|
||||
ess.getLogger().log(Level.SEVERE, ess.getAdventureFacet().miniToLegacy(tlLiteral("unknownItemInList", signName, "unprotected-sign-names")));
|
||||
}
|
||||
}
|
||||
return newSigns;
|
||||
@@ -1938,6 +1986,11 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
return config.getBoolean("world-change-preserve-flying", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGamemodeChangePreserveFlying() {
|
||||
return config.getBoolean("gamemode-change-preserve-flying", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWorldChangeSpeedResetEnabled() {
|
||||
return config.getBoolean("world-change-speed-reset", true);
|
||||
@@ -2053,6 +2106,15 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
return logCommandBlockCommands;
|
||||
}
|
||||
|
||||
private boolean _logConsoleCommands() {
|
||||
return config.getBoolean("log-console-commands", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean logConsoleCommands() {
|
||||
return logConsoleCommands;
|
||||
}
|
||||
|
||||
private Set<Predicate<String>> _getNickBlacklist() {
|
||||
final Set<Predicate<String>> blacklist = new HashSet<>();
|
||||
|
||||
@@ -2120,6 +2182,11 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
return config.getBoolean("show-zero-baltop", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNickRegex() {
|
||||
return config.getString("allowed-nicks-regex", "^[a-zA-Z_0-9§]+$");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getMultiplier(final User user) {
|
||||
BigDecimal multiplier = defaultMultiplier;
|
||||
@@ -2153,39 +2220,40 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getPrimaryColor() {
|
||||
public String getPrimaryColor() {
|
||||
return primaryColor;
|
||||
}
|
||||
|
||||
private Tag _getPrimaryColor() {
|
||||
private String _getPrimaryColor() {
|
||||
final String color = config.getString("message-colors.primary", "#ffaa00");
|
||||
final TextColor textColor = _getTagColor(color);
|
||||
return textColor != null ? Tag.styling(textColor) : DEFAULT_PRIMARY_COLOR;
|
||||
final String textColor = _getTagColor(color);
|
||||
return textColor != null ? textColor : DEFAULT_PRIMARY_COLOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getSecondaryColor() {
|
||||
public String getSecondaryColor() {
|
||||
return secondaryColor;
|
||||
}
|
||||
|
||||
private Tag _getSecondaryColor() {
|
||||
private String _getSecondaryColor() {
|
||||
final String color = config.getString("message-colors.secondary", "#ff5555");
|
||||
final TextColor textColor = _getTagColor(color);
|
||||
return textColor != null ? Tag.styling(textColor) : DEFAULT_SECONDARY_COLOR;
|
||||
final String textColor = _getTagColor(color);
|
||||
return textColor != null ? textColor : DEFAULT_SECONDARY_COLOR;
|
||||
}
|
||||
|
||||
private TextColor _getTagColor(final String color) {
|
||||
private String _getTagColor(final String color) {
|
||||
try {
|
||||
if (color.startsWith("#") && color.length() == 7 && NumberUtil.isHexadecimal(color.substring(1))) {
|
||||
return TextColor.color(Color.fromRGB(Integer.decode(color)).asRGB());
|
||||
Color.fromRGB(Integer.decode(color));
|
||||
return color;
|
||||
}
|
||||
|
||||
if (color.length() == 1) {
|
||||
return AdventureUtil.fromChar(color.charAt(0));
|
||||
return Objects.requireNonNull(AdventureUtil.fromChar(color.charAt(0))).toString();
|
||||
}
|
||||
|
||||
return NamedTextColor.NAMES.value(color.toLowerCase(Locale.ENGLISH));
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
return Objects.requireNonNull(NamedTextColor.NAMES.value(color.toLowerCase(Locale.ENGLISH))).toString();
|
||||
} catch (NullPointerException | IllegalArgumentException ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -2195,6 +2263,11 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
return config.getBigDecimal("baltop-requirements.minimum-balance", BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBaltopEntryLimit() {
|
||||
return config.getInt("baltop-entry-limit", -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBaltopMinPlaytime() {
|
||||
return config.getLong("baltop-requirements.minimum-playtime", 0);
|
||||
|
||||
@@ -32,6 +32,10 @@ public final 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 COPPER_HELMET = EnumUtil.getMaterial("COPPER_HELMET");
|
||||
private static final Material COPPER_CHESTPLATE = EnumUtil.getMaterial("COPPER_CHESTPLATE");
|
||||
private static final Material COPPER_LEGGINGS = EnumUtil.getMaterial("COPPER_LEGGINGS");
|
||||
private static final Material COPPER_BOOTS = EnumUtil.getMaterial("COPPER_BOOTS");
|
||||
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");
|
||||
@@ -210,6 +214,11 @@ public final class SpawnMob {
|
||||
invent.setLeggings(new ItemStack(Material.NETHERITE_LEGGINGS, 1));
|
||||
invent.setChestplate(new ItemStack(Material.NETHERITE_CHESTPLATE, 1));
|
||||
invent.setHelmet(new ItemStack(Material.NETHERITE_HELMET, 1));
|
||||
} else if (inputData.contains("copper") && COPPER_HELMET != null) {
|
||||
invent.setBoots(new ItemStack(COPPER_BOOTS, 1));
|
||||
invent.setLeggings(new ItemStack(COPPER_LEGGINGS, 1));
|
||||
invent.setChestplate(new ItemStack(COPPER_CHESTPLATE, 1));
|
||||
invent.setHelmet(new ItemStack(COPPER_HELMET, 1));
|
||||
} else if (inputData.contains("diamond")) {
|
||||
invent.setBoots(new ItemStack(Material.DIAMOND_BOOTS, 1));
|
||||
invent.setLeggings(new ItemStack(Material.DIAMOND_LEGGINGS, 1));
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.craftbukkit.SetExpFix;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
@@ -20,6 +20,7 @@ import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
@@ -86,7 +87,14 @@ public class Trade {
|
||||
sb.append(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date()));
|
||||
sb.append("\",\"");
|
||||
if (sender != null) {
|
||||
sb.append(sender);
|
||||
String senderIdentifier = sender;
|
||||
if (ess.getSettings().isEcoLogUUIDEnabled()) {
|
||||
final UUID uuid = ess.getUsers().getNameCache().get(sender);
|
||||
if (uuid != null) {
|
||||
senderIdentifier = uuid.toString();
|
||||
}
|
||||
}
|
||||
sb.append(senderIdentifier);
|
||||
}
|
||||
sb.append("\",");
|
||||
if (charge == null) {
|
||||
@@ -112,7 +120,14 @@ public class Trade {
|
||||
}
|
||||
sb.append(",\"");
|
||||
if (receiver != null) {
|
||||
sb.append(receiver);
|
||||
String receiverIdentifier = receiver;
|
||||
if (ess.getSettings().isEcoLogUUIDEnabled()) {
|
||||
final UUID uuid = ess.getUsers().getNameCache().get(receiver);
|
||||
if (uuid != null) {
|
||||
receiverIdentifier = uuid.toString();
|
||||
}
|
||||
}
|
||||
sb.append(receiverIdentifier);
|
||||
}
|
||||
sb.append("\",");
|
||||
if (pay == null) {
|
||||
@@ -145,7 +160,7 @@ public class Trade {
|
||||
sb.append(loc.getBlockY()).append(",");
|
||||
sb.append(loc.getBlockZ()).append(",");
|
||||
}
|
||||
|
||||
|
||||
if (endBalance == null) {
|
||||
sb.append(",");
|
||||
} else {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.ComponentHolder;
|
||||
import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.economy.EconomyLayer;
|
||||
import com.earth2me.essentials.economy.EconomyLayers;
|
||||
import com.earth2me.essentials.messaging.IMessageRecipient;
|
||||
import com.earth2me.essentials.messaging.SimpleMessageRecipient;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
@@ -22,10 +23,9 @@ import net.ess3.api.events.JailStatusChangeEvent;
|
||||
import net.ess3.api.events.MuteStatusChangeEvent;
|
||||
import net.ess3.api.events.UserBalanceUpdateEvent;
|
||||
import net.ess3.provider.PlayerLocaleProvider;
|
||||
import net.essentialsx.api.v2.events.PreTransactionEvent;
|
||||
import net.essentialsx.api.v2.events.TransactionEvent;
|
||||
import net.essentialsx.api.v2.services.mail.MailSender;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentLike;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
@@ -136,6 +136,10 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(final String node) {
|
||||
if (Essentials.TESTING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean result = isAuthorizedCheck(node);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "checking if " + base.getName() + " has " + node + " - " + result);
|
||||
@@ -143,8 +147,25 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthorizedCached(final String node) {
|
||||
if (Essentials.TESTING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean result = isAuthorizedCachedCheck(node);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "checking if " + base.getName() + " has " + node + " (cached) - " + result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(final String node) {
|
||||
if (Essentials.TESTING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean result = isPermSetCheck(node);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "checking if " + base.getName() + " has " + node + " (set-explicit) - " + result);
|
||||
@@ -178,6 +199,24 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAuthorizedCachedCheck(final String node) {
|
||||
if (base instanceof OfflinePlayerStub) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return ess.getPermissionsHandler().hasPermissionCached(base, node);
|
||||
} catch (final 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;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPermSetCheck(final String node) {
|
||||
if (base instanceof OfflinePlayerStub) {
|
||||
return false;
|
||||
@@ -256,12 +295,20 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
payUser(reciever, value, UserBalanceUpdateEvent.Cause.UNKNOWN);
|
||||
}
|
||||
|
||||
public void payUser(final User reciever, final BigDecimal value, final UserBalanceUpdateEvent.Cause cause) throws Exception {
|
||||
public void payUser(final User reciever, BigDecimal value, final UserBalanceUpdateEvent.Cause cause) throws Exception {
|
||||
if (value.compareTo(BigDecimal.ZERO) < 1) {
|
||||
throw new Exception(tlLocale(playerLocale, "payMustBePositive"));
|
||||
}
|
||||
|
||||
if (canAfford(value)) {
|
||||
// Call an event for pre-transaction
|
||||
final PreTransactionEvent preTransactionEvent = new PreTransactionEvent(this.getSource(), reciever, value);
|
||||
ess.getServer().getPluginManager().callEvent(preTransactionEvent);
|
||||
if (preTransactionEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
value = preTransactionEvent.getAmount();
|
||||
|
||||
setMoney(getMoney().subtract(value), cause);
|
||||
reciever.setMoney(reciever.getMoney().add(value), cause);
|
||||
sendTl("moneySentTo", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)), reciever.getDisplayName());
|
||||
@@ -570,7 +617,8 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
final BigDecimal value = _getMoney();
|
||||
final long elapsed = System.nanoTime() - start;
|
||||
if (elapsed > ess.getSettings().getEconomyLagWarning()) {
|
||||
ess.getLogger().log(Level.INFO, "Lag Notice - Slow Economy Response - Request took over {0}ms!", elapsed / 1000000.0);
|
||||
ess.getLogger().log(Level.INFO, String.format(Locale.ROOT,
|
||||
"Lag Notice - Slow Economy Response - Request took over %.3fms!", elapsed / 1_000_000.0));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -640,7 +688,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
return;
|
||||
}
|
||||
|
||||
this.getBase().setSleepingIgnored(this.isAuthorized("essentials.sleepingignored") || (set && ess.getSettings().sleepIgnoresAfkPlayers()));
|
||||
this.getBase().setSleepingIgnored(this.isAuthorized("essentials.sleepingignored") || set && ess.getSettings().sleepIgnoresAfkPlayers());
|
||||
if (set && !isAfk()) {
|
||||
afkPosition = this.getLocation();
|
||||
this.afkSince = System.currentTimeMillis();
|
||||
@@ -775,6 +823,29 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
return false;
|
||||
}
|
||||
|
||||
// Notifies this (muted) user that they have been silenced, including the reason and remaining time if applicable.
|
||||
public void notifyMuted() {
|
||||
final String dateDiff = getMuteTimeout() > 0 ? DateUtil.formatDateDiff(getMuteTimeout()) : null;
|
||||
if (dateDiff == null) {
|
||||
if (hasMuteReason()) {
|
||||
sendTl("voiceSilencedReason", getMuteReason());
|
||||
} else {
|
||||
sendTl("voiceSilenced");
|
||||
}
|
||||
} else {
|
||||
if (hasMuteReason()) {
|
||||
sendTl("voiceSilencedReasonTime", dateDiff, getMuteReason());
|
||||
} else {
|
||||
sendTl("voiceSilencedTime", dateDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastActivityTime() {
|
||||
return this.lastActivity;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void updateActivity(final boolean broadcast) {
|
||||
updateActivity(broadcast, AfkStatusChangeEvent.Cause.UNKNOWN);
|
||||
@@ -819,24 +890,39 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
return;
|
||||
}
|
||||
|
||||
final long autoafkkick = ess.getSettings().getAutoAfkKick();
|
||||
if (autoafkkick > 0
|
||||
&& lastActivity > 0 && (lastActivity + (autoafkkick * 1000)) < System.currentTimeMillis()
|
||||
final long autoafktimeout = ess.getSettings().getAutoAfkTimeout();
|
||||
|
||||
// Checks if the player has been inactive for longer than the configured auto-afk-timeout time.
|
||||
if (autoafktimeout > 0
|
||||
&& lastActivity > 0 && (lastActivity + (autoafktimeout * 1000)) < System.currentTimeMillis()
|
||||
&& !isAuthorized("essentials.kick.exempt")
|
||||
&& !isAuthorized("essentials.afk.kickexempt")) {
|
||||
lastActivity = 0;
|
||||
final double kickTime = autoafkkick / 60.0;
|
||||
final double kickTime = autoafktimeout / 60.0;
|
||||
|
||||
this.getBase().kickPlayer(AdventureUtil.miniToLegacy(playerTl("autoAfkKickReason", kickTime)));
|
||||
// If `afk-timeout-command` in config.yml is empty, use default Essentials kicking behaviour instead of executing a command.
|
||||
if (ess.getSettings().getAfkTimeoutCommands().isEmpty()) {
|
||||
this.getBase().kickPlayer(ess.getAdventureFacet().miniToLegacy(playerTl("autoAfkKickReason", kickTime)));
|
||||
|
||||
for (final User user : ess.getOnlineUsers()) {
|
||||
if (user.isAuthorized("essentials.kick.notify")) {
|
||||
user.sendTl("playerKicked", Console.DISPLAY_NAME, getName(), user.playerTl("autoAfkKickReason", kickTime));
|
||||
for (final User user : ess.getOnlineUsers()) {
|
||||
if (user.isAuthorized("essentials.kick.notify")) {
|
||||
user.sendTl("playerKicked", Console.displayName(), getName(), user.playerTl("autoAfkKickReason", kickTime));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If `afk-timeout-commands` in config.yml is populated, execute the command(s) instead of kicking the player.
|
||||
for (final String command : ess.getSettings().getAfkTimeoutCommands()) {
|
||||
if (command == null || command.isEmpty()){
|
||||
continue;
|
||||
}
|
||||
// Replace placeholders in the command with actual values.
|
||||
final String cmd = command.replace("{USERNAME}", getName()).replace("{KICKTIME}", String.valueOf(kickTime));
|
||||
ess.getServer().dispatchCommand(ess.getServer().getConsoleSender(), cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
final long autoafk = ess.getSettings().getAutoAfk();
|
||||
if (!isAfk() && autoafk > 0 && lastActivity + autoafk * 1000 < System.currentTimeMillis() && isAuthorized("essentials.afk.auto")) {
|
||||
if (!isAfk() && autoafk > 0 && lastActivity + autoafk * 1000 < System.currentTimeMillis() && isAuthorizedCached("essentials.afk.auto")) {
|
||||
setAfk(true, AfkStatusChangeEvent.Cause.ACTIVITY);
|
||||
if (isAfk() && !isHidden()) {
|
||||
setDisplayNick();
|
||||
@@ -1046,14 +1132,14 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendComponent(ComponentLike component) {
|
||||
ess.getBukkitAudience().player(base).sendMessage(component);
|
||||
public void sendComponent(ComponentHolder component) {
|
||||
ess.getAdventureFacet().send(base, component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component tlComponent(String tlKey, Object... args) {
|
||||
public ComponentHolder tlComponent(String tlKey, Object... args) {
|
||||
final String translation = playerTl(tlKey, args);
|
||||
return AdventureUtil.miniMessage().deserialize(translation);
|
||||
return ess.getAdventureFacet().deserializeMiniMessage(translation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1063,14 +1149,17 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
return;
|
||||
}
|
||||
|
||||
sendComponent(AdventureUtil.miniMessage().deserialize(translation));
|
||||
sendComponent(ess.getAdventureFacet().deserializeMiniMessage(translation));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String playerTl(String tlKey, Object... args) {
|
||||
if (ess.getSettings().isPerPlayerLocale()) {
|
||||
final PlayerLocaleProvider provider = ess.provider(PlayerLocaleProvider.class);
|
||||
return tlLocale(getPlayerLocale(provider.getLocale(base)), tlKey, args);
|
||||
final Locale locale = base != null ? getPlayerLocale(provider.getLocale(base)) : playerLocale;
|
||||
if (locale != null) {
|
||||
return tlLocale(locale, tlKey, args);
|
||||
}
|
||||
}
|
||||
return tlLiteral(tlKey, args);
|
||||
}
|
||||
@@ -1081,7 +1170,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
}
|
||||
|
||||
public Locale getPlayerLocale(final String locale) {
|
||||
if (locale.equals(lastLocaleString)) {
|
||||
if (locale == null || locale.equals(lastLocaleString)) {
|
||||
return playerLocale;
|
||||
}
|
||||
lastLocaleString = locale;
|
||||
|
||||
@@ -42,7 +42,9 @@ public abstract class UserData extends PlayerExtension implements IConf {
|
||||
super(base);
|
||||
this.ess = (Essentials) ess;
|
||||
final File folder = new File(ess.getDataFolder(), "userdata");
|
||||
if (!folder.exists() && !folder.mkdirs()) {
|
||||
// mkdirs() may return false if another thread created the folder concurrently,
|
||||
// so fall back to checking whether the directory now exists to avoid a race.
|
||||
if (!folder.isDirectory() && !folder.mkdirs() && !folder.isDirectory()) {
|
||||
throw new RuntimeException("Unable to create userdata folder!");
|
||||
}
|
||||
|
||||
@@ -74,6 +76,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
|
||||
|
||||
public final void cleanup() {
|
||||
config.blockingSave();
|
||||
ess.getUsers().removeCache(getConfigUUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -271,6 +274,10 @@ public abstract class UserData extends PlayerExtension implements IConf {
|
||||
return !holder.powertools().isEmpty();
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getAllPowertools() {
|
||||
return holder.powertools();
|
||||
}
|
||||
|
||||
public Location getLastLocation() {
|
||||
final LazyLocation lastLocation = holder.lastLocation();
|
||||
return lastLocation != null ? lastLocation.location() : null;
|
||||
@@ -464,6 +471,15 @@ public abstract class UserData extends PlayerExtension implements IConf {
|
||||
config.save();
|
||||
}
|
||||
|
||||
public boolean isFlyModeEnabled() {
|
||||
return holder.flyMode();
|
||||
}
|
||||
|
||||
public void setFlyModeEnabled(final boolean set) {
|
||||
holder.flyMode(set);
|
||||
config.save();
|
||||
}
|
||||
|
||||
public boolean getMuted() {
|
||||
return holder.muted();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.commands.WarpNotFoundException;
|
||||
import com.earth2me.essentials.config.EssentialsConfiguration;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import net.ess3.api.InvalidNameException;
|
||||
import net.ess3.api.TranslatableException;
|
||||
@@ -134,7 +134,7 @@ public class Warps implements IConf, net.ess3.api.IWarps {
|
||||
warpPoints.put(new StringIgnoreCase(name), conf);
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
Essentials.getWrappedLogger().log(Level.WARNING, AdventureUtil.miniToLegacy(tlLiteral("loadWarpError", filename)), ex);
|
||||
Essentials.getWrappedLogger().log(Level.WARNING, AdventureUtil.getAdventureFacet().miniToLegacy(tlLiteral("loadWarpError", filename)), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.earth2me.essentials.adventure;
|
||||
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
public final class AdventureUtil {
|
||||
private static final String LOOKUP = "0123456789abcdefklmnor";
|
||||
private static final NamedTextColor[] COLORS = new NamedTextColor[]{NamedTextColor.BLACK, NamedTextColor.DARK_BLUE, NamedTextColor.DARK_GREEN, NamedTextColor.DARK_AQUA, NamedTextColor.DARK_RED, NamedTextColor.DARK_PURPLE, NamedTextColor.GOLD, NamedTextColor.GRAY, NamedTextColor.DARK_GRAY, NamedTextColor.BLUE, NamedTextColor.GREEN, NamedTextColor.AQUA, NamedTextColor.RED, NamedTextColor.LIGHT_PURPLE, NamedTextColor.YELLOW, NamedTextColor.WHITE};
|
||||
|
||||
private static AdventureFacet ADVENTURE_FACET_INSTANCE = null;
|
||||
|
||||
private AdventureUtil() {
|
||||
}
|
||||
|
||||
public static void setAdventureFacet(AdventureFacet adventureFacetInstance) {
|
||||
ADVENTURE_FACET_INSTANCE = adventureFacetInstance;
|
||||
}
|
||||
|
||||
public static AdventureFacet getAdventureFacet() {
|
||||
return ADVENTURE_FACET_INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link NamedTextColor} from its associated section sign char.
|
||||
*/
|
||||
public static NamedTextColor fromChar(final char c) {
|
||||
final int index = LOOKUP.indexOf(c);
|
||||
if (index == -1 || index > 15) {
|
||||
return null;
|
||||
}
|
||||
return COLORS[index];
|
||||
}
|
||||
|
||||
public static String fromCharName(final char c) {
|
||||
final NamedTextColor namedTextColor = fromChar(c);
|
||||
if (namedTextColor == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return namedTextColor.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for a translation message are not parsed for MiniMessage by default to avoid injection. If you want
|
||||
* a parameter to be parsed for MiniMessage you must wrap it in a ParsedPlaceholder by using this method.
|
||||
*/
|
||||
public static ParsedPlaceholder parsed(final String literal) {
|
||||
return new ParsedPlaceholder(literal);
|
||||
}
|
||||
|
||||
public static class ParsedPlaceholder {
|
||||
private final String value;
|
||||
|
||||
protected ParsedPlaceholder(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.earth2me.essentials.adventure;
|
||||
|
||||
import com.earth2me.essentials.Essentials;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import net.ess3.provider.AbstractChatEvent;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.flattener.ComponentFlattener;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class SpigotAdventureFacet implements AdventureFacet {
|
||||
private static final LegacyComponentSerializer LEGACY_SERIALIZER;
|
||||
private static final LegacyComponentSerializer LEGACY_SERIALIZER_URLS;
|
||||
private static final MiniMessage MINI_MESSAGE_NO_TAGS;
|
||||
|
||||
static {
|
||||
final LegacyComponentSerializer.Builder builder = LegacyComponentSerializer.builder()
|
||||
.flattener(ComponentFlattener.basic())
|
||||
.useUnusualXRepeatedCharacterHexFormat();
|
||||
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_16_1_R01)) {
|
||||
builder.hexColors();
|
||||
}
|
||||
LEGACY_SERIALIZER = builder.build();
|
||||
LEGACY_SERIALIZER_URLS = builder.extractUrls(AbstractChatEvent.URL_PATTERN).build();
|
||||
|
||||
MINI_MESSAGE_NO_TAGS = MiniMessage.builder().strict(true).build();
|
||||
}
|
||||
|
||||
private final Essentials ess;
|
||||
private final BukkitAudiences bukkitAudiences;
|
||||
private final MiniMessage miniMessageInstance;
|
||||
|
||||
public SpigotAdventureFacet(final Essentials ess) {
|
||||
this.ess = ess.getSettings() == null ? null : ess;
|
||||
bukkitAudiences = BukkitAudiences.create(ess);
|
||||
|
||||
miniMessageInstance = MiniMessage.builder()
|
||||
.tags(TagResolver.builder()
|
||||
.resolvers(TagResolver.standard())
|
||||
.resolver(TagResolver.resolver("primary", supplyTag(true)))
|
||||
.resolver(TagResolver.resolver("secondary", supplyTag(false)))
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
private Tag supplyTag(final boolean primary) {
|
||||
final String color = primary ? (ess != null ? ess.getSettings().getPrimaryColor() : "gold") : (ess != null ? ess.getSettings().getSecondaryColor() : "red");
|
||||
|
||||
final TextColor textColor;
|
||||
if (color.startsWith("#") && color.length() == 7 && NumberUtil.isHexadecimal(color.substring(1))) {
|
||||
textColor = TextColor.color(Color.fromRGB(Integer.decode(color)).asRGB());
|
||||
} else if (color.length() == 1) {
|
||||
textColor = AdventureUtil.fromChar(color.charAt(0));
|
||||
} else {
|
||||
textColor = NamedTextColor.NAMES.value(color.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
return ess != null && textColor != null ? Tag.styling(textColor) : Tag.styling(primary ? NamedTextColor.GOLD : NamedTextColor.RED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentHolder deserializeMiniMessage(String message) {
|
||||
return new ComponentHolder(miniMessageInstance.deserialize(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String legacyToMini(String message) {
|
||||
return legacyToMini(message, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(CommandSender sender, ComponentHolder component) {
|
||||
bukkitAudiences.sender(sender).sendMessage((Component) component.getComponent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Player player, ComponentHolder component) {
|
||||
bukkitAudiences.player(player).sendMessage((Component) component.getComponent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String adventureToLegacy(ComponentHolder component) {
|
||||
return adventureToLegacy((Component) component.getComponent());
|
||||
}
|
||||
|
||||
private String adventureToLegacy(Component component) {
|
||||
return LEGACY_SERIALIZER.serialize(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentHolder legacyToAdventure(String message) {
|
||||
return new ComponentHolder(LEGACY_SERIALIZER.deserialize(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentHolder text(String message) {
|
||||
return new ComponentHolder(Component.text(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String legacyToMini(String message, boolean useCustomTags) {
|
||||
final Component deserializedText = LEGACY_SERIALIZER.deserialize(message);
|
||||
if (useCustomTags) {
|
||||
return miniMessageInstance.serialize(deserializedText);
|
||||
} else {
|
||||
return MINI_MESSAGE_NO_TAGS.serialize(deserializedText);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String miniToLegacy(String message) {
|
||||
return adventureToLegacy(miniMessageInstance.deserialize(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stripTags(String input) {
|
||||
return miniMessageInstance.stripTags(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String legacyToMiniWithUrls(String message) {
|
||||
return miniMessageInstance.serialize(LEGACY_SERIALIZER_URLS.deserialize(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeTags(String input) {
|
||||
return miniMessageInstance.escapeTags(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentHolder append(ComponentHolder base, ComponentHolder... addition) {
|
||||
Component baseComponent = (Component) base.getComponent();
|
||||
for (ComponentHolder holder : addition) {
|
||||
final Component additionComponent = (Component) holder.getComponent();
|
||||
baseComponent = baseComponent.append(additionComponent);
|
||||
}
|
||||
return new ComponentHolder(baseComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
bukkitAudiences.close();
|
||||
}
|
||||
}
|
||||
@@ -323,7 +323,13 @@ public class Economy {
|
||||
throw new IllegalArgumentException("Economy user cannot be null");
|
||||
}
|
||||
final BigDecimal result = getMoneyExact(user).add(amount, MATH_CONTEXT);
|
||||
setMoney(user, result);
|
||||
// Deposits (positive amounts) always improve the balance, so minMoney and
|
||||
// loan checks don't apply — they exist to prevent the balance from dropping.
|
||||
if (amount.signum() <= 0) {
|
||||
setMoney(user, result);
|
||||
} else {
|
||||
user.setMoney(result, UserBalanceUpdateEvent.Cause.API);
|
||||
}
|
||||
Trade.log("API", "Add", "API", user.getName(), new Trade(amount, ess), null, null, null, result, ess);
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ public class Commandafk extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1 && sender.isAuthorized("essentials.afk.others")) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class Commandback extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
|
||||
if (user.isAuthorized("essentials.back.others") && args.length == 1) {
|
||||
return getPlayers(server, user);
|
||||
return getPlayers(user);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import org.bukkit.Server;
|
||||
|
||||
@@ -20,14 +20,14 @@ public class Commandbalance extends EssentialsCommand {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
|
||||
final User target = getPlayer(server, args, 0, false, true);
|
||||
final User target = getPlayer(server, args, 0, true, true);
|
||||
sender.sendTl("balanceOther", target.isHidden() ? target.getName() : target.getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(target.getMoney(), ess)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
if (args.length == 1 && user.isAuthorized("essentials.balance.others")) {
|
||||
final User target = getPlayer(server, args, 0, true, true);
|
||||
final User target = getPlayer(server, args, 0, false, true);
|
||||
user.sendTl("balanceOther", target.isHidden() ? target.getName() : target.getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(target.getMoney(), ess)));
|
||||
} else if (args.length < 2) {
|
||||
user.sendTl("balance", AdventureUtil.parsed(NumberUtil.displayCurrency(user.getMoney(), ess)));
|
||||
@@ -39,7 +39,7 @@ public class Commandbalance extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1 && sender.isAuthorized("essentials.balance.others")) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -4,9 +4,10 @@ import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.textreader.SimpleTextInput;
|
||||
import com.earth2me.essentials.textreader.TextPager;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.essentialsx.api.v2.services.BalanceTop;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -114,16 +115,21 @@ public class Commandbalancetop extends EssentialsCommand {
|
||||
future.thenRun(() -> {
|
||||
if (fresh) {
|
||||
final SimpleTextInput newCache = new SimpleTextInput();
|
||||
newCache.getLines().add(AdventureUtil.miniToLegacy(tlLiteral("serverTotal", AdventureUtil.parsed(NumberUtil.displayCurrency(ess.getBalanceTop().getBalanceTopTotal(), ess)))));
|
||||
newCache.getLines().add(ess.getAdventureFacet().miniToLegacy(tlLiteral("serverTotal", AdventureUtil.parsed(NumberUtil.displayCurrency(ess.getBalanceTop().getBalanceTopTotal(), ess)))));
|
||||
int pos = 1;
|
||||
for (final Map.Entry<UUID, BalanceTop.Entry> entry : ess.getBalanceTop().getBalanceTopCache().entrySet()) {
|
||||
final BigDecimal balance = entry.getValue().getBalance();
|
||||
final User user = ess.getUser(entry.getKey());
|
||||
|
||||
final Statistic PLAY_ONE_TICK = EnumUtil.getStatistic("PLAY_ONE_MINUTE", "PLAY_ONE_TICK");
|
||||
final boolean offlineStatisticSupported = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_15_2_R01);
|
||||
final long playtime;
|
||||
if (user.getBase() == null || !user.getBase().isOnline()) {
|
||||
playtime = Bukkit.getServer().getOfflinePlayer(entry.getKey()).getStatistic(PLAY_ONE_TICK);
|
||||
if (offlineStatisticSupported) {
|
||||
playtime = Bukkit.getServer().getOfflinePlayer(entry.getKey()).getStatistic(PLAY_ONE_TICK);
|
||||
} else {
|
||||
playtime = -1;
|
||||
}
|
||||
} else {
|
||||
playtime = user.getBase().getStatistic(PLAY_ONE_TICK);
|
||||
}
|
||||
@@ -133,8 +139,9 @@ public class Commandbalancetop extends EssentialsCommand {
|
||||
// Checking if player meets the requirements of minimum balance and minimum playtime to be listed in baltop list
|
||||
if ((ess.getSettings().showZeroBaltop() || balance.compareTo(BigDecimal.ZERO) > 0)
|
||||
&& balance.compareTo(ess.getSettings().getBaltopMinBalance()) >= 0 &&
|
||||
playTimeSecs >= ess.getSettings().getBaltopMinPlaytime()) {
|
||||
newCache.getLines().add(AdventureUtil.miniToLegacy(tlLiteral("balanceTopLine", pos, entry.getValue().getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(balance, ess)))));
|
||||
// Skip playtime check for offline players on versions below 1.15.2
|
||||
(playtime == -1 || playTimeSecs >= ess.getSettings().getBaltopMinPlaytime())) {
|
||||
newCache.getLines().add(ess.getAdventureFacet().miniToLegacy(tlLiteral("balanceTopLine", pos, entry.getValue().getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(balance, ess)))));
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.Console;
|
||||
import com.earth2me.essentials.OfflinePlayerStub;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import net.ess3.api.TranslatableException;
|
||||
import org.bukkit.BanList;
|
||||
@@ -43,7 +42,7 @@ public class Commandban extends EssentialsCommand {
|
||||
}
|
||||
|
||||
final String senderName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.NAME;
|
||||
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.DISPLAY_NAME;
|
||||
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.displayName();
|
||||
final String banReason;
|
||||
if (args.length > 1) {
|
||||
banReason = FormatUtil.replaceFormat(getFinalArg(args, 1).replace("\\n", "\n").replace("|", "\n"));
|
||||
@@ -55,8 +54,8 @@ public class Commandban extends EssentialsCommand {
|
||||
|
||||
final String banDisplay = tlLiteral("banFormat", banReason, senderDisplayName);
|
||||
|
||||
user.getBase().kickPlayer(AdventureUtil.miniToLegacy(banDisplay));
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("playerBanned", senderDisplayName, user.getName(), banDisplay)));
|
||||
user.getBase().kickPlayer(ess.getAdventureFacet().miniToLegacy(banDisplay));
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("playerBanned", senderDisplayName, user.getName(), banDisplay)));
|
||||
|
||||
if (nomatch) {
|
||||
sender.sendTl("userUnknown", user.getName());
|
||||
@@ -68,7 +67,7 @@ public class Commandban extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.Console;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import org.bukkit.BanList;
|
||||
import org.bukkit.Server;
|
||||
@@ -27,7 +26,7 @@ public class Commandbanip extends EssentialsCommand {
|
||||
}
|
||||
|
||||
final String senderName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.NAME;
|
||||
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.DISPLAY_NAME;
|
||||
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.displayName();
|
||||
|
||||
String ipAddress;
|
||||
if (FormatUtil.validIP(args[0])) {
|
||||
@@ -52,10 +51,10 @@ public class Commandbanip extends EssentialsCommand {
|
||||
banReason = tlLiteral("defaultBanReason");
|
||||
}
|
||||
|
||||
final String banDisplay = AdventureUtil.miniToLegacy(tlLiteral("banFormat", banReason, senderDisplayName));
|
||||
final String banDisplay = ess.getAdventureFacet().miniToLegacy(tlLiteral("banFormat", banReason, senderDisplayName));
|
||||
|
||||
ess.getServer().getBanList(BanList.Type.IP).addBan(ipAddress, banReason, null, senderName);
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("playerBanIpAddress", senderDisplayName, ipAddress, banReason)));
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("playerBanIpAddress", senderDisplayName, ipAddress, banReason)));
|
||||
|
||||
for (final Player player : ess.getServer().getOnlinePlayers()) {
|
||||
if (player.getAddress().getAddress().getHostAddress().equalsIgnoreCase(ipAddress)) {
|
||||
@@ -70,7 +69,7 @@ public class Commandbanip extends EssentialsCommand {
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
// TODO: Also list IP addresses?
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public class Commandbook extends EssentialsCommand {
|
||||
}
|
||||
return options;
|
||||
} else if (args.length == 2 && args[0].equalsIgnoreCase("author") && user.isAuthorized("essentials.book.author")) {
|
||||
final List<String> options = getPlayers(server, user);
|
||||
final List<String> options = getPlayers(user);
|
||||
options.add("Herobrine"); // #EasterEgg
|
||||
return options;
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import org.bukkit.Server;
|
||||
|
||||
@@ -15,6 +16,9 @@ public class Commandbroadcast extends EssentialsCommand {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
|
||||
ess.broadcastTl("broadcast", FormatUtil.replaceFormat(getFinalArg(args, 0)).replace("\\n", "\n"), sender.getDisplayName());
|
||||
final String message = FormatUtil.replaceFormat(getFinalArg(args, 0)).replace("\\n", "\n");
|
||||
ess.broadcastTl("broadcast",
|
||||
AdventureUtil.parsed(ess.getAdventureFacet().legacyToMiniWithUrls(ess.getAdventureFacet().escapeTags(message))),
|
||||
sender.getDisplayName());
|
||||
}
|
||||
}
|
||||
+6
-2
@@ -2,7 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.ess3.api.TranslatableException;
|
||||
@@ -54,7 +54,11 @@ public class Commandbroadcastworld extends EssentialsCommand {
|
||||
if (message.isEmpty()) {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
ess.broadcastTl(null, u -> !u.getBase().getWorld().equals(world), true, "broadcast", FormatUtil.replaceFormat(message).replace("\\n", "\n"), AdventureUtil.parsed(AdventureUtil.legacyToMini(name)));
|
||||
final String formatted = FormatUtil.replaceFormat(message).replace("\\n", "\n");
|
||||
ess.broadcastTl(null, u -> !u.getBase().getWorld().equals(world), true, "broadcast",
|
||||
AdventureUtil.parsed(
|
||||
ess.getAdventureFacet().legacyToMiniWithUrls(ess.getAdventureFacet().escapeTags(formatted))),
|
||||
AdventureUtil.parsed(ess.getAdventureFacet().legacyToMini(name)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,14 +19,18 @@ public class Commandburn extends EssentialsCommand {
|
||||
}
|
||||
|
||||
final User user = getPlayer(server, sender, args, 0);
|
||||
user.getBase().setFireTicks(Integer.parseInt(args[1]) * 20);
|
||||
sender.sendTl("burnMsg", user.getDisplayName(), Integer.parseInt(args[1]));
|
||||
final int seconds = Integer.parseInt(args[1]);
|
||||
|
||||
final int fireTicks = (int) Math.max(0L, Math.min((long) seconds * 20, Integer.MAX_VALUE));
|
||||
|
||||
user.getBase().setFireTicks(fireTicks);
|
||||
sender.sendTl("burnMsg", user.getDisplayName(), Math.max(0, seconds));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else if (args.length == 2) {
|
||||
return COMMON_DURATIONS;
|
||||
} else {
|
||||
|
||||
+5
-2
@@ -153,7 +153,7 @@ public class Commandclearinventory extends EssentialsCommand {
|
||||
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
|
||||
if (user.isAuthorized("essentials.clearinventory.others")) {
|
||||
if (args.length == 1) {
|
||||
final List<String> options = getPlayers(server, user);
|
||||
final List<String> options = getPlayers(user);
|
||||
if (user.isAuthorized("essentials.clearinventory.all") || user.isAuthorized("essentials.clearinventory.multiple")) {
|
||||
// Assume that nobody will have the 'all' permission without the 'others' permission
|
||||
options.add("*");
|
||||
@@ -182,7 +182,7 @@ public class Commandclearinventory extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
final List<String> options = getPlayers(server, sender);
|
||||
final List<String> options = getPlayers(sender);
|
||||
options.add("*");
|
||||
return options;
|
||||
} else if (args.length == 2) {
|
||||
@@ -196,6 +196,9 @@ public class Commandclearinventory extends EssentialsCommand {
|
||||
}
|
||||
|
||||
private String formatCommand(final String commandLabel, final String[] args) {
|
||||
if (args == null || args.length == 0) {
|
||||
return "/" + commandLabel;
|
||||
}
|
||||
return "/" + commandLabel + " " + StringUtil.joinList(" ", (Object[]) args);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,13 +51,14 @@ public class Commandcreatekit extends EssentialsCommand {
|
||||
useSerializationProvider = false;
|
||||
}
|
||||
|
||||
for (ItemStack is : items) {
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
final ItemStack is = items[i];
|
||||
if (is != null && is.getType() != null && is.getType() != Material.AIR) {
|
||||
final String serialized;
|
||||
if (useSerializationProvider) {
|
||||
serialized = "@" + Base64Coder.encodeLines(serializationProvider.serializeItem(is));
|
||||
serialized = "slot:" + i + " @" + Base64Coder.encodeLines(serializationProvider.serializeItem(is));
|
||||
} else {
|
||||
serialized = ess.getItemDb().serialize(is);
|
||||
serialized = "slot:" + i + " " + ess.getItemDb().serialize(is);
|
||||
}
|
||||
list.add(serialized);
|
||||
}
|
||||
|
||||
@@ -30,10 +30,10 @@ public class Commanddelhome extends EssentialsCommand {
|
||||
|
||||
try {
|
||||
user.delHome(home);
|
||||
sender.sendTl("deleteHome", home);
|
||||
} catch (Exception e) {
|
||||
sender.sendTl("invalidHome", home);
|
||||
}
|
||||
sender.sendTl("deleteHome", home);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,7 +87,7 @@ public class Commanddelhome extends EssentialsCommand {
|
||||
if (canDelOthers) {
|
||||
final int sepIndex = args[0].indexOf(':');
|
||||
if (sepIndex < 0) {
|
||||
getPlayers(server, sender).forEach(player -> homes.add(player + ":"));
|
||||
getPlayers(sender).forEach(player -> homes.add(player + ":"));
|
||||
} else {
|
||||
final String namePart = args[0].substring(0, sepIndex);
|
||||
final User otherUser;
|
||||
|
||||
@@ -12,7 +12,8 @@ public class Commanddisposal extends EssentialsCommand {
|
||||
@Override
|
||||
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
user.sendTl("openingDisposal");
|
||||
user.getBase().openInventory(ess.getServer().createInventory(user.getBase(), 36, user.playerTl("disposal")));
|
||||
final String title = ess.getAdventureFacet().miniToLegacy(user.playerTl("disposal"));
|
||||
user.getBase().openInventory(ess.getServer().createInventory(user.getBase(), 36, title));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,12 +3,13 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.ChargeException;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.ess3.api.MaxMoneyException;
|
||||
import net.ess3.api.TranslatableException;
|
||||
import net.ess3.api.events.UserBalanceUpdateEvent;
|
||||
import net.ess3.provider.PlayerLocaleProvider;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -34,7 +35,14 @@ public class Commandeco extends EssentialsLoopCommand {
|
||||
try {
|
||||
cmd = EcoCommands.valueOf(args[0].toUpperCase(Locale.ENGLISH));
|
||||
isPercent = cmd != EcoCommands.RESET && args[2].endsWith("%");
|
||||
amount = (cmd == EcoCommands.RESET) ? ess.getSettings().getStartingBalance() : new BigDecimal(args[2].replaceAll("[^0-9\\.]", ""));
|
||||
if (cmd == EcoCommands.RESET) {
|
||||
amount = ess.getSettings().getStartingBalance();
|
||||
} else if (sender.isPlayer() && ess.getSettings().isPerPlayerLocale()) {
|
||||
final String playerLocale = ess.provider(PlayerLocaleProvider.class).getLocale(sender.getPlayer());
|
||||
amount = NumberUtil.parseStringToBDecimal(args[2], ess.getUser(sender.getPlayer()).getPlayerLocale(playerLocale));
|
||||
} else {
|
||||
amount = NumberUtil.parseStringToBDecimal(args[2]);
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
throw new NotEnoughArgumentsException(ex);
|
||||
}
|
||||
@@ -87,7 +95,7 @@ public class Commandeco extends EssentialsLoopCommand {
|
||||
}
|
||||
return options;
|
||||
} else if (args.length == 2) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else if (args.length == 3 && !args[0].equalsIgnoreCase(EcoCommands.RESET.name())) {
|
||||
if (args[0].equalsIgnoreCase(EcoCommands.SET.name())) {
|
||||
return Lists.newArrayList("0", ess.getSettings().getStartingBalance().toString());
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.bukkit.block.data.type.HangingSign;
|
||||
import org.bukkit.block.data.type.WallHangingSign;
|
||||
import org.bukkit.block.data.type.WallSign;
|
||||
import org.bukkit.block.sign.Side;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@@ -49,7 +48,7 @@ public class Commandeditsign extends EssentialsCommand {
|
||||
throw new TranslatableException("editsignCommandLimit");
|
||||
}
|
||||
existingLines[line] = text;
|
||||
if (callSignEvent(sign, user.getBase(), existingLines)) {
|
||||
if (callSignEvent(sign, user, existingLines)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -61,7 +60,7 @@ public class Commandeditsign extends EssentialsCommand {
|
||||
existingLines[i] = "";
|
||||
}
|
||||
|
||||
if (callSignEvent(sign, user.getBase(), existingLines)) {
|
||||
if (callSignEvent(sign, user, existingLines)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -71,7 +70,7 @@ public class Commandeditsign extends EssentialsCommand {
|
||||
final int line = Integer.parseInt(args[1]) - 1;
|
||||
existingLines[line] = "";
|
||||
|
||||
if (callSignEvent(sign, user.getBase(), existingLines)) {
|
||||
if (callSignEvent(sign, user, existingLines)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -100,13 +99,17 @@ public class Commandeditsign extends EssentialsCommand {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
existingLines[i] = FormatUtil.formatString(user, "essentials.editsign", user.getSignCopy().get(i));
|
||||
}
|
||||
if (callSignEvent(sign, user, existingLines)) {
|
||||
return;
|
||||
}
|
||||
user.sendTl("editsignPaste", commandLabel);
|
||||
} else {
|
||||
existingLines[line] = FormatUtil.formatString(user, "essentials.editsign", user.getSignCopy().get(line));
|
||||
if (callSignEvent(sign, user, existingLines)) {
|
||||
return;
|
||||
}
|
||||
user.sendTl("editsignPasteLine", line + 1, commandLabel);
|
||||
}
|
||||
|
||||
callSignEvent(sign, user.getBase(), existingLines);
|
||||
} else {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
@@ -115,22 +118,22 @@ public class Commandeditsign extends EssentialsCommand {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean callSignEvent(final ModifiableSign sign, final Player player, final String[] lines) {
|
||||
private boolean callSignEvent(final ModifiableSign sign, final User user, final String[] lines) {
|
||||
final SignChangeEvent event;
|
||||
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_1_R01)) {
|
||||
if (sign.isWaxed() && !player.hasPermission("essentials.editsign.waxed.exempt")) {
|
||||
if (sign.isWaxed() && !user.isAuthorized("essentials.editsign.waxed.exempt")) {
|
||||
return true;
|
||||
}
|
||||
event = new SignChangeEvent(sign.getBlock(), player, lines, sign.isFront() ? Side.FRONT : Side.BACK);
|
||||
event = new SignChangeEvent(sign.getBlock(), user.getBase(), lines, sign.isFront() ? Side.FRONT : Side.BACK);
|
||||
} else {
|
||||
//noinspection deprecation
|
||||
event = new SignChangeEvent(sign.getBlock(), player, lines);
|
||||
event = new SignChangeEvent(sign.getBlock(), user.getBase(), lines);
|
||||
}
|
||||
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("SignChangeEvent canceled for /editsign execution by " + player.getName());
|
||||
ess.getLogger().info("SignChangeEvent canceled for /editsign execution by " + user.getName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class Commandenderchest extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1 && user.isAuthorized("essentials.enderchest.others")) {
|
||||
return getPlayers(server, user);
|
||||
return getPlayers(user);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -1,962 +1,31 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.EssentialsUpgrade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.economy.EconomyLayer;
|
||||
import com.earth2me.essentials.economy.EconomyLayers;
|
||||
import com.earth2me.essentials.userstorage.ModernUserMap;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.CommandMapUtil;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.FloatUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.PasteUtil;
|
||||
import com.earth2me.essentials.utils.RegistryUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import net.ess3.api.TranslatableException;
|
||||
import net.ess3.provider.KnownCommandsProvider;
|
||||
import net.ess3.provider.OnlineModeProvider;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tlLiteral;
|
||||
import com.earth2me.essentials.commands.essentials.CleanupCommand;
|
||||
import com.earth2me.essentials.commands.essentials.CommandMapCommand;
|
||||
import com.earth2me.essentials.commands.essentials.DebugCommand;
|
||||
import com.earth2me.essentials.commands.essentials.DumpCommand;
|
||||
import com.earth2me.essentials.commands.essentials.HomesCommand;
|
||||
import com.earth2me.essentials.commands.essentials.ItemTestCommand;
|
||||
import com.earth2me.essentials.commands.essentials.MooCommand;
|
||||
import com.earth2me.essentials.commands.essentials.NyanCommand;
|
||||
import com.earth2me.essentials.commands.essentials.ReloadCommand;
|
||||
import com.earth2me.essentials.commands.essentials.UsermapCommand;
|
||||
import com.earth2me.essentials.commands.essentials.VersionCommand;
|
||||
|
||||
// This command has 4 undocumented behaviours #EasterEgg
|
||||
public class Commandessentials extends EssentialsCommand {
|
||||
|
||||
private static final Sound NOTE_HARP = RegistryUtil.valueOf(Sound.class, "BLOCK_NOTE_BLOCK_HARP", "BLOCK_NOTE_HARP", "NOTE_PIANO");
|
||||
private static final Sound MOO_SOUND = RegistryUtil.valueOf(Sound.class, "COW_IDLE", "ENTITY_COW_MILK");
|
||||
|
||||
private static final String HOMES_USAGE = "/<command> homes (fix | delete [world])";
|
||||
|
||||
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?\"..."};
|
||||
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)
|
||||
"DiscordSRV", // potential for issues if EssentialsXDiscord is installed
|
||||
|
||||
// Chat signing bypass plugins that can potentially break EssentialsChat
|
||||
"AntiPopup",
|
||||
"NoChatReports",
|
||||
"NoEncryption"
|
||||
);
|
||||
private static final List<String> officialPlugins = Arrays.asList(
|
||||
"EssentialsAntiBuild",
|
||||
"EssentialsChat",
|
||||
"EssentialsDiscord",
|
||||
"EssentialsDiscordLink",
|
||||
"EssentialsGeoIP",
|
||||
"EssentialsProtect",
|
||||
"EssentialsSpawn",
|
||||
"EssentialsXMPP"
|
||||
);
|
||||
private static final List<String> warnPlugins = Arrays.asList(
|
||||
"PermissionsEx",
|
||||
"GroupManager",
|
||||
"bPermissions",
|
||||
|
||||
// Brain-dead chat signing bypass that break EssentialsChat
|
||||
"NoChatReports",
|
||||
"NoEncryption"
|
||||
);
|
||||
private transient TuneRunnable currentTune = null;
|
||||
|
||||
public class Commandessentials extends EssentialsTreeCommand {
|
||||
public Commandessentials() {
|
||||
super("essentials");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
|
||||
if (args.length == 0) {
|
||||
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;
|
||||
case "dump":
|
||||
runDump(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 "homes":
|
||||
runHomes(server, sender, commandLabel, args);
|
||||
break;
|
||||
case "usermap":
|
||||
runUserMap(sender, args);
|
||||
break;
|
||||
|
||||
case "itemtest":
|
||||
runItemTest(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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void runItemTest(Server server, CommandSource sender, String commandLabel, String[] args) {
|
||||
if (!sender.isAuthorized("essentials.itemtest") || args.length < 2 || !sender.isPlayer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Player player = sender.getPlayer();
|
||||
assert player != null;
|
||||
|
||||
switch (args[1]) {
|
||||
case "slot": {
|
||||
if (args.length < 3) {
|
||||
return;
|
||||
}
|
||||
player.getInventory().setItem(Integer.parseInt(args[2]), new ItemStack(Material.DIRT));
|
||||
break;
|
||||
}
|
||||
case "overfill": {
|
||||
sender.sendMessage(Inventories.addItem(player, 42, false, new ItemStack(Material.DIAMOND_SWORD, 1), new ItemStack(Material.DIRT, 32), new ItemStack(Material.DIRT, 32)).toString());
|
||||
break;
|
||||
}
|
||||
case "overfill2": {
|
||||
if (args.length < 4) {
|
||||
return;
|
||||
}
|
||||
final boolean armor = Boolean.parseBoolean(args[2]);
|
||||
final boolean add = Boolean.parseBoolean(args[3]);
|
||||
final ItemStack[] items = new ItemStack[]{new ItemStack(Material.DIAMOND_SWORD, 1), new ItemStack(Material.DIRT, 32), new ItemStack(Material.DIRT, 32), new ItemStack(Material.DIAMOND_HELMET, 4), new ItemStack(Material.CHAINMAIL_LEGGINGS, 1)};
|
||||
if (Inventories.hasSpace(player, 0, armor, items)) {
|
||||
if (add) {
|
||||
sender.sendMessage(Inventories.addItem(player, 0, armor, items).toString());
|
||||
}
|
||||
sender.sendMessage("SO MUCH SPACE!");
|
||||
} else {
|
||||
sender.sendMessage("No space!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "remove": {
|
||||
if (args.length < 3) {
|
||||
return;
|
||||
}
|
||||
Inventories.removeItemExact(player, new ItemStack(Material.PUMPKIN, 1), Boolean.parseBoolean(args[2]));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Displays the command's usage.
|
||||
private void showUsage(final CommandSource sender) throws Exception {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (ess.getAlternativeCommandsHandler().disabledCommands().size() == 0) {
|
||||
sender.sendTl("blockListEmpty");
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendTl("blockList");
|
||||
for (final Map.Entry<String, String> entry : ess.getAlternativeCommandsHandler().disabledCommands().entrySet()) {
|
||||
sender.sendMessage(entry.getKey() + " => " + entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// Generates a paste of useful information
|
||||
private void runDump(Server server, CommandSource sender, String commandLabel, String[] args) {
|
||||
sender.sendTl("dumpCreating");
|
||||
|
||||
final JsonObject dump = new JsonObject();
|
||||
|
||||
final JsonObject meta = new JsonObject();
|
||||
meta.addProperty("timestamp", Instant.now().toEpochMilli());
|
||||
meta.addProperty("sender", sender.getPlayer() != null ? sender.getPlayer().getName() : null);
|
||||
meta.addProperty("senderUuid", sender.getPlayer() != null ? sender.getPlayer().getUniqueId().toString() : null);
|
||||
dump.add("meta", meta);
|
||||
|
||||
final JsonObject serverData = new JsonObject();
|
||||
serverData.addProperty("bukkit-version", Bukkit.getBukkitVersion());
|
||||
serverData.addProperty("server-version", Bukkit.getVersion());
|
||||
serverData.addProperty("server-brand", Bukkit.getName());
|
||||
serverData.addProperty("online-mode", ess.provider(OnlineModeProvider.class).getOnlineModeString());
|
||||
final JsonObject supportStatus = new JsonObject();
|
||||
final VersionUtil.SupportStatus status = VersionUtil.getServerSupportStatus();
|
||||
supportStatus.addProperty("status", status.name());
|
||||
supportStatus.addProperty("supported", status.isSupported());
|
||||
supportStatus.addProperty("trigger", VersionUtil.getSupportStatusClass());
|
||||
serverData.add("support-status", supportStatus);
|
||||
dump.add("server-data", serverData);
|
||||
|
||||
final JsonObject environment = new JsonObject();
|
||||
environment.addProperty("java-version", System.getProperty("java.version"));
|
||||
environment.addProperty("operating-system", System.getProperty("os.name"));
|
||||
environment.addProperty("uptime", DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime()));
|
||||
environment.addProperty("allocated-memory", (Runtime.getRuntime().totalMemory() / 1024 / 1024) + "MB");
|
||||
dump.add("environment", environment);
|
||||
|
||||
final JsonObject essData = new JsonObject();
|
||||
essData.addProperty("version", ess.getDescription().getVersion());
|
||||
final JsonObject updateData = new JsonObject();
|
||||
updateData.addProperty("id", ess.getUpdateChecker().getVersionIdentifier());
|
||||
updateData.addProperty("branch", ess.getUpdateChecker().getVersionBranch());
|
||||
updateData.addProperty("dev", ess.getUpdateChecker().isDevBuild());
|
||||
essData.add("update-data", updateData);
|
||||
final JsonObject econLayer = new JsonObject();
|
||||
econLayer.addProperty("enabled", !ess.getSettings().isEcoDisabled());
|
||||
econLayer.addProperty("selected-layer", EconomyLayers.isLayerSelected());
|
||||
final EconomyLayer layer = EconomyLayers.getSelectedLayer();
|
||||
econLayer.addProperty("name", layer == null ? "null" : layer.getName());
|
||||
econLayer.addProperty("layer-version", layer == null ? "null" : layer.getPluginVersion());
|
||||
econLayer.addProperty("backend-name", layer == null ? "null" : layer.getBackendName());
|
||||
essData.add("economy-layer", econLayer);
|
||||
final JsonArray addons = new JsonArray();
|
||||
final JsonArray plugins = new JsonArray();
|
||||
final ArrayList<Plugin> alphabetical = new ArrayList<>();
|
||||
Collections.addAll(alphabetical, Bukkit.getPluginManager().getPlugins());
|
||||
alphabetical.sort(Comparator.comparing(o -> o.getName().toUpperCase(Locale.ENGLISH)));
|
||||
for (final Plugin plugin : alphabetical) {
|
||||
final JsonObject pluginData = new JsonObject();
|
||||
final PluginDescriptionFile info = plugin.getDescription();
|
||||
final String name = info.getName();
|
||||
|
||||
pluginData.addProperty("name", name);
|
||||
pluginData.addProperty("version", info.getVersion());
|
||||
pluginData.addProperty("description", info.getDescription());
|
||||
pluginData.addProperty("main", info.getMain());
|
||||
pluginData.addProperty("enabled", plugin.isEnabled());
|
||||
pluginData.addProperty("official", plugin == ess || officialPlugins.contains(name));
|
||||
pluginData.addProperty("unsupported", warnPlugins.contains(name));
|
||||
|
||||
final JsonArray authors = new JsonArray();
|
||||
for (final String author : info.getAuthors()) {
|
||||
authors.add(author == null ? JsonNull.INSTANCE : new JsonPrimitive(author));
|
||||
}
|
||||
pluginData.add("authors", authors);
|
||||
|
||||
if (name.startsWith("Essentials") && !name.equals("Essentials")) {
|
||||
addons.add(pluginData);
|
||||
}
|
||||
plugins.add(pluginData);
|
||||
}
|
||||
essData.add("addons", addons);
|
||||
dump.add("ess-data", essData);
|
||||
dump.add("plugins", plugins);
|
||||
|
||||
final List<PasteUtil.PasteFile> files = new ArrayList<>();
|
||||
files.add(new PasteUtil.PasteFile("dump.json", dump.toString()));
|
||||
|
||||
final Plugin essDiscord = Bukkit.getPluginManager().getPlugin("EssentialsDiscord");
|
||||
final Plugin essDiscordLink = Bukkit.getPluginManager().getPlugin("EssentialsDiscordLink");
|
||||
final Plugin essSpawn = Bukkit.getPluginManager().getPlugin("EssentialsSpawn");
|
||||
|
||||
final Map<String, Command> knownCommandsCopy = new HashMap<>(ess.provider(KnownCommandsProvider.class).getKnownCommands());
|
||||
final Map<String, String> disabledCommandsCopy = new HashMap<>(ess.getAlternativeCommandsHandler().disabledCommands());
|
||||
|
||||
// Further operations will be heavy IO
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
boolean config = false;
|
||||
boolean discord = false;
|
||||
boolean kits = false;
|
||||
boolean log = false;
|
||||
boolean worth = false;
|
||||
boolean tpr = false;
|
||||
boolean spawns = false;
|
||||
boolean commands = false;
|
||||
for (final String arg : args) {
|
||||
if (arg.equals("*") || arg.equalsIgnoreCase("all")) {
|
||||
config = true;
|
||||
discord = true;
|
||||
kits = true;
|
||||
log = true;
|
||||
worth = true;
|
||||
tpr = true;
|
||||
spawns = true;
|
||||
commands = true;
|
||||
break;
|
||||
} else if (arg.equalsIgnoreCase("config")) {
|
||||
config = true;
|
||||
} else if (arg.equalsIgnoreCase("discord")) {
|
||||
discord = true;
|
||||
} else if (arg.equalsIgnoreCase("kits")) {
|
||||
kits = true;
|
||||
} else if (arg.equalsIgnoreCase("log")) {
|
||||
log = true;
|
||||
} else if (arg.equalsIgnoreCase("worth")) {
|
||||
worth = true;
|
||||
} else if (arg.equalsIgnoreCase("tpr")) {
|
||||
tpr = true;
|
||||
} else if (arg.equalsIgnoreCase("spawns")) {
|
||||
spawns = true;
|
||||
} else if (arg.equalsIgnoreCase("commands")) {
|
||||
commands = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (config) {
|
||||
try {
|
||||
files.add(new PasteUtil.PasteFile("config.yml", new String(Files.readAllBytes(ess.getSettings().getConfigFile().toPath()), StandardCharsets.UTF_8)));
|
||||
} catch (IOException e) {
|
||||
sender.sendTl("dumpErrorUpload", "config.yml", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (discord && essDiscord != null) {
|
||||
try {
|
||||
files.add(new PasteUtil.PasteFile("discord-config.yml",
|
||||
new String(Files.readAllBytes(essDiscord.getDataFolder().toPath().resolve("config.yml")), StandardCharsets.UTF_8)
|
||||
.replaceAll("[A-Za-z\\d]{24}\\.[\\w-]{6}\\.[\\w-]{27}", "<censored token>")));
|
||||
} catch (IOException e) {
|
||||
sender.sendTl("dumpErrorUpload", "discord-config.yml", e.getMessage());
|
||||
}
|
||||
|
||||
if (essDiscordLink != null) {
|
||||
try {
|
||||
files.add(new PasteUtil.PasteFile("discord-link-config.yml",
|
||||
new String(Files.readAllBytes(essDiscordLink.getDataFolder().toPath().resolve("config.yml")), StandardCharsets.UTF_8)));
|
||||
} catch (IOException e) {
|
||||
sender.sendTl("dumpErrorUpload", "discord-link-config.yml", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kits) {
|
||||
try {
|
||||
files.add(new PasteUtil.PasteFile("kits.yml", new String(Files.readAllBytes(ess.getKits().getFile().toPath()), StandardCharsets.UTF_8)));
|
||||
} catch (IOException e) {
|
||||
sender.sendTl("dumpErrorUpload", "kits.yml", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (log) {
|
||||
try {
|
||||
files.add(new PasteUtil.PasteFile("latest.log", new String(Files.readAllBytes(Paths.get("logs", "latest.log")), StandardCharsets.UTF_8)
|
||||
.replaceAll("(?m)^\\[\\d\\d:\\d\\d:\\d\\d] \\[.+/(?:DEBUG|TRACE)]: .+\\s(?:[A-Za-z.]+:.+\\s(?:\\t.+\\s)*)?\\s*(?:\"[A-Za-z]+\" : .+[\\s}\\]]+)*", "")
|
||||
.replaceAll("(?:[0-9]{1,3}\\.){3}[0-9]{1,3}", "<censored ip address>")));
|
||||
} catch (IOException e) {
|
||||
sender.sendTl("dumpErrorUpload", "latest.log", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (worth) {
|
||||
try {
|
||||
files.add(new PasteUtil.PasteFile("worth.yml", new String(Files.readAllBytes(ess.getWorth().getFile().toPath()), StandardCharsets.UTF_8)));
|
||||
} catch (IOException e) {
|
||||
sender.sendTl("dumpErrorUpload", "worth.yml", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (tpr) {
|
||||
try {
|
||||
files.add(new PasteUtil.PasteFile("tpr.yml", new String(Files.readAllBytes(ess.getRandomTeleport().getFile().toPath()), StandardCharsets.UTF_8)));
|
||||
} catch (IOException e) {
|
||||
sender.sendTl("dumpErrorUpload", "tpr.yml", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (spawns && essSpawn != null) {
|
||||
try {
|
||||
files.add(new PasteUtil.PasteFile("spawn.yml", new String(Files.readAllBytes(ess.getDataFolder().toPath().resolve("spawn.yml")), StandardCharsets.UTF_8)));
|
||||
} catch (IOException e) {
|
||||
sender.sendTl("dumpErrorUpload", "spawn.yml", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (commands) {
|
||||
try {
|
||||
files.add(new PasteUtil.PasteFile("commands.yml", new String(Files.readAllBytes(Paths.get("commands.yml")), StandardCharsets.UTF_8)));
|
||||
files.add(new PasteUtil.PasteFile("commandmap.json", CommandMapUtil.toJsonPretty(ess, knownCommandsCopy)));
|
||||
files.add(new PasteUtil.PasteFile("commandoverride.json", disabledCommandsCopy.toString()));
|
||||
} catch (IOException e) {
|
||||
sender.sendTl("dumpErrorUpload", "commands.yml", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
final CompletableFuture<PasteUtil.PasteResult> future = PasteUtil.createPaste(files);
|
||||
future.thenAccept(result -> {
|
||||
if (result != null) {
|
||||
final String dumpUrl = "https://essentialsx.net/dump.html?bytebin=" + result.getPasteId();
|
||||
sender.sendTl("dumpUrl", dumpUrl);
|
||||
// pastes.dev doesn't support deletion keys
|
||||
//sender.sendTl("dumpDeleteKey", result.getDeletionKey());
|
||||
if (sender.isPlayer()) {
|
||||
ess.getLogger().info(AdventureUtil.miniToLegacy(tlLiteral("dumpConsoleUrl", dumpUrl)));
|
||||
// pastes.dev doesn't support deletion keys
|
||||
//ess.getLogger().info(AdventureUtil.miniToLegacy(tlLiteral("dumpDeleteKey", result.getDeletionKey())));
|
||||
}
|
||||
}
|
||||
files.clear();
|
||||
});
|
||||
future.exceptionally(throwable -> {
|
||||
sender.sendTl("dumpError", throwable.getMessage());
|
||||
return null;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 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>");
|
||||
}
|
||||
final User user = getPlayer(server, args, 1, true, true);
|
||||
user.reset();
|
||||
sender.sendMessage("Reset Essentials userdata for player: " + user.getDisplayName());
|
||||
}
|
||||
|
||||
// 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"));
|
||||
}
|
||||
|
||||
// Reloads all reloadable configs.
|
||||
private void runReload(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
|
||||
ess.reload();
|
||||
sender.sendTl("essentialsReload", ess.getDescription().getVersion());
|
||||
}
|
||||
|
||||
// Pop tarts.
|
||||
private void runNya(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
|
||||
if (currentTune != null) {
|
||||
currentTune.cancel();
|
||||
}
|
||||
|
||||
currentTune = new TuneRunnable(NYAN_TUNE, NOTE_HARP, ess::getOnlinePlayers);
|
||||
currentTune.runTaskTimer(ess, 20, 2);
|
||||
}
|
||||
|
||||
// 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 (final String s : CONSOLE_MOO) {
|
||||
ess.getLogger().info(s);
|
||||
}
|
||||
for (final Player player : ess.getOnlinePlayers()) {
|
||||
player.sendMessage(PLAYER_MOO);
|
||||
player.playSound(player.getLocation(), MOO_SOUND, 1, 1.0f);
|
||||
}
|
||||
} else {
|
||||
if (sender.isPlayer()) {
|
||||
sender.getSender().sendMessage(PLAYER_MOO);
|
||||
final Player player = sender.getPlayer();
|
||||
player.playSound(player.getLocation(), MOO_SOUND, 1, 1.0f);
|
||||
|
||||
} else {
|
||||
sender.getSender().sendMessage(CONSOLE_MOO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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.sendTl("cleaning");
|
||||
|
||||
final long daysArg = Long.parseLong(args[1]);
|
||||
final double moneyArg = args.length >= 3 ? FloatUtil.parseDouble(args[2].replaceAll("[^0-9.]", "")) : 0;
|
||||
final int homesArg = args.length >= 4 && NumberUtil.isInt(args[3]) ? Integer.parseInt(args[3]) : 0;
|
||||
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
final long currTime = System.currentTimeMillis();
|
||||
for (final UUID u : ess.getUsers().getAllUserUUIDs()) {
|
||||
final User user = ess.getUsers().loadUncachedUser(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;
|
||||
}
|
||||
|
||||
final long timeDiff = currTime - lastLog;
|
||||
final long milliDays = daysArg * 24L * 60L * 60L * 1000L;
|
||||
final int homeCount = user.getHomes().size();
|
||||
final 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.sendTl("cleaned");
|
||||
});
|
||||
}
|
||||
|
||||
private void runHomes(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage("This sub-command provides a utility to mass-delete homes based on user options:");
|
||||
sender.sendMessage("Use \"fix\" to delete all homes inside non-existent or unloaded worlds.");
|
||||
sender.sendMessage("Use \"delete\" to delete all existing homes.");
|
||||
sender.sendMessage("Use \"delete <worldname>\" to delete all homes inside a specific world.");
|
||||
throw new Exception(HOMES_USAGE);
|
||||
}
|
||||
|
||||
switch (args[1]) {
|
||||
case "fix":
|
||||
sender.sendTl("fixingHomes");
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
for (final UUID u : ess.getUsers().getAllUserUUIDs()) {
|
||||
final User user = ess.getUsers().loadUncachedUser(u);
|
||||
if (user == null) {
|
||||
continue;
|
||||
}
|
||||
for (String homeName : user.getHomes()) {
|
||||
try {
|
||||
if (user.getHome(homeName) == null) {
|
||||
user.delHome(homeName);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ess.getLogger().info("Unable to delete home " + homeName + " for " + user.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
sender.sendTl("fixedHomes");
|
||||
});
|
||||
break;
|
||||
case "delete":
|
||||
final boolean filterByWorld = args.length >= 3;
|
||||
if (filterByWorld && server.getWorld(args[2]) == null) {
|
||||
throw new TranslatableException("invalidWorld");
|
||||
}
|
||||
if (filterByWorld) {
|
||||
sender.sendTl("deletingHomesWorld", args[2]);
|
||||
} else {
|
||||
sender.sendTl("deletingHomes");
|
||||
}
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
for (final UUID u : ess.getUsers().getAllUserUUIDs()) {
|
||||
final User user = ess.getUsers().loadUncachedUser(u);
|
||||
if (user == null) {
|
||||
continue;
|
||||
}
|
||||
for (String homeName : user.getHomes()) {
|
||||
try {
|
||||
final Location home = user.getHome(homeName);
|
||||
if (!filterByWorld || (home != null && home.getWorld() != null && home.getWorld().getName().equals(args[2]))) {
|
||||
user.delHome(homeName);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ess.getLogger().info("Unable to delete home " + homeName + " for " + user.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (filterByWorld) {
|
||||
sender.sendTl("deletedHomesWorld", args[2]);
|
||||
} else {
|
||||
sender.sendTl("deletedHomes");
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new Exception(HOMES_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
// Gets information about cached users
|
||||
private void runUserMap(final CommandSource sender, final String[] args) {
|
||||
if (!sender.isAuthorized("essentials.usermap")) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ModernUserMap userMap = (ModernUserMap) ess.getUsers();
|
||||
sender.sendTl("usermapSize", userMap.getCachedCount(), userMap.getUserCount(), ess.getSettings().getMaxUserCacheCount());
|
||||
if (args.length > 1) {
|
||||
if (args[1].equals("full")) {
|
||||
for (final Map.Entry<String, UUID> entry : userMap.getNameCache().entrySet()) {
|
||||
sender.sendTl("usermapEntry", entry.getKey(), entry.getValue().toString());
|
||||
}
|
||||
} else if (args[1].equals("purge")) {
|
||||
final boolean seppuku = args.length > 2 && args[2].equals("iknowwhatimdoing");
|
||||
|
||||
sender.sendTl("usermapPurge", String.valueOf(seppuku));
|
||||
|
||||
final Set<UUID> uuids = new HashSet<>(ess.getUsers().getAllUserUUIDs());
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
final File userdataFolder = new File(ess.getDataFolder(), "userdata");
|
||||
final File backupFolder = new File(ess.getDataFolder(), "userdata-npc-backup-boogaloo-" + System.currentTimeMillis());
|
||||
|
||||
if (!userdataFolder.isDirectory()) {
|
||||
ess.getLogger().warning("Missing userdata folder, aborting usermap purge.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (seppuku && !backupFolder.mkdir()) {
|
||||
ess.getLogger().warning("Unable to create backup folder, aborting usermap purge.");
|
||||
return;
|
||||
}
|
||||
|
||||
int total = 0;
|
||||
final File[] files = userdataFolder.listFiles(EssentialsUpgrade.YML_FILTER);
|
||||
if (files != null) {
|
||||
for (final File file : files) {
|
||||
try {
|
||||
final String fileName = file.getName();
|
||||
final UUID uuid = UUID.fromString(fileName.substring(0, fileName.length() - 4));
|
||||
if (!uuids.contains(uuid)) {
|
||||
total++;
|
||||
ess.getLogger().warning("Found orphaned userdata file: " + file.getName());
|
||||
if (seppuku) {
|
||||
try {
|
||||
com.google.common.io.Files.move(file, new File(backupFolder, file.getName()));
|
||||
} catch (IOException e) {
|
||||
ess.getLogger().log(Level.WARNING, "Unable to move orphaned userdata file: " + file.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
ess.getLogger().info("Found " + total + " orphaned userdata files.");
|
||||
});
|
||||
} else if (args[1].equalsIgnoreCase("cache")) {
|
||||
sender.sendTl("usermapKnown", ess.getUsers().getAllUserUUIDs().size(), ess.getUsers().getNameCache().size());
|
||||
} else {
|
||||
try {
|
||||
final UUID uuid = UUID.fromString(args[1]);
|
||||
for (final Map.Entry<String, UUID> entry : userMap.getNameCache().entrySet()) {
|
||||
if (entry.getValue().equals(uuid)) {
|
||||
sender.sendTl("usermapEntry", entry.getKey(), args[1]);
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
final String sanitizedName = userMap.getSanitizedName(args[1]);
|
||||
sender.sendTl("usermapEntry", sanitizedName, userMap.getNameCache().get(sanitizedName).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 VersionUtil.SupportStatus supportStatus = VersionUtil.getServerSupportStatus();
|
||||
final PluginManager pm = server.getPluginManager();
|
||||
final String essVer = pm.getPlugin("Essentials").getDescription().getVersion();
|
||||
|
||||
final String serverMessageKey;
|
||||
if (supportStatus.isSupported()) {
|
||||
serverMessageKey = "versionOutputFine";
|
||||
} else if (supportStatus == VersionUtil.SupportStatus.UNSTABLE) {
|
||||
serverMessageKey = "versionOutputUnsupported";
|
||||
} else {
|
||||
serverMessageKey = "versionOutputWarn";
|
||||
}
|
||||
|
||||
sender.sendTl(serverMessageKey, "Server", server.getBukkitVersion() + " " + server.getVersion());
|
||||
sender.sendTl(serverMessageKey, "Brand", server.getName());
|
||||
sender.sendTl("versionOutputFine", "EssentialsX", essVer);
|
||||
|
||||
for (final Plugin plugin : pm.getPlugins()) {
|
||||
final PluginDescriptionFile desc = plugin.getDescription();
|
||||
String name = desc.getName();
|
||||
final String version = desc.getVersion();
|
||||
|
||||
if (name.startsWith("Essentials") && !name.equalsIgnoreCase("Essentials")) {
|
||||
if (officialPlugins.contains(name)) {
|
||||
name = name.replace("Essentials", "EssentialsX");
|
||||
|
||||
if (!version.equalsIgnoreCase(essVer)) {
|
||||
isMismatched = true;
|
||||
sender.sendTl("versionOutputWarn", name, version);
|
||||
} else {
|
||||
sender.sendTl("versionOutputFine", name, version);
|
||||
}
|
||||
} else {
|
||||
sender.sendTl("versionOutputUnsupported", name, version);
|
||||
isUnsupported = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (versionPlugins.contains(name)) {
|
||||
if (warnPlugins.contains(name)) {
|
||||
sender.sendTl("versionOutputUnsupported", name, version);
|
||||
isUnsupported = true;
|
||||
} else {
|
||||
sender.sendTl("versionOutputFine", name, version);
|
||||
}
|
||||
}
|
||||
|
||||
if (name.equals("Vault")) isVaultInstalled = true;
|
||||
}
|
||||
|
||||
final String layer;
|
||||
if (ess.getSettings().isEcoDisabled()) {
|
||||
layer = "Disabled";
|
||||
} else if (EconomyLayers.isLayerSelected()) {
|
||||
final EconomyLayer economyLayer = EconomyLayers.getSelectedLayer();
|
||||
layer = economyLayer.getName() + " (" + economyLayer.getBackendName() + ")";
|
||||
} else {
|
||||
layer = "None";
|
||||
}
|
||||
sender.sendTl("versionOutputEconLayer", layer);
|
||||
|
||||
if (isMismatched) {
|
||||
sender.sendTl("versionMismatchAll");
|
||||
}
|
||||
|
||||
if (!isVaultInstalled) {
|
||||
sender.sendTl("versionOutputVaultMissing");
|
||||
}
|
||||
|
||||
if (isUnsupported) {
|
||||
sender.sendTl("versionOutputUnsupportedPlugins");
|
||||
}
|
||||
|
||||
switch (supportStatus) {
|
||||
case NMS_CLEANROOM:
|
||||
sender.sendComponent(sender.tlComponent("serverUnsupportedCleanroom").color(NamedTextColor.DARK_RED));
|
||||
break;
|
||||
case DANGEROUS_FORK:
|
||||
sender.sendComponent(sender.tlComponent("serverUnsupportedDangerous").color(NamedTextColor.DARK_RED));
|
||||
break;
|
||||
case STUPID_PLUGIN:
|
||||
sender.sendComponent(sender.tlComponent("serverUnsupportedDumbPlugins").color(NamedTextColor.DARK_RED));
|
||||
break;
|
||||
case UNSTABLE:
|
||||
sender.sendComponent(sender.tlComponent("serverUnsupportedMods").color(NamedTextColor.DARK_RED));
|
||||
break;
|
||||
case OUTDATED:
|
||||
sender.sendComponent(sender.tlComponent("serverUnsupported").color(NamedTextColor.RED));
|
||||
break;
|
||||
case LIMITED:
|
||||
sender.sendComponent(sender.tlComponent("serverUnsupportedLimitedApi").color(NamedTextColor.RED));
|
||||
break;
|
||||
}
|
||||
if (VersionUtil.getSupportStatusClass() != null) {
|
||||
sender.sendComponent(sender.tlComponent("serverUnsupportedClass").color(NamedTextColor.RED));
|
||||
}
|
||||
|
||||
sender.sendTl("versionFetching");
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
for (final Component component : ess.getUpdateChecker().getVersionMessages(true, true, sender)) {
|
||||
sender.sendComponent(component);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
final List<String> options = Lists.newArrayList();
|
||||
options.add("reload");
|
||||
options.add("version");
|
||||
options.add("dump");
|
||||
options.add("commands");
|
||||
options.add("debug");
|
||||
options.add("reset");
|
||||
options.add("cleanup");
|
||||
options.add("homes");
|
||||
//options.add("uuidconvert");
|
||||
//options.add("nya");
|
||||
//options.add("moo");
|
||||
return options;
|
||||
}
|
||||
|
||||
switch (args[0]) {
|
||||
case "moo":
|
||||
if (args.length == 2) {
|
||||
return Lists.newArrayList("moo");
|
||||
}
|
||||
break;
|
||||
case "reset":
|
||||
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 "homes":
|
||||
if (args.length == 2) {
|
||||
return Lists.newArrayList("fix", "delete");
|
||||
} else if (args.length == 3 && args[1].equalsIgnoreCase("delete")) {
|
||||
return server.getWorlds().stream().map(World::getName).collect(Collectors.toList());
|
||||
}
|
||||
break;
|
||||
case "dump":
|
||||
final List<String> list = Lists.newArrayList("config", "kits", "log", "discord", "worth", "tpr", "spawns", "commands", "all");
|
||||
for (String arg : args) {
|
||||
if (arg.equals("*") || arg.equalsIgnoreCase("all")) {
|
||||
list.clear();
|
||||
return list;
|
||||
}
|
||||
list.remove(arg.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
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 (final Player onlinePlayer : players.get()) {
|
||||
onlinePlayer.playSound(onlinePlayer.getLocation(), sound, 1, noteMap.get(note));
|
||||
}
|
||||
}
|
||||
registerNode(new VersionCommand());
|
||||
registerNode(new DebugCommand());
|
||||
registerNode(new CommandMapCommand());
|
||||
registerNode(new DumpCommand());
|
||||
registerNode(new ReloadCommand());
|
||||
registerNode(new CleanupCommand());
|
||||
registerNode(new HomesCommand());
|
||||
registerNode(new UsermapCommand());
|
||||
registerNode(new ItemTestCommand());
|
||||
registerNode(new NyanCommand());
|
||||
registerNode(new MooCommand());
|
||||
}
|
||||
}
|
||||
@@ -147,15 +147,21 @@ public class Commandexp extends EssentialsLoopCommand {
|
||||
}
|
||||
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")) || (args[0].equalsIgnoreCase("take") && user.isAuthorized("essentials.exp.take"))) {
|
||||
final ExpCommands cmd;
|
||||
try {
|
||||
cmd = ExpCommands.valueOf(args[0].toUpperCase(Locale.ENGLISH));
|
||||
} catch (final IllegalArgumentException e) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (cmd.hasOtherPermission(user)) {
|
||||
return getPlayers(user);
|
||||
}
|
||||
if (cmd.hasPermission(user) && cmd != ExpCommands.SHOW && cmd != ExpCommands.RESET) {
|
||||
final String levellessArg = args[1].toLowerCase(Locale.ENGLISH).replaceAll("l", "");
|
||||
if (NumberUtil.isInt(levellessArg)) {
|
||||
return Lists.newArrayList(levellessArg + "l");
|
||||
}
|
||||
}
|
||||
if (user.isAuthorized("essentials.exp.others")) {
|
||||
return getPlayers(server, user);
|
||||
}
|
||||
} else if (args.length == 3 && !(args[0].equalsIgnoreCase("show") || args[0].equalsIgnoreCase("reset"))) {
|
||||
final String levellessArg = args[2].toLowerCase(Locale.ENGLISH).replaceAll("l", "");
|
||||
if (NumberUtil.isInt(levellessArg)) {
|
||||
@@ -182,10 +188,10 @@ public class Commandexp extends EssentialsLoopCommand {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
} else { // even without 'show'
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
}
|
||||
} else if (args.length == 3 && (args[0].equalsIgnoreCase("set") || args[0].equalsIgnoreCase("give"))) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class Commandext extends EssentialsLoopCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class Commandfeed extends EssentialsLoopCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1 && sender.isAuthorized("essentials.feed.others")) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ public class Commandfly extends EssentialsToggleCommand {
|
||||
user.getBase().setFallDistance(0f);
|
||||
user.getBase().setAllowFlight(enabled);
|
||||
|
||||
user.setFlyModeEnabled(enabled);
|
||||
|
||||
if (!user.getBase().getAllowFlight()) {
|
||||
user.getBase().setFlying(false);
|
||||
}
|
||||
|
||||
@@ -105,12 +105,12 @@ public class Commandgamemode extends EssentialsLoopCommand {
|
||||
try {
|
||||
// Direct command? Don't ask for the mode
|
||||
matchGameMode(commandLabel);
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} catch (final NotEnoughArgumentsException e) {
|
||||
return STANDARD_OPTIONS;
|
||||
}
|
||||
} else if (args.length == 2) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -128,12 +128,12 @@ public class Commandgamemode extends EssentialsLoopCommand {
|
||||
}
|
||||
if (args.length == 1) {
|
||||
if (user.isAuthorized("essentials.gamemode.others") && isDirectGamemodeCommand) {
|
||||
return getPlayers(server, user);
|
||||
return getPlayers(user);
|
||||
} else {
|
||||
return STANDARD_OPTIONS;
|
||||
}
|
||||
} else if (args.length == 2 && user.isAuthorized("essentials.gamemode.others") && !isDirectGamemodeCommand) {
|
||||
return getPlayers(server, user);
|
||||
return getPlayers(user);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import net.ess3.provider.TileEntityProvider;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Server;
|
||||
@@ -36,6 +37,7 @@ public class Commandgc extends EssentialsCommand {
|
||||
sender.sendTl("gcfree", Runtime.getRuntime().freeMemory() / 1024 / 1024);
|
||||
|
||||
final List<World> worlds = server.getWorlds();
|
||||
final TileEntityProvider tileEntityProvider = ess.provider(TileEntityProvider.class);
|
||||
for (final World w : worlds) {
|
||||
String worldType = "World";
|
||||
switch (w.getEnvironment()) {
|
||||
@@ -51,7 +53,7 @@ public class Commandgc extends EssentialsCommand {
|
||||
|
||||
try {
|
||||
for (final Chunk chunk : w.getLoadedChunks()) {
|
||||
tileEntities += chunk.getTileEntities().length;
|
||||
tileEntities += tileEntityProvider.getTileEntities(chunk).length;
|
||||
}
|
||||
} catch (final java.lang.ClassCastException ex) {
|
||||
ess.getLogger().log(Level.SEVERE, "Corrupted chunk data on world " + w, ex);
|
||||
|
||||
@@ -47,7 +47,7 @@ public class Commandgetpos extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1 && sender.isAuthorized("essentials.getpos.others")) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ public class Commandgive extends EssentialsLoopCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else if (args.length == 2) {
|
||||
return getItems();
|
||||
} else if (args.length == 3) {
|
||||
|
||||
@@ -63,13 +63,16 @@ public class Commandheal extends EssentialsLoopCommand {
|
||||
player.setHealth(newAmount);
|
||||
player.setFoodLevel(20);
|
||||
player.setFireTicks(0);
|
||||
player.setRemainingAir(player.getMaximumAir());
|
||||
user.sendTl("heal");
|
||||
if (ess.getSettings().isRemovingEffectsOnHeal()) {
|
||||
for (final PotionEffect effect : player.getActivePotionEffects()) {
|
||||
player.removePotionEffect(effect.getType());
|
||||
}
|
||||
}
|
||||
sender.sendTl("healOther", user.getDisplayName());
|
||||
if (!sender.isPlayer() || !user.getBase().equals(sender.getPlayer())) {
|
||||
sender.sendTl("healOther", user.getDisplayName());
|
||||
}
|
||||
} catch (final QuietAbortException e) {
|
||||
//Handle Quietly
|
||||
}
|
||||
@@ -78,7 +81,7 @@ public class Commandheal extends EssentialsLoopCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1 && sender.isAuthorized("essentials.heal.others")) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.earth2me.essentials.textreader.IText;
|
||||
import com.earth2me.essentials.textreader.KeywordReplacer;
|
||||
import com.earth2me.essentials.textreader.TextInput;
|
||||
import com.earth2me.essentials.textreader.TextPager;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import net.ess3.provider.KnownCommandsProvider;
|
||||
import org.bukkit.Server;
|
||||
@@ -54,7 +54,7 @@ public class Commandhelp extends EssentialsCommand {
|
||||
user.sendTl("commandHelpLine3");
|
||||
if (essCommand != null && !essCommand.getUsageStrings().isEmpty()) {
|
||||
for (Map.Entry<String, String> usage : essCommand.getUsageStrings().entrySet()) {
|
||||
user.sendTl("commandHelpLineUsage", AdventureUtil.parsed(usage.getKey().replace("<command>", cmd)), AdventureUtil.parsed(usage.getValue()));
|
||||
user.sendTl("commandHelpLineUsage", AdventureUtil.parsed(usage.getKey().replace("<command>", cmd)), AdventureUtil.parsed(user.playerTl(usage.getValue())));
|
||||
}
|
||||
} else {
|
||||
user.sendMessage(bukkit.getUsage());
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.Console;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.messaging.IMessageRecipient;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import net.ess3.api.IUser;
|
||||
import net.essentialsx.api.v2.events.HelpopMessageSendEvent;
|
||||
@@ -39,11 +38,11 @@ public class Commandhelpop extends EssentialsCommand {
|
||||
}
|
||||
|
||||
final String message = FormatUtil.stripFormat(getFinalArg(args, 0));
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral("helpOp", from.getDisplayName(), message)));
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("helpOp", from.getDisplayName(), message)));
|
||||
|
||||
final List<IUser> recipients = new ArrayList<>();
|
||||
for (IUser user : ess.getOnlineUsers()) {
|
||||
if (user.getBase().hasPermission("essentials.helpop.receive")) {
|
||||
if (user.isAuthorized("essentials.helpop.receive")) {
|
||||
recipients.add(user);
|
||||
}
|
||||
}
|
||||
@@ -51,9 +50,11 @@ public class Commandhelpop extends EssentialsCommand {
|
||||
final HelpopMessageSendEvent sendEvent = new HelpopMessageSendEvent(from, recipients, message);
|
||||
ess.getServer().getPluginManager().callEvent(sendEvent);
|
||||
|
||||
final IUser sender = (IUser) from;
|
||||
if(!recipients.contains(sender)){
|
||||
from.sendTl("helpOp", from.getDisplayName(), message);
|
||||
if (from instanceof IUser) {
|
||||
final IUser sender = (IUser) from;
|
||||
if (!recipients.contains(sender)) {
|
||||
from.sendTl("helpOp", from.getDisplayName(), message);
|
||||
}
|
||||
}
|
||||
|
||||
for (IUser recipient : sendEvent.getRecipients()) {
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.OfflinePlayerStub;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.ess3.api.TranslatableException;
|
||||
@@ -41,7 +41,10 @@ public class Commandhome extends EssentialsCommand {
|
||||
}
|
||||
}
|
||||
try {
|
||||
if ("bed".equalsIgnoreCase(homeName) && user.isAuthorized("essentials.home.bed")) {
|
||||
if ("bed".equalsIgnoreCase(homeName)) {
|
||||
if (!user.isAuthorized("essentials.home.bed")) {
|
||||
throw new TranslatableException("noAccessCommand");
|
||||
}
|
||||
if (!player.getBase().isOnline() || player.getBase() instanceof OfflinePlayerStub) {
|
||||
throw new TranslatableException("bedOffline");
|
||||
}
|
||||
@@ -73,10 +76,15 @@ public class Commandhome extends EssentialsCommand {
|
||||
final List<String> homes = finalPlayer.getHomes();
|
||||
if (homes.isEmpty() && finalPlayer.equals(user)) {
|
||||
if (ess.getSettings().isSpawnIfNoHome()) {
|
||||
final UserTeleportHomeEvent event = new UserTeleportHomeEvent(user, null, bed != null ? bed : finalPlayer.getWorld().getSpawnLocation(), bed != null ? UserTeleportHomeEvent.HomeType.BED : UserTeleportHomeEvent.HomeType.SPAWN);
|
||||
final boolean useBed = bed != null && user.isAuthorized("essentials.home.bed");
|
||||
final UserTeleportHomeEvent event = new UserTeleportHomeEvent(user, null, useBed ? bed : finalPlayer.getWorld().getSpawnLocation(), useBed ? UserTeleportHomeEvent.HomeType.BED : UserTeleportHomeEvent.HomeType.SPAWN);
|
||||
server.getPluginManager().callEvent(event);
|
||||
if (!event.isCancelled()) {
|
||||
user.getAsyncTeleport().respawn(charge, TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
if (useBed) {
|
||||
user.getAsyncTeleport().respawn(charge, TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
} else {
|
||||
user.getAsyncTeleport().teleport(finalPlayer.getWorld().getSpawnLocation(), charge, TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
showError(user.getBase(), new TranslatableException("noHomeSetPlayer"), commandLabel);
|
||||
@@ -155,7 +163,7 @@ public class Commandhome extends EssentialsCommand {
|
||||
if (canVisitOthers) {
|
||||
final int sepIndex = args[0].indexOf(':');
|
||||
if (sepIndex < 0) {
|
||||
getPlayers(server, user).forEach(player -> homes.add(player + ":"));
|
||||
getPlayers(user).forEach(player -> homes.add(player + ":"));
|
||||
} else {
|
||||
final String namePart = args[0].substring(0, sepIndex);
|
||||
final User otherUser;
|
||||
|
||||
@@ -49,7 +49,7 @@ public class Commandice extends EssentialsLoopCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(Server server, CommandSource sender, String commandLabel, String[] args) {
|
||||
if (args.length == 1 && sender.isAuthorized("essentials.ice.others")) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -27,15 +27,7 @@ public class Commandignore extends EssentialsCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
User player;
|
||||
try {
|
||||
player = getPlayer(server, args, 0, true, true);
|
||||
} catch (final PlayerNotFoundException ex) {
|
||||
player = ess.getOfflineUser(args[0]);
|
||||
}
|
||||
if (player == null) {
|
||||
throw new PlayerNotFoundException();
|
||||
}
|
||||
final User player = getPlayer(server, args, 0, false, true);
|
||||
|
||||
if (player.isIgnoreExempt()) {
|
||||
user.sendTl("ignoreExempt");
|
||||
@@ -53,7 +45,7 @@ public class Commandignore extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, user);
|
||||
return getPlayers(user);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class Commandinvsee extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
final List<String> suggestions = getPlayers(server, user);
|
||||
final List<String> suggestions = getPlayers(user);
|
||||
suggestions.remove(user.getName());
|
||||
return suggestions;
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Commandjailedplayers extends EssentialsCommand {
|
||||
public Commandjailedplayers() {
|
||||
super("jailedplayers");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
|
||||
if (ess.getJailedPlayers() != null && !ess.getJailedPlayers().isEmpty()) {
|
||||
sender.sendTl("jailedPlayersList", StringUtil.joinList(", ", ess.getJailedPlayers().stream().map(Player::getName).collect(Collectors.toList())));
|
||||
} else {
|
||||
sender.sendTl("jailedPlayersEmpty");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.Console;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import net.ess3.api.TranslatableException;
|
||||
import net.essentialsx.api.v2.events.UserKickEvent;
|
||||
@@ -39,7 +38,7 @@ public class Commandkick extends EssentialsCommand {
|
||||
}
|
||||
}
|
||||
|
||||
String kickReason = args.length > 1 ? getFinalArg(args, 1) : AdventureUtil.miniToLegacy(tlLiteral("kickDefault"));
|
||||
String kickReason = args.length > 1 ? getFinalArg(args, 1) : ess.getAdventureFacet().miniToLegacy(tlLiteral("kickDefault"));
|
||||
kickReason = FormatUtil.replaceFormat(kickReason.replace("\\n", "\n").replace("|", "\n"));
|
||||
|
||||
final UserKickEvent event = new UserKickEvent(user, target, kickReason);
|
||||
@@ -51,18 +50,18 @@ public class Commandkick extends EssentialsCommand {
|
||||
|
||||
kickReason = event.getReason();
|
||||
target.getBase().kickPlayer(kickReason);
|
||||
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.DISPLAY_NAME;
|
||||
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.displayName();
|
||||
|
||||
final String tlKey = "playerKicked";
|
||||
final Object[] objects = {senderDisplayName, target.getName(), kickReason};
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral(tlKey, objects)));
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral(tlKey, objects)));
|
||||
ess.broadcastTl(null, "essentials.kick.notify", tlKey, objects);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -15,7 +14,7 @@ public class Commandkickall extends EssentialsCommand {
|
||||
|
||||
@Override
|
||||
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
|
||||
String kickReason = args.length > 0 ? getFinalArg(args, 0) : AdventureUtil.miniToLegacy(tlLiteral("kickDefault"));
|
||||
String kickReason = args.length > 0 ? getFinalArg(args, 0) : ess.getAdventureFacet().miniToLegacy(tlLiteral("kickDefault"));
|
||||
kickReason = FormatUtil.replaceFormat(kickReason.replace("\\n", "\n").replace("|", "\n"));
|
||||
|
||||
for (final Player onlinePlayer : ess.getOnlinePlayers()) {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class Commandkill extends EssentialsLoopCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.Kit;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import net.ess3.api.TranslatableException;
|
||||
import org.bukkit.Server;
|
||||
@@ -108,7 +108,7 @@ public class Commandkit extends EssentialsCommand {
|
||||
}
|
||||
return options;
|
||||
} else if (args.length == 2 && user.isAuthorized("essentials.kit.others")) {
|
||||
return getPlayers(server, user);
|
||||
return getPlayers(user);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -119,7 +119,7 @@ public class Commandkit extends EssentialsCommand {
|
||||
if (args.length == 1) {
|
||||
return new ArrayList<>(ess.getKits().getKitKeys()); // TODO: Move this to its own method
|
||||
} else if (args.length == 2) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public class Commandkitreset extends EssentialsCommand {
|
||||
if (args.length == 1) {
|
||||
return new ArrayList<>(ess.getKits().getKitKeys());
|
||||
} else if (args.length == 2 && sender.isAuthorized("essentials.kitreset.others")) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class Commandlightning extends EssentialsLoopCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else if (args.length == 2) {
|
||||
return Lists.newArrayList("5");
|
||||
} else {
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.PlayerList;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -24,11 +23,11 @@ public class Commandlist extends EssentialsCommand {
|
||||
user = ess.getUser(sender.getPlayer());
|
||||
showHidden = user.isAuthorized("essentials.list.hidden") || user.canInteractVanished();
|
||||
}
|
||||
sender.sendComponent(AdventureUtil.miniMessage().deserialize(PlayerList.listSummary(ess, user, showHidden)));
|
||||
sender.sendComponent(ess.getAdventureFacet().deserializeMiniMessage(PlayerList.listSummary(ess, user, showHidden)));
|
||||
final Map<String, List<User>> playerList = PlayerList.getPlayerLists(ess, user, showHidden);
|
||||
|
||||
if (args.length > 0) {
|
||||
sender.sendComponent(AdventureUtil.miniMessage().deserialize(PlayerList.listGroupUsers(ess, playerList, args[0].toLowerCase())));
|
||||
sender.sendComponent(ess.getAdventureFacet().deserializeMiniMessage(PlayerList.listGroupUsers(ess, playerList, args[0].toLowerCase())));
|
||||
} else {
|
||||
sendGroupedList(sender, commandLabel, playerList);
|
||||
}
|
||||
@@ -37,7 +36,7 @@ public class Commandlist extends EssentialsCommand {
|
||||
// Output the standard /list output, when no group is specified
|
||||
private void sendGroupedList(final CommandSource sender, final String commandLabel, final Map<String, List<User>> playerList) {
|
||||
for (final String str : PlayerList.prepareGroupedList(ess, sender, commandLabel, playerList)) {
|
||||
sender.sendComponent(AdventureUtil.miniMessage().deserialize(str));
|
||||
sender.sendComponent(ess.getAdventureFacet().deserializeMiniMessage(str));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -334,7 +334,7 @@ public class Commandmail extends EssentialsCommand {
|
||||
return options;
|
||||
} else if (args.length == 2) {
|
||||
if ((args[0].equalsIgnoreCase("send") && user.isAuthorized("essentials.mail.send")) || (args[0].equalsIgnoreCase("sendtemp") && user.isAuthorized("essentials.mail.sendtemp")) || ((args[0].equalsIgnoreCase("clear"))&& user.isAuthorized("essentials.mail.clear.others"))) {
|
||||
return getPlayers(server, user);
|
||||
return getPlayers(user);
|
||||
} else if (args[0].equalsIgnoreCase("sendtempall") && user.isAuthorized("essentials.mail.sendtempall")) {
|
||||
return COMMON_DATE_DIFFS;
|
||||
} else if (args[0].equalsIgnoreCase("read")) {
|
||||
@@ -374,7 +374,7 @@ public class Commandmail extends EssentialsCommand {
|
||||
return Lists.newArrayList("send", "sendall", "sendtemp", "sendtempall", "clearall", "clear");
|
||||
} else if (args.length == 2) {
|
||||
if (args[0].equalsIgnoreCase("send") || args[0].equalsIgnoreCase("sendtemp") || args[0].equalsIgnoreCase("clear")) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else if (args[0].equalsIgnoreCase("sendtempall")) {
|
||||
return COMMON_DATE_DIFFS;
|
||||
}
|
||||
|
||||
@@ -36,11 +36,13 @@ public class Commandmore extends EssentialsCommand {
|
||||
if (!NumberUtil.isPositiveInt(args[0])) {
|
||||
throw new TranslatableException("nonZeroPosNumber");
|
||||
}
|
||||
newStackSize += Integer.parseInt(args[0]);
|
||||
|
||||
if (newStackSize > (canOversized ? ess.getSettings().getOversizedStackSize() : stack.getMaxStackSize())) {
|
||||
user.sendTl(canOversized ? "fullStackDefaultOversize" : "fullStackDefault", canOversized ? ess.getSettings().getOversizedStackSize() : stack.getMaxStackSize());
|
||||
newStackSize = canOversized ? ess.getSettings().getOversizedStackSize() : stack.getMaxStackSize();
|
||||
final int cap = canOversized ? ess.getSettings().getOversizedStackSize() : stack.getMaxStackSize();
|
||||
final long newSizeLong = (long) stack.getAmount() + Integer.parseInt(args[0]);
|
||||
if (newSizeLong > cap) {
|
||||
user.sendTl(canOversized ? "fullStackDefaultOversize" : "fullStackDefault", cap);
|
||||
newStackSize = cap;
|
||||
} else {
|
||||
newStackSize = (int) newSizeLong;
|
||||
}
|
||||
} else if (canOversized) {
|
||||
newStackSize = ess.getSettings().getOversizedStackSize();
|
||||
|
||||
@@ -4,9 +4,7 @@ import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.Console;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.messaging.IMessageRecipient;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import net.ess3.api.TranslatableException;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -27,20 +25,15 @@ public class Commandmsg extends EssentialsLoopCommand {
|
||||
final boolean canWildcard = sender.isAuthorized("essentials.msg.multiple");
|
||||
if (sender.isPlayer()) {
|
||||
final User user = ess.getUser(sender.getPlayer());
|
||||
if (user.isMuted()) {
|
||||
final String dateDiff = user.getMuteTimeout() > 0 ? DateUtil.formatDateDiff(user.getMuteTimeout()) : null;
|
||||
if (dateDiff == null) {
|
||||
throw new TranslatableException(user.hasMuteReason() ? "voiceSilencedReason" : "voiceSilenced", user.getMuteReason());
|
||||
}
|
||||
throw new TranslatableException(user.hasMuteReason() ? "voiceSilencedReasonTime" : "voiceSilencedTime", dateDiff, user.getMuteReason());
|
||||
}
|
||||
// Muted players are handled in SimpleMessageRecipient#sendMessage so that the message can still
|
||||
// be shown to social spies before being dropped instead of being delivered to the recipient.
|
||||
message = FormatUtil.formatMessage(user, "essentials.msg", message);
|
||||
} else {
|
||||
message = FormatUtil.replaceFormat(message);
|
||||
}
|
||||
|
||||
// Sending messages to console
|
||||
if (args[0].equalsIgnoreCase(Console.NAME) || args[0].equalsIgnoreCase(Console.DISPLAY_NAME)) {
|
||||
if (args[0].equalsIgnoreCase(Console.NAME) || args[0].equalsIgnoreCase(Console.displayName())) {
|
||||
final IMessageRecipient messageSender = sender.isPlayer() ? ess.getUser(sender.getPlayer()) : Console.getInstance();
|
||||
messageSender.sendMessage(Console.getInstance(), message);
|
||||
return;
|
||||
@@ -58,7 +51,7 @@ public class Commandmsg extends EssentialsLoopCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList(); // It's a chat message, send an empty list.
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.OfflinePlayerStub;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import net.ess3.api.TranslatableException;
|
||||
import net.ess3.api.events.MuteStatusChangeEvent;
|
||||
@@ -22,6 +21,7 @@ public class Commandmute extends EssentialsCommand {
|
||||
|
||||
@Override
|
||||
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
|
||||
final boolean isUnmute = commandLabel.toLowerCase(java.util.Locale.ENGLISH).contains("unmute");
|
||||
boolean nomatch = false;
|
||||
if (args.length < 1) {
|
||||
throw new NotEnoughArgumentsException();
|
||||
@@ -33,11 +33,17 @@ public class Commandmute extends EssentialsCommand {
|
||||
nomatch = true;
|
||||
user = ess.getUser(new OfflinePlayerStub(args[0], ess.getServer()));
|
||||
}
|
||||
|
||||
if (isUnmute && !user.getMuted()) {
|
||||
sender.sendTl("playerNotMuted", user.getDisplayName());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!user.getBase().isOnline() && sender.isPlayer()) {
|
||||
if (!sender.isAuthorized("essentials.mute.offline")) {
|
||||
throw new TranslatableException("muteExemptOffline");
|
||||
}
|
||||
} else if (user.isAuthorized("essentials.mute.exempt")) {
|
||||
} else if (!isUnmute && user.isAuthorized("essentials.mute.exempt")) {
|
||||
throw new TranslatableException("muteExempt");
|
||||
}
|
||||
|
||||
@@ -45,7 +51,7 @@ public class Commandmute extends EssentialsCommand {
|
||||
final String time;
|
||||
String muteReason = null;
|
||||
|
||||
if (args.length > 1) {
|
||||
if (!isUnmute && args.length > 1) {
|
||||
time = args[1];
|
||||
try {
|
||||
muteTimestamp = DateUtil.parseDateDiff(time, true);
|
||||
@@ -60,7 +66,7 @@ public class Commandmute extends EssentialsCommand {
|
||||
}
|
||||
}
|
||||
|
||||
final boolean willMute = (args.length > 1) || !user.getMuted();
|
||||
final boolean willMute = !isUnmute && ((args.length > 1) || !user.getMuted());
|
||||
final User controller = sender.isPlayer() ? ess.getUser(sender.getPlayer()) : null;
|
||||
final MuteStatusChangeEvent event = new MuteStatusChangeEvent(user, controller, willMute, muteTimestamp, muteReason);
|
||||
ess.getServer().getPluginManager().callEvent(event);
|
||||
@@ -117,11 +123,13 @@ public class Commandmute extends EssentialsCommand {
|
||||
objects = new Object[]{sender.getSender().getName(), user.getName(), muteTime};
|
||||
}
|
||||
|
||||
ess.getLogger().log(Level.INFO, AdventureUtil.miniToLegacy(tlLiteral(tlKey, objects)));
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral(tlKey, objects)));
|
||||
ess.broadcastTl(null, "essentials.mute.notify", tlKey, objects);
|
||||
} else {
|
||||
sender.sendTl("unmutedPlayer", user.getDisplayName());
|
||||
user.sendTl("playerUnmuted");
|
||||
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("unmuteNotify", sender.getSender().getName(), user.getName())));
|
||||
ess.broadcastTl(null, "essentials.mute.notify", "unmuteNotify", new Object[]{sender.getSender().getName(), user.getName()});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,7 +137,7 @@ public class Commandmute extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return COMMON_DATE_DIFFS; // Date diff can span multiple words
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
@@ -117,7 +117,7 @@ public class Commandnear extends EssentialsCommand {
|
||||
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
|
||||
if (user.isAuthorized("essentials.near.others")) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, user);
|
||||
return getPlayers(user);
|
||||
} else if (args.length == 2) {
|
||||
return Lists.newArrayList(Integer.toString(ess.getSettings().getNearRadius()));
|
||||
} else {
|
||||
@@ -135,7 +135,7 @@ public class Commandnear extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else if (args.length == 2) {
|
||||
return Lists.newArrayList(Integer.toString(ess.getSettings().getNearRadius()));
|
||||
} else {
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import net.ess3.api.TranslatableException;
|
||||
import net.ess3.api.events.NickChangeEvent;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -49,7 +48,8 @@ public class Commandnick extends EssentialsLoopCommand {
|
||||
target.sendTl("nickNoMore");
|
||||
} else if (target.getName().equalsIgnoreCase(nick)) {
|
||||
setNickname(server, sender, target, nick);
|
||||
if (!target.getDisplayName().equalsIgnoreCase(target.getDisplayName())) {
|
||||
final String strippedDisplay = FormatUtil.stripFormat(target.getDisplayName());
|
||||
if (strippedDisplay != null && !strippedDisplay.equalsIgnoreCase(target.getName())) {
|
||||
target.sendTl("nickNoMore");
|
||||
}
|
||||
target.sendTl("nickSet", ess.getSettings().changeDisplayName() ? target.getDisplayName() : nick);
|
||||
@@ -63,7 +63,7 @@ public class Commandnick extends EssentialsLoopCommand {
|
||||
|
||||
private String formatNickname(final User user, final String nick) throws Exception {
|
||||
final String newNick = user == null ? FormatUtil.replaceFormat(nick) : FormatUtil.formatString(user, "essentials.nick", nick);
|
||||
if (!newNick.matches("^[a-zA-Z_0-9" + ChatColor.COLOR_CHAR + "]+$") && user != null && !user.isAuthorized("essentials.nick.allowunsafe")) {
|
||||
if (!newNick.matches(ess.getSettings().getNickRegex()) && user != null && !user.isAuthorized("essentials.nick.allowunsafe")) {
|
||||
throw new TranslatableException("nickNamesAlpha");
|
||||
} else if (getNickLength(newNick) > ess.getSettings().getMaxNickLength()) {
|
||||
throw new TranslatableException("nickTooLong");
|
||||
@@ -87,7 +87,10 @@ public class Commandnick extends EssentialsLoopCommand {
|
||||
}
|
||||
|
||||
private int getNickLength(final String nick) {
|
||||
return ess.getSettings().ignoreColorsInMaxLength() ? ChatColor.stripColor(nick).length() : nick.length();
|
||||
if (ess.getSettings().ignoreColorsInMaxLength()) {
|
||||
return FormatUtil.stripFormat(nick).length();
|
||||
}
|
||||
return FormatUtil.unformatString(nick).length();
|
||||
}
|
||||
|
||||
private boolean nickInUse(final User target, final String nick) {
|
||||
@@ -118,7 +121,7 @@ public class Commandnick extends EssentialsLoopCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1 && sender.isAuthorized("essentials.nick.others")) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public class Commandnuke extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -109,7 +109,7 @@ public class Commandpay extends EssentialsLoopCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else if (args.length == 2) {
|
||||
return Lists.newArrayList(ess.getSettings().getMinimumPayAmount().toString());
|
||||
} else {
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
@@ -28,7 +28,7 @@ public class Commandplaytime extends EssentialsCommand {
|
||||
String displayName;
|
||||
long playtime;
|
||||
final String key;
|
||||
|
||||
|
||||
if (args.length > 0 && sender.isAuthorized("essentials.playtime.others")) {
|
||||
try {
|
||||
final IUser user = getPlayer(server, sender, args, 0);
|
||||
@@ -57,16 +57,16 @@ public class Commandplaytime extends EssentialsCommand {
|
||||
}
|
||||
|
||||
final long playtimeMs = System.currentTimeMillis() - (playtime * 50L);
|
||||
sender.sendTl(key, DateUtil.formatDateDiff(playtimeMs), AdventureUtil.parsed(AdventureUtil.legacyToMini(displayName)));
|
||||
sender.sendTl(key, DateUtil.formatDateDiff(playtimeMs), AdventureUtil.parsed(ess.getAdventureFacet().legacyToMini(displayName)));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1 && sender.isAuthorized("essentials.playtime.others")) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class Commandpotion extends EssentialsCommand {
|
||||
|
||||
boolean holdingPotion = stack.getType() == Material.POTION;
|
||||
if (!holdingPotion && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01)) {
|
||||
holdingPotion = stack.getType() == Material.SPLASH_POTION || stack.getType() == Material.LINGERING_POTION;
|
||||
holdingPotion = stack.getType() == Material.SPLASH_POTION || stack.getType() == Material.LINGERING_POTION || stack.getType() == Material.TIPPED_ARROW;
|
||||
}
|
||||
if (holdingPotion) {
|
||||
PotionMeta pmeta = (PotionMeta) stack.getItemMeta();
|
||||
@@ -75,7 +75,7 @@ public class Commandpotion extends EssentialsCommand {
|
||||
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
|
||||
// Note: this enforces an order of effect power duration splash, which the actual command doesn't have. But that's fine.
|
||||
// Note: this enforces an order of effect power duration splash, which the actual command doesn't have. But that's fine.
|
||||
if (args.length == 1) {
|
||||
final List<String> options = Lists.newArrayList();
|
||||
options.add("clear");
|
||||
|
||||
@@ -129,7 +129,7 @@ public class Commandpowertool extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else if (args.length == 2) {
|
||||
return getItems();
|
||||
} else if (args.length == 3) {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class Commandpowertoollist extends EssentialsCommand {
|
||||
public Commandpowertoollist() {
|
||||
super("powertoollist");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
if (!user.hasPowerTools()) {
|
||||
user.sendTl("noPowerTools");
|
||||
return;
|
||||
}
|
||||
final Map<String, List<String>> powertools = user.getAllPowertools();
|
||||
for (Map.Entry<String, List<String>> entry : powertools.entrySet()) {
|
||||
final String itemName = entry.getKey().toLowerCase(Locale.ENGLISH).replaceAll("_", " ");
|
||||
final List<String> commands = entry.getValue();
|
||||
user.sendTl("powerToolList", StringUtil.joinList(commands), itemName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.IUser;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.AdventureUtil;
|
||||
import com.earth2me.essentials.adventure.AdventureUtil;
|
||||
import com.earth2me.essentials.utils.DescParseTickFormat;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.bukkit.Server;
|
||||
@@ -122,7 +122,7 @@ public class Commandptime extends EssentialsLoopCommand {
|
||||
if (args.length == 1) {
|
||||
return Lists.newArrayList("get", "reset", "sunrise", "day", "morning", "noon", "afternoon", "sunset", "night", "midnight");
|
||||
} else if (args.length == 2 && (getAliases.contains(args[0]) || user == null || user.isAuthorized("essentials.ptime.others"))) {
|
||||
return getPlayers(server, sender);
|
||||
return getPlayers(sender);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Loaded 100 of 335 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user