Compare commits

..
566 changed files with 37521 additions and 56590 deletions

No files matched your search

-270
View File
@@ -1,270 +0,0 @@
---
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`.
+6 -10
View File
@@ -1,7 +1,6 @@
name: Report bug
description: Report a bug in EssentialsX.
labels: 'bug: unconfirmed'
type: Bug
body:
- type: markdown
attributes:
@@ -32,8 +31,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://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"
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"
- type: textarea
attributes:
@@ -71,13 +70,10 @@ body:
validations:
required: true
- type: textarea
- type: markdown
attributes:
label: Additional Information
description: |
In this box, you can attach any relevant screenshots, files and links to Timings/spark profiler reports.
value: |
In the text box below, you can attach any relevant screenshots, files and links to Timings/spark profiler reports.
You can also include a link to a heapdump if necessary, but please make sure you don't include any private player data in the heapdump.
If you suspect this issue is related to a prior issue/PR/commit, please mention it here.
validations:
required: false
@@ -1,7 +1,6 @@
name: Request a feature
description: Suggest a feature you want to see in EssentialsX!
labels: 'type: enhancement'
type: Feature
body:
- type: markdown
attributes:
+1 -1
View File
@@ -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 (XX.YY.Z, git-Paper-BUILD)
- [ ] Most recent Paper version (1.XX.Y, git-Paper-BUILD)
- [ ] CraftBukkit/Spigot/Paper 1.12.2
- [ ] CraftBukkit 1.8.8
+1 -1
View File
@@ -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 (XX.YY.Z, git-Paper-BUILD)
- [ ] Most recent Paper version (1.XX.Y, git-Paper-BUILD)
- [ ] CraftBukkit/Spigot/Paper 1.12.2
- [ ] CraftBukkit 1.8.8
+20 -75
View File
@@ -5,9 +5,6 @@ on:
branches:
- 2.x
- dev/*
release:
types:
- published
jobs:
build:
@@ -16,90 +13,38 @@ jobs:
steps:
- name: Checkout Git repo
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up JDK 25
uses: actions/setup-java@v4
- name: Restore Gradle cache
uses: actions/cache@v2
with:
distribution: 'temurin'
java-version: 25
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Set up JDK 16
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: 16
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Build with Gradle
run: |
chmod +x gradlew
./gradlew build --stacktrace
- name: Publish JUnit report
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@v7
uses: actions/upload-artifact@master
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:
@@ -121,7 +66,7 @@ jobs:
cp -r EssentialsXMPP/build/docs/javadoc/ javadocs/EssentialsXMPP/
- name: Archive Javadocs
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@master
with:
name: javadocs
path: javadocs/
@@ -134,12 +79,12 @@ jobs:
steps:
- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
node-version: 22
node-version: 16
- name: Download Javadocs
uses: actions/download-artifact@v8
uses: actions/download-artifact@master
with:
name: javadocs
path: javadocs/
+16 -73
View File
@@ -10,11 +10,6 @@ on:
- 2.x
- mc/*
- dev/*
merge_group:
types: [checks_requested]
permissions:
checks: write
jobs:
build:
@@ -23,86 +18,34 @@ jobs:
steps:
- name: Checkout Git repo
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up JDK 25
uses: actions/setup-java@v4
- name: Restore Gradle cache
uses: actions/cache@v2
with:
distribution: 'temurin'
java-version: 25
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Set up JDK 16
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: 16
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Build with Gradle
run: |
chmod +x gradlew
./gradlew build --stacktrace
- name: Publish JUnit report
uses: mikepenz/action-junit-report@v4
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@v7
uses: actions/upload-artifact@master
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
-112
View File
@@ -1,112 +0,0 @@
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}`);
}
-43
View File
@@ -1,43 +0,0 @@
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: ./
-5
View File
@@ -21,15 +21,10 @@
# Build files
.gradle/
/jars/
generated/
out/
build/
target/
*.class
build-logic/.kotlin/
build-logic/bin/
bin/
test-tmp/
# Run directory
/run/
+2 -2
View File
@@ -11,8 +11,8 @@
</option>
<option name="locations">
<list>
<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="bundled-sun-checks" type="BUNDLED" scope="All" description="Sun Checks">(bundled)</ConfigurationLocation>
<ConfigurationLocation id="bundled-google-checks" type="BUNDLED" scope="All" description="Google Checks">(bundled)</ConfigurationLocation>
<ConfigurationLocation id="321e5753-4201-4d2c-bf31-6232011122fd" type="PROJECT_RELATIVE" scope="All" description="EssentialsX">
$PROJECT_DIR$/.checkstyle/checkstyle.xml
<option name="properties">
+11 -55
View File
@@ -3,36 +3,29 @@ plugins {
}
dependencies {
compileOnly('net.essentialsx.deps:VaultAPI:1.7') {
compileOnly('com.github.milkbowl:VaultAPI:1.7') {
exclude group: "org.bukkit", module: "bukkit"
}
compileOnly 'net.luckperms:api:5.3'
compileOnly 'net.luckperms:api:5.0'
api 'io.papermc:paperlib:1.0.6'
implementation 'org.spongepowered:configurate-yaml:4.2.0'
implementation 'org.checkerframework:checker-qual:3.49.0'
implementation 'nu.studer:java-ordered-properties:1.0.4'
api 'org.bstats:bstats-bukkit:2.2.1'
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'
implementation 'org.spongepowered:configurate-yaml:4.1.2'
implementation 'org.checkerframework:checker-qual:3.14.0'
// Providers
api(project(':providers:BaseProviders')) {
exclude(module: 'spigot-api')
}
api(project(path: ':providers:PaperProvider', configuration: 'shadow')){
exclude(module: 'paper-api')
}
api project(':providers:BaseProviders')
api project(':providers:PaperProvider')
api(project(':providers:NMSReflectionProvider')) {
exclude(module: 'bukkit')
exclude group: "org.bukkit", module: "bukkit"
}
api(project(':providers:1_8Provider')) {
exclude(module: 'spigot-api')
exclude group: "org.spigotmc", module: "spigot"
}
api(project(':providers:1_12Provider')) {
exclude(module: 'bukkit')
exclude group: "org.bukkit", module: "bukkit"
}
}
@@ -40,10 +33,6 @@ 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'))
@@ -54,39 +43,11 @@ shadowJar {
include (dependency('org.yaml:snakeyaml'))
include (dependency('io.leangen.geantyref:geantyref'))
include (dependency('org.checkerframework:checker-qual'))
include (dependency('nu.studer:java-ordered-properties'))
include (dependency('net.kyori:adventure-api'))
include (dependency('net.kyori:adventure-key'))
include (dependency('net.kyori:examination-api'))
include (dependency('net.kyori:examination-string'))
include (dependency('net.kyori:option'))
include (dependency('net.kyori:adventure-platform-bukkit'))
include (dependency('net.kyori:adventure-platform-api'))
include (dependency('net.kyori:adventure-platform-facet'))
include (dependency('net.kyori:adventure-nbt'))
include (dependency('net.kyori:adventure-text-serializer-bungeecord'))
include (dependency('net.kyori:adventure-text-serializer-gson'))
include (dependency('net.kyori:adventure-text-serializer-gson-legacy-impl'))
include (dependency('net.kyori:adventure-text-serializer-json'))
include (dependency('net.kyori:adventure-text-serializer-json-legacy-impl'))
include (dependency('net.kyori:adventure-text-serializer-legacy'))
include (dependency('net.kyori:adventure-text-minimessage'))
include (project(':providers:BaseProviders'))
include (project(path: ':providers:PaperProvider', configuration: 'shadow'))
include (project(':providers:PaperProvider'))
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'
@@ -94,13 +55,8 @@ shadowJar {
relocate 'org.yaml.snakeyaml', 'com.earth2me.essentials.libs.snakeyaml'
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' // Undo temporary relocation for Paper Provider
minimize {
include(dependency('org.checkerframework:checker-qual'))
include(dependency('net.kyori:adventure-api'))
include(dependency('net.kyori:adventure-platform-bukkit'))
include(dependency('net.kyori:adventure-text-minimessage'))
}
}
@@ -1,12 +1,9 @@
package com.earth2me.essentials;
import java.util.stream.Collectors;
import net.ess3.provider.KnownCommandsProvider;
import org.bukkit.command.Command;
import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.plugin.Plugin;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -16,7 +13,7 @@ import java.util.Map;
import java.util.logging.Level;
public class AlternativeCommandsHandler {
private final transient Map<String, List<WeakReference<Command>>> altCommands = new HashMap<>();
private final transient Map<String, List<Command>> altcommands = new HashMap<>();
private final transient Map<String, String> disabledList = new HashMap<>();
private final transient IEssentials ess;
@@ -33,72 +30,41 @@ public class AlternativeCommandsHandler {
if (plugin.getDescription().getMain().contains("com.earth2me.essentials") || plugin.getDescription().getMain().contains("net.essentialsx")) {
return;
}
for (final Map.Entry<String, Command> entry : getPluginCommands(plugin)) {
for (final Map.Entry<String, Command> entry : getPluginCommands(plugin).entrySet()) {
final String[] commandSplit = entry.getKey().split(":", 2);
final String commandName = commandSplit.length > 1 ? commandSplit[1] : entry.getKey();
final Command command = entry.getValue();
final List<WeakReference<Command>> pluginCommands = altCommands.computeIfAbsent(commandName.toLowerCase(Locale.ENGLISH), k -> new ArrayList<>());
final List<Command> pluginCommands = altcommands.computeIfAbsent(commandName.toLowerCase(Locale.ENGLISH), k -> new ArrayList<>());
boolean found = false;
final Iterator<WeakReference<Command>> pluginCmdIterator = pluginCommands.iterator();
while (pluginCmdIterator.hasNext()) {
final Command cmd = pluginCmdIterator.next().get();
if (cmd == null) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "Essentials: Alternative command for " + commandName + " removed due to garbage collection");
}
pluginCmdIterator.remove();
continue;
}
for (final Command pc2 : pluginCommands) {
// Safe cast, everything that's added comes from getPluginCommands which already performs the cast check.
if (((PluginIdentifiableCommand) cmd).getPlugin().equals(plugin)) {
if (((PluginIdentifiableCommand) pc2).getPlugin().equals(plugin)) {
found = true;
break;
}
}
if (!found) {
pluginCommands.add(new WeakReference<>(command));
pluginCommands.add(command);
}
}
}
private List<Map.Entry<String, Command>> getPluginCommands(Plugin plugin) {
private Map<String, Command> getPluginCommands(Plugin plugin) {
final Map<String, Command> commands = new HashMap<>();
for (final Map.Entry<String, Command> entry : ess.provider(KnownCommandsProvider.class).getKnownCommands().entrySet()) {
for (final Map.Entry<String, Command> entry : ess.getKnownCommandsProvider().getKnownCommands().entrySet()) {
if (entry.getValue() instanceof PluginIdentifiableCommand && ((PluginIdentifiableCommand) entry.getValue()).getPlugin().equals(plugin)) {
commands.put(entry.getKey(), entry.getValue());
}
}
// Try to use non-namespaced commands first if we can, some Commands may not like being registered under a
// different label than their getName() returns, so avoid doing that when we can
return commands.entrySet().stream().sorted((o1, o2) -> {
if (o1.getKey().contains(":") && !o2.getKey().contains(":")) {
return 1;
} else if (!o1.getKey().contains(":") && o2.getKey().contains(":")) {
return -1;
}
return 0;
}).collect(Collectors.toList());
return commands;
}
public void removePlugin(final Plugin plugin) {
final Iterator<Map.Entry<String, List<WeakReference<Command>>>> iterator = altCommands.entrySet().iterator();
final Iterator<Map.Entry<String, List<Command>>> iterator = altcommands.entrySet().iterator();
while (iterator.hasNext()) {
final Map.Entry<String, List<WeakReference<Command>>> entry = iterator.next();
final Iterator<WeakReference<Command>> commands = entry.getValue().iterator();
while (commands.hasNext()) {
final Command pc = commands.next().get();
if (pc instanceof PluginIdentifiableCommand && !((PluginIdentifiableCommand) pc).getPlugin().equals(plugin)) {
continue;
}
commands.remove();
}
final Map.Entry<String, List<Command>> entry = iterator.next();
entry.getValue().removeIf(pc -> !(pc instanceof PluginIdentifiableCommand) || ((PluginIdentifiableCommand) pc).getPlugin().equals(plugin));
if (entry.getValue().isEmpty()) {
iterator.remove();
}
@@ -106,37 +72,21 @@ public class AlternativeCommandsHandler {
}
public Command getAlternative(final String label) {
final List<WeakReference<Command>> commands = altCommands.get(label);
final List<Command> commands = altcommands.get(label);
if (commands == null || commands.isEmpty()) {
return null;
}
if (commands.size() == 1) {
return commands.get(0).get();
return commands.get(0);
}
// 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();
if (cmd == null) {
iterator.remove();
continue;
}
if (cmd.getName().equalsIgnoreCase(label)) {
return cmd;
}
if (firstAlias == null) {
firstAlias = cmd;
for (final Command command : commands) {
if (command.getName().equalsIgnoreCase(label)) {
return command;
}
}
// return the first alias, or null if every reference in this bucket has been collected
return firstAlias;
// return the first alias
return commands.get(0);
}
public void executed(final String label, final Command pc) {
@@ -7,7 +7,7 @@ import com.earth2me.essentials.utils.LocationUtil;
import io.papermc.lib.PaperLib;
import net.ess3.api.IEssentials;
import net.ess3.api.IUser;
import net.ess3.api.TranslatableException;
import net.ess3.api.InvalidWorldException;
import net.ess3.api.events.UserWarpEvent;
import net.ess3.api.events.teleport.PreTeleportEvent;
import net.ess3.api.events.teleport.TeleportWarmupEvent;
@@ -23,6 +23,8 @@ import java.util.GregorianCalendar;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import static com.earth2me.essentials.I18n.tl;
public class AsyncTeleport implements IAsyncTeleport {
private final IUser teleportOwner;
private final IEssentials ess;
@@ -71,7 +73,7 @@ public class AsyncTeleport implements IAsyncTeleport {
time.setTimeInMillis(lastTime);
time.add(Calendar.SECOND, (int) cooldown);
time.add(Calendar.MILLISECOND, (int) ((cooldown * 1000.0) % 1000.0));
future.completeExceptionally(new TranslatableException("timeBeforeTeleport", DateUtil.formatDateDiff(time.getTimeInMillis())));
future.completeExceptionally(new Exception(tl("timeBeforeTeleport", DateUtil.formatDateDiff(time.getTimeInMillis()))));
return true;
}
}
@@ -105,7 +107,7 @@ public class AsyncTeleport implements IAsyncTeleport {
final Calendar c = new GregorianCalendar();
c.add(Calendar.SECOND, (int) delay);
c.add(Calendar.MILLISECOND, (int) ((delay * 1000.0) % 1000.0));
user.sendTl("dontMoveMessage", DateUtil.formatDateDiff(c.getTimeInMillis()));
user.sendMessage(tl("dontMoveMessage", DateUtil.formatDateDiff(c.getTimeInMillis())));
}
@Override
@@ -127,7 +129,7 @@ public class AsyncTeleport implements IAsyncTeleport {
nowAsync(teleportOwner, target, cause, future);
future.thenAccept(success -> {
if (success) {
teleportOwner.sendTl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ());
teleportOwner.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
}
});
}
@@ -164,7 +166,7 @@ public class AsyncTeleport implements IAsyncTeleport {
if (!ess.getSettings().isForcePassengerTeleport() && !teleportee.getBase().isEmpty()) {
if (!ess.getSettings().isTeleportPassengerDismount()) {
future.completeExceptionally(new TranslatableException("passengerTeleportFail"));
future.completeExceptionally(new Exception(tl("passengerTeleportFail")));
return;
}
@@ -202,7 +204,7 @@ public class AsyncTeleport implements IAsyncTeleport {
}
}
} else {
future.completeExceptionally(new TranslatableException("unsafeTeleportDestination", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
future.completeExceptionally(new Exception(tl("unsafeTeleportDestination", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())));
return;
}
} else {
@@ -231,7 +233,7 @@ public class AsyncTeleport implements IAsyncTeleport {
@Override
public void teleport(final Player entity, final Trade chargeFor, final TeleportCause cause, final CompletableFuture<Boolean> future) {
teleportOwner.sendTl("teleportToPlayer", entity.getDisplayName());
teleportOwner.sendMessage(tl("teleportToPlayer", entity.getDisplayName()));
teleport(teleportOwner, new PlayerTarget(entity), chargeFor, cause, future);
}
@@ -246,8 +248,8 @@ public class AsyncTeleport implements IAsyncTeleport {
teleport(otherUser, target, chargeFor, cause, future);
future.thenAccept(success -> {
if (success) {
otherUser.sendTl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ());
teleportOwner.sendTl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ());
otherUser.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
teleportOwner.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
}
});
}
@@ -423,16 +425,16 @@ public class AsyncTeleport implements IAsyncTeleport {
final Location loc;
try {
loc = ess.getWarps().getWarp(warp);
} catch (final WarpNotFoundException e) {
} catch (final WarpNotFoundException | InvalidWorldException e) {
future.completeExceptionally(e);
return;
}
final String finalWarp = warp;
future.thenAccept(success -> {
if (success) {
otherUser.sendTl("warpingTo", finalWarp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
otherUser.sendMessage(tl("warpingTo", finalWarp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
if (!otherUser.equals(teleportOwner)) {
teleportOwner.sendTl("warpingTo", finalWarp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
teleportOwner.sendMessage(tl("warpingTo", finalWarp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
}
}
});
@@ -448,7 +450,7 @@ public class AsyncTeleport implements IAsyncTeleport {
public void back(final IUser teleporter, final Trade chargeFor, final CompletableFuture<Boolean> future) {
tpType = TeleportType.BACK;
final Location loc = teleportOwner.getLastLocation();
teleportOwner.sendTl("backUsageMsg", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
teleportOwner.sendMessage(tl("backUsageMsg", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
teleportOther(teleporter, teleportOwner, new LocationTarget(loc), chargeFor, TeleportCause.COMMAND, future);
}
@@ -457,10 +459,6 @@ 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,15 +1,14 @@
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;
import static com.earth2me.essentials.I18n.tl;
public class AsyncTimedTeleport implements Runnable {
private static final double MOVE_CONSTANT = 0.3;
@@ -107,14 +106,14 @@ public class AsyncTimedTeleport implements Runnable {
try {
teleport.cooldown(false);
} catch (final Throwable ex) {
teleportOwner.sendTl("cooldownWithMessage", ex.getMessage());
teleportOwner.sendMessage(tl("cooldownWithMessage", ex.getMessage()));
if (teleportOwner != teleportUser) {
teleportUser.sendTl("cooldownWithMessage", ex.getMessage());
teleportUser.sendMessage(tl("cooldownWithMessage", ex.getMessage()));
}
}
try {
cancelTimer(false);
teleportUser.sendTl("teleportationCommencing");
teleportUser.sendMessage(tl("teleportationCommencing"));
if (timer_chargeFor != null) {
timer_chargeFor.isAffordableFor(teleportOwner);
@@ -152,18 +151,10 @@ 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");
teleportOwner.sendMessage(tl("pendingTeleportCancelled"));
if (timer_teleportee != null && !timer_teleportee.equals(teleportOwner.getBase().getUniqueId())) {
ess.getUser(timer_teleportee).sendTl("pendingTeleportCancelled");
ess.getUser(timer_teleportee).sendMessage(tl("pendingTeleportCancelled"));
}
}
} finally {
@@ -11,7 +11,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public class Backup implements Runnable {
private transient final Server server;
@@ -79,7 +79,7 @@ public class Backup implements Runnable {
taskLock.complete(new Object());
return;
}
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("backupStarted")));
ess.getLogger().log(Level.INFO, tl("backupStarted"));
final CommandSender cs = server.getConsoleSender();
server.dispatchCommand(cs, "save-all");
server.dispatchCommand(cs, "save-off");
@@ -118,7 +118,7 @@ public class Backup implements Runnable {
}
active = false;
taskLock.complete(new Object());
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("backupFinished")));
ess.getLogger().log(Level.INFO, tl("backupFinished"));
}
}
@@ -40,7 +40,7 @@ public class BalanceTopImpl implements BalanceTop {
user.updateMoneyCache(userMoney);
newTotal = newTotal.add(userMoney);
final String name;
if (user.getBase() instanceof OfflinePlayerStub) {
if (user.getBase() instanceof OfflinePlayer) {
name = user.getLastAccountName();
} else if (user.isHidden()) {
name = user.getName();
@@ -53,10 +53,7 @@ public class BalanceTopImpl implements BalanceTop {
}
final LinkedHashMap<UUID, Entry> sortedMap = new LinkedHashMap<>();
entries.sort((entry1, entry2) -> entry2.getBalance().compareTo(entry1.getBalance()));
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);
for (Entry entry : entries) {
sortedMap.put(entry.getUuid(), entry);
}
topCache = sortedMap;
@@ -1,9 +1,11 @@
package com.earth2me.essentials;
import net.ess3.api.TranslatableException;
public class ChargeException extends Exception {
public ChargeException(final String message) {
super(message);
}
public class ChargeException extends TranslatableException {
public ChargeException(String tlKey, Object... args) {
super(tlKey, args);
public ChargeException(final String message, final Throwable throwable) {
super(message, throwable);
}
}
@@ -1,17 +1,12 @@
package com.earth2me.essentials;
import com.earth2me.essentials.adventure.ComponentHolder;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import static com.earth2me.essentials.I18n.tlLiteral;
public class CommandSource {
protected Essentials ess;
protected CommandSender sender;
public CommandSource(final Essentials ess, final CommandSender base) {
this.ess = ess;
public CommandSource(final CommandSender base) {
this.sender = base;
}
@@ -26,41 +21,7 @@ public class CommandSource {
return null;
}
public void sendTl(final String tlKey, final Object... args) {
if (isPlayer()) {
//noinspection ConstantConditions
getUser().sendTl(tlKey, args);
return;
}
final String translation = tlLiteral(tlKey, args);
if (!translation.isEmpty()) {
sendComponent(ess.getAdventureFacet().deserializeMiniMessage(translation));
}
}
public String tl(final String tlKey, final Object... args) {
if (isPlayer()) {
//noinspection ConstantConditions
return getUser().playerTl(tlKey, args);
}
return tlLiteral(tlKey, 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 ess.getAdventureFacet().deserializeMiniMessage(translation);
}
public void sendComponent(final ComponentHolder component) {
ess.getAdventureFacet().send(sender, component);
}
public final net.ess3.api.IUser getUser() {
public final net.ess3.api.IUser getUser(final IEssentials ess) {
if (sender instanceof Player) {
return ess.getUser((Player) sender);
}
@@ -81,18 +42,15 @@ public class CommandSource {
}
}
public boolean isAuthorized(final String permission) {
//noinspection ConstantConditions
return !(sender instanceof Player) || getUser().isAuthorized(permission);
public boolean isAuthorized(final String permission, final IEssentials ess) {
return !(sender instanceof Player) || getUser(ess).isAuthorized(permission);
}
public String getSelfSelector() {
//noinspection ConstantConditions
return sender instanceof Player ? getPlayer().getName() : "*";
}
public String getDisplayName() {
//noinspection ConstantConditions
return sender instanceof Player ? getPlayer().getDisplayName() : getSender().getName();
}
}
@@ -1,6 +1,5 @@
package com.earth2me.essentials;
import com.earth2me.essentials.adventure.AdventureFacet;
import com.earth2me.essentials.messaging.IMessageRecipient;
import com.earth2me.essentials.messaging.SimpleMessageRecipient;
import org.bukkit.Server;
@@ -9,15 +8,11 @@ import org.bukkit.entity.Player;
import java.util.UUID;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public final class Console implements IMessageRecipient {
public static final String NAME = "Console";
public static String displayName() {
return tlLiteral("consoleName");
}
public static final String DISPLAY_NAME = tl("consoleName");
private static Console instance; // Set in essentials
private final IEssentials ess;
@@ -60,7 +55,7 @@ public final class Console implements IMessageRecipient {
@Override
public String getDisplayName() {
return displayName();
return Console.DISPLAY_NAME;
}
@Override
@@ -68,22 +63,6 @@ public final class Console implements IMessageRecipient {
getCommandSender().sendMessage(message);
}
@Override
public void sendTl(String tlKey, Object... args) {
final String translation = tlLiteral(tlKey, args);
if (translation.isEmpty()) {
return;
}
final AdventureFacet adventureFacet = ess.getAdventureFacet();
adventureFacet.send(getCommandSender(), adventureFacet.deserializeMiniMessage(translation));
}
@Override
public String tlSender(String tlKey, Object... args) {
return tlLiteral(tlKey, args);
}
@Override
public boolean isReachable() {
return true;
@@ -1,6 +1,5 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.RegistryUtil;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
@@ -16,43 +15,33 @@ public final class Enchantments {
private static boolean isFlat;
static {
final Enchantment SHARPNESS = RegistryUtil.valueOf(Enchantment.class, "DAMAGE_ALL", "SHARPNESS");
ENCHANTMENTS.put("alldamage", Enchantment.DAMAGE_ALL);
ALIASENCHANTMENTS.put("alldmg", Enchantment.DAMAGE_ALL);
ENCHANTMENTS.put("sharpness", Enchantment.DAMAGE_ALL);
ALIASENCHANTMENTS.put("sharp", Enchantment.DAMAGE_ALL);
ALIASENCHANTMENTS.put("dal", Enchantment.DAMAGE_ALL);
ENCHANTMENTS.put("alldamage", SHARPNESS);
ALIASENCHANTMENTS.put("alldmg", SHARPNESS);
ENCHANTMENTS.put("sharpness", SHARPNESS);
ALIASENCHANTMENTS.put("sharp", SHARPNESS);
ALIASENCHANTMENTS.put("dal", SHARPNESS);
ENCHANTMENTS.put("ardmg", Enchantment.DAMAGE_ARTHROPODS);
ENCHANTMENTS.put("baneofarthropods", Enchantment.DAMAGE_ARTHROPODS);
ALIASENCHANTMENTS.put("baneofarthropod", Enchantment.DAMAGE_ARTHROPODS);
ALIASENCHANTMENTS.put("arthropod", Enchantment.DAMAGE_ARTHROPODS);
ALIASENCHANTMENTS.put("dar", Enchantment.DAMAGE_ARTHROPODS);
final Enchantment BANE_OF_ARTHROPODS = RegistryUtil.valueOf(Enchantment.class, "DAMAGE_ARTHROPODS", "BANE_OF_ARTHROPODS");
ENCHANTMENTS.put("undeaddamage", Enchantment.DAMAGE_UNDEAD);
ENCHANTMENTS.put("smite", Enchantment.DAMAGE_UNDEAD);
ALIASENCHANTMENTS.put("du", Enchantment.DAMAGE_UNDEAD);
ENCHANTMENTS.put("ardmg", BANE_OF_ARTHROPODS);
ENCHANTMENTS.put("baneofarthropods", BANE_OF_ARTHROPODS);
ALIASENCHANTMENTS.put("baneofarthropod", BANE_OF_ARTHROPODS);
ALIASENCHANTMENTS.put("arthropod", BANE_OF_ARTHROPODS);
ALIASENCHANTMENTS.put("dar", BANE_OF_ARTHROPODS);
ENCHANTMENTS.put("digspeed", Enchantment.DIG_SPEED);
ENCHANTMENTS.put("efficiency", Enchantment.DIG_SPEED);
ALIASENCHANTMENTS.put("minespeed", Enchantment.DIG_SPEED);
ALIASENCHANTMENTS.put("cutspeed", Enchantment.DIG_SPEED);
ALIASENCHANTMENTS.put("ds", Enchantment.DIG_SPEED);
ALIASENCHANTMENTS.put("eff", Enchantment.DIG_SPEED);
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);
ENCHANTMENTS.put("efficiency", EFFICIENCY);
ALIASENCHANTMENTS.put("minespeed", EFFICIENCY);
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);
ALIASENCHANTMENTS.put("dura", UNBREAKING);
ENCHANTMENTS.put("unbreaking", UNBREAKING);
ALIASENCHANTMENTS.put("d", UNBREAKING);
ENCHANTMENTS.put("durability", Enchantment.DURABILITY);
ALIASENCHANTMENTS.put("dura", Enchantment.DURABILITY);
ENCHANTMENTS.put("unbreaking", Enchantment.DURABILITY);
ALIASENCHANTMENTS.put("d", Enchantment.DURABILITY);
ENCHANTMENTS.put("thorns", Enchantment.THORNS);
ENCHANTMENTS.put("highcrit", Enchantment.THORNS);
@@ -71,126 +60,105 @@ public final class Enchantments {
ALIASENCHANTMENTS.put("kb", Enchantment.KNOCKBACK);
ALIASENCHANTMENTS.put("k", Enchantment.KNOCKBACK);
final Enchantment FORTUNE = RegistryUtil.valueOf(Enchantment.class, "LOOT_BONUS_BLOCKS", "FORTUNE");
ALIASENCHANTMENTS.put("blockslootbonus", Enchantment.LOOT_BONUS_BLOCKS);
ENCHANTMENTS.put("fortune", Enchantment.LOOT_BONUS_BLOCKS);
ALIASENCHANTMENTS.put("fort", Enchantment.LOOT_BONUS_BLOCKS);
ALIASENCHANTMENTS.put("lbb", Enchantment.LOOT_BONUS_BLOCKS);
ALIASENCHANTMENTS.put("blockslootbonus", FORTUNE);
ENCHANTMENTS.put("fortune", FORTUNE);
ALIASENCHANTMENTS.put("fort", FORTUNE);
ALIASENCHANTMENTS.put("lbb", FORTUNE);
ALIASENCHANTMENTS.put("mobslootbonus", Enchantment.LOOT_BONUS_MOBS);
ENCHANTMENTS.put("mobloot", Enchantment.LOOT_BONUS_MOBS);
ENCHANTMENTS.put("looting", Enchantment.LOOT_BONUS_MOBS);
ALIASENCHANTMENTS.put("lbm", Enchantment.LOOT_BONUS_MOBS);
final Enchantment LOOTING = RegistryUtil.valueOf(Enchantment.class, "LOOT_BONUS_MOBS", "LOOTING");
ALIASENCHANTMENTS.put("oxygen", Enchantment.OXYGEN);
ENCHANTMENTS.put("respiration", Enchantment.OXYGEN);
ALIASENCHANTMENTS.put("breathing", Enchantment.OXYGEN);
ENCHANTMENTS.put("breath", Enchantment.OXYGEN);
ALIASENCHANTMENTS.put("o", Enchantment.OXYGEN);
ALIASENCHANTMENTS.put("mobslootbonus", LOOTING);
ENCHANTMENTS.put("mobloot", LOOTING);
ENCHANTMENTS.put("looting", LOOTING);
ALIASENCHANTMENTS.put("lbm", LOOTING);
ENCHANTMENTS.put("protection", Enchantment.PROTECTION_ENVIRONMENTAL);
ALIASENCHANTMENTS.put("prot", Enchantment.PROTECTION_ENVIRONMENTAL);
ENCHANTMENTS.put("protect", Enchantment.PROTECTION_ENVIRONMENTAL);
ALIASENCHANTMENTS.put("p", Enchantment.PROTECTION_ENVIRONMENTAL);
final Enchantment RESPIRATION = RegistryUtil.valueOf(Enchantment.class, "OXYGEN", "RESPIRATION");
ALIASENCHANTMENTS.put("explosionsprotection", Enchantment.PROTECTION_EXPLOSIONS);
ALIASENCHANTMENTS.put("explosionprotection", Enchantment.PROTECTION_EXPLOSIONS);
ALIASENCHANTMENTS.put("expprot", Enchantment.PROTECTION_EXPLOSIONS);
ALIASENCHANTMENTS.put("blastprotection", Enchantment.PROTECTION_EXPLOSIONS);
ALIASENCHANTMENTS.put("bprotection", Enchantment.PROTECTION_EXPLOSIONS);
ALIASENCHANTMENTS.put("bprotect", Enchantment.PROTECTION_EXPLOSIONS);
ENCHANTMENTS.put("blastprotect", Enchantment.PROTECTION_EXPLOSIONS);
ALIASENCHANTMENTS.put("pe", Enchantment.PROTECTION_EXPLOSIONS);
ALIASENCHANTMENTS.put("oxygen", RESPIRATION);
ENCHANTMENTS.put("respiration", RESPIRATION);
ALIASENCHANTMENTS.put("breathing", RESPIRATION);
ENCHANTMENTS.put("breath", RESPIRATION);
ALIASENCHANTMENTS.put("o", RESPIRATION);
ALIASENCHANTMENTS.put("fallprotection", Enchantment.PROTECTION_FALL);
ENCHANTMENTS.put("fallprot", Enchantment.PROTECTION_FALL);
ENCHANTMENTS.put("featherfall", Enchantment.PROTECTION_FALL);
ALIASENCHANTMENTS.put("featherfalling", Enchantment.PROTECTION_FALL);
ALIASENCHANTMENTS.put("pfa", Enchantment.PROTECTION_FALL);
final Enchantment PROTECTION = RegistryUtil.valueOf(Enchantment.class, "PROTECTION_ENVIRONMENTAL", "PROTECTION");
ALIASENCHANTMENTS.put("fireprotection", Enchantment.PROTECTION_FIRE);
ALIASENCHANTMENTS.put("flameprotection", Enchantment.PROTECTION_FIRE);
ENCHANTMENTS.put("fireprotect", Enchantment.PROTECTION_FIRE);
ALIASENCHANTMENTS.put("flameprotect", Enchantment.PROTECTION_FIRE);
ENCHANTMENTS.put("fireprot", Enchantment.PROTECTION_FIRE);
ALIASENCHANTMENTS.put("flameprot", Enchantment.PROTECTION_FIRE);
ALIASENCHANTMENTS.put("pf", Enchantment.PROTECTION_FIRE);
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);
ALIASENCHANTMENTS.put("explosionprotection", BLAST_PROTECTION);
ALIASENCHANTMENTS.put("expprot", BLAST_PROTECTION);
ALIASENCHANTMENTS.put("blastprotection", BLAST_PROTECTION);
ALIASENCHANTMENTS.put("bprotection", BLAST_PROTECTION);
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);
ENCHANTMENTS.put("fallprot", FEATHER_FALLING);
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);
ALIASENCHANTMENTS.put("flameprotection", FIRE_PROTECTION);
ENCHANTMENTS.put("fireprotect", FIRE_PROTECTION);
ALIASENCHANTMENTS.put("flameprotect", FIRE_PROTECTION);
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);
ENCHANTMENTS.put("projprot", PROJECTILE_PROTECTION);
ALIASENCHANTMENTS.put("pp", PROJECTILE_PROTECTION);
ENCHANTMENTS.put("projectileprotection", Enchantment.PROTECTION_PROJECTILE);
ENCHANTMENTS.put("projprot", Enchantment.PROTECTION_PROJECTILE);
ALIASENCHANTMENTS.put("pp", Enchantment.PROTECTION_PROJECTILE);
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", Enchantment.WATER_WORKER);
ENCHANTMENTS.put("aquaaffinity", Enchantment.WATER_WORKER);
ALIASENCHANTMENTS.put("watermine", Enchantment.WATER_WORKER);
ALIASENCHANTMENTS.put("ww", Enchantment.WATER_WORKER);
ENCHANTMENTS.put("waterworker", AQUA_AFFINITY);
ENCHANTMENTS.put("aquaaffinity", AQUA_AFFINITY);
ALIASENCHANTMENTS.put("watermine", AQUA_AFFINITY);
ALIASENCHANTMENTS.put("ww", AQUA_AFFINITY);
ALIASENCHANTMENTS.put("firearrow", Enchantment.ARROW_FIRE);
ENCHANTMENTS.put("flame", Enchantment.ARROW_FIRE);
ENCHANTMENTS.put("flamearrow", Enchantment.ARROW_FIRE);
ALIASENCHANTMENTS.put("af", Enchantment.ARROW_FIRE);
final Enchantment FLAME = RegistryUtil.valueOf(Enchantment.class, "ARROW_FIRE", "FLAME");
ENCHANTMENTS.put("arrowdamage", Enchantment.ARROW_DAMAGE);
ENCHANTMENTS.put("power", Enchantment.ARROW_DAMAGE);
ALIASENCHANTMENTS.put("arrowpower", Enchantment.ARROW_DAMAGE);
ALIASENCHANTMENTS.put("ad", Enchantment.ARROW_DAMAGE);
ALIASENCHANTMENTS.put("firearrow", FLAME);
ENCHANTMENTS.put("flame", FLAME);
ENCHANTMENTS.put("flamearrow", FLAME);
ALIASENCHANTMENTS.put("af", FLAME);
ENCHANTMENTS.put("arrowknockback", Enchantment.ARROW_KNOCKBACK);
ALIASENCHANTMENTS.put("arrowkb", Enchantment.ARROW_KNOCKBACK);
ENCHANTMENTS.put("punch", Enchantment.ARROW_KNOCKBACK);
ALIASENCHANTMENTS.put("arrowpunch", Enchantment.ARROW_KNOCKBACK);
ALIASENCHANTMENTS.put("ak", Enchantment.ARROW_KNOCKBACK);
final Enchantment POWER = RegistryUtil.valueOf(Enchantment.class, "ARROW_DAMAGE", "POWER");
ALIASENCHANTMENTS.put("infinitearrows", Enchantment.ARROW_INFINITE);
ENCHANTMENTS.put("infarrows", Enchantment.ARROW_INFINITE);
ENCHANTMENTS.put("infinity", Enchantment.ARROW_INFINITE);
ALIASENCHANTMENTS.put("infinite", Enchantment.ARROW_INFINITE);
ALIASENCHANTMENTS.put("unlimited", Enchantment.ARROW_INFINITE);
ALIASENCHANTMENTS.put("unlimitedarrows", Enchantment.ARROW_INFINITE);
ALIASENCHANTMENTS.put("ai", Enchantment.ARROW_INFINITE);
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);
ALIASENCHANTMENTS.put("arrowkb", PUNCH);
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);
ENCHANTMENTS.put("infarrows", INFINITY);
ENCHANTMENTS.put("infinity", INFINITY);
ALIASENCHANTMENTS.put("infinite", INFINITY);
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);
ALIASENCHANTMENTS.put("luckofsea", LUCK_OF_THE_SEA);
ALIASENCHANTMENTS.put("luckofseas", LUCK_OF_THE_SEA);
ALIASENCHANTMENTS.put("rodluck", LUCK_OF_THE_SEA);
ENCHANTMENTS.put("luck", Enchantment.LUCK);
ALIASENCHANTMENTS.put("luckofsea", Enchantment.LUCK);
ALIASENCHANTMENTS.put("luckofseas", Enchantment.LUCK);
ALIASENCHANTMENTS.put("rodluck", Enchantment.LUCK);
ENCHANTMENTS.put("lure", Enchantment.LURE);
ALIASENCHANTMENTS.put("rodlure", Enchantment.LURE);
ENCHANTMENTS.put("depthstrider", Enchantment.DEPTH_STRIDER);
ALIASENCHANTMENTS.put("depth", Enchantment.DEPTH_STRIDER);
ALIASENCHANTMENTS.put("strider", Enchantment.DEPTH_STRIDER);
// 1.8
try {
final Enchantment depthStrider = Enchantment.getByName("DEPTH_STRIDER");
if (depthStrider != null) {
ENCHANTMENTS.put("depthstrider", depthStrider);
ALIASENCHANTMENTS.put("depth", depthStrider);
ALIASENCHANTMENTS.put("strider", depthStrider);
}
} catch (final IllegalArgumentException ignored) {
}
// 1.9
try {
@@ -303,32 +271,6 @@ public final class Enchantments {
} catch (final IllegalArgumentException ignored) {
}
try { // 1.21
final Enchantment breach = Enchantment.getByName("BREACH");
if (breach != null) {
ENCHANTMENTS.put("breach", breach);
}
final Enchantment density = Enchantment.getByName("DENSITY");
if (density != null) {
ENCHANTMENTS.put("density", density);
}
final Enchantment windBurst = Enchantment.getByName("WIND_BURST");
if (windBurst != null) {
ENCHANTMENTS.put("windburst", windBurst);
ALIASENCHANTMENTS.put("wind", windBurst);
ALIASENCHANTMENTS.put("burst", windBurst);
}
} 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");
@@ -342,17 +284,6 @@ public final class Enchantments {
private Enchantments() {
}
public static String getRealName(final Enchantment enchantment) {
if (enchantment == null) {
return null;
}
if (isFlat) { // 1.13+ only
return enchantment.getKey().getKey();
}
return enchantment.getName().toLowerCase(Locale.ENGLISH);
}
public static Enchantment getByName(final String name) {
if (name == null || name.isEmpty()) {
return null;
File diff suppressed because it is too large. Load diff
@@ -3,8 +3,6 @@ package com.earth2me.essentials;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.MaterialUtil;
import net.ess3.api.IEssentials;
import net.ess3.provider.PersistentDataProvider;
import net.ess3.provider.SpawnerItemProvider;
import org.bukkit.GameMode;
import org.bukkit.block.BlockState;
import org.bukkit.block.CreatureSpawner;
@@ -28,11 +26,11 @@ public class EssentialsBlockListener implements Listener {
public void onBlockPlace(final BlockPlaceEvent event) {
final ItemStack is = event.getItemInHand();
if (is.getType() == MaterialUtil.SPAWNER && ess.provider(PersistentDataProvider.class).getString(is, "convert") != null) {
if (is.getType() == MaterialUtil.SPAWNER && ess.getPersistentDataProvider().getString(is, "convert") != null) {
final BlockState blockState = event.getBlockPlaced().getState();
if (blockState instanceof CreatureSpawner) {
final CreatureSpawner spawner = (CreatureSpawner) blockState;
final EntityType type = ess.provider(SpawnerItemProvider.class).getEntityType(event.getItemInHand());
final EntityType type = ess.getSpawnerItemProvider().getEntityType(event.getItemInHand());
if (type != null && Mob.fromBukkitType(type) != null) {
if (ess.getUser(event.getPlayer()).isAuthorized("essentials.spawnerconvert." + Mob.fromBukkitType(type).name().toLowerCase(Locale.ENGLISH))) {
spawner.setSpawnedType(type);
@@ -32,6 +32,8 @@ import java.util.List;
import java.util.logging.Level;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
public class EssentialsEntityListener implements Listener {
private static final transient Pattern powertoolPlayer = Pattern.compile("\\{player\\}");
private final IEssentials ess;
@@ -156,7 +158,7 @@ public class EssentialsEntityListener implements Listener {
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerDeathEvent(final PlayerDeathEvent event) {
final Entity entity = event.getEntity();
if (entity.hasMetadata("NPC")) {
@@ -165,11 +167,11 @@ public class EssentialsEntityListener implements Listener {
final User user = ess.getUser(event.getEntity());
if (ess.getSettings().infoAfterDeath()) {
final Location loc = user.getLocation();
user.sendTl("infoAfterDeath", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
user.sendMessage(tl("infoAfterDeath", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
}
if (user.isAuthorized("essentials.back.ondeath") && !ess.getSettings().isCommandDisabled("back")) {
user.setLastLocation();
user.sendTl("backAfterDeath");
user.sendMessage(tl("backAfterDeath"));
}
if (!ess.getSettings().areDeathMessagesEnabled()) {
event.setDeathMessage("");
@@ -190,15 +192,7 @@ public class EssentialsEntityListener implements Listener {
final User user = ess.getUser(event.getEntity());
if (user.isAuthorized("essentials.keepinv")) {
event.setKeepInventory(true);
// We don't do getDrops().clear() here because it would remove any loot tables that were added by other plugins/datapacks.
// Instead, we remove the items from the drops that are in the player's inventory. This way, the loot tables can still drop items.
// This is the same behavior as the vanilla /gamerule keepInventory.
final ItemStack[] inventory = Inventories.getInventory(event.getEntity(), true);
for (final ItemStack item : inventory) {
if (item != null) {
event.getDrops().remove(item);
}
}
event.getDrops().clear();
final ISettings.KeepInvPolicy vanish = ess.getSettings().getVanishingItemsPolicy();
final ISettings.KeepInvPolicy bind = ess.getSettings().getBindingItemsPolicy();
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_11_2_R01) && (vanish != ISettings.KeepInvPolicy.KEEP || bind != ISettings.KeepInvPolicy.KEEP)) {
File diff suppressed because it is too large. Load diff
@@ -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.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.StringUtil;
@@ -12,7 +11,6 @@ import com.google.common.io.Files;
import com.google.gson.reflect.TypeToken;
import net.ess3.api.IEssentials;
import net.essentialsx.api.v2.services.mail.MailMessage;
import nu.studer.java.util.OrderedProperties;
import org.bukkit.BanList;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -51,7 +49,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public class EssentialsUpgrade {
public static final FileFilter YML_FILTER = pathname -> pathname.isFile() && pathname.getName().endsWith(".yml");
@@ -71,7 +69,7 @@ public class EssentialsUpgrade {
doneFile.load();
}
private static void uuidFileConvert(final IEssentials ess, final Boolean ignoreUFCache) {
public 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");
@@ -156,42 +154,7 @@ public class EssentialsUpgrade {
ess.getLogger().info("To rerun the conversion type /essentials uuidconvert");
}
private void updateRandomTeleport() {
if (doneFile.getBoolean("updateRandomTeleport", false)) {
return;
}
final EssentialsConfiguration config = ess.getRandomTeleport().getConfig();
if (config.getRootNode() != null) {
final LazyLocation center = config.getLocation("center");
final Location centerLoc = center != null ? center.location() : null;
if (center != null && centerLoc != null) {
final double minRange = config.getDouble("min-range", Double.MIN_VALUE);
final double maxRange = config.getDouble("max-range", Double.MIN_VALUE);
for (final World world : ess.getServer().getWorlds()) {
final String propPrefix = "locations." + world.getName() + ".";
config.setProperty(propPrefix + "center", centerLoc);
if (minRange != Double.MIN_VALUE) {
config.setProperty(propPrefix + "min-range", minRange);
}
if (maxRange != Double.MIN_VALUE) {
config.setProperty(propPrefix + "max-range", maxRange);
}
}
}
config.removeProperty("center");
config.blockingSave();
}
doneFile.setProperty("updateRandomTeleport", true);
doneFile.save();
ess.getLogger().info("Done converting random teleport config.");
}
private void convertMailList() {
public void convertMailList() {
if (doneFile.getBoolean("updateUsersMailList", false)) {
return;
}
@@ -231,7 +194,7 @@ public class EssentialsUpgrade {
ess.getLogger().info("Done converting mail list.");
}
private void convertStupidCamelCaseUserdataKeys() {
public void convertStupidCamelCaseUserdataKeys() {
if (doneFile.getBoolean("updateUsersStupidLegacyPathNames", false)) {
return;
}
@@ -311,7 +274,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."
*/
private void purgeBrokenNpcAccounts() {
public void purgeBrokenNpcAccounts() {
if (doneFile.getBoolean("updatePurgeBrokenNpcAccounts", false)) {
return;
}
@@ -422,7 +385,7 @@ public class EssentialsUpgrade {
ess.getLogger().info("#===========================================================================#");
}
private void convertIgnoreList() {
public 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;
@@ -473,10 +436,6 @@ 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)) {
@@ -534,7 +493,7 @@ public class EssentialsUpgrade {
doneFile.setProperty("move" + name + "ToFile", true);
doneFile.save();
} catch (final IOException e) {
ess.getLogger().log(Level.SEVERE, ess.getAdventureFacet().miniToLegacy(tlLiteral("upgradingFilesError")), e);
ess.getLogger().log(Level.SEVERE, tl("upgradingFilesError"), e);
}
}
@@ -569,10 +528,10 @@ public class EssentialsUpgrade {
bWriter.close();
if (needUpdate) {
if (!file.renameTo(new File(file.getParentFile(), file.getName().concat("." + System.currentTimeMillis() + ".upgradebackup")))) {
throw new Exception(tlLiteral("configFileMoveError"));
throw new Exception(tl("configFileMoveError"));
}
if (!tempFile.renameTo(file)) {
throw new Exception(tlLiteral("configFileRenameError"));
throw new Exception(tl("configFileRenameError"));
}
} else {
tempFile.delete();
@@ -697,15 +656,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, ess.getAdventureFacet().miniToLegacy(tlLiteral("userdataMoveError", filename, sanitizedFilename)));
ess.getLogger().log(Level.WARNING, tl("userdataMoveError", filename, sanitizedFilename));
continue;
}
if (newFile.exists()) {
ess.getLogger().log(Level.WARNING, ess.getAdventureFacet().miniToLegacy(tlLiteral("duplicatedUserdata", filename, sanitizedFilename)));
ess.getLogger().log(Level.WARNING, tl("duplicatedUserdata", filename, sanitizedFilename));
continue;
}
if (!tmpFile.renameTo(newFile)) {
ess.getLogger().log(Level.WARNING, ess.getAdventureFacet().miniToLegacy(tlLiteral("userdataMoveBackError", sanitizedFilename, sanitizedFilename)));
ess.getLogger().log(Level.WARNING, tl("userdataMoveBackError", sanitizedFilename, sanitizedFilename));
}
}
doneFile.setProperty("sanitizeAllUserFilenames", true);
@@ -721,7 +680,7 @@ public class EssentialsUpgrade {
return null;
}
private Location getFakeLocation(final CommentedConfigurationNode config, final String path) {
public Location getFakeLocation(final CommentedConfigurationNode config, final String path) {
final String worldName = config.getString((path != null ? path + "." : "") + "world");
if (worldName == null || worldName.isEmpty()) {
return null;
@@ -783,7 +742,7 @@ public class EssentialsUpgrade {
config.setProperty(entry.getKey(), loc);
}
if (!configFile.renameTo(new File(ess.getDataFolder(), "spawn.yml.old"))) {
throw new Exception(tlLiteral("fileRenameError", "spawn.yml"));
throw new Exception(tl("fileRenameError", "spawn.yml"));
}
config.blockingSave();
}
@@ -811,7 +770,7 @@ public class EssentialsUpgrade {
config.setProperty(entry.getKey(), loc);
}
if (!configFile.renameTo(new File(ess.getDataFolder(), "jail.yml.old"))) {
throw new Exception(tlLiteral("fileRenameError", "jail.yml"));
throw new Exception(tl("fileRenameError", "jail.yml"));
}
config.blockingSave();
}
@@ -885,7 +844,7 @@ public class EssentialsUpgrade {
doneFile.save();
}
private void banFormatChange() {
public void banFormatChange() {
if (doneFile.getBoolean("banFormatChange", false)) {
return;
}
@@ -955,7 +914,7 @@ public class EssentialsUpgrade {
Bukkit.getBanList(BanList.Type.NAME).addBan(playerName, banReason, banTimeout == 0 ? null : new Date(banTimeout), Console.NAME);
}
private void generateUidCache() {
public void generateUidCache() {
if (doneFile.getBoolean("newUidCacheBuilt", false)) {
return;
}
@@ -995,7 +954,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 {
@@ -1004,7 +963,7 @@ public class EssentialsUpgrade {
}
}
uuids.put(uuid, time);
uuids.put(uuid, config.getLong("timestamps.logout", 0L));
nameToUuidMap.put(name, uuid);
}
} catch (IllegalArgumentException | IndexOutOfBoundsException ignored) {
@@ -1027,65 +986,7 @@ public class EssentialsUpgrade {
}
}
public void upgradeLang() {
if (doneFile.getBoolean("updateLegacyToAdventure", false)) {
return;
}
ess.getLogger().log(Level.WARNING, "Beginning Adventure locale file conversion.");
try {
final File dataFolder = ess.getDataFolder();
if (!dataFolder.exists() || !dataFolder.isDirectory()) {
return;
}
final File backDir = new File(dataFolder, "msg-backups-" + System.currentTimeMillis());
if (backDir.exists() || !backDir.mkdir()) {
ess.getLogger().log(Level.SEVERE, "Unable to make msg-backups dir?!");
return;
}
final File messagesDir = new File(dataFolder, "messages");
//noinspection ResultOfMethodCallIgnored
messagesDir.mkdir();
final File[] files = dataFolder.listFiles();
boolean isThereAtLeastOneBackup = false;
if (files != null) {
for (final File file : files) {
if (file.getName().endsWith(".properties")) {
final File newFile = new File(messagesDir, file.getName());
final File backup = new File(backDir, file.getName());
Files.move(file, backup);
isThereAtLeastOneBackup = true;
final OrderedProperties properties = new OrderedProperties();
properties.load(Files.newReader(backup, Charsets.UTF_8));
for (final String key : properties.stringPropertyNames()) {
final String value = properties.getProperty(key);
properties.setProperty(key, ess.getAdventureFacet().legacyToMini(ess.getAdventureFacet().escapeTags(value), true));
}
properties.store(Files.newWriter(newFile, Charsets.UTF_8), null);
}
}
}
if (!isThereAtLeastOneBackup) {
backDir.delete();
}
doneFile.setProperty("updateLegacyToAdventure", true);
doneFile.save();
} catch (final Throwable e) {
ess.getLogger().log(Level.SEVERE, "Error while upgrading custom locales", e);
}
}
public void beforeSettings() {
if (Essentials.TESTING) {
return;
}
if (!ess.getDataFolder().exists()) {
ess.getDataFolder().mkdirs();
}
@@ -1094,17 +995,10 @@ public class EssentialsUpgrade {
}
public void preModules() {
if (Essentials.TESTING) {
return;
}
generateUidCache();
}
public void afterSettings() {
if (Essentials.TESTING) {
return;
}
sanitizeAllUserFilenames();
updateUsersPowerToolsFormat();
updateUsersHomesFormat();
@@ -1118,6 +1012,5 @@ public class EssentialsUpgrade {
convertStupidCamelCaseUserdataKeys();
convertMailList();
purgeBrokenNpcAccounts();
updateRandomTeleport();
}
}
@@ -1,8 +1,6 @@
package com.earth2me.essentials;
import com.earth2me.essentials.adventure.AdventureUtil;
import net.ess3.api.IEssentials;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileInputStream;
@@ -15,35 +13,25 @@ import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
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;
public class I18n implements net.ess3.api.II18n {
private static final String MESSAGES = "messages";
private static final Pattern NODOUBLEMARK = Pattern.compile("''");
private static volatile ExecutorService BUNDLE_LOADER_EXECUTOR = Executors.newFixedThreadPool(2);
private static final ResourceBundle NULL_BUNDLE = new ResourceBundle() {
@SuppressWarnings("NullableProblems")
public Enumeration<String> getKeys() {
return null;
}
protected Object handleGetObject(final @NotNull String key) {
protected Object handleGetObject(final String key) {
return null;
}
};
@@ -52,53 +40,30 @@ public class I18n implements net.ess3.api.II18n {
private final transient ResourceBundle defaultBundle;
private final transient IEssentials ess;
private transient Locale currentLocale = defaultLocale;
private final transient Map<Locale, ResourceBundle> loadedBundles = new ConcurrentHashMap<>();
private final transient List<Locale> loadingBundles = new ArrayList<>();
private transient ResourceBundle customBundle;
private transient ResourceBundle localeBundle;
private final transient Map<Locale, Map<String, MessageFormat>> messageFormatCache = new HashMap<>();
private transient Map<String, MessageFormat> messageFormatCache = new HashMap<>();
public I18n(final IEssentials ess) {
this.ess = ess;
defaultBundle = ResourceBundle.getBundle(MESSAGES, Locale.ENGLISH, new UTF8PropertiesControl());
localeBundle = defaultBundle;
customBundle = NULL_BUNDLE;
}
/**
* Translates a message using the server's configured locale.
* @param tlKey The translation key.
* @param objects Translation parameters, if applicable. Note: by default, these will not be parsed for MiniMessage.
* @return The translated message.
* @see AdventureUtil#parsed(String)
*/
public static String tlLiteral(final String tlKey, final Object... objects) {
if (instance == null) {
return "";
}
return tlLocale(instance.currentLocale, tlKey, objects);
}
/**
* Translates a message using the provided locale.
* @param locale The locale to translate the key to.
* @param tlKey The translation key.
* @param objects Translation parameters, if applicable. Note: by default, these will not be parsed for MiniMessage.
* @return The translated message.
* @see AdventureUtil#parsed(String)
*/
public static String tlLocale(final Locale locale, final String tlKey, final Object... objects) {
public static String tl(final String string, final Object... objects) {
if (instance == null) {
return "";
}
if (objects.length == 0) {
return NODOUBLEMARK.matcher(instance.translate(locale, tlKey)).replaceAll("'");
return NODOUBLEMARK.matcher(instance.translate(string)).replaceAll("'");
} else {
return instance.format(locale, tlKey, objects);
return instance.format(string, objects);
}
}
public static String capitalCase(final String input) {
return input == null || input.isEmpty() ? input : input.toUpperCase(Locale.ENGLISH).charAt(0) + input.toLowerCase(Locale.ENGLISH).substring(1);
return input == null || input.length() == 0 ? input : input.toUpperCase(Locale.ENGLISH).charAt(0) + input.toLowerCase(Locale.ENGLISH).substring(1);
}
public void onEnable() {
@@ -107,29 +72,6 @@ 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
@@ -137,108 +79,52 @@ public class I18n implements net.ess3.api.II18n {
return currentLocale;
}
/**
* Returns the {@link ResourceBundle} for the given {@link Locale}, if loaded. If a bundle is requested which is
* not loaded, it will be loaded asynchronously and the default bundle will be returned in the meantime.
*/
private ResourceBundle getBundle(final Locale locale) {
if (loadedBundles.containsKey(locale)) {
return loadedBundles.get(locale);
} else {
synchronized (loadingBundles) {
if (!loadingBundles.contains(locale)) {
loadingBundles.add(locale);
getExecutor().submit(() -> {
blockingLoadBundle(locale);
synchronized (loadingBundles) {
loadingBundles.remove(locale);
}
});
}
}
return defaultBundle;
}
}
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) {
private String translate(final String string) {
try {
try {
return getBundle(locale).getString(string);
return customBundle.getString(string);
} catch (final MissingResourceException ex) {
return localeBundle.getString(string);
}
} catch (final MissingResourceException ex) {
if (ess != null && ess.getSettings().isDebug()) {
if (ess == null || ess.getSettings().isDebug()) {
ess.getLogger().log(Level.WARNING, String.format("Missing translation key \"%s\" in translation file %s", ex.getKey(), localeBundle.getLocale().toString()), ex);
}
return defaultBundle.getString(string);
}
}
private String format(final Locale locale, final String string, final Object... objects) {
String format = translate(locale, string);
MessageFormat messageFormat = messageFormatCache.computeIfAbsent(locale, l -> new HashMap<>()).get(format);
public String format(final String string, final Object... objects) {
String format = translate(string);
MessageFormat messageFormat = messageFormatCache.get(format);
if (messageFormat == null) {
try {
messageFormat = new MessageFormat(format);
} catch (final IllegalArgumentException e) {
ess.getLogger().log(Level.SEVERE, "Invalid Translation key for '" + string + "': " + e.getMessage());
format = format.replaceAll("\\{(\\D*?)}", "\\[$1\\]");
format = format.replaceAll("\\{(\\D*?)\\}", "\\[$1\\]");
messageFormat = new MessageFormat(format);
}
messageFormatCache.get(locale).put(format, messageFormat);
messageFormatCache.put(format, messageFormat);
}
final Object[] processedArgs = mutateArgs(objects, arg -> {
if (arg instanceof AdventureUtil.ParsedPlaceholder) {
return arg.toString();
}
return ess.getAdventureFacet().legacyToMini(ess.getAdventureFacet().escapeTags(arg.toString()));
});
return messageFormat.format(processedArgs).replace(' ', ' '); // replace nbsp with a space
}
public static Object[] mutateArgs(final Object[] objects, final Function<Object, String> mutator) {
final Object[] args = new Object[objects.length];
for (int i = 0; i < objects.length; i++) {
final Object object = objects[i];
// MessageFormat will format these itself, troll face.
if (object instanceof Number || object instanceof Date || object == null) {
args[i] = object;
continue;
}
args[i] = mutator.apply(object);
}
return args;
return messageFormat.format(objects).replace(' ', ' '); // replace nbsp with a space
}
public void updateLocale(final String loc) {
if (loc != null && !loc.isEmpty()) {
currentLocale = getLocale(loc);
final String[] parts = loc.split("[_\\.]");
if (parts.length == 1) {
currentLocale = new Locale(parts[0]);
}
if (parts.length == 2) {
currentLocale = new Locale(parts[0], parts[1]);
}
if (parts.length == 3) {
currentLocale = new Locale(parts[0], parts[1], parts[2]);
}
}
ResourceBundle.clearCache();
loadedBundles.clear();
messageFormatCache.clear();
messageFormatCache = new HashMap<>();
ess.getLogger().log(Level.INFO, String.format("Using locale %s", currentLocale.toString()));
try {
@@ -246,41 +132,28 @@ public class I18n implements net.ess3.api.II18n {
} catch (final MissingResourceException ex) {
localeBundle = NULL_BUNDLE;
}
}
public static Locale getLocale(final String loc) {
if (loc == null || loc.isEmpty()) {
return instance.currentLocale;
try {
customBundle = ResourceBundle.getBundle(MESSAGES, currentLocale, new FileResClassLoader(I18n.class.getClassLoader(), ess), new UTF8PropertiesControl());
} catch (final MissingResourceException ex) {
customBundle = NULL_BUNDLE;
}
final String[] parts = loc.split("[_.]");
if (parts.length == 1) {
return new Locale(parts[0]);
}
if (parts.length == 2) {
return new Locale(parts[0], parts[1]);
}
if (parts.length == 3) {
return new Locale(parts[0], parts[1], parts[2]);
}
return instance.currentLocale;
}
/**
* Attempts to load properties files from the plugin directory before falling back to the jar.
*/
private static class FileResClassLoader extends ClassLoader {
private final transient File messagesFolder;
private final transient File dataFolder;
FileResClassLoader(final ClassLoader classLoader, final IEssentials ess) {
super(classLoader);
this.messagesFolder = new File(ess.getDataFolder(), "messages");
//noinspection ResultOfMethodCallIgnored
this.messagesFolder.mkdirs();
this.dataFolder = ess.getDataFolder();
}
@Override
public URL getResource(final String string) {
final File file = new File(messagesFolder, string);
final File file = new File(dataFolder, string);
if (file.exists()) {
try {
return file.toURI().toURL();
@@ -292,7 +165,7 @@ public class I18n implements net.ess3.api.II18n {
@Override
public InputStream getResourceAsStream(final String string) {
final File file = new File(messagesFolder, string);
final File file = new File(dataFolder, string);
if (file.exists()) {
try {
return new FileInputStream(file);
@@ -307,7 +180,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 final class UTF8PropertiesControl extends ResourceBundle.Control {
private static 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;
@@ -334,13 +207,5 @@ public class I18n implements net.ess3.api.II18n {
}
return bundle;
}
@Override
public Locale getFallbackLocale(String baseName, Locale locale) {
if (baseName == null || locale == null) {
throw new NullPointerException();
}
return null;
}
}
}
@@ -1,6 +1,5 @@
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;
@@ -9,7 +8,20 @@ import com.earth2me.essentials.commands.PlayerNotFoundException;
import com.earth2me.essentials.perm.PermissionsHandler;
import com.earth2me.essentials.updatecheck.UpdateChecker;
import com.earth2me.essentials.userstorage.IUserMap;
import net.ess3.provider.Provider;
import net.ess3.nms.refl.providers.ReflOnlineModeProvider;
import net.ess3.provider.ContainerProvider;
import net.ess3.provider.FormattedCommandAliasProvider;
import net.ess3.provider.ItemUnbreakableProvider;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.MaterialTagProvider;
import net.ess3.provider.PersistentDataProvider;
import net.ess3.provider.SerializationProvider;
import net.ess3.provider.ServerStateProvider;
import net.ess3.provider.SignDataProvider;
import net.ess3.provider.SpawnerBlockProvider;
import net.ess3.provider.SpawnerItemProvider;
import net.ess3.provider.SyncCommandsProvider;
import net.ess3.provider.WorldInfoProvider;
import net.essentialsx.api.v2.services.BalanceTop;
import net.essentialsx.api.v2.services.mail.MailService;
import org.bukkit.Server;
@@ -68,22 +80,10 @@ public interface IEssentials extends Plugin {
int broadcastMessage(String permission, String message);
void broadcastTl(String tlKey, Object... args);
void broadcastTl(IUser sender, String tlKey, Object... args);
void broadcastTl(IUser sender, String permission, String tlKey, Object... args);
void broadcastTl(IUser sender, Predicate<IUser> shouldExclude, String tlKey, Object... args);
void broadcastTl(IUser sender, Predicate<IUser> shouldExclude, boolean parseKeywords, String tlKey, Object... args);
ISettings getSettings();
BukkitScheduler getScheduler();
List<Player> getJailedPlayers();
IJails getJails();
IWarps getWarps();
@@ -142,13 +142,33 @@ public interface IEssentials extends Plugin {
Iterable<User> getOnlineUsers();
SpawnerItemProvider getSpawnerItemProvider();
SpawnerBlockProvider getSpawnerBlockProvider();
ServerStateProvider getServerStateProvider();
MaterialTagProvider getMaterialTagProvider();
ContainerProvider getContainerProvider();
KnownCommandsProvider getKnownCommandsProvider();
SerializationProvider getSerializationProvider();
FormattedCommandAliasProvider getFormattedCommandAliasProvider();
SyncCommandsProvider getSyncCommandsProvider();
PersistentDataProvider getPersistentDataProvider();
ReflOnlineModeProvider getOnlineModeProvider();
ItemUnbreakableProvider getItemUnbreakableProvider();
WorldInfoProvider getWorldInfoProvider();
SignDataProvider getSignDataProvider();
PluginCommand getPluginCommand(String cmd);
ProviderFactory getProviders();
default <P extends Provider> P provider(final Class<P> providerClass) {
return getProviders().get(providerClass);
}
AdventureFacet getAdventureFacet();
}
@@ -3,7 +3,7 @@ package com.earth2me.essentials;
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 com.earth2me.essentials.utils.NumberUtil;
import org.bukkit.Material;
import org.bukkit.event.EventPriority;
import org.spongepowered.configurate.CommentedConfigurationNode;
@@ -19,6 +19,8 @@ import java.util.function.Predicate;
import java.util.regex.Pattern;
public interface ISettings extends IConf {
String DEBUG_FLAG_NAMESPACE = "net.essentialsx";
File getConfigFile();
boolean areSignsDisabled();
@@ -37,8 +39,6 @@ public interface ISettings extends IConf {
String getChatFormat(String group);
String getChatFormat(String group, ChatType chatType);
String getWorldAlias(String world);
int getChatRadius();
@@ -55,8 +55,6 @@ public interface ISettings extends IConf {
boolean isChatQuestionEnabled();
boolean isUsePaperChatEvent();
BigDecimal getCommandCost(IEssentialsCommand cmd);
BigDecimal getCommandCost(String label);
@@ -77,8 +75,6 @@ public interface ISettings extends IConf {
boolean isSocialSpyMessages();
boolean isSocialSpyDisplayNames();
Set<String> getMuteCommands();
@Deprecated
@@ -88,14 +84,10 @@ public interface ISettings extends IConf {
String getLocale();
boolean isPerPlayerLocale();
String getNewbieSpawn();
String getNicknamePrefix();
boolean isResetNickOnNameChange();
String getOperatorColor() throws Exception;
boolean getPerWarpPermission();
@@ -106,18 +98,12 @@ public interface ISettings extends IConf {
List<Material> getProtectList(final String configName);
List<String> getProtectListRaw(final String configName);
boolean getProtectPreventSpawn(final String creatureName);
String getProtectString(final String configName);
boolean getRespawnAtHome();
String getRandomSpawnLocation();
String getRandomRespawnLocation();
boolean isRespawnAtAnchor();
Set getMultipleHomes();
@@ -136,8 +122,6 @@ public interface ISettings extends IConf {
boolean isAlwaysTeleportSafety();
boolean isConsiderWorldHeightForTeleportSafety();
boolean isTeleportPassengerDismount();
boolean isForcePassengerTeleport();
@@ -160,6 +144,10 @@ public interface ISettings extends IConf {
boolean isDebug();
boolean isDebug(DebugFlag flag);
Long getDebugLong(DebugFlag flag);
void setDebug(boolean debug);
boolean isEcoDisabled();
@@ -187,8 +175,6 @@ public interface ISettings extends IConf {
boolean isEcoLogEnabled();
boolean isEcoLogUUIDEnabled();
boolean isEcoLogUpdateEnabled();
boolean realNamesOnList();
@@ -213,9 +199,7 @@ public interface ISettings extends IConf {
long getAutoAfk();
long getAutoAfkTimeout();
List<String> getAfkTimeoutCommands();
long getAutoAfkKick();
boolean getFreezeAfkPlayers();
@@ -225,8 +209,6 @@ public interface ISettings extends IConf {
boolean cancelAfkOnChat();
boolean cancelAfkOnFish();
boolean sleepIgnoresAfkPlayers();
boolean sleepIgnoresVanishedPlayers();
@@ -307,8 +289,6 @@ public interface ISettings extends IConf {
int getMaxUserCacheCount();
long getMaxUserCacheValueExpiry();
boolean allowSilentJoinQuit();
boolean isCustomJoinMessage();
@@ -325,8 +305,6 @@ public interface ISettings extends IConf {
boolean isCustomServerFullMessage();
boolean isCustomWhitelistMessage();
boolean isNotifyNoNewMail();
boolean isDropItemsIfFull();
@@ -359,10 +337,6 @@ public interface ISettings extends IConf {
boolean isWorldChangeFlyResetEnabled();
boolean isWorldChangePreserveFlying();
boolean isGamemodeChangePreserveFlying();
boolean isWorldChangeSpeedResetEnabled();
long getCommandCooldownMs(String label);
@@ -419,8 +393,6 @@ public interface ISettings extends IConf {
boolean logCommandBlockCommands();
boolean logConsoleCommands();
Set<Predicate<String>> getNickBlacklist();
double getMaxProjectileSpeed();
@@ -439,22 +411,6 @@ public interface ISettings extends IConf {
boolean showZeroBaltop();
String getNickRegex();
BigDecimal getMultiplier(final User user);
int getMaxItemLore();
String getPrimaryColor();
String getSecondaryColor();
BigDecimal getBaltopMinBalance();
long getBaltopMinPlaytime();
int getBaltopEntryLimit();
enum KeepInvPolicy {
KEEP,
DELETE,
@@ -467,4 +423,52 @@ public interface ISettings extends IConf {
OFF
}
// TODO: consider separating out non-bool values? or replace this with an object-mapped class?
enum DebugFlag {
GENERIC("debug.generic", true),
USERMAP_PRINT_STACK("usermap.print-stack", false),
USERMAP_MAX_WARNS("usermap.max-warns", false),
;
private final String flagKey;
private final boolean isSetByGlobal;
DebugFlag(final String flagKey, final boolean isSetByGlobal) {
this.flagKey = flagKey;
this.isSetByGlobal = isSetByGlobal;
}
public String getFlagKey() {
return flagKey;
}
public boolean isSetByGlobal() {
return isSetByGlobal;
}
public String getSystemPropertyKey() {
return DEBUG_FLAG_NAMESPACE + "." + flagKey;
}
public String getConfigKey() {
return "debug." + (flagKey.replace("debug.", ""));
}
public String getSystemPropertyValue() {
return System.getProperty(getSystemPropertyKey(), "false");
}
public boolean getSystemPropertyBoolean() {
return Boolean.parseBoolean(getSystemPropertyValue());
}
public Long getSystemPropertyLong() {
final String value = getSystemPropertyValue();
if (NumberUtil.isLong(value)) {
return Long.parseLong(value);
}
return null;
}
}
}
@@ -1,9 +1,9 @@
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;
import net.ess3.api.ITeleport;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.events.AfkStatusChangeEvent;
import net.essentialsx.api.v2.services.mail.MailMessage;
@@ -15,6 +15,7 @@ import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -32,8 +33,6 @@ 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);
@@ -70,9 +69,13 @@ public interface IUser {
* @return whether there is a teleport request
*/
@Deprecated
default boolean hasOutstandingTeleportRequest() {
return getNextTpaRequest(false, false, false) != null;
}
boolean hasOutstandingTeleportRequest();
/**
* @deprecated This API is not asynchronous. Use {@link com.earth2me.essentials.api.IAsyncTeleport IAsyncTeleport} with {@link IUser#getAsyncTeleport()}
*/
@Deprecated
ITeleport getTeleport();
IAsyncTeleport getAsyncTeleport();
@@ -139,14 +142,6 @@ public interface IUser {
void sendMessage(String message);
void sendComponent(ComponentHolder component);
ComponentHolder tlComponent(String tlKey, Object... args);
String playerTl(String tlKey, Object... args);
void sendTl(String tlKey, Object... args);
/*
* UserData
*/
@@ -178,17 +173,6 @@ 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();
@@ -5,7 +5,6 @@ import com.earth2me.essentials.config.EssentialsConfiguration;
import com.earth2me.essentials.config.entities.LazyLocation;
import net.ess3.api.IEssentials;
import net.ess3.api.IUser;
import net.ess3.api.TranslatableException;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@@ -36,10 +35,10 @@ import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public class Jails implements net.ess3.api.IJails {
private static boolean enabled = false;
private static transient boolean enabled = false;
private final IEssentials ess;
private final EssentialsConfiguration config;
private final Map<String, LazyLocation> jails = new HashMap<>();
@@ -103,17 +102,17 @@ public class Jails implements net.ess3.api.IJails {
@Override
public Location getJail(String jailName) throws Exception {
if (jailName == null) {
throw new TranslatableException("jailNotExist");
throw new Exception(tl("jailNotExist"));
}
jailName = jailName.toLowerCase(Locale.ENGLISH);
synchronized (jails) {
if (!jails.containsKey(jailName)) {
throw new TranslatableException("jailNotExist");
throw new Exception(tl("jailNotExist"));
}
final Location location = jails.get(jailName).location();
if (location == null) {
throw new TranslatableException("jailWorldNotExist");
throw new Exception(tl("jailWorldNotExist"));
}
return location;
}
@@ -141,6 +140,28 @@ public class Jails implements net.ess3.api.IJails {
}
}
/**
* @deprecated This method does not use asynchronous teleportation. Use {@link Jails#sendToJail(IUser, String, CompletableFuture)}
*/
@SuppressWarnings("deprecation")
@Override
@Deprecated
public void sendToJail(final IUser user, String jail) throws Exception {
if (jail == null || jail.isEmpty()) {
return;
}
jail = jail.toLowerCase(Locale.ENGLISH);
synchronized (jails) {
if (jails.containsKey(jail)) {
if (user.getBase().isOnline()) {
user.getTeleport().now(getJail(jail), false, TeleportCause.COMMAND);
}
user.setJail(jail);
}
}
}
@Override
public void sendToJail(final IUser user, final String jailName, final CompletableFuture<Boolean> future) throws Exception {
if (jailName == null || jailName.isEmpty()) {
@@ -272,9 +293,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, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())), ex);
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
} else {
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())));
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
}
}
}
@@ -294,12 +315,12 @@ 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, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())), ex);
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
} else {
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())));
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
}
}
user.sendTl("jailMessage");
user.sendMessage(tl("jailMessage"));
}
@EventHandler(priority = EventPriority.HIGHEST)
@@ -318,13 +339,13 @@ 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, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())), ex);
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
} else {
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage())));
ess.getLogger().log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
}
return false;
});
future.thenAccept(success -> user.sendTl("jailMessage"));
future.thenAccept(success -> user.sendMessage(tl("jailMessage")));
try {
sendToJail(user, user.getJail(), future);
@@ -9,10 +9,7 @@ import com.earth2me.essentials.textreader.SimpleTextInput;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.KitClaimEvent;
import net.ess3.provider.SerializationProvider;
import net.essentialsx.api.v2.events.KitPreExpandItemsEvent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
@@ -25,10 +22,9 @@ 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;
import static com.earth2me.essentials.I18n.tl;
public class Kit {
final IEssentials ess;
@@ -43,7 +39,7 @@ public class Kit {
this.charge = new Trade("kit-" + kitName, new Trade("kit-kit", ess), ess);
if (kit == null) {
throw new TranslatableException("kitNotFound");
throw new Exception(tl("kitNotFound"));
}
}
@@ -53,7 +49,7 @@ public class Kit {
public void checkPerms(final User user) throws Exception {
if (!user.isAuthorized("essentials.kits." + kitName)) {
throw new TranslatableException("noKitPermission", "essentials.kits." + kitName);
throw new Exception(tl("noKitPermission", "essentials.kits." + kitName));
}
}
@@ -62,10 +58,10 @@ public class Kit {
if (nextUse == 0L) {
} else if (nextUse < 0L) {
user.sendTl("kitOnce");
user.sendMessage(tl("kitOnce"));
throw new NoChargeException();
} else {
user.sendTl("kitTimed", DateUtil.formatDateDiff(nextUse));
user.sendMessage(tl("kitTimed", DateUtil.formatDateDiff(nextUse)));
throw new NoChargeException();
}
}
@@ -99,7 +95,7 @@ public class Kit {
// Make sure delay is valid
delay = kit.containsKey("delay") ? ((Number) kit.get("delay")).doubleValue() : 0.0d;
} catch (final Exception e) {
throw new TranslatableException("kitError2");
throw new Exception(tl("kitError2"));
}
// When was the last kit used?
@@ -133,7 +129,7 @@ public class Kit {
public List<String> getItems() throws Exception {
if (kit == null) {
throw new TranslatableException("kitNotFound");
throw new Exception(tl("kitNotFound"));
}
try {
final List<String> itemList = new ArrayList<>();
@@ -151,7 +147,7 @@ public class Kit {
throw new Exception("Invalid item list");
} catch (final Exception e) {
ess.getLogger().log(Level.WARNING, "Error parsing kit " + kitName + ": " + e.getMessage());
throw new TranslatableException(e,"kitError2");
throw new Exception(tl("kitError2"), e);
}
}
@@ -174,11 +170,10 @@ 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 (String kitItem : output.getLines()) {
for (final String kitItem : output.getLines()) {
if (kitItem.startsWith("$") || kitItem.startsWith(currencySymbol)) {
moneyQueue.add(NumberUtil.sanitizeCurrencyString(kitItem, ess));
continue;
@@ -192,25 +187,14 @@ 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, ess.getAdventureFacet().miniToLegacy(tlLiteral("kitError3", kitName, user.getName())));
if (ess.getSerializationProvider() == null) {
ess.getLogger().log(Level.WARNING, tl("kitError3", kitName, user.getName()));
continue;
}
stack = serializationProvider.deserializeItem(Base64Coder.decodeLines(kitItem.substring(1)));
stack = ess.getSerializationProvider().deserializeItem(Base64Coder.decodeLines(kitItem.substring(1)));
} else {
final String[] parts = kitItem.split(" +");
final ItemStack parseStack = ess.getItemDb().get(parts[0], parts.length > 1 ? Integer.parseInt(parts[1]) : 1);
@@ -229,35 +213,18 @@ public class Kit {
stack = metaStack.getItemStack();
}
if (itemSlot == -1 || itemsWithSlot.containsKey(itemSlot)) {
itemList.add(stack);
} else {
itemsWithSlot.put(itemSlot, stack);
}
itemList.add(stack);
}
final int maxStackSize = user.isAuthorized("essentials.oversizedstacks") ? ess.getSettings().getOversizedStackSize() : 0;
final boolean isDropItemsIfFull = ess.getSettings().isDropItemsIfFull();
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[] totalItemsArray = totalItems.toArray(new ItemStack[0]);
if (!isDropItemsIfFull && !Inventories.hasSpace(user.getBase(), maxStackSize, autoEquip, totalItemsArray)) {
user.sendTl("kitInvFullNoDrop");
final ItemStack[] itemArray = itemList.toArray(new ItemStack[0]);
if (!isDropItemsIfFull && !Inventories.hasSpace(user.getBase(), maxStackSize, autoEquip, itemArray)) {
user.sendMessage(tl("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 :(
@@ -266,10 +233,10 @@ public class Kit {
for (final ItemStack itemStack : leftover.values()) {
int spillAmount = itemStack.getAmount();
if (maxStackSize != 0) {
itemStack.setAmount(Math.min(spillAmount, itemStack.getMaxStackSize()));
}
while (spillAmount > 0) {
if (maxStackSize != 0) {
itemStack.setAmount(Math.min(spillAmount, itemStack.getMaxStackSize()));
}
user.getWorld().dropItemNaturally(user.getLocation(), itemStack);
spillAmount -= itemStack.getAmount();
}
@@ -291,12 +258,12 @@ public class Kit {
}
if (spew) {
user.sendTl("kitInvFull");
user.sendMessage(tl("kitInvFull"));
}
} catch (final Exception e) {
user.getBase().updateInventory();
ess.getLogger().log(Level.WARNING, e.getMessage());
throw new TranslatableException(e, "kitError2");
throw new Exception(tl("kitError2"), e);
}
return true;
}
@@ -3,7 +3,6 @@ package com.earth2me.essentials;
import com.earth2me.essentials.config.ConfigurateUtil;
import com.earth2me.essentials.config.EssentialsConfiguration;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.TranslatableException;
import org.spongepowered.configurate.CommentedConfigurationNode;
import java.io.File;
@@ -15,6 +14,7 @@ import java.util.Map;
import java.util.Set;
import static com.earth2me.essentials.I18n.capitalCase;
import static com.earth2me.essentials.I18n.tl;
public class Kits implements IConf {
private final IEssentials ess;
@@ -145,7 +145,7 @@ public class Kits implements IConf {
String name = capitalCase(kitItem);
final BigDecimal costPrice = new Trade("kit-" + kitItem.toLowerCase(Locale.ENGLISH), ess).getCommandCost(user);
if (costPrice.signum() > 0) {
cost = user.playerTl("kitCost", NumberUtil.displayCurrency(costPrice, ess));
cost = tl("kitCost", NumberUtil.displayCurrency(costPrice, ess));
}
final Kit kit = new Kit(kitItem, ess);
@@ -153,7 +153,7 @@ public class Kits implements IConf {
if (nextUse == -1 && ess.getSettings().isSkippingUsedOneTimeKitsFromKitList()) {
continue;
} else if (nextUse != 0) {
name = user.playerTl("kitDelay", name);
name = tl("kitDelay", name);
}
list.append(" ").append(name).append(cost);
@@ -161,7 +161,7 @@ public class Kits implements IConf {
}
return list.toString().trim();
} catch (final Exception ex) {
throw new TranslatableException(ex, "kitError");
throw new Exception(tl("kitError"), ex);
}
}
@@ -12,7 +12,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public class MailServiceImpl implements MailService {
private final transient ThreadLocal<SimpleDateFormat> df = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy/MM/dd HH:mm"));
@@ -52,28 +52,10 @@ public class MailServiceImpl implements MailService {
public String getMailLine(MailMessage mail) {
final String message = mail.getMessage();
if (mail.isLegacy()) {
return tlLiteral("mailMessage", message);
return tl("mailMessage", message);
}
final String expire = mail.getTimeExpire() != 0 ? "Timed" : "";
return tlLiteral((mail.isRead() ? "mailFormatNewRead" : "mailFormatNew") + expire, df.get().format(new Date(mail.getTimeSent())), mail.getSenderUsername(), message);
}
@Override
public String getMailTlKey(MailMessage message) {
if (message.isLegacy()) {
return "mailMessage";
}
final String expire = message.getTimeExpire() != 0 ? "Timed" : "";
return (message.isRead() ? "mailFormatNewRead" : "mailFormatNew") + expire;
}
@Override
public Object[] getMailTlArgs(MailMessage message) {
if (message.isLegacy()) {
return new Object[] {message.getMessage()};
}
return new Object[] {df.get().format(new Date(message.getTimeSent())), message.getSenderUsername(), message.getMessage()};
return tl((mail.isRead() ? "mailFormatNewRead" : "mailFormatNew") + expire, df.get().format(new Date(mail.getTimeSent())), mail.getSenderUsername(), message);
}
}
@@ -22,7 +22,7 @@ import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public class ManagedFile {
private static final int BUFFERSIZE = 1024 * 8;
@@ -45,7 +45,7 @@ public class ManagedFile {
try {
copyResourceAscii("/" + filename, file);
} catch (final IOException ex) {
Essentials.getWrappedLogger().log(Level.SEVERE, ess.getAdventureFacet().miniToLegacy(tlLiteral("itemsCsvNotLoaded", filename)), ex);
Essentials.getWrappedLogger().log(Level.SEVERE, tl("itemsCsvNotLoaded", filename), ex);
}
}
}
@@ -1,20 +1,15 @@
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;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.base.Joiner;
import net.ess3.api.IEssentials;
import net.ess3.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;
import org.bukkit.FireworkEffect;
@@ -22,8 +17,6 @@ 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;
@@ -36,10 +29,7 @@ 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.Potion;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
@@ -52,10 +42,11 @@ import java.util.Map;
import java.util.logging.Level;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
public class MetaItemStack {
private static final Map<String, DyeColor> colorMap = new HashMap<>();
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 {
@@ -87,32 +78,6 @@ 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;
@@ -166,30 +131,21 @@ public class MetaItemStack {
}
public boolean canSpawn(final IEssentials ess) {
if (VersionUtil.PRE_FLATTENING) {
try {
ess.getServer().getUnsafe().modifyItemStack(stack.clone(), "{}");
return true;
} catch (final NoSuchMethodError nsme) {
return true;
} catch (final Throwable npe) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "Itemstack is invalid", npe);
}
return false;
try {
ess.getServer().getUnsafe().modifyItemStack(stack.clone(), "{}");
return true;
} catch (final NoSuchMethodError nsme) {
return true;
} catch (final Throwable npe) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "Itemstack is invalid", npe);
}
return false;
}
return stack.getType().isItem();
}
public void parseStringMeta(final CommandSource sender, final boolean allowUnsafe, final String[] string, final int fromArg, final IEssentials ess) throws Exception {
final boolean nbtIsKill = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_6_R01);
if (string[fromArg].startsWith("{") && hasMetaPermission(sender, "vanilla", false, true, ess)) {
if (nbtIsKill) {
throw new TranslatableException("noMetaNbtKill");
}
try {
stack = ess.getServer().getUnsafe().modifyItemStack(stack, Joiner.on(' ').join(Arrays.asList(string).subList(fromArg, string.length)));
} catch (final NullPointerException npe) {
@@ -197,28 +153,7 @@ public class MetaItemStack {
ess.getLogger().log(Level.INFO, "Itemstack is invalid", npe);
}
} catch (final NoSuchMethodError nsme) {
throw new TranslatableException(nsme, "noMetaJson");
} catch (final Throwable throwable) {
throw new Exception(throwable.getMessage(), throwable);
}
} else if (string[fromArg].startsWith("[") && hasMetaPermission(sender, "vanilla", false, true, ess)) {
if (!nbtIsKill) {
throw new TranslatableException("noMetaComponents");
}
try {
final String components = Joiner.on(' ').join(Arrays.asList(string).subList(fromArg, string.length));
// 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);
}
throw new Exception(tl("noMetaJson"), nsme);
} catch (final Throwable throwable) {
throw new Exception(throwable.getMessage(), throwable);
}
@@ -228,19 +163,19 @@ public class MetaItemStack {
}
if (validFirework) {
if (!hasMetaPermission(sender, "firework", true, true, ess)) {
throw new TranslatableException("noMetaFirework");
throw new Exception(tl("noMetaFirework"));
}
final FireworkEffect effect = builder.build();
final FireworkMeta fmeta = (FireworkMeta) stack.getItemMeta();
fmeta.addEffect(effect);
if (fmeta.getEffects().size() > 1 && !hasMetaPermission(sender, "firework-multiple", true, true, ess)) {
throw new TranslatableException("multipleCharges");
throw new Exception(tl("multipleCharges"));
}
stack.setItemMeta(fmeta);
}
if (validFireworkCharge) {
if (!hasMetaPermission(sender, "firework", true, true, ess)) {
throw new TranslatableException("noMetaFirework");
throw new Exception(tl("noMetaFirework"));
}
final FireworkEffect effect = builder.build();
final FireworkEffectMeta meta = (FireworkEffectMeta) stack.getItemMeta();
@@ -256,26 +191,21 @@ public class MetaItemStack {
return;
}
final Material WRITTEN_BOOK = EnumUtil.getMaterial("WRITTEN_BOOK");
if (split.length > 1 && split[0].equalsIgnoreCase("name") && hasMetaPermission(sender, "name", false, true, ess)) {
final String displayName = FormatUtil.replaceFormat(split[1].replaceAll("(?<!\\\\)_", " ").replace("\\_", "_"));
final String displayName = FormatUtil.replaceFormat(split[1].replace('_', ' '));
final ItemMeta meta = stack.getItemMeta();
meta.setDisplayName(displayName);
stack.setItemMeta(meta);
} else if (split.length > 1 && (split[0].equalsIgnoreCase("lore") || split[0].equalsIgnoreCase("desc")) && hasMetaPermission(sender, "lore", false, true, ess)) {
final List<String> lore = new ArrayList<>();
for (final String line : split[1].split("(?<!\\\\)\\|")) {
lore.add(FormatUtil.replaceFormat(line.replaceAll("(?<!\\\\)_", " ").replace("\\_", "_").replace("\\|", "|")));
lore.add(FormatUtil.replaceFormat(line.replace('_', ' ').replace("\\|", "|")));
}
final ItemMeta meta = stack.getItemMeta();
meta.setLore(lore);
stack.setItemMeta(meta);
} else if ((split[0].equalsIgnoreCase("custom-model-data") || split[0].equalsIgnoreCase("cmd")) && hasMetaPermission(sender, "custom-model-data", false, true, ess)) {
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_14_R01)) {
final int value = split.length <= 1 ? 0 : Integer.parseInt(split[1]);
final ItemMeta meta = stack.getItemMeta();
meta.setCustomModelData(value);
stack.setItemMeta(meta);
}
} else if (split[0].equalsIgnoreCase("unbreakable") && hasMetaPermission(sender, "unbreakable", false, true, ess)) {
final boolean value = split.length <= 1 || Boolean.parseBoolean(split[1]);
setUnbreakable(ess, stack, value);
@@ -284,49 +214,33 @@ public class MetaItemStack {
final String owner = split[1];
setSkullOwner(ess, stack, owner);
} else {
throw new TranslatableException("onlyPlayerSkulls");
throw new Exception(tl("onlyPlayerSkulls"));
}
} else if (split.length > 1 && split[0].equalsIgnoreCase("book") && MaterialUtil.isEditableBook(stack.getType()) && (hasMetaPermission(sender, "book", true, true, ess) || hasMetaPermission(sender, "chapter-" + split[1].toLowerCase(Locale.ENGLISH), true, true, ess))) {
} else if (split.length > 1 && split[0].equalsIgnoreCase("book") && MaterialUtil.isEditableBook(stack.getType()) && (hasMetaPermission(sender, "book",true, true, ess) || hasMetaPermission(sender, "chapter-" + split[1].toLowerCase(Locale.ENGLISH), true, true, ess))) {
final BookMeta meta = (BookMeta) stack.getItemMeta();
final IText input = new BookInput("book", true, ess);
final BookPager pager = new BookPager(input);
// This fix only applies to written books - which require an author and a title. https://bugs.mojang.com/browse/MC-59153
if (stack.getType() == Material.WRITTEN_BOOK) {
if (!meta.hasAuthor()) {
// The sender can be null when this method is called from {@link com.earth2me.essentials.signs.EssentialsSign#getItemMeta(ItemStack, String, IEssentials)}
meta.setAuthor(sender == null ? Console.getInstance().getDisplayName() : sender.getPlayer().getName());
}
if (!meta.hasTitle()) {
final String title = FormatUtil.replaceFormat(split[1].replace('_', ' '));
meta.setTitle(title.length() > 32 ? title.substring(0, 32) : title);
}
}
final List<String> pages = pager.getPages(split[1]);
meta.setPages(pages);
stack.setItemMeta(meta);
} else if (split.length > 1 && split[0].equalsIgnoreCase("author") && stack.getType() == Material.WRITTEN_BOOK && hasMetaPermission(sender, "author", false, true, ess)) {
} else if (split.length > 1 && split[0].equalsIgnoreCase("author") && stack.getType() == WRITTEN_BOOK && hasMetaPermission(sender, "author", false, true, ess)) {
final String author = FormatUtil.replaceFormat(split[1]);
final BookMeta meta = (BookMeta) stack.getItemMeta();
meta.setAuthor(author);
stack.setItemMeta(meta);
} else if (split.length > 1 && split[0].equalsIgnoreCase("title") && stack.getType() == Material.WRITTEN_BOOK && hasMetaPermission(sender, "title", false, true, ess)) {
final String title = FormatUtil.replaceFormat(split[1].replaceAll("(?<!\\\\)_", " ").replace("\\_", "_"));
} else if (split.length > 1 && split[0].equalsIgnoreCase("title") && stack.getType() == WRITTEN_BOOK && hasMetaPermission(sender, "title", false, true, ess)) {
final String title = FormatUtil.replaceFormat(split[1].replace('_', ' '));
final BookMeta meta = (BookMeta) stack.getItemMeta();
meta.setTitle(title);
stack.setItemMeta(meta);
} else if (split.length > 1 && split[0].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");
}
} 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;
final BookMeta meta = (BookMeta) stack.getItemMeta();
final List<String> pages = meta.hasPages() ? new ArrayList<>(meta.getPages()) : new ArrayList<>();
final List<String> lines = new ArrayList<>();
for (final String line : split[1].split("(?<!\\\\)\\|")) {
lines.add(FormatUtil.replaceFormat(line.replaceAll("(?<!\\\\)_", " ").replace("\\_", "_").replace("\\|", "|")));
lines.add(FormatUtil.replaceFormat(line.replace('_', ' ').replace("\\|", "|")));
}
final String content = String.join("\n", lines);
if (page >= pages.size()) {
@@ -387,43 +301,17 @@ public class MetaItemStack {
meta.setColor(Color.fromRGB(red, green, blue));
stack.setItemMeta(meta);
} else {
throw new TranslatableException("leatherSyntax");
throw new Exception(tl("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) {
throw new TranslatableException("invalidItemFlagMeta", string);
throw new Exception(tl("invalidItemFlagMeta", string));
}
final String[] split = separate[1].split(",");
@@ -438,7 +326,7 @@ public class MetaItemStack {
}
if (meta.getItemFlags().isEmpty()) {
throw new TranslatableException("invalidItemFlagMeta", string);
throw new Exception(tl("invalidItemFlagMeta", string));
}
stack.setItemMeta(meta);
@@ -461,7 +349,7 @@ public class MetaItemStack {
validFireworkCharge = true;
primaryColors.add(Color.fromRGB(Integer.decode(color)));
} else {
throw new TranslatableException("invalidFireworkFormat", split[1], split[0]);
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
}
}
builder.withColor(primaryColors);
@@ -471,7 +359,7 @@ public class MetaItemStack {
if (fireworkShape.containsKey(split[1].toUpperCase())) {
finalEffect = fireworkShape.get(split[1].toUpperCase());
} else {
throw new TranslatableException("invalidFireworkFormat", split[1], split[0]);
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
}
if (finalEffect != null) {
builder.with(finalEffect);
@@ -485,7 +373,7 @@ public class MetaItemStack {
} else if (hexPattern.matcher(color).matches()) {
fadeColors.add(Color.fromRGB(Integer.decode(color)));
} else {
throw new TranslatableException("invalidFireworkFormat", split[1], split[0]);
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
}
}
if (!fadeColors.isEmpty()) {
@@ -499,7 +387,7 @@ public class MetaItemStack {
} else if (effect.equalsIgnoreCase("trail")) {
builder.trail(true);
} else {
throw new TranslatableException("invalidFireworkFormat", split[1], split[0]);
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
}
}
}
@@ -515,13 +403,13 @@ public class MetaItemStack {
if (split[0].equalsIgnoreCase("color") || split[0].equalsIgnoreCase("colour") || (allowShortName && split[0].equalsIgnoreCase("c"))) {
if (validFirework) {
if (!hasMetaPermission(sender, "firework", true, true, ess)) {
throw new TranslatableException("noMetaFirework");
throw new Exception(tl("noMetaFirework"));
}
final FireworkEffect effect = builder.build();
final FireworkMeta fmeta = (FireworkMeta) stack.getItemMeta();
fmeta.addEffect(effect);
if (fmeta.getEffects().size() > 1 && !hasMetaPermission(sender, "firework-multiple", true, true, ess)) {
throw new TranslatableException("multipleCharges");
throw new Exception(tl("multipleCharges"));
}
stack.setItemMeta(fmeta);
builder = FireworkEffect.builder();
@@ -537,7 +425,7 @@ public class MetaItemStack {
validFirework = true;
primaryColors.add(Color.fromRGB(Integer.decode(color)));
} else {
throw new TranslatableException("invalidFireworkFormat", split[1], split[0]);
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
}
}
builder.withColor(primaryColors);
@@ -547,7 +435,7 @@ public class MetaItemStack {
if (fireworkShape.containsKey(split[1].toUpperCase())) {
finalEffect = fireworkShape.get(split[1].toUpperCase());
} else {
throw new TranslatableException("invalidFireworkFormat", split[1], split[0]);
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
}
if (finalEffect != null) {
builder.with(finalEffect);
@@ -561,7 +449,7 @@ public class MetaItemStack {
} else if (hexPattern.matcher(color).matches()) {
fadeColors.add(Color.fromRGB(Integer.decode(color)));
} else {
throw new TranslatableException("invalidFireworkFormat", split[1], split[0]);
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
}
}
if (!fadeColors.isEmpty()) {
@@ -575,7 +463,7 @@ public class MetaItemStack {
} else if (effect.equalsIgnoreCase("trail")) {
builder.trail(true);
} else {
throw new TranslatableException("invalidFireworkFormat", split[1], split[0]);
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
}
}
}
@@ -596,10 +484,10 @@ public class MetaItemStack {
if (hasMetaPermission(sender, "potions." + pEffectType.getName().toLowerCase(Locale.ENGLISH), true, false, ess)) {
validPotionEffect = true;
} else {
throw new TranslatableException("noPotionEffectPerm", pEffectType.getName().toLowerCase(Locale.ENGLISH));
throw new Exception(tl("noPotionEffectPerm", pEffectType.getName().toLowerCase(Locale.ENGLISH)));
}
} else {
throw new TranslatableException("invalidPotionMeta", split[1]);
throw new Exception(tl("invalidPotionMeta", split[1]));
}
} else if (split[0].equalsIgnoreCase("power") || (allowShortName && split[0].equalsIgnoreCase("p"))) {
if (NumberUtil.isInt(split[1])) {
@@ -609,22 +497,21 @@ public class MetaItemStack {
power -= 1;
}
} else {
throw new TranslatableException("invalidPotionMeta", split[1]);
throw new Exception(tl("invalidPotionMeta", split[1]));
}
} else if (split[0].equalsIgnoreCase("amplifier") || (allowShortName && split[0].equalsIgnoreCase("a"))) {
if (NumberUtil.isInt(split[1])) {
validPotionPower = true;
power = Integer.parseInt(split[1]);
} else {
throw new TranslatableException("invalidPotionMeta", split[1]);
throw new Exception(tl("invalidPotionMeta", split[1]));
}
} else if (split[0].equalsIgnoreCase("duration") || (allowShortName && split[0].equalsIgnoreCase("d"))) {
if (NumberUtil.isInt(split[1])) {
validPotionDuration = true;
final int parsed = Integer.parseInt(split[1]);
duration = parsed == -1 ? -1 : parsed * 20; //Duration is in ticks by default, converted to seconds
duration = Integer.parseInt(split[1]) * 20; //Duration is in ticks by default, converted to seconds
} else {
throw new TranslatableException("invalidPotionMeta", split[1]);
throw new Exception(tl("invalidPotionMeta", split[1]));
}
} else if (split[0].equalsIgnoreCase("splash") || (allowShortName && split[0].equalsIgnoreCase("s"))) {
isSplashPotion = Boolean.parseBoolean(split[1]);
@@ -634,11 +521,21 @@ public class MetaItemStack {
final PotionMeta pmeta = (PotionMeta) stack.getItemMeta();
pEffect = pEffectType.createEffect(duration, power);
if (pmeta.getCustomEffects().size() > 1 && !hasMetaPermission(sender, "potions.multiple", true, false, ess)) {
throw new TranslatableException("multiplePotionEffects");
throw new Exception(tl("multiplePotionEffects"));
}
pmeta.addCustomEffect(pEffect, true);
stack.setItemMeta(pmeta);
ess.provider(PotionMetaProvider.class).setSplashPotion(stack, isSplashPotion);
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01)) {
if (isSplashPotion && stack.getType() != Material.SPLASH_POTION) {
stack.setType(Material.SPLASH_POTION);
} else if (!isSplashPotion && stack.getType() != Material.POTION) {
stack.setType(Material.POTION);
}
} else {
final Potion potion = Potion.fromDamage(stack.getDurability());
potion.setSplash(isSplashPotion);
potion.apply(stack);
}
resetPotionMeta();
}
}
@@ -649,7 +546,7 @@ public class MetaItemStack {
if (enchantment == null) {
return false;
}
if (hasMetaPermission(sender, "enchantments." + Enchantments.getRealName(enchantment), false, false, ess)) {
if (hasMetaPermission(sender, "enchantments." + enchantment.getName().toLowerCase(Locale.ENGLISH), false, false, ess)) {
int level = -1;
if (split.length > 1) {
try {
@@ -669,7 +566,7 @@ public class MetaItemStack {
public void addEnchantment(final CommandSource sender, final boolean allowUnsafe, final Enchantment enchantment, final int level) throws Exception {
if (enchantment == null) {
throw new TranslatableException("enchantmentNotFound");
throw new Exception(tl("enchantmentNotFound"));
}
try {
if (stack.getType().equals(Material.ENCHANTED_BOOK)) {
@@ -692,7 +589,7 @@ public class MetaItemStack {
}
}
} catch (final Exception ex) {
throw new Exception("Enchantment " + Enchantments.getRealName(enchantment) + ": " + ex.getMessage(), ex);
throw new Exception("Enchantment " + enchantment.getName() + ": " + ex.getMessage(), ex);
}
}
@@ -702,10 +599,10 @@ public class MetaItemStack {
return null;
}
final String enchantmentName = Enchantments.getRealName(enchantment);
final String enchantmentName = enchantment.getName().toLowerCase(Locale.ENGLISH);
if (!hasMetaPermission(user, "enchantments." + enchantmentName, true, false)) {
throw new TranslatableException("enchantmentPerm", enchantmentName);
throw new Exception(tl("enchantmentPerm", enchantmentName));
}
return enchantment;
}
@@ -715,18 +612,23 @@ public class MetaItemStack {
final String[] split = splitPattern.split(string, 2);
if (split.length < 2) {
throw new TranslatableException("invalidBanner", split[1]);
throw new Exception(tl("invalidBanner", split[1]));
}
final PatternType patternType = ess.provider(PatternTypeProvider.class).getPatternTypeByIdentifier(split[0]);
PatternType patternType = null;
try {
patternType = PatternType.valueOf(split[0]);
} catch (final Exception ignored) {
}
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));
meta.setBaseColor(DyeColor.getByColor(color));
} else if (patternType != null) {
final PatternType type = PatternType.valueOf(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, patternType);
final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type);
meta.addPattern(pattern);
}
@@ -735,10 +637,14 @@ public class MetaItemStack {
final String[] split = splitPattern.split(string, 2);
if (split.length < 2) {
throw new TranslatableException("invalidBanner", split[1]);
throw new Exception(tl("invalidBanner", split[1]));
}
final PatternType patternType = ess.provider(PatternTypeProvider.class).getPatternTypeByIdentifier(split[0]);
PatternType patternType = null;
try {
patternType = PatternType.valueOf(split[0]);
} catch (final Exception ignored) {
}
// Hacky fix for accessing Shield meta - https://github.com/drtshock/Essentials/pull/745#issuecomment-234843795
final BlockStateMeta meta = (BlockStateMeta) stack.getItemMeta();
@@ -747,8 +653,9 @@ public class MetaItemStack {
final Color color = Color.fromRGB(Integer.parseInt(split[1]));
banner.setBaseColor(DyeColor.getByColor(color));
} else if (patternType != null) {
final PatternType type = PatternType.valueOf(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, patternType);
final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type);
banner.addPattern(pattern);
}
banner.update();
@@ -771,13 +678,13 @@ public class MetaItemStack {
if (graceful) {
return false;
} else {
throw new TranslatableException("noMetaPerm", metaPerm);
throw new Exception(tl("noMetaPerm", metaPerm));
}
}
private void setUnbreakable(final IEssentials ess, final ItemStack is, final boolean unbreakable) {
final ItemMeta meta = is.getItemMeta();
ess.provider(ItemUnbreakableProvider.class).setUnbreakable(meta, unbreakable);
ess.getItemUnbreakableProvider().setUnbreakable(meta, unbreakable);
is.setItemMeta(meta);
}
}
@@ -1,6 +1,5 @@
package com.earth2me.essentials;
import com.earth2me.essentials.adventure.AdventureUtil;
import com.earth2me.essentials.utils.EnumUtil;
import org.bukkit.Location;
import org.bukkit.Server;
@@ -15,7 +14,7 @@ import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
// Suffixes can be appended on the end of a mob name to make it plural
// Entities without a suffix, will default to 's'
@@ -42,32 +41,22 @@ public enum Mob {
ENDERDRAGON("EnderDragon", Enemies.ENEMY, EntityType.ENDER_DRAGON),
VILLAGER("Villager", Enemies.FRIENDLY, EntityType.VILLAGER),
BLAZE("Blaze", Enemies.ENEMY, EntityType.BLAZE),
MUSHROOMCOW("MushroomCow", Enemies.FRIENDLY, MobCompat.MOOSHROOM),
MUSHROOMCOW("MushroomCow", Enemies.FRIENDLY, EntityType.MUSHROOM_COW),
MAGMACUBE("MagmaCube", Enemies.ENEMY, EntityType.MAGMA_CUBE),
SNOWMAN("Snowman", Enemies.FRIENDLY, "", MobCompat.SNOW_GOLEM),
SNOWMAN("Snowman", Enemies.FRIENDLY, "", EntityType.SNOWMAN),
OCELOT("Ocelot", Enemies.NEUTRAL, EntityType.OCELOT),
IRONGOLEM("IronGolem", Enemies.NEUTRAL, EntityType.IRON_GOLEM),
WITHER("Wither", Enemies.ENEMY, EntityType.WITHER),
BAT("Bat", Enemies.FRIENDLY, EntityType.BAT),
WITCH("Witch", Enemies.ENEMY, EntityType.WITCH),
BOAT("Boat", Enemies.NEUTRAL, MobCompat.OAK_BOAT),
ACACIA_BOAT("AcaciaBoat", Enemies.NEUTRAL, "ACACIA_BOAT"),
DARK_OAK_BOAT("DarkOakBoat", Enemies.NEUTRAL, "DARK_OAK_BOAT"),
BIRCH_BOAT("BirchBoat", Enemies.NEUTRAL, "BIRCH_BOAT"),
JUNGLE_BOAT("JungleBoat", Enemies.NEUTRAL, "JUNGLE_BOAT"),
SPRUCE_BOAT("SpruceBoat", Enemies.NEUTRAL, "SPRUCE_BOAT"),
MANGROVE_BOAT("MangroveBoat", Enemies.NEUTRAL, "MANGROVE_BOAT"),
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"),
BOAT("Boat", Enemies.NEUTRAL, EntityType.BOAT),
MINECART("Minecart", Enemies.NEUTRAL, EntityType.MINECART),
MINECART_CHEST("ChestMinecart", Enemies.NEUTRAL, MobCompat.CHEST_MINECART),
MINECART_FURNACE("FurnaceMinecart", Enemies.NEUTRAL, MobCompat.FURNACE_MINECART),
MINECART_TNT("TNTMinecart", Enemies.NEUTRAL, MobCompat.TNT_MINECART),
MINECART_HOPPER("HopperMinecart", Enemies.NEUTRAL, MobCompat.HOPPER_MINECART),
MINECART_MOB_SPAWNER("SpawnerMinecart", Enemies.NEUTRAL, MobCompat.SPAWNER_MINECART),
ENDERCRYSTAL("EnderCrystal", Enemies.NEUTRAL, MobCompat.END_CRYSTAL),
MINECART_CHEST("ChestMinecart", Enemies.NEUTRAL, EntityType.MINECART_CHEST),
MINECART_FURNACE("FurnaceMinecart", Enemies.NEUTRAL, EntityType.MINECART_FURNACE),
MINECART_TNT("TNTMinecart", Enemies.NEUTRAL, EntityType.MINECART_TNT),
MINECART_HOPPER("HopperMinecart", Enemies.NEUTRAL, EntityType.MINECART_HOPPER),
MINECART_MOB_SPAWNER("SpawnerMinecart", Enemies.NEUTRAL, EntityType.MINECART_MOB_SPAWNER),
ENDERCRYSTAL("EnderCrystal", Enemies.NEUTRAL, EntityType.ENDER_CRYSTAL),
EXPERIENCEORB("ExperienceOrb", Enemies.NEUTRAL, "EXPERIENCE_ORB"),
ARMOR_STAND("ArmorStand", Enemies.NEUTRAL, "ARMOR_STAND"),
ENDERMITE("Endermite", Enemies.ENEMY, "ENDERMITE"),
@@ -119,31 +108,7 @@ public enum Mob {
FROG("Frog", Enemies.FRIENDLY, "FROG"),
TADPOLE("Tadpole", Enemies.FRIENDLY, "TADPOLE"),
WARDEN("Warden", Enemies.ENEMY, "WARDEN"),
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"),
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")
CHEST_BOAT("ChestBoat", Enemies.NEUTRAL, "CHEST_BOAT"),
;
private static final Map<String, Mob> hashMap = new HashMap<>();
@@ -204,7 +169,7 @@ public enum Mob {
public Entity spawn(final World world, final Server server, final Location loc) throws MobException {
final Entity entity = world.spawn(loc, this.bukkitType.getEntityClass());
if (entity == null) {
Essentials.getWrappedLogger().log(Level.WARNING, AdventureUtil.getAdventureFacet().miniToLegacy(tlLiteral("unableToSpawnMob")));
Essentials.getWrappedLogger().log(Level.WARNING, tl("unableToSpawnMob"));
throw new MobException();
}
return entity;
@@ -1,17 +1,11 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.RegistryUtil;
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;
@@ -21,18 +15,9 @@ 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;
@@ -40,21 +25,8 @@ import static com.earth2me.essentials.utils.EnumUtil.getEntityType;
public final class MobCompat {
// Constants for mob interfaces added in later versions
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;
}
@SuppressWarnings("rawtypes")
public static final Class RAIDER = ReflUtil.getClassCached("org.bukkit.entity.Raider");
// Constants for mobs added in later versions
public static final EntityType LLAMA = getEntityType("LLAMA");
@@ -69,26 +41,10 @@ public final class MobCompat {
public static final EntityType AXOLOTL = getEntityType("AXOLOTL");
public static final EntityType GOAT = getEntityType("GOAT");
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");
public static final EntityType ZOMBIFIED_PIGLIN = getEntityType("ZOMBIFIED_PIGLIN", "PIG_ZOMBIE");
public static final EntityType MOOSHROOM = getEntityType("MOOSHROOM", "MUSHROOM_COW");
public static final EntityType SNOW_GOLEM = getEntityType("SNOW_GOLEM", "SNOWMAN");
public static final EntityType CHEST_MINECART = getEntityType("CHEST_MINECART", "MINECART_CHEST");
public static final EntityType FURNACE_MINECART = getEntityType("FURNACE_MINECART", "MINECART_FURNACE");
public static final EntityType TNT_MINECART = getEntityType("TNT_MINECART", "MINECART_TNT");
public static final EntityType HOPPER_MINECART = getEntityType("HOPPER_MINECART", "MINECART_HOPPER");
public static final EntityType SPAWNER_MINECART = getEntityType("SPAWNER_MINECART", "MINECART_MOB_SPAWNER");
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() {
}
@@ -222,7 +178,7 @@ public final class MobCompat {
}
public static void setBoatVariant(final Entity entity, final BoatVariant variant) {
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_21_3_R01) || VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
return;
}
final Boat boat;
@@ -235,105 +191,10 @@ public final class MobCompat {
//noinspection deprecation
boat.setWoodType(TreeSpecies.valueOf(variant.getTreeSpecies()));
} else {
//noinspection deprecation
boat.setBoatType(Boat.Type.valueOf(variant.getBoatType()));
}
}
public static void setCamelSaddle(final Entity entity, final Player target) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_20_1_R01)) {
return;
}
if (entity instanceof Camel) {
final Camel camel = (Camel) entity;
camel.setTamed(true);
camel.setOwner(target);
camel.getInventory().setSaddle(new ItemStack(Material.SADDLE, 1));
}
}
public static void setWolfVariant(final Entity entity, final String variant) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_20_6_R01)) {
return;
}
if (entity instanceof Wolf) {
final Wolf wolf = (Wolf) entity;
//noinspection DataFlowIssue
wolf.setVariant(RegistryUtil.valueOf(Wolf.Variant.class, variant));
}
}
public static void setSalmonSize(Entity spawned, String s) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_21_3_R01)) {
return;
}
if (spawned instanceof org.bukkit.entity.Salmon) {
((Salmon) spawned).setVariant(Salmon.Variant.valueOf(s));
}
}
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"),
@@ -394,7 +255,7 @@ public final class MobCompat {
}
private Villager.Profession asEnum() {
return RegistryUtil.valueOf(Villager.Profession.class, newProfession, oldProfession);
return EnumUtil.valueOf(Villager.Profession.class, newProfession, oldProfession);
}
}
@@ -410,7 +271,6 @@ public final class MobCompat {
OAK("GENERIC", "OAK"),
SPRUCE("REDWOOD", "SPRUCE"),
MANGROVE("GENERIC", "MANGROVE"),
POPLAR("GENERIC", "POPLAR"),
;
private final String treeSpecies;
@@ -4,13 +4,11 @@ import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.TranslatableException;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.Boat;
import org.bukkit.entity.ChestedHorse;
import org.bukkit.entity.Chicken;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@@ -40,6 +38,8 @@ import java.util.Locale;
import java.util.Random;
import java.util.stream.Collectors;
import static com.earth2me.essentials.I18n.tl;
public enum MobData {
BABY_AGEABLE("baby", Ageable.class, Data.BABY, true),
@@ -55,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_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),
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),
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),
@@ -82,7 +82,6 @@ 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),
@@ -159,8 +158,8 @@ public enum MobData {
BLOCKFISH_TROPICAL_FISH("blockfish", MobCompat.TROPICAL_FISH, "tropicalfish:BLOCKFISH", true),
BETTY_TROPICAL_FISH("betty", MobCompat.TROPICAL_FISH, "tropicalfish:BETTY", true),
CLAYFISH_TROPICAL_FISH("clayfish", MobCompat.TROPICAL_FISH, "tropicalfish:CLAYFISH", true),
BROWN_MUSHROOM_COW("brown", MobCompat.MOOSHROOM, "mooshroom:BROWN", true),
RED_MUSHROOM_COW("red", MobCompat.MOOSHROOM, "mooshroom:RED", true),
BROWN_MUSHROOM_COW("brown", EntityType.MUSHROOM_COW, "mooshroom:BROWN", true),
RED_MUSHROOM_COW("red", EntityType.MUSHROOM_COW, "mooshroom:RED", true),
AGGRESSIVE_PANDA_MAIN("aggressive", MobCompat.PANDA, "pandamain:AGGRESSIVE", true),
LAZY_PANDA_MAIN("lazy", MobCompat.PANDA, "pandamain:LAZY", true),
WORRIED_PANDA_MAIN("worried", MobCompat.PANDA, "pandamain:WORRIED", true),
@@ -181,6 +180,8 @@ 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,36 +207,8 @@ 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: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),
WOODS_WOLF("woods", EntityType.WOLF, "wolf:WOODS", true),
CHESTNUT_WOLF("chestnut", EntityType.WOLF, "wolf:CHESTNUT", true),
STRIPED_WOLF("striped", EntityType.WOLF, "wolf:STRIPED", true),
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;
@@ -354,14 +327,14 @@ public enum MobData {
}
this.matched = rawData;
} catch (final Exception e) {
throw new TranslatableException(e, "sheepMalformedColor");
throw new Exception(tl("sheepMalformedColor"), e);
}
} else if (this.value.equals(Data.EXP)) {
try {
((ExperienceOrb) spawned).setExperience(Integer.parseInt(rawData));
this.matched = rawData;
} catch (final NumberFormatException e) {
throw new TranslatableException(e, "invalidNumber");
throw new Exception(tl("invalidNumber"), e);
}
} else if (this.value.equals(Data.SIZE)) {
try {
@@ -373,7 +346,7 @@ public enum MobData {
}
this.matched = rawData;
} catch (final NumberFormatException e) {
throw new TranslatableException(e, "slimeMalformedSize");
throw new Exception(tl("slimeMalformedSize"), e);
}
} else if (this.value instanceof Horse.Color) {
((Horse) spawned).setColor((Horse.Color) this.value);
@@ -414,14 +387,6 @@ public enum MobData {
}
} else if (this.value.equals(Data.GOAT_SCREAMING)) {
((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) {
@@ -457,24 +422,6 @@ public enum MobData {
case "frog":
MobCompat.setFrogVariant(spawned, split[1]);
break;
case "wolf":
MobCompat.setWolfVariant(spawned, split[1]);
break;
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());
@@ -499,9 +446,5 @@ public enum MobData {
FISH_BODY_COLOR,
FISH_PATTERN_COLOR,
GOAT_SCREAMING,
CAMELSADDLE,
CAMELHUSKSADDLE,
NAUTILUSSADDLE,
ZOMBIENAUTILUSSADDLE,
}
}
@@ -1,7 +1,6 @@
package com.earth2me.essentials;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Player;
@@ -32,11 +31,4 @@ public class PlayerExtension {
public Location getLocation() {
return base.getLocation();
}
public OfflinePlayer getOffline() {
if (base instanceof OfflinePlayerStub) {
return ((OfflinePlayerStub) base).base;
}
return base;
}
}
@@ -2,7 +2,7 @@ package com.earth2me.essentials;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.TranslatableException;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import java.util.ArrayList;
@@ -14,7 +14,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public final class PlayerList {
@@ -32,19 +32,19 @@ public final class PlayerList {
}
needComma = true;
if (user.isAfk()) {
groupString.append(tlLiteral("listAfkTag"));
groupString.append(tl("listAfkTag"));
}
if (user.isHidden()) {
groupString.append(tlLiteral("listHiddenTag"));
groupString.append(tl("listHiddenTag"));
}
user.setDisplayNick();
groupString.append(ess.getAdventureFacet().legacyToMini(user.getDisplayName()));
groupString.append(user.getDisplayName());
final String strippedNick = FormatUtil.stripFormat(user.getNickname());
if (ess.getSettings().realNamesOnList() && strippedNick != null && !strippedNick.equals(user.getName())) {
groupString.append(" ").append(tlLiteral("listRealName",user.getName()));
groupString.append(" ").append(tl("listRealName",user.getName()));
}
groupString.append("<white>");
groupString.append(ChatColor.WHITE.toString());
}
return groupString.toString();
}
@@ -55,31 +55,27 @@ public final class PlayerList {
int playerHidden = 0;
int hiddenCount = 0;
for (final User onlinePlayer : ess.getOnlineUsers()) {
if (onlinePlayer.isHidden() || (user != null && onlinePlayer.isHiddenFrom(user.getBase()))) {
if (onlinePlayer.isHidden() || (user != null && !user.getBase().canSee(onlinePlayer.getBase()))) {
playerHidden++;
if (showHidden || user != null && !onlinePlayer.isHiddenFrom(user.getBase())) {
if (showHidden || user != null && user.getBase().canSee(onlinePlayer.getBase())) {
hiddenCount++;
}
}
}
final String tlKey;
final Object[] objects;
final String online;
if (hiddenCount > 0) {
tlKey = "listAmountHidden";
objects = new Object[]{ess.getOnlinePlayers().size() - playerHidden, hiddenCount, server.getMaxPlayers()};
online = tl("listAmountHidden", ess.getOnlinePlayers().size() - playerHidden, hiddenCount, server.getMaxPlayers());
} else {
tlKey = "listAmount";
objects = new Object[]{ess.getOnlinePlayers().size() - playerHidden, server.getMaxPlayers()};
online = tl("listAmount", ess.getOnlinePlayers().size() - playerHidden, server.getMaxPlayers());
}
return user == null ? tlLiteral(tlKey, objects) : user.playerTl(tlKey, objects);
return online;
}
// Build the basic player list, divided by groups.
public static Map<String, List<User>> getPlayerLists(final IEssentials ess, final IUser sender, final boolean showHidden) {
final Map<String, List<User>> playerList = new HashMap<>();
for (final User onlineUser : ess.getOnlineUsers()) {
if ((sender == null && !showHidden && onlineUser.isHidden()) || (sender != null && !showHidden && onlineUser.isHiddenFrom(sender.getBase()))) {
if ((sender == null && !showHidden && onlineUser.isHidden()) || (sender != null && !showHidden && !sender.getBase().canSee(onlineUser.getBase()))) {
continue;
}
final String group = FormatUtil.stripFormat(FormatUtil.stripEssentialsFormat(onlineUser.getGroup().toLowerCase()));
@@ -121,7 +117,7 @@ public final class PlayerList {
users.addAll(groupUsers);
}
if (users.isEmpty()) {
throw new TranslatableException("groupDoesNotExist");
throw new Exception(tl("groupDoesNotExist"));
}
final String displayGroupName = Character.toTitleCase(groupName.charAt(0)) +
groupName.substring(1);
@@ -130,11 +126,11 @@ public final class PlayerList {
// Build the output string
public static String outputFormat(final String group, final String message) {
return tlLiteral("listGroupTag", FormatUtil.replaceFormat(group)) +
return tl("listGroupTag", FormatUtil.replaceFormat(group)) +
message;
}
public static List<String> prepareGroupedList(final IEssentials ess, final CommandSource source, final String commandLabel, final Map<String, List<User>> playerList) {
public static List<String> prepareGroupedList(final IEssentials ess, final String commandLabel, final Map<String, List<User>> playerList) {
final List<String> output = new ArrayList<>();
final Set<String> configGroups = ess.getSettings().getListGroupConfig().keySet();
@@ -167,9 +163,7 @@ public final class PlayerList {
outputUserList = new ArrayList<>(matchedList);
final int limit = Integer.parseInt(groupValue);
if (matchedList.size() > limit) {
final String tlKey = "groupNumber";
final Object[] objects = {matchedList.size(), commandLabel, FormatUtil.stripFormat(configGroup)};
output.add(outputFormat(oConfigGroup, source == null ? tlLiteral(tlKey, objects) : source.tl(tlKey, objects)));
output.add(outputFormat(oConfigGroup, tl("groupNumber", matchedList.size(), commandLabel, FormatUtil.stripFormat(configGroup))));
} else {
output.add(outputFormat(oConfigGroup, listUsers(ess, outputUserList, ", ")));
}
@@ -209,7 +203,7 @@ public final class PlayerList {
String groupName = asterisk.isEmpty() ? users.get(0).getGroup() : onlineGroup;
if (ess.getPermissionsHandler().getName().equals("ConfigPermissions")) {
groupName = source == null ? tlLiteral("connectedPlayers") : source.tl("connectedPlayers");
groupName = tl("connectedPlayers");
}
if (users == null || users.isEmpty()) {
continue;
@@ -1,7 +1,6 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.RegistryUtil;
import org.bukkit.potion.PotionEffectType;
import java.util.HashMap;
@@ -22,68 +21,50 @@ public final class Potions {
ALIASPOTIONS.put("sprint", PotionEffectType.SPEED);
ALIASPOTIONS.put("swift", PotionEffectType.SPEED);
final PotionEffectType SLOWNESS = RegistryUtil.valueOf(PotionEffectType.class, "SLOW", "SLOWNESS");
POTIONS.put("slowness", PotionEffectType.SLOW);
ALIASPOTIONS.put("slow", PotionEffectType.SLOW);
ALIASPOTIONS.put("sluggish", PotionEffectType.SLOW);
POTIONS.put("slowness", SLOWNESS);
ALIASPOTIONS.put("slow", SLOWNESS);
ALIASPOTIONS.put("sluggish", SLOWNESS);
POTIONS.put("haste", PotionEffectType.FAST_DIGGING);
ALIASPOTIONS.put("superpick", PotionEffectType.FAST_DIGGING);
ALIASPOTIONS.put("quickmine", PotionEffectType.FAST_DIGGING);
ALIASPOTIONS.put("digspeed", PotionEffectType.FAST_DIGGING);
ALIASPOTIONS.put("digfast", PotionEffectType.FAST_DIGGING);
ALIASPOTIONS.put("sharp", PotionEffectType.FAST_DIGGING);
final PotionEffectType HASTE = RegistryUtil.valueOf(PotionEffectType.class, "FAST_DIGGING", "HASTE");
POTIONS.put("fatigue", PotionEffectType.SLOW_DIGGING);
ALIASPOTIONS.put("slow", PotionEffectType.SLOW_DIGGING);
ALIASPOTIONS.put("dull", PotionEffectType.SLOW_DIGGING);
POTIONS.put("haste", HASTE);
ALIASPOTIONS.put("superpick", HASTE);
ALIASPOTIONS.put("quickmine", HASTE);
ALIASPOTIONS.put("digspeed", HASTE);
ALIASPOTIONS.put("digfast", HASTE);
ALIASPOTIONS.put("sharp", HASTE);
POTIONS.put("strength", PotionEffectType.INCREASE_DAMAGE);
ALIASPOTIONS.put("strong", PotionEffectType.INCREASE_DAMAGE);
ALIASPOTIONS.put("bull", PotionEffectType.INCREASE_DAMAGE);
ALIASPOTIONS.put("attack", PotionEffectType.INCREASE_DAMAGE);
final PotionEffectType MINING_FATIGUE = RegistryUtil.valueOf(PotionEffectType.class, "SLOW_DIGGING", "MINING_FATIGUE");
POTIONS.put("heal", PotionEffectType.HEAL);
ALIASPOTIONS.put("healthy", PotionEffectType.HEAL);
ALIASPOTIONS.put("instaheal", PotionEffectType.HEAL);
POTIONS.put("fatigue", MINING_FATIGUE);
ALIASPOTIONS.put("slow", MINING_FATIGUE);
ALIASPOTIONS.put("dull", MINING_FATIGUE);
POTIONS.put("harm", PotionEffectType.HARM);
ALIASPOTIONS.put("harming", PotionEffectType.HARM);
ALIASPOTIONS.put("injure", PotionEffectType.HARM);
ALIASPOTIONS.put("damage", PotionEffectType.HARM);
ALIASPOTIONS.put("inflict", PotionEffectType.HARM);
final PotionEffectType STRENGTH = RegistryUtil.valueOf(PotionEffectType.class, "INCREASE_DAMAGE", "STRENGTH");
POTIONS.put("jump", PotionEffectType.JUMP);
ALIASPOTIONS.put("leap", PotionEffectType.JUMP);
POTIONS.put("strength", STRENGTH);
ALIASPOTIONS.put("strong", STRENGTH);
ALIASPOTIONS.put("bull", STRENGTH);
ALIASPOTIONS.put("attack", STRENGTH);
final PotionEffectType INSTANT_HEALTH = RegistryUtil.valueOf(PotionEffectType.class, "HEAL", "INSTANT_HEALTH");
POTIONS.put("heal", INSTANT_HEALTH);
ALIASPOTIONS.put("healthy", INSTANT_HEALTH);
ALIASPOTIONS.put("instaheal", INSTANT_HEALTH);
final PotionEffectType INSTANT_DAMAGE = RegistryUtil.valueOf(PotionEffectType.class, "HARM", "INSTANT_DAMAGE");
POTIONS.put("harm", INSTANT_DAMAGE);
ALIASPOTIONS.put("harming", INSTANT_DAMAGE);
ALIASPOTIONS.put("injure", INSTANT_DAMAGE);
ALIASPOTIONS.put("damage", INSTANT_DAMAGE);
ALIASPOTIONS.put("inflict", INSTANT_DAMAGE);
final PotionEffectType JUMP_BOOST = RegistryUtil.valueOf(PotionEffectType.class, "JUMP", "JUMP_BOOST");
POTIONS.put("jump", JUMP_BOOST);
ALIASPOTIONS.put("leap", JUMP_BOOST);
final PotionEffectType NAUSEA = RegistryUtil.valueOf(PotionEffectType.class, "CONFUSION", "NAUSEA");
POTIONS.put("nausea", NAUSEA);
ALIASPOTIONS.put("sick", NAUSEA);
ALIASPOTIONS.put("sickness", NAUSEA);
ALIASPOTIONS.put("confusion", NAUSEA);
POTIONS.put("nausea", PotionEffectType.CONFUSION);
ALIASPOTIONS.put("sick", PotionEffectType.CONFUSION);
ALIASPOTIONS.put("sickness", PotionEffectType.CONFUSION);
ALIASPOTIONS.put("confusion", PotionEffectType.CONFUSION);
POTIONS.put("regeneration", PotionEffectType.REGENERATION);
ALIASPOTIONS.put("regen", PotionEffectType.REGENERATION);
final PotionEffectType RESISTANCE = RegistryUtil.valueOf(PotionEffectType.class, "DAMAGE_RESISTANCE", "RESISTANCE");
POTIONS.put("resistance", RESISTANCE);
ALIASPOTIONS.put("dmgresist", RESISTANCE);
ALIASPOTIONS.put("armor", RESISTANCE);
POTIONS.put("resistance", PotionEffectType.DAMAGE_RESISTANCE);
ALIASPOTIONS.put("dmgresist", PotionEffectType.DAMAGE_RESISTANCE);
ALIASPOTIONS.put("armor", PotionEffectType.DAMAGE_RESISTANCE);
POTIONS.put("fireresist", PotionEffectType.FIRE_RESISTANCE);
ALIASPOTIONS.put("fireresistance", PotionEffectType.FIRE_RESISTANCE);
@@ -144,31 +125,6 @@ public final class Potions {
POTIONS.put("unluck", PotionEffectType.UNLUCK);
} catch (final Throwable ignored) {
}
// 1.21
try {
POTIONS.put("infested", PotionEffectType.INFESTED);
ALIASPOTIONS.put("silverfish", PotionEffectType.INFESTED);
POTIONS.put("oozing", PotionEffectType.OOZING);
ALIASPOTIONS.put("ooze", PotionEffectType.OOZING);
POTIONS.put("weaving", PotionEffectType.WEAVING);
ALIASPOTIONS.put("weave", PotionEffectType.WEAVING);
POTIONS.put("windcharged", PotionEffectType.WIND_CHARGED);
ALIASPOTIONS.put("windcharge", PotionEffectType.WIND_CHARGED);
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() {
@@ -1,137 +0,0 @@
package com.earth2me.essentials;
import io.papermc.lib.PaperLib;
import net.ess3.provider.Provider;
import net.essentialsx.providers.NullableProvider;
import net.essentialsx.providers.ProviderData;
import net.essentialsx.providers.ProviderTest;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
public class ProviderFactory {
private final Map<Class<? extends Provider>, Provider> providers = new HashMap<>();
private final Map<Class<? extends Provider>, List<Class<? extends Provider>>> registeredProviders = new HashMap<>();
private final Essentials essentials;
public ProviderFactory(final Essentials essentials) {
this.essentials = essentials;
}
/**
* Gets the provider which has been selected for the given type.
* @param providerClass The provider type.
* @return the provider or null if no provider could be selected for that type.
*/
public <P extends Provider> P get(final Class<P> providerClass) {
final Provider provider = providers.get(providerClass);
if (provider == null) {
return null;
}
//noinspection unchecked
return (P) provider;
}
@SafeVarargs
public final void registerProvider(final Class<? extends Provider>... toRegister) {
for (final Class<? extends Provider> provider : toRegister) {
final Class<?> superclass = provider.getInterfaces().length > 0 ? provider.getInterfaces()[0] : provider.getSuperclass();
if (Provider.class.isAssignableFrom(superclass)) {
//noinspection unchecked
registeredProviders.computeIfAbsent((Class<? extends Provider>) superclass, k -> new ArrayList<>()).add(provider);
if (essentials.getSettings().isDebug()) {
essentials.getLogger().info("Registered provider " + provider.getSimpleName() + " for " + superclass.getSimpleName());
}
}
}
}
public void finalizeRegistration() {
for (final Map.Entry<Class<? extends Provider>, List<Class<? extends Provider>>> entry : registeredProviders.entrySet()) {
final Class<? extends Provider> providerClass = entry.getKey();
final boolean nullable = providerClass.isAnnotationPresent(NullableProvider.class);
Class<? extends Provider> highestProvider = null;
ProviderData highestProviderData = null;
int highestWeight = -1;
for (final Class<? extends Provider> provider : entry.getValue()) {
try {
final ProviderData providerData = provider.getAnnotation(ProviderData.class);
if (providerData.weight() > highestWeight && testProvider(provider)) {
highestWeight = providerData.weight();
highestProvider = provider;
highestProviderData = providerData;
}
} catch (final Throwable e) {
essentials.getLogger().log(Level.SEVERE, "Failed to initialize provider " + provider.getName(), e);
}
}
if (highestProvider != null) {
essentials.getLogger().info("Selected " + highestProviderData.description() + " as the provider for " + providerClass.getSimpleName());
providers.put(providerClass, getProviderInstance(highestProvider));
} else if (!nullable) {
throw new IllegalStateException("No provider found for " + providerClass.getName());
} else {
essentials.getLogger().info("No provider found for " + providerClass.getSimpleName() + ", but it is nullable");
}
}
registeredProviders.clear();
}
private boolean testProvider(final Class<?> providerClass) throws InvocationTargetException, IllegalAccessException {
try {
for (final Method method : providerClass.getMethods()) {
if (method.isAnnotationPresent(ProviderTest.class)) {
return (Boolean) method.invoke(null);
}
}
return true;
} catch (final NoClassDefFoundError ignored) {
return false;
}
}
private <P extends Provider> P getProviderInstance(final Class<P> provider) {
try {
final Constructor<?> constructor = provider.getConstructors()[0];
if (constructor.getParameterTypes().length == 0) {
//noinspection unchecked
return (P) constructor.newInstance();
}
final Object[] args = new Object[constructor.getParameterTypes().length];
/*
Providers can have constructors with any of the following types, and this code will automatically supply them;
- Plugin - The Essentials instance will be passed
- boolean - True will be passed if this server is running Paper, otherwise false.
*/
for (int i = 0; i < args.length; i++) {
final Class<?> paramType = constructor.getParameterTypes()[i];
if (paramType.isAssignableFrom(Plugin.class)) {
args[i] = essentials;
} else if (paramType.isAssignableFrom(boolean.class)) {
args[i] = PaperLib.isPaper();
} else {
throw new IllegalArgumentException("Unsupported parameter type " + paramType.getName());
}
}
//noinspection unchecked
return (P) constructor.newInstance(args);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
try {
return provider.getConstructor().newInstance();
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException ex) {
e.printStackTrace();
throw new RuntimeException(ex);
}
}
}
}
@@ -1,24 +1,18 @@
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.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 net.ess3.api.InvalidWorldException;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Biome;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
@@ -30,83 +24,66 @@ public class RandomTeleport implements IConf {
private static final int HIGHEST_BLOCK_Y_OFFSET = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_15_R01) ? 1 : 0;
private final IEssentials ess;
private final EssentialsConfiguration config;
private final Map<String, ConcurrentLinkedQueue<Location>> cachedLocations = new HashMap<>();
private WorldInfoProvider worldInfoProvider;
private final ConcurrentLinkedQueue<Location> cachedLocations = new ConcurrentLinkedQueue<>();
public RandomTeleport(final IEssentials essentials) {
this.ess = essentials;
config = new EssentialsConfiguration(new File(essentials.getDataFolder(), "tpr.yml"), "/tpr.yml",
"Configuration for the random teleport command.\nUse the /settpr command in-game to set random teleport locations.");
}
public EssentialsConfiguration getConfig() {
return config;
"Configuration for the random teleport command.\nSome settings may be defaulted, and can be changed via the /settpr command in-game.");
reloadConfig();
}
@Override
public void reloadConfig() {
worldInfoProvider = ess.provider(WorldInfoProvider.class);
config.load();
cachedLocations.clear();
}
public boolean hasLocation(final String name) {
return config.hasProperty("locations." + name);
}
public Location getCenter(final String name) {
final LazyLocation center = config.getLocation(locationKey(name, "center"));
if (center != null && center.location() != null) {
return center.location();
public Location getCenter() {
try {
final LazyLocation center = config.getLocation("center");
if (center != null && center.location() != null) {
return center.location();
}
} catch (final InvalidWorldException ignored) {
}
final Location worldCenter = ess.getServer().getWorlds().get(0).getWorldBorder().getCenter();
worldCenter.setY(worldCenter.getWorld().getHighestBlockYAt(worldCenter) + HIGHEST_BLOCK_Y_OFFSET);
setCenter(name, worldCenter);
return worldCenter;
final Location center = ess.getServer().getWorlds().get(0).getWorldBorder().getCenter();
center.setY(center.getWorld().getHighestBlockYAt(center) + HIGHEST_BLOCK_Y_OFFSET);
setCenter(center);
return center;
}
public void setCenter(final String name, final Location center) {
config.setProperty(locationKey(name, "center"), center);
public void setCenter(final Location center) {
config.setProperty("center", center);
config.save();
// Clear cached locations since center changed
this.getCachedLocations(name).clear();
}
public double getMinRange(final String name) {
return config.getDouble(locationKey(name, "min-range"), 0d);
public double getMinRange() {
return config.getDouble("min-range", 0d);
}
public void setMinRange(final String name, final double minRange) {
config.setProperty(locationKey(name, "min-range"), minRange);
public void setMinRange(final double minRange) {
config.setProperty("min-range", minRange);
config.save();
// Clear cached locations since min range changed
this.getCachedLocations(name).clear();
}
public double getMaxRange(final String name) {
return config.getDouble(locationKey(name, "max-range"), getCenter(name).getWorld().getWorldBorder().getSize() / 2);
public double getMaxRange() {
return config.getDouble("max-range", getCenter().getWorld().getWorldBorder().getSize() / 2);
}
public void setMaxRange(final String name, final double maxRange) {
config.setProperty(locationKey(name, "max-range"), maxRange);
public void setMaxRange(final double maxRange) {
config.setProperty("max-range", maxRange);
config.save();
// Clear cached locations since max range changed
this.getCachedLocations(name).clear();
}
public String getDefaultLocation() {
return config.getString("default-location", "{world}");
}
public boolean isPerLocationPermission() {
return config.getBoolean("per-location-permission", false);
}
public Set<String> getExcludedBiomes() {
final Set<String> excludedBiomes = new HashSet<>();
for (final String key : config.getList("excluded-biomes", String.class)) {
excludedBiomes.add(key.toLowerCase());
public Set<Biome> getExcludedBiomes() {
final List<String> biomeNames = config.getList("excluded-biomes", String.class);
final Set<Biome> excludedBiomes = new HashSet<>();
for (final String biomeName : biomeNames) {
try {
excludedBiomes.add(Biome.valueOf(biomeName.toUpperCase()));
} catch (final IllegalArgumentException ignored) {
}
}
return excludedBiomes;
}
@@ -119,48 +96,39 @@ public class RandomTeleport implements IConf {
return config.getInt("cache-threshold", 10);
}
public List<String> listLocations() {
return new ArrayList<>(ConfigurateUtil.getKeys(config.getRootNode().node("locations")));
public boolean getPreCache() {
return config.getBoolean("pre-cache", false);
}
public Queue<Location> getCachedLocations(final String name) {
this.cachedLocations.computeIfAbsent(name, x -> new ConcurrentLinkedQueue<>());
return cachedLocations.get(name);
public Queue<Location> getCachedLocations() {
return cachedLocations;
}
// Get a named random teleport location; cached if possible, otherwise on demand.
public CompletableFuture<Location> getRandomLocation(final String name) {
final Queue<Location> cached = this.getCachedLocations(name);
// Get a random location; cached if possible. Otherwise on demand.
public CompletableFuture<Location> getRandomLocation(final Location center, final double minRange, final double maxRange) {
final int findAttempts = this.getFindAttempts();
final Queue<Location> cachedLocations = this.getCachedLocations();
// Try to build up the cache if it is below the threshold
if (cached.size() < this.getCacheThreshold()) {
cacheRandomLocations(name);
if (cachedLocations.size() < this.getCacheThreshold()) {
cacheRandomLocations(center, minRange, maxRange);
}
final CompletableFuture<Location> future = new CompletableFuture<>();
// Return a random location immediately if one is available, otherwise try to find one now
if (cached.isEmpty()) {
final int findAttempts = this.getFindAttempts();
final Location center = this.getCenter(name);
final double minRange = this.getMinRange(name);
final double maxRange = this.getMaxRange(name);
if (cachedLocations.isEmpty()) {
attemptRandomLocation(findAttempts, center, minRange, maxRange).thenAccept(future::complete);
} else {
future.complete(cached.poll());
future.complete(cachedLocations.poll());
}
return future;
}
// Get a random location with specific parameters (note: not cached).
public CompletableFuture<Location> getRandomLocation(final Location center, final double minRange, final double maxRange) {
return attemptRandomLocation(this.getFindAttempts(), center, minRange, maxRange);
}
// Prompts caching random valid locations, up to a maximum number of attempts.
public void cacheRandomLocations(final String name) {
// Prompts caching random valid locations, up to a maximum number of attempts
public void cacheRandomLocations(final Location center, final double minRange, final double maxRange) {
ess.getServer().getScheduler().scheduleSyncDelayedTask(ess, () -> {
for (int i = 0; i < this.getFindAttempts(); ++i) {
calculateRandomLocation(getCenter(name), getMinRange(name), getMaxRange(name)).thenAccept(location -> {
calculateRandomLocation(center, minRange, maxRange).thenAccept(location -> {
if (isValidRandomLocation(location)) {
this.getCachedLocations(name).add(location);
this.getCachedLocations().add(location);
}
});
}
@@ -209,7 +177,7 @@ public class RandomTeleport implements IConf {
final Location location = new Location(
center.getWorld(),
center.getX() + offsetX,
worldInfoProvider.getMaxHeight(center.getWorld()),
ess.getWorldInfoProvider().getMaxHeight(center.getWorld()),
center.getZ() + offsetZ,
360 * RANDOM.nextFloat() - 180,
0
@@ -225,51 +193,18 @@ public class RandomTeleport implements IConf {
return future;
}
// Returns an appropriate elevation for a given location in the nether, or MIN_VALUE if none is found
// Returns an appropriate elevation for a given location in the nether, or -1 if none is found
private double getNetherYAt(final Location location) {
final World world = location.getWorld();
for (int y = 32; y < worldInfoProvider.getMaxHeight(world); ++y) {
if (Material.BEDROCK.equals(world.getBlockAt(location.getBlockX(), y, location.getBlockZ()).getType())) {
break;
}
if (!LocationUtil.isBlockUnsafe(ess, world, location.getBlockX(), y, location.getBlockZ())) {
for (int y = 32; y < ess.getWorldInfoProvider().getMaxHeight(location.getWorld()); ++y) {
if (!LocationUtil.isBlockUnsafe(ess, location.getWorld(), location.getBlockX(), y, location.getBlockZ())) {
return y;
}
}
return Double.MIN_VALUE;
return -1;
}
private boolean isValidRandomLocation(final Location location) {
return location.getBlockY() > worldInfoProvider.getMinHeight(location.getWorld()) && !isExcludedBiome(location);
}
// 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 = biomeNameProvider.getBiomeName(location.getBlock());
// Try with good old bukkit enum
if (excluded.contains(enumKey)) {
return true;
}
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_14_4_R01)) {
// No way to get the biome key on versions below this
return false;
}
final String biomeKey;
final BiomeKeyProvider biomeKeyProvider = ess.provider(BiomeKeyProvider.class);
if (biomeKeyProvider != null) {
// Works with custom biome keys
biomeKey = biomeKeyProvider.getBiomeKey(location.getBlock()).toString();
} else {
// Custom biome keys resolve as "minecraft:custom" which is unfortunate
biomeKey = location.getBlock().getBiome().getKey().toString();
}
return excluded.contains(biomeKey);
}
private String locationKey(final String name, final String key) {
return "locations." + name + "." + key;
return location.getBlockY() > ess.getWorldInfoProvider().getMinHeight(location.getWorld()) && !this.getExcludedBiomes().contains(location.getBlock().getBiome());
}
public File getFile() {
@@ -1,6 +1,5 @@
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;
@@ -14,17 +13,11 @@ import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.LocationUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.IEssentials;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.SyncCommandsProvider;
import net.essentialsx.api.v2.ChatType;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.event.EventPriority;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.spongepowered.configurate.CommentedConfigurationNode;
import java.io.File;
@@ -36,7 +29,6 @@ import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -44,26 +36,22 @@ 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;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
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 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);
private final ChatFormats chatFormats = new ChatFormats();
private final Map<String, String> chatFormats = Collections.synchronizedMap(new HashMap<>());
private int chatRadius = 0;
// #easteregg
private char chatShout = '!';
@@ -91,7 +79,6 @@ 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,17 +132,10 @@ 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 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;
@@ -173,16 +153,6 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("respawn-at-home", false);
}
@Override
public String getRandomSpawnLocation() {
return config.getString("random-spawn-location", "none");
}
@Override
public String getRandomRespawnLocation() {
return config.getString("random-respawn-location", "none");
}
@Override
public boolean isRespawnAtAnchor() {
return config.getBoolean("respawn-at-anchor", false);
@@ -209,7 +179,7 @@ public class Settings implements net.ess3.api.ISettings {
final Set<String> homeList = getMultipleHomes();
if (homeList != null) {
for (final String set : homeList) {
if (user.isAuthorized("essentials.sethome.multiple." + set) && limit < getHomeLimit(set)) {
if (user.isAuthorized("essentials.sethome.multiple." + set) && (limit < getHomeLimit(set))) {
limit = getHomeLimit(set);
}
}
@@ -269,11 +239,6 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("chat.question-enabled", true);
}
@Override
public boolean isUsePaperChatEvent() {
return config.getBoolean("chat.paper-chat-events", true);
}
public boolean _isTeleportSafetyEnabled() {
return config.getBoolean("teleport-safety", true);
}
@@ -297,11 +262,6 @@ 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);
@@ -353,11 +313,9 @@ public class Settings implements net.ess3.api.ISettings {
}
private void _addAlternativeCommand(final String label, final Command current) {
final KnownCommandsProvider knownCommandsProvider = ess.provider(KnownCommandsProvider.class);
Command cmd = ess.getAlternativeCommandsHandler().getAlternative(label);
if (cmd == null) {
for (final Map.Entry<String, Command> entry : knownCommandsProvider.getKnownCommands().entrySet()) {
for (final Map.Entry<String, Command> entry : ess.getKnownCommandsProvider().getKnownCommands().entrySet()) {
final String[] split = entry.getKey().split(":");
if (entry.getValue() != current && split[split.length - 1].equals(label)) {
cmd = entry.getValue();
@@ -367,7 +325,7 @@ public class Settings implements net.ess3.api.ISettings {
}
if (cmd != null) {
knownCommandsProvider.getKnownCommands().put(label, cmd);
ess.getKnownCommandsProvider().getKnownCommands().put(label, cmd);
}
}
@@ -489,11 +447,6 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("socialspy-messages", true);
}
@Override
public boolean isSocialSpyDisplayNames() {
return config.getBoolean("socialspy-uses-displaynames", true);
}
private Set<String> _getMuteCommands() {
final Set<String> muteCommands = new HashSet<>();
if (config.isList("mute-commands")) {
@@ -514,20 +467,11 @@ 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);
@@ -621,132 +565,32 @@ public class Settings implements net.ess3.api.ISettings {
@Override
public String getChatFormat(final String group) {
return getChatFormat(group, null);
}
@Override
public String getChatFormat(final String group, final ChatType chatType) {
final String mFormat = chatFormats.getFormat(group, chatType, new ChatFormatConfigSupplier(group, chatType));
String mFormat = chatFormats.get(group);
if (mFormat == null) {
mFormat = config.getString("chat.group-formats." + (group == null ? "Default" : group), config.getString("chat.format", "&7[{GROUP}]&r {DISPLAYNAME}&7:&r {MESSAGE}"));
mFormat = FormatUtil.replaceFormat(mFormat);
mFormat = mFormat.replace("{DISPLAYNAME}", "%1$s");
mFormat = mFormat.replace("{MESSAGE}", "%2$s");
mFormat = mFormat.replace("{GROUP}", "{0}");
mFormat = mFormat.replace("{WORLD}", "{1}");
mFormat = mFormat.replace("{WORLDNAME}", "{1}");
mFormat = mFormat.replace("{SHORTWORLDNAME}", "{2}");
mFormat = mFormat.replace("{TEAMPREFIX}", "{3}");
mFormat = mFormat.replace("{TEAMSUFFIX}", "{4}");
mFormat = mFormat.replace("{TEAMNAME}", "{5}");
mFormat = mFormat.replace("{PREFIX}", "{6}");
mFormat = mFormat.replace("{SUFFIX}", "{7}");
mFormat = mFormat.replace("{USERNAME}", "{8}");
mFormat = mFormat.replace("{NICKNAME}", "{9}");
mFormat = "§r".concat(mFormat);
chatFormats.put(group, mFormat);
}
if (isDebug()) {
ess.getLogger().info(String.format("Found format '%s' for group '%s'", mFormat, group));
}
return mFormat;
}
private class ChatFormatConfigSupplier implements Supplier<String> {
private final String group;
private final ChatType chatType;
ChatFormatConfigSupplier(String group, ChatType chatType) {
this.group = group;
this.chatType = chatType;
}
@Override
public String get() {
final String chatKey = chatType.key();
final String groupPath = "chat.group-formats." + (group == null ? "Default" : group);
String configFormat = config.getString(groupPath + "." + chatKey, null);
if (configFormat == null) {
configFormat = config.getString(groupPath, null);
}
final String formatPath = "chat.format";
if (configFormat == null) {
configFormat = config.getString(formatPath + "." + chatKey, null);
}
if (configFormat == null) {
configFormat = config.getString(formatPath, null);
}
if (configFormat == null) {
configFormat = "&7[{GROUP}]&r {DISPLAYNAME}&7:&r {MESSAGE}";
}
configFormat = FormatUtil.replaceFormat(configFormat);
configFormat = configFormat.replace("{DISPLAYNAME}", "%1$s");
configFormat = configFormat.replace("{MESSAGE}", "%2$s");
configFormat = configFormat.replace("{GROUP}", "{0}");
configFormat = configFormat.replace("{WORLD}", "{1}");
configFormat = configFormat.replace("{WORLDNAME}", "{1}");
configFormat = configFormat.replace("{SHORTWORLDNAME}", "{2}");
configFormat = configFormat.replace("{TEAMPREFIX}", "{3}");
configFormat = configFormat.replace("{TEAMSUFFIX}", "{4}");
configFormat = configFormat.replace("{TEAMNAME}", "{5}");
configFormat = configFormat.replace("{PREFIX}", "{6}");
configFormat = configFormat.replace("{SUFFIX}", "{7}");
configFormat = configFormat.replace("{USERNAME}", "{8}");
configFormat = configFormat.replace("{NICKNAME}", "{9}");
configFormat = "§r".concat(configFormat);
return configFormat;
}
}
private static class ChatFormats {
private final Map<String, TypedChatFormat> groupFormats;
private TypedChatFormat defaultFormat;
ChatFormats() {
defaultFormat = null;
groupFormats = new HashMap<>();
}
public String getFormat(String group, ChatType type, Supplier<String> configSupplier) {
// With such a large synchronize block, we synchronize a potential config deserialization
// It does not matter as it needs to be done. It's even better as we ensure to do it once
// TypedChatFormat is also synchronized
synchronized (this) {
final TypedChatFormat typedChatFormat;
if (group == null) {
if (defaultFormat == null) {
defaultFormat = new TypedChatFormat();
}
typedChatFormat = defaultFormat;
} else {
typedChatFormat = groupFormats.computeIfAbsent(group, s -> new TypedChatFormat());
}
return typedChatFormat.getFormat(type, configSupplier);
}
}
public void clear() {
synchronized (this) {
defaultFormat = null;
groupFormats.clear();
}
}
}
private static class TypedChatFormat {
private final Map<ChatType, String> typedFormats;
private String defaultFormat;
TypedChatFormat() {
defaultFormat = null;
typedFormats = new EnumMap<>(ChatType.class);
}
public String getFormat(ChatType type, Supplier<String> configSupplier) {
final String format;
if (type == null) {
if (defaultFormat == null) {
defaultFormat = configSupplier.get();
}
format = defaultFormat;
} else {
format = typedFormats.computeIfAbsent(type, c -> configSupplier.get());
}
return format;
}
}
@Override
public String getWorldAlias(String world) {
return worldAliases.getOrDefault(world.toLowerCase(), world);
@@ -835,32 +679,18 @@ public class Settings implements net.ess3.api.ISettings {
overriddenCommands = _getOverriddenCommands();
playerCommands = _getPlayerCommands();
final KnownCommandsProvider knownCommandsProvider = ess.provider(KnownCommandsProvider.class);
// This will be late loaded
if (knownCommandsProvider != null) {
if (ess.getKnownCommandsProvider() != null) {
boolean mapModified = false;
if (!disabledBukkitCommands.isEmpty()) {
if (isDebug()) {
ess.getLogger().log(Level.INFO, "Re-adding " + disabledBukkitCommands.size() + " disabled commands!");
}
knownCommandsProvider.getKnownCommands().putAll(disabledBukkitCommands);
ess.getKnownCommandsProvider().getKnownCommands().putAll(disabledBukkitCommands);
disabledBukkitCommands.clear();
mapModified = true;
}
if (reloadCount.get() < 2) {
// on startup: add plugins again in case they registered commands with the new API
// we need to schedule this task before any of the below tasks using _addAlternativeCommand.
ess.scheduleSyncDelayedTask(() -> {
for (final Plugin plugin : ess.getServer().getPluginManager().getPlugins()) {
if (plugin.isEnabled()) {
ess.getAlternativeCommandsHandler().addPlugin(plugin);
}
}
});
}
for (final String command : disabledCommands) {
final String effectiveAlias = command.toLowerCase(Locale.ENGLISH);
final Command toDisable = ess.getPluginCommand(effectiveAlias);
@@ -868,7 +698,7 @@ public class Settings implements net.ess3.api.ISettings {
if (isDebug()) {
ess.getLogger().log(Level.INFO, "Attempting removal of " + effectiveAlias);
}
final Command removed = knownCommandsProvider.getKnownCommands().remove(effectiveAlias);
final Command removed = ess.getKnownCommandsProvider().getKnownCommands().remove(effectiveAlias);
if (removed != null) {
if (isDebug()) {
ess.getLogger().log(Level.INFO, "Adding command " + effectiveAlias + " to disabled map!");
@@ -886,22 +716,19 @@ public class Settings implements net.ess3.api.ISettings {
}
}
final SyncCommandsProvider syncCommandsProvider = ess.provider(SyncCommandsProvider.class);
if (mapModified) {
if (isDebug()) {
ess.getLogger().log(Level.INFO, "Syncing commands");
}
if (reloadCount.get() < 2) {
ess.scheduleSyncDelayedTask(syncCommandsProvider::syncCommands);
ess.scheduleSyncDelayedTask(() -> ess.getSyncCommandsProvider().syncCommands());
} else {
syncCommandsProvider.syncCommands();
ess.getSyncCommandsProvider().syncCommands();
}
}
}
nicknamePrefix = _getNicknamePrefix();
resetNickOnNameChange = _resetNickOnNameChange();
operatorColor = _getOperatorColor();
changePlayerListName = _changePlayerListName();
configDebug = _isDebug();
@@ -921,7 +748,6 @@ public class Settings implements net.ess3.api.ISettings {
permissionsLagWarning = _getPermissionsLagWarning();
economyLagWarning = _getEconomyLagWarning();
economyLog = _isEcoLogEnabled();
economyLogUUID = _isEcoLogUUIDEnabled();
economyLogUpdate = _isEcoLogUpdateEnabled();
economyDisabled = _isEcoDisabled();
allowSilentJoin = _allowSilentJoinQuit();
@@ -946,7 +772,6 @@ public class Settings implements net.ess3.api.ISettings {
isWaterSafe = _isWaterSafe();
isSafeUsermap = _isSafeUsermap();
logCommandBlockCommands = _logCommandBlockCommands();
logConsoleCommands = _logConsoleCommands();
nickBlacklist = _getNickBlacklist();
maxProjectileSpeed = _getMaxProjectileSpeed();
removeEffectsOnHeal = _isRemovingEffectsOnHeal();
@@ -954,11 +779,6 @@ public class Settings implements net.ess3.api.ISettings {
bindingItemPolicy = _getBindingItemsPolicy();
currencySymbol = _getCurrencySymbol();
worldAliases = _getWorldAliases();
primaryColor = _getPrimaryColor();
secondaryColor = _getSecondaryColor();
multiplierPerms = _getMultiplierPerms();
defaultMultiplier = _getDefaultMultiplier();
afkTimeoutCommands = _getAfkTimeoutCommands();
reloadCount.incrementAndGet();
}
@@ -989,7 +809,7 @@ public class Settings implements net.ess3.api.ISettings {
final ItemStack iStack = itemDb.get(itemName);
epItemSpwn.add(iStack.getType());
} catch (final Exception ex) {
ess.getLogger().log(Level.SEVERE, ess.getAdventureFacet().miniToLegacy(tlLiteral("unknownItemInList", itemName, "item-spawn-blacklist")), ex);
ess.getLogger().log(Level.SEVERE, tl("unknownItemInList", itemName, "item-spawn-blacklist"), ex);
}
}
return epItemSpwn;
@@ -1017,7 +837,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, ess.getAdventureFacet().miniToLegacy(tlLiteral("unknownItemInList", signName, "enabledSigns")));
ess.getLogger().log(Level.SEVERE, tl("unknownItemInList", signName, "enabledSigns"));
continue;
}
signsEnabled = true;
@@ -1035,12 +855,41 @@ public class Settings implements net.ess3.api.ISettings {
}
private boolean _isDebug() {
return config.getBoolean("debug", false);
if (config.isBoolean("debug")) {
return config.getBoolean("debug", false);
}
if (config.isBoolean("debug.enabled")) {
return config.getBoolean("debug.enabled", false);
}
return false;
}
@Override
public boolean isDebug() {
return debug || configDebug;
return isDebug(DebugFlag.GENERIC);
}
@Override
public boolean isDebug(DebugFlag flag) {
if (flag.isSetByGlobal() && (debug || configDebug)) {
return true;
}
final String flagConfigPath = flag.getConfigKey();
if (config.isBoolean(flagConfigPath)) {
return config.getBoolean(flagConfigPath, false);
}
return flag.getSystemPropertyBoolean();
}
@Override
public Long getDebugLong(DebugFlag flag) {
final String flagConfigPath = flag.getConfigKey();
if (config.hasProperty(flagConfigPath)) {
return config.getLong(flagConfigPath, 0);
}
return flag.getSystemPropertyLong();
}
@Override
@@ -1063,11 +912,6 @@ public class Settings implements net.ess3.api.ISettings {
return config.getString("locale", "");
}
@Override
public boolean isPerPlayerLocale() {
return config.getBoolean("per-player-locale", false);
}
private String currencySymbol = "$";
// A valid currency symbol value must be one non-integer character.
@@ -1117,23 +961,14 @@ public class Settings implements net.ess3.api.ISettings {
}
@Override
public List<String> getProtectListRaw(String configName) {
final List<String> list = new ArrayList<>();
public List<Material> getProtectList(final String configName) {
final List<Material> list = new ArrayList<>();
for (String itemName : config.getString(configName, "").split(",")) {
itemName = itemName.trim();
if (itemName.isEmpty()) {
continue;
}
list.add(itemName);
}
return list;
}
@Override
public List<Material> getProtectList(final String configName) {
final List<Material> list = new ArrayList<>();
for (String itemName : getProtectListRaw(configName)) {
Material mat = EnumUtil.getMaterial(itemName.toUpperCase());
if (mat == null) {
@@ -1145,7 +980,7 @@ public class Settings implements net.ess3.api.ISettings {
}
if (mat == null) {
ess.getLogger().log(Level.SEVERE, ess.getAdventureFacet().miniToLegacy(tlLiteral("unknownItemInList", itemName, configName)));
ess.getLogger().log(Level.SEVERE, tl("unknownItemInList", itemName, configName));
} else {
list.add(mat);
}
@@ -1194,14 +1029,6 @@ 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;
@@ -1291,17 +1118,8 @@ public class Settings implements net.ess3.api.ISettings {
}
@Override
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;
public long getAutoAfkKick() {
return config.getLong("auto-afk-kick", -1);
}
@Override
@@ -1336,11 +1154,6 @@ 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;
@@ -1662,11 +1475,6 @@ 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);
@@ -1690,16 +1498,10 @@ public class Settings implements net.ess3.api.ISettings {
// #easteregg
@Override
public int getMaxUserCacheCount() {
final long count = Runtime.getRuntime().maxMemory() / 1024 / 1024;
final long count = Runtime.getRuntime().maxMemory() / 1024 / 96;
return config.getInt("max-user-cache-count", (int) count);
}
// #easteregg
@Override
public long getMaxUserCacheValueExpiry() {
return config.getLong("max-user-cache-value-expiry", 600);
}
@Override
public boolean isLastMessageReplyRecipient() {
return config.getBoolean("last-message-reply-recipient", false);
@@ -1920,7 +1722,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, ess.getAdventureFacet().miniToLegacy(tlLiteral("unknownItemInList", signName, "unprotected-sign-names")));
ess.getLogger().log(Level.SEVERE, tl("unknownItemInList", signName, "unprotected-sign-names"));
}
}
return newSigns;
@@ -1981,16 +1783,6 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("world-change-fly-reset", true);
}
@Override
public boolean isWorldChangePreserveFlying() {
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);
@@ -1998,7 +1790,9 @@ public class Settings implements net.ess3.api.ISettings {
private List<String> _getDefaultEnabledConfirmCommands() {
final List<String> commands = config.getList("default-enabled-confirm-commands", String.class);
commands.replaceAll(String::toLowerCase);
for (int i = 0; i < commands.size(); i++) {
commands.set(i, commands.get(i).toLowerCase());
}
return commands;
}
@@ -2106,15 +1900,6 @@ 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<>();
@@ -2181,95 +1966,4 @@ public class Settings implements net.ess3.api.ISettings {
public boolean showZeroBaltop() {
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;
if (multiplierPerms == null) {
return defaultMultiplier;
}
for (final String multiplierPerm : multiplierPerms) {
if (user.isAuthorized("essentials.sell.multiplier." + multiplierPerm)) {
final BigDecimal value = config.getBigDecimal("sell-multipliers." + multiplierPerm, BigDecimal.ZERO);
if (value.compareTo(multiplier) > 0) {
multiplier = value;
}
}
}
return multiplier;
}
private BigDecimal _getDefaultMultiplier() {
return config.getBigDecimal("sell-multipliers.default", BigDecimal.ONE);
}
private Set<String> _getMultiplierPerms() {
final CommentedConfigurationNode section = config.getSection("sell-multipliers");
return section == null ? null : ConfigurateUtil.getKeys(section);
}
public int getMaxItemLore() {
return config.getInt("max-itemlore-lines", 10);
}
@Override
public String getPrimaryColor() {
return primaryColor;
}
private String _getPrimaryColor() {
final String color = config.getString("message-colors.primary", "#ffaa00");
final String textColor = _getTagColor(color);
return textColor != null ? textColor : DEFAULT_PRIMARY_COLOR;
}
@Override
public String getSecondaryColor() {
return secondaryColor;
}
private String _getSecondaryColor() {
final String color = config.getString("message-colors.secondary", "#ff5555");
final String textColor = _getTagColor(color);
return textColor != null ? textColor : DEFAULT_SECONDARY_COLOR;
}
private String _getTagColor(final String color) {
try {
if (color.startsWith("#") && color.length() == 7 && NumberUtil.isHexadecimal(color.substring(1))) {
Color.fromRGB(Integer.decode(color));
return color;
}
if (color.length() == 1) {
return Objects.requireNonNull(AdventureUtil.fromChar(color.charAt(0))).toString();
}
return Objects.requireNonNull(NamedTextColor.NAMES.value(color.toLowerCase(Locale.ENGLISH))).toString();
} catch (NullPointerException | IllegalArgumentException ignored) {
}
return null;
}
@Override
public BigDecimal getBaltopMinBalance() {
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);
}
}
@@ -7,7 +7,6 @@ import com.earth2me.essentials.utils.LocationUtil;
import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Server;
@@ -28,14 +27,12 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import static com.earth2me.essentials.I18n.tl;
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");
@@ -52,7 +49,7 @@ public final class SpawnMob {
}
}
if (availableList.isEmpty()) {
availableList.add(user.playerTl("none"));
availableList.add(tl("none"));
}
return StringUtil.joinList(availableList);
}
@@ -94,7 +91,7 @@ public final class SpawnMob {
public static void spawnmob(final IEssentials ess, final Server server, final User user, final List<String> parts, final List<String> data, final int mobCount) throws Exception {
final Block block = LocationUtil.getTarget(user.getBase()).getBlock();
if (block == null) {
throw new TranslatableException("unableToSpawnMob");
throw new Exception(tl("unableToSpawnMob"));
}
spawnmob(ess, server, user.getSource(), user, block.getLocation(), parts, data, mobCount);
}
@@ -125,7 +122,7 @@ public final class SpawnMob {
if (mobCount > effectiveLimit) {
mobCount = effectiveLimit;
sender.sendTl("mobSpawnLimit");
sender.sendMessage(tl("mobSpawnLimit"));
}
final Mob mob = Mob.fromName(parts.get(0)); // Get the first mob
@@ -133,13 +130,13 @@ public final class SpawnMob {
for (int i = 0; i < mobCount; i++) {
spawnMob(ess, server, sender, target, sloc, parts, data);
}
sender.sendMessage(mobCount * parts.size() + " " + mob.name.toLowerCase(Locale.ENGLISH) + mob.suffix + " " + sender.tl("spawned"));
sender.sendMessage(mobCount * parts.size() + " " + mob.name.toLowerCase(Locale.ENGLISH) + mob.suffix + " " + tl("spawned"));
} catch (final MobException e1) {
throw new TranslatableException(e1, "unableToSpawnMob");
throw new Exception(tl("unableToSpawnMob"), e1);
} catch (final NumberFormatException e2) {
throw new TranslatableException(e2, "numberRequired");
throw new Exception(tl("numberRequired"), e2);
} catch (final NullPointerException np) {
throw new TranslatableException(np, "soloMob");
throw new Exception(tl("soloMob"), np);
}
}
@@ -179,15 +176,15 @@ public final class SpawnMob {
private static void checkSpawnable(final IEssentials ess, final CommandSource sender, final Mob mob) throws Exception {
if (mob == null || mob.getType() == null) {
throw new TranslatableException("invalidMob");
throw new Exception(tl("invalidMob"));
}
if (ess.getSettings().getProtectPreventSpawn(mob.getType().toString().toLowerCase(Locale.ENGLISH))) {
throw new TranslatableException("disabledToSpawnMob");
throw new Exception(tl("disabledToSpawnMob"));
}
if (sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.spawnmob." + mob.name.toLowerCase(Locale.ENGLISH))) {
throw new TranslatableException("noPermToSpawnMob");
throw new Exception(tl("noPermToSpawnMob"));
}
}
@@ -195,7 +192,7 @@ public final class SpawnMob {
String data = inputData;
if (data.isEmpty()) {
sender.sendTl("mobDataList", StringUtil.joinList(MobData.getValidHelp(spawned)));
sender.sendMessage(tl("mobDataList", StringUtil.joinList(MobData.getValidHelp(spawned))));
}
if (spawned instanceof Zombie) {
@@ -214,11 +211,6 @@ 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));
@@ -0,0 +1,403 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.LocationUtil;
import io.papermc.lib.PaperLib;
import net.ess3.api.IEssentials;
import net.ess3.api.ITeleport;
import net.ess3.api.IUser;
import net.ess3.api.events.UserWarpEvent;
import net.ess3.api.events.teleport.PreTeleportEvent;
import net.ess3.api.events.teleport.TeleportWarmupEvent;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.GregorianCalendar;
import static com.earth2me.essentials.I18n.tl;
/**
* @deprecated This API is not asynchronous. Use {@link com.earth2me.essentials.AsyncTeleport AsyncTeleport}
*/
@Deprecated
public class Teleport implements ITeleport {
private final IUser teleportOwner;
private final IEssentials ess;
private TimedTeleport timedTeleport;
private TeleportType tpType;
@Deprecated
public Teleport(final IUser user, final IEssentials ess) {
this.teleportOwner = user;
this.ess = ess;
tpType = TeleportType.NORMAL;
}
@Deprecated
public void cooldown(final boolean check) throws Exception {
final Calendar time = new GregorianCalendar();
if (teleportOwner.getLastTeleportTimestamp() > 0) {
// Take the current time, and remove the delay from it.
final double cooldown = ess.getSettings().getTeleportCooldown();
final Calendar earliestTime = new GregorianCalendar();
earliestTime.add(Calendar.SECOND, -(int) cooldown);
earliestTime.add(Calendar.MILLISECOND, -(int) ((cooldown * 1000.0) % 1000.0));
// This value contains the most recent time a teleportPlayer could have been used that would allow another use.
final long earliestLong = earliestTime.getTimeInMillis();
// When was the last teleportPlayer used?
final long lastTime = teleportOwner.getLastTeleportTimestamp();
if (lastTime > time.getTimeInMillis()) {
// This is to make sure time didn't get messed up on last teleportPlayer use.
// If this happens, let's give the user the benifit of the doubt.
teleportOwner.setLastTeleportTimestamp(time.getTimeInMillis());
return;
} else if (lastTime > earliestLong
&& cooldownApplies()) {
time.setTimeInMillis(lastTime);
time.add(Calendar.SECOND, (int) cooldown);
time.add(Calendar.MILLISECOND, (int) ((cooldown * 1000.0) % 1000.0));
throw new Exception(tl("timeBeforeTeleport", DateUtil.formatDateDiff(time.getTimeInMillis())));
}
}
// if justCheck is set, don't update lastTeleport; we're just checking
if (!check) {
teleportOwner.setLastTeleportTimestamp(time.getTimeInMillis());
}
}
@Deprecated
private boolean cooldownApplies() {
boolean applies = true;
final String globalBypassPerm = "essentials.teleport.cooldown.bypass";
switch (tpType) {
case NORMAL:
applies = !teleportOwner.isAuthorized(globalBypassPerm);
break;
case BACK:
applies = !(teleportOwner.isAuthorized(globalBypassPerm) &&
teleportOwner.isAuthorized("essentials.teleport.cooldown.bypass.back"));
break;
case TPA:
applies = !(teleportOwner.isAuthorized(globalBypassPerm) &&
teleportOwner.isAuthorized("essentials.teleport.cooldown.bypass.tpa"));
break;
}
return applies;
}
@Deprecated
private void warnUser(final IUser user, final double delay) {
final Calendar c = new GregorianCalendar();
c.add(Calendar.SECOND, (int) delay);
c.add(Calendar.MILLISECOND, (int) ((delay * 1000.0) % 1000.0));
user.sendMessage(tl("dontMoveMessage", DateUtil.formatDateDiff(c.getTimeInMillis())));
}
//The now function is used when you want to skip tp delay when teleporting someone to a location or player.
@Override
@Deprecated
public void now(final Location loc, final boolean cooldown, final TeleportCause cause) throws Exception {
if (cooldown) {
cooldown(false);
}
final ITarget target = new LocationTarget(loc);
now(teleportOwner, target, cause);
}
@Override
@Deprecated
public void now(final Player entity, final boolean cooldown, final TeleportCause cause) throws Exception {
if (cooldown) {
cooldown(false);
}
final ITarget target = new PlayerTarget(entity);
now(teleportOwner, target, cause);
teleportOwner.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
}
@Deprecated
protected void now(final IUser teleportee, final ITarget target, final TeleportCause cause) throws Exception {
cancel(false);
Location loc = target.getLocation();
final PreTeleportEvent event = new PreTeleportEvent(teleportee, cause, target);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
if (teleportee.isAuthorized("essentials.back.onteleport")) {
teleportee.setLastLocation();
}
if (!teleportee.getBase().isEmpty()) {
if (!ess.getSettings().isTeleportPassengerDismount()) {
throw new Exception(tl("passengerTeleportFail"));
}
teleportee.getBase().eject();
}
if (LocationUtil.isBlockUnsafeForUser(ess, teleportee, loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
if (ess.getSettings().isTeleportSafetyEnabled()) {
if (ess.getSettings().isForceDisableTeleportSafety()) {
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
} else {
PaperLib.teleportAsync(teleportee.getBase(), LocationUtil.getSafeDestination(ess, teleportee, loc), cause);
}
} else {
throw new Exception(tl("unsafeTeleportDestination", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
}
} else {
if (ess.getSettings().isForceDisableTeleportSafety()) {
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
} else {
if (ess.getSettings().isTeleportToCenterLocation()) {
loc = LocationUtil.getRoundedDestination(loc);
}
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
}
}
}
//The teleportPlayer function is used when you want to normally teleportPlayer someone to a location or player.
//This method is nolonger used internally and will be removed.
@Deprecated
@Override
public void teleport(final Location loc, final Trade chargeFor) throws Exception {
teleport(loc, chargeFor, TeleportCause.PLUGIN);
}
@Override
@Deprecated
public void teleport(final Location loc, final Trade chargeFor, final TeleportCause cause) throws Exception {
teleport(teleportOwner, new LocationTarget(loc), chargeFor, cause);
}
//This is used when teleporting to a player
@Override
@Deprecated
public void teleport(final Player entity, final Trade chargeFor, final TeleportCause cause) throws Exception {
final ITarget target = new PlayerTarget(entity);
teleportOwner.sendMessage(tl("teleportToPlayer", entity.getDisplayName()));
teleport(teleportOwner, target, chargeFor, cause);
}
//This is used when teleporting to stored location
@Override
@Deprecated
public void teleportPlayer(final IUser teleportee, final Location loc, final Trade chargeFor, final TeleportCause cause) throws Exception {
teleport(teleportee, new LocationTarget(loc), chargeFor, cause);
}
//This is used on /tphere
@Override
@Deprecated
public void teleportPlayer(final IUser teleportee, final Player entity, final Trade chargeFor, final TeleportCause cause) throws Exception {
final ITarget target = new PlayerTarget(entity);
teleport(teleportee, target, chargeFor, cause);
teleportee.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
teleportOwner.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
}
@Deprecated
private void teleport(final IUser teleportee, final ITarget target, final Trade chargeFor, final TeleportCause cause) throws Exception {
double delay = ess.getSettings().getTeleportDelay();
final TeleportWarmupEvent event = new TeleportWarmupEvent(teleportee, cause, target, delay);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
delay = event.getDelay();
Trade cashCharge = chargeFor;
if (chargeFor != null) {
chargeFor.isAffordableFor(teleportOwner);
//This code is to make sure that commandcosts are checked in the initial world, and not in the resulting world.
if (!chargeFor.getCommandCost(teleportOwner).equals(BigDecimal.ZERO)) {
//By converting a command cost to a regular cost, the command cost permission isn't checked when executing the charge after teleport.
cashCharge = new Trade(chargeFor.getCommandCost(teleportOwner), ess);
}
}
cooldown(true);
if (delay <= 0 || teleportOwner.isAuthorized("essentials.teleport.timer.bypass") || teleportee.isAuthorized("essentials.teleport.timer.bypass")) {
cooldown(false);
now(teleportee, target, cause);
if (cashCharge != null) {
cashCharge.charge(teleportOwner);
}
return;
}
cancel(false);
warnUser(teleportee, delay);
initTimer((long) (delay * 1000.0), teleportee, target, cashCharge, cause, false);
}
@Deprecated
private void teleportOther(final IUser teleporter, final IUser teleportee, final ITarget target, final Trade chargeFor, final TeleportCause cause) throws Exception {
double delay = ess.getSettings().getTeleportDelay();
final TeleportWarmupEvent event = new TeleportWarmupEvent(teleporter, teleportee, cause, target, delay);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
delay = event.getDelay();
Trade cashCharge = chargeFor;
if (teleporter != null && chargeFor != null) {
chargeFor.isAffordableFor(teleporter);
//This code is to make sure that commandcosts are checked in the initial world, and not in the resulting world.
if (!chargeFor.getCommandCost(teleporter).equals(BigDecimal.ZERO)) {
//By converting a command cost to a regular cost, the command cost permission isn't checked when executing the charge after teleport.
cashCharge = new Trade(chargeFor.getCommandCost(teleporter), ess);
}
}
cooldown(true);
if (delay <= 0 || teleporter == null
|| teleporter.isAuthorized("essentials.teleport.timer.bypass")
|| teleportOwner.isAuthorized("essentials.teleport.timer.bypass")
|| teleportee.isAuthorized("essentials.teleport.timer.bypass")) {
cooldown(false);
now(teleportee, target, cause);
if (teleporter != null && cashCharge != null) {
cashCharge.charge(teleporter);
}
return;
}
cancel(false);
warnUser(teleportee, delay);
initTimer((long) (delay * 1000.0), teleportee, target, cashCharge, cause, false);
}
//The respawn function is a wrapper used to handle tp fallback, on /jail and /home
@Override
@Deprecated
public void respawn(final Trade chargeFor, final TeleportCause cause) throws Exception {
double delay = ess.getSettings().getTeleportDelay();
final TeleportWarmupEvent event = new TeleportWarmupEvent(teleportOwner, cause, null, delay);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
delay = event.getDelay();
if (chargeFor != null) {
chargeFor.isAffordableFor(teleportOwner);
}
cooldown(true);
if (delay <= 0 || teleportOwner.isAuthorized("essentials.teleport.timer.bypass")) {
cooldown(false);
respawnNow(teleportOwner, cause);
if (chargeFor != null) {
chargeFor.charge(teleportOwner);
}
return;
}
cancel(false);
warnUser(teleportOwner, delay);
initTimer((long) (delay * 1000.0), teleportOwner, null, chargeFor, cause, true);
}
@Deprecated
void respawnNow(final IUser teleportee, final TeleportCause cause) throws Exception {
final Player player = teleportee.getBase();
final Location bed = player.getBedSpawnLocation();
if (bed != null) {
now(teleportee, new LocationTarget(bed), cause);
} else {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("Could not find bed spawn, forcing respawn event.");
}
final PlayerRespawnEvent pre = new PlayerRespawnEvent(player, player.getWorld().getSpawnLocation(), false);
ess.getServer().getPluginManager().callEvent(pre);
now(teleportee, new LocationTarget(pre.getRespawnLocation()), cause);
}
}
//The warp function is a wrapper used to teleportPlayer a player to a /warp
@Override
@Deprecated
public void warp(final IUser teleportee, String warp, final Trade chargeFor, final TeleportCause cause) throws Exception {
final UserWarpEvent event = new UserWarpEvent(teleportee, warp, chargeFor);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
warp = event.getWarp();
final Location loc = ess.getWarps().getWarp(warp);
teleportee.sendMessage(tl("warpingTo", warp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
if (!teleportee.equals(teleportOwner)) {
teleportOwner.sendMessage(tl("warpingTo", warp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
}
teleport(teleportee, new LocationTarget(loc), chargeFor, cause);
}
//The back function is a wrapper used to teleportPlayer a player /back to their previous location.
@Override
@Deprecated
public void back(final Trade chargeFor) throws Exception {
back(teleportOwner, chargeFor);
}
//This function is a wrapper over the other back function for cases where another player performs back for them
@Override
@Deprecated
public void back(final IUser teleporter, final Trade chargeFor) throws Exception {
tpType = TeleportType.BACK;
final Location loc = teleportOwner.getLastLocation();
teleportOwner.sendMessage(tl("backUsageMsg", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
teleportOther(teleporter, teleportOwner, new LocationTarget(loc), chargeFor, TeleportCause.COMMAND);
}
//This function is used to throw a user back after a jail sentence
@Override
@Deprecated
public void back() throws Exception {
now(teleportOwner, new LocationTarget(teleportOwner.getLastLocation()), TeleportCause.COMMAND);
}
@Deprecated
public void setTpType(final TeleportType tpType) {
this.tpType = tpType;
}
//If we need to cancelTimer a pending teleportPlayer call this method
@Deprecated
private void cancel(final boolean notifyUser) {
if (timedTeleport != null) {
timedTeleport.cancelTimer(notifyUser);
timedTeleport = null;
}
}
@Deprecated
private void initTimer(final long delay, final IUser teleportUser, final ITarget target, final Trade chargeFor, final TeleportCause cause, final boolean respawn) {
timedTeleport = new TimedTeleport(teleportOwner, ess, this, delay, teleportUser, target, chargeFor, cause, respawn);
}
public enum TeleportType {
TPA,
BACK,
NORMAL
}
}
@@ -0,0 +1,140 @@
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 static com.earth2me.essentials.I18n.tl;
@Deprecated
public class TimedTeleport implements Runnable {
private static final double MOVE_CONSTANT = 0.3;
private final IUser teleportOwner;
private final IEssentials ess;
private final Teleport teleport;
private final UUID timer_teleportee;
private final long timer_started; // time this task was initiated
private final long timer_delay; // how long to delay the teleportPlayer
// note that I initially stored a clone of the location for reference, but...
// when comparing locations, I got incorrect mismatches (rounding errors, looked like)
// so, the X/Y/Z values are stored instead and rounded off
private final long timer_initX;
private final long timer_initY;
private final long timer_initZ;
private final ITarget timer_teleportTarget;
private final boolean timer_respawn;
private final boolean timer_canMove;
private final Trade timer_chargeFor;
private final TeleportCause timer_cause;
private int timer_task;
private double timer_health;
TimedTeleport(final IUser user, final IEssentials ess, final Teleport teleport, final long delay, final IUser teleportUser, final ITarget target, final Trade chargeFor, final TeleportCause cause, final boolean respawn) {
this.teleportOwner = user;
this.ess = ess;
this.teleport = teleport;
this.timer_started = System.currentTimeMillis();
this.timer_delay = delay;
this.timer_health = teleportUser.getBase().getHealth();
this.timer_initX = Math.round(teleportUser.getBase().getLocation().getX() * MOVE_CONSTANT);
this.timer_initY = Math.round(teleportUser.getBase().getLocation().getY() * MOVE_CONSTANT);
this.timer_initZ = Math.round(teleportUser.getBase().getLocation().getZ() * MOVE_CONSTANT);
this.timer_teleportee = teleportUser.getBase().getUniqueId();
this.timer_teleportTarget = target;
this.timer_chargeFor = chargeFor;
this.timer_cause = cause;
this.timer_respawn = respawn;
this.timer_canMove = user.isAuthorized("essentials.teleport.timer.move");
timer_task = ess.runTaskTimerAsynchronously(this, 20, 20).getTaskId();
}
@Override
public void run() {
if (teleportOwner == null || !teleportOwner.getBase().isOnline() || teleportOwner.getBase().getLocation() == null) {
cancelTimer(false);
return;
}
final IUser teleportUser = ess.getUser(this.timer_teleportee);
if (teleportUser == null || !teleportUser.getBase().isOnline()) {
cancelTimer(false);
return;
}
final Location currLocation = teleportUser.getBase().getLocation();
if (currLocation == null) {
cancelTimer(false);
return;
}
if (!timer_canMove && (Math.round(currLocation.getX() * MOVE_CONSTANT) != timer_initX || Math.round(currLocation.getY() * MOVE_CONSTANT) != timer_initY || Math.round(currLocation.getZ() * MOVE_CONSTANT) != timer_initZ || teleportUser.getBase().getHealth() < timer_health)) {
// user moved, cancelTimer teleportPlayer
cancelTimer(true);
return;
}
class DelayedTeleportTask implements Runnable {
@Override
public void run() {
timer_health = teleportUser.getBase().getHealth(); // in case user healed, then later gets injured
final long now = System.currentTimeMillis();
if (now > timer_started + timer_delay) {
try {
teleport.cooldown(false);
} catch (final Exception ex) {
teleportOwner.sendMessage(tl("cooldownWithMessage", ex.getMessage()));
if (teleportOwner != teleportUser) {
teleportUser.sendMessage(tl("cooldownWithMessage", ex.getMessage()));
}
}
try {
cancelTimer(false);
teleportUser.sendMessage(tl("teleportationCommencing"));
if (timer_chargeFor != null) {
timer_chargeFor.isAffordableFor(teleportOwner);
}
if (timer_respawn) {
teleport.respawnNow(teleportUser, timer_cause);
} else {
teleport.now(teleportUser, timer_teleportTarget, timer_cause);
}
if (timer_chargeFor != null) {
timer_chargeFor.charge(teleportOwner);
}
} catch (final Exception ex) {
ess.showError(teleportOwner.getSource(), ex, "\\ teleport");
}
}
}
}
ess.scheduleSyncDelayedTask(new DelayedTeleportTask());
}
//If we need to cancelTimer a pending teleportPlayer call this method
void cancelTimer(final boolean notifyUser) {
if (timer_task == -1) {
return;
}
try {
ess.getServer().getScheduler().cancelTask(timer_task);
if (notifyUser) {
teleportOwner.sendMessage(tl("pendingTeleportCancelled"));
if (timer_teleportee != null && !timer_teleportee.equals(teleportOwner.getBase().getUniqueId())) {
ess.getUser(timer_teleportee).sendMessage(tl("pendingTeleportCancelled"));
}
}
} finally {
timer_task = -1;
}
}
}
@@ -2,7 +2,6 @@ package com.earth2me.essentials;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.craftbukkit.SetExpFix;
import com.earth2me.essentials.adventure.AdventureUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
@@ -20,11 +19,12 @@ 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;
import static com.earth2me.essentials.I18n.tl;
public class Trade {
private static FileWriter fw = null;
private final transient String command;
@@ -87,14 +87,7 @@ public class Trade {
sb.append(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date()));
sb.append("\",\"");
if (sender != null) {
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(sender);
}
sb.append("\",");
if (charge == null) {
@@ -120,14 +113,7 @@ public class Trade {
}
sb.append(",\"");
if (receiver != null) {
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(receiver);
}
sb.append("\",");
if (pay == null) {
@@ -160,7 +146,7 @@ public class Trade {
sb.append(loc.getBlockY()).append(",");
sb.append(loc.getBlockZ()).append(",");
}
if (endBalance == null) {
sb.append(",");
} else {
@@ -207,23 +193,23 @@ public class Trade {
}
if (getMoney() != null && getMoney().signum() > 0 && !user.canAfford(getMoney())) {
future.completeExceptionally(new ChargeException("notEnoughMoney", AdventureUtil.parsed(NumberUtil.displayCurrency(getMoney(), ess))));
future.completeExceptionally(new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess))));
return;
}
if (getItemStack() != null && !Inventories.containsAtLeast(user.getBase(), itemStack, itemStack.getAmount())) {
future.completeExceptionally(new ChargeException("missingItems", getItemStack().getAmount(), ess.getItemDb().name(getItemStack())));
future.completeExceptionally(new ChargeException(tl("missingItems", getItemStack().getAmount(), ess.getItemDb().name(getItemStack()))));
return;
}
final BigDecimal money;
if (command != null && !command.isEmpty() && (money = getCommandCost(user)).signum() > 0 && !user.canAfford(money)) {
future.completeExceptionally(new ChargeException("notEnoughMoney", AdventureUtil.parsed(NumberUtil.displayCurrency(money, ess))));
future.completeExceptionally(new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(money, ess))));
return;
}
if (exp != null && exp > 0 && SetExpFix.getTotalExperience(user.getBase()) < exp) {
future.completeExceptionally(new ChargeException("notEnoughExperience"));
future.completeExceptionally(new ChargeException(tl("notEnoughExperience")));
}
}
@@ -257,8 +243,8 @@ public class Trade {
} else {
for (final ItemStack itemStack : leftover.values()) {
int spillAmount = itemStack.getAmount();
itemStack.setAmount(Math.min(spillAmount, itemStack.getMaxStackSize()));
while (spillAmount > 0) {
itemStack.setAmount(Math.min(spillAmount, itemStack.getMaxStackSize()));
user.getBase().getWorld().dropItemNaturally(user.getBase().getLocation(), itemStack);
spillAmount -= itemStack.getAmount();
}
@@ -301,7 +287,7 @@ public class Trade {
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " money " + getMoney().toPlainString());
}
if (!user.canAfford(getMoney()) && getMoney().signum() > 0) {
future.completeExceptionally(new ChargeException("notEnoughMoney", AdventureUtil.parsed(NumberUtil.displayCurrency(getMoney(), ess))));
future.completeExceptionally(new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess))));
return;
}
user.takeMoney(getMoney());
@@ -311,7 +297,7 @@ public class Trade {
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " itemstack " + getItemStack().toString());
}
if (!Inventories.containsAtLeast(user.getBase(), getItemStack(), getItemStack().getAmount())) {
future.completeExceptionally(new ChargeException("missingItems", getItemStack().getAmount(), getItemStack().getType().toString().toLowerCase(Locale.ENGLISH).replace("_", " ")));
future.completeExceptionally(new ChargeException(tl("missingItems", getItemStack().getAmount(), getItemStack().getType().toString().toLowerCase(Locale.ENGLISH).replace("_", " "))));
return;
}
Inventories.removeItemAmount(user.getBase(), getItemStack(), getItemStack().getAmount());
@@ -320,7 +306,7 @@ public class Trade {
if (command != null) {
final BigDecimal cost = getCommandCost(user);
if (!user.canAfford(cost) && cost.signum() > 0) {
future.completeExceptionally(new ChargeException("notEnoughMoney", AdventureUtil.parsed(NumberUtil.displayCurrency(cost, ess))));
future.completeExceptionally(new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(cost, ess))));
return;
}
user.takeMoney(cost);
@@ -331,7 +317,7 @@ public class Trade {
}
final int experience = SetExpFix.getTotalExperience(user.getBase());
if (experience < getExperience() && getExperience() > 0) {
future.completeExceptionally(new ChargeException("notEnoughExperience"));
future.completeExceptionally(new ChargeException(tl("notEnoughExperience")));
return;
}
SetExpFix.setTotalExperience(user.getBase(), experience - getExperience());
@@ -1,7 +1,5 @@
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;
@@ -17,13 +15,10 @@ import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.AfkStatusChangeEvent;
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 org.bukkit.Location;
@@ -54,8 +49,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tlLocale;
import static com.earth2me.essentials.I18n.tl;
public class User extends UserData implements Comparable<User>, IMessageRecipient, net.ess3.api.IUser {
private static final Statistic PLAY_ONE_TICK = EnumUtil.getStatistic("PLAY_ONE_MINUTE", "PLAY_ONE_TICK");
@@ -63,11 +57,10 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
// User modules
private final IMessageRecipient messageRecipient;
private transient final AsyncTeleport teleport;
private transient final Teleport legacyTeleport;
// User command confirmation strings
private final Map<User, BigDecimal> confirmingPayments = new WeakHashMap<>();
private String confirmingClearCommand;
private String lastHomeConfirmation;
// User teleport variables
private final transient LinkedHashMap<String, TpaRequest> teleportRequestQueue = new LinkedHashMap<>();
@@ -81,32 +74,30 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
private boolean recipeSee = false;
private boolean enderSee = false;
private boolean ignoreMsg = false;
private Boolean toggleShout;
private boolean freeze = false;
// User afk variables
private String afkMessage;
private long afkSince;
private transient Location afkPosition = null;
// Timestamps
// Misc
private transient long lastOnlineActivity;
private transient long lastThrottledAction;
private transient long lastActivity = System.currentTimeMillis();
private transient long teleportInvulnerabilityTimestamp = 0;
private String confirmingClearCommand;
private long lastNotifiedAboutMailsMs;
private String lastHomeConfirmation;
private long lastHomeConfirmationTimestamp;
// Misc
private Boolean toggleShout;
private boolean freeze = false;
private transient final List<String> signCopy = Lists.newArrayList("", "", "", "");
private transient long lastVanishTime = System.currentTimeMillis();
private transient int flightTick = -1;
private String lastLocaleString;
private Locale playerLocale;
public User(final Player base, final IEssentials ess) {
super(base, ess);
teleport = new AsyncTeleport(this, ess);
legacyTeleport = new Teleport(this, ess);
if (isAfk()) {
afkPosition = this.getLocation();
}
@@ -136,10 +127,6 @@ 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);
@@ -147,25 +134,8 @@ 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);
@@ -182,7 +152,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
private boolean isAuthorizedCheck(final String node) {
if (base instanceof OfflinePlayerStub) {
if (base instanceof OfflinePlayer) {
return false;
}
@@ -199,26 +169,8 @@ 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) {
if (base instanceof OfflinePlayer) {
return false;
}
@@ -236,7 +188,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
private TriState isAuthorizedExactCheck(final String node) {
if (base instanceof OfflinePlayerStub) {
if (base instanceof OfflinePlayer) {
return TriState.UNSET;
}
@@ -263,7 +215,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
cooldownTime.add(Calendar.SECOND, (int) cooldown);
cooldownTime.add(Calendar.MILLISECOND, (int) ((cooldown * 1000.0) % 1000.0));
if (cooldownTime.after(now) && !isAuthorized("essentials.heal.cooldown.bypass")) {
throw new TranslatableException("timeBeforeHeal", DateUtil.formatDateDiff(cooldownTime.getTimeInMillis()));
throw new Exception(tl("timeBeforeHeal", DateUtil.formatDateDiff(cooldownTime.getTimeInMillis())));
}
}
setLastHealTimestamp(now.getTimeInMillis());
@@ -284,9 +236,9 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return;
}
setMoney(getMoney().add(value), cause);
sendTl("addedToAccount", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)));
sendMessage(tl("addedToAccount", NumberUtil.displayCurrency(value, ess)));
if (initiator != null) {
initiator.sendTl("addedToOthersAccount", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)), getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(getMoney(), ess)));
initiator.sendMessage(tl("addedToOthersAccount", NumberUtil.displayCurrency(value, ess), this.getDisplayName(), NumberUtil.displayCurrency(getMoney(), ess)));
}
}
@@ -295,28 +247,20 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
payUser(reciever, value, UserBalanceUpdateEvent.Cause.UNKNOWN);
}
public void payUser(final User reciever, BigDecimal value, final UserBalanceUpdateEvent.Cause cause) throws Exception {
public void payUser(final User reciever, final BigDecimal value, final UserBalanceUpdateEvent.Cause cause) throws Exception {
if (value.compareTo(BigDecimal.ZERO) < 1) {
throw new Exception(tlLocale(playerLocale, "payMustBePositive"));
throw new Exception(tl("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());
reciever.sendTl("moneyRecievedFrom", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)), getDisplayName());
sendMessage(tl("moneySentTo", NumberUtil.displayCurrency(value, ess), reciever.getDisplayName()));
reciever.sendMessage(tl("moneyRecievedFrom", NumberUtil.displayCurrency(value, ess), getDisplayName()));
final TransactionEvent transactionEvent = new TransactionEvent(this.getSource(), reciever, value);
ess.getServer().getPluginManager().callEvent(transactionEvent);
} else {
throw new ChargeException("notEnoughMoney", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)));
throw new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(value, ess)));
}
}
@@ -339,9 +283,9 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
} catch (final MaxMoneyException ex) {
ess.getLogger().log(Level.WARNING, "Invalid call to takeMoney, total balance can't be more than the max-money limit.", ex);
}
sendTl("takenFromAccount", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)));
sendMessage(tl("takenFromAccount", NumberUtil.displayCurrency(value, ess)));
if (initiator != null) {
initiator.sendTl("takenFromOthersAccount", AdventureUtil.parsed(NumberUtil.displayCurrency(value, ess)), getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(getMoney(), ess)));
initiator.sendMessage(tl("takenFromOthersAccount", NumberUtil.displayCurrency(value, ess), this.getDisplayName(), NumberUtil.displayCurrency(getMoney(), ess)));
}
}
@@ -367,7 +311,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
private void _dispose() {
if (!base.isOnline()) {
this.base = new OfflinePlayerStub(getConfigUUID(), ess.getServer());
this.base = new OfflinePlayer(getConfigUUID(), ess.getServer());
}
cleanup();
}
@@ -381,9 +325,8 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return true;
if (VersionUtil.PRE_FLATTENING) {
//noinspection deprecation
final int id = material.getId();
return isAuthorized("essentials.itemspawn.item-" + id);
if (isAuthorized("essentials.itemspawn.item-" + id)) return true;
}
return false;
@@ -420,6 +363,12 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
teleportRequestQueue.put(request.getName(), request);
}
@Override
@Deprecated
public boolean hasOutstandingTeleportRequest() {
return getNextTpaRequest(false, false, false) != null;
}
public Collection<String> getPendingTpaKeys() {
return teleportRequestQueue.keySet();
}
@@ -446,7 +395,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
teleportRequestQueue.remove(playerUsername);
if (inform) {
sendTl("requestTimedOutFrom", ess.getUser(request.getRequesterUuid()).getDisplayName());
sendMessage(tl("requestTimedOutFrom", ess.getUser(request.getRequesterUuid()).getDisplayName()));
}
return null;
}
@@ -480,7 +429,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
} else {
if (inform) {
sendTl("requestTimedOutFrom", ess.getUser(request.getRequesterUuid()).getDisplayName());
sendMessage(tl("requestTimedOutFrom", ess.getUser(request.getRequesterUuid()).getDisplayName()));
}
teleportRequestQueue.remove(key);
}
@@ -495,15 +444,14 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
/**
* Needed for backwards compatibility.
*/
public String getNick(@SuppressWarnings("unused") final boolean longNick) {
public String getNick(final boolean longnick) {
return getNick(true, true);
}
/**
* Needed for backwards compatibility.
*/
@SuppressWarnings("unused")
public String getNick(@SuppressWarnings("unused") final boolean longNick, final boolean withPrefix, final boolean withSuffix) {
public String getNick(final boolean longnick, final boolean withPrefix, final boolean withSuffix) {
return getNick(withPrefix, withSuffix);
}
@@ -585,7 +533,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public String getDisplayName() {
//noinspection ConstantConditions
return super.getBase().getDisplayName() == null || (ess.getSettings().hideDisplayNameInVanish() && isHidden()) ? super.getBase().getName() : super.getBase().getDisplayName();
}
@@ -603,6 +550,15 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return teleport;
}
/**
* @deprecated This API is not asynchronous. Use {@link User#getAsyncTeleport()}
*/
@Override
@Deprecated
public Teleport getTeleport() {
return legacyTeleport;
}
public long getLastOnlineActivity() {
return lastOnlineActivity;
}
@@ -617,8 +573,7 @@ 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, String.format(Locale.ROOT,
"Lag Notice - Slow Economy Response - Request took over %.3fms!", elapsed / 1_000_000.0));
ess.getLogger().log(Level.INFO, "Lag Notice - Slow Economy Response - Request took over {0}ms!", elapsed / 1000000.0);
}
return value;
}
@@ -674,7 +629,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
}
@SuppressWarnings("deprecation")
@Override
public void setAfk(final boolean set) {
setAfk(set, AfkStatusChangeEvent.Cause.UNKNOWN);
@@ -688,7 +642,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();
@@ -725,9 +679,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public boolean isHiddenFrom(Player player) {
if (getBase() instanceof OfflinePlayerStub || player instanceof OfflinePlayerStub) {
return true;
}
return !player.canSee(getBase());
}
@@ -755,7 +706,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
public boolean isHidden(final Player player) {
return hidden || isHiddenFrom(player);
return hidden || !player.canSee(getBase());
}
@Override
@@ -768,7 +719,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
//Returns true if status expired during this check
@SuppressWarnings("UnusedReturnValue")
public boolean checkJailTimeout(final long currentTime) {
if (getJailTimeout() > 0) {
@@ -786,7 +736,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
setJailTimeout(0);
setOnlineJailedTime(0);
setJailed(false);
sendTl("haveBeenReleased");
sendMessage(tl("haveBeenReleased"));
setJail(null);
if (ess.getSettings().getTeleportWhenFreePolicy() == ISettings.TeleportWhenFreePolicy.BACK) {
final CompletableFuture<Boolean> future = new CompletableFuture<>();
@@ -806,7 +756,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
//Returns true if status expired during this check
@SuppressWarnings("UnusedReturnValue")
public boolean checkMuteTimeout(final long currentTime) {
if (getMuteTimeout() > 0 && getMuteTimeout() < currentTime && isMuted()) {
final MuteStatusChangeEvent event = new MuteStatusChangeEvent(this, null, false, getMuteTimeout(), getMuteReason());
@@ -814,7 +763,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
if (!event.isCancelled()) {
setMuteTimeout(0);
sendTl("canTalkAgain");
sendMessage(tl("canTalkAgain"));
setMuted(false);
setMuteReason(null);
return true;
@@ -823,29 +772,6 @@ 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);
@@ -856,10 +782,15 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
setAfk(false, cause);
if (broadcast && !isHidden() && !isAfk()) {
setDisplayNick();
if (ess.getSettings().broadcastAfkMessage()) {
ess.broadcastTl(this, u -> u == this, "userIsNotAway", getDisplayName());
final String msg = tl("userIsNotAway", getDisplayName());
final String selfmsg = tl("userIsNotAwaySelf", getDisplayName());
if (!msg.isEmpty() && ess.getSettings().broadcastAfkMessage()) {
// exclude user from receiving general AFK announcement in favor of personal message
ess.broadcastMessage(this, msg, u -> u == this);
}
if (!selfmsg.isEmpty()) {
this.sendMessage(selfmsg);
}
sendTl("userIsNotAwaySelf", getDisplayName());
}
}
lastActivity = System.currentTimeMillis();
@@ -880,56 +811,47 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
public void updateActivityOnChat(final boolean broadcast) {
if (ess.getSettings().cancelAfkOnChat()) {
//Chat happens async, make sure we have a sync context
ess.scheduleSyncDelayedTask(() -> updateActivity(broadcast, AfkStatusChangeEvent.Cause.CHAT));
ess.scheduleSyncDelayedTask(() -> {
updateActivity(broadcast, AfkStatusChangeEvent.Cause.CHAT);
});
}
}
public void checkActivity() {
// Graceful time before the first afk check call.
// Graceful time before the first afk check call.
if (System.currentTimeMillis() - lastActivity <= 10000) {
return;
}
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()
final long autoafkkick = ess.getSettings().getAutoAfkKick();
if (autoafkkick > 0
&& lastActivity > 0 && (lastActivity + (autoafkkick * 1000)) < System.currentTimeMillis()
&& !isAuthorized("essentials.kick.exempt")
&& !isAuthorized("essentials.afk.kickexempt")) {
final String kickReason = tl("autoAfkKickReason", autoafkkick / 60.0);
lastActivity = 0;
final double kickTime = autoafktimeout / 60.0;
this.getBase().kickPlayer(kickReason);
// 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.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);
for (final User user : ess.getOnlineUsers()) {
if (user.isAuthorized("essentials.kick.notify")) {
user.sendMessage(tl("playerKicked", Console.DISPLAY_NAME, getName(), kickReason));
}
}
}
final long autoafk = ess.getSettings().getAutoAfk();
if (!isAfk() && autoafk > 0 && lastActivity + autoafk * 1000 < System.currentTimeMillis() && isAuthorizedCached("essentials.afk.auto")) {
if (!isAfk() && autoafk > 0 && lastActivity + autoafk * 1000 < System.currentTimeMillis() && isAuthorized("essentials.afk.auto")) {
setAfk(true, AfkStatusChangeEvent.Cause.ACTIVITY);
if (isAfk() && !isHidden()) {
setDisplayNick();
if (ess.getSettings().broadcastAfkMessage()) {
ess.broadcastTl(this, u -> u == this, "userIsAway", getDisplayName());
final String msg = tl("userIsAway", getDisplayName());
final String selfmsg = tl("userIsAwaySelf", getDisplayName());
if (!msg.isEmpty() && ess.getSettings().broadcastAfkMessage()) {
// exclude user from receiving general AFK announcement in favor of personal message
ess.broadcastMessage(this, msg, u -> u == this);
}
if (!selfmsg.isEmpty()) {
this.sendMessage(selfmsg);
}
sendTl("userIsAwaySelf", getDisplayName());
}
}
}
@@ -944,7 +866,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
// This enables the no-god-in-worlds functionality where the actual player god mode state is never modified in disabled worlds,
// but this method gets called every time the player takes damage. In the case that the world has god-mode disabled then this method
// will return false and the player will take damage, even though they are in god mode (isGodModeEnabledRaw()).
//noinspection ConstantConditions
if (!ess.getSettings().getNoGodWorlds().contains(this.getLocation().getWorld().getName())) {
return true;
}
@@ -986,7 +907,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
return ess.getPermissionsHandler().canBuild(base, getGroup());
}
@SuppressWarnings("deprecation")
@Override
@Deprecated
public long getTeleportRequestTime() {
@@ -1055,7 +975,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
if (set) {
for (final User user : ess.getOnlineUsers()) {
if (!user.isAuthorized("essentials.vanish.see")) {
//noinspection deprecation
user.getBase().hidePlayer(getBase());
}
}
@@ -1071,7 +990,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
} else {
for (final Player p : ess.getOnlinePlayers()) {
//noinspection deprecation
p.showPlayer(getBase());
}
setHidden(false);
@@ -1131,52 +1049,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
}
@Override
public void sendComponent(ComponentHolder component) {
ess.getAdventureFacet().send(base, component);
}
@Override
public ComponentHolder tlComponent(String tlKey, Object... args) {
final String translation = playerTl(tlKey, args);
return ess.getAdventureFacet().deserializeMiniMessage(translation);
}
@Override
public void sendTl(String tlKey, Object... args) {
final String translation = playerTl(tlKey, args);
if (translation.trim().isEmpty()) {
return;
}
sendComponent(ess.getAdventureFacet().deserializeMiniMessage(translation));
}
@Override
public String playerTl(String tlKey, Object... args) {
if (ess.getSettings().isPerPlayerLocale()) {
final PlayerLocaleProvider provider = ess.provider(PlayerLocaleProvider.class);
final Locale locale = base != null ? getPlayerLocale(provider.getLocale(base)) : playerLocale;
if (locale != null) {
return tlLocale(locale, tlKey, args);
}
}
return tlLiteral(tlKey, args);
}
@Override
public String tlSender(String tlKey, Object... args) {
return playerTl(tlKey, args);
}
public Locale getPlayerLocale(final String locale) {
if (locale == null || locale.equals(lastLocaleString)) {
return playerLocale;
}
lastLocaleString = locale;
return playerLocale = I18n.getLocale(locale);
}
@Override
public int compareTo(final User other) {
return FormatUtil.stripFormat(getDisplayName()).compareToIgnoreCase(FormatUtil.stripFormat(other.getDisplayName()));
@@ -1198,7 +1070,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public CommandSource getSource() {
return new CommandSource(ess, getBase());
return new CommandSource(getBase());
}
@Override
@@ -1283,7 +1155,6 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
ess.getMail().sendMail(this, sender, message, expireAt);
}
@SuppressWarnings("deprecation")
@Override
@Deprecated
public void addMail(String mail) {
@@ -1295,7 +1166,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
if (unread != 0) {
final int notifyPlayerOfMailCooldown = ess.getSettings().getNotifyPlayerOfMailCooldown() * 1000;
if (System.currentTimeMillis() - lastNotifiedAboutMailsMs >= notifyPlayerOfMailCooldown) {
sendTl("youHaveNewMail", unread);
sendMessage(tl("youHaveNewMail", unread));
lastNotifiedAboutMailsMs = System.currentTimeMillis();
}
}
@@ -1368,12 +1239,4 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
return toggleShout == null ? toggleShout = ess.getSettings().isShoutDefault() : toggleShout;
}
public int getFlightTick() {
return flightTick;
}
public void setFlightTick(int flightTick) {
this.flightTick = flightTick;
}
}
@@ -11,13 +11,13 @@ import com.earth2me.essentials.utils.StringUtil;
import com.google.common.base.Charsets;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.TranslatableException;
import net.essentialsx.api.v2.services.mail.MailMessage;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.spongepowered.configurate.serialize.SerializationException;
import java.io.File;
import java.math.BigDecimal;
@@ -32,19 +32,19 @@ import java.util.UUID;
import java.util.logging.Level;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
public abstract class UserData extends PlayerExtension implements IConf {
protected final transient Essentials ess;
protected final transient IEssentials ess;
private final EssentialsUserConfiguration config;
private UserConfigHolder holder;
private BigDecimal money;
protected UserData(final Player base, final IEssentials ess) {
super(base);
this.ess = (Essentials) ess;
this.ess = ess;
final File folder = new File(ess.getDataFolder(), "userdata");
// 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()) {
if (!folder.exists() && !folder.mkdirs()) {
throw new RuntimeException("Unable to create userdata folder!");
}
@@ -76,7 +76,6 @@ public abstract class UserData extends PlayerExtension implements IConf {
public final void cleanup() {
config.blockingSave();
ess.getUsers().removeCache(getConfigUUID());
}
@Override
@@ -84,7 +83,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
config.load();
try {
holder = config.getRootNode().get(UserConfigHolder.class);
} catch (Throwable e) {
} catch (SerializationException e) {
ess.getLogger().log(Level.SEVERE, "Error while reading user config: " + config.getFile().getName(), e);
throw new RuntimeException(e);
}
@@ -196,7 +195,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
holder.homes().remove(search);
config.save();
} else {
throw new TranslatableException("invalidHome", search);
throw new Exception(tl("invalidHome", search));
}
}
@@ -206,7 +205,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
holder.homes().put(StringUtil.safeString(newName), location);
config.save();
} else {
throw new TranslatableException("invalidHome", name);
throw new Exception(tl("invalidHome", name));
}
}
@@ -274,10 +273,6 @@ 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;
@@ -355,17 +350,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
}
public int getMailAmount() {
if (holder.mail() == null) {
return 0;
}
int amount = 0;
for (MailMessage element : holder.mail()) {
if (!element.isExpired()) {
amount++;
}
}
return amount;
return holder.mail() == null ? 0 : holder.mail().size();
}
public int getUnreadMailAmount() {
@@ -375,7 +360,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
int unread = 0;
for (MailMessage element : holder.mail()) {
if (!element.isRead() && !element.isExpired()) {
if (!element.isRead()) {
unread++;
}
}
@@ -471,15 +456,6 @@ 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();
}
@@ -40,7 +40,7 @@ public class UserMap {
if (player instanceof Player) {
userPlayer = (Player) player;
} else {
final OfflinePlayerStub essPlayer = new OfflinePlayerStub(player.getUniqueId(), Bukkit.getServer());
final com.earth2me.essentials.OfflinePlayer essPlayer = new com.earth2me.essentials.OfflinePlayer(player.getUniqueId(), Bukkit.getServer());
essPlayer.setName(player.getName());
userPlayer = essPlayer;
}
@@ -1,11 +1,10 @@
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.StringUtil;
import net.ess3.api.InvalidNameException;
import net.ess3.api.TranslatableException;
import net.ess3.api.InvalidWorldException;
import org.bukkit.Location;
import java.io.File;
@@ -18,7 +17,7 @@ import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public class Warps implements IConf, net.ess3.api.IWarps {
private final Map<StringIgnoreCase, EssentialsConfiguration> warpPoints = new HashMap<>();
@@ -53,7 +52,7 @@ public class Warps implements IConf, net.ess3.api.IWarps {
}
@Override
public Location getWarp(final String warp) throws WarpNotFoundException {
public Location getWarp(final String warp) throws WarpNotFoundException, InvalidWorldException {
final EssentialsConfiguration conf = warpPoints.get(new StringIgnoreCase(warp));
if (conf == null) {
throw new WarpNotFoundException();
@@ -78,7 +77,7 @@ public class Warps implements IConf, net.ess3.api.IWarps {
if (conf == null) {
final File confFile = new File(warpsFolder, filename + ".yml");
if (confFile.exists()) {
throw new TranslatableException("similarWarpExist");
throw new Exception(tl("similarWarpExist"));
}
conf = new EssentialsConfiguration(confFile);
conf.load();
@@ -110,10 +109,10 @@ public class Warps implements IConf, net.ess3.api.IWarps {
public void removeWarp(final String name) throws Exception {
final EssentialsConfiguration conf = warpPoints.get(new StringIgnoreCase(name));
if (conf == null) {
throw new TranslatableException("warpNotExist");
throw new Exception(tl("warpNotExist"));
}
if (!conf.getFile().delete()) {
throw new TranslatableException("warpDeleteError");
throw new Exception(tl("warpDeleteError"));
}
warpPoints.remove(new StringIgnoreCase(name));
}
@@ -122,7 +121,7 @@ public class Warps implements IConf, net.ess3.api.IWarps {
public final void reloadConfig() {
warpPoints.clear();
final File[] listOfFiles = warpsFolder.listFiles();
if (listOfFiles != null) {
if (listOfFiles.length >= 1) {
for (final File listOfFile : listOfFiles) {
final String filename = listOfFile.getName();
if (listOfFile.isFile() && filename.endsWith(".yml")) {
@@ -134,7 +133,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.getAdventureFacet().miniToLegacy(tlLiteral("loadWarpError", filename)), ex);
Essentials.getWrappedLogger().log(Level.WARNING, tl("loadWarpError", filename), ex);
}
}
}
@@ -5,7 +5,6 @@ import com.earth2me.essentials.config.ConfigurateUtil;
import com.earth2me.essentials.config.EssentialsConfiguration;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.TranslatableException;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.spongepowered.configurate.CommentedConfigurationNode;
@@ -14,6 +13,8 @@ import java.io.File;
import java.math.BigDecimal;
import java.util.Locale;
import static com.earth2me.essentials.I18n.tl;
public class Worth implements IConf {
private final EssentialsConfiguration config;
@@ -77,7 +78,7 @@ public class Worth implements IConf {
*/
public int getAmount(final IEssentials ess, final User user, final ItemStack is, final String[] args, final boolean isBulkSell) throws Exception {
if (is == null || is.getType() == Material.AIR) {
throw new TranslatableException("itemSellAir");
throw new Exception(tl("itemSellAir"));
}
int amount = 0;
@@ -97,7 +98,7 @@ public class Worth implements IConf {
final boolean requireStack = ess.getSettings().isTradeInStacks(is.getType());
if (requireStack && !stack) {
throw new TranslatableException("itemMustBeStacked");
throw new Exception(tl("itemMustBeStacked"));
}
int max = 0;
@@ -120,9 +121,9 @@ public class Worth implements IConf {
}
if (amount > max || amount < 1) {
if (!isBulkSell) {
user.sendTl("itemNotEnough2");
user.sendTl("itemNotEnough3");
throw new TranslatableException("itemNotEnough1");
user.sendMessage(tl("itemNotEnough2"));
user.sendMessage(tl("itemNotEnough3"));
throw new Exception(tl("itemNotEnough1"));
} else {
return amount;
}
@@ -1,62 +0,0 @@
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;
}
}
}
@@ -1,155 +0,0 @@
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,13 +323,7 @@ public class Economy {
throw new IllegalArgumentException("Economy user cannot be null");
}
final BigDecimal result = getMoneyExact(user).add(amount, MATH_CONTEXT);
// 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);
}
setMoney(user, result);
Trade.log("API", "Add", "API", user.getName(), new Trade(amount, ess), null, null, null, result, ess);
}
@@ -46,6 +46,17 @@ public interface IJails extends IConf {
*/
void removeJail(String jail) throws Exception;
/**
* Attempts to send the given user to the given jail
*
* @param user the user to send to jail
* @param jail the jail to send the user to
* @throws Exception if the user is offline or jail does not exist
* @deprecated Use {@link IJails#sendToJail(IUser, String, CompletableFuture)}
*/
@Deprecated
void sendToJail(IUser user, String jail) throws Exception;
/**
* Attempts to send the given user to the given jail
*
@@ -22,8 +22,9 @@ public interface IWarps extends IConf {
* @param warp - Warp name
* @return - Location the warp is set to
* @throws WarpNotFoundException When the warp is not found
* @throws net.ess3.api.InvalidWorldException When the world the warp is in is not found
*/
Location getWarp(String warp) throws WarpNotFoundException;
Location getWarp(String warp) throws WarpNotFoundException, net.ess3.api.InvalidWorldException;
/**
* Checks if the provided name is a warp.
@@ -1,16 +1,16 @@
package com.earth2me.essentials.api;
import net.ess3.api.TranslatableException;
import static com.earth2me.essentials.I18n.tl;
/**
* @deprecated This exception is unused. Use {@link net.ess3.api.InvalidWorldException} instead.
*/
@Deprecated
public class InvalidWorldException extends TranslatableException {
public class InvalidWorldException extends Exception {
private final String world;
public InvalidWorldException(final String world) {
super("invalidWorld");
super(tl("invalidWorld"));
this.world = world;
}
@@ -1,18 +1,18 @@
package com.earth2me.essentials.api;
import net.ess3.api.TranslatableException;
import java.util.UUID;
import static com.earth2me.essentials.I18n.tl;
/**
* Thrown when the requested user does not exist.
*/
public class UserDoesNotExistException extends TranslatableException {
public class UserDoesNotExistException extends Exception {
public UserDoesNotExistException(final String name) {
super("userDoesNotExist", name);
super(tl("userDoesNotExist", name));
}
public UserDoesNotExistException(final UUID uuid) {
super("uuidDoesNotExist", uuid.toString());
super(tl("uuidDoesNotExist", uuid.toString()));
}
}
@@ -3,13 +3,14 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.DateUtil;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.AfkStatusChangeEvent;
import org.bukkit.Server;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandafk extends EssentialsCommand {
public Commandafk() {
super("afk");
@@ -49,23 +50,17 @@ public class Commandafk extends EssentialsCommand {
if (sender.isMuted()) {
final String dateDiff = sender.getMuteTimeout() > 0 ? DateUtil.formatDateDiff(sender.getMuteTimeout()) : null;
if (dateDiff == null) {
if (sender.hasMuteReason()) {
throw new TranslatableException("voiceSilencedReason", sender.getMuteReason());
} else {
throw new TranslatableException("voiceSilenced");
}
}
if (sender.hasMuteReason()) {
throw new TranslatableException("voiceSilencedReasonTime", dateDiff, sender.getMuteReason());
} else {
throw new TranslatableException("voiceSilencedTime", dateDiff);
throw new Exception(sender.hasMuteReason() ? tl("voiceSilencedReason", sender.getMuteReason()) : tl("voiceSilenced"));
}
throw new Exception(sender.hasMuteReason() ? tl("voiceSilencedReasonTime", dateDiff, sender.getMuteReason()) : tl("voiceSilencedTime", dateDiff));
}
if (!sender.isAuthorized("essentials.afk.message")) {
throw new TranslatableException("noPermToAFKMessage");
throw new Exception(tl("noPermToAFKMessage"));
}
}
user.setDisplayNick();
String msg = "";
String selfmsg = "";
final boolean currentStatus = user.isAfk();
final boolean afterStatus = user.toggleAfk(AfkStatusChangeEvent.Cause.COMMAND);
@@ -73,40 +68,38 @@ public class Commandafk extends EssentialsCommand {
return;
}
String tlKey = "";
String selfTlKey = "";
if (!afterStatus) {
if (!user.isHidden()) {
tlKey = "userIsNotAway";
selfTlKey = "userIsNotAwaySelf";
msg = tl("userIsNotAway", user.getDisplayName());
selfmsg = tl("userIsNotAwaySelf", user.getDisplayName());
}
user.updateActivity(false, AfkStatusChangeEvent.Cause.COMMAND);
} else {
if (!user.isHidden()) {
if (message != null) {
tlKey = "userIsAwayWithMessage";
selfTlKey = "userIsAwaySelfWithMessage";
msg = tl("userIsAwayWithMessage", user.getDisplayName(), message);
selfmsg = tl("userIsAwaySelfWithMessage", user.getDisplayName(), message);
} else {
tlKey = "userIsAway";
selfTlKey = "userIsAwaySelf";
msg = tl("userIsAway", user.getDisplayName());
selfmsg = tl("userIsAwaySelf", user.getDisplayName());
}
}
user.setAfkMessage(message);
}
if (!tlKey.isEmpty() && ess.getSettings().broadcastAfkMessage()) {
if (!msg.isEmpty() && ess.getSettings().broadcastAfkMessage()) {
// exclude user from receiving general AFK announcement in favor of personal message
ess.broadcastTl(user, u -> u == user, tlKey, user.getDisplayName(), message);
ess.broadcastMessage(user, msg, u -> u == user);
}
if (!selfTlKey.isEmpty()) {
user.sendTl(selfTlKey, user.getDisplayName(), message);
if (!selfmsg.isEmpty()) {
user.sendMessage(selfmsg);
}
user.setDisplayNick(); // Set this again after toggling
}
@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(sender);
if (args.length == 1 && sender.isAuthorized("essentials.afk.others", ess)) {
return getPlayers(server, sender);
} else {
return Collections.emptyList();
}
@@ -1,9 +1,10 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.provider.ContainerProvider;
import org.bukkit.Server;
import static com.earth2me.essentials.I18n.tl;
public class Commandanvil extends EssentialsCommand {
public Commandanvil() {
@@ -12,13 +13,11 @@ public class Commandanvil extends EssentialsCommand {
@Override
protected void run(Server server, User user, String commandLabel, String[] args) throws Exception {
final ContainerProvider containerProvider = ess.provider(ContainerProvider.class);
if (containerProvider == null) {
user.sendTl("unsupportedBrand");
if (ess.getContainerProvider() == null) {
user.sendMessage(tl("unsupportedBrand"));
return;
}
containerProvider.openAnvil(user.getBase());
ess.getContainerProvider().openAnvil(user.getBase());
}
}
@@ -3,12 +3,13 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import net.ess3.api.TranslatableException;
import org.bukkit.Server;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandback extends EssentialsCommand {
public Commandback() {
super("back");
@@ -36,13 +37,13 @@ public class Commandback extends EssentialsCommand {
private void parseOthers(final Server server, final CommandSource sender, final String[] args, final String commandLabel) throws Exception {
final User player = getPlayer(server, args, 0, true, false);
sender.sendTl("backOther", player.getName());
sender.sendMessage(tl("backOther", player.getName()));
teleportBack(sender, player, commandLabel);
}
private void teleportBack(final CommandSource sender, final User user, final String commandLabel) throws Exception {
if (user.getLastLocation() == null) {
throw new TranslatableException("noLocationFound");
throw new Exception(tl("noLocationFound"));
}
final String lastWorldName = user.getLastLocation().getWorld().getName();
@@ -52,11 +53,11 @@ public class Commandback extends EssentialsCommand {
requester = ess.getUser(sender.getPlayer());
if (user.getWorld() != user.getLastLocation().getWorld() && this.ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + lastWorldName)) {
throw new TranslatableException("noPerm", "essentials.worlds." + lastWorldName);
throw new Exception(tl("noPerm", "essentials.worlds." + lastWorldName));
}
if (!requester.isAuthorized("essentials.back.into." + lastWorldName)) {
throw new TranslatableException("noPerm", "essentials.back.into." + lastWorldName);
throw new Exception(tl("noPerm", "essentials.back.into." + lastWorldName));
}
}
@@ -77,7 +78,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(user);
return getPlayers(server, user);
} else {
return Collections.emptyList();
}
@@ -2,9 +2,10 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.Backup;
import com.earth2me.essentials.CommandSource;
import net.ess3.api.TranslatableException;
import org.bukkit.Server;
import static com.earth2me.essentials.I18n.tl;
public class Commandbackup extends EssentialsCommand {
public Commandbackup() {
super("backup");
@@ -14,13 +15,13 @@ public class Commandbackup extends EssentialsCommand {
protected void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
final Backup backup = ess.getBackup();
if (backup == null) {
throw new TranslatableException("backupDisabled");
throw new Exception(tl("backupDisabled"));
}
final String command = ess.getSettings().getBackupCommand();
if (command == null || "".equals(command) || "save-all".equalsIgnoreCase(command)) {
throw new TranslatableException("backupDisabled");
throw new Exception(tl("backupDisabled"));
}
backup.run();
sender.sendTl("backupStarted");
sender.sendMessage(tl("backupStarted"));
}
}
@@ -2,13 +2,14 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.adventure.AdventureUtil;
import com.earth2me.essentials.utils.NumberUtil;
import org.bukkit.Server;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandbalance extends EssentialsCommand {
public Commandbalance() {
super("balance");
@@ -20,17 +21,17 @@ public class Commandbalance extends EssentialsCommand {
throw new NotEnoughArgumentsException();
}
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)));
final User target = getPlayer(server, args, 0, false, true);
sender.sendMessage(tl("balanceOther", target.isHidden() ? target.getName() : target.getDisplayName(), 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, false, true);
user.sendTl("balanceOther", target.isHidden() ? target.getName() : target.getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(target.getMoney(), ess)));
final User target = getPlayer(server, args, 0, true, true);
user.sendMessage(tl("balanceOther", target.isHidden() ? target.getName() : target.getDisplayName(), NumberUtil.displayCurrency(target.getMoney(), ess)));
} else if (args.length < 2) {
user.sendTl("balance", AdventureUtil.parsed(NumberUtil.displayCurrency(user.getMoney(), ess)));
user.sendMessage(tl("balance", NumberUtil.displayCurrency(user.getMoney(), ess)));
} else {
throw new NotEnoughArgumentsException();
}
@@ -38,8 +39,8 @@ 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(sender);
if (args.length == 1 && sender.isAuthorized("essentials.balance.others", ess)) {
return getPlayers(server, sender);
} else {
return Collections.emptyList();
}
@@ -1,18 +1,12 @@
package com.earth2me.essentials.commands;
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.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;
import org.bukkit.Server;
import org.bukkit.Statistic;
import org.bukkit.command.BlockCommandSender;
import java.math.BigDecimal;
@@ -24,7 +18,7 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public class Commandbalancetop extends EssentialsCommand {
public static final int MINUSERS = 50;
@@ -40,7 +34,7 @@ public class Commandbalancetop extends EssentialsCommand {
cal.setTimeInMillis(ess.getBalanceTop().getCacheAge());
final DateFormat format = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
final Runnable runnable = () -> {
sender.sendTl("balanceTop", format.format(cal.getTime()));
sender.sendMessage(tl("balanceTop", format.format(cal.getTime())));
new TextPager(cache).showPage(Integer.toString(page), null, "balancetop", sender);
};
if (sender.getSender() instanceof BlockCommandSender) {
@@ -71,7 +65,7 @@ public class Commandbalancetop extends EssentialsCommand {
// If there are less than 50 users in our usermap, there is no need to display a warning as these calculations should be done quickly
if (ess.getUsers().getUserCount() > MINUSERS) {
sender.sendTl("orderBalances", ess.getUsers().getUserCount());
sender.sendMessage(tl("orderBalances", ess.getUsers().getUserCount()));
}
ess.runTaskAsynchronously(new Viewer(sender, page, force));
@@ -115,38 +109,17 @@ public class Commandbalancetop extends EssentialsCommand {
future.thenRun(() -> {
if (fresh) {
final SimpleTextInput newCache = new SimpleTextInput();
newCache.getLines().add(ess.getAdventureFacet().miniToLegacy(tlLiteral("serverTotal", AdventureUtil.parsed(NumberUtil.displayCurrency(ess.getBalanceTop().getBalanceTopTotal(), ess)))));
newCache.getLines().add(tl("serverTotal", 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()) {
if (offlineStatisticSupported) {
playtime = Bukkit.getServer().getOfflinePlayer(entry.getKey()).getStatistic(PLAY_ONE_TICK);
} else {
playtime = -1;
}
} else {
playtime = user.getBase().getStatistic(PLAY_ONE_TICK);
}
// Play time in seconds
final long playTimeSecs = Math.max(playtime / 20, 0);
// 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 &&
// 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)))));
if (ess.getSettings().showZeroBaltop() || entry.getValue().getBalance().compareTo(BigDecimal.ZERO) > 0) {
newCache.getLines().add(tl("balanceTopLine", pos, entry.getValue().getDisplayName(), NumberUtil.displayCurrency(entry.getValue().getBalance(), ess)));
}
pos++;
}
cache = newCache;
}
outputCache(sender, page);
});
}
@@ -2,10 +2,9 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.Console;
import com.earth2me.essentials.OfflinePlayerStub;
import com.earth2me.essentials.OfflinePlayer;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import net.ess3.api.TranslatableException;
import org.bukkit.BanList;
import org.bukkit.Server;
@@ -13,7 +12,7 @@ import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public class Commandban extends EssentialsCommand {
public Commandban() {
@@ -31,43 +30,43 @@ public class Commandban extends EssentialsCommand {
user = getPlayer(server, args, 0, true, true);
} catch (final PlayerNotFoundException e) {
nomatch = true;
user = ess.getUser(new OfflinePlayerStub(args[0], ess.getServer()));
user = ess.getUser(new OfflinePlayer(args[0], ess.getServer()));
}
if (!user.getBase().isOnline()) {
if (sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.ban.offline")) {
throw new TranslatableException("banExemptOffline");
throw new Exception(tl("banExemptOffline"));
}
} else if (user.isAuthorized("essentials.ban.exempt") && sender.isPlayer()) {
throw new TranslatableException("banExempt");
throw new Exception(tl("banExempt"));
}
final String senderName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.NAME;
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.displayName();
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.DISPLAY_NAME;
final String banReason;
if (args.length > 1) {
banReason = FormatUtil.replaceFormat(getFinalArg(args, 1).replace("\\n", "\n").replace("|", "\n"));
} else {
banReason = tlLiteral("defaultBanReason");
banReason = tl("defaultBanReason");
}
ess.getServer().getBanList(BanList.Type.NAME).addBan(user.getName(), banReason, null, senderName);
final String banDisplay = tlLiteral("banFormat", banReason, senderDisplayName);
final String banDisplay = tl("banFormat", banReason, senderDisplayName);
user.getBase().kickPlayer(ess.getAdventureFacet().miniToLegacy(banDisplay));
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("playerBanned", senderDisplayName, user.getName(), banDisplay)));
user.getBase().kickPlayer(banDisplay);
ess.getLogger().log(Level.INFO, tl("playerBanned", senderDisplayName, user.getName(), banDisplay));
if (nomatch) {
sender.sendTl("userUnknown", user.getName());
sender.sendMessage(tl("userUnknown", user.getName()));
}
ess.broadcastTl(null, u -> !u.isAuthorized("essentials.ban.notify"), "playerBanned", senderDisplayName, user.getName(), banReason);
ess.broadcastMessage("essentials.ban.notify", tl("playerBanned", senderDisplayName, user.getName(), banReason));
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
if (args.length == 1) {
return getPlayers(sender);
return getPlayers(server, sender);
} else {
return Collections.emptyList();
}
@@ -12,7 +12,7 @@ import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public class Commandbanip extends EssentialsCommand {
public Commandbanip() {
@@ -26,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.displayName();
final String senderDisplayName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.DISPLAY_NAME;
String ipAddress;
if (FormatUtil.validIP(args[0])) {
@@ -48,13 +48,13 @@ public class Commandbanip extends EssentialsCommand {
if (args.length > 1) {
banReason = FormatUtil.replaceFormat(getFinalArg(args, 1).replace("\\n", "\n").replace("|", "\n"));
} else {
banReason = tlLiteral("defaultBanReason");
banReason = tl("defaultBanReason");
}
final String banDisplay = ess.getAdventureFacet().miniToLegacy(tlLiteral("banFormat", banReason, senderDisplayName));
final String banDisplay = tl("banFormat", banReason, senderDisplayName);
ess.getServer().getBanList(BanList.Type.IP).addBan(ipAddress, banReason, null, senderName);
ess.getLogger().log(Level.INFO, ess.getAdventureFacet().miniToLegacy(tlLiteral("playerBanIpAddress", senderDisplayName, ipAddress, banReason)));
ess.getLogger().log(Level.INFO, tl("playerBanIpAddress", senderDisplayName, ipAddress, banReason));
for (final Player player : ess.getServer().getOnlinePlayers()) {
if (player.getAddress().getAddress().getHostAddress().equalsIgnoreCase(ipAddress)) {
@@ -62,14 +62,14 @@ public class Commandbanip extends EssentialsCommand {
}
}
ess.broadcastTl(null, u -> !u.isAuthorized("essentials.banip.notify"), "playerBanIpAddress", senderDisplayName, ipAddress, banReason);
ess.broadcastMessage("essentials.banip.notify", tl("playerBanIpAddress", senderDisplayName, ipAddress, banReason));
}
@Override
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(sender);
return getPlayers(server, sender);
} else {
return Collections.emptyList();
}
@@ -7,6 +7,8 @@ import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.entity.Entity;
import static com.earth2me.essentials.I18n.tl;
public class Commandbeezooka extends EssentialsCommand {
public Commandbeezooka() {
@@ -16,7 +18,7 @@ public class Commandbeezooka extends EssentialsCommand {
@Override
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_15_R01)) {
user.sendTl("unsupportedFeature");
user.sendMessage(tl("unsupportedFeature"));
return;
}
@@ -3,7 +3,6 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.LocationUtil;
import com.google.common.collect.Lists;
import net.ess3.api.TranslatableException;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.TreeType;
@@ -11,6 +10,8 @@ import org.bukkit.TreeType;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandbigtree extends EssentialsCommand {
public Commandbigtree() {
super("bigtree");
@@ -33,13 +34,13 @@ public class Commandbigtree extends EssentialsCommand {
final Location loc = LocationUtil.getTarget(user.getBase(), ess.getSettings().getMaxTreeCommandRange()).add(0, 1, 0);
if (loc.getBlock().getType().isSolid()) {
throw new TranslatableException("bigTreeFailure");
throw new Exception(tl("bigTreeFailure"));
}
final boolean success = user.getWorld().generateTree(loc, tree);
if (success) {
user.sendTl("bigTreeSuccess");
user.sendMessage(tl("bigTreeSuccess"));
} else {
throw new TranslatableException("bigTreeFailure");
throw new Exception(tl("bigTreeFailure"));
}
}
@@ -1,21 +1,20 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists;
import net.ess3.api.TranslatableException;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.WritableBookMeta;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandbook extends EssentialsCommand {
private static final Material WRITABLE_BOOK = EnumUtil.getMaterial("WRITABLE_BOOK", "BOOK_AND_QUILL");
@@ -26,7 +25,7 @@ public class Commandbook extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final ItemStack item = Inventories.getItemInMainHand(user.getBase());
final ItemStack item = user.getItemInHand();
final String player = user.getName();
if (item.getType() == Material.WRITTEN_BOOK) {
final BookMeta bmeta = (BookMeta) item.getItemMeta();
@@ -36,34 +35,27 @@ public class Commandbook extends EssentialsCommand {
final String newAuthor = FormatUtil.formatString(user, "essentials.book.author", getFinalArg(args, 1)).trim();
bmeta.setAuthor(newAuthor);
item.setItemMeta(bmeta);
user.sendTl("bookAuthorSet", newAuthor);
user.sendMessage(tl("bookAuthorSet", newAuthor));
} else {
throw new TranslatableException("denyChangeAuthor");
throw new Exception(tl("denyChangeAuthor"));
}
} else if (args.length > 1 && args[0].equalsIgnoreCase("title")) {
if (user.isAuthorized("essentials.book.title") && (isAuthor(bmeta, player) || user.isAuthorized("essentials.book.others"))) {
final String newTitle = FormatUtil.formatString(user, "essentials.book.title", getFinalArg(args, 1)).trim();
bmeta.setTitle(newTitle);
item.setItemMeta(bmeta);
user.sendTl("bookTitleSet", newTitle);
user.sendMessage(tl("bookTitleSet", newTitle));
} else {
throw new TranslatableException("denyChangeTitle");
throw new Exception(tl("denyChangeTitle"));
}
} else {
if (isAuthor(bmeta, player) || user.isAuthorized("essentials.book.others")) {
final ItemStack newItem = new ItemStack(WRITABLE_BOOK, item.getAmount());
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_6_R01)) {
final WritableBookMeta wbmeta = (WritableBookMeta) newItem.getItemMeta();
//noinspection DataFlowIssue
wbmeta.setPages(bmeta.getPages());
newItem.setItemMeta(wbmeta);
} else {
newItem.setItemMeta(bmeta);
}
newItem.setItemMeta(bmeta);
Inventories.setItemInMainHand(user.getBase(), newItem);
user.sendTl("editBookContents");
user.sendMessage(tl("editBookContents"));
} else {
throw new TranslatableException("denyBookEdit");
throw new Exception(tl("denyBookEdit"));
}
}
} else if (item.getType() == WRITABLE_BOOK) {
@@ -72,19 +64,11 @@ public class Commandbook extends EssentialsCommand {
bmeta.setAuthor(player);
}
final ItemStack newItem = new ItemStack(Material.WRITTEN_BOOK, item.getAmount());
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_6_R01)) {
final BookMeta real = (BookMeta) newItem.getItemMeta();
real.setAuthor(bmeta.getAuthor());
real.setTitle(bmeta.getTitle());
real.setPages(bmeta.getPages());
newItem.setItemMeta(real);
} else {
newItem.setItemMeta(bmeta);
}
newItem.setItemMeta(bmeta);
Inventories.setItemInMainHand(user.getBase(), newItem);
user.sendTl("bookLocked");
user.sendMessage(tl("bookLocked"));
} else {
throw new TranslatableException("holdBook");
throw new Exception(tl("holdBook"));
}
}
@@ -106,7 +90,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(user);
final List<String> options = getPlayers(server, user);
options.add("Herobrine"); // #EasterEgg
return options;
} else {
@@ -1,35 +0,0 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.LocationUtil;
import net.ess3.provider.WorldInfoProvider;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.concurrent.CompletableFuture;
public class Commandbottom extends EssentialsCommand {
public Commandbottom() {
super("bottom");
}
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final int bottomX = user.getLocation().getBlockX();
final int bottomZ = user.getLocation().getBlockZ();
final float pitch = user.getLocation().getPitch();
final float yaw = user.getLocation().getYaw();
final Location unsafe = new Location(user.getWorld(), bottomX, ess.provider(WorldInfoProvider.class).getMinHeight(user.getWorld()), bottomZ, yaw, pitch);
final Location safe = LocationUtil.getSafeDestination(ess, unsafe);
final CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
future.thenAccept(success -> {
if (success) {
user.sendTl("teleportBottom", safe.getWorld().getName(), safe.getBlockX(), safe.getBlockY(), safe.getBlockZ());
}
});
user.getAsyncTeleport().teleport(safe, new Trade(this.getName(), ess), PlayerTeleportEvent.TeleportCause.COMMAND, future);
}
}
@@ -1,12 +1,13 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.api.TranslatableException;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.block.Block;
import org.bukkit.event.block.BlockBreakEvent;
import static com.earth2me.essentials.I18n.tl;
public class Commandbreak extends EssentialsCommand {
public Commandbreak() {
super("break");
@@ -21,7 +22,7 @@ public class Commandbreak extends EssentialsCommand {
throw new NoChargeException();
}
if (block.getType() == Material.BEDROCK && !user.isAuthorized("essentials.break.bedrock")) {
throw new TranslatableException("noBreakBedrock");
throw new Exception(tl("noBreakBedrock"));
}
//final List<ItemStack> list = (List<ItemStack>)block.getDrops();
//final BlockBreakEvent event = new BlockBreakEvent(block, user.getBase(), list);
@@ -1,10 +1,11 @@
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;
import static com.earth2me.essentials.I18n.tl;
public class Commandbroadcast extends EssentialsCommand {
public Commandbroadcast() {
super("broadcast");
@@ -16,9 +17,6 @@ public class Commandbroadcast extends EssentialsCommand {
throw new NotEnoughArgumentsException();
}
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());
ess.broadcastMessage(tl("broadcast", FormatUtil.replaceFormat(getFinalArg(args, 0)).replace("\\n", "\n"), sender.getDisplayName()));
}
}
@@ -2,16 +2,21 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.adventure.AdventureUtil;
import com.earth2me.essentials.textreader.IText;
import com.earth2me.essentials.textreader.KeywordReplacer;
import com.earth2me.essentials.textreader.SimpleTextInput;
import com.earth2me.essentials.utils.FormatUtil;
import com.google.common.collect.Lists;
import net.ess3.api.TranslatableException;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandbroadcastworld extends EssentialsCommand {
public Commandbroadcastworld() {
@@ -20,13 +25,13 @@ public class Commandbroadcastworld extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
if (args.length < 2) {
if (args.length == 0) {
throw new NotEnoughArgumentsException();
}
World world = user.getWorld();
String message = getFinalArg(args, 0);
if (ess.getSettings().isAllowWorldInBroadcastworld()) {
if (args.length > 1 && ess.getSettings().isAllowWorldInBroadcastworld()) {
final World argWorld = ess.getWorld(args[0]);
if (argWorld != null) {
world = argWorld;
@@ -40,12 +45,12 @@ public class Commandbroadcastworld extends EssentialsCommand {
@Override
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 2) {
throw new NotEnoughArgumentsException();
throw new NotEnoughArgumentsException("world");
}
final World world = ess.getWorld(args[0]);
if (world == null) {
throw new TranslatableException("invalidWorld");
throw new Exception(tl("invalidWorld"));
}
sendBroadcast(world, sender.getSender().getName(), getFinalArg(args, 1));
}
@@ -54,11 +59,22 @@ public class Commandbroadcastworld extends EssentialsCommand {
if (message.isEmpty()) {
throw new NotEnoughArgumentsException();
}
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)));
sendToWorld(world, tl("broadcast", FormatUtil.replaceFormat(message).replace("\\n", "\n"), name));
}
private void sendToWorld(final World world, final String message) {
IText broadcast = new SimpleTextInput(message);
final Collection<Player> players = ess.getOnlinePlayers();
for (final Player player : players) {
if (player.getWorld().equals(world)) {
final User user = ess.getUser(player);
broadcast = new KeywordReplacer(broadcast, new CommandSource(player), ess, false);
for (final String messageText : broadcast.getLines()) {
user.sendMessage(messageText);
}
}
}
}
@Override
@@ -7,6 +7,8 @@ import org.bukkit.Server;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandburn extends EssentialsCommand {
public Commandburn() {
super("burn");
@@ -19,18 +21,14 @@ public class Commandburn extends EssentialsCommand {
}
final User user = getPlayer(server, sender, args, 0);
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));
user.getBase().setFireTicks(Integer.parseInt(args[1]) * 20);
sender.sendMessage(tl("burnMsg", user.getDisplayName(), Integer.parseInt(args[1])));
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
if (args.length == 1) {
return getPlayers(sender);
return getPlayers(server, sender);
} else if (args.length == 2) {
return COMMON_DURATIONS;
} else {
@@ -1,9 +1,10 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import net.ess3.provider.ContainerProvider;
import org.bukkit.Server;
import static com.earth2me.essentials.I18n.tl;
public class Commandcartographytable extends EssentialsCommand {
public Commandcartographytable() {
@@ -12,13 +13,11 @@ public class Commandcartographytable extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final ContainerProvider containerProvider = ess.provider(ContainerProvider.class);
if (containerProvider == null) {
user.sendTl("unsupportedBrand");
if (ess.getContainerProvider() == null) {
user.sendMessage(tl("unsupportedBrand"));
return;
}
containerProvider.openCartographyTable(user.getBase());
ess.getContainerProvider().openCartographyTable(user.getBase());
}
}
@@ -6,7 +6,6 @@ import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.TranslatableException;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.entity.Player;
@@ -20,6 +19,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import static com.earth2me.essentials.I18n.tl;
public class Commandclearinventory extends EssentialsCommand {
private static final int EXTENDED_CAP = 8;
@@ -54,7 +55,7 @@ public class Commandclearinventory extends EssentialsCommand {
}
if (allowAll && args.length > 0 && args[0].contentEquals("*")) {
sender.sendTl("inventoryClearingFromAll");
sender.sendMessage(tl("inventoryClearingFromAll"));
offset = 1;
players = ess.getOnlinePlayers();
} else if (allowOthers && args.length > 0 && args[0].trim().length() > 2) {
@@ -71,7 +72,7 @@ public class Commandclearinventory extends EssentialsCommand {
if (senderUser != null && senderUser.isPromptingClearConfirm()) {
if (!formattedCommand.equals(previousClearCommand)) {
senderUser.setConfirmingClearCommand(formattedCommand);
senderUser.sendTl("confirmClear", formattedCommand);
senderUser.sendMessage(tl("confirmClear", formattedCommand));
return;
}
}
@@ -81,7 +82,7 @@ public class Commandclearinventory extends EssentialsCommand {
}
}
protected void clearHandler(final CommandSource sender, final Player player, final String[] args, final int offset, final boolean showExtended) throws TranslatableException {
protected void clearHandler(final CommandSource sender, final Player player, final String[] args, final int offset, final boolean showExtended) {
ClearHandlerType type = ClearHandlerType.ALL_EXCEPT_ARMOR;
final Set<Item> items = new HashSet<>();
int amount = -1;
@@ -114,7 +115,7 @@ public class Commandclearinventory extends EssentialsCommand {
if (type != ClearHandlerType.SPECIFIC_ITEM) {
final boolean armor = type == ClearHandlerType.ALL_INCLUDING_ARMOR;
if (showExtended) {
sender.sendTl(armor ? "inventoryClearingAllArmor" : "inventoryClearingAllItems", player.getDisplayName());
sender.sendMessage(tl(armor ? "inventoryClearingAllArmor" : "inventoryClearingAllItems", player.getDisplayName()));
}
Inventories.removeItems(player, item -> true, armor);
} else {
@@ -125,23 +126,19 @@ public class Commandclearinventory extends EssentialsCommand {
stack.setDurability(item.getData());
}
// can't remove a negative amount of items. (it adds them)
if (amount < -1) {
throw new TranslatableException("cannotRemoveNegativeItems");
}
// amount -1 means all items will be cleared
if (amount == -1) {
final int removedAmount = Inventories.removeItemSimilar(player, stack, true);
if (removedAmount > 0 || showExtended) {
sender.sendTl("inventoryClearingStack", removedAmount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName());
sender.sendMessage(tl("inventoryClearingStack", removedAmount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName()));
}
} else {
stack.setAmount(amount < 0 ? 1 : amount);
if (Inventories.removeItemAmount(player, stack, amount)) {
sender.sendTl("inventoryClearingStack", amount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName());
sender.sendMessage(tl("inventoryClearingStack", amount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName()));
} else {
if (showExtended) {
sender.sendTl("inventoryClearFail", player.getDisplayName(), amount, stack.getType().toString().toLowerCase(Locale.ENGLISH));
sender.sendMessage(tl("inventoryClearFail", player.getDisplayName(), amount, stack.getType().toString().toLowerCase(Locale.ENGLISH)));
}
}
}
@@ -153,7 +150,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(user);
final List<String> options = getPlayers(server, 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 +179,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(sender);
final List<String> options = getPlayers(server, sender);
options.add("*");
return options;
} else if (args.length == 2) {
@@ -196,9 +193,6 @@ 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);
}
@@ -3,6 +3,8 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import org.bukkit.Server;
import static com.earth2me.essentials.I18n.tl;
public class Commandclearinventoryconfirmtoggle extends EssentialsCommand {
public Commandclearinventoryconfirmtoggle() {
@@ -19,9 +21,9 @@ public class Commandclearinventoryconfirmtoggle extends EssentialsCommand {
}
user.setPromptingClearConfirm(confirmingClear);
if (confirmingClear) {
user.sendTl("clearInventoryConfirmToggleOn");
user.sendMessage(tl("clearInventoryConfirmToggleOn"));
} else {
user.sendTl("clearInventoryConfirmToggleOff");
user.sendMessage(tl("clearInventoryConfirmToggleOff"));
}
user.setConfirmingClearCommand(null);
}
@@ -3,6 +3,8 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import org.bukkit.Server;
import static com.earth2me.essentials.I18n.tl;
public class Commandcompass extends EssentialsCommand {
public Commandcompass() {
super("compass");
@@ -13,24 +15,24 @@ public class Commandcompass extends EssentialsCommand {
final int bearing = (int) (user.getLocation().getYaw() + 180 + 360) % 360;
final String dir;
if (bearing < 23) {
dir = user.playerTl("north");
dir = tl("north");
} else if (bearing < 68) {
dir = user.playerTl("northEast");
dir = tl("northEast");
} else if (bearing < 113) {
dir = user.playerTl("east");
dir = tl("east");
} else if (bearing < 158) {
dir = user.playerTl("southEast");
dir = tl("southEast");
} else if (bearing < 203) {
dir = user.playerTl("south");
dir = tl("south");
} else if (bearing < 248) {
dir = user.playerTl("southWest");
dir = tl("southWest");
} else if (bearing < 293) {
dir = user.playerTl("west");
dir = tl("west");
} else if (bearing < 338) {
dir = user.playerTl("northWest");
dir = tl("northWest");
} else {
dir = user.playerTl("north");
dir = tl("north");
}
user.sendTl("compassBearing", dir, bearing);
user.sendMessage(tl("compassBearing", dir, bearing));
}
}
@@ -23,6 +23,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static com.earth2me.essentials.I18n.tl;
public class Commandcondense extends EssentialsCommand {
private final Map<ItemStack, SimpleRecipe> condenseList = new HashMap<>();
@@ -56,9 +58,9 @@ public class Commandcondense extends EssentialsCommand {
user.getBase().updateInventory();
if (didConvert) {
user.sendTl("itemsConverted");
user.sendMessage(tl("itemsConverted"));
} else {
user.sendTl("itemsNotConverted");
user.sendMessage(tl("itemsNotConverted"));
throw new NoChargeException();
}
}
@@ -5,8 +5,6 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.PasteUtil;
import net.ess3.api.TranslatableException;
import net.ess3.provider.SerializationProvider;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.ItemStack;
@@ -23,7 +21,7 @@ import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tlLiteral;
import static com.earth2me.essentials.I18n.tl;
public class Commandcreatekit extends EssentialsCommand {
public Commandcreatekit() {
@@ -43,22 +41,20 @@ public class Commandcreatekit extends EssentialsCommand {
final ItemStack[] items = Inventories.getInventory(user.getBase(), true);
final List<String> list = new ArrayList<>();
final SerializationProvider serializationProvider = ess.provider(SerializationProvider.class);
boolean useSerializationProvider = ess.getSettings().isUseBetterKits();
if (useSerializationProvider && serializationProvider == null) {
ess.showError(user.getSource(), new TranslatableException("createKitUnsupported"), commandLabel);
if (useSerializationProvider && ess.getSerializationProvider() == null) {
ess.showError(user.getSource(), new Exception(tl("createKitUnsupported")), commandLabel);
useSerializationProvider = false;
}
for (int i = 0; i < items.length; i++) {
final ItemStack is = items[i];
for (ItemStack is : items) {
if (is != null && is.getType() != null && is.getType() != Material.AIR) {
final String serialized;
if (useSerializationProvider) {
serialized = "slot:" + i + " @" + Base64Coder.encodeLines(serializationProvider.serializeItem(is));
serialized = "@" + Base64Coder.encodeLines(ess.getSerializationProvider().serializeItem(is));
} else {
serialized = "slot:" + i + " " + ess.getItemDb().serialize(is);
serialized = ess.getItemDb().serialize(is);
}
list.add(serialized);
}
@@ -66,7 +62,7 @@ public class Commandcreatekit extends EssentialsCommand {
// Some users might want to directly write to config knowing the consequences. *shrug*
if (!ess.getSettings().isPastebinCreateKit()) {
ess.getKits().addKit(kitname, list, delay);
user.sendTl("createdKit", kitname, list.size(), delay);
user.sendMessage(tl("createdKit", kitname, list.size(), delay));
} else {
uploadPaste(user.getSource(), kitname, delay, list);
}
@@ -90,10 +86,10 @@ public class Commandcreatekit extends EssentialsCommand {
final CompletableFuture<PasteUtil.PasteResult> future = PasteUtil.createPaste(Collections.singletonList(new PasteUtil.PasteFile("kit_" + kitName + ".yml", fileContents)));
future.thenAccept(result -> {
if (result != null) {
final String separator = tlLiteral("createKitSeparator");
final String separator = tl("createKitSeparator");
final String delayFormat = delay <= 0 ? "0" : DateUtil.formatDateDiff(System.currentTimeMillis() + (delay * 1000));
sender.sendMessage(separator);
sender.sendTl("createKitSuccess", kitName, delayFormat, result.getPasteUrl());
sender.sendMessage(tl("createKitSuccess", kitName, delayFormat, result.getPasteUrl()));
sender.sendMessage(separator);
if (ess.getSettings().isDebug()) {
ess.getLogger().info(sender.getSender().getName() + " created a kit: " + result.getPasteUrl());
@@ -101,12 +97,12 @@ public class Commandcreatekit extends EssentialsCommand {
}
});
future.exceptionally(throwable -> {
sender.sendTl("createKitFailed", kitName);
sender.sendMessage(tl("createKitFailed", kitName));
ess.getLogger().log(Level.SEVERE, "Error creating kit: ", throwable);
return null;
});
} catch (Exception e) {
sender.sendTl("createKitFailed", kitName);
sender.sendMessage(tl("createKitFailed", kitName));
ess.getLogger().log(Level.SEVERE, "Error creating kit: ", e);
}
});
@@ -3,9 +3,6 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.IUser;
import com.earth2me.essentials.User;
import net.ess3.api.TranslatableException;
import net.essentialsx.api.v2.events.HomeModifyEvent;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import java.util.ArrayList;
@@ -13,29 +10,13 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import static com.earth2me.essentials.I18n.tl;
public class Commanddelhome extends EssentialsCommand {
public Commanddelhome() {
super("delhome");
}
private void deleteHome(CommandSource sender, User user, String home) {
final HomeModifyEvent event = new HomeModifyEvent(sender.getUser(), user, home, user.getHome(home), false);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("HomeModifyEvent canceled for /delhome execution by " + sender.getDisplayName());
}
return;
}
try {
user.delHome(home);
sender.sendTl("deleteHome", home);
} catch (Exception e) {
sender.sendTl("invalidHome", home);
}
}
@Override
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 1) {
@@ -56,38 +37,31 @@ public class Commanddelhome extends EssentialsCommand {
if (expandedArg.length > 1 && (user == null || user.isAuthorized("essentials.delhome.others"))) {
user = getPlayer(server, expandedArg, 0, true, true);
name = expandedArg[1].toLowerCase(Locale.ENGLISH);
name = expandedArg[1];
} else if (user == null) {
throw new NotEnoughArgumentsException();
} else {
name = expandedArg[0].toLowerCase(Locale.ENGLISH);
name = expandedArg[0];
}
switch (name) {
case "bed":
throw new TranslatableException("invalidHomeName");
case "*":
final List<String> homes = user.getHomes();
for (String home : homes) {
deleteHome(sender, user, home);
}
break;
default:
deleteHome(sender, user, name);
break;
if (name.equalsIgnoreCase("bed")) {
throw new Exception(tl("invalidHomeName"));
}
user.delHome(name.toLowerCase(Locale.ENGLISH));
sender.sendMessage(tl("deleteHome", name));
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
final IUser user = sender.getUser();
final boolean canDelOthers = sender.isAuthorized("essentials.delhome.others");
final IUser user = sender.getUser(ess);
final boolean canDelOthers = sender.isAuthorized("essentials.delhome.others", ess);
if (args.length == 1) {
final List<String> homes = user == null ? new ArrayList<>() : user.getHomes();
if (canDelOthers) {
final int sepIndex = args[0].indexOf(':');
if (sepIndex < 0) {
getPlayers(sender).forEach(player -> homes.add(player + ":"));
getPlayers(server, sender).forEach(player -> homes.add(player + ":"));
} else {
final String namePart = args[0].substring(0, sepIndex);
final User otherUser;
@@ -97,7 +71,6 @@ public class Commanddelhome extends EssentialsCommand {
return homes;
}
otherUser.getHomes().forEach(home -> homes.add(namePart + ":" + home));
homes.add(namePart + ":" + "*");
}
}
return homes;
@@ -1,13 +1,14 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import net.ess3.api.TranslatableException;
import org.bukkit.Server;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commanddeljail extends EssentialsCommand {
public Commanddeljail() {
super("deljail");
@@ -20,11 +21,11 @@ public class Commanddeljail extends EssentialsCommand {
}
if (ess.getJails().getJail(args[0]) == null) {
throw new TranslatableException("jailNotExist");
throw new Exception(tl("jailNotExist"));
}
ess.getJails().removeJail(args[0]);
sender.sendTl("deleteJail", args[0]);
sender.sendMessage(tl("deleteJail", args[0]));
}
@Override
@@ -8,6 +8,8 @@ import org.bukkit.Server;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commanddelkit extends EssentialsCommand {
public Commanddelkit() {
super("delkit");
@@ -17,7 +19,7 @@ public class Commanddelkit extends EssentialsCommand {
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length == 0) {
final String kitList = ess.getKits().listKits(ess, null);
sender.sendTl(kitList.length() > 0 ? "kits" : "noKits", kitList);
sender.sendMessage(kitList.length() > 0 ? tl("kits", kitList) : tl("noKits"));
throw new NoChargeException();
} else {
final String kitName = ess.getKits().matchKit(args[0]);
@@ -28,7 +30,7 @@ public class Commanddelkit extends EssentialsCommand {
}
ess.getKits().removeKit(kitName);
sender.sendTl("deleteKit", kitName);
sender.sendMessage(tl("deleteKit", kitName));
}
}
@@ -1,7 +1,6 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import net.ess3.api.TranslatableException;
import net.essentialsx.api.v2.events.WarpModifyEvent;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -11,6 +10,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commanddelwarp extends EssentialsCommand {
public Commanddelwarp() {
super("delwarp");
@@ -30,15 +31,15 @@ public class Commanddelwarp extends EssentialsCommand {
// World is unloaded/deleted
location = null;
}
final WarpModifyEvent event = new WarpModifyEvent(sender.getUser(), args[0], location, null, WarpModifyEvent.WarpModifyCause.DELETE);
final WarpModifyEvent event = new WarpModifyEvent(sender.getUser(this.ess), args[0], location, null, WarpModifyEvent.WarpModifyCause.DELETE);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
ess.getWarps().removeWarp(args[0]);
sender.sendTl("deleteWarp", args[0]);
sender.sendMessage(tl("deleteWarp", args[0]));
} else {
throw new TranslatableException("warpNotExist");
throw new Exception(tl("warpNotExist"));
}
}
@@ -3,6 +3,8 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import org.bukkit.Server;
import static com.earth2me.essentials.I18n.tl;
public class Commanddepth extends EssentialsCommand {
public Commanddepth() {
super("depth");
@@ -12,11 +14,11 @@ public class Commanddepth extends EssentialsCommand {
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final int depth = user.getLocation().getBlockY() - user.getWorld().getSeaLevel();
if (depth > 0) {
user.sendTl("depthAboveSea", depth);
user.sendMessage(tl("depthAboveSea", depth));
} else if (depth < 0) {
user.sendTl("depthBelowSea", -depth);
user.sendMessage(tl("depthBelowSea", -depth));
} else {
user.sendTl("depth");
user.sendMessage(tl("depth"));
}
}
}
@@ -3,6 +3,8 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import org.bukkit.Server;
import static com.earth2me.essentials.I18n.tl;
public class Commanddisposal extends EssentialsCommand {
public Commanddisposal() {
@@ -11,9 +13,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");
final String title = ess.getAdventureFacet().miniToLegacy(user.playerTl("disposal"));
user.getBase().openInventory(ess.getServer().createInventory(user.getBase(), 36, title));
user.sendMessage(tl("openingDisposal"));
user.getBase().openInventory(ess.getServer().createInventory(user.getBase(), 36, tl("disposal")));
}
}
@@ -3,13 +3,10 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
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;
@@ -17,6 +14,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import static com.earth2me.essentials.I18n.tl;
public class Commandeco extends EssentialsLoopCommand {
public Commandeco() {
@@ -35,14 +34,7 @@ public class Commandeco extends EssentialsLoopCommand {
try {
cmd = EcoCommands.valueOf(args[0].toUpperCase(Locale.ENGLISH));
isPercent = cmd != EcoCommands.RESET && args[2].endsWith("%");
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]);
}
amount = (cmd == EcoCommands.RESET) ? ess.getSettings().getStartingBalance() : new BigDecimal(args[2].replaceAll("[^0-9\\.]", ""));
} catch (final Exception ex) {
throw new NotEnoughArgumentsException(ex);
}
@@ -62,7 +54,7 @@ public class Commandeco extends EssentialsLoopCommand {
if (player.getMoney().subtract(userAmount).compareTo(ess.getSettings().getMinMoney()) >= 0) {
player.takeMoney(userAmount, sender, UserBalanceUpdateEvent.Cause.COMMAND_ECO);
} else {
ess.showError(sender, new TranslatableException("minimumBalanceError", AdventureUtil.parsed(NumberUtil.displayCurrency(ess.getSettings().getMinMoney(), ess))), commandLabel);
ess.showError(sender, new Exception(tl("minimumBalanceError", NumberUtil.displayCurrency(ess.getSettings().getMinMoney(), ess))), commandLabel);
}
break;
}
@@ -73,8 +65,8 @@ public class Commandeco extends EssentialsLoopCommand {
final boolean underMin = userAmount.compareTo(minBal) < 0;
final boolean aboveMax = userAmount.compareTo(maxBal) > 0;
player.setMoney(underMin ? minBal : aboveMax ? maxBal : userAmount, UserBalanceUpdateEvent.Cause.COMMAND_ECO);
player.sendTl("setBal", AdventureUtil.parsed(NumberUtil.displayCurrency(player.getMoney(), ess)));
sender.sendTl("setBalOthers", player.getDisplayName(), AdventureUtil.parsed(NumberUtil.displayCurrency(player.getMoney(), ess)));
player.sendMessage(tl("setBal", NumberUtil.displayCurrency(player.getMoney(), ess)));
sender.sendMessage(tl("setBalOthers", player.getDisplayName(), NumberUtil.displayCurrency(player.getMoney(), ess)));
break;
}
}
@@ -95,7 +87,7 @@ public class Commandeco extends EssentialsLoopCommand {
}
return options;
} else if (args.length == 2) {
return getPlayers(sender);
return getPlayers(server, 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());
@@ -3,26 +3,17 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists;
import net.ess3.api.TranslatableException;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;
import org.bukkit.block.data.BlockData;
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.event.block.SignChangeEvent;
import org.bukkit.util.Vector;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandeditsign extends EssentialsCommand {
public Commandeditsign() {
super("editsign");
@@ -36,113 +27,67 @@ public class Commandeditsign extends EssentialsCommand {
final Block target = user.getTargetBlock(5); //5 is a good number
if (!(target.getState() instanceof Sign)) {
throw new TranslatableException("editsignCommandTarget");
throw new Exception(tl("editsignCommandTarget"));
}
final ModifiableSign sign = wrapSign((Sign) target.getState(), user);
final Sign sign = (Sign) target.getState();
try {
if (args[0].equalsIgnoreCase("set") && args.length > 2) {
final String[] existingLines = sign.getLines();
final int line = Integer.parseInt(args[1]) - 1;
final String text = FormatUtil.formatString(user, "essentials.editsign", getFinalArg(args, 2)).trim();
if (ChatColor.stripColor(text).length() > 15 && !user.isAuthorized("essentials.editsign.unlimited")) {
throw new TranslatableException("editsignCommandLimit");
throw new Exception(tl("editsignCommandLimit"));
}
existingLines[line] = text;
if (callSignEvent(sign, user, existingLines)) {
return;
}
user.sendTl("editsignCommandSetSuccess", line + 1, text);
sign.setLine(line, text);
sign.update();
user.sendMessage(tl("editsignCommandSetSuccess", line + 1, text));
} else if (args[0].equalsIgnoreCase("clear")) {
if (args.length == 1) {
final String[] existingLines = sign.getLines();
for (int i = 0; i < 4; i++) { // A whole one line of line savings!
existingLines[i] = "";
sign.setLine(i, "");
}
if (callSignEvent(sign, user, existingLines)) {
return;
}
user.sendTl("editsignCommandClear");
sign.update();
user.sendMessage(tl("editsignCommandClear"));
} else {
final String[] existingLines = sign.getLines();
final int line = Integer.parseInt(args[1]) - 1;
existingLines[line] = "";
if (callSignEvent(sign, user, existingLines)) {
return;
}
user.sendTl("editsignCommandClearLine", line + 1);
sign.setLine(line, "");
sign.update();
user.sendMessage(tl("editsignCommandClearLine", line + 1));
}
} else if (args[0].equalsIgnoreCase("copy")) {
} else if (args[0].equalsIgnoreCase("copy") || args[0].equalsIgnoreCase("paste")) {
final boolean copy = args[0].equalsIgnoreCase("copy");
final String tlPrefix = copy ? "editsignCopy" : "editsignPaste";
final int line = args.length == 1 ? -1 : Integer.parseInt(args[1]) - 1;
if (line == -1) {
for (int i = 0; i < 4; i++) {
// We use unformat here to prevent players from copying signs with colors that they do not have permission to use.
user.getSignCopy().set(i, FormatUtil.unformatString(user, "essentials.editsign", sign.getLine(i)));
processSignCopyPaste(user, sign, i, copy);
}
user.sendTl("editsignCopy", commandLabel);
user.sendMessage(tl(tlPrefix, commandLabel));
} else {
// We use unformat here to prevent players from copying signs with colors that they do not have permission to use.
user.getSignCopy().set(line, FormatUtil.unformatString(user, "essentials.editsign", sign.getLine(line)));
user.sendTl("editsignCopyLine", line + 1, commandLabel);
processSignCopyPaste(user, sign, line, copy);
user.sendMessage(tl(tlPrefix + "Line", line + 1, commandLabel));
}
} else if (args[0].equalsIgnoreCase("paste")) {
final int line = args.length == 1 ? -1 : Integer.parseInt(args[1]) - 1;
final String[] existingLines = sign.getLines();
if (line == -1) {
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);
if (!copy) {
sign.update();
}
} else {
throw new NotEnoughArgumentsException();
}
} catch (final IndexOutOfBoundsException e) {
throw new TranslatableException(e, "editsignCommandNoLine");
throw new Exception(tl("editsignCommandNoLine"), e);
}
}
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() && !user.isAuthorized("essentials.editsign.waxed.exempt")) {
return true;
}
event = new SignChangeEvent(sign.getBlock(), user.getBase(), lines, sign.isFront() ? Side.FRONT : Side.BACK);
} else {
//noinspection deprecation
event = new SignChangeEvent(sign.getBlock(), user.getBase(), lines);
private void processSignCopyPaste(final User user, final Sign sign, final int index, final boolean copy) {
if (copy) {
// We use unformat here to prevent players from copying signs with colors that they do not have permission to use.
user.getSignCopy().set(index, FormatUtil.unformatString(user, "essentials.editsign", sign.getLine(index)));
return;
}
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("SignChangeEvent canceled for /editsign execution by " + user.getName());
}
return true;
}
for (int i = 0; i < 4; i++) {
sign.setLine(i, lines[i]);
}
sign.update();
return false;
final String line = FormatUtil.formatString(user, "essentials.editsign", user.getSignCopy().get(index));
sign.setLine(index, line == null ? "" : line);
}
@Override
@@ -155,7 +100,7 @@ public class Commandeditsign extends EssentialsCommand {
final int line = Integer.parseInt(args[1]);
final Block target = user.getTargetBlock(5);
if (target.getState() instanceof Sign && line <= 4) {
final ModifiableSign sign = wrapSign((Sign) target.getState(), user);
final Sign sign = (Sign) target.getState();
return Lists.newArrayList(FormatUtil.unformatString(user, "essentials.editsign", sign.getLine(line - 1)));
}
return Collections.emptyList();
@@ -163,105 +108,4 @@ public class Commandeditsign extends EssentialsCommand {
return Collections.emptyList();
}
}
private ModifiableSign wrapSign(final Sign sign, final User user) {
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_1_R01)) {
final Vector eyeLocLessSign = user.getBase().getEyeLocation().toVector().subtract(sign.getLocation().add(.5, .5, .5).toVector());
final BlockData signBlockData = sign.getBlockData();
final BlockFace signDirection;
if (signBlockData instanceof org.bukkit.block.data.type.Sign) {
signDirection = ((org.bukkit.block.data.type.Sign) signBlockData).getRotation();
} else if (signBlockData instanceof WallSign) {
signDirection = ((WallSign) signBlockData).getFacing();
} else if (signBlockData instanceof HangingSign) {
signDirection = ((HangingSign) signBlockData).getRotation();
} else if (signBlockData instanceof WallHangingSign) {
signDirection = ((WallHangingSign) signBlockData).getFacing();
} else {
throw new IllegalStateException("Unknown block data for sign: " + signBlockData.getClass());
}
final Side side = eyeLocLessSign.dot(signDirection.getDirection()) > 0 ? Side.FRONT : Side.BACK;
return new ModifiableSign(sign) {
@Override
String[] getLines() {
return sign.getSide(side).getLines();
}
@Override
String getLine(int line) {
return sign.getSide(side).getLine(line);
}
@Override
void setLine(int line, String text) {
sign.getSide(side).setLine(line, text);
}
@Override
boolean isFront() {
return side == Side.FRONT;
}
@Override
boolean isWaxed() {
return sign.isWaxed();
}
};
}
return new ModifiableSign(sign) {
@Override
String[] getLines() {
return sign.getLines();
}
@Override
String getLine(int line) {
return sign.getLine(line);
}
@Override
void setLine(int line, String text) {
sign.setLine(line, text);
}
@Override
boolean isFront() {
return true;
}
@Override
boolean isWaxed() {
return false;
}
};
}
private abstract static class ModifiableSign {
protected final Sign sign;
protected ModifiableSign(final Sign sign) {
this.sign = sign;
}
abstract String getLine(int line);
abstract String[] getLines();
abstract void setLine(int line, String text);
abstract boolean isFront();
abstract boolean isWaxed();
Block getBlock() {
return sign.getBlock();
}
void update() {
sign.update();
}
}
}
@@ -3,9 +3,9 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.Enchantments;
import com.earth2me.essentials.MetaItemStack;
import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.StringUtil;
import com.google.common.collect.Lists;
import net.ess3.api.TranslatableException;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.enchantments.Enchantment;
@@ -14,10 +14,13 @@ import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import static com.earth2me.essentials.I18n.tl;
public class Commandenchant extends EssentialsCommand {
public Commandenchant() {
super("enchant");
@@ -28,18 +31,18 @@ public class Commandenchant extends EssentialsCommand {
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final ItemStack stack = user.getItemInHand();
if (stack == null || stack.getType() == Material.AIR) {
throw new TranslatableException("nothingInHand");
throw new Exception(tl("nothingInHand"));
}
if (args.length == 0) {
final Set<String> usableEnchants = new TreeSet<>();
for (final Map.Entry<String, Enchantment> entry : Enchantments.entrySet()) {
final String name = Enchantments.getRealName(entry.getValue());
final String name = entry.getValue().getName().toLowerCase(Locale.ENGLISH);
if (usableEnchants.contains(name) || (user.isAuthorized("essentials.enchantments." + name) && entry.getValue().canEnchantItem(stack))) {
usableEnchants.add(entry.getKey());
}
}
throw new NotEnoughArgumentsException(user.playerTl("enchantments", StringUtil.joinList(usableEnchants.toArray())));
throw new NotEnoughArgumentsException(tl("enchantments", StringUtil.joinList(usableEnchants.toArray())));
}
int level = 1;
@@ -54,13 +57,13 @@ public class Commandenchant extends EssentialsCommand {
final MetaItemStack metaStack = new MetaItemStack(stack);
final Enchantment enchantment = metaStack.getEnchantment(user, args[0]);
metaStack.addEnchantment(user.getSource(), ess.getSettings().allowUnsafeEnchantments() && user.isAuthorized("essentials.enchantments.allowunsafe"), enchantment, level);
stack.setItemMeta(metaStack.getItemStack().getItemMeta());
Inventories.setItemInMainHand(user.getBase(), metaStack.getItemStack());
user.getBase().updateInventory();
final String enchantName = Enchantments.getRealName(enchantment).replace('_', ' ');
final String enchantName = enchantment.getName().toLowerCase(Locale.ENGLISH).replace('_', ' ');
if (level == 0) {
user.sendTl("enchantmentRemoved", enchantName);
user.sendMessage(tl("enchantmentRemoved", enchantName));
} else {
user.sendTl("enchantmentApplied", enchantName);
user.sendMessage(tl("enchantmentApplied", enchantName));
}
}
@@ -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(user);
return getPlayers(server, user);
} else {
return Collections.emptyList();
}
@@ -1,31 +1,934 @@
package com.earth2me.essentials.commands;
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;
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.CommandMapUtil;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FloatUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.PasteUtil;
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 org.bukkit.Bukkit;
import org.bukkit.ChatColor;
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.tl;
// This command has 4 undocumented behaviours #EasterEgg
public class Commandessentials extends EssentialsTreeCommand {
public class Commandessentials extends EssentialsCommand {
private static final Sound NOTE_HARP = EnumUtil.valueOf(Sound.class, "BLOCK_NOTE_BLOCK_HARP", "BLOCK_NOTE_HARP", "NOTE_PIANO");
private static final Sound MOO_SOUND = EnumUtil.valueOf(Sound.class, "COW_IDLE", "ENTITY_COW_MILK");
private static final String 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 Commandessentials() {
super("essentials");
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());
}
@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", ess) || 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.sendMessage(tl("blockListEmpty"));
return;
}
sender.sendMessage(tl("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.sendMessage(tl("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.getOnlineModeProvider().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 essSpawn = Bukkit.getPluginManager().getPlugin("EssentialsSpawn");
final Map<String, Command> knownCommandsCopy = new HashMap<>(ess.getKnownCommandsProvider().getKnownCommands());
final Map<String, String> disabledCommandsCopy = new HashMap<>(ess.getAlternativeCommandsHandler().disabledCommands());
// Further operations will be heavy IO
ess.runTaskAsynchronously(() -> {
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.sendMessage(tl("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.sendMessage(tl("dumpErrorUpload", "discord-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.sendMessage(tl("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.sendMessage(tl("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.sendMessage(tl("dumpErrorUpload", "worth.yml", e.getMessage()));
}
}
if (tpr) {
try {
files.add(new PasteUtil.PasteFile("tpr.yml", new String(Files.readAllBytes(ess.getRandomTeleport().getFile().toPath()), StandardCharsets.UTF_8)));
} catch (IOException e) {
sender.sendMessage(tl("dumpErrorUpload", "tpr.yml", e.getMessage()));
}
}
if (spawns && essSpawn != null) {
try {
files.add(new PasteUtil.PasteFile("spawn.yml", new String(Files.readAllBytes(ess.getDataFolder().toPath().resolve("spawn.yml")), StandardCharsets.UTF_8)));
} catch (IOException e) {
sender.sendMessage(tl("dumpErrorUpload", "spawn.yml", e.getMessage()));
}
}
if (commands) {
try {
files.add(new PasteUtil.PasteFile("commands.yml", new String(Files.readAllBytes(Paths.get("commands.yml")), StandardCharsets.UTF_8)));
files.add(new PasteUtil.PasteFile("commandmap.json", CommandMapUtil.toJsonPretty(ess, knownCommandsCopy)));
files.add(new PasteUtil.PasteFile("commandoverride.json", disabledCommandsCopy.toString()));
} catch (IOException e) {
sender.sendMessage(tl("dumpErrorUpload", "commands.yml", e.getMessage()));
}
}
final CompletableFuture<PasteUtil.PasteResult> future = PasteUtil.createPaste(files);
future.thenAccept(result -> {
if (result != null) {
final String dumpUrl = "https://essentialsx.net/dump.html?id=" + result.getPasteId();
sender.sendMessage(tl("dumpUrl", dumpUrl));
sender.sendMessage(tl("dumpDeleteKey", result.getDeletionKey()));
if (sender.isPlayer()) {
ess.getLogger().info(tl("dumpConsoleUrl", dumpUrl));
ess.getLogger().info(tl("dumpDeleteKey", result.getDeletionKey()));
}
}
files.clear();
});
future.exceptionally(throwable -> {
sender.sendMessage(tl("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.sendMessage(tl("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.sendMessage(tl("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.sendMessage(tl("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.sendMessage(tl("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.sendMessage(tl("fixedHomes"));
});
break;
case "delete":
final boolean filterByWorld = args.length >= 3;
if (filterByWorld && server.getWorld(args[2]) == null) {
throw new Exception(tl("invalidWorld"));
}
sender.sendMessage(filterByWorld ? tl("deletingHomesWorld", args[2]) : tl("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());
}
}
}
sender.sendMessage(filterByWorld ? tl("deletedHomesWorld", args[2]) : tl("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", ess)) {
return;
}
final ModernUserMap userMap = (ModernUserMap) ess.getUsers();
sender.sendMessage(tl("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.sendMessage(tl("usermapEntry", entry.getKey(), entry.getValue().toString()));
}
} else if (args[1].equals("purge")) {
final boolean seppuku = args.length > 2 && args[2].equals("iknowwhatimdoing");
sender.sendMessage(tl("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 {
try {
final UUID uuid = UUID.fromString(args[1]);
for (final Map.Entry<String, UUID> entry : userMap.getNameCache().entrySet()) {
if (entry.getValue().equals(uuid)) {
sender.sendMessage(tl("usermapEntry", entry.getKey(), args[1]));
}
}
} catch (IllegalArgumentException ignored) {
final String sanitizedName = userMap.getSanitizedName(args[1]);
sender.sendMessage(tl("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.sendMessage(tl(serverMessageKey, "Server", server.getBukkitVersion() + " " + server.getVersion()));
sender.sendMessage(tl(serverMessageKey, "Brand", server.getName()));
sender.sendMessage(tl("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.sendMessage(tl("versionOutputWarn", name, version));
} else {
sender.sendMessage(tl("versionOutputFine", name, version));
}
} else {
sender.sendMessage(tl("versionOutputUnsupported", name, version));
isUnsupported = true;
}
}
if (versionPlugins.contains(name)) {
if (warnPlugins.contains(name)) {
sender.sendMessage(tl("versionOutputUnsupported", name, version));
isUnsupported = true;
} else {
sender.sendMessage(tl("versionOutputFine", name, version));
}
}
if (name.equals("Vault")) isVaultInstalled = true;
}
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.sendMessage(tl("versionOutputEconLayer", layer));
if (isMismatched) {
sender.sendMessage(tl("versionMismatchAll"));
}
if (!isVaultInstalled) {
sender.sendMessage(tl("versionOutputVaultMissing"));
}
if (isUnsupported) {
sender.sendMessage(tl("versionOutputUnsupportedPlugins"));
}
switch (supportStatus) {
case NMS_CLEANROOM:
sender.sendMessage(ChatColor.DARK_RED + tl("serverUnsupportedCleanroom"));
break;
case DANGEROUS_FORK:
sender.sendMessage(ChatColor.DARK_RED + tl("serverUnsupportedDangerous"));
break;
case STUPID_PLUGIN:
sender.sendMessage(ChatColor.DARK_RED + tl("serverUnsupportedDumbPlugins"));
break;
case UNSTABLE:
sender.sendMessage(ChatColor.DARK_RED + tl("serverUnsupportedMods"));
break;
case OUTDATED:
sender.sendMessage(ChatColor.RED + tl("serverUnsupported"));
break;
case LIMITED:
sender.sendMessage(ChatColor.RED + tl("serverUnsupportedLimitedApi"));
break;
}
if (VersionUtil.getSupportStatusClass() != null) {
sender.sendMessage(ChatColor.RED + tl("serverUnsupportedClass", VersionUtil.getSupportStatusClass()));
}
sender.sendMessage(tl("versionFetching"));
ess.runTaskAsynchronously(() -> {
for (String str : ess.getUpdateChecker().getVersionMessages(true, true)) {
sender.sendMessage(str);
}
});
}
@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));
}
}
}
}
@@ -13,6 +13,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import static com.earth2me.essentials.I18n.tl;
public class Commandexp extends EssentialsLoopCommand {
public Commandexp() {
super("exp");
@@ -20,7 +22,7 @@ public class Commandexp extends EssentialsLoopCommand {
@Override
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
final IUser user = sender.getUser();
final IUser user = sender.getUser(ess);
if (args.length == 0 || (args.length < 2 && user == null)) {
if (user == null) {
throw new NotEnoughArgumentsException();
@@ -37,7 +39,7 @@ public class Commandexp extends EssentialsLoopCommand {
}
if (!cmd.hasPermission(user)) {
user.sendTl("noAccessSubCommand", "/" + commandLabel + " " + cmd.name().toLowerCase(Locale.ENGLISH));
user.sendMessage(tl("noAccessSubCommand", "/" + commandLabel + " " + cmd.name().toLowerCase(Locale.ENGLISH)));
return;
}
@@ -97,7 +99,7 @@ public class Commandexp extends EssentialsLoopCommand {
}
private void showExp(final CommandSource sender, final IUser target) {
sender.sendTl("exp", target.getDisplayName(), SetExpFix.getTotalExperience(target.getBase()), target.getBase().getLevel(), SetExpFix.getExpUntilNextLevel(target.getBase()));
sender.sendMessage(tl("exp", target.getDisplayName(), SetExpFix.getTotalExperience(target.getBase()), target.getBase().getLevel(), SetExpFix.getExpUntilNextLevel(target.getBase())));
}
//TODO: Limit who can give negative exp?
@@ -129,7 +131,7 @@ public class Commandexp extends EssentialsLoopCommand {
amount = 0L;
}
SetExpFix.setTotalExperience(target.getBase(), (int) amount);
sender.sendTl("expSet", target.getDisplayName(), amount);
sender.sendMessage(tl("expSet", target.getDisplayName(), amount));
}
@Override
@@ -147,21 +149,15 @@ public class Commandexp extends EssentialsLoopCommand {
}
return options;
} else if (args.length == 2) {
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) {
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 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)) {
@@ -188,10 +184,10 @@ public class Commandexp extends EssentialsLoopCommand {
return Collections.emptyList();
}
} else { // even without 'show'
return getPlayers(sender);
return getPlayers(server, sender);
}
} else if (args.length == 3 && (args[0].equalsIgnoreCase("set") || args[0].equalsIgnoreCase("give"))) {
return getPlayers(sender);
return getPlayers(server, sender);
} else {
return Collections.emptyList();
}
@@ -8,6 +8,8 @@ import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandext extends EssentialsLoopCommand {
public Commandext() {
super("ext");
@@ -30,13 +32,13 @@ public class Commandext extends EssentialsLoopCommand {
}
extPlayer(user.getBase());
user.sendTl("extinguish");
user.sendMessage(tl("extinguish"));
}
@Override
protected void updatePlayer(final Server server, final CommandSource sender, final User player, final String[] args) {
extPlayer(player.getBase());
sender.sendTl("extinguishOthers", player.getDisplayName());
sender.sendMessage(tl("extinguishOthers", player.getDisplayName()));
}
private void extPlayer(final Player player) {
@@ -46,7 +48,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(sender);
return getPlayers(server, sender);
} else {
return Collections.emptyList();
}
@@ -9,6 +9,8 @@ import org.bukkit.event.entity.FoodLevelChangeEvent;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commandfeed extends EssentialsLoopCommand {
public Commandfeed() {
super("feed");
@@ -26,7 +28,7 @@ public class Commandfeed extends EssentialsLoopCommand {
}
feedPlayer(user.getBase());
user.sendTl("feed");
user.sendMessage(tl("feed"));
}
@Override
@@ -42,7 +44,7 @@ public class Commandfeed extends EssentialsLoopCommand {
protected void updatePlayer(final Server server, final CommandSource sender, final User player, final String[] args) throws PlayerExemptException {
try {
feedPlayer(player.getBase());
sender.sendTl("feedOther", player.getDisplayName());
sender.sendMessage(tl("feedOther", player.getDisplayName()));
} catch (final QuietAbortException e) {
//Handle Quietly
}
@@ -64,8 +66,8 @@ 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(sender);
if (args.length == 1 && sender.isAuthorized("essentials.feed.others", ess)) {
return getPlayers(server, sender);
} else {
return Collections.emptyList();
}
@@ -5,7 +5,6 @@ import com.earth2me.essentials.utils.FloatUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import net.ess3.api.TranslatableException;
import org.bukkit.Server;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.DragonFireball;
@@ -19,7 +18,6 @@ import org.bukkit.entity.Snowball;
import org.bukkit.entity.SplashPotion;
import org.bukkit.entity.ThrownExpBottle;
import org.bukkit.entity.Trident;
import org.bukkit.entity.WindCharge;
import org.bukkit.entity.WitherSkull;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.util.Vector;
@@ -29,6 +27,8 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.earth2me.essentials.I18n.tl;
public class Commandfireball extends EssentialsCommand {
public static final String FIREBALL_META_KEY = "ess_fireball_proj";
@@ -56,10 +56,6 @@ public class Commandfireball extends EssentialsCommand {
builder.put("trident", Trident.class);
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_21_R01)) {
builder.put("windcharge", WindCharge.class);
}
types = builder.build();
}
@@ -82,7 +78,7 @@ public class Commandfireball extends EssentialsCommand {
}
if (!user.isAuthorized("essentials.fireball." + type)) {
throw new TranslatableException("noPerm", "essentials.fireball." + type);
throw new Exception(tl("noPerm", "essentials.fireball." + type));
}
final Vector direction = user.getBase().getEyeLocation().getDirection().multiply(speed);
@@ -1,15 +1,14 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.MetaItemStack;
import com.earth2me.essentials.MobCompat;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.google.common.collect.Lists;
import net.ess3.api.TranslatableException;
import org.bukkit.DyeColor;
import org.bukkit.FireworkEffect;
import org.bukkit.Server;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Firework;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.FireworkMeta;
@@ -18,6 +17,8 @@ import org.bukkit.util.Vector;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
//This command has quite a complicated syntax, in theory it has 4 seperate syntaxes which are all variable:
//
//1: /firework clear - This clears all of the effects on a firework stack
@@ -48,21 +49,21 @@ public class Commandfirework extends EssentialsCommand {
final ItemStack stack = user.getItemInHand();
if (!MaterialUtil.isFirework(stack.getType())) {
throw new TranslatableException("holdFirework");
throw new Exception(tl("holdFirework"));
}
if (args[0].equalsIgnoreCase("clear")) {
final FireworkMeta fmeta = (FireworkMeta) stack.getItemMeta();
fmeta.clearEffects();
stack.setItemMeta(fmeta);
user.sendTl("fireworkEffectsCleared");
user.sendMessage(tl("fireworkEffectsCleared"));
} else if (args.length > 1 && (args[0].equalsIgnoreCase("power") || args[0].equalsIgnoreCase("p"))) {
final FireworkMeta fmeta = (FireworkMeta) stack.getItemMeta();
try {
final int power = Integer.parseInt(args[1]);
fmeta.setPower(power > 3 ? 4 : power);
} catch (final NumberFormatException e) {
throw new TranslatableException("invalidFireworkFormat", args[1], args[0]);
throw new Exception(tl("invalidFireworkFormat", args[1], args[0]));
}
stack.setItemMeta(fmeta);
} else if ((args[0].equalsIgnoreCase("fire") || args[0].equalsIgnoreCase("f")) && user.isAuthorized("essentials.firework.fire")) {
@@ -74,14 +75,14 @@ public class Commandfirework extends EssentialsCommand {
amount = Integer.parseInt(args[1]);
if (amount > serverLimit) {
amount = serverLimit;
user.sendTl("mobSpawnLimit");
user.sendMessage(tl("mobSpawnLimit"));
}
} else {
direction = true;
}
}
for (int i = 0; i < amount; i++) {
final Firework firework = (Firework) user.getWorld().spawnEntity(user.getLocation(), MobCompat.FIREWORK_ROCKET);
final Firework firework = (Firework) user.getWorld().spawnEntity(user.getLocation(), EntityType.FIREWORK);
final FireworkMeta fmeta = (FireworkMeta) stack.getItemMeta();
if (direction) {
final Vector vector = user.getBase().getEyeLocation().getDirection().multiply(0.070);
@@ -98,7 +99,7 @@ public class Commandfirework extends EssentialsCommand {
try {
mStack.addFireworkMeta(user.getSource(), true, arg, ess);
} catch (final Exception e) {
user.sendTl("fireworkSyntax");
user.sendMessage(tl("fireworkSyntax"));
throw e;
}
}
@@ -107,13 +108,13 @@ public class Commandfirework extends EssentialsCommand {
final FireworkMeta fmeta = (FireworkMeta) mStack.getItemStack().getItemMeta();
final FireworkEffect effect = mStack.getFireworkBuilder().build();
if (fmeta.getEffects().size() > 0 && !user.isAuthorized("essentials.firework.multiple")) {
throw new TranslatableException("multipleCharges");
throw new Exception(tl("multipleCharges"));
}
fmeta.addEffect(effect);
stack.setItemMeta(fmeta);
} else {
user.sendTl("fireworkSyntax");
throw new TranslatableException("fireworkColor");
user.sendMessage(tl("fireworkSyntax"));
throw new Exception(tl("fireworkColor"));
}
}
}
@@ -2,10 +2,11 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.CommonPlaceholders;
import net.ess3.api.events.FlyStatusChangeEvent;
import org.bukkit.Server;
import static com.earth2me.essentials.I18n.tl;
public class Commandfly extends EssentialsToggleCommand {
public Commandfly() {
super("fly", "essentials.fly.others");
@@ -34,15 +35,13 @@ public class Commandfly extends EssentialsToggleCommand {
user.getBase().setFallDistance(0f);
user.getBase().setAllowFlight(enabled);
user.setFlyModeEnabled(enabled);
if (!user.getBase().getAllowFlight()) {
user.getBase().setFlying(false);
}
user.sendTl("flyMode", CommonPlaceholders.enableDisable(user.getSource(), enabled), user.getDisplayName());
user.sendMessage(tl("flyMode", tl(enabled ? "enabled" : "disabled"), user.getDisplayName()));
if (!sender.isPlayer() || !sender.getPlayer().equals(user.getBase())) {
sender.sendTl("flyMode", CommonPlaceholders.enableDisable(user.getSource(), enabled), user.getDisplayName());
sender.sendMessage(tl("flyMode", tl(enabled ? "enabled" : "disabled"), user.getDisplayName()));
}
}
}
Loaded 100 of 566 files, more files were not shown because too many files have changed in this diff. Show more