Merge remote-tracking branch 'upstream/2.x' into rework/providers

# Conflicts:
#	Essentials/src/main/java/com/earth2me/essentials/Essentials.java
#	Essentials/src/main/java/com/earth2me/essentials/IEssentials.java
#	Essentials/src/main/java/com/earth2me/essentials/RandomTeleport.java
#	Essentials/src/main/java/com/earth2me/essentials/commands/EssentialsCommand.java
#	Essentials/src/main/java/com/earth2me/essentials/items/FlatItemDb.java
#	providers/BaseProviders/src/main/java/net/ess3/provider/providers/BasePotionDataProvider.java
#	providers/BaseProviders/src/main/java/net/ess3/provider/providers/LegacyPotionMetaProvider.java
This commit is contained in:
JRoy 2024-07-23 17:39:16 -04:00
commit 0dcdb8bebb
No known key found for this signature in database
GPG Key ID: FAD510B503869E7D
88 changed files with 5448 additions and 681 deletions

View File

@ -70,10 +70,13 @@ body:
validations: validations:
required: true required: true
- type: markdown - type: textarea
attributes: attributes:
value: | label: Additional Information
In the text box below, you can attach any relevant screenshots, files and links to Timings/spark profiler reports. description: |
In this box, 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. 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. If you suspect this issue is related to a prior issue/PR/commit, please mention it here.
validations:
required: false

View File

@ -16,26 +16,32 @@ jobs:
steps: steps:
- name: Checkout Git repo - name: Checkout Git repo
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: 17 java-version: 17
- name: Setup Gradle - name: Setup Gradle
uses: gradle/gradle-build-action@v2 uses: gradle/gradle-build-action@v3
- name: Build with Gradle - name: Build with Gradle
run: | run: |
chmod +x gradlew chmod +x gradlew
./gradlew build --stacktrace ./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 - name: Archive plugin jars on GitHub
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: EssentialsX plugin jars name: EssentialsX plugin jars
path: jars/ path: jars/
@ -61,7 +67,7 @@ jobs:
cp -r EssentialsXMPP/build/docs/javadoc/ javadocs/EssentialsXMPP/ cp -r EssentialsXMPP/build/docs/javadoc/ javadocs/EssentialsXMPP/
- name: Archive Javadocs - name: Archive Javadocs
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: javadocs name: javadocs
path: javadocs/ path: javadocs/
@ -74,12 +80,12 @@ jobs:
steps: steps:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 16 node-version: 16
- name: Download Javadocs - name: Download Javadocs
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
with: with:
name: javadocs name: javadocs
path: javadocs/ path: javadocs/

View File

@ -18,26 +18,32 @@ jobs:
steps: steps:
- name: Checkout Git repo - name: Checkout Git repo
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: 17 java-version: 17
- name: Setup Gradle - name: Setup Gradle
uses: gradle/gradle-build-action@v2 uses: gradle/gradle-build-action@v3
- name: Build with Gradle - name: Build with Gradle
run: | run: |
chmod +x gradlew chmod +x gradlew
./gradlew build --stacktrace ./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 - name: Archive plugin jars on GitHub
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: EssentialsX plugin jars name: EssentialsX plugin jars
path: jars/ path: jars/

View File

@ -14,9 +14,9 @@ dependencies {
implementation 'org.checkerframework:checker-qual:3.21.0' implementation 'org.checkerframework:checker-qual:3.21.0'
implementation 'nu.studer:java-ordered-properties:1.0.4' implementation 'nu.studer:java-ordered-properties:1.0.4'
implementation 'net.kyori:adventure-api:4.15.0' implementation 'net.kyori:adventure-api:4.17.0'
implementation 'net.kyori:adventure-text-minimessage:4.15.0' implementation 'net.kyori:adventure-text-minimessage:4.17.0'
implementation 'net.kyori:adventure-platform-bukkit:4.3.2' implementation 'net.kyori:adventure-platform-bukkit:4.3.3'
// Providers // Providers
api project(':providers:BaseProviders') api project(':providers:BaseProviders')

View File

@ -1,11 +1,9 @@
package com.earth2me.essentials; package com.earth2me.essentials;
public class ChargeException extends Exception { import net.ess3.api.TranslatableException;
public ChargeException(final String message) {
super(message);
}
public ChargeException(final String message, final Throwable throwable) { public class ChargeException extends TranslatableException {
super(message, throwable); public ChargeException(String tlKey, Object... args) {
super(tlKey, args);
} }
} }

View File

@ -36,7 +36,9 @@ public class CommandSource {
} }
final String translation = tlLiteral(tlKey, args); final String translation = tlLiteral(tlKey, args);
sendComponent(AdventureUtil.miniMessage().deserialize(translation)); if (!translation.isEmpty()) {
sendComponent(AdventureUtil.miniMessage().deserialize(translation));
}
} }
public String tl(final String tlKey, final Object... args) { public String tl(final String tlKey, final Object... args) {

View File

@ -69,6 +69,9 @@ public final class Console implements IMessageRecipient {
@Override @Override
public void sendTl(String tlKey, Object... args) { public void sendTl(String tlKey, Object... args) {
final String translation = tlLiteral(tlKey, args); final String translation = tlLiteral(tlKey, args);
if (translation.isEmpty()) {
return;
}
final Audience consoleAudience = ((Essentials) ess).getBukkitAudience().sender(getCommandSender()); final Audience consoleAudience = ((Essentials) ess).getBukkitAudience().sender(getCommandSender());
final Component component = AdventureUtil.miniMessage() final Component component = AdventureUtil.miniMessage()

View File

@ -1,5 +1,6 @@
package com.earth2me.essentials; package com.earth2me.essentials;
import com.earth2me.essentials.utils.RegistryUtil;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
@ -15,33 +16,43 @@ public final class Enchantments {
private static boolean isFlat; private static boolean isFlat;
static { static {
ENCHANTMENTS.put("alldamage", Enchantment.DAMAGE_ALL); final Enchantment SHARPNESS = RegistryUtil.valueOf(Enchantment.class, "DAMAGE_ALL", "SHARPNESS");
ALIASENCHANTMENTS.put("alldmg", Enchantment.DAMAGE_ALL);
ENCHANTMENTS.put("sharpness", Enchantment.DAMAGE_ALL); ENCHANTMENTS.put("alldamage", SHARPNESS);
ALIASENCHANTMENTS.put("sharp", Enchantment.DAMAGE_ALL); ALIASENCHANTMENTS.put("alldmg", SHARPNESS);
ALIASENCHANTMENTS.put("dal", Enchantment.DAMAGE_ALL); ENCHANTMENTS.put("sharpness", SHARPNESS);
ALIASENCHANTMENTS.put("sharp", SHARPNESS);
ALIASENCHANTMENTS.put("dal", SHARPNESS);
final Enchantment BANE_OF_ARTHROPODS = RegistryUtil.valueOf(Enchantment.class, "DAMAGE_ARTHROPODS", "BANE_OF_ARTHROPODS");
ENCHANTMENTS.put("ardmg", Enchantment.DAMAGE_ARTHROPODS); ENCHANTMENTS.put("ardmg", BANE_OF_ARTHROPODS);
ENCHANTMENTS.put("baneofarthropods", Enchantment.DAMAGE_ARTHROPODS); ENCHANTMENTS.put("baneofarthropods", BANE_OF_ARTHROPODS);
ALIASENCHANTMENTS.put("baneofarthropod", Enchantment.DAMAGE_ARTHROPODS); ALIASENCHANTMENTS.put("baneofarthropod", BANE_OF_ARTHROPODS);
ALIASENCHANTMENTS.put("arthropod", Enchantment.DAMAGE_ARTHROPODS); ALIASENCHANTMENTS.put("arthropod", BANE_OF_ARTHROPODS);
ALIASENCHANTMENTS.put("dar", Enchantment.DAMAGE_ARTHROPODS); ALIASENCHANTMENTS.put("dar", BANE_OF_ARTHROPODS);
final Enchantment SMITE = RegistryUtil.valueOf(Enchantment.class, "DAMAGE_UNDEAD", "SMITE");
ENCHANTMENTS.put("undeaddamage", Enchantment.DAMAGE_UNDEAD); ENCHANTMENTS.put("undeaddamage", SMITE);
ENCHANTMENTS.put("smite", Enchantment.DAMAGE_UNDEAD); ENCHANTMENTS.put("smite", SMITE);
ALIASENCHANTMENTS.put("du", Enchantment.DAMAGE_UNDEAD); ALIASENCHANTMENTS.put("du", SMITE);
final Enchantment EFFICIENCY = RegistryUtil.valueOf(Enchantment.class, "DIG_SPEED", "EFFICIENCY");
ENCHANTMENTS.put("digspeed", Enchantment.DIG_SPEED); ENCHANTMENTS.put("digspeed", EFFICIENCY);
ENCHANTMENTS.put("efficiency", Enchantment.DIG_SPEED); ENCHANTMENTS.put("efficiency", EFFICIENCY);
ALIASENCHANTMENTS.put("minespeed", Enchantment.DIG_SPEED); ALIASENCHANTMENTS.put("minespeed", EFFICIENCY);
ALIASENCHANTMENTS.put("cutspeed", Enchantment.DIG_SPEED); ALIASENCHANTMENTS.put("cutspeed", EFFICIENCY);
ALIASENCHANTMENTS.put("ds", Enchantment.DIG_SPEED); ALIASENCHANTMENTS.put("ds", EFFICIENCY);
ALIASENCHANTMENTS.put("eff", Enchantment.DIG_SPEED); ALIASENCHANTMENTS.put("eff", EFFICIENCY);
final Enchantment UNBREAKING = RegistryUtil.valueOf(Enchantment.class, "DURABILITY", "UNBREAKING");
ENCHANTMENTS.put("durability", Enchantment.DURABILITY); ENCHANTMENTS.put("durability", UNBREAKING);
ALIASENCHANTMENTS.put("dura", Enchantment.DURABILITY); ALIASENCHANTMENTS.put("dura", UNBREAKING);
ENCHANTMENTS.put("unbreaking", Enchantment.DURABILITY); ENCHANTMENTS.put("unbreaking", UNBREAKING);
ALIASENCHANTMENTS.put("d", Enchantment.DURABILITY); ALIASENCHANTMENTS.put("d", UNBREAKING);
ENCHANTMENTS.put("thorns", Enchantment.THORNS); ENCHANTMENTS.put("thorns", Enchantment.THORNS);
ENCHANTMENTS.put("highcrit", Enchantment.THORNS); ENCHANTMENTS.put("highcrit", Enchantment.THORNS);
@ -59,106 +70,127 @@ public final class Enchantments {
ALIASENCHANTMENTS.put("kback", Enchantment.KNOCKBACK); ALIASENCHANTMENTS.put("kback", Enchantment.KNOCKBACK);
ALIASENCHANTMENTS.put("kb", Enchantment.KNOCKBACK); ALIASENCHANTMENTS.put("kb", Enchantment.KNOCKBACK);
ALIASENCHANTMENTS.put("k", 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); ALIASENCHANTMENTS.put("blockslootbonus", FORTUNE);
ENCHANTMENTS.put("fortune", Enchantment.LOOT_BONUS_BLOCKS); ENCHANTMENTS.put("fortune", FORTUNE);
ALIASENCHANTMENTS.put("fort", Enchantment.LOOT_BONUS_BLOCKS); ALIASENCHANTMENTS.put("fort", FORTUNE);
ALIASENCHANTMENTS.put("lbb", Enchantment.LOOT_BONUS_BLOCKS); ALIASENCHANTMENTS.put("lbb", FORTUNE);
final Enchantment LOOTING = RegistryUtil.valueOf(Enchantment.class, "LOOT_BONUS_MOBS", "LOOTING");
ALIASENCHANTMENTS.put("mobslootbonus", Enchantment.LOOT_BONUS_MOBS); ALIASENCHANTMENTS.put("mobslootbonus", LOOTING);
ENCHANTMENTS.put("mobloot", Enchantment.LOOT_BONUS_MOBS); ENCHANTMENTS.put("mobloot", LOOTING);
ENCHANTMENTS.put("looting", Enchantment.LOOT_BONUS_MOBS); ENCHANTMENTS.put("looting", LOOTING);
ALIASENCHANTMENTS.put("lbm", Enchantment.LOOT_BONUS_MOBS); ALIASENCHANTMENTS.put("lbm", LOOTING);
final Enchantment RESPIRATION = RegistryUtil.valueOf(Enchantment.class, "OXYGEN", "RESPIRATION");
ALIASENCHANTMENTS.put("oxygen", Enchantment.OXYGEN); ALIASENCHANTMENTS.put("oxygen", RESPIRATION);
ENCHANTMENTS.put("respiration", Enchantment.OXYGEN); ENCHANTMENTS.put("respiration", RESPIRATION);
ALIASENCHANTMENTS.put("breathing", Enchantment.OXYGEN); ALIASENCHANTMENTS.put("breathing", RESPIRATION);
ENCHANTMENTS.put("breath", Enchantment.OXYGEN); ENCHANTMENTS.put("breath", RESPIRATION);
ALIASENCHANTMENTS.put("o", Enchantment.OXYGEN); ALIASENCHANTMENTS.put("o", RESPIRATION);
final Enchantment PROTECTION = RegistryUtil.valueOf(Enchantment.class, "PROTECTION_ENVIRONMENTAL", "PROTECTION");
ENCHANTMENTS.put("protection", Enchantment.PROTECTION_ENVIRONMENTAL); ENCHANTMENTS.put("protection", PROTECTION);
ALIASENCHANTMENTS.put("prot", Enchantment.PROTECTION_ENVIRONMENTAL); ALIASENCHANTMENTS.put("prot", PROTECTION);
ENCHANTMENTS.put("protect", Enchantment.PROTECTION_ENVIRONMENTAL); ENCHANTMENTS.put("protect", PROTECTION);
ALIASENCHANTMENTS.put("p", Enchantment.PROTECTION_ENVIRONMENTAL); ALIASENCHANTMENTS.put("p", PROTECTION);
final Enchantment BLAST_PROTECTION = RegistryUtil.valueOf(Enchantment.class, "PROTECTION_EXPLOSIONS", "BLAST_PROTECTION");
ALIASENCHANTMENTS.put("explosionsprotection", Enchantment.PROTECTION_EXPLOSIONS); ALIASENCHANTMENTS.put("explosionsprotection", BLAST_PROTECTION);
ALIASENCHANTMENTS.put("explosionprotection", Enchantment.PROTECTION_EXPLOSIONS); ALIASENCHANTMENTS.put("explosionprotection", BLAST_PROTECTION);
ALIASENCHANTMENTS.put("expprot", Enchantment.PROTECTION_EXPLOSIONS); ALIASENCHANTMENTS.put("expprot", BLAST_PROTECTION);
ALIASENCHANTMENTS.put("blastprotection", Enchantment.PROTECTION_EXPLOSIONS); ALIASENCHANTMENTS.put("blastprotection", BLAST_PROTECTION);
ALIASENCHANTMENTS.put("bprotection", Enchantment.PROTECTION_EXPLOSIONS); ALIASENCHANTMENTS.put("bprotection", BLAST_PROTECTION);
ALIASENCHANTMENTS.put("bprotect", Enchantment.PROTECTION_EXPLOSIONS); ALIASENCHANTMENTS.put("bprotect", BLAST_PROTECTION);
ENCHANTMENTS.put("blastprotect", Enchantment.PROTECTION_EXPLOSIONS); ENCHANTMENTS.put("blastprotect", BLAST_PROTECTION);
ALIASENCHANTMENTS.put("pe", Enchantment.PROTECTION_EXPLOSIONS); ALIASENCHANTMENTS.put("pe", BLAST_PROTECTION);
final Enchantment FEATHER_FALLING = RegistryUtil.valueOf(Enchantment.class, "PROTECTION_FALL", "FEATHER_FALLING");
ALIASENCHANTMENTS.put("fallprotection", Enchantment.PROTECTION_FALL); ALIASENCHANTMENTS.put("fallprotection", FEATHER_FALLING);
ENCHANTMENTS.put("fallprot", Enchantment.PROTECTION_FALL); ENCHANTMENTS.put("fallprot", FEATHER_FALLING);
ENCHANTMENTS.put("featherfall", Enchantment.PROTECTION_FALL); ENCHANTMENTS.put("featherfall", FEATHER_FALLING);
ALIASENCHANTMENTS.put("featherfalling", Enchantment.PROTECTION_FALL); ALIASENCHANTMENTS.put("featherfalling", FEATHER_FALLING);
ALIASENCHANTMENTS.put("pfa", Enchantment.PROTECTION_FALL); ALIASENCHANTMENTS.put("pfa", FEATHER_FALLING);
final Enchantment FIRE_PROTECTION = RegistryUtil.valueOf(Enchantment.class, "PROTECTION_FIRE", "FIRE_PROTECTION");
ALIASENCHANTMENTS.put("fireprotection", Enchantment.PROTECTION_FIRE); ALIASENCHANTMENTS.put("fireprotection", FIRE_PROTECTION);
ALIASENCHANTMENTS.put("flameprotection", Enchantment.PROTECTION_FIRE); ALIASENCHANTMENTS.put("flameprotection", FIRE_PROTECTION);
ENCHANTMENTS.put("fireprotect", Enchantment.PROTECTION_FIRE); ENCHANTMENTS.put("fireprotect", FIRE_PROTECTION);
ALIASENCHANTMENTS.put("flameprotect", Enchantment.PROTECTION_FIRE); ALIASENCHANTMENTS.put("flameprotect", FIRE_PROTECTION);
ENCHANTMENTS.put("fireprot", Enchantment.PROTECTION_FIRE); ENCHANTMENTS.put("fireprot", FIRE_PROTECTION);
ALIASENCHANTMENTS.put("flameprot", Enchantment.PROTECTION_FIRE); ALIASENCHANTMENTS.put("flameprot", FIRE_PROTECTION);
ALIASENCHANTMENTS.put("pf", Enchantment.PROTECTION_FIRE); ALIASENCHANTMENTS.put("pf", FIRE_PROTECTION);
final Enchantment PROJECTILE_PROTECTION = RegistryUtil.valueOf(Enchantment.class, "PROTECTION_PROJECTILE", "PROJECTILE_PROTECTION");
ENCHANTMENTS.put("projectileprotection", Enchantment.PROTECTION_PROJECTILE); ENCHANTMENTS.put("projectileprotection", PROJECTILE_PROTECTION);
ENCHANTMENTS.put("projprot", Enchantment.PROTECTION_PROJECTILE); ENCHANTMENTS.put("projprot", PROJECTILE_PROTECTION);
ALIASENCHANTMENTS.put("pp", Enchantment.PROTECTION_PROJECTILE); ALIASENCHANTMENTS.put("pp", PROJECTILE_PROTECTION);
ENCHANTMENTS.put("silktouch", Enchantment.SILK_TOUCH); ENCHANTMENTS.put("silktouch", Enchantment.SILK_TOUCH);
ALIASENCHANTMENTS.put("softtouch", Enchantment.SILK_TOUCH); ALIASENCHANTMENTS.put("softtouch", Enchantment.SILK_TOUCH);
ALIASENCHANTMENTS.put("st", 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("waterworker", AQUA_AFFINITY);
ENCHANTMENTS.put("aquaaffinity", Enchantment.WATER_WORKER); ENCHANTMENTS.put("aquaaffinity", AQUA_AFFINITY);
ALIASENCHANTMENTS.put("watermine", Enchantment.WATER_WORKER); ALIASENCHANTMENTS.put("watermine", AQUA_AFFINITY);
ALIASENCHANTMENTS.put("ww", Enchantment.WATER_WORKER); ALIASENCHANTMENTS.put("ww", AQUA_AFFINITY);
final Enchantment FLAME = RegistryUtil.valueOf(Enchantment.class, "ARROW_FIRE", "FLAME");
ALIASENCHANTMENTS.put("firearrow", Enchantment.ARROW_FIRE); ALIASENCHANTMENTS.put("firearrow", FLAME);
ENCHANTMENTS.put("flame", Enchantment.ARROW_FIRE); ENCHANTMENTS.put("flame", FLAME);
ENCHANTMENTS.put("flamearrow", Enchantment.ARROW_FIRE); ENCHANTMENTS.put("flamearrow", FLAME);
ALIASENCHANTMENTS.put("af", Enchantment.ARROW_FIRE); ALIASENCHANTMENTS.put("af", FLAME);
final Enchantment POWER = RegistryUtil.valueOf(Enchantment.class, "ARROW_DAMAGE", "POWER");
ENCHANTMENTS.put("arrowdamage", Enchantment.ARROW_DAMAGE); ENCHANTMENTS.put("arrowdamage", POWER);
ENCHANTMENTS.put("power", Enchantment.ARROW_DAMAGE); ENCHANTMENTS.put("power", POWER);
ALIASENCHANTMENTS.put("arrowpower", Enchantment.ARROW_DAMAGE); ALIASENCHANTMENTS.put("arrowpower", POWER);
ALIASENCHANTMENTS.put("ad", Enchantment.ARROW_DAMAGE); ALIASENCHANTMENTS.put("ad", POWER);
final Enchantment PUNCH = RegistryUtil.valueOf(Enchantment.class, "ARROW_KNOCKBACK", "PUNCH");
ENCHANTMENTS.put("arrowknockback", Enchantment.ARROW_KNOCKBACK); ENCHANTMENTS.put("arrowknockback", PUNCH);
ALIASENCHANTMENTS.put("arrowkb", Enchantment.ARROW_KNOCKBACK); ALIASENCHANTMENTS.put("arrowkb", PUNCH);
ENCHANTMENTS.put("punch", Enchantment.ARROW_KNOCKBACK); ENCHANTMENTS.put("punch", PUNCH);
ALIASENCHANTMENTS.put("arrowpunch", Enchantment.ARROW_KNOCKBACK); ALIASENCHANTMENTS.put("arrowpunch", PUNCH);
ALIASENCHANTMENTS.put("ak", Enchantment.ARROW_KNOCKBACK); ALIASENCHANTMENTS.put("ak", PUNCH);
final Enchantment INFINITY = RegistryUtil.valueOf(Enchantment.class, "ARROW_INFINITE", "INFINITY");
ALIASENCHANTMENTS.put("infinitearrows", Enchantment.ARROW_INFINITE); ALIASENCHANTMENTS.put("infinitearrows", INFINITY);
ENCHANTMENTS.put("infarrows", Enchantment.ARROW_INFINITE); ENCHANTMENTS.put("infarrows", INFINITY);
ENCHANTMENTS.put("infinity", Enchantment.ARROW_INFINITE); ENCHANTMENTS.put("infinity", INFINITY);
ALIASENCHANTMENTS.put("infinite", Enchantment.ARROW_INFINITE); ALIASENCHANTMENTS.put("infinite", INFINITY);
ALIASENCHANTMENTS.put("unlimited", Enchantment.ARROW_INFINITE); ALIASENCHANTMENTS.put("unlimited", INFINITY);
ALIASENCHANTMENTS.put("unlimitedarrows", Enchantment.ARROW_INFINITE); ALIASENCHANTMENTS.put("unlimitedarrows", INFINITY);
ALIASENCHANTMENTS.put("ai", Enchantment.ARROW_INFINITE); ALIASENCHANTMENTS.put("ai", INFINITY);
final Enchantment LUCK_OF_THE_SEA = RegistryUtil.valueOf(Enchantment.class, "LUCK", "LUCK_OF_THE_SEA");
ENCHANTMENTS.put("luck", Enchantment.LUCK); ENCHANTMENTS.put("luck", LUCK_OF_THE_SEA);
ALIASENCHANTMENTS.put("luckofsea", Enchantment.LUCK); ALIASENCHANTMENTS.put("luckofsea", LUCK_OF_THE_SEA);
ALIASENCHANTMENTS.put("luckofseas", Enchantment.LUCK); ALIASENCHANTMENTS.put("luckofseas", LUCK_OF_THE_SEA);
ALIASENCHANTMENTS.put("rodluck", Enchantment.LUCK); ALIASENCHANTMENTS.put("rodluck", LUCK_OF_THE_SEA);
ENCHANTMENTS.put("lure", Enchantment.LURE); ENCHANTMENTS.put("lure", Enchantment.LURE);
ALIASENCHANTMENTS.put("rodlure", Enchantment.LURE); ALIASENCHANTMENTS.put("rodlure", Enchantment.LURE);
// 1.8 ENCHANTMENTS.put("depthstrider", Enchantment.DEPTH_STRIDER);
try { ALIASENCHANTMENTS.put("depth", Enchantment.DEPTH_STRIDER);
final Enchantment depthStrider = Enchantment.getByName("DEPTH_STRIDER"); ALIASENCHANTMENTS.put("strider", Enchantment.DEPTH_STRIDER);
if (depthStrider != null) {
ENCHANTMENTS.put("depthstrider", depthStrider);
ALIASENCHANTMENTS.put("depth", depthStrider);
ALIASENCHANTMENTS.put("strider", depthStrider);
}
} catch (final IllegalArgumentException ignored) {
}
// 1.9 // 1.9
try { try {
@ -271,6 +303,24 @@ public final class Enchantments {
} catch (final IllegalArgumentException ignored) { } 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 (breach != null) {
ENCHANTMENTS.put("windburst", windBurst);
ALIASENCHANTMENTS.put("wind", windBurst);
ALIASENCHANTMENTS.put("burst", windBurst);
}
} catch (final IllegalArgumentException ignored) {
}
try { try {
final Class<?> namespacedKeyClass = Class.forName("org.bukkit.NamespacedKey"); final Class<?> namespacedKeyClass = Class.forName("org.bukkit.NamespacedKey");
final Class<?> enchantmentClass = Class.forName("org.bukkit.enchantments.Enchantment"); final Class<?> enchantmentClass = Class.forName("org.bukkit.enchantments.Enchantment");
@ -284,6 +334,17 @@ public final class Enchantments {
private 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) { public static Enchantment getByName(final String name) {
if (name == null || name.isEmpty()) { if (name == null || name.isEmpty()) {
return null; return null;

View File

@ -110,6 +110,7 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerEvent; import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.inventory.InventoryView;
import org.bukkit.plugin.InvalidDescriptionException; import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginDescriptionFile;
@ -142,6 +143,7 @@ import static com.earth2me.essentials.I18n.tlLocale;
public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials { public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private static final Logger BUKKIT_LOGGER = Logger.getLogger("Essentials"); private static final Logger BUKKIT_LOGGER = Logger.getLogger("Essentials");
private static Logger LOGGER = null; private static Logger LOGGER = null;
public static boolean TESTING = false;
private final transient TNTExplodeListener tntListener = new TNTExplodeListener(); private final transient TNTExplodeListener tntListener = new TNTExplodeListener();
private final transient Set<String> vanishedPlayers = new LinkedHashSet<>(); private final transient Set<String> vanishedPlayers = new LinkedHashSet<>();
private final transient Map<String, IEssentialsCommand> commandMap = new HashMap<>(); private final transient Map<String, IEssentialsCommand> commandMap = new HashMap<>();
@ -192,6 +194,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
} }
public void setupForTesting(final Server server) throws IOException, InvalidDescriptionException { public void setupForTesting(final Server server) throws IOException, InvalidDescriptionException {
TESTING = true;
LOGGER = new BaseLoggerProvider(this, BUKKIT_LOGGER); LOGGER = new BaseLoggerProvider(this, BUKKIT_LOGGER);
final File dataFolder = File.createTempFile("essentialstest", ""); final File dataFolder = File.createTempFile("essentialstest", "");
if (!dataFolder.delete()) { if (!dataFolder.delete()) {
@ -359,8 +362,21 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
// Spawn Egg Providers // Spawn Egg Providers
providerFactory.registerProvider(LegacySpawnEggProvider.class, ReflSpawnEggProvider.class, FlatSpawnEggProvider.class); providerFactory.registerProvider(LegacySpawnEggProvider.class, ReflSpawnEggProvider.class, FlatSpawnEggProvider.class);
// Potion Meta Provider //Potion Meta Provider
providerFactory.registerProvider(LegacyPotionMetaProvider.class, BasePotionDataProvider.class); if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_6_R01)) {
potionMetaProvider = new ModernPotionMetaProvider();
} else if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
potionMetaProvider = new PrehistoricPotionMetaProvider();
} else {
potionMetaProvider = new LegacyPotionMetaProvider();
}
//Banner Meta Provider
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_6_R01)) {
bannerDataProvider = new BaseBannerDataProvider();
} else {
bannerDataProvider = new LegacyBannerDataProvider();
}
// Server State Provider // Server State Provider
providerFactory.registerProvider(ReflServerStateProvider.class, PaperServerStateProvider.class); providerFactory.registerProvider(ReflServerStateProvider.class, PaperServerStateProvider.class);
@ -419,6 +435,72 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
} }
} }
//Known Commands Provider
if (PaperLib.isPaper() && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_11_2_R01)) {
knownCommandsProvider = new PaperKnownCommandsProvider();
} else {
knownCommandsProvider = new ReflKnownCommandsProvider();
}
// Command aliases provider
formattedCommandAliasProvider = new ReflFormattedCommandAliasProvider(PaperLib.isPaper());
// Material Tag Providers
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_13_0_R01)) {
materialTagProvider = PaperLib.isPaper() ? new PaperMaterialTagProvider() : new BukkitMaterialTagProvider();
}
// Sync Commands Provider
syncCommandsProvider = new ReflSyncCommandsProvider();
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_14_4_R01)) {
persistentDataProvider = new ModernPersistentDataProvider(this);
} else {
persistentDataProvider = new ReflPersistentDataProvider(this);
}
onlineModeProvider = new ReflOnlineModeProvider();
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_11_2_R01)) {
unbreakableProvider = new ModernItemUnbreakableProvider();
} else {
unbreakableProvider = new LegacyItemUnbreakableProvider();
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_17_1_R01)) {
worldInfoProvider = new ModernDataWorldInfoProvider();
} else if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_16_5_R01)) {
worldInfoProvider = new ReflDataWorldInfoProvider();
} else {
worldInfoProvider = new FixedHeightWorldInfoProvider();
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_14_4_R01)) {
signDataProvider = new ModernSignDataProvider(this);
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_12_2_R01)) {
playerLocaleProvider = new ModernPlayerLocaleProvider();
} else {
playerLocaleProvider = new LegacyPlayerLocaleProvider();
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_4_R01)) {
damageEventProvider = new ModernDamageEventProvider();
} else {
damageEventProvider = new LegacyDamageEventProvider();
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_21_R01)) {
inventoryViewProvider = new BaseInventoryViewProvider();
} else {
inventoryViewProvider = new LegacyInventoryViewProvider();
}
if (PaperLib.isPaper() && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_19_4_R01)) {
biomeKeyProvider = new PaperBiomeKeyProvider();
}
execTimer.mark("Init(Providers)"); execTimer.mark("Init(Providers)");
reload(); reload();
@ -574,6 +656,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
public void reload() { public void reload() {
Trade.closeLog(); Trade.closeLog();
if (bukkitAudience != null) {
bukkitAudience.close();
bukkitAudience = null;
}
for (final IConf iConf : confList) { for (final IConf iConf : confList) {
iConf.reloadConfig(); iConf.reloadConfig();
execTimer.mark("Reload(" + iConf.getClass().getSimpleName() + ")"); execTimer.mark("Reload(" + iConf.getClass().getSimpleName() + ")");
@ -591,6 +678,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
final PluginManager pm = getServer().getPluginManager(); final PluginManager pm = getServer().getPluginManager();
registerListeners(pm); registerListeners(pm);
AdventureUtil.setEss(this);
bukkitAudience = BukkitAudiences.create(this); bukkitAudience = BukkitAudiences.create(this);
} }
@ -813,7 +901,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
sender.sendMessage(command.getUsage().replace("<command>", commandLabel)); sender.sendMessage(command.getUsage().replace("<command>", commandLabel));
} }
if (!ex.getMessage().isEmpty()) { if (!ex.getMessage().isEmpty()) {
sender.sendMessage(ex.getMessage()); sender.sendComponent(AdventureUtil.miniMessage().deserialize(ex.getMessage()));
} }
if (ex.getCause() != null && settings.isDebug()) { if (ex.getCause() != null && settings.isDebug()) {
ex.getCause().printStackTrace(); ex.getCause().printStackTrace();
@ -839,12 +927,14 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
public void cleanupOpenInventories() { public void cleanupOpenInventories() {
for (final User user : getOnlineUsers()) { for (final User user : getOnlineUsers()) {
if (user.isRecipeSee()) { if (user.isRecipeSee()) {
user.getBase().getOpenInventory().getTopInventory().clear(); final InventoryView view = user.getBase().getOpenInventory();
user.getBase().getOpenInventory().close();
inventoryViewProvider.getTopInventory(view).clear();
inventoryViewProvider.close(view);
user.setRecipeSee(false); user.setRecipeSee(false);
} }
if (user.isInvSee() || user.isEnderSee()) { if (user.isInvSee() || user.isEnderSee()) {
user.getBase().getOpenInventory().close(); inventoryViewProvider.close(user.getBase().getOpenInventory());
user.setInvSee(false); user.setInvSee(false);
user.setEnderSee(false); user.setEnderSee(false);
} }
@ -1127,7 +1217,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
@Override @Override
public void broadcastTl(final String tlKey, final Object... args) { public void broadcastTl(final String tlKey, final Object... args) {
broadcastTl(null, null, true, tlKey, args); broadcastTl(null, null, false, tlKey, args);
} }
@Override @Override

View File

@ -301,7 +301,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
} }
user.setLogoutLocation(); user.setLogoutLocation();
if (user.isRecipeSee()) { if (user.isRecipeSee()) {
user.getBase().getOpenInventory().getTopInventory().clear(); ess.getInventoryViewProvider().getTopInventory(user.getBase().getOpenInventory()).clear();
} }
final ArrayList<HumanEntity> viewers = new ArrayList<>(user.getBase().getInventory().getViewers()); final ArrayList<HumanEntity> viewers = new ArrayList<>(user.getBase().getInventory().getViewers());
@ -547,14 +547,14 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
final Date banExpiry = banEntry.getExpiration(); final Date banExpiry = banEntry.getExpiration();
if (banExpiry != null) { if (banExpiry != null) {
final String expiry = DateUtil.formatDateDiff(banExpiry.getTime()); final String expiry = DateUtil.formatDateDiff(banExpiry.getTime());
event.setKickMessage(tlLiteral("tempbanJoin", expiry, banEntry.getReason())); event.setKickMessage(AdventureUtil.miniToLegacy(tlLiteral("tempbanJoin", expiry, banEntry.getReason())));
} else { } else {
event.setKickMessage(tlLiteral("banJoin", banEntry.getReason())); event.setKickMessage(AdventureUtil.miniToLegacy(tlLiteral("banJoin", banEntry.getReason())));
} }
} else { } else {
banEntry = ess.getServer().getBanList(BanList.Type.IP).getBanEntry(event.getAddress().getHostAddress()); banEntry = ess.getServer().getBanList(BanList.Type.IP).getBanEntry(event.getAddress().getHostAddress());
if (banEntry != null) { if (banEntry != null) {
event.setKickMessage(tlLiteral("banIpJoin", banEntry.getReason())); event.setKickMessage(AdventureUtil.miniToLegacy(tlLiteral("banIpJoin", banEntry.getReason())));
} }
} }
} }
@ -642,12 +642,13 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|| (!pluginCommand.getName().equals("msg") && !pluginCommand.getName().equals("r"))) { // /msg and /r are handled in SimpleMessageRecipient || (!pluginCommand.getName().equals("msg") && !pluginCommand.getName().equals("r"))) { // /msg and /r are handled in SimpleMessageRecipient
final User user = ess.getUser(player); final User user = ess.getUser(player);
if (!user.isAuthorized("essentials.chat.spy.exempt")) { if (!user.isAuthorized("essentials.chat.spy.exempt")) {
final String playerName = ess.getSettings().isSocialSpyDisplayNames() ? player.getDisplayName() : player.getName();
for (final User spyer : ess.getOnlineUsers()) { for (final User spyer : ess.getOnlineUsers()) {
if (spyer.isSocialSpyEnabled() && !player.equals(spyer.getBase())) { if (spyer.isSocialSpyEnabled() && !player.equals(spyer.getBase())) {
final Component base = (user.isMuted() && ess.getSettings().getSocialSpyListenMutedPlayers()) final Component base = (user.isMuted() && ess.getSettings().getSocialSpyListenMutedPlayers())
? spyer.tlComponent("socialSpyMutedPrefix") ? spyer.tlComponent("socialSpyMutedPrefix")
: spyer.tlComponent("socialSpyPrefix"); : spyer.tlComponent("socialSpyPrefix");
spyer.sendComponent(base.append(AdventureUtil.legacyToAdventure(player.getDisplayName())).append(Component.text(": " + event.getMessage()))); spyer.sendComponent(base.append(AdventureUtil.legacyToAdventure(playerName)).append(Component.text(": " + event.getMessage())));
} }
} }
} }
@ -898,14 +899,14 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onInventoryClickEvent(final InventoryClickEvent event) { public void onInventoryClickEvent(final InventoryClickEvent event) {
Player refreshPlayer = null; Player refreshPlayer = null;
final Inventory top = event.getView().getTopInventory(); final Inventory top = ess.getInventoryViewProvider().getTopInventory(event.getView());
final InventoryType type = top.getType(); final InventoryType type = top.getType();
final Inventory clickedInventory; final Inventory clickedInventory;
if (event.getRawSlot() < 0) { if (event.getRawSlot() < 0) {
clickedInventory = null; clickedInventory = null;
} else { } else {
clickedInventory = event.getRawSlot() < top.getSize() ? top : event.getView().getBottomInventory(); clickedInventory = event.getRawSlot() < top.getSize() ? top : ess.getInventoryViewProvider().getBottomInventory(event.getView());
} }
final User user = ess.getUser((Player) event.getWhoClicked()); final User user = ess.getUser((Player) event.getWhoClicked());
@ -964,7 +965,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onInventoryCloseEvent(final InventoryCloseEvent event) { public void onInventoryCloseEvent(final InventoryCloseEvent event) {
Player refreshPlayer = null; Player refreshPlayer = null;
final Inventory top = event.getView().getTopInventory(); final Inventory top = ess.getInventoryViewProvider().getTopInventory(event.getView());
final InventoryType type = top.getType(); final InventoryType type = top.getType();
if (type == InventoryType.PLAYER) { if (type == InventoryType.PLAYER) {
final User user = ess.getUser((Player) event.getPlayer()); final User user = ess.getUser((Player) event.getPlayer());
@ -978,7 +979,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
final User user = ess.getUser((Player) event.getPlayer()); final User user = ess.getUser((Player) event.getPlayer());
if (user.isRecipeSee()) { if (user.isRecipeSee()) {
user.setRecipeSee(false); user.setRecipeSee(false);
event.getView().getTopInventory().clear(); ess.getInventoryViewProvider().getTopInventory(event.getView()).clear();
refreshPlayer = user.getBase(); refreshPlayer = user.getBase();
} }
} else if (type == InventoryType.CHEST && top.getSize() == 9) { } else if (type == InventoryType.CHEST && top.getSize() == 9) {

View File

@ -182,8 +182,10 @@ public class I18n implements net.ess3.api.II18n {
} }
final Object[] processedArgs = mutateArgs(objects, arg -> { final Object[] processedArgs = mutateArgs(objects, arg -> {
final String str = arg instanceof AdventureUtil.ParsedPlaceholder ? arg.toString() : AdventureUtil.miniMessage().escapeTags(arg.toString()); if (arg instanceof AdventureUtil.ParsedPlaceholder) {
return AdventureUtil.legacyToMini(str); return arg.toString();
}
return AdventureUtil.legacyToMini(AdventureUtil.miniMessage().escapeTags(arg.toString()));
}); });
return messageFormat.format(processedArgs).replace(' ', ' '); // replace nbsp with a space return messageFormat.format(processedArgs).replace(' ', ' '); // replace nbsp with a space

View File

@ -73,6 +73,8 @@ public interface ISettings extends IConf {
boolean isSocialSpyMessages(); boolean isSocialSpyMessages();
boolean isSocialSpyDisplayNames();
Set<String> getMuteCommands(); Set<String> getMuteCommands();
@Deprecated @Deprecated

View File

@ -31,7 +31,6 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
@ -131,21 +130,30 @@ public class MetaItemStack {
} }
public boolean canSpawn(final IEssentials ess) { public boolean canSpawn(final IEssentials ess) {
try { if (VersionUtil.PRE_FLATTENING) {
ess.getServer().getUnsafe().modifyItemStack(stack.clone(), "{}"); try {
return true; ess.getServer().getUnsafe().modifyItemStack(stack.clone(), "{}");
} catch (final NoSuchMethodError nsme) { return true;
return true; } catch (final NoSuchMethodError nsme) {
} catch (final Throwable npe) { return true;
if (ess.getSettings().isDebug()) { } catch (final Throwable npe) {
ess.getLogger().log(Level.INFO, "Itemstack is invalid", npe); if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "Itemstack is invalid", npe);
}
return false;
} }
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 { 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 (string[fromArg].startsWith("{") && hasMetaPermission(sender, "vanilla", false, true, ess)) {
if (nbtIsKill) {
throw new TranslatableException("noMetaNbtKill");
}
try { try {
stack = ess.getServer().getUnsafe().modifyItemStack(stack, Joiner.on(' ').join(Arrays.asList(string).subList(fromArg, string.length))); stack = ess.getServer().getUnsafe().modifyItemStack(stack, Joiner.on(' ').join(Arrays.asList(string).subList(fromArg, string.length)));
} catch (final NullPointerException npe) { } catch (final NullPointerException npe) {
@ -157,6 +165,22 @@ public class MetaItemStack {
} catch (final Throwable throwable) { } catch (final Throwable throwable) {
throw new Exception(throwable.getMessage(), 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));
// modifyItemStack requires that the item namespaced key is prepended to the components for some reason
stack = ess.getServer().getUnsafe().modifyItemStack(stack, stack.getType().getKey() + components);
} catch (final NullPointerException npe) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "Itemstack is invalid", npe);
}
} catch (final Throwable throwable) {
throw new Exception(throwable.getMessage(), throwable);
}
} else { } else {
for (int i = fromArg; i < string.length; i++) { for (int i = fromArg; i < string.length; i++) {
addStringMeta(sender, allowUnsafe, string[i], ess); addStringMeta(sender, allowUnsafe, string[i], ess);
@ -542,17 +566,7 @@ public class MetaItemStack {
} }
pmeta.addCustomEffect(pEffect, true); pmeta.addCustomEffect(pEffect, true);
stack.setItemMeta(pmeta); stack.setItemMeta(pmeta);
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01)) { ess.getPotionMetaProvider().setSplashPotion(stack, isSplashPotion);
if (isSplashPotion && stack.getType() == Material.POTION) {
stack.setType(Material.SPLASH_POTION);
} else if (!isSplashPotion && stack.getType() == Material.SPLASH_POTION) {
stack.setType(Material.POTION);
}
} else {
final Potion potion = Potion.fromDamage(stack.getDurability());
potion.setSplash(isSplashPotion);
potion.apply(stack);
}
resetPotionMeta(); resetPotionMeta();
} }
} }
@ -563,7 +577,7 @@ public class MetaItemStack {
if (enchantment == null) { if (enchantment == null) {
return false; return false;
} }
if (hasMetaPermission(sender, "enchantments." + enchantment.getName().toLowerCase(Locale.ENGLISH), false, false, ess)) { if (hasMetaPermission(sender, "enchantments." + Enchantments.getRealName(enchantment), false, false, ess)) {
int level = -1; int level = -1;
if (split.length > 1) { if (split.length > 1) {
try { try {
@ -606,7 +620,7 @@ public class MetaItemStack {
} }
} }
} catch (final Exception ex) { } catch (final Exception ex) {
throw new Exception("Enchantment " + enchantment.getName() + ": " + ex.getMessage(), ex); throw new Exception("Enchantment " + Enchantments.getRealName(enchantment) + ": " + ex.getMessage(), ex);
} }
} }
@ -616,7 +630,7 @@ public class MetaItemStack {
return null; return null;
} }
final String enchantmentName = enchantment.getName().toLowerCase(Locale.ENGLISH); final String enchantmentName = Enchantments.getRealName(enchantment);
if (!hasMetaPermission(user, "enchantments." + enchantmentName, true, false)) { if (!hasMetaPermission(user, "enchantments." + enchantmentName, true, false)) {
throw new TranslatableException("enchantmentPerm", enchantmentName); throw new TranslatableException("enchantmentPerm", enchantmentName);
@ -634,16 +648,18 @@ public class MetaItemStack {
PatternType patternType = null; PatternType patternType = null;
try { try {
patternType = PatternType.valueOf(split[0]); //noinspection removal
patternType = PatternType.getByIdentifier(split[0]);
} catch (final Exception ignored) { } catch (final Exception ignored) {
} }
final BannerMeta meta = (BannerMeta) stack.getItemMeta(); final BannerMeta meta = (BannerMeta) stack.getItemMeta();
if (split[0].equalsIgnoreCase("basecolor")) { if (split[0].equalsIgnoreCase("basecolor")) {
final Color color = Color.fromRGB(Integer.parseInt(split[1])); final Color color = Color.fromRGB(Integer.parseInt(split[1]));
meta.setBaseColor(DyeColor.getByColor(color)); ess.getBannerDataProvider().setBaseColor(stack, DyeColor.getByColor(color));
} else if (patternType != null) { } else if (patternType != null) {
final PatternType type = PatternType.valueOf(split[0]); //noinspection removal
final PatternType type = PatternType.getByIdentifier(split[0]);
final DyeColor color = DyeColor.getByColor(Color.fromRGB(Integer.parseInt(split[1]))); final DyeColor color = DyeColor.getByColor(Color.fromRGB(Integer.parseInt(split[1])));
final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type); final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type);
meta.addPattern(pattern); meta.addPattern(pattern);
@ -659,7 +675,8 @@ public class MetaItemStack {
PatternType patternType = null; PatternType patternType = null;
try { try {
patternType = PatternType.valueOf(split[0]); //noinspection removal
patternType = PatternType.getByIdentifier(split[0]);
} catch (final Exception ignored) { } catch (final Exception ignored) {
} }
@ -670,7 +687,8 @@ public class MetaItemStack {
final Color color = Color.fromRGB(Integer.parseInt(split[1])); final Color color = Color.fromRGB(Integer.parseInt(split[1]));
banner.setBaseColor(DyeColor.getByColor(color)); banner.setBaseColor(DyeColor.getByColor(color));
} else if (patternType != null) { } else if (patternType != null) {
final PatternType type = PatternType.valueOf(split[0]); //noinspection removal
final PatternType type = PatternType.getByIdentifier(split[0]);
final DyeColor color = DyeColor.getByColor(Color.fromRGB(Integer.parseInt(split[1]))); final DyeColor color = DyeColor.getByColor(Color.fromRGB(Integer.parseInt(split[1])));
final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type); final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type);
banner.addPattern(pattern); banner.addPattern(pattern);

View File

@ -42,9 +42,9 @@ public enum Mob {
ENDERDRAGON("EnderDragon", Enemies.ENEMY, EntityType.ENDER_DRAGON), ENDERDRAGON("EnderDragon", Enemies.ENEMY, EntityType.ENDER_DRAGON),
VILLAGER("Villager", Enemies.FRIENDLY, EntityType.VILLAGER), VILLAGER("Villager", Enemies.FRIENDLY, EntityType.VILLAGER),
BLAZE("Blaze", Enemies.ENEMY, EntityType.BLAZE), BLAZE("Blaze", Enemies.ENEMY, EntityType.BLAZE),
MUSHROOMCOW("MushroomCow", Enemies.FRIENDLY, EntityType.MUSHROOM_COW), MUSHROOMCOW("MushroomCow", Enemies.FRIENDLY, MobCompat.MOOSHROOM),
MAGMACUBE("MagmaCube", Enemies.ENEMY, EntityType.MAGMA_CUBE), MAGMACUBE("MagmaCube", Enemies.ENEMY, EntityType.MAGMA_CUBE),
SNOWMAN("Snowman", Enemies.FRIENDLY, "", EntityType.SNOWMAN), SNOWMAN("Snowman", Enemies.FRIENDLY, "", MobCompat.SNOW_GOLEM),
OCELOT("Ocelot", Enemies.NEUTRAL, EntityType.OCELOT), OCELOT("Ocelot", Enemies.NEUTRAL, EntityType.OCELOT),
IRONGOLEM("IronGolem", Enemies.NEUTRAL, EntityType.IRON_GOLEM), IRONGOLEM("IronGolem", Enemies.NEUTRAL, EntityType.IRON_GOLEM),
WITHER("Wither", Enemies.ENEMY, EntityType.WITHER), WITHER("Wither", Enemies.ENEMY, EntityType.WITHER),
@ -52,12 +52,12 @@ public enum Mob {
WITCH("Witch", Enemies.ENEMY, EntityType.WITCH), WITCH("Witch", Enemies.ENEMY, EntityType.WITCH),
BOAT("Boat", Enemies.NEUTRAL, EntityType.BOAT), BOAT("Boat", Enemies.NEUTRAL, EntityType.BOAT),
MINECART("Minecart", Enemies.NEUTRAL, EntityType.MINECART), MINECART("Minecart", Enemies.NEUTRAL, EntityType.MINECART),
MINECART_CHEST("ChestMinecart", Enemies.NEUTRAL, EntityType.MINECART_CHEST), MINECART_CHEST("ChestMinecart", Enemies.NEUTRAL, MobCompat.CHEST_MINECART),
MINECART_FURNACE("FurnaceMinecart", Enemies.NEUTRAL, EntityType.MINECART_FURNACE), MINECART_FURNACE("FurnaceMinecart", Enemies.NEUTRAL, MobCompat.FURNACE_MINECART),
MINECART_TNT("TNTMinecart", Enemies.NEUTRAL, EntityType.MINECART_TNT), MINECART_TNT("TNTMinecart", Enemies.NEUTRAL, MobCompat.TNT_MINECART),
MINECART_HOPPER("HopperMinecart", Enemies.NEUTRAL, EntityType.MINECART_HOPPER), MINECART_HOPPER("HopperMinecart", Enemies.NEUTRAL, MobCompat.HOPPER_MINECART),
MINECART_MOB_SPAWNER("SpawnerMinecart", Enemies.NEUTRAL, EntityType.MINECART_MOB_SPAWNER), MINECART_MOB_SPAWNER("SpawnerMinecart", Enemies.NEUTRAL, MobCompat.SPAWNER_MINECART),
ENDERCRYSTAL("EnderCrystal", Enemies.NEUTRAL, EntityType.ENDER_CRYSTAL), ENDERCRYSTAL("EnderCrystal", Enemies.NEUTRAL, MobCompat.END_CRYSTAL),
EXPERIENCEORB("ExperienceOrb", Enemies.NEUTRAL, "EXPERIENCE_ORB"), EXPERIENCEORB("ExperienceOrb", Enemies.NEUTRAL, "EXPERIENCE_ORB"),
ARMOR_STAND("ArmorStand", Enemies.NEUTRAL, "ARMOR_STAND"), ARMOR_STAND("ArmorStand", Enemies.NEUTRAL, "ARMOR_STAND"),
ENDERMITE("Endermite", Enemies.ENEMY, "ENDERMITE"), ENDERMITE("Endermite", Enemies.ENEMY, "ENDERMITE"),
@ -112,6 +112,9 @@ public enum Mob {
CHEST_BOAT("ChestBoat", Enemies.NEUTRAL, "CHEST_BOAT"), CHEST_BOAT("ChestBoat", Enemies.NEUTRAL, "CHEST_BOAT"),
CAMEL("Camel", Enemies.FRIENDLY, "CAMEL"), CAMEL("Camel", Enemies.FRIENDLY, "CAMEL"),
SNIFFER("Sniffer", Enemies.FRIENDLY, "SNIFFER"), SNIFFER("Sniffer", Enemies.FRIENDLY, "SNIFFER"),
ARMADILLO("Armadillo", Enemies.FRIENDLY, "ARMADILLO"),
BREEZE("Breeze", Enemies.ENEMY, "BREEZE"),
BOGGED("Bogged", Enemies.ENEMY, "BOGGED"),
; ;
private static final Map<String, Mob> hashMap = new HashMap<>(); private static final Map<String, Mob> hashMap = new HashMap<>();

View File

@ -1,6 +1,7 @@
package com.earth2me.essentials; package com.earth2me.essentials;
import com.earth2me.essentials.utils.EnumUtil; import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.RegistryUtil;
import com.earth2me.essentials.utils.VersionUtil; import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.nms.refl.ReflUtil; import net.ess3.nms.refl.ReflUtil;
import org.bukkit.Material; import org.bukkit.Material;
@ -20,6 +21,7 @@ import org.bukkit.entity.Parrot;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.TropicalFish; import org.bukkit.entity.TropicalFish;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
import org.bukkit.entity.Wolf;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -50,6 +52,15 @@ public final class MobCompat {
// Constants for mobs that have changed since earlier versions // Constants for mobs that have changed since earlier versions
public static final EntityType CAT = getEntityType("CAT", "OCELOT"); public static final EntityType CAT = getEntityType("CAT", "OCELOT");
public static final EntityType ZOMBIFIED_PIGLIN = getEntityType("ZOMBIFIED_PIGLIN", "PIG_ZOMBIE"); 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");
private MobCompat() { private MobCompat() {
} }
@ -213,6 +224,18 @@ public final class MobCompat {
} }
} }
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 enum CatType { public enum CatType {
// These are (loosely) Mojang names for the cats // These are (loosely) Mojang names for the cats
SIAMESE("SIAMESE", "SIAMESE_CAT"), SIAMESE("SIAMESE", "SIAMESE_CAT"),
@ -273,7 +296,7 @@ public final class MobCompat {
} }
private Villager.Profession asEnum() { private Villager.Profession asEnum() {
return EnumUtil.valueOf(Villager.Profession.class, newProfession, oldProfession); return RegistryUtil.valueOf(Villager.Profession.class, newProfession, oldProfession);
} }
} }

View File

@ -157,8 +157,8 @@ public enum MobData {
BLOCKFISH_TROPICAL_FISH("blockfish", MobCompat.TROPICAL_FISH, "tropicalfish:BLOCKFISH", true), BLOCKFISH_TROPICAL_FISH("blockfish", MobCompat.TROPICAL_FISH, "tropicalfish:BLOCKFISH", true),
BETTY_TROPICAL_FISH("betty", MobCompat.TROPICAL_FISH, "tropicalfish:BETTY", true), BETTY_TROPICAL_FISH("betty", MobCompat.TROPICAL_FISH, "tropicalfish:BETTY", true),
CLAYFISH_TROPICAL_FISH("clayfish", MobCompat.TROPICAL_FISH, "tropicalfish:CLAYFISH", true), CLAYFISH_TROPICAL_FISH("clayfish", MobCompat.TROPICAL_FISH, "tropicalfish:CLAYFISH", true),
BROWN_MUSHROOM_COW("brown", EntityType.MUSHROOM_COW, "mooshroom:BROWN", true), BROWN_MUSHROOM_COW("brown", MobCompat.MOOSHROOM, "mooshroom:BROWN", true),
RED_MUSHROOM_COW("red", EntityType.MUSHROOM_COW, "mooshroom:RED", true), RED_MUSHROOM_COW("red", MobCompat.MOOSHROOM, "mooshroom:RED", true),
AGGRESSIVE_PANDA_MAIN("aggressive", MobCompat.PANDA, "pandamain:AGGRESSIVE", true), AGGRESSIVE_PANDA_MAIN("aggressive", MobCompat.PANDA, "pandamain:AGGRESSIVE", true),
LAZY_PANDA_MAIN("lazy", MobCompat.PANDA, "pandamain:LAZY", true), LAZY_PANDA_MAIN("lazy", MobCompat.PANDA, "pandamain:LAZY", true),
WORRIED_PANDA_MAIN("worried", MobCompat.PANDA, "pandamain:WORRIED", true), WORRIED_PANDA_MAIN("worried", MobCompat.PANDA, "pandamain:WORRIED", true),
@ -209,6 +209,15 @@ public enum MobData {
OAK_BOAT("oak", Boat.class, MobCompat.BoatVariant.OAK, true), OAK_BOAT("oak", Boat.class, MobCompat.BoatVariant.OAK, true),
SPRUCE_BOAT("spruce", Boat.class, MobCompat.BoatVariant.SPRUCE, true), SPRUCE_BOAT("spruce", Boat.class, MobCompat.BoatVariant.SPRUCE, true),
SADDLE_CAMEL("saddle", MobCompat.CAMEL, Data.CAMELSADDLE, true), SADDLE_CAMEL("saddle", MobCompat.CAMEL, Data.CAMELSADDLE, true),
PALE_WOLF("pale", EntityType.WOLF, "wolf:PALE", true),
SPOTTED_WOLF("spotted", EntityType.WOLF, "wolf:PALE", true),
SNOWY_WOLF("snowy", EntityType.WOLF, "wolf:PALE", true),
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),
; ;
final private String nickname; final private String nickname;
@ -424,6 +433,9 @@ public enum MobData {
case "frog": case "frog":
MobCompat.setFrogVariant(spawned, split[1]); MobCompat.setFrogVariant(spawned, split[1]);
break; break;
case "wolf":
MobCompat.setWolfVariant(spawned, split[1]);
break;
} }
} else { } else {
Essentials.getWrappedLogger().warning("Unknown mob data type: " + this.toString()); Essentials.getWrappedLogger().warning("Unknown mob data type: " + this.toString());

View File

@ -1,6 +1,7 @@
package com.earth2me.essentials; package com.earth2me.essentials;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -31,4 +32,11 @@ public class PlayerExtension {
public Location getLocation() { public Location getLocation() {
return base.getLocation(); return base.getLocation();
} }
public OfflinePlayer getOffline() {
if (base instanceof OfflinePlayerStub) {
return ((OfflinePlayerStub) base).base;
}
return base;
}
} }

View File

@ -1,6 +1,7 @@
package com.earth2me.essentials; package com.earth2me.essentials;
import com.earth2me.essentials.utils.NumberUtil; import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.RegistryUtil;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import java.util.HashMap; import java.util.HashMap;
@ -21,50 +22,68 @@ public final class Potions {
ALIASPOTIONS.put("sprint", PotionEffectType.SPEED); ALIASPOTIONS.put("sprint", PotionEffectType.SPEED);
ALIASPOTIONS.put("swift", PotionEffectType.SPEED); ALIASPOTIONS.put("swift", PotionEffectType.SPEED);
POTIONS.put("slowness", PotionEffectType.SLOW); final PotionEffectType SLOWNESS = RegistryUtil.valueOf(PotionEffectType.class, "SLOW", "SLOWNESS");
ALIASPOTIONS.put("slow", PotionEffectType.SLOW);
ALIASPOTIONS.put("sluggish", PotionEffectType.SLOW);
POTIONS.put("haste", PotionEffectType.FAST_DIGGING); POTIONS.put("slowness", SLOWNESS);
ALIASPOTIONS.put("superpick", PotionEffectType.FAST_DIGGING); ALIASPOTIONS.put("slow", SLOWNESS);
ALIASPOTIONS.put("quickmine", PotionEffectType.FAST_DIGGING); ALIASPOTIONS.put("sluggish", SLOWNESS);
ALIASPOTIONS.put("digspeed", PotionEffectType.FAST_DIGGING);
ALIASPOTIONS.put("digfast", PotionEffectType.FAST_DIGGING);
ALIASPOTIONS.put("sharp", PotionEffectType.FAST_DIGGING);
POTIONS.put("fatigue", PotionEffectType.SLOW_DIGGING); final PotionEffectType HASTE = RegistryUtil.valueOf(PotionEffectType.class, "FAST_DIGGING", "HASTE");
ALIASPOTIONS.put("slow", PotionEffectType.SLOW_DIGGING);
ALIASPOTIONS.put("dull", PotionEffectType.SLOW_DIGGING);
POTIONS.put("strength", PotionEffectType.INCREASE_DAMAGE); POTIONS.put("haste", HASTE);
ALIASPOTIONS.put("strong", PotionEffectType.INCREASE_DAMAGE); ALIASPOTIONS.put("superpick", HASTE);
ALIASPOTIONS.put("bull", PotionEffectType.INCREASE_DAMAGE); ALIASPOTIONS.put("quickmine", HASTE);
ALIASPOTIONS.put("attack", PotionEffectType.INCREASE_DAMAGE); ALIASPOTIONS.put("digspeed", HASTE);
ALIASPOTIONS.put("digfast", HASTE);
ALIASPOTIONS.put("sharp", HASTE);
POTIONS.put("heal", PotionEffectType.HEAL); final PotionEffectType MINING_FATIGUE = RegistryUtil.valueOf(PotionEffectType.class, "SLOW_DIGGING", "MINING_FATIGUE");
ALIASPOTIONS.put("healthy", PotionEffectType.HEAL);
ALIASPOTIONS.put("instaheal", PotionEffectType.HEAL);
POTIONS.put("harm", PotionEffectType.HARM); POTIONS.put("fatigue", MINING_FATIGUE);
ALIASPOTIONS.put("harming", PotionEffectType.HARM); ALIASPOTIONS.put("slow", MINING_FATIGUE);
ALIASPOTIONS.put("injure", PotionEffectType.HARM); ALIASPOTIONS.put("dull", MINING_FATIGUE);
ALIASPOTIONS.put("damage", PotionEffectType.HARM);
ALIASPOTIONS.put("inflict", PotionEffectType.HARM);
POTIONS.put("jump", PotionEffectType.JUMP); final PotionEffectType STRENGTH = RegistryUtil.valueOf(PotionEffectType.class, "INCREASE_DAMAGE", "STRENGTH");
ALIASPOTIONS.put("leap", PotionEffectType.JUMP);
POTIONS.put("nausea", PotionEffectType.CONFUSION); POTIONS.put("strength", STRENGTH);
ALIASPOTIONS.put("sick", PotionEffectType.CONFUSION); ALIASPOTIONS.put("strong", STRENGTH);
ALIASPOTIONS.put("sickness", PotionEffectType.CONFUSION); ALIASPOTIONS.put("bull", STRENGTH);
ALIASPOTIONS.put("confusion", PotionEffectType.CONFUSION); 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("regeneration", PotionEffectType.REGENERATION); POTIONS.put("regeneration", PotionEffectType.REGENERATION);
ALIASPOTIONS.put("regen", PotionEffectType.REGENERATION); ALIASPOTIONS.put("regen", PotionEffectType.REGENERATION);
POTIONS.put("resistance", PotionEffectType.DAMAGE_RESISTANCE); final PotionEffectType RESISTANCE = RegistryUtil.valueOf(PotionEffectType.class, "DAMAGE_RESISTANCE", "RESISTANCE");
ALIASPOTIONS.put("dmgresist", PotionEffectType.DAMAGE_RESISTANCE);
ALIASPOTIONS.put("armor", PotionEffectType.DAMAGE_RESISTANCE); POTIONS.put("resistance", RESISTANCE);
ALIASPOTIONS.put("dmgresist", RESISTANCE);
ALIASPOTIONS.put("armor", RESISTANCE);
POTIONS.put("fireresist", PotionEffectType.FIRE_RESISTANCE); POTIONS.put("fireresist", PotionEffectType.FIRE_RESISTANCE);
ALIASPOTIONS.put("fireresistance", PotionEffectType.FIRE_RESISTANCE); ALIASPOTIONS.put("fireresistance", PotionEffectType.FIRE_RESISTANCE);
@ -125,6 +144,23 @@ public final class Potions {
POTIONS.put("unluck", PotionEffectType.UNLUCK); POTIONS.put("unluck", PotionEffectType.UNLUCK);
} catch (final Throwable ignored) { } 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) {
}
} }
private Potions() { private Potions() {

View File

@ -6,14 +6,13 @@ import com.earth2me.essentials.utils.LocationUtil;
import com.earth2me.essentials.utils.VersionUtil; import com.earth2me.essentials.utils.VersionUtil;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import net.ess3.api.InvalidWorldException; import net.ess3.api.InvalidWorldException;
import net.ess3.provider.BiomeKeyProvider;
import net.ess3.provider.WorldInfoProvider; import net.ess3.provider.WorldInfoProvider;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome;
import java.io.File; import java.io.File;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
@ -78,14 +77,10 @@ public class RandomTeleport implements IConf {
config.save(); config.save();
} }
public Set<Biome> getExcludedBiomes() { public Set<String> getExcludedBiomes() {
final List<String> biomeNames = config.getList("excluded-biomes", String.class); final Set<String> excludedBiomes = new HashSet<>();
final Set<Biome> excludedBiomes = new HashSet<>(); for (final String key : config.getList("excluded-biomes", String.class)) {
for (final String biomeName : biomeNames) { excludedBiomes.add(key.toLowerCase());
try {
excludedBiomes.add(Biome.valueOf(biomeName.toUpperCase()));
} catch (final IllegalArgumentException ignored) {
}
} }
return excludedBiomes; return excludedBiomes;
} }
@ -206,7 +201,31 @@ public class RandomTeleport implements IConf {
} }
private boolean isValidRandomLocation(final Location location) { private boolean isValidRandomLocation(final Location location) {
return location.getBlockY() > worldInfoProvider.getMinHeight(location.getWorld()) && !this.getExcludedBiomes().contains(location.getBlock().getBiome()); return location.getBlockY() > worldInfoProvider.getMinHeight(location.getWorld()) && !isExcludedBiome(location);
}
// Exclude biome if enum or namespaced key matches
private boolean isExcludedBiome(final Location location) {
final Set<String> excluded = getExcludedBiomes();
final String enumKey = location.getBlock().getBiome().name().toLowerCase();
// 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.getBiomeKeyProvider();
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);
} }
public File getFile() { public File getFile() {

View File

@ -55,6 +55,8 @@ import static com.earth2me.essentials.I18n.tlLiteral;
public class Settings implements net.ess3.api.ISettings { public class Settings implements net.ess3.api.ISettings {
private static final BigDecimal DEFAULT_MAX_MONEY = new BigDecimal("10000000000000"); private static final BigDecimal DEFAULT_MAX_MONEY = new BigDecimal("10000000000000");
private static final BigDecimal DEFAULT_MIN_MONEY = new BigDecimal("-10000000000000"); private static final BigDecimal DEFAULT_MIN_MONEY = new BigDecimal("-10000000000000");
private static final Tag DEFAULT_PRIMARY_COLOR = Tag.styling(NamedTextColor.GOLD);
private static final Tag DEFAULT_SECONDARY_COLOR = Tag.styling(NamedTextColor.RED);
private final transient EssentialsConfiguration config; private final transient EssentialsConfiguration config;
private final transient IEssentials ess; private final transient IEssentials ess;
private final transient AtomicInteger reloadCount = new AtomicInteger(0); private final transient AtomicInteger reloadCount = new AtomicInteger(0);
@ -143,8 +145,8 @@ public class Settings implements net.ess3.api.ISettings {
private double maxProjectileSpeed; private double maxProjectileSpeed;
private boolean removeEffectsOnHeal; private boolean removeEffectsOnHeal;
private Map<String, String> worldAliases; private Map<String, String> worldAliases;
private Tag primaryColor = Tag.styling(NamedTextColor.GOLD); private Tag primaryColor = DEFAULT_PRIMARY_COLOR;
private Tag secondaryColor = Tag.styling(NamedTextColor.RED); private Tag secondaryColor = DEFAULT_SECONDARY_COLOR;
public Settings(final IEssentials ess) { public Settings(final IEssentials ess) {
this.ess = ess; this.ess = ess;
@ -458,6 +460,11 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("socialspy-messages", true); return config.getBoolean("socialspy-messages", true);
} }
@Override
public boolean isSocialSpyDisplayNames() {
return config.getBoolean("socialspy-uses-displaynames", true);
}
private Set<String> _getMuteCommands() { private Set<String> _getMuteCommands() {
final Set<String> muteCommands = new HashSet<>(); final Set<String> muteCommands = new HashSet<>();
if (config.isList("mute-commands")) { if (config.isList("mute-commands")) {
@ -1978,7 +1985,8 @@ public class Settings implements net.ess3.api.ISettings {
private Tag _getPrimaryColor() { private Tag _getPrimaryColor() {
final String color = config.getString("message-colors.primary", "#ffaa00"); final String color = config.getString("message-colors.primary", "#ffaa00");
return Tag.styling(_getTagColor(color, NamedTextColor.GOLD)); final TextColor textColor = _getTagColor(color);
return textColor != null ? Tag.styling(textColor) : DEFAULT_PRIMARY_COLOR;
} }
@Override @Override
@ -1988,24 +1996,23 @@ public class Settings implements net.ess3.api.ISettings {
private Tag _getSecondaryColor() { private Tag _getSecondaryColor() {
final String color = config.getString("message-colors.secondary", "#ff5555"); final String color = config.getString("message-colors.secondary", "#ff5555");
return Tag.styling(_getTagColor(color, NamedTextColor.RED)); final TextColor textColor = _getTagColor(color);
return textColor != null ? Tag.styling(textColor) : DEFAULT_SECONDARY_COLOR;
} }
private TextColor _getTagColor(final String color, final TextColor def) { private TextColor _getTagColor(final String color) {
try { try {
if (color.startsWith("#") && color.length() == 7 && NumberUtil.isNumeric(color.substring(1))) { if (color.startsWith("#") && color.length() == 7 && NumberUtil.isHexadecimal(color.substring(1))) {
return TextColor.color(Color.fromRGB(Integer.decode(color)).asRGB()); return TextColor.color(Color.fromRGB(Integer.decode(color)).asRGB());
} }
if (color.length() == 1) { if (color.length() == 1) {
final NamedTextColor named = AdventureUtil.fromChar(color.charAt(0)); return AdventureUtil.fromChar(color.charAt(0));
return named != null ? named : def;
} }
final NamedTextColor named = NamedTextColor.NAMES.value(color.toLowerCase(Locale.ENGLISH)); return NamedTextColor.NAMES.value(color.toLowerCase(Locale.ENGLISH));
return named != null ? named : def;
} catch (IllegalArgumentException ignored) { } catch (IllegalArgumentException ignored) {
} }
return def; return null;
} }
} }

View File

@ -191,23 +191,23 @@ public class Trade {
} }
if (getMoney() != null && getMoney().signum() > 0 && !user.canAfford(getMoney())) { if (getMoney() != null && getMoney().signum() > 0 && !user.canAfford(getMoney())) {
future.completeExceptionally(new ChargeException(user.playerTl("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess)))); future.completeExceptionally(new ChargeException("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess)));
return; return;
} }
if (getItemStack() != null && !Inventories.containsAtLeast(user.getBase(), itemStack, itemStack.getAmount())) { if (getItemStack() != null && !Inventories.containsAtLeast(user.getBase(), itemStack, itemStack.getAmount())) {
future.completeExceptionally(new ChargeException(user.playerTl("missingItems", getItemStack().getAmount(), ess.getItemDb().name(getItemStack())))); future.completeExceptionally(new ChargeException("missingItems", getItemStack().getAmount(), ess.getItemDb().name(getItemStack())));
return; return;
} }
final BigDecimal money; final BigDecimal money;
if (command != null && !command.isEmpty() && (money = getCommandCost(user)).signum() > 0 && !user.canAfford(money)) { if (command != null && !command.isEmpty() && (money = getCommandCost(user)).signum() > 0 && !user.canAfford(money)) {
future.completeExceptionally(new ChargeException(user.playerTl("notEnoughMoney", NumberUtil.displayCurrency(money, ess)))); future.completeExceptionally(new ChargeException("notEnoughMoney", NumberUtil.displayCurrency(money, ess)));
return; return;
} }
if (exp != null && exp > 0 && SetExpFix.getTotalExperience(user.getBase()) < exp) { if (exp != null && exp > 0 && SetExpFix.getTotalExperience(user.getBase()) < exp) {
future.completeExceptionally(new ChargeException(user.playerTl("notEnoughExperience"))); future.completeExceptionally(new ChargeException("notEnoughExperience"));
} }
} }
@ -285,7 +285,7 @@ public class Trade {
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " money " + getMoney().toPlainString()); ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " money " + getMoney().toPlainString());
} }
if (!user.canAfford(getMoney()) && getMoney().signum() > 0) { if (!user.canAfford(getMoney()) && getMoney().signum() > 0) {
future.completeExceptionally(new ChargeException(user.playerTl("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess)))); future.completeExceptionally(new ChargeException("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess)));
return; return;
} }
user.takeMoney(getMoney()); user.takeMoney(getMoney());
@ -295,7 +295,7 @@ public class Trade {
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " itemstack " + getItemStack().toString()); ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " itemstack " + getItemStack().toString());
} }
if (!Inventories.containsAtLeast(user.getBase(), getItemStack(), getItemStack().getAmount())) { if (!Inventories.containsAtLeast(user.getBase(), getItemStack(), getItemStack().getAmount())) {
future.completeExceptionally(new ChargeException(user.playerTl("missingItems", getItemStack().getAmount(), getItemStack().getType().toString().toLowerCase(Locale.ENGLISH).replace("_", " ")))); future.completeExceptionally(new ChargeException("missingItems", getItemStack().getAmount(), getItemStack().getType().toString().toLowerCase(Locale.ENGLISH).replace("_", " ")));
return; return;
} }
Inventories.removeItemAmount(user.getBase(), getItemStack(), getItemStack().getAmount()); Inventories.removeItemAmount(user.getBase(), getItemStack(), getItemStack().getAmount());
@ -304,7 +304,7 @@ public class Trade {
if (command != null) { if (command != null) {
final BigDecimal cost = getCommandCost(user); final BigDecimal cost = getCommandCost(user);
if (!user.canAfford(cost) && cost.signum() > 0) { if (!user.canAfford(cost) && cost.signum() > 0) {
future.completeExceptionally(new ChargeException(user.playerTl("notEnoughMoney", NumberUtil.displayCurrency(cost, ess)))); future.completeExceptionally(new ChargeException("notEnoughMoney", NumberUtil.displayCurrency(cost, ess)));
return; return;
} }
user.takeMoney(cost); user.takeMoney(cost);
@ -315,7 +315,7 @@ public class Trade {
} }
final int experience = SetExpFix.getTotalExperience(user.getBase()); final int experience = SetExpFix.getTotalExperience(user.getBase());
if (experience < getExperience() && getExperience() > 0) { if (experience < getExperience() && getExperience() > 0) {
future.completeExceptionally(new ChargeException(user.playerTl("notEnoughExperience"))); future.completeExceptionally(new ChargeException("notEnoughExperience"));
return; return;
} }
SetExpFix.setTotalExperience(user.getBase(), experience - getExperience()); SetExpFix.setTotalExperience(user.getBase(), experience - getExperience());

View File

@ -16,6 +16,7 @@ import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.ess3.api.IEssentials; import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException; import net.ess3.api.MaxMoneyException;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.AfkStatusChangeEvent; import net.ess3.api.events.AfkStatusChangeEvent;
import net.ess3.api.events.JailStatusChangeEvent; import net.ess3.api.events.JailStatusChangeEvent;
import net.ess3.api.events.MuteStatusChangeEvent; import net.ess3.api.events.MuteStatusChangeEvent;
@ -226,7 +227,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
cooldownTime.add(Calendar.SECOND, (int) cooldown); cooldownTime.add(Calendar.SECOND, (int) cooldown);
cooldownTime.add(Calendar.MILLISECOND, (int) ((cooldown * 1000.0) % 1000.0)); cooldownTime.add(Calendar.MILLISECOND, (int) ((cooldown * 1000.0) % 1000.0));
if (cooldownTime.after(now) && !isAuthorized("essentials.heal.cooldown.bypass")) { if (cooldownTime.after(now) && !isAuthorized("essentials.heal.cooldown.bypass")) {
throw new Exception(playerTl("timeBeforeHeal", DateUtil.formatDateDiff(cooldownTime.getTimeInMillis()))); throw new TranslatableException("timeBeforeHeal", DateUtil.formatDateDiff(cooldownTime.getTimeInMillis()));
} }
} }
setLastHealTimestamp(now.getTimeInMillis()); setLastHealTimestamp(now.getTimeInMillis());
@ -271,7 +272,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
final TransactionEvent transactionEvent = new TransactionEvent(this.getSource(), reciever, value); final TransactionEvent transactionEvent = new TransactionEvent(this.getSource(), reciever, value);
ess.getServer().getPluginManager().callEvent(transactionEvent); ess.getServer().getPluginManager().callEvent(transactionEvent);
} else { } else {
throw new ChargeException(tlLocale(playerLocale, "notEnoughMoney", NumberUtil.displayCurrency(value, ess))); throw new ChargeException("notEnoughMoney", NumberUtil.displayCurrency(value, ess));
} }
} }

View File

@ -19,13 +19,13 @@ public class Commandbroadcastworld extends EssentialsCommand {
@Override @Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception { public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
if (args.length == 0) { if (args.length < 2) {
throw new NotEnoughArgumentsException(); throw new NotEnoughArgumentsException();
} }
World world = user.getWorld(); World world = user.getWorld();
String message = getFinalArg(args, 0); String message = getFinalArg(args, 0);
if (args.length > 1 && ess.getSettings().isAllowWorldInBroadcastworld()) { if (ess.getSettings().isAllowWorldInBroadcastworld()) {
final World argWorld = ess.getWorld(args[0]); final World argWorld = ess.getWorld(args[0]);
if (argWorld != null) { if (argWorld != null) {
world = argWorld; world = argWorld;
@ -39,7 +39,7 @@ public class Commandbroadcastworld extends EssentialsCommand {
@Override @Override
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception { public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 2) { if (args.length < 2) {
throw new NotEnoughArgumentsException("world"); throw new NotEnoughArgumentsException();
} }
final World world = ess.getWorld(args[0]); final World world = ess.getWorld(args[0]);
@ -53,7 +53,7 @@ public class Commandbroadcastworld extends EssentialsCommand {
if (message.isEmpty()) { if (message.isEmpty()) {
throw new NotEnoughArgumentsException(); throw new NotEnoughArgumentsException();
} }
ess.broadcastTl(null, u -> u.getBase().getWorld().equals(world), true, "broadcast", message, AdventureUtil.parsed(AdventureUtil.legacyToMini(name))); ess.broadcastTl(null, u -> !u.getBase().getWorld().equals(world), true, "broadcast", message, AdventureUtil.parsed(AdventureUtil.legacyToMini(name)));
} }
@Override @Override

View File

@ -14,7 +14,6 @@ import org.bukkit.inventory.ItemStack;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
@ -35,7 +34,7 @@ public class Commandenchant extends EssentialsCommand {
if (args.length == 0) { if (args.length == 0) {
final Set<String> usableEnchants = new TreeSet<>(); final Set<String> usableEnchants = new TreeSet<>();
for (final Map.Entry<String, Enchantment> entry : Enchantments.entrySet()) { for (final Map.Entry<String, Enchantment> entry : Enchantments.entrySet()) {
final String name = entry.getValue().getName().toLowerCase(Locale.ENGLISH); final String name = Enchantments.getRealName(entry.getValue());
if (usableEnchants.contains(name) || (user.isAuthorized("essentials.enchantments." + name) && entry.getValue().canEnchantItem(stack))) { if (usableEnchants.contains(name) || (user.isAuthorized("essentials.enchantments." + name) && entry.getValue().canEnchantItem(stack))) {
usableEnchants.add(entry.getKey()); usableEnchants.add(entry.getKey());
} }
@ -57,7 +56,7 @@ public class Commandenchant extends EssentialsCommand {
metaStack.addEnchantment(user.getSource(), ess.getSettings().allowUnsafeEnchantments() && user.isAuthorized("essentials.enchantments.allowunsafe"), enchantment, level); metaStack.addEnchantment(user.getSource(), ess.getSettings().allowUnsafeEnchantments() && user.isAuthorized("essentials.enchantments.allowunsafe"), enchantment, level);
stack.setItemMeta(metaStack.getItemStack().getItemMeta()); stack.setItemMeta(metaStack.getItemStack().getItemMeta());
user.getBase().updateInventory(); user.getBase().updateInventory();
final String enchantName = enchantment.getName().toLowerCase(Locale.ENGLISH).replace('_', ' '); final String enchantName = Enchantments.getRealName(enchantment).replace('_', ' ');
if (level == 0) { if (level == 0) {
user.sendTl("enchantmentRemoved", enchantName); user.sendTl("enchantmentRemoved", enchantName);
} else { } else {

View File

@ -1,6 +1,7 @@
package com.earth2me.essentials.commands; package com.earth2me.essentials.commands;
import com.earth2me.essentials.MetaItemStack; import com.earth2me.essentials.MetaItemStack;
import com.earth2me.essentials.MobCompat;
import com.earth2me.essentials.User; import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.MaterialUtil; import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil; import com.earth2me.essentials.utils.NumberUtil;
@ -9,7 +10,6 @@ import net.ess3.api.TranslatableException;
import org.bukkit.DyeColor; import org.bukkit.DyeColor;
import org.bukkit.FireworkEffect; import org.bukkit.FireworkEffect;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Firework; import org.bukkit.entity.Firework;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.FireworkMeta;
@ -81,7 +81,7 @@ public class Commandfirework extends EssentialsCommand {
} }
} }
for (int i = 0; i < amount; i++) { for (int i = 0; i < amount; i++) {
final Firework firework = (Firework) user.getWorld().spawnEntity(user.getLocation(), EntityType.FIREWORK); final Firework firework = (Firework) user.getWorld().spawnEntity(user.getLocation(), MobCompat.FIREWORK_ROCKET);
final FireworkMeta fmeta = (FireworkMeta) stack.getItemMeta(); final FireworkMeta fmeta = (FireworkMeta) stack.getItemMeta();
if (direction) { if (direction) {
final Vector vector = user.getBase().getEyeLocation().getDirection().multiply(0.070); final Vector vector = user.getBase().getEyeLocation().getDirection().multiply(0.070);

View File

@ -55,7 +55,7 @@ public class Commandgamemode extends EssentialsLoopCommand {
} }
if (isProhibitedChange(user, gameMode)) { if (isProhibitedChange(user, gameMode)) {
user.sendTl("cantGamemode", gameMode.name()); user.sendTl("cantGamemode", user.playerTl(gameMode.toString().toLowerCase(Locale.ENGLISH)));
return; return;
} }

View File

@ -51,6 +51,11 @@ public class Commandhelpop extends EssentialsCommand {
final HelpopMessageSendEvent sendEvent = new HelpopMessageSendEvent(from, recipients, message); final HelpopMessageSendEvent sendEvent = new HelpopMessageSendEvent(from, recipients, message);
ess.getServer().getPluginManager().callEvent(sendEvent); ess.getServer().getPluginManager().callEvent(sendEvent);
final IUser sender = (IUser) from;
if(!recipients.contains(sender)){
from.sendTl("helpOp", from.getDisplayName(), message);
}
for (IUser recipient : sendEvent.getRecipients()) { for (IUser recipient : sendEvent.getRecipients()) {
recipient.sendTl("helpOp", from.getDisplayName(), message); recipient.sendTl("helpOp", from.getDisplayName(), message);
} }

View File

@ -17,8 +17,6 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static com.earth2me.essentials.I18n.tlLiteral;
public class Commandme extends EssentialsCommand { public class Commandme extends EssentialsCommand {
public Commandme() { public Commandme() {
super("me"); super("me");
@ -109,7 +107,7 @@ public class Commandme extends EssentialsCommand {
String message = getFinalArg(args, 0); String message = getFinalArg(args, 0);
message = FormatUtil.replaceFormat(message); message = FormatUtil.replaceFormat(message);
ess.getServer().broadcastMessage(tlLiteral("action", "@", message)); ess.broadcastTl("action", "@", message);
} }
@Override @Override

View File

@ -109,8 +109,10 @@ public class Commandpay extends EssentialsLoopCommand {
user.setMoney(user.getMoney().add(amount)); user.setMoney(user.getMoney().add(amount));
} catch (final MaxMoneyException ignored) { } catch (final MaxMoneyException ignored) {
} }
} catch (final TranslatableException e) {
throw e;
} catch (final Exception e) { } catch (final Exception e) {
user.sendMessage(e.getMessage()); throw new TranslatableException("errorWithMessage", e.getMessage());
} }
}); });
if (informToConfirm.get()) { if (informToConfirm.get()) {

View File

@ -131,7 +131,7 @@ public class Commandrecipe extends EssentialsCommand {
if (VersionUtil.PRE_FLATTENING && item.getDurability() == Short.MAX_VALUE) { if (VersionUtil.PRE_FLATTENING && item.getDurability() == Short.MAX_VALUE) {
item.setDurability((short) 0); item.setDurability((short) 0);
} }
view.getTopInventory().setItem(j * 3 + k + 1, item); ess.getInventoryViewProvider().getTopInventory(view).setItem(j * 3 + k + 1, item);
} }
} }
} else { } else {
@ -174,7 +174,7 @@ public class Commandrecipe extends EssentialsCommand {
if (VersionUtil.PRE_FLATTENING && item.getDurability() == Short.MAX_VALUE) { if (VersionUtil.PRE_FLATTENING && item.getDurability() == Short.MAX_VALUE) {
item.setDurability((short) 0); item.setDurability((short) 0);
} }
view.setItem(i + 1, item); ess.getInventoryViewProvider().setItem(view, i + 1, item);
} }
} else { } else {

View File

@ -6,6 +6,7 @@ import com.earth2me.essentials.IUser;
import com.earth2me.essentials.User; import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.AdventureUtil; import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.DateUtil; import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.FormatUtil;
import org.bukkit.BanList; import org.bukkit.BanList;
import org.bukkit.Server; import org.bukkit.Server;
@ -36,7 +37,7 @@ public class Commandtempban extends EssentialsCommand {
} }
final String time = getFinalArg(args, 1); final String time = getFinalArg(args, 1);
final long banTimestamp = DateUtil.parseDateDiff(time, true); final long banTimestamp = DateUtil.parseDateDiff(time, true);
String banReason = DateUtil.removeTimePattern(time); String banReason = FormatUtil.replaceFormat(DateUtil.removeTimePattern(time));
final long maxBanLength = ess.getSettings().getMaxTempban() * 1000; final long maxBanLength = ess.getSettings().getMaxTempban() * 1000;
if (maxBanLength > 0 && ((banTimestamp - GregorianCalendar.getInstance().getTimeInMillis()) > maxBanLength) && sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.tempban.unlimited")) { if (maxBanLength > 0 && ((banTimestamp - GregorianCalendar.getInstance().getTimeInMillis()) > maxBanLength) && sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.tempban.unlimited")) {

View File

@ -49,7 +49,7 @@ public class Commandtempbanip extends EssentialsCommand {
final String time = getFinalArg(args, 1); final String time = getFinalArg(args, 1);
final long banTimestamp = DateUtil.parseDateDiff(time, true); final long banTimestamp = DateUtil.parseDateDiff(time, true);
String banReason = DateUtil.removeTimePattern(time); String banReason = FormatUtil.replaceFormat(DateUtil.removeTimePattern(time));
final long maxBanLength = ess.getSettings().getMaxTempban() * 1000; final long maxBanLength = ess.getSettings().getMaxTempban() * 1000;
if (maxBanLength > 0 && ((banTimestamp - GregorianCalendar.getInstance().getTimeInMillis()) > maxBanLength) && sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.tempban.unlimited")) { if (maxBanLength > 0 && ((banTimestamp - GregorianCalendar.getInstance().getTimeInMillis()) > maxBanLength) && sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.tempban.unlimited")) {

View File

@ -83,7 +83,7 @@ public class Commandtogglejail extends EssentialsCommand {
if (args.length > 2) { if (args.length > 2) {
player.setJailTimeout(timeDiff); player.setJailTimeout(timeDiff);
// 50 MSPT (milliseconds per tick) // 50 MSPT (milliseconds per tick)
player.setOnlineJailedTime(ess.getSettings().isJailOnlineTime() ? ((player.getBase().getStatistic(PLAY_ONE_TICK)) + (timeDiff / 50)) : 0); player.setOnlineJailedTime(ess.getSettings().isJailOnlineTime() ? ((player.getOffline().getStatistic(PLAY_ONE_TICK)) + (timeDiff / 50)) : 0);
} }
final String tlKey; final String tlKey;
@ -121,7 +121,7 @@ public class Commandtogglejail extends EssentialsCommand {
final long displayTimeDiff = DateUtil.parseDateDiff(unparsedTime, true); final long displayTimeDiff = DateUtil.parseDateDiff(unparsedTime, true);
final long timeDiff = DateUtil.parseDateDiff(unparsedTime, true, ess.getSettings().isJailOnlineTime()); final long timeDiff = DateUtil.parseDateDiff(unparsedTime, true, ess.getSettings().isJailOnlineTime());
player.setJailTimeout(timeDiff); player.setJailTimeout(timeDiff);
player.setOnlineJailedTime(ess.getSettings().isJailOnlineTime() ? ((player.getBase().getStatistic(PLAY_ONE_TICK)) + (timeDiff / 50)) : 0); player.setOnlineJailedTime(ess.getSettings().isJailOnlineTime() ? ((player.getOffline().getStatistic(PLAY_ONE_TICK)) + (timeDiff / 50)) : 0);
sender.sendTl("jailSentenceExtended", DateUtil.formatDateDiff(displayTimeDiff)); sender.sendTl("jailSentenceExtended", DateUtil.formatDateDiff(displayTimeDiff));
final String tlKey = "jailNotifySentenceExtended"; final String tlKey = "jailNotifySentenceExtended";

View File

@ -10,7 +10,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import net.ess3.api.IEssentials; import net.ess3.api.IEssentials;
import net.ess3.provider.KnownCommandsProvider; import net.ess3.api.TranslatableException;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -181,7 +181,7 @@ public abstract class EssentialsCommand implements IEssentialsCommand {
} }
protected void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception { protected void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
throw new Exception(tlLiteral("onlyPlayers", commandLabel)); throw new TranslatableException("onlyPlayers", commandLabel);
} }
@Override @Override

View File

@ -6,6 +6,7 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil; import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.StringUtil; import com.earth2me.essentials.utils.StringUtil;
import net.ess3.api.MaxMoneyException; import net.ess3.api.MaxMoneyException;
import net.ess3.api.TranslatableException;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -18,11 +19,11 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
super(command); super(command);
} }
protected void loopOfflinePlayers(final Server server, final CommandSource sender, final boolean multipleStringMatches, final boolean matchWildcards, final String searchTerm, final String[] commandArgs) throws PlayerNotFoundException, NotEnoughArgumentsException, PlayerExemptException, ChargeException, MaxMoneyException { protected void loopOfflinePlayers(final Server server, final CommandSource sender, final boolean multipleStringMatches, final boolean matchWildcards, final String searchTerm, final String[] commandArgs) throws TranslatableException, NotEnoughArgumentsException {
loopOfflinePlayersConsumer(server, sender, multipleStringMatches, matchWildcards, searchTerm, user -> updatePlayer(server, sender, user, commandArgs)); loopOfflinePlayersConsumer(server, sender, multipleStringMatches, matchWildcards, searchTerm, user -> updatePlayer(server, sender, user, commandArgs));
} }
protected void loopOfflinePlayersConsumer(final Server server, final CommandSource sender, final boolean multipleStringMatches, final boolean matchWildcards, final String searchTerm, final UserConsumer userConsumer) throws PlayerNotFoundException, NotEnoughArgumentsException, PlayerExemptException, ChargeException, MaxMoneyException { protected void loopOfflinePlayersConsumer(final Server server, final CommandSource sender, final boolean multipleStringMatches, final boolean matchWildcards, final String searchTerm, final UserConsumer userConsumer) throws TranslatableException, NotEnoughArgumentsException {
if (searchTerm.isEmpty()) { if (searchTerm.isEmpty()) {
throw new PlayerNotFoundException(); throw new PlayerNotFoundException();
} }
@ -68,11 +69,11 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
} }
} }
protected void loopOnlinePlayers(final Server server, final CommandSource sender, final boolean multipleStringMatches, final boolean matchWildcards, final String searchTerm, final String[] commandArgs) throws PlayerNotFoundException, NotEnoughArgumentsException, PlayerExemptException, ChargeException, MaxMoneyException { protected void loopOnlinePlayers(final Server server, final CommandSource sender, final boolean multipleStringMatches, final boolean matchWildcards, final String searchTerm, final String[] commandArgs) throws TranslatableException, NotEnoughArgumentsException {
loopOnlinePlayersConsumer(server, sender, multipleStringMatches, matchWildcards, searchTerm, user -> updatePlayer(server, sender, user, commandArgs)); loopOnlinePlayersConsumer(server, sender, multipleStringMatches, matchWildcards, searchTerm, user -> updatePlayer(server, sender, user, commandArgs));
} }
protected void loopOnlinePlayersConsumer(final Server server, final CommandSource sender, final boolean multipleStringMatches, final boolean matchWildcards, final String searchTerm, final UserConsumer userConsumer) throws PlayerNotFoundException, NotEnoughArgumentsException, PlayerExemptException, ChargeException, MaxMoneyException { protected void loopOnlinePlayersConsumer(final Server server, final CommandSource sender, final boolean multipleStringMatches, final boolean matchWildcards, final String searchTerm, final UserConsumer userConsumer) throws NotEnoughArgumentsException, TranslatableException {
if (searchTerm.isEmpty()) { if (searchTerm.isEmpty()) {
throw new PlayerNotFoundException(); throw new PlayerNotFoundException();
} }
@ -143,6 +144,6 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
} }
public interface UserConsumer { public interface UserConsumer {
void accept(User user) throws PlayerNotFoundException, NotEnoughArgumentsException, PlayerExemptException, ChargeException, MaxMoneyException; void accept(User user) throws NotEnoughArgumentsException, TranslatableException;
} }
} }

View File

@ -1,5 +1,6 @@
package com.earth2me.essentials.items; package com.earth2me.essentials.items;
import com.earth2me.essentials.Enchantments;
import com.earth2me.essentials.IConf; import com.earth2me.essentials.IConf;
import com.earth2me.essentials.User; import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.Inventories; import com.earth2me.essentials.craftbukkit.Inventories;
@ -24,10 +25,8 @@ import org.bukkit.inventory.meta.FireworkEffectMeta;
import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.FireworkMeta;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import java.util.ArrayList; import java.util.ArrayList;
@ -220,7 +219,7 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
if (meta.hasEnchants()) { if (meta.hasEnchants()) {
for (final Enchantment e : meta.getEnchants().keySet()) { for (final Enchantment e : meta.getEnchants().keySet()) {
sb.append(e.getName().toLowerCase()).append(":").append(meta.getEnchantLevel(e)).append(" "); sb.append(Enchantments.getRealName(e)).append(":").append(meta.getEnchantLevel(e)).append(" ");
} }
} }
@ -265,7 +264,7 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
case ENCHANTED_BOOK: case ENCHANTED_BOOK:
final EnchantmentStorageMeta enchantmentStorageMeta = (EnchantmentStorageMeta) is.getItemMeta(); final EnchantmentStorageMeta enchantmentStorageMeta = (EnchantmentStorageMeta) is.getItemMeta();
for (final Enchantment e : enchantmentStorageMeta.getStoredEnchants().keySet()) { for (final Enchantment e : enchantmentStorageMeta.getStoredEnchants().keySet()) {
sb.append(e.getName().toLowerCase()).append(":").append(enchantmentStorageMeta.getStoredEnchantLevel(e)).append(" "); sb.append(Enchantments.getRealName(e)).append(":").append(enchantmentStorageMeta.getStoredEnchantLevel(e)).append(" ");
} }
break; break;
} }
@ -285,16 +284,8 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
serializeEffectMeta(sb, fireworkEffectMeta.getEffect()); serializeEffectMeta(sb, fireworkEffectMeta.getEffect());
} }
} else if (MaterialUtil.isPotion(material)) { } else if (MaterialUtil.isPotion(material)) {
final boolean splash; final boolean splash = ess.getPotionMetaProvider().isSplashPotion(is);
final Collection<PotionEffect> effects; final Collection<PotionEffect> effects = ess.getPotionMetaProvider().getCustomEffects(is);
if (VersionUtil.PRE_FLATTENING) {
final Potion potion = Potion.fromDamage(is.getDurability());
splash = potion.isSplash();
effects = potion.getEffects();
} else {
splash = is.getType() == Material.SPLASH_POTION;
effects = ((PotionMeta) is.getItemMeta()).getCustomEffects();
}
for (final PotionEffect e : effects) { for (final PotionEffect e : effects) {
// long but needs to be effect:speed power:2 duration:120 in that order. // long but needs to be effect:speed power:2 duration:120 in that order.
@ -317,6 +308,7 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
sb.append("basecolor:").append(basecolor).append(" "); sb.append("basecolor:").append(basecolor).append(" ");
} }
for (final org.bukkit.block.banner.Pattern p : shieldBannerMeta.getPatterns()) { for (final org.bukkit.block.banner.Pattern p : shieldBannerMeta.getPatterns()) {
//noinspection removal
final String type = p.getPattern().getIdentifier(); final String type = p.getPattern().getIdentifier();
final int color = p.getColor().getColor().asRGB(); final int color = p.getColor().getColor().asRGB();
sb.append(type).append(",").append(color).append(" "); sb.append(type).append(",").append(color).append(" ");
@ -324,7 +316,7 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
} else { } else {
final BannerMeta bannerMeta = (BannerMeta) is.getItemMeta(); final BannerMeta bannerMeta = (BannerMeta) is.getItemMeta();
if (bannerMeta != null) { if (bannerMeta != null) {
DyeColor baseDyeColor = bannerMeta.getBaseColor(); DyeColor baseDyeColor = ess.getBannerDataProvider().getBaseColor(is);
if (baseDyeColor == null) { if (baseDyeColor == null) {
baseDyeColor = MaterialUtil.getColorOf(material); baseDyeColor = MaterialUtil.getColorOf(material);
} }
@ -335,6 +327,7 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
sb.append("basecolor:").append(basecolor).append(" "); sb.append("basecolor:").append(basecolor).append(" ");
} }
for (final org.bukkit.block.banner.Pattern p : bannerMeta.getPatterns()) { for (final org.bukkit.block.banner.Pattern p : bannerMeta.getPatterns()) {
//noinspection removal
final String type = p.getPattern().getIdentifier(); final String type = p.getPattern().getIdentifier();
final int color = p.getColor().getColor().asRGB(); final int color = p.getColor().getColor().asRGB();
sb.append(type).append(",").append(color).append(" "); sb.append(type).append(",").append(color).append(" ");

View File

@ -9,15 +9,13 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import net.ess3.api.IEssentials; import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException; import net.ess3.api.TranslatableException;
import net.ess3.provider.PersistentDataProvider;
import net.ess3.provider.SpawnerItemProvider;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionData; import org.bukkit.potion.PotionType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -25,6 +23,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -129,14 +128,14 @@ public class FlatItemDb extends AbstractItemDb {
final ItemStack stack = new ItemStack(material); final ItemStack stack = new ItemStack(material);
stack.setAmount(material.getMaxStackSize()); stack.setAmount(material.getMaxStackSize());
final PotionData potionData = data.getPotionData(); final ItemData.EssentialPotionData potionData = data.getPotionData();
final ItemMeta meta = stack.getItemMeta();
if (potionData != null && meta instanceof PotionMeta) { if (potionData != null && stack.getItemMeta() instanceof PotionMeta) {
final PotionMeta potionMeta = (PotionMeta) meta; ess.getPotionMetaProvider().setBasePotionType(stack, potionData.getType(), potionData.isExtended(), potionData.isUpgraded());
potionMeta.setBasePotionData(potionData);
} }
final ItemMeta meta = stack.getItemMeta();
// For some reason, Damageable doesn't extend ItemMeta but CB implements them in the same // For some reason, Damageable doesn't extend ItemMeta but CB implements them in the same
// class. As to why, your guess is as good as mine. // class. As to why, your guess is as good as mine.
if (split.length > 1 && meta instanceof Damageable) { if (split.length > 1 && meta instanceof Damageable) {
@ -202,14 +201,14 @@ public class FlatItemDb extends AbstractItemDb {
throw new UnsupportedOperationException("Legacy IDs aren't supported on this version."); throw new UnsupportedOperationException("Legacy IDs aren't supported on this version.");
} }
private ItemData lookup(final ItemStack item) { private ItemData lookup(final ItemStack is) {
final Material type = item.getType(); final Material type = is.getType();
if (MaterialUtil.isPotion(type) && item.getItemMeta() instanceof PotionMeta) { if (MaterialUtil.isPotion(type) && is.getItemMeta() instanceof PotionMeta) {
final PotionData potion = ((PotionMeta) item.getItemMeta()).getBasePotionData(); final PotionMetaProvider provider = ess.getPotionMetaProvider();
return new ItemData(type, potion); return new ItemData(type, new ItemData.EssentialPotionData(provider.getBasePotionType(is), provider.isUpgraded(is), provider.isExtended(is)));
} else if (type.toString().contains("SPAWNER")) { } else if (type.toString().contains("SPAWNER")) {
final EntityType entity = ess.provider(SpawnerItemProvider.class).getEntityType(item); final EntityType entity = ess.provider(SpawnerItemProvider.class).getEntityType(is);
return new ItemData(type, entity); return new ItemData(type, entity);
} else { } else {
return new ItemData(type); return new ItemData(type);
@ -226,14 +225,14 @@ public class FlatItemDb extends AbstractItemDb {
public static class ItemData { public static class ItemData {
private Material material; private Material material;
private String[] fallbacks = null; private String[] fallbacks = null;
private PotionData potionData = null; private EssentialPotionData potionData = null;
private EntityType entity = null; private EntityType entity = null;
ItemData(final Material material) { ItemData(final Material material) {
this.material = material; this.material = material;
} }
ItemData(final Material material, final PotionData potionData) { ItemData(final Material material, final EssentialPotionData potionData) {
this.material = material; this.material = material;
this.potionData = potionData; this.potionData = potionData;
} }
@ -269,7 +268,7 @@ public class FlatItemDb extends AbstractItemDb {
return material; return material;
} }
public PotionData getPotionData() { public EssentialPotionData getPotionData() {
return this.potionData; return this.potionData;
} }
@ -296,5 +295,51 @@ public class FlatItemDb extends AbstractItemDb {
return false; return false;
} }
} }
public static class EssentialPotionData {
private PotionType type;
private String fallbackType;
private final boolean upgraded;
private final boolean extended;
EssentialPotionData(PotionType type, boolean upgraded, boolean extended) {
this.type = type;
this.upgraded = upgraded;
this.extended = extended;
}
public PotionType getType() {
if (type == null && fallbackType != null) {
type = EnumUtil.valueOf(PotionType.class, fallbackType);
fallbackType = null; // If fallback fails, don't keep trying to look up fallbacks
}
return type;
}
public boolean isUpgraded() {
return upgraded;
}
public boolean isExtended() {
return extended;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final EssentialPotionData that = (EssentialPotionData) o;
return upgraded == that.upgraded &&
extended == that.extended &&
// Use the getters here to ensure the fallbacks are being used
getType() == that.getType();
}
@Override
public int hashCode() {
return Objects.hash(getType(), upgraded, extended);
}
}
} }
} }

View File

@ -121,15 +121,17 @@ public class SimpleMessageRecipient implements IMessageRecipient {
// Dont spy on chats involving socialspy exempt players // Dont spy on chats involving socialspy exempt players
&& !senderUser.isAuthorized("essentials.chat.spy.exempt") && !senderUser.isAuthorized("essentials.chat.spy.exempt")
&& recipientUser != null && !recipientUser.isAuthorized("essentials.chat.spy.exempt")) { && recipientUser != null && !recipientUser.isAuthorized("essentials.chat.spy.exempt")) {
final String senderName = ess.getSettings().isSocialSpyDisplayNames() ? getDisplayName() : getName();
final String recipientName = ess.getSettings().isSocialSpyDisplayNames() ? recipient.getDisplayName() : recipient.getName();
for (final User onlineUser : ess.getOnlineUsers()) { for (final User onlineUser : ess.getOnlineUsers()) {
if (onlineUser.isSocialSpyEnabled() if (onlineUser.isSocialSpyEnabled()
// Don't send socialspy messages to message sender/receiver to prevent spam // Don't send socialspy messages to message sender/receiver to prevent spam
&& !onlineUser.equals(senderUser) && !onlineUser.equals(senderUser)
&& !onlineUser.equals(recipient)) { && !onlineUser.equals(recipient)) {
if (senderUser.isMuted() && ess.getSettings().getSocialSpyListenMutedPlayers()) { if (senderUser.isMuted() && ess.getSettings().getSocialSpyListenMutedPlayers()) {
onlineUser.sendComponent(AdventureUtil.miniMessage().deserialize(tlSender("socialSpyMutedPrefix") + tlLiteral("socialSpyMsgFormat", getDisplayName(), recipient.getDisplayName(), message))); onlineUser.sendComponent(AdventureUtil.miniMessage().deserialize(tlSender("socialSpyMutedPrefix") + tlLiteral("socialSpyMsgFormat", senderName, recipientName, message)));
} else { } else {
onlineUser.sendComponent(AdventureUtil.miniMessage().deserialize(tlLiteral("socialSpyPrefix") + tlLiteral("socialSpyMsgFormat", getDisplayName(), recipient.getDisplayName(), message))); onlineUser.sendComponent(AdventureUtil.miniMessage().deserialize(tlLiteral("socialSpyPrefix") + tlLiteral("socialSpyMsgFormat", senderName, recipientName, message)));
} }
} }
} }

View File

@ -553,9 +553,11 @@ public class EssentialsSign {
static class BlockSign implements ISign { static class BlockSign implements ISign {
private final transient Block block; private final transient Block block;
private transient Sign sign;
BlockSign(final Block block) { BlockSign(final Block block) {
this.block = block; this.block = block;
this.sign = getSign();
} }
@Override @Override
@ -572,7 +574,7 @@ public class EssentialsSign {
@Override @Override
public final void setLine(final int index, final String text) { public final void setLine(final int index, final String text) {
getSign().setLine(index, text); sign.setLine(index, text);
updateSign(); updateSign();
} }
@ -589,7 +591,8 @@ public class EssentialsSign {
@Override @Override
public final void updateSign() { public final void updateSign() {
getSign().update(); sign.update();
sign = getSign();
} }
} }
} }

View File

@ -46,7 +46,7 @@ public class SignBuy extends EssentialsSign {
charge.isAffordableFor(player); charge.isAffordableFor(player);
if (!items.pay(player)) { if (!items.pay(player)) {
throw new ChargeException("Inventory full"); //TODO: TL throw new ChargeException("inventoryFull");
} }
charge.charge(player); charge.charge(player);
Trade.log("Sign", "Buy", "Interact", username, charge, username, items, sign.getBlock().getLocation(), player.getMoney(), ess); Trade.log("Sign", "Buy", "Interact", username, charge, username, items, sign.getBlock().getLocation(), player.getMoney(), ess);

View File

@ -106,7 +106,7 @@ public class SignEnchant extends EssentialsSign {
throw new SignException(ex, "errorWithMessage", ex.getMessage()); throw new SignException(ex, "errorWithMessage", ex.getMessage());
} }
final String enchantmentName = enchantment.getName().toLowerCase(Locale.ENGLISH); final String enchantmentName = Enchantments.getRealName(enchantment);
if (level == 0) { if (level == 0) {
player.sendTl("enchantmentRemoved", enchantmentName.replace('_', ' ')); player.sendTl("enchantmentRemoved", enchantmentName.replace('_', ' '));
} else { } else {

View File

@ -21,9 +21,10 @@ public class SignHeal extends EssentialsSign {
if (player.getBase().getHealth() == 0) { if (player.getBase().getHealth() == 0) {
throw new SignException("healDead"); throw new SignException("healDead");
} }
final double amount = player.getBase().getMaxHealth();
final Trade charge = getTrade(sign, 1, ess); final Trade charge = getTrade(sign, 1, ess);
charge.isAffordableFor(player); charge.isAffordableFor(player);
player.getBase().setHealth(20); player.getBase().setHealth(amount);
player.getBase().setFoodLevel(20); player.getBase().setFoodLevel(20);
player.getBase().setFireTicks(0); player.getBase().setFireTicks(0);
player.sendTl("youAreHealed"); player.sendTl("youAreHealed");

View File

@ -72,7 +72,7 @@ public class SignTrade extends EssentialsSign {
if (!trade.pay(player)) { if (!trade.pay(player)) {
subtractAmount(sign, 1, charge, ess); subtractAmount(sign, 1, charge, ess);
addAmount(sign, 2, trade, ess); addAmount(sign, 2, trade, ess);
throw new ChargeException("Full inventory"); throw new ChargeException("inventoryFull");
} }
charge.charge(player); charge.charge(player);
Trade.log("Sign", "Trade", "Interact", sign.getLine(3).substring(2), charge, username, trade, sign.getBlock().getLocation(), player.getMoney(), ess); Trade.log("Sign", "Trade", "Interact", sign.getLine(3).substring(2), charge, username, trade, sign.getBlock().getLocation(), player.getMoney(), ess);

View File

@ -4,40 +4,55 @@ import net.ess3.api.IEssentials;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.flattener.ComponentFlattener; import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.Tag; import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.kyori.adventure.text.serializer.legacy.CharacterAndFormat;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.ChatColor; import net.kyori.adventure.text.serializer.legacy.Reset;
import java.util.regex.Matcher; import java.util.ArrayList;
import java.util.regex.Pattern; import java.util.Arrays;
import java.util.List;
public final class AdventureUtil { public final class AdventureUtil {
private static final LegacyComponentSerializer LEGACY_SERIALIZER; private static final LegacyComponentSerializer LEGACY_SERIALIZER;
private static final MiniMessage MINI_MESSAGE_INSTANCE; private static final MiniMessage MINI_MESSAGE_NO_TAGS;
private static IEssentials ess;
private static final Pattern NAMED_PATTERN = Pattern.compile(ChatColor.COLOR_CHAR + "[0-9a-fk-orA-FK-OR]");
private static final Pattern HEX_PATTERN = Pattern.compile(ChatColor.COLOR_CHAR + "x((?:" + ChatColor.COLOR_CHAR + "[0-9a-fA-F]){6})");
private static final String LOOKUP = "0123456789abcdefklmnor"; private static final String LOOKUP = "0123456789abcdefklmnor";
private static final String[] MINI_TAGS = new String[] {"black", "dark_blue", "dark_green", "dark_aqua", "dark_red", "dark_purple", "gold", "gray", "dark_gray", "blue", "green", "aqua", "red", "light_purple", "yellow", "white", "obf", "b", "st", "u", "i", "reset"}; 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 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 IEssentials ess;
private static MiniMessage miniMessageInstance;
static { static {
final LegacyComponentSerializer.Builder builder = LegacyComponentSerializer.builder().flattener(ComponentFlattener.basic()).useUnusualXRepeatedCharacterHexFormat(); final List<CharacterAndFormat> formats = new ArrayList<>();
formats.addAll(CharacterAndFormat.defaults());
formats.addAll(Arrays.asList(
CharacterAndFormat.characterAndFormat('A', NamedTextColor.GREEN),
CharacterAndFormat.characterAndFormat('B', NamedTextColor.AQUA),
CharacterAndFormat.characterAndFormat('C', NamedTextColor.RED),
CharacterAndFormat.characterAndFormat('D', NamedTextColor.LIGHT_PURPLE),
CharacterAndFormat.characterAndFormat('E', NamedTextColor.YELLOW),
CharacterAndFormat.characterAndFormat('F', NamedTextColor.WHITE),
CharacterAndFormat.characterAndFormat('K', TextDecoration.OBFUSCATED),
CharacterAndFormat.characterAndFormat('L', TextDecoration.BOLD),
CharacterAndFormat.characterAndFormat('M', TextDecoration.STRIKETHROUGH),
CharacterAndFormat.characterAndFormat('N', TextDecoration.UNDERLINED),
CharacterAndFormat.characterAndFormat('O', TextDecoration.ITALIC),
CharacterAndFormat.characterAndFormat('R', Reset.INSTANCE)
));
final LegacyComponentSerializer.Builder builder = LegacyComponentSerializer.builder()
.flattener(ComponentFlattener.basic())
.formats(formats)
.useUnusualXRepeatedCharacterHexFormat();
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_16_1_R01)) { if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_16_1_R01)) {
builder.hexColors(); builder.hexColors();
} }
LEGACY_SERIALIZER = builder.build(); LEGACY_SERIALIZER = builder.build();
MINI_MESSAGE_INSTANCE = MiniMessage.builder() MINI_MESSAGE_NO_TAGS = MiniMessage.builder().strict(true).build();
.tags(TagResolver.builder()
.resolvers(TagResolver.standard())
.resolver(TagResolver.resolver("primary", supplyTag(true)))
.resolver(TagResolver.resolver("secondary", supplyTag(false)))
.build())
.build();
miniMessageInstance = createMiniMessageInstance();
} }
private AdventureUtil() { private AdventureUtil() {
@ -45,10 +60,21 @@ public final class AdventureUtil {
public static void setEss(final IEssentials ess) { public static void setEss(final IEssentials ess) {
AdventureUtil.ess = ess; AdventureUtil.ess = ess;
miniMessageInstance = createMiniMessageInstance();
}
private static MiniMessage createMiniMessageInstance() {
return MiniMessage.builder()
.tags(TagResolver.builder()
.resolvers(TagResolver.standard())
.resolver(TagResolver.resolver("primary", supplyTag(true)))
.resolver(TagResolver.resolver("secondary", supplyTag(false)))
.build())
.build();
} }
public static MiniMessage miniMessage() { public static MiniMessage miniMessage() {
return MINI_MESSAGE_INSTANCE; return miniMessageInstance;
} }
/** /**
@ -81,37 +107,16 @@ public final class AdventureUtil {
/** /**
* Converts a section sign legacy string to a MiniMessage string. * Converts a section sign legacy string to a MiniMessage string.
*
* @param useCustomTags true if gold and red colors should use primary and secondary tags instead. * @param useCustomTags true if gold and red colors should use primary and secondary tags instead.
*/ */
public static String legacyToMini(String text, boolean useCustomTags) { public static String legacyToMini(String text, boolean useCustomTags) {
StringBuffer buffer = new StringBuffer(); final Component deserializedText = LEGACY_SERIALIZER.deserialize(text);
Matcher matcher = HEX_PATTERN.matcher(text); if (useCustomTags) {
while (matcher.find()) { return miniMessageInstance.serialize(deserializedText);
final String code = matcher.group(1).replace(String.valueOf(ChatColor.COLOR_CHAR), ""); } else {
matcher.appendReplacement(buffer, "<#" + code + ">"); return MINI_MESSAGE_NO_TAGS.serialize(deserializedText);
} }
matcher.appendTail(buffer);
matcher = NAMED_PATTERN.matcher(buffer.toString());
buffer = new StringBuffer();
while (matcher.find()) {
final int format = LOOKUP.indexOf(Character.toLowerCase(matcher.group().charAt(1)));
if (format != -1) {
String tagName = MINI_TAGS[format];
if (useCustomTags) {
if (tagName.equals("gold")) {
tagName = "primary";
} else if (tagName.equals("red")) {
tagName = "secondary";
}
}
matcher.appendReplacement(buffer, "<" + tagName + ">");
}
}
matcher.appendTail(buffer);
return buffer.toString();
} }
/** /**

View File

@ -40,6 +40,13 @@ public final class FormatUtil {
return ChatColor.stripColor(input); return ChatColor.stripColor(input);
} }
public static String stripMiniFormat(final String input) {
if (input == null) {
return null;
}
return AdventureUtil.miniMessage().stripTags(input);
}
//This method is used to simply strip the & convention colour codes //This method is used to simply strip the & convention colour codes
public static String stripEssentialsFormat(final String input) { public static String stripEssentialsFormat(final String input) {
if (input == null) { if (input == null) {

View File

@ -1,5 +1,6 @@
package com.earth2me.essentials.utils; package com.earth2me.essentials.utils;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.IEssentials; import com.earth2me.essentials.IEssentials;
import net.ess3.api.IUser; import net.ess3.api.IUser;
import net.ess3.api.TranslatableException; import net.ess3.api.TranslatableException;
@ -41,10 +42,14 @@ public final class LocationUtil {
private static final Set<Material> TRANSPARENT_MATERIALS = EnumSet.noneOf(Material.class); private static final Set<Material> TRANSPARENT_MATERIALS = EnumSet.noneOf(Material.class);
static { static {
// Materials from Material.isTransparent() // If the server is running in a test environment, the isTransparent() method will blow up since
for (final Material mat : Material.values()) { // it requires the registry to be initialized. This is a workaround to prevent that from happening.
if (mat.isTransparent()) { if (!Essentials.TESTING) {
HOLLOW_MATERIALS.add(mat); // Materials from Material.isTransparent()
for (final Material mat : Material.values()) {
if (mat.isTransparent()) {
HOLLOW_MATERIALS.add(mat);
}
} }
} }

View File

@ -129,6 +129,15 @@ public final class NumberUtil {
return true; return true;
} }
public static boolean isHexadecimal(final String sNum) {
try {
Integer.parseInt(sNum, 16);
return true;
} catch (final NumberFormatException e) {
return false;
}
}
/** /**
* Backport from Guava. * Backport from Guava.
*/ */

View File

@ -0,0 +1,32 @@
package com.earth2me.essentials.utils;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
public final class RegistryUtil {
private static final Table<Class<?>, String, Object> registryCache = HashBasedTable.create();
private RegistryUtil() {
}
public static <T> T valueOf(Class<T> registry, String... names) {
for (final String name : names) {
//noinspection unchecked
T value = (T) registryCache.get(registry, name);
if (value != null) {
return value;
}
try {
//noinspection unchecked
value = (T) registry.getDeclaredField(name).get(null);
if (value != null) {
registryCache.put(registry, name, value);
return value;
}
} catch (NoSuchFieldException | IllegalAccessException ignored) {
}
}
return null;
}
}

View File

@ -39,8 +39,10 @@ public final class VersionUtil {
public static final BukkitVersion v1_19_4_R01 = BukkitVersion.fromString("1.19.4-R0.1-SNAPSHOT"); public static final BukkitVersion v1_19_4_R01 = BukkitVersion.fromString("1.19.4-R0.1-SNAPSHOT");
public static final BukkitVersion v1_20_1_R01 = BukkitVersion.fromString("1.20.1-R0.1-SNAPSHOT"); public static final BukkitVersion v1_20_1_R01 = BukkitVersion.fromString("1.20.1-R0.1-SNAPSHOT");
public static final BukkitVersion v1_20_4_R01 = BukkitVersion.fromString("1.20.4-R0.1-SNAPSHOT"); public static final BukkitVersion v1_20_4_R01 = BukkitVersion.fromString("1.20.4-R0.1-SNAPSHOT");
public static final BukkitVersion v1_20_6_R01 = BukkitVersion.fromString("1.20.6-R0.1-SNAPSHOT");
public static final BukkitVersion v1_21_R01 = BukkitVersion.fromString("1.21-R0.1-SNAPSHOT");
private static final Set<BukkitVersion> supportedVersions = ImmutableSet.of(v1_8_8_R01, v1_9_4_R01, v1_10_2_R01, v1_11_2_R01, v1_12_2_R01, v1_13_2_R01, v1_14_4_R01, v1_15_2_R01, v1_16_5_R01, v1_17_1_R01, v1_18_2_R01, v1_19_4_R01, v1_20_4_R01); private static final Set<BukkitVersion> supportedVersions = ImmutableSet.of(v1_8_8_R01, v1_9_4_R01, v1_10_2_R01, v1_11_2_R01, v1_12_2_R01, v1_13_2_R01, v1_14_4_R01, v1_15_2_R01, v1_16_5_R01, v1_17_1_R01, v1_18_2_R01, v1_19_4_R01, v1_20_6_R01, v1_21_R01);
public static final boolean PRE_FLATTENING = VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01); public static final boolean PRE_FLATTENING = VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01);

View File

@ -213,6 +213,10 @@ socialspy-listen-muted-players: true
# If false, social spy will only monitor commands from the list above. # If false, social spy will only monitor commands from the list above.
socialspy-messages: true socialspy-messages: true
# Whether social spy should use formatted display names which may include color.
# If false, social spy will use only the actual player names.
socialspy-uses-displaynames: true
# The following settings listen for when a player changes worlds. # The following settings listen for when a player changes worlds.
# If you use another plugin to control speed and flight, you should change these to false. # If you use another plugin to control speed and flight, you should change these to false.

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#Sat Feb 03 17:34:46 GMT 2024 #Sat Feb 03 17:34:46 GMT 2024
action=<dark_purple>* {0} <dark_purple>{1} action=<dark_purple>* {0} <dark_purple>{1}
addedToAccount=<green>{0} has been added to your account. addedToAccount=<yellow>{0}<green> has been added to your account.
addedToOthersAccount=<green>{0} added to {1}<green> account. New balance\: {2} addedToOthersAccount=<yellow>{0}<green> added to<yellow> {1}<green> account. New balance\:<yellow> {2}
adventure=adventure adventure=adventure
afkCommandDescription=Marks you as away-from-keyboard. afkCommandDescription=Marks you as away-from-keyboard.
afkCommandUsage=/<command> [player/message...] afkCommandUsage=/<command> [player/message...]
@ -561,6 +561,7 @@ inventoryClearingAllArmor=<primary>Cleared all inventory items and armor from<se
inventoryClearingAllItems=<primary>Cleared all inventory items from<secondary> {0}<primary>. inventoryClearingAllItems=<primary>Cleared all inventory items from<secondary> {0}<primary>.
inventoryClearingFromAll=<primary>Clearing the inventory of all users... inventoryClearingFromAll=<primary>Clearing the inventory of all users...
inventoryClearingStack=<primary>Removed<secondary> {0} <primary>of<secondary> {1} <primary>from<secondary> {2}<primary>. inventoryClearingStack=<primary>Removed<secondary> {0} <primary>of<secondary> {1} <primary>from<secondary> {2}<primary>.
inventoryFull=<dark_red>Your inventory is full.
invseeCommandDescription=See the inventory of other players. invseeCommandDescription=See the inventory of other players.
invseeCommandUsage=/<command> <player> invseeCommandUsage=/<command> <player>
invseeCommandUsage1=/<command> <player> invseeCommandUsage1=/<command> <player>
@ -862,8 +863,10 @@ noLocationFound=<dark_red>No valid location found.
noMail=<primary>You do not have any mail. noMail=<primary>You do not have any mail.
noMailOther=<secondary>{0} <primary>does not have any mail. noMailOther=<secondary>{0} <primary>does not have any mail.
noMatchingPlayers=<primary>No matching players found. noMatchingPlayers=<primary>No matching players found.
noMetaComponents=Data Components are not supported in this version of Bukkit. Please use JSON NBT metadata.
noMetaFirework=<dark_red>You do not have permission to apply firework meta. noMetaFirework=<dark_red>You do not have permission to apply firework meta.
noMetaJson=JSON Metadata is not supported in this version of Bukkit. noMetaJson=JSON Metadata is not supported in this version of Bukkit.
noMetaNbtKill=JSON NBT metadata is no longer supported. You must manually convert your defined items to data components. You can convert JSON NBT to data components here: https://docs.papermc.io/misc/tools/item-command-converter
noMetaPerm=<dark_red>You do not have permission to apply <secondary>{0}<dark_red> meta to this item. noMetaPerm=<dark_red>You do not have permission to apply <secondary>{0}<dark_red> meta to this item.
none=none none=none
noNewMail=<primary>You have no new mail. noNewMail=<primary>You have no new mail.

View File

@ -218,7 +218,7 @@ public abstract class AbstractChatHandler {
// Strip local chat prefix to preserve API behaviour // Strip local chat prefix to preserve API behaviour
final String localPrefix = AdventureUtil.miniToLegacy(tlLiteral("chatTypeLocal")); final String localPrefix = AdventureUtil.miniToLegacy(tlLiteral("chatTypeLocal"));
String baseFormat = event.getFormat(); String baseFormat = AdventureUtil.legacyToMini(event.getFormat());
if (event.getFormat().startsWith(localPrefix)) { if (event.getFormat().startsWith(localPrefix)) {
baseFormat = baseFormat.substring(localPrefix.length()); baseFormat = baseFormat.substring(localPrefix.length());
} }

View File

@ -10,6 +10,13 @@ public interface InteractionEvent {
*/ */
void reply(String message); void reply(String message);
/**
* Appends the given string to the initial response message and creates one if it doesn't exist.
* @param tlKey The tlKey of the message to append.
* @param args The args for the message to append.
*/
void replyTl(String tlKey, Object... args);
/** /**
* Gets the member which caused this event. * Gets the member which caused this event.
* @return the member which caused the event. * @return the member which caused the event.

View File

@ -383,11 +383,10 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
final Webhook webhook = DiscordUtil.getOrCreateWebhook(channel, DiscordUtil.ADVANCED_RELAY_NAME).join(); final Webhook webhook = DiscordUtil.getOrCreateWebhook(channel, DiscordUtil.ADVANCED_RELAY_NAME).join();
if (webhook == null) { if (webhook == null) {
final WrappedWebhookClient current = channelIdToWebhook.get(channel.getId()); final WrappedWebhookClient current = channelIdToWebhook.remove(channel.getId());
if (current != null) { if (current != null) {
current.close(); current.close();
} }
channelIdToWebhook.remove(channel.getId()).close();
continue; continue;
} }
typeToChannelId.put(type, channel.getId()); typeToChannelId.put(type, channel.getId());

View File

@ -61,7 +61,7 @@ public class InteractionControllerImpl extends ListenerAdapter implements Intera
final InteractionEvent interactionEvent = new InteractionEventImpl(event); final InteractionEvent interactionEvent = new InteractionEventImpl(event);
final List<String> commandSnowflakes = jda.getSettings().getCommandSnowflakes(command.getName()); final List<String> commandSnowflakes = jda.getSettings().getCommandSnowflakes(command.getName());
if (commandSnowflakes != null && !DiscordUtil.hasRoles(event.getMember(), commandSnowflakes)) { if (commandSnowflakes != null && !DiscordUtil.hasRoles(event.getMember(), commandSnowflakes)) {
interactionEvent.reply(tlLiteral("noAccessCommand")); interactionEvent.replyTl("noAccessCommand");
return; return;
} }
jda.getPlugin().getEss().scheduleSyncDelayedTask(() -> command.onCommand(interactionEvent)); jda.getPlugin().getEss().scheduleSyncDelayedTask(() -> command.onCommand(interactionEvent));

View File

@ -1,5 +1,6 @@
package net.essentialsx.discord.interactions; package net.essentialsx.discord.interactions;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.FormatUtil; import com.earth2me.essentials.utils.FormatUtil;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
@ -18,6 +19,8 @@ import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import static com.earth2me.essentials.I18n.tlLiteral;
/** /**
* A class which provides information about what triggered an interaction event. * A class which provides information about what triggered an interaction event.
*/ */
@ -45,6 +48,11 @@ public class InteractionEventImpl implements InteractionEvent {
.queue(null, error -> logger.log(Level.SEVERE, "Error while editing command interaction response", error)); .queue(null, error -> logger.log(Level.SEVERE, "Error while editing command interaction response", error));
} }
@Override
public void replyTl(String tlKey, Object... args) {
reply(AdventureUtil.miniToLegacy(tlLiteral(tlKey, args)));
}
@Override @Override
public InteractionMember getMember() { public InteractionMember getMember() {
return member; return member;

View File

@ -21,7 +21,7 @@ public class ExecuteCommand extends InteractionCommandImpl {
@Override @Override
public void onCommand(final InteractionEvent event) { public void onCommand(final InteractionEvent event) {
final String command = event.getStringArgument("command"); final String command = event.getStringArgument("command");
event.reply(tlLiteral("discordCommandExecuteReply", command)); event.replyTl("discordCommandExecuteReply", command);
Bukkit.getScheduler().runTask(jda.getPlugin(), () -> { Bukkit.getScheduler().runTask(jda.getPlugin(), () -> {
try { try {
Bukkit.dispatchCommand(new DiscordCommandSender(jda, Bukkit.getConsoleSender(), message -> event.reply(MessageUtil.sanitizeDiscordMarkdown(message))).getSender(), command); Bukkit.dispatchCommand(new DiscordCommandSender(jda, Bukkit.getConsoleSender(), message -> event.reply(MessageUtil.sanitizeDiscordMarkdown(message))).getSender(), command);

View File

@ -3,6 +3,7 @@ package net.essentialsx.discord.interactions.commands;
import com.earth2me.essentials.IEssentials; import com.earth2me.essentials.IEssentials;
import com.earth2me.essentials.PlayerList; import com.earth2me.essentials.PlayerList;
import com.earth2me.essentials.User; import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import net.essentialsx.api.v2.services.discord.InteractionCommandArgument; import net.essentialsx.api.v2.services.discord.InteractionCommandArgument;
import net.essentialsx.api.v2.services.discord.InteractionCommandArgumentType; import net.essentialsx.api.v2.services.discord.InteractionCommandArgumentType;
import net.essentialsx.api.v2.services.discord.InteractionEvent; import net.essentialsx.api.v2.services.discord.InteractionEvent;
@ -45,8 +46,8 @@ public class ListCommand extends InteractionCommandImpl {
final StringBuilder stringBuilder = new StringBuilder(); final StringBuilder stringBuilder = new StringBuilder();
for (final String str : output) { for (final String str : output) {
stringBuilder.append(str).append("\n"); stringBuilder.append(FormatUtil.stripMiniFormat(str)).append("\n");
} }
event.reply(MessageUtil.sanitizeDiscordMarkdown(stringBuilder.substring(0, stringBuilder.length() - 2))); event.reply(MessageUtil.sanitizeDiscordMarkdown(stringBuilder.substring(0, stringBuilder.length() - 1)));
} }
} }

View File

@ -2,6 +2,7 @@ package net.essentialsx.discord.interactions.commands;
import com.earth2me.essentials.User; import com.earth2me.essentials.User;
import com.earth2me.essentials.commands.PlayerNotFoundException; import com.earth2me.essentials.commands.PlayerNotFoundException;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.FormatUtil; import com.earth2me.essentials.utils.FormatUtil;
import net.essentialsx.api.v2.services.discord.InteractionCommandArgument; import net.essentialsx.api.v2.services.discord.InteractionCommandArgument;
import net.essentialsx.api.v2.services.discord.InteractionCommandArgumentType; import net.essentialsx.api.v2.services.discord.InteractionCommandArgumentType;
@ -30,28 +31,28 @@ public class MessageCommand extends InteractionCommandImpl {
try { try {
user = jda.getPlugin().getEss().matchUser(Bukkit.getServer(), null, event.getStringArgument("username"), getHidden, false); user = jda.getPlugin().getEss().matchUser(Bukkit.getServer(), null, event.getStringArgument("username"), getHidden, false);
} catch (PlayerNotFoundException e) { } catch (PlayerNotFoundException e) {
event.reply(tlLiteral("errorWithMessage", e.getMessage())); event.replyTl("errorWithMessage", e.getMessage());
return; return;
} }
if (!getHidden && user.isIgnoreMsg()) { if (!getHidden && user.isIgnoreMsg()) {
event.reply(tlLiteral("msgIgnore", MessageUtil.sanitizeDiscordMarkdown(user.getDisplayName()))); event.replyTl("msgIgnore", MessageUtil.sanitizeDiscordMarkdown(user.getDisplayName()));
return; return;
} }
if (user.isAfk()) { if (user.isAfk()) {
if (user.getAfkMessage() != null) { if (user.getAfkMessage() != null) {
event.reply(tlLiteral("userAFKWithMessage", MessageUtil.sanitizeDiscordMarkdown(user.getDisplayName()), MessageUtil.sanitizeDiscordMarkdown(user.getAfkMessage()))); event.replyTl("userAFKWithMessage", MessageUtil.sanitizeDiscordMarkdown(user.getDisplayName()), MessageUtil.sanitizeDiscordMarkdown(user.getAfkMessage()));
} else { } else {
event.reply(tlLiteral("userAFK", MessageUtil.sanitizeDiscordMarkdown(user.getDisplayName()))); event.replyTl("userAFK", MessageUtil.sanitizeDiscordMarkdown(user.getDisplayName()));
} }
} }
final String message = event.getMember().hasRoles(jda.getSettings().getPermittedFormattingRoles()) ? final String message = event.getMember().hasRoles(jda.getSettings().getPermittedFormattingRoles()) ?
FormatUtil.replaceFormat(event.getStringArgument("message")) : FormatUtil.stripFormat(event.getStringArgument("message")); FormatUtil.replaceFormat(event.getStringArgument("message")) : FormatUtil.stripFormat(event.getStringArgument("message"));
event.reply(tlLiteral("msgFormat", tlLiteral("meSender"), MessageUtil.sanitizeDiscordMarkdown(user.getDisplayName()), MessageUtil.sanitizeDiscordMarkdown(message))); event.replyTl("msgFormat", tlLiteral("meSender"), MessageUtil.sanitizeDiscordMarkdown(user.getDisplayName()), MessageUtil.sanitizeDiscordMarkdown(message));
user.sendMessage(tlLiteral("msgFormat", event.getMember().getTag(), user.playerTl("meRecipient"), message)); user.sendTl("msgFormat", event.getMember().getTag(), AdventureUtil.parsed(user.playerTl("meRecipient")), message);
// We use an atomic reference here so that java will garbage collect the recipient // We use an atomic reference here so that java will garbage collect the recipient
final AtomicReference<DiscordMessageRecipient> ref = new AtomicReference<>(new DiscordMessageRecipient(event.getMember())); final AtomicReference<DiscordMessageRecipient> ref = new AtomicReference<>(new DiscordMessageRecipient(event.getMember()));
jda.getPlugin().getEss().runTaskLaterAsynchronously(() -> ref.set(null), 6000); // Expires after 5 minutes jda.getPlugin().getEss().runTaskLaterAsynchronously(() -> ref.set(null), 6000); // Expires after 5 minutes

View File

@ -53,14 +53,14 @@ public class AccountInteractionCommand implements InteractionCommand {
final InteractionMember effectiveUser = userArg == null ? event.getMember() : userArg; final InteractionMember effectiveUser = userArg == null ? event.getMember() : userArg;
final IUser user = accounts.getUser(effectiveUser.getId()); final IUser user = accounts.getUser(effectiveUser.getId());
if (user == null) { if (user == null) {
event.reply(tlLiteral(event.getMember().getId().equals(effectiveUser.getId()) ? "discordCommandAccountResponseNotLinked" : "discordCommandAccountResponseNotLinkedOther", effectiveUser.getAsMention())); event.replyTl(event.getMember().getId().equals(effectiveUser.getId()) ? "discordCommandAccountResponseNotLinked" : "discordCommandAccountResponseNotLinkedOther", effectiveUser.getAsMention());
return; return;
} }
if (event.getMember().getId().equals(effectiveUser.getId())) { if (event.getMember().getId().equals(effectiveUser.getId())) {
event.reply(tlLiteral("discordCommandAccountResponseLinked", user.getName())); event.replyTl("discordCommandAccountResponseLinked", user.getName());
return; return;
} }
event.reply(tlLiteral("discordCommandAccountResponseLinkedOther", effectiveUser.getAsMention(), user.getName())); event.replyTl("discordCommandAccountResponseLinkedOther", effectiveUser.getAsMention(), user.getName());
} }
} }

View File

@ -25,18 +25,18 @@ public class LinkInteractionCommand implements InteractionCommand {
@Override @Override
public void onCommand(InteractionEvent event) { public void onCommand(InteractionEvent event) {
if (accounts.isLinked(event.getMember().getId())) { if (accounts.isLinked(event.getMember().getId())) {
event.reply(tlLiteral("discordCommandLinkHasAccount")); event.replyTl("discordCommandLinkHasAccount");
return; return;
} }
final UUID uuid = accounts.getPendingUUID(event.getStringArgument("code")); final UUID uuid = accounts.getPendingUUID(event.getStringArgument("code"));
if (uuid == null) { if (uuid == null) {
event.reply(tlLiteral("discordCommandLinkInvalidCode")); event.replyTl("discordCommandLinkInvalidCode");
return; return;
} }
accounts.registerAccount(uuid, event.getMember(), DiscordLinkStatusChangeEvent.Cause.SYNC_PLAYER); accounts.registerAccount(uuid, event.getMember(), DiscordLinkStatusChangeEvent.Cause.SYNC_PLAYER);
event.reply(tlLiteral("discordCommandLinkLinked")); event.replyTl("discordCommandLinkLinked");
} }
@Override @Override

View File

@ -20,10 +20,10 @@ public class UnlinkInteractionCommand implements InteractionCommand {
@Override @Override
public void onCommand(InteractionEvent event) { public void onCommand(InteractionEvent event) {
if (!accounts.removeAccount(event.getMember(), DiscordLinkStatusChangeEvent.Cause.UNSYNC_PLAYER)) { if (!accounts.removeAccount(event.getMember(), DiscordLinkStatusChangeEvent.Cause.UNSYNC_PLAYER)) {
event.reply(tlLiteral("discordCommandUnlinkInvalidCode")); event.replyTl("discordCommandUnlinkInvalidCode");
return; return;
} }
event.reply(tlLiteral("discordCommandUnlinkUnlinked")); event.replyTl("discordCommandUnlinkUnlinked");
} }
@Override @Override

View File

@ -60,7 +60,7 @@ public class LinkBukkitListener implements Listener {
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
code = e.getMessage(); code = e.getMessage();
} }
event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, tlLiteral("discordLinkLoginKick", "/link " + code, ess.getApi().getInviteUrl())); event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, AdventureUtil.miniToLegacy(tlLiteral("discordLinkLoginKick", "/link " + code, ess.getApi().getInviteUrl())));
} }
} }

View File

@ -1,13 +1,10 @@
package com.earth2me.essentials.xmpp; package com.earth2me.essentials.xmpp;
import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.CommandSource; import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User; import com.earth2me.essentials.User;
import com.earth2me.essentials.commands.EssentialsLoopCommand; import com.earth2me.essentials.commands.EssentialsLoopCommand;
import com.earth2me.essentials.commands.NotEnoughArgumentsException; import com.earth2me.essentials.commands.NotEnoughArgumentsException;
import com.earth2me.essentials.commands.PlayerExemptException; import net.ess3.api.TranslatableException;
import com.earth2me.essentials.commands.PlayerNotFoundException;
import net.ess3.api.MaxMoneyException;
import org.bukkit.Server; import org.bukkit.Server;
public class Commandxmppspy extends EssentialsLoopCommand { public class Commandxmppspy extends EssentialsLoopCommand {
@ -16,7 +13,7 @@ public class Commandxmppspy extends EssentialsLoopCommand {
} }
@Override @Override
protected void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws NotEnoughArgumentsException, PlayerExemptException, MaxMoneyException, ChargeException, PlayerNotFoundException { protected void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws NotEnoughArgumentsException, TranslatableException {
if (args.length == 0) { if (args.length == 0) {
throw new NotEnoughArgumentsException(); throw new NotEnoughArgumentsException();
} }

View File

@ -26,7 +26,7 @@ however, have some new requirements:
* **EssentialsX requires CraftBukkit, Spigot or Paper to run.** Other server software may work, but these are not tested * **EssentialsX requires CraftBukkit, Spigot or Paper to run.** Other server software may work, but these are not tested
by the team and we may not be able to help with any issues that occur. by the team and we may not be able to help with any issues that occur.
* **EssentialsX currently supports Minecraft versions 1.8.8, 1.9.4, 1.10.2, 1.11.2, 1.12.2, 1.13.2, 1.14.4, 1.15.2, * **EssentialsX currently supports Minecraft versions 1.8.8, 1.9.4, 1.10.2, 1.11.2, 1.12.2, 1.13.2, 1.14.4, 1.15.2,
1.16.5, 1.17.1, 1.18.2, 1.19.4, and 1.20.4.** 1.16.5, 1.17.1, 1.18.2, 1.19.4, 1.20.6, and 1.21.**
* **EssentialsX currently requires Java 8 or higher.** We recommend using the latest Java version supported by your * **EssentialsX currently requires Java 8 or higher.** We recommend using the latest Java version supported by your
server software. server software.
* **EssentialsX requires [Vault](http://dev.bukkit.org/bukkit-plugins/vault/) to enable using chat prefix/suffixes and * **EssentialsX requires [Vault](http://dev.bukkit.org/bukkit-plugins/vault/) to enable using chat prefix/suffixes and

View File

@ -9,5 +9,5 @@ repositories {
dependencies { dependencies {
implementation("net.kyori", "indra-common", "3.1.3") implementation("net.kyori", "indra-common", "3.1.3")
implementation("com.github.johnrengelman", "shadow", "8.1.1") implementation("com.github.johnrengelman", "shadow", "8.1.1")
implementation("xyz.jpenilla", "run-task", "2.2.3") implementation("xyz.jpenilla", "run-task", "2.3.0")
} }

View File

@ -1 +1 @@
const val RUN_PAPER_MINECRAFT_VERSION = "1.20.4" const val RUN_PAPER_MINECRAFT_VERSION = "1.21"

View File

@ -10,7 +10,7 @@ plugins {
val baseExtension = extensions.create<EssentialsBaseExtension>("essentials", project) val baseExtension = extensions.create<EssentialsBaseExtension>("essentials", project)
val checkstyleVersion = "8.36.2" val checkstyleVersion = "8.36.2"
val spigotVersion = "1.20.4-R0.1-SNAPSHOT" val spigotVersion = "1.21-R0.1-SNAPSHOT"
val junit5Version = "5.10.2" val junit5Version = "5.10.2"
val mockitoVersion = "3.12.4" val mockitoVersion = "3.12.4"
@ -75,6 +75,9 @@ tasks {
} }
withType<Jar> { withType<Jar> {
archiveVersion.set(rootProject.ext["FULL_VERSION"] as String) archiveVersion.set(rootProject.ext["FULL_VERSION"] as String)
manifest {
attributes("paperweight-mappings-namespace" to "mojang")
}
} }
withType<Sign> { withType<Sign> {
onlyIf { project.hasProperty("forceSign") } onlyIf { project.hasProperty("forceSign") }
@ -122,7 +125,7 @@ indra {
javaVersions { javaVersions {
target(8) target(8)
minimumToolchain(17) minimumToolchain(21)
// Don't enforce running tests on Java 8; we only care about the release for compiling, not running tests // Don't enforce running tests on Java 8; we only care about the release for compiling, not running tests
strictVersions(false) strictVersions(false)
} }

View File

@ -3,6 +3,9 @@ plugins {
} }
dependencies { dependencies {
implementation(project(':providers:BaseProviders')) {
exclude group: "org.spigotmc", module: "spigot-api"
}
api project(':providers:NMSReflectionProvider') api project(':providers:NMSReflectionProvider')
} }

View File

@ -64,8 +64,8 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
public class OfflinePlayerStub implements Player { public class OfflinePlayerStub implements Player {
protected final transient org.bukkit.OfflinePlayer base;
private final transient Server server; private final transient Server server;
private final transient org.bukkit.OfflinePlayer base;
private transient Location location = new Location(null, 0, 0, 0, 0, 0); private transient Location location = new Location(null, 0, 0, 0, 0, 0);
private transient World world; private transient World world;
private boolean allowFlight = false; private boolean allowFlight = false;

View File

@ -0,0 +1,26 @@
package net.ess3.provider.providers;
import net.ess3.provider.BannerDataProvider;
import org.bukkit.DyeColor;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BannerMeta;
public class LegacyBannerDataProvider implements BannerDataProvider {
@Override
public DyeColor getBaseColor(ItemStack stack) {
final BannerMeta bannerMeta = (BannerMeta) stack.getItemMeta();
return bannerMeta.getBaseColor();
}
@Override
public void setBaseColor(ItemStack stack, DyeColor color) {
final BannerMeta bannerMeta = (BannerMeta) stack.getItemMeta();
bannerMeta.setBaseColor(color);
stack.setItemMeta(bannerMeta);
}
@Override
public String getDescription() {
return "Legacy Banner Meta Provider";
}
}

View File

@ -0,0 +1,33 @@
package net.ess3.provider.providers;
import net.ess3.provider.InventoryViewProvider;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
public class LegacyInventoryViewProvider implements InventoryViewProvider {
@Override
public Inventory getTopInventory(InventoryView view) {
return view.getTopInventory();
}
@Override
public Inventory getBottomInventory(InventoryView view) {
return view.getBottomInventory();
}
@Override
public void setItem(InventoryView view, int slot, ItemStack item) {
view.setItem(slot, item);
}
@Override
public void close(InventoryView view) {
view.close();
}
@Override
public String getDescription() {
return "Legacy InventoryView Abstract Class ABI Provider";
}
}

View File

@ -0,0 +1,134 @@
package net.ess3.provider.providers;
import com.google.common.collect.ImmutableMap;
import net.ess3.provider.PotionMetaProvider;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionType;
import java.util.Collection;
import java.util.Map;
public class LegacyPotionMetaProvider implements PotionMetaProvider {
private static final Map<Integer, PotionType> damageValueToType = ImmutableMap.<Integer, PotionType>builder()
.put(1, PotionType.REGEN)
.put(2, PotionType.SPEED)
.put(3, PotionType.FIRE_RESISTANCE)
.put(4, PotionType.POISON)
.put(5, PotionType.INSTANT_HEAL)
.put(6, PotionType.NIGHT_VISION)
// Skip 7
.put(8, PotionType.WEAKNESS)
.put(9, PotionType.STRENGTH)
.put(10, PotionType.SLOWNESS)
.put(11, PotionType.JUMP)
.put(12, PotionType.INSTANT_DAMAGE)
.put(13, PotionType.WATER_BREATHING)
.put(14, PotionType.INVISIBILITY)
.build();
private static int getBit(final int n, final int k) {
return (n >> k) & 1;
}
@Override
public ItemStack createPotionItem(final Material initial, final int effectId) {
ItemStack potion = new ItemStack(initial, 1);
if (effectId == 0) {
return potion;
}
final int damageValue = getBit(effectId, 0) +
2 * getBit(effectId, 1) +
4 * getBit(effectId, 2) +
8 * getBit(effectId, 3);
final PotionType type = damageValueToType.get(damageValue);
if (type == null) {
throw new IllegalArgumentException("Unable to process potion effect ID " + effectId + " with damage value " + damageValue);
}
//getBit is splash here
if (getBit(effectId, 14) == 1 && initial == Material.POTION) {
potion = new ItemStack(Material.SPLASH_POTION, 1);
}
final PotionMeta meta = (PotionMeta) potion.getItemMeta();
//getBit(s) are extended and upgraded respectfully
final PotionData data = new PotionData(type, getBit(effectId, 6) == 1, getBit(effectId, 5) == 1);
meta.setBasePotionData(data); // this method is exclusive to recent 1.9+
potion.setItemMeta(meta);
return potion;
}
@Override
public void setSplashPotion(final ItemStack stack, final boolean isSplash) {
if (stack == null) {
throw new IllegalArgumentException("ItemStack cannot be null");
}
if (isSplash && stack.getType() == Material.POTION) {
stack.setType(Material.SPLASH_POTION);
} else if (!isSplash && stack.getType() == Material.SPLASH_POTION) {
stack.setType(Material.POTION);
}
}
@Override
public boolean isSplashPotion(final ItemStack stack) {
return stack != null && stack.getType() == Material.SPLASH_POTION;
}
@Override
public Collection<PotionEffect> getCustomEffects(final ItemStack stack) {
final PotionMeta meta = (PotionMeta) stack.getItemMeta();
return meta.getCustomEffects();
}
@Override
public boolean isExtended(final ItemStack stack) {
final PotionMeta meta = (PotionMeta) stack.getItemMeta();
final PotionData data = meta.getBasePotionData();
return data.isExtended();
}
@Override
public boolean isUpgraded(final ItemStack stack) {
final PotionMeta meta = (PotionMeta) stack.getItemMeta();
final PotionData data = meta.getBasePotionData();
return data.isUpgraded();
}
@Override
public PotionType getBasePotionType(final ItemStack stack) {
final PotionMeta meta = (PotionMeta) stack.getItemMeta();
final PotionData data = meta.getBasePotionData();
return data.getType();
}
@Override
public void setBasePotionType(final ItemStack stack, final PotionType type, final boolean extended, final boolean upgraded) {
if (stack == null) {
throw new IllegalArgumentException("ItemStack cannot be null");
}
if (extended && upgraded) {
throw new IllegalArgumentException("Potion cannot be both extended and upgraded");
}
final PotionData data = new PotionData(type, extended, upgraded);
final PotionMeta meta = (PotionMeta) stack.getItemMeta();
meta.setBasePotionData(data);
stack.setItemMeta(meta);
}
@Override
public String getDescription() {
return "1.9-1.20.4 Potion Meta Provider";
}
}

View File

@ -0,0 +1,85 @@
package net.ess3.provider.providers;
import net.ess3.provider.PotionMetaProvider;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionType;
import java.util.Collection;
public class PrehistoricPotionMetaProvider implements PotionMetaProvider {
@Override
public ItemStack createPotionItem(final Material initial, final int effectId) {
final ItemStack potion = new ItemStack(initial, 1);
potion.setDurability((short) effectId);
return potion;
}
@Override
public void setSplashPotion(final ItemStack stack, final boolean isSplash) {
if (stack == null) {
throw new IllegalArgumentException("ItemStack cannot be null");
}
final Potion potion = Potion.fromItemStack(stack);
potion.setSplash(isSplash);
potion.apply(stack);
}
@Override
public boolean isSplashPotion(ItemStack stack) {
return Potion.fromItemStack(stack).isSplash();
}
@Override
public Collection<PotionEffect> getCustomEffects(ItemStack stack) {
return Potion.fromItemStack(stack).getEffects();
}
@Override
public boolean isExtended(final ItemStack stack) {
throw new UnsupportedOperationException();
}
@Override
public boolean isUpgraded(final ItemStack stack) {
throw new UnsupportedOperationException();
}
@Override
public PotionType getBasePotionType(final ItemStack stack) {
throw new UnsupportedOperationException();
}
@Override
public void setBasePotionType(final ItemStack stack, final PotionType type, final boolean extended, final boolean upgraded) {
if (stack == null) {
throw new IllegalArgumentException("ItemStack cannot be null");
}
if (extended && upgraded) {
throw new IllegalArgumentException("Potion cannot be both extended and upgraded");
}
final Potion potion = Potion.fromItemStack(stack);
if (extended && !potion.getType().isInstant()) {
potion.setHasExtendedDuration(true);
potion.setLevel(Math.min(potion.getLevel(), 1));
}
if (upgraded && type.getMaxLevel() == 2) {
potion.setLevel(2);
potion.setHasExtendedDuration(false);
}
potion.apply(stack);
}
@Override
public String getDescription() {
return "Legacy 1.8 Potion Meta Provider";
}
}

View File

@ -0,0 +1,10 @@
package net.ess3.provider;
import org.bukkit.DyeColor;
import org.bukkit.inventory.ItemStack;
public interface BannerDataProvider extends Provider {
DyeColor getBaseColor(ItemStack stack);
void setBaseColor(ItemStack stack, DyeColor color);
}

View File

@ -0,0 +1,8 @@
package net.ess3.provider;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
public interface BiomeKeyProvider extends Provider {
NamespacedKey getBiomeKey(Block block);
}

View File

@ -0,0 +1,19 @@
package net.ess3.provider;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
/**
* Bukkit changed InventoryView to an interface in 1.21. We need to use providers
* to avoid breaking ABI compatibility with earlier versions of Bukkit.
*/
public interface InventoryViewProvider extends Provider {
Inventory getTopInventory(InventoryView view);
void close(InventoryView view);
Inventory getBottomInventory(InventoryView view);
void setItem(InventoryView view, int slot, ItemStack item);
}

View File

@ -2,7 +2,25 @@ package net.ess3.provider;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionType;
import java.util.Collection;
public interface PotionMetaProvider extends Provider { public interface PotionMetaProvider extends Provider {
ItemStack createPotionItem(Material initial, int effectId); ItemStack createPotionItem(Material initial, int effectId);
void setSplashPotion(ItemStack stack, boolean isSplash);
boolean isSplashPotion(ItemStack stack);
Collection<PotionEffect> getCustomEffects(ItemStack stack);
boolean isExtended(ItemStack stack);
boolean isUpgraded(ItemStack stack);
PotionType getBasePotionType(ItemStack stack);
void setBasePotionType(ItemStack stack, PotionType type, boolean extended, boolean upgraded);
} }

View File

@ -0,0 +1,49 @@
package net.ess3.provider.providers;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import net.ess3.provider.BannerDataProvider;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
public class BaseBannerDataProvider implements BannerDataProvider {
private final BiMap<Material, DyeColor> materialToDyeMap = HashBiMap.create();
public BaseBannerDataProvider() {
materialToDyeMap.put(Material.WHITE_BANNER, DyeColor.WHITE);
materialToDyeMap.put(Material.LIGHT_GRAY_BANNER, DyeColor.LIGHT_GRAY);
materialToDyeMap.put(Material.GRAY_BANNER, DyeColor.GRAY);
materialToDyeMap.put(Material.BLACK_BANNER, DyeColor.BLACK);
materialToDyeMap.put(Material.RED_BANNER, DyeColor.RED);
materialToDyeMap.put(Material.ORANGE_BANNER, DyeColor.ORANGE);
materialToDyeMap.put(Material.YELLOW_BANNER, DyeColor.YELLOW);
materialToDyeMap.put(Material.LIME_BANNER, DyeColor.LIME);
materialToDyeMap.put(Material.GREEN_BANNER, DyeColor.GREEN);
materialToDyeMap.put(Material.CYAN_BANNER, DyeColor.CYAN);
materialToDyeMap.put(Material.LIGHT_BLUE_BANNER, DyeColor.LIGHT_BLUE);
materialToDyeMap.put(Material.BLUE_BANNER, DyeColor.BLUE);
materialToDyeMap.put(Material.PURPLE_BANNER, DyeColor.PURPLE);
materialToDyeMap.put(Material.MAGENTA_BANNER, DyeColor.MAGENTA);
materialToDyeMap.put(Material.PINK_BANNER, DyeColor.PINK);
materialToDyeMap.put(Material.BROWN_BANNER, DyeColor.BROWN);
}
@Override
public DyeColor getBaseColor(ItemStack stack) {
return materialToDyeMap.get(stack.getType());
}
@Override
public void setBaseColor(ItemStack stack, DyeColor color) {
final Material material = materialToDyeMap.inverse().get(color);
if (material != null) {
stack.setType(material);
}
}
@Override
public String getDescription() {
return "1.20.5+ Banner Data Provider.";
}
}

View File

@ -0,0 +1,33 @@
package net.ess3.provider.providers;
import net.ess3.provider.InventoryViewProvider;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
public class BaseInventoryViewProvider implements InventoryViewProvider {
@Override
public Inventory getTopInventory(InventoryView view) {
return view.getTopInventory();
}
@Override
public Inventory getBottomInventory(InventoryView view) {
return view.getBottomInventory();
}
@Override
public void setItem(InventoryView view, int slot, ItemStack item) {
view.setItem(slot, item);
}
@Override
public void close(InventoryView view) {
view.close();
}
@Override
public String getDescription() {
return "1.21+ InventoryView Interface ABI Provider";
}
}

View File

@ -1,79 +0,0 @@
package net.ess3.provider.providers;
import com.google.common.collect.ImmutableMap;
import net.ess3.provider.PotionMetaProvider;
import net.essentialsx.providers.ProviderData;
import net.essentialsx.providers.ProviderTest;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionType;
import java.util.Map;
@ProviderData(description = "1.9+ Potion Meta Provider", weight = 1)
public class BasePotionDataProvider implements PotionMetaProvider {
private static final Map<Integer, PotionType> damageValueToType = ImmutableMap.<Integer, PotionType>builder()
.put(1, PotionType.REGEN)
.put(2, PotionType.SPEED)
.put(3, PotionType.FIRE_RESISTANCE)
.put(4, PotionType.POISON)
.put(5, PotionType.INSTANT_HEAL)
.put(6, PotionType.NIGHT_VISION)
// Skip 7
.put(8, PotionType.WEAKNESS)
.put(9, PotionType.STRENGTH)
.put(10, PotionType.SLOWNESS)
.put(11, PotionType.JUMP)
.put(12, PotionType.INSTANT_DAMAGE)
.put(13, PotionType.WATER_BREATHING)
.put(14, PotionType.INVISIBILITY)
.build();
private static int getBit(final int n, final int k) {
return (n >> k) & 1;
}
@Override
public ItemStack createPotionItem(final Material initial, final int effectId) {
ItemStack potion = new ItemStack(initial, 1);
if (effectId == 0) {
return potion;
}
final int damageValue = getBit(effectId, 0) +
2 * getBit(effectId, 1) +
4 * getBit(effectId, 2) +
8 * getBit(effectId, 3);
final PotionType type = damageValueToType.get(damageValue);
if (type == null) {
throw new IllegalArgumentException("Unable to process potion effect ID " + effectId + " with damage value " + damageValue);
}
//getBit is splash here
if (getBit(effectId, 14) == 1 && initial == Material.POTION) {
potion = new ItemStack(Material.SPLASH_POTION, 1);
}
final PotionMeta meta = (PotionMeta) potion.getItemMeta();
//getBit(s) are extended and upgraded respectfully
final PotionData data = new PotionData(type, getBit(effectId, 6) == 1, getBit(effectId, 5) == 1);
meta.setBasePotionData(data); // this method is exclusive to recent 1.9+
potion.setItemMeta(meta);
return potion;
}
@ProviderTest
public static boolean test() {
try {
Class.forName("org.bukkit.potion.PotionData");
return true;
} catch (final ClassNotFoundException ignored) {
return false;
}
}
}

View File

@ -1,17 +0,0 @@
package net.ess3.provider.providers;
import net.ess3.provider.PotionMetaProvider;
import net.essentialsx.providers.ProviderData;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
@SuppressWarnings("deprecation")
@ProviderData(description = "1.8 Potion Meta Provider")
public class LegacyPotionMetaProvider implements PotionMetaProvider {
@Override
public ItemStack createPotionItem(final Material initial, final int effectId) {
final ItemStack potion = new ItemStack(initial, 1);
potion.setDurability((short) effectId);
return potion;
}
}

View File

@ -0,0 +1,107 @@
package net.ess3.provider.providers;
import net.ess3.provider.PotionMetaProvider;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionType;
import java.util.Collection;
public class ModernPotionMetaProvider implements PotionMetaProvider {
@Override
public ItemStack createPotionItem(Material initial, int effectId) {
throw new UnsupportedOperationException("This should never happen, if this happens please submit a bug report!");
}
@Override
public void setBasePotionType(final ItemStack stack, PotionType type, final boolean extended, final boolean upgraded) {
if (stack == null) {
throw new IllegalArgumentException("ItemStack cannot be null");
}
if (extended && upgraded) {
throw new IllegalArgumentException("Potion cannot be both extended and upgraded");
}
final String name = type.name();
if (name.startsWith("LONG_")) {
type = PotionType.valueOf(name.substring(5));
} else if (name.startsWith("STRONG_")) {
type = PotionType.valueOf(name.substring(7));
}
if (extended && type.isExtendable()) {
type = PotionType.valueOf("LONG_" + type.name());
}
if (upgraded && type.isUpgradeable()) {
type = PotionType.valueOf("STRONG_" + type.name());
}
final PotionMeta meta = (PotionMeta) stack.getItemMeta();
//noinspection DataFlowIssue
meta.setBasePotionType(type);
stack.setItemMeta(meta);
}
@Override
public Collection<PotionEffect> getCustomEffects(ItemStack stack) {
final PotionMeta meta = (PotionMeta) stack.getItemMeta();
//noinspection DataFlowIssue
return meta.getCustomEffects();
}
@Override
public boolean isSplashPotion(ItemStack stack) {
return stack != null && stack.getType() == Material.SPLASH_POTION;
}
@Override
public boolean isExtended(ItemStack stack) {
final PotionMeta meta = (PotionMeta) stack.getItemMeta();
//noinspection DataFlowIssue
return meta.getBasePotionType().name().startsWith("LONG_");
}
@Override
public boolean isUpgraded(ItemStack stack) {
final PotionMeta meta = (PotionMeta) stack.getItemMeta();
//noinspection DataFlowIssue
return meta.getBasePotionType().name().startsWith("STRONG_");
}
@Override
public PotionType getBasePotionType(ItemStack stack) {
final PotionMeta meta = (PotionMeta) stack.getItemMeta();
//noinspection DataFlowIssue
PotionType type = meta.getBasePotionType();
//noinspection DataFlowIssue
final String name = type.name();
if (name.startsWith("LONG_")) {
type = PotionType.valueOf(name.substring(5));
} else if (name.startsWith("STRONG_")) {
type = PotionType.valueOf(name.substring(7));
}
return type;
}
@Override
public void setSplashPotion(ItemStack stack, boolean isSplash) {
if (stack == null) {
throw new IllegalArgumentException("ItemStack cannot be null");
}
if (isSplash && stack.getType() == Material.POTION) {
stack.setType(Material.SPLASH_POTION);
} else if (!isSplash && stack.getType() == Material.SPLASH_POTION) {
stack.setType(Material.POTION);
}
}
@Override
public String getDescription() {
return "1.20.5+ Potion Meta Provider";
}
}

View File

@ -22,6 +22,7 @@ public final class ReflUtil {
public static final NMSVersion V1_18_R1 = NMSVersion.fromString("v1_18_R1"); public static final NMSVersion V1_18_R1 = NMSVersion.fromString("v1_18_R1");
public static final NMSVersion V1_19_R1 = NMSVersion.fromString("v1_19_R1"); public static final NMSVersion V1_19_R1 = NMSVersion.fromString("v1_19_R1");
public static final NMSVersion V1_19_R2 = NMSVersion.fromString("v1_19_R2"); public static final NMSVersion V1_19_R2 = NMSVersion.fromString("v1_19_R2");
public static final NMSVersion V1_20_R4 = NMSVersion.fromString("v1_20_R4");
private static final Map<String, Class<?>> classCache = new HashMap<>(); private static final Map<String, Class<?>> classCache = new HashMap<>();
private static final Table<Class<?>, String, Method> methodCache = HashBasedTable.create(); private static final Table<Class<?>, String, Method> methodCache = HashBasedTable.create();
private static final Table<Class<?>, MethodParams, Method> methodParamCache = HashBasedTable.create(); private static final Table<Class<?>, MethodParams, Method> methodParamCache = HashBasedTable.create();

View File

@ -18,7 +18,9 @@ public class ReflServerStateProvider implements ServerStateProvider {
MethodHandle isRunning = null; MethodHandle isRunning = null;
final String MDFIVEMAGICLETTER; final String MDFIVEMAGICLETTER;
if (ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_19_R2)) { if (ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_20_R4)) {
MDFIVEMAGICLETTER = "x";
} else if (ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_19_R2)) {
MDFIVEMAGICLETTER = "v"; MDFIVEMAGICLETTER = "v";
} else if (ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_19_R1)) { } else if (ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_19_R1)) {
MDFIVEMAGICLETTER = "u"; MDFIVEMAGICLETTER = "u";

View File

@ -11,8 +11,8 @@ dependencies {
implementation(project(':providers:BaseProviders')) { implementation(project(':providers:BaseProviders')) {
exclude(module: 'spigot-api') exclude(module: 'spigot-api')
} }
compileOnly 'io.papermc.paper:paper-api:1.18.2-R0.1-SNAPSHOT' compileOnly 'io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT'
compileOnly 'io.papermc.paper:paper-mojangapi:1.18.2-R0.1-SNAPSHOT' compileOnly 'io.papermc.paper:paper-mojangapi:1.20.4-R0.1-SNAPSHOT'
} }
essentials { essentials {

View File

@ -0,0 +1,19 @@
package net.ess3.provider.providers;
import net.ess3.provider.BiomeKeyProvider;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
@SuppressWarnings("deprecation")
public class PaperBiomeKeyProvider implements BiomeKeyProvider {
@Override
public NamespacedKey getBiomeKey(final Block block) {
return Bukkit.getUnsafe().getBiomeKey(block.getWorld(), block.getX(), block.getY(), block.getZ());
}
@Override
public String getDescription() {
return "Paper Biome Key Provider";
}
}