Merge branch '2.x' into l10n_2.x

This commit is contained in:
Josh Roy 2024-11-24 18:20:20 -05:00 committed by GitHub
commit 9a5f748783
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
94 changed files with 5835 additions and 739 deletions

View File

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

View File

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

View File

@ -1,5 +1,6 @@
package com.earth2me.essentials;
import java.util.stream.Collectors;
import org.bukkit.command.Command;
import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.plugin.Plugin;
@ -31,7 +32,7 @@ public class AlternativeCommandsHandler {
if (plugin.getDescription().getMain().contains("com.earth2me.essentials") || plugin.getDescription().getMain().contains("net.essentialsx")) {
return;
}
for (final Map.Entry<String, Command> entry : getPluginCommands(plugin).entrySet()) {
for (final Map.Entry<String, Command> entry : getPluginCommands(plugin)) {
final String[] commandSplit = entry.getKey().split(":", 2);
final String commandName = commandSplit.length > 1 ? commandSplit[1] : entry.getKey();
final Command command = entry.getValue();
@ -64,14 +65,23 @@ public class AlternativeCommandsHandler {
}
}
private Map<String, Command> getPluginCommands(Plugin plugin) {
private List<Map.Entry<String, Command>> getPluginCommands(Plugin plugin) {
final Map<String, Command> commands = new HashMap<>();
for (final Map.Entry<String, Command> entry : ess.getKnownCommandsProvider().getKnownCommands().entrySet()) {
if (entry.getValue() instanceof PluginIdentifiableCommand && ((PluginIdentifiableCommand) entry.getValue()).getPlugin().equals(plugin)) {
commands.put(entry.getKey(), entry.getValue());
}
}
return commands;
// Try to use non-namespaced commands first if we can, some Commands may not like being registered under a
// different label than their getName() returns, so avoid doing that when we can
return commands.entrySet().stream().sorted((o1, o2) -> {
if (o1.getKey().contains(":") && !o2.getKey().contains(":")) {
return 1;
} else if (!o1.getKey().contains(":") && o2.getKey().contains(":")) {
return -1;
}
return 0;
}).collect(Collectors.toList());
}
public void removePlugin(final Plugin plugin) {

View File

@ -7,7 +7,6 @@ import com.earth2me.essentials.utils.LocationUtil;
import io.papermc.lib.PaperLib;
import net.ess3.api.IEssentials;
import net.ess3.api.IUser;
import net.ess3.api.InvalidWorldException;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.UserWarpEvent;
import net.ess3.api.events.teleport.PreTeleportEvent;
@ -424,7 +423,7 @@ public class AsyncTeleport implements IAsyncTeleport {
final Location loc;
try {
loc = ess.getWarps().getWarp(warp);
} catch (final WarpNotFoundException | InvalidWorldException e) {
} catch (final WarpNotFoundException e) {
future.completeExceptionally(e);
return;
}

View File

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

View File

@ -36,7 +36,9 @@ public class CommandSource {
}
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) {

View File

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

View File

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

View File

@ -59,10 +59,12 @@ import net.ess3.nms.refl.providers.ReflServerStateProvider;
import net.ess3.nms.refl.providers.ReflSpawnEggProvider;
import net.ess3.nms.refl.providers.ReflSpawnerBlockProvider;
import net.ess3.nms.refl.providers.ReflSyncCommandsProvider;
import net.ess3.provider.BannerDataProvider;
import net.ess3.provider.BiomeKeyProvider;
import net.ess3.provider.ContainerProvider;
import net.ess3.provider.DamageEventProvider;
import net.ess3.provider.FormattedCommandAliasProvider;
import net.ess3.provider.InventoryViewProvider;
import net.ess3.provider.ItemUnbreakableProvider;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.MaterialTagProvider;
@ -78,14 +80,17 @@ import net.ess3.provider.SpawnerBlockProvider;
import net.ess3.provider.SpawnerItemProvider;
import net.ess3.provider.SyncCommandsProvider;
import net.ess3.provider.WorldInfoProvider;
import net.ess3.provider.providers.BaseBannerDataProvider;
import net.ess3.provider.providers.BaseInventoryViewProvider;
import net.ess3.provider.providers.BaseLoggerProvider;
import net.ess3.provider.providers.BasePotionDataProvider;
import net.ess3.provider.providers.BlockMetaSpawnerItemProvider;
import net.ess3.provider.providers.BukkitMaterialTagProvider;
import net.ess3.provider.providers.BukkitSpawnerBlockProvider;
import net.ess3.provider.providers.FixedHeightWorldInfoProvider;
import net.ess3.provider.providers.FlatSpawnEggProvider;
import net.ess3.provider.providers.LegacyBannerDataProvider;
import net.ess3.provider.providers.LegacyDamageEventProvider;
import net.ess3.provider.providers.LegacyInventoryViewProvider;
import net.ess3.provider.providers.LegacyItemUnbreakableProvider;
import net.ess3.provider.providers.LegacyPlayerLocaleProvider;
import net.ess3.provider.providers.LegacyPotionMetaProvider;
@ -95,6 +100,7 @@ import net.ess3.provider.providers.ModernDataWorldInfoProvider;
import net.ess3.provider.providers.ModernItemUnbreakableProvider;
import net.ess3.provider.providers.ModernPersistentDataProvider;
import net.ess3.provider.providers.ModernPlayerLocaleProvider;
import net.ess3.provider.providers.ModernPotionMetaProvider;
import net.ess3.provider.providers.ModernSignDataProvider;
import net.ess3.provider.providers.PaperBiomeKeyProvider;
import net.ess3.provider.providers.PaperContainerProvider;
@ -103,6 +109,7 @@ import net.ess3.provider.providers.PaperMaterialTagProvider;
import net.ess3.provider.providers.PaperRecipeBookListener;
import net.ess3.provider.providers.PaperSerializationProvider;
import net.ess3.provider.providers.PaperServerStateProvider;
import net.ess3.provider.providers.PrehistoricPotionMetaProvider;
import net.essentialsx.api.v2.services.BalanceTop;
import net.essentialsx.api.v2.services.mail.MailService;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
@ -126,6 +133,7 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.inventory.InventoryView;
import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
@ -146,6 +154,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.UUID;
import java.util.function.Predicate;
@ -158,6 +167,7 @@ import static com.earth2me.essentials.I18n.tlLocale;
public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private static final Logger BUKKIT_LOGGER = Logger.getLogger("Essentials");
private static Logger LOGGER = null;
public static boolean TESTING = false;
private final transient TNTExplodeListener tntListener = new TNTExplodeListener();
private final transient Set<String> vanishedPlayers = new LinkedHashSet<>();
private final transient Map<String, IEssentialsCommand> commandMap = new HashMap<>();
@ -184,6 +194,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private transient SpawnerBlockProvider spawnerBlockProvider;
private transient SpawnEggProvider spawnEggProvider;
private transient PotionMetaProvider potionMetaProvider;
private transient BannerDataProvider bannerDataProvider;
private transient ServerStateProvider serverStateProvider;
private transient ContainerProvider containerProvider;
private transient SerializationProvider serializationProvider;
@ -200,6 +211,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private transient SignDataProvider signDataProvider;
private transient DamageEventProvider damageEventProvider;
private transient BiomeKeyProvider biomeKeyProvider;
private transient InventoryViewProvider inventoryViewProvider;
private transient Kits kits;
private transient RandomTeleport randomTeleport;
private transient UpdateChecker updateChecker;
@ -226,6 +238,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
public void setupForTesting(final Server server) throws IOException, InvalidDescriptionException {
TESTING = true;
LOGGER = new BaseLoggerProvider(this, BUKKIT_LOGGER);
final File dataFolder = File.createTempFile("essentialstest", "");
if (!dataFolder.delete()) {
@ -345,6 +358,10 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
upgrade.convertKits();
execTimer.mark("Kits");
randomTeleport = new RandomTeleport(this);
confList.add(randomTeleport);
execTimer.mark("Init(RandomTeleport)");
upgrade.afterSettings();
execTimer.mark("Upgrade3");
@ -360,13 +377,6 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
confList.add(itemDb);
execTimer.mark("Init(ItemDB)");
randomTeleport = new RandomTeleport(this);
if (randomTeleport.getPreCache()) {
randomTeleport.cacheRandomLocations(randomTeleport.getCenter(), randomTeleport.getMinRange(), randomTeleport.getMaxRange());
}
confList.add(randomTeleport);
execTimer.mark("Init(RandomTeleport)");
customItemResolver = new CustomItemResolver(this);
try {
itemDb.registerResolver(this, "custom_items", customItemResolver);
@ -403,10 +413,19 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
//Potion Meta Provider
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
potionMetaProvider = new LegacyPotionMetaProvider();
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 BasePotionDataProvider();
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
@ -488,6 +507,12 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
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();
}
@ -785,7 +810,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
} catch (final Exception ex) {
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
if (cSender instanceof Player) {
cSender.sendMessage(tlLocale(I18n.getLocale(getPlayerLocaleProvider().getLocale((Player) cSender)), "internalError"));
getBukkitAudience().sender(cSender).sendMessage(AdventureUtil.miniMessage().deserialize(tlLocale(I18n.getLocale(getPlayerLocaleProvider().getLocale((Player) cSender)), "internalError")));
} else {
cSender.sendMessage(tlLiteral("internalError"));
}
@ -876,7 +901,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
} catch (final NotEnoughArgumentsException ex) {
if (getSettings().isVerboseCommandUsages() && !cmd.getUsageStrings().isEmpty()) {
sender.sendTl("commandHelpLine1", commandLabel);
sender.sendTl("commandHelpLine2", command.getDescription());
String description = command.getDescription();
try {
description = sender.tl(command.getName() + "CommandDescription");
} catch (MissingResourceException ignored) {}
sender.sendTl("commandHelpLine2", description);
sender.sendTl("commandHelpLine3");
for (Map.Entry<String, String> usage : cmd.getUsageStrings().entrySet()) {
sender.sendTl("commandHelpLineUsage", AdventureUtil.parsed(usage.getKey().replace("<command>", commandLabel)), AdventureUtil.parsed(usage.getValue()));
@ -912,12 +941,14 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
public void cleanupOpenInventories() {
for (final User user : getOnlineUsers()) {
if (user.isRecipeSee()) {
user.getBase().getOpenInventory().getTopInventory().clear();
user.getBase().getOpenInventory().close();
final InventoryView view = user.getBase().getOpenInventory();
inventoryViewProvider.getTopInventory(view).clear();
inventoryViewProvider.close(view);
user.setRecipeSee(false);
}
if (user.isInvSee() || user.isEnderSee()) {
user.getBase().getOpenInventory().close();
inventoryViewProvider.close(user.getBase().getOpenInventory());
user.setInvSee(false);
user.setEnderSee(false);
}
@ -1200,7 +1231,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
@Override
public void broadcastTl(final String tlKey, final Object... args) {
broadcastTl(null, null, true, tlKey, args);
broadcastTl(null, null, false, tlKey, args);
}
@Override
@ -1364,6 +1395,16 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
return potionMetaProvider;
}
@Override
public BannerDataProvider getBannerDataProvider() {
return bannerDataProvider;
}
@Override
public InventoryViewProvider getInventoryViewProvider() {
return inventoryViewProvider;
}
@Override
public CustomItemResolver getCustomItemResolver() {
return customItemResolver;

View File

@ -299,7 +299,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
}
user.setLogoutLocation();
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());
@ -545,14 +545,14 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
final Date banExpiry = banEntry.getExpiration();
if (banExpiry != null) {
final String expiry = DateUtil.formatDateDiff(banExpiry.getTime());
event.setKickMessage(tlLiteral("tempbanJoin", expiry, banEntry.getReason()));
event.setKickMessage(AdventureUtil.miniToLegacy(tlLiteral("tempbanJoin", expiry, banEntry.getReason())));
} else {
event.setKickMessage(tlLiteral("banJoin", banEntry.getReason()));
event.setKickMessage(AdventureUtil.miniToLegacy(tlLiteral("banJoin", banEntry.getReason())));
}
} else {
banEntry = ess.getServer().getBanList(BanList.Type.IP).getBanEntry(event.getAddress().getHostAddress());
if (banEntry != null) {
event.setKickMessage(tlLiteral("banIpJoin", banEntry.getReason()));
event.setKickMessage(AdventureUtil.miniToLegacy(tlLiteral("banIpJoin", banEntry.getReason())));
}
}
}
@ -609,7 +609,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) {
final String cmd = event.getMessage().toLowerCase(Locale.ENGLISH).split(" ")[0].replace("/", "").toLowerCase(Locale.ENGLISH);
final String cmd = event.getMessage().split(" ")[0].replace("/", "").toLowerCase(Locale.ENGLISH);
final int argStartIndex = event.getMessage().indexOf(" ");
final String args = argStartIndex == -1 ? "" // No arguments present
: event.getMessage().substring(argStartIndex); // arguments start at argStartIndex; substring from there.
@ -632,7 +632,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
public void handlePlayerCommandPreprocess(final PlayerCommandPreprocessEvent event, final String effectiveCommand) {
final Player player = event.getPlayer();
final String cmd = effectiveCommand.toLowerCase(Locale.ENGLISH).split(" ")[0].replace("/", "").toLowerCase(Locale.ENGLISH);
final String cmd = effectiveCommand.split(" ")[0].replace("/", "").toLowerCase(Locale.ENGLISH);
final PluginCommand pluginCommand = ess.getServer().getPluginCommand(cmd);
if (ess.getSettings().getSocialSpyCommands().contains(cmd) || ess.getSettings().getSocialSpyCommands().contains("*")) {
@ -640,12 +640,13 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|| (!pluginCommand.getName().equals("msg") && !pluginCommand.getName().equals("r"))) { // /msg and /r are handled in SimpleMessageRecipient
final User user = ess.getUser(player);
if (!user.isAuthorized("essentials.chat.spy.exempt")) {
final String playerName = ess.getSettings().isSocialSpyDisplayNames() ? player.getDisplayName() : player.getName();
for (final User spyer : ess.getOnlineUsers()) {
if (spyer.isSocialSpyEnabled() && !player.equals(spyer.getBase())) {
final Component base = (user.isMuted() && ess.getSettings().getSocialSpyListenMutedPlayers())
? spyer.tlComponent("socialSpyMutedPrefix")
: 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())));
}
}
}
@ -896,14 +897,14 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onInventoryClickEvent(final InventoryClickEvent event) {
Player refreshPlayer = null;
final Inventory top = event.getView().getTopInventory();
final Inventory top = ess.getInventoryViewProvider().getTopInventory(event.getView());
final InventoryType type = top.getType();
final Inventory clickedInventory;
if (event.getRawSlot() < 0) {
clickedInventory = null;
} 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());
@ -962,7 +963,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
@EventHandler(priority = EventPriority.MONITOR)
public void onInventoryCloseEvent(final InventoryCloseEvent event) {
Player refreshPlayer = null;
final Inventory top = event.getView().getTopInventory();
final Inventory top = ess.getInventoryViewProvider().getTopInventory(event.getView());
final InventoryType type = top.getType();
if (type == InventoryType.PLAYER) {
final User user = ess.getUser((Player) event.getPlayer());
@ -976,7 +977,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
final User user = ess.getUser((Player) event.getPlayer());
if (user.isRecipeSee()) {
user.setRecipeSee(false);
event.getView().getTopInventory().clear();
ess.getInventoryViewProvider().getTopInventory(event.getView()).clear();
refreshPlayer = user.getBase();
}
} else if (type == InventoryType.CHEST && top.getSize() == 9) {

View File

@ -3,6 +3,7 @@ package com.earth2me.essentials;
import com.earth2me.essentials.config.ConfigurateUtil;
import com.earth2me.essentials.config.EssentialsConfiguration;
import com.earth2me.essentials.config.EssentialsUserConfiguration;
import com.earth2me.essentials.config.entities.LazyLocation;
import com.earth2me.essentials.craftbukkit.BanLookup;
import com.earth2me.essentials.userstorage.ModernUUIDCache;
import com.earth2me.essentials.utils.AdventureUtil;
@ -156,6 +157,39 @@ public class EssentialsUpgrade {
ess.getLogger().info("To rerun the conversion type /essentials uuidconvert");
}
public void updateRandomTeleport() {
if (doneFile.getBoolean("updateRandomTeleport", false)) {
return;
}
final EssentialsConfiguration config = ess.getRandomTeleport().getConfig();
final LazyLocation center = config.getLocation("center");
final Location centerLoc = center != null ? center.location() : null;
if (center != null && centerLoc != null) {
final double minRange = config.getDouble("min-range", Double.MIN_VALUE);
final double maxRange = config.getDouble("max-range", Double.MIN_VALUE);
for (final World world : ess.getServer().getWorlds()) {
final String propPrefix = "locations." + world.getName() + ".";
config.setProperty(propPrefix + "center", centerLoc);
if (minRange != Double.MIN_VALUE) {
config.setProperty(propPrefix + "min-range", minRange);
}
if (maxRange != Double.MIN_VALUE) {
config.setProperty(propPrefix + "max-range", maxRange);
}
}
}
config.removeProperty("center");
config.blockingSave();
doneFile.setProperty("updateRandomTeleport", true);
doneFile.save();
ess.getLogger().info("Done converting random teleport config.");
}
public void convertMailList() {
if (doneFile.getBoolean("updateUsersMailList", false)) {
return;
@ -1068,5 +1102,6 @@ public class EssentialsUpgrade {
convertStupidCamelCaseUserdataKeys();
convertMailList();
purgeBrokenNpcAccounts();
updateRandomTeleport();
}
}

View File

@ -9,10 +9,12 @@ import com.earth2me.essentials.perm.PermissionsHandler;
import com.earth2me.essentials.updatecheck.UpdateChecker;
import com.earth2me.essentials.userstorage.IUserMap;
import net.ess3.nms.refl.providers.ReflOnlineModeProvider;
import net.ess3.provider.BannerDataProvider;
import net.ess3.provider.BiomeKeyProvider;
import net.ess3.provider.ContainerProvider;
import net.ess3.provider.DamageEventProvider;
import net.ess3.provider.FormattedCommandAliasProvider;
import net.ess3.provider.InventoryViewProvider;
import net.ess3.provider.ItemUnbreakableProvider;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.MaterialTagProvider;
@ -189,5 +191,9 @@ public interface IEssentials extends Plugin {
BiomeKeyProvider getBiomeKeyProvider();
BannerDataProvider getBannerDataProvider();
InventoryViewProvider getInventoryViewProvider();
PluginCommand getPluginCommand(String cmd);
}

View File

@ -73,6 +73,8 @@ public interface ISettings extends IConf {
boolean isSocialSpyMessages();
boolean isSocialSpyDisplayNames();
Set<String> getMuteCommands();
@Deprecated
@ -104,6 +106,10 @@ public interface ISettings extends IConf {
boolean getRespawnAtHome();
String getRandomSpawnLocation();
String getRandomRespawnLocation();
boolean isRespawnAtAnchor();
Set getMultipleHomes();

View File

@ -30,7 +30,6 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
@ -130,21 +129,30 @@ public class MetaItemStack {
}
public boolean canSpawn(final IEssentials ess) {
try {
ess.getServer().getUnsafe().modifyItemStack(stack.clone(), "{}");
return true;
} catch (final NoSuchMethodError nsme) {
return true;
} catch (final Throwable npe) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "Itemstack is invalid", npe);
if (VersionUtil.PRE_FLATTENING) {
try {
ess.getServer().getUnsafe().modifyItemStack(stack.clone(), "{}");
return true;
} catch (final NoSuchMethodError nsme) {
return true;
} catch (final Throwable npe) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "Itemstack is invalid", npe);
}
return false;
}
return false;
}
return stack.getType().isItem();
}
public void parseStringMeta(final CommandSource sender, final boolean allowUnsafe, final String[] string, final int fromArg, final IEssentials ess) throws Exception {
final boolean nbtIsKill = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_6_R01);
if (string[fromArg].startsWith("{") && hasMetaPermission(sender, "vanilla", false, true, ess)) {
if (nbtIsKill) {
throw new TranslatableException("noMetaNbtKill");
}
try {
stack = ess.getServer().getUnsafe().modifyItemStack(stack, Joiner.on(' ').join(Arrays.asList(string).subList(fromArg, string.length)));
} catch (final NullPointerException npe) {
@ -156,6 +164,22 @@ public class MetaItemStack {
} catch (final Throwable throwable) {
throw new Exception(throwable.getMessage(), throwable);
}
} else if (string[fromArg].startsWith("[") && hasMetaPermission(sender, "vanilla", false, true, ess)) {
if (!nbtIsKill) {
throw new TranslatableException("noMetaComponents");
}
try {
final String components = Joiner.on(' ').join(Arrays.asList(string).subList(fromArg, string.length));
// 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 {
for (int i = fromArg; i < string.length; i++) {
addStringMeta(sender, allowUnsafe, string[i], ess);
@ -541,17 +565,7 @@ public class MetaItemStack {
}
pmeta.addCustomEffect(pEffect, true);
stack.setItemMeta(pmeta);
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01)) {
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);
}
ess.getPotionMetaProvider().setSplashPotion(stack, isSplashPotion);
resetPotionMeta();
}
}
@ -562,7 +576,7 @@ public class MetaItemStack {
if (enchantment == null) {
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;
if (split.length > 1) {
try {
@ -605,7 +619,7 @@ public class MetaItemStack {
}
}
} catch (final Exception ex) {
throw new Exception("Enchantment " + enchantment.getName() + ": " + ex.getMessage(), ex);
throw new Exception("Enchantment " + Enchantments.getRealName(enchantment) + ": " + ex.getMessage(), ex);
}
}
@ -615,7 +629,7 @@ public class MetaItemStack {
return null;
}
final String enchantmentName = enchantment.getName().toLowerCase(Locale.ENGLISH);
final String enchantmentName = Enchantments.getRealName(enchantment);
if (!hasMetaPermission(user, "enchantments." + enchantmentName, true, false)) {
throw new TranslatableException("enchantmentPerm", enchantmentName);
@ -633,16 +647,18 @@ public class MetaItemStack {
PatternType patternType = null;
try {
patternType = PatternType.valueOf(split[0]);
//noinspection removal
patternType = PatternType.getByIdentifier(split[0]);
} catch (final Exception ignored) {
}
final BannerMeta meta = (BannerMeta) stack.getItemMeta();
if (split[0].equalsIgnoreCase("basecolor")) {
final Color color = Color.fromRGB(Integer.parseInt(split[1]));
meta.setBaseColor(DyeColor.getByColor(color));
ess.getBannerDataProvider().setBaseColor(stack, DyeColor.getByColor(color));
} 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 org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type);
meta.addPattern(pattern);
@ -658,7 +674,8 @@ public class MetaItemStack {
PatternType patternType = null;
try {
patternType = PatternType.valueOf(split[0]);
//noinspection removal
patternType = PatternType.getByIdentifier(split[0]);
} catch (final Exception ignored) {
}
@ -669,7 +686,8 @@ public class MetaItemStack {
final Color color = Color.fromRGB(Integer.parseInt(split[1]));
banner.setBaseColor(DyeColor.getByColor(color));
} else if (patternType != null) {
final PatternType type = PatternType.valueOf(split[0]);
//noinspection removal
final PatternType type = PatternType.getByIdentifier(split[0]);
final DyeColor color = DyeColor.getByColor(Color.fromRGB(Integer.parseInt(split[1])));
final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type);
banner.addPattern(pattern);

View File

@ -42,22 +42,30 @@ public enum Mob {
ENDERDRAGON("EnderDragon", Enemies.ENEMY, EntityType.ENDER_DRAGON),
VILLAGER("Villager", Enemies.FRIENDLY, EntityType.VILLAGER),
BLAZE("Blaze", Enemies.ENEMY, EntityType.BLAZE),
MUSHROOMCOW("MushroomCow", Enemies.FRIENDLY, EntityType.MUSHROOM_COW),
MUSHROOMCOW("MushroomCow", Enemies.FRIENDLY, MobCompat.MOOSHROOM),
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),
IRONGOLEM("IronGolem", Enemies.NEUTRAL, EntityType.IRON_GOLEM),
WITHER("Wither", Enemies.ENEMY, EntityType.WITHER),
BAT("Bat", Enemies.FRIENDLY, EntityType.BAT),
WITCH("Witch", Enemies.ENEMY, EntityType.WITCH),
BOAT("Boat", Enemies.NEUTRAL, EntityType.BOAT),
BOAT("Boat", Enemies.NEUTRAL, MobCompat.OAK_BOAT),
ACACIA_BOAT("AcaciaBoat", Enemies.NEUTRAL, "ACACIA_BOAT"),
DARK_OAK_BOAT("DarkOakBoat", Enemies.NEUTRAL, "DARK_OAK_BOAT"),
BIRCH_BOAT("BirchBoat", Enemies.NEUTRAL, "BIRCH_BOAT"),
JUNGLE_BOAT("JungleBoat", Enemies.NEUTRAL, "JUNGLE_BOAT"),
SPRUCE_BOAT("SpruceBoat", Enemies.NEUTRAL, "SPRUCE_BOAT"),
MANGROVE_BOAT("MangroveBoat", Enemies.NEUTRAL, "MANGROVE_BOAT"),
CHERRY_BOAT("CherryBoat", Enemies.NEUTRAL, "CHERRY_BOAT"),
BAMBOO_RAFT("BambooRaft", Enemies.NEUTRAL, "BAMBOO_RAFT"),
MINECART("Minecart", Enemies.NEUTRAL, EntityType.MINECART),
MINECART_CHEST("ChestMinecart", Enemies.NEUTRAL, EntityType.MINECART_CHEST),
MINECART_FURNACE("FurnaceMinecart", Enemies.NEUTRAL, EntityType.MINECART_FURNACE),
MINECART_TNT("TNTMinecart", Enemies.NEUTRAL, EntityType.MINECART_TNT),
MINECART_HOPPER("HopperMinecart", Enemies.NEUTRAL, EntityType.MINECART_HOPPER),
MINECART_MOB_SPAWNER("SpawnerMinecart", Enemies.NEUTRAL, EntityType.MINECART_MOB_SPAWNER),
ENDERCRYSTAL("EnderCrystal", Enemies.NEUTRAL, EntityType.ENDER_CRYSTAL),
MINECART_CHEST("ChestMinecart", Enemies.NEUTRAL, MobCompat.CHEST_MINECART),
MINECART_FURNACE("FurnaceMinecart", Enemies.NEUTRAL, MobCompat.FURNACE_MINECART),
MINECART_TNT("TNTMinecart", Enemies.NEUTRAL, MobCompat.TNT_MINECART),
MINECART_HOPPER("HopperMinecart", Enemies.NEUTRAL, MobCompat.HOPPER_MINECART),
MINECART_MOB_SPAWNER("SpawnerMinecart", Enemies.NEUTRAL, MobCompat.SPAWNER_MINECART),
ENDERCRYSTAL("EnderCrystal", Enemies.NEUTRAL, MobCompat.END_CRYSTAL),
EXPERIENCEORB("ExperienceOrb", Enemies.NEUTRAL, "EXPERIENCE_ORB"),
ARMOR_STAND("ArmorStand", Enemies.NEUTRAL, "ARMOR_STAND"),
ENDERMITE("Endermite", Enemies.ENEMY, "ENDERMITE"),
@ -112,6 +120,9 @@ public enum Mob {
CHEST_BOAT("ChestBoat", Enemies.NEUTRAL, "CHEST_BOAT"),
CAMEL("Camel", Enemies.FRIENDLY, "CAMEL"),
SNIFFER("Sniffer", Enemies.FRIENDLY, "SNIFFER"),
ARMADILLO("Armadillo", Enemies.FRIENDLY, "ARMADILLO"),
BREEZE("Breeze", Enemies.ENEMY, "BREEZE"),
BOGGED("Bogged", Enemies.ENEMY, "BOGGED"),
;
private static final Map<String, Mob> hashMap = new HashMap<>();

View File

@ -1,6 +1,7 @@
package com.earth2me.essentials;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.RegistryUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.nms.refl.ReflUtil;
import org.bukkit.Material;
@ -18,8 +19,10 @@ import org.bukkit.entity.Ocelot;
import org.bukkit.entity.Panda;
import org.bukkit.entity.Parrot;
import org.bukkit.entity.Player;
import org.bukkit.entity.Salmon;
import org.bukkit.entity.TropicalFish;
import org.bukkit.entity.Villager;
import org.bukkit.entity.Wolf;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Method;
@ -46,10 +49,21 @@ public final class MobCompat {
public static final EntityType GOAT = getEntityType("GOAT");
public static final EntityType FROG = getEntityType("FROG");
public static final EntityType CAMEL = getEntityType("CAMEL");
public static final EntityType SALMON = getEntityType("SALMON");
// Constants for mobs that have changed since earlier versions
public static final EntityType CAT = getEntityType("CAT", "OCELOT");
public static final EntityType ZOMBIFIED_PIGLIN = getEntityType("ZOMBIFIED_PIGLIN", "PIG_ZOMBIE");
public static final EntityType MOOSHROOM = getEntityType("MOOSHROOM", "MUSHROOM_COW");
public static final EntityType SNOW_GOLEM = getEntityType("SNOW_GOLEM", "SNOWMAN");
public static final EntityType CHEST_MINECART = getEntityType("CHEST_MINECART", "MINECART_CHEST");
public static final EntityType FURNACE_MINECART = getEntityType("FURNACE_MINECART", "MINECART_FURNACE");
public static final EntityType TNT_MINECART = getEntityType("TNT_MINECART", "MINECART_TNT");
public static final EntityType HOPPER_MINECART = getEntityType("HOPPER_MINECART", "MINECART_HOPPER");
public static final EntityType SPAWNER_MINECART = getEntityType("SPAWNER_MINECART", "MINECART_MOB_SPAWNER");
public static final EntityType END_CRYSTAL = getEntityType("END_CRYSTAL", "ENDER_CRYSTAL");
public static final EntityType FIREWORK_ROCKET = getEntityType("FIREWORK_ROCKET", "FIREWORK");
public static final EntityType OAK_BOAT = getEntityType("BOAT", "OAK_BOAT");
private MobCompat() {
}
@ -183,7 +197,7 @@ public final class MobCompat {
}
public static void setBoatVariant(final Entity entity, final BoatVariant variant) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_21_3_R01) || VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
return;
}
final Boat boat;
@ -196,6 +210,7 @@ public final class MobCompat {
//noinspection deprecation
boat.setWoodType(TreeSpecies.valueOf(variant.getTreeSpecies()));
} else {
//noinspection deprecation
boat.setBoatType(Boat.Type.valueOf(variant.getBoatType()));
}
}
@ -213,6 +228,28 @@ 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 static void setSalmonSize(Entity spawned, String s) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_21_3_R01)) {
return;
}
if (spawned instanceof org.bukkit.entity.Salmon) {
((Salmon) spawned).setVariant(Salmon.Variant.valueOf(s));
}
}
public enum CatType {
// These are (loosely) Mojang names for the cats
SIAMESE("SIAMESE", "SIAMESE_CAT"),
@ -273,7 +310,7 @@ public final class MobCompat {
}
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),
BETTY_TROPICAL_FISH("betty", MobCompat.TROPICAL_FISH, "tropicalfish:BETTY", true),
CLAYFISH_TROPICAL_FISH("clayfish", MobCompat.TROPICAL_FISH, "tropicalfish:CLAYFISH", true),
BROWN_MUSHROOM_COW("brown", EntityType.MUSHROOM_COW, "mooshroom:BROWN", true),
RED_MUSHROOM_COW("red", EntityType.MUSHROOM_COW, "mooshroom:RED", true),
BROWN_MUSHROOM_COW("brown", MobCompat.MOOSHROOM, "mooshroom:BROWN", true),
RED_MUSHROOM_COW("red", MobCompat.MOOSHROOM, "mooshroom:RED", true),
AGGRESSIVE_PANDA_MAIN("aggressive", MobCompat.PANDA, "pandamain:AGGRESSIVE", true),
LAZY_PANDA_MAIN("lazy", MobCompat.PANDA, "pandamain:LAZY", true),
WORRIED_PANDA_MAIN("worried", MobCompat.PANDA, "pandamain:WORRIED", true),
@ -209,6 +209,18 @@ public enum MobData {
OAK_BOAT("oak", Boat.class, MobCompat.BoatVariant.OAK, true),
SPRUCE_BOAT("spruce", Boat.class, MobCompat.BoatVariant.SPRUCE, true),
SADDLE_CAMEL("saddle", MobCompat.CAMEL, Data.CAMELSADDLE, true),
PALE_WOLF("pale", EntityType.WOLF, "wolf:PALE", true),
SPOTTED_WOLF("spotted", EntityType.WOLF, "wolf:PALE", true),
SNOWY_WOLF("snowy", EntityType.WOLF, "wolf:PALE", true),
BLACK_WOLF("black", EntityType.WOLF, "wolf:BLACK", true),
ASHEN_WOLF("ashen", EntityType.WOLF, "wolf:ASHEN", true),
RUSTY_WOLF("rusty", EntityType.WOLF, "wolf:RUSTY", true),
WOODS_WOLF("woods", EntityType.WOLF, "wolf:WOODS", true),
CHESTNUT_WOLF("chestnut", EntityType.WOLF, "wolf:CHESTNUT", true),
STRIPED_WOLF("striped", EntityType.WOLF, "wolf:STRIPED", true),
SMALL_SALMON("small", MobCompat.SALMON, "salmon:SMALL", true),
MEDIUM_SALMON("medium", MobCompat.SALMON, "salmon:MEDIUM", true),
LARGE_SALMON("large", MobCompat.SALMON, "salmon:LARGE", true),
;
final private String nickname;
@ -424,6 +436,12 @@ public enum MobData {
case "frog":
MobCompat.setFrogVariant(spawned, split[1]);
break;
case "wolf":
MobCompat.setWolfVariant(spawned, split[1]);
break;
case "salmon":
MobCompat.setSalmonSize(spawned, split[1]);
break;
}
} else {
Essentials.getWrappedLogger().warning("Unknown mob data type: " + this.toString());

View File

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

View File

@ -1,17 +1,22 @@
package com.earth2me.essentials;
import com.earth2me.essentials.config.ConfigurateUtil;
import com.earth2me.essentials.config.EssentialsConfiguration;
import com.earth2me.essentials.config.entities.LazyLocation;
import com.earth2me.essentials.utils.LocationUtil;
import com.earth2me.essentials.utils.VersionUtil;
import io.papermc.lib.PaperLib;
import net.ess3.api.InvalidWorldException;
import net.ess3.provider.BiomeKeyProvider;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
@ -23,58 +28,72 @@ public class RandomTeleport implements IConf {
private static final int HIGHEST_BLOCK_Y_OFFSET = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_15_R01) ? 1 : 0;
private final IEssentials ess;
private final EssentialsConfiguration config;
private final ConcurrentLinkedQueue<Location> cachedLocations = new ConcurrentLinkedQueue<>();
private final Map<String, ConcurrentLinkedQueue<Location>> cachedLocations = new HashMap<>();
public RandomTeleport(final IEssentials essentials) {
this.ess = essentials;
config = new EssentialsConfiguration(new File(essentials.getDataFolder(), "tpr.yml"), "/tpr.yml",
"Configuration for the random teleport command.\nSome settings may be defaulted, and can be changed via the /settpr command in-game.");
"Configuration for the random teleport command.\nUse the /settpr command in-game to set random teleport locations.");
reloadConfig();
}
public EssentialsConfiguration getConfig() {
return config;
}
@Override
public void reloadConfig() {
config.load();
cachedLocations.clear();
}
public Location getCenter() {
try {
final LazyLocation center = config.getLocation("center");
if (center != null && center.location() != null) {
return center.location();
}
} catch (final InvalidWorldException ignored) {
public boolean hasLocation(final String name) {
return config.hasProperty("locations." + name);
}
public Location getCenter(final String name) {
final LazyLocation center = config.getLocation(locationKey(name, "center"));
if (center != null && center.location() != null) {
return center.location();
}
final Location center = ess.getServer().getWorlds().get(0).getWorldBorder().getCenter();
center.setY(center.getWorld().getHighestBlockYAt(center) + HIGHEST_BLOCK_Y_OFFSET);
setCenter(center);
return center;
final Location worldCenter = ess.getServer().getWorlds().get(0).getWorldBorder().getCenter();
worldCenter.setY(worldCenter.getWorld().getHighestBlockYAt(worldCenter) + HIGHEST_BLOCK_Y_OFFSET);
setCenter(name, worldCenter);
return worldCenter;
}
public void setCenter(final Location center) {
config.setProperty("center", center);
public void setCenter(final String name, final Location center) {
config.setProperty(locationKey(name, "center"), center);
config.save();
}
public double getMinRange() {
return config.getDouble("min-range", 0d);
public double getMinRange(final String name) {
return config.getDouble(locationKey(name, "min-range"), 0d);
}
public void setMinRange(final double minRange) {
config.setProperty("min-range", minRange);
public void setMinRange(final String name, final double minRange) {
config.setProperty(locationKey(name, "min-range"), minRange);
config.save();
}
public double getMaxRange() {
return config.getDouble("max-range", getCenter().getWorld().getWorldBorder().getSize() / 2);
public double getMaxRange(final String name) {
return config.getDouble(locationKey(name, "max-range"), getCenter(name).getWorld().getWorldBorder().getSize() / 2);
}
public void setMaxRange(final double maxRange) {
config.setProperty("max-range", maxRange);
public void setMaxRange(final String name, final double maxRange) {
config.setProperty(locationKey(name, "max-range"), maxRange);
config.save();
}
public String getDefaultLocation() {
return config.getString("default-location", "{world}");
}
public boolean isPerLocationPermission() {
return config.getBoolean("per-location-permission", false);
}
public Set<String> getExcludedBiomes() {
final Set<String> excludedBiomes = new HashSet<>();
for (final String key : config.getList("excluded-biomes", String.class)) {
@ -91,39 +110,48 @@ public class RandomTeleport implements IConf {
return config.getInt("cache-threshold", 10);
}
public boolean getPreCache() {
return config.getBoolean("pre-cache", false);
public List<String> listLocations() {
return new ArrayList<>(ConfigurateUtil.getKeys(config.getRootNode().node("locations")));
}
public Queue<Location> getCachedLocations() {
return cachedLocations;
public Queue<Location> getCachedLocations(final String name) {
this.cachedLocations.computeIfAbsent(name, x -> new ConcurrentLinkedQueue<>());
return cachedLocations.get(name);
}
// Get a random location; cached if possible. Otherwise on demand.
public CompletableFuture<Location> getRandomLocation(final Location center, final double minRange, final double maxRange) {
final int findAttempts = this.getFindAttempts();
final Queue<Location> cachedLocations = this.getCachedLocations();
// Get a named random teleport location; cached if possible, otherwise on demand.
public CompletableFuture<Location> getRandomLocation(final String name) {
final Queue<Location> cached = this.getCachedLocations(name);
// Try to build up the cache if it is below the threshold
if (cachedLocations.size() < this.getCacheThreshold()) {
cacheRandomLocations(center, minRange, maxRange);
if (cached.size() < this.getCacheThreshold()) {
cacheRandomLocations(name);
}
final CompletableFuture<Location> future = new CompletableFuture<>();
// Return a random location immediately if one is available, otherwise try to find one now
if (cachedLocations.isEmpty()) {
if (cached.isEmpty()) {
final int findAttempts = this.getFindAttempts();
final Location center = this.getCenter(name);
final double minRange = this.getMinRange(name);
final double maxRange = this.getMaxRange(name);
attemptRandomLocation(findAttempts, center, minRange, maxRange).thenAccept(future::complete);
} else {
future.complete(cachedLocations.poll());
future.complete(cached.poll());
}
return future;
}
// Prompts caching random valid locations, up to a maximum number of attempts
public void cacheRandomLocations(final Location center, final double minRange, final double maxRange) {
// Get a random location with specific parameters (note: not cached).
public CompletableFuture<Location> getRandomLocation(final Location center, final double minRange, final double maxRange) {
return attemptRandomLocation(this.getFindAttempts(), center, minRange, maxRange);
}
// Prompts caching random valid locations, up to a maximum number of attempts.
public void cacheRandomLocations(final String name) {
ess.getServer().getScheduler().scheduleSyncDelayedTask(ess, () -> {
for (int i = 0; i < this.getFindAttempts(); ++i) {
calculateRandomLocation(center, minRange, maxRange).thenAccept(location -> {
calculateRandomLocation(getCenter(name), getMinRange(name), getMaxRange(name)).thenAccept(location -> {
if (isValidRandomLocation(location)) {
this.getCachedLocations().add(location);
this.getCachedLocations(name).add(location);
}
});
}
@ -188,14 +216,18 @@ public class RandomTeleport implements IConf {
return future;
}
// Returns an appropriate elevation for a given location in the nether, or -1 if none is found
// Returns an appropriate elevation for a given location in the nether, or MIN_VALUE if none is found
private double getNetherYAt(final Location location) {
for (int y = 32; y < ess.getWorldInfoProvider().getMaxHeight(location.getWorld()); ++y) {
if (!LocationUtil.isBlockUnsafe(ess, location.getWorld(), location.getBlockX(), y, location.getBlockZ())) {
final World world = location.getWorld();
for (int y = 32; y < ess.getWorldInfoProvider().getMaxHeight(world); ++y) {
if (Material.BEDROCK.equals(world.getBlockAt(location.getBlockX(), y, location.getBlockZ()).getType())) {
break;
}
if (!LocationUtil.isBlockUnsafe(ess, world, location.getBlockX(), y, location.getBlockZ())) {
return y;
}
}
return -1;
return Double.MIN_VALUE;
}
private boolean isValidRandomLocation(final Location location) {
@ -226,6 +258,10 @@ public class RandomTeleport implements IConf {
return excluded.contains(biomeKey);
}
private String locationKey(final String name, final String key) {
return "locations." + name + "." + key;
}
public File getFile() {
return config.getFile();
}

View File

@ -23,6 +23,7 @@ import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.event.EventPriority;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.spongepowered.configurate.CommentedConfigurationNode;
import java.io.File;
@ -162,6 +163,16 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("respawn-at-home", false);
}
@Override
public String getRandomSpawnLocation() {
return config.getString("random-spawn-location", "none");
}
@Override
public String getRandomRespawnLocation() {
return config.getString("random-respawn-location", "none");
}
@Override
public boolean isRespawnAtAnchor() {
return config.getBoolean("respawn-at-anchor", false);
@ -456,6 +467,11 @@ public class Settings implements net.ess3.api.ISettings {
return config.getBoolean("socialspy-messages", true);
}
@Override
public boolean isSocialSpyDisplayNames() {
return config.getBoolean("socialspy-uses-displaynames", true);
}
private Set<String> _getMuteCommands() {
final Set<String> muteCommands = new HashSet<>();
if (config.isList("mute-commands")) {
@ -700,6 +716,18 @@ public class Settings implements net.ess3.api.ISettings {
mapModified = true;
}
if (reloadCount.get() < 2) {
// on startup: add plugins again in case they registered commands with the new API
// we need to schedule this task before any of the below tasks using _addAlternativeCommand.
ess.scheduleSyncDelayedTask(() -> {
for (final Plugin plugin : ess.getServer().getPluginManager().getPlugins()) {
if (plugin.isEnabled()) {
ess.getAlternativeCommandsHandler().addPlugin(plugin);
}
}
});
}
for (final String command : disabledCommands) {
final String effectiveAlias = command.toLowerCase(Locale.ENGLISH);
final Command toDisable = ess.getPluginCommand(effectiveAlias);

View File

@ -191,23 +191,23 @@ public class Trade {
}
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;
}
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;
}
final BigDecimal 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;
}
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());
}
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;
}
user.takeMoney(getMoney());
@ -295,7 +295,7 @@ public class Trade {
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " itemstack " + getItemStack().toString());
}
if (!Inventories.containsAtLeast(user.getBase(), getItemStack(), getItemStack().getAmount())) {
future.completeExceptionally(new ChargeException(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;
}
Inventories.removeItemAmount(user.getBase(), getItemStack(), getItemStack().getAmount());
@ -304,7 +304,7 @@ public class Trade {
if (command != null) {
final BigDecimal cost = getCommandCost(user);
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;
}
user.takeMoney(cost);
@ -315,7 +315,7 @@ public class Trade {
}
final int experience = SetExpFix.getTotalExperience(user.getBase());
if (experience < getExperience() && getExperience() > 0) {
future.completeExceptionally(new ChargeException(user.playerTl("notEnoughExperience")));
future.completeExceptionally(new ChargeException("notEnoughExperience"));
return;
}
SetExpFix.setTotalExperience(user.getBase(), experience - getExperience());

View File

@ -271,7 +271,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
final TransactionEvent transactionEvent = new TransactionEvent(this.getSource(), reciever, value);
ess.getServer().getPluginManager().callEvent(transactionEvent);
} else {
throw new ChargeException(tlLocale(playerLocale, "notEnoughMoney", NumberUtil.displayCurrency(value, ess)));
throw new ChargeException("notEnoughMoney", NumberUtil.displayCurrency(value, ess));
}
}

View File

@ -5,7 +5,6 @@ import com.earth2me.essentials.config.EssentialsConfiguration;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.StringUtil;
import net.ess3.api.InvalidNameException;
import net.ess3.api.InvalidWorldException;
import net.ess3.api.TranslatableException;
import org.bukkit.Location;
@ -54,7 +53,7 @@ public class Warps implements IConf, net.ess3.api.IWarps {
}
@Override
public Location getWarp(final String warp) throws WarpNotFoundException, InvalidWorldException {
public Location getWarp(final String warp) throws WarpNotFoundException {
final EssentialsConfiguration conf = warpPoints.get(new StringIgnoreCase(warp));
if (conf == null) {
throw new WarpNotFoundException();
@ -79,7 +78,7 @@ public class Warps implements IConf, net.ess3.api.IWarps {
if (conf == null) {
final File confFile = new File(warpsFolder, filename + ".yml");
if (confFile.exists()) {
throw new Exception(user == null ? tlLiteral("similarWarpExist") : user.playerTl("similarWarpExist"));
throw new TranslatableException("similarWarpExist");
}
conf = new EssentialsConfiguration(confFile);
conf.load();

View File

@ -22,9 +22,8 @@ public interface IWarps extends IConf {
* @param warp - Warp name
* @return - Location the warp is set to
* @throws WarpNotFoundException When the warp is not found
* @throws net.ess3.api.InvalidWorldException When the world the warp is in is not found
*/
Location getWarp(String warp) throws WarpNotFoundException, net.ess3.api.InvalidWorldException;
Location getWarp(String warp) throws WarpNotFoundException;
/**
* Checks if the provided name is a warp.

View File

@ -1,20 +0,0 @@
package com.earth2me.essentials.api;
import net.ess3.api.TranslatableException;
/**
* @deprecated This exception is unused. Use {@link net.ess3.api.InvalidWorldException} instead.
*/
@Deprecated
public class InvalidWorldException extends TranslatableException {
private final String world;
public InvalidWorldException(final String world) {
super("invalidWorld");
this.world = world;
}
public String getWorld() {
return this.world;
}
}

View File

@ -3,6 +3,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.FormatUtil;
import com.google.common.collect.Lists;
import net.ess3.api.TranslatableException;
import org.bukkit.Server;
@ -53,7 +54,7 @@ public class Commandbroadcastworld extends EssentialsCommand {
if (message.isEmpty()) {
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", FormatUtil.replaceFormat(message).replace("\\n", "\n"), AdventureUtil.parsed(AdventureUtil.legacyToMini(name)));
}
@Override

View File

@ -6,6 +6,7 @@ import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.TranslatableException;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.entity.Player;
@ -80,7 +81,7 @@ public class Commandclearinventory extends EssentialsCommand {
}
}
protected void clearHandler(final CommandSource sender, final Player player, final String[] args, final int offset, final boolean showExtended) {
protected void clearHandler(final CommandSource sender, final Player player, final String[] args, final int offset, final boolean showExtended) throws TranslatableException {
ClearHandlerType type = ClearHandlerType.ALL_EXCEPT_ARMOR;
final Set<Item> items = new HashSet<>();
int amount = -1;
@ -124,6 +125,11 @@ public class Commandclearinventory extends EssentialsCommand {
stack.setDurability(item.getData());
}
// can't remove a negative amount of items. (it adds them)
if (amount < -1) {
throw new TranslatableException("cannotRemoveNegativeItems");
}
// amount -1 means all items will be cleared
if (amount == -1) {
final int removedAmount = Inventories.removeItemSimilar(player, stack, true);
@ -131,7 +137,6 @@ public class Commandclearinventory extends EssentialsCommand {
sender.sendTl("inventoryClearingStack", removedAmount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName());
}
} else {
stack.setAmount(amount < 0 ? 1 : amount);
if (Inventories.removeItemAmount(player, stack, amount)) {
sender.sendTl("inventoryClearingStack", amount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName());
} else {

View File

@ -18,6 +18,24 @@ public class Commanddelhome extends EssentialsCommand {
super("delhome");
}
private void deleteHome(CommandSource sender, User user, String home) {
final HomeModifyEvent event = new HomeModifyEvent(sender.getUser(), user, home, user.getHome(home), false);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("HomeModifyEvent canceled for /delhome execution by " + sender.getDisplayName());
}
return;
}
try {
user.delHome(home);
} catch (Exception e) {
sender.sendTl("invalidHome", home);
}
sender.sendTl("deleteHome", home);
}
@Override
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 1) {
@ -45,21 +63,19 @@ public class Commanddelhome extends EssentialsCommand {
name = expandedArg[0].toLowerCase(Locale.ENGLISH);
}
if (name.equals("bed")) {
throw new TranslatableException("invalidHomeName");
switch (name) {
case "bed":
throw new TranslatableException("invalidHomeName");
case "*":
final List<String> homes = user.getHomes();
for (String home : homes) {
deleteHome(sender, user, home);
}
break;
default:
deleteHome(sender, user, name);
break;
}
final HomeModifyEvent event = new HomeModifyEvent(sender.getUser(), user, name, user.getHome(name), false);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("HomeModifyEvent canceled for /delhome execution by " + sender.getDisplayName());
}
return;
}
user.delHome(name);
sender.sendTl("deleteHome", name);
}
@Override
@ -81,6 +97,7 @@ public class Commanddelhome extends EssentialsCommand {
return homes;
}
otherUser.getHomes().forEach(home -> homes.add(namePart + ":" + home));
homes.add(namePart + ":" + "*");
}
}
return homes;

View File

@ -14,7 +14,6 @@ import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
@ -35,7 +34,7 @@ public class Commandenchant extends EssentialsCommand {
if (args.length == 0) {
final Set<String> usableEnchants = new TreeSet<>();
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))) {
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);
stack.setItemMeta(metaStack.getItemStack().getItemMeta());
user.getBase().updateInventory();
final String enchantName = enchantment.getName().toLowerCase(Locale.ENGLISH).replace('_', ' ');
final String enchantName = Enchantments.getRealName(enchantment).replace('_', ' ');
if (level == 0) {
user.sendTl("enchantmentRemoved", enchantName);
} else {

View File

@ -10,10 +10,10 @@ import com.earth2me.essentials.userstorage.ModernUserMap;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.CommandMapUtil;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.FloatUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.PasteUtil;
import com.earth2me.essentials.utils.RegistryUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
@ -67,8 +67,8 @@ import static com.earth2me.essentials.I18n.tlLiteral;
// This command has 4 undocumented behaviours #EasterEgg
public class Commandessentials extends EssentialsCommand {
private static final Sound NOTE_HARP = EnumUtil.valueOf(Sound.class, "BLOCK_NOTE_BLOCK_HARP", "BLOCK_NOTE_HARP", "NOTE_PIANO");
private static final Sound MOO_SOUND = EnumUtil.valueOf(Sound.class, "COW_IDLE", "ENTITY_COW_MILK");
private static final Sound NOTE_HARP = RegistryUtil.valueOf(Sound.class, "BLOCK_NOTE_BLOCK_HARP", "BLOCK_NOTE_HARP", "NOTE_PIANO");
private static final Sound MOO_SOUND = RegistryUtil.valueOf(Sound.class, "COW_IDLE", "ENTITY_COW_MILK");
private static final String HOMES_USAGE = "/<command> homes (fix | delete [world])";

View File

@ -19,6 +19,7 @@ import org.bukkit.entity.Snowball;
import org.bukkit.entity.SplashPotion;
import org.bukkit.entity.ThrownExpBottle;
import org.bukkit.entity.Trident;
import org.bukkit.entity.WindCharge;
import org.bukkit.entity.WitherSkull;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.util.Vector;
@ -55,6 +56,10 @@ public class Commandfireball extends EssentialsCommand {
builder.put("trident", Trident.class);
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_21_R01)) {
builder.put("windcharge", WindCharge.class);
}
types = builder.build();
}

View File

@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.MetaItemStack;
import com.earth2me.essentials.MobCompat;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
@ -9,7 +10,6 @@ import net.ess3.api.TranslatableException;
import org.bukkit.DyeColor;
import org.bukkit.FireworkEffect;
import org.bukkit.Server;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Firework;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.FireworkMeta;
@ -81,7 +81,7 @@ public class Commandfirework extends EssentialsCommand {
}
}
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();
if (direction) {
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)) {
user.sendTl("cantGamemode", gameMode.name());
user.sendTl("cantGamemode", user.playerTl(gameMode.toString().toLowerCase(Locale.ENGLISH)));
return;
}

View File

@ -18,6 +18,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
public class Commandhelp extends EssentialsCommand {
public Commandhelp() {
@ -37,18 +38,25 @@ public class Commandhelp extends EssentialsCommand {
final String cmd = pageStr.substring(1);
for (final Map.Entry<String, Command> knownCmd : ess.getKnownCommandsProvider().getKnownCommands().entrySet()) {
if (knownCmd.getKey().equalsIgnoreCase(cmd)) {
final Command bukkit = knownCmd.getValue();
final boolean isEssCommand = bukkit instanceof PluginIdentifiableCommand && ((PluginIdentifiableCommand) bukkit).getPlugin().equals(ess);
final IEssentialsCommand essCommand = isEssCommand ? ess.getCommandMap().get(bukkit.getName()) : null;
user.sendTl("commandHelpLine1", cmd);
user.sendTl("commandHelpLine2", knownCmd.getValue().getDescription());
user.sendTl("commandHelpLine4", knownCmd.getValue().getAliases().toString());
String description = bukkit.getDescription();
if (essCommand != null) {
try {
description = user.playerTl(bukkit.getName() + "CommandDescription");
} catch (MissingResourceException ignored) {}
}
user.sendTl("commandHelpLine2", description);
user.sendTl("commandHelpLine4", bukkit.getAliases().toString());
user.sendTl("commandHelpLine3");
final boolean isEssCommand = knownCmd.getValue() instanceof PluginIdentifiableCommand && ((PluginIdentifiableCommand) knownCmd.getValue()).getPlugin().equals(ess);
final IEssentialsCommand essCommand = isEssCommand ? ess.getCommandMap().get(knownCmd.getValue().getName()) : null;
if (essCommand != null && !essCommand.getUsageStrings().isEmpty()) {
for (Map.Entry<String, String> usage : essCommand.getUsageStrings().entrySet()) {
user.sendTl("commandHelpLineUsage", AdventureUtil.parsed(usage.getKey().replace("<command>", cmd)), AdventureUtil.parsed(usage.getValue()));
}
} else {
user.sendMessage(knownCmd.getValue().getUsage());
user.sendMessage(bukkit.getUsage());
}
return;
}

View File

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

View File

@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.Mob;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.RegistryUtil;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.entity.Cat;
@ -21,8 +22,12 @@ public class Commandkittycannon extends EssentialsCommand {
private static Ocelot spawnOcelot(final Server server, final User user) throws Mob.MobException {
final Ocelot ocelot = (Ocelot) Mob.OCELOT.spawn(user.getWorld(), server, user.getBase().getEyeLocation());
final int i = random.nextInt(Ocelot.Type.values().length);
ocelot.setCatType(Ocelot.Type.values()[i]);
//noinspection deprecation
final Object[] values = RegistryUtil.values(Ocelot.Type.class);
final int i = random.nextInt(values.length);
//noinspection deprecation
ocelot.setCatType((Ocelot.Type) values[i]);
((Tameable) ocelot).setTamed(true);
ocelot.setBaby();
ocelot.setVelocity(user.getBase().getEyeLocation().getDirection().multiply(2));
@ -31,8 +36,10 @@ public class Commandkittycannon extends EssentialsCommand {
private static Entity spawnCat(final Server server, final User user) throws Mob.MobException {
final Cat cat = (Cat) Mob.CAT.spawn(user.getWorld(), server, user.getBase().getEyeLocation());
final int i = random.nextInt(Cat.Type.values().length);
cat.setCatType(Cat.Type.values()[i]);
final Object[] values = RegistryUtil.values(Cat.Type.class);
final int i = random.nextInt(values.length);
cat.setCatType((Cat.Type) values[i]);
cat.setTamed(true);
cat.setBaby();
cat.setVelocity(user.getBase().getEyeLocation().getDirection().multiply(2));

View File

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

View File

@ -3,10 +3,12 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.TranslatableException;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.FurnaceRecipe;
@ -131,7 +133,7 @@ public class Commandrecipe extends EssentialsCommand {
if (VersionUtil.PRE_FLATTENING && item.getDurability() == Short.MAX_VALUE) {
item.setDurability((short) 0);
}
view.getTopInventory().setItem(j * 3 + k + 1, item);
ess.getInventoryViewProvider().getTopInventory(view).setItem(j * 3 + k + 1, item);
}
}
} else {
@ -150,18 +152,28 @@ public class Commandrecipe extends EssentialsCommand {
materials[j][k] = item == null ? null : item.getType();
}
}
sender.sendTl("recipeGrid", colorMap.get(materials[0][0]), colorMap.get(materials[0][1]), colorMap.get(materials[0][2]));
sender.sendTl("recipeGrid", colorMap.get(materials[1][0]), colorMap.get(materials[1][1]), colorMap.get(materials[1][2]));
sender.sendTl("recipeGrid", colorMap.get(materials[2][0]), colorMap.get(materials[2][1]), colorMap.get(materials[2][2]));
sender.sendTl("recipeGrid", colorTag(colorMap, materials, 0, 0), colorTag(colorMap, materials, 0, 1), colorTag(colorMap, materials, 0, 2));
sender.sendTl("recipeGrid", colorTag(colorMap, materials, 1, 0), colorTag(colorMap, materials, 1, 1), colorTag(colorMap, materials, 1, 2));
sender.sendTl("recipeGrid", colorTag(colorMap, materials, 2, 0), colorTag(colorMap, materials, 2, 1), colorTag(colorMap, materials, 2, 2));
final StringBuilder s = new StringBuilder();
for (final Material items : colorMap.keySet().toArray(new Material[0])) {
s.append(sender.tl("recipeGridItem", colorMap.get(items), getMaterialName(sender, items)));
s.append(sender.tl("recipeGridItem", colorMap.get(items), getMaterialName(sender, items))).append(" ");
}
sender.sendTl("recipeWhere", s.toString());
sender.sendTl("recipeWhere", AdventureUtil.parsed(s.toString()));
}
}
private AdventureUtil.ParsedPlaceholder colorTag(final Map<Material, String> colorMap, final Material[][] materials, final int x, final int y) {
final char colorChar = colorMap.get(materials[x][y]).charAt(0);
final NamedTextColor namedTextColor = AdventureUtil.fromChar(colorChar);
if (namedTextColor == null) {
throw new IllegalStateException("Illegal amount of materials in recipe");
}
return AdventureUtil.parsed("<" + namedTextColor + ">" + colorChar);
}
public void shapelessRecipe(final CommandSource sender, final ShapelessRecipe recipe, final boolean showWindow) {
final List<ItemStack> ingredients = recipe.getIngredientList();
if (showWindow) {
@ -174,7 +186,7 @@ public class Commandrecipe extends EssentialsCommand {
if (VersionUtil.PRE_FLATTENING && item.getDurability() == Short.MAX_VALUE) {
item.setDurability((short) 0);
}
view.setItem(i + 1, item);
ess.getInventoryViewProvider().setItem(view, i + 1, item);
}
} else {

View File

@ -3,10 +3,12 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.RandomTeleport;
import com.earth2me.essentials.User;
import org.bukkit.Server;
import org.bukkit.World;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class Commandsettpr extends EssentialsCommand {
public Commandsettpr() {
@ -15,22 +17,20 @@ public class Commandsettpr extends EssentialsCommand {
@Override
protected 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();
}
final RandomTeleport randomTeleport = ess.getRandomTeleport();
randomTeleport.getCachedLocations().clear();
if ("center".equalsIgnoreCase(args[0])) {
randomTeleport.setCenter(user.getLocation());
if ("center".equalsIgnoreCase(args[1])) {
randomTeleport.setCenter(args[0], user.getLocation());
user.sendTl("settpr");
} else if (args.length > 1) {
if ("minrange".equalsIgnoreCase(args[0])) {
randomTeleport.setMinRange(Double.parseDouble(args[1]));
} else if ("maxrange".equalsIgnoreCase(args[0])) {
randomTeleport.setMaxRange(Double.parseDouble(args[1]));
} else if (args.length > 2) {
if ("minrange".equalsIgnoreCase(args[1])) {
randomTeleport.setMinRange(args[0], Double.parseDouble(args[2]));
} else if ("maxrange".equalsIgnoreCase(args[1])) {
randomTeleport.setMaxRange(args[0], Double.parseDouble(args[2]));
}
user.sendTl("settprValue", args[0].toLowerCase(), args[1].toLowerCase());
user.sendTl("settprValue", args[1].toLowerCase(), args[2].toLowerCase());
} else {
throw new NotEnoughArgumentsException();
}
@ -39,6 +39,8 @@ public class Commandsettpr extends EssentialsCommand {
@Override
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
if (args.length == 1) {
return user.getServer().getWorlds().stream().map(World::getName).collect(Collectors.toList());
} else if (args.length == 2) {
return Arrays.asList("center", "minrange", "maxrange");
}
return Collections.emptyList();

View File

@ -4,7 +4,6 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.api.IWarps;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import net.ess3.api.InvalidWorldException;
import net.ess3.api.TranslatableException;
import net.essentialsx.api.v2.events.WarpModifyEvent;
import org.bukkit.Bukkit;
@ -31,7 +30,7 @@ public class Commandsetwarp extends EssentialsCommand {
try {
warpLoc = warps.getWarp(args[0]);
} catch (final WarpNotFoundException | InvalidWorldException ignored) {
} catch (final WarpNotFoundException ignored) {
}
if (warpLoc == null) {
final WarpModifyEvent event = new WarpModifyEvent(user, args[0], null, user.getLocation(), WarpModifyEvent.WarpModifyCause.CREATE);

View File

@ -6,6 +6,7 @@ import com.earth2me.essentials.IUser;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.FormatUtil;
import org.bukkit.BanList;
import org.bukkit.Server;
@ -36,7 +37,7 @@ public class Commandtempban extends EssentialsCommand {
}
final String time = getFinalArg(args, 1);
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;
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 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;
if (maxBanLength > 0 && ((banTimestamp - GregorianCalendar.getInstance().getTimeInMillis()) > maxBanLength) && sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.tempban.unlimited")) {

View File

@ -1,8 +1,10 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.RandomTeleport;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.UserRandomTeleportEvent;
import org.bukkit.Server;
import org.bukkit.event.player.PlayerTeleportEvent;
@ -10,6 +12,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class Commandtpr extends EssentialsCommand {
@ -22,25 +25,67 @@ public class Commandtpr extends EssentialsCommand {
final Trade charge = new Trade(this.getName(), ess);
charge.isAffordableFor(user);
final RandomTeleport randomTeleport = ess.getRandomTeleport();
final UserRandomTeleportEvent event = new UserRandomTeleportEvent(user, randomTeleport.getCenter(), randomTeleport.getMinRange(), randomTeleport.getMaxRange());
final String defaultLocation = randomTeleport.getDefaultLocation().replace("{world}", user.getLocation().getWorld().getName());
final String name = args.length > 0 ? args[0] : defaultLocation;
final User userToTeleport = args.length > 1 && user.isAuthorized("essentials.tpr.others") ? getPlayer(server, user, args, 1) : user;
if (randomTeleport.isPerLocationPermission() && !user.isAuthorized("essentials.tpr.location." + name)) {
throw new TranslatableException("warpUsePermission");
}
final UserRandomTeleportEvent event = new UserRandomTeleportEvent(userToTeleport, name, randomTeleport.getCenter(name), randomTeleport.getMinRange(name), randomTeleport.getMaxRange(name));
server.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
randomTeleport.getRandomLocation(event.getCenter(), event.getMinRange(), event.getMaxRange()).thenAccept(location -> {
final CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
user.getAsyncTeleport().teleport(location, charge, PlayerTeleportEvent.TeleportCause.COMMAND, future);
future.thenAccept(success -> {
if (success) {
user.sendTl("tprSuccess");
}
});
});
(event.isModified() ? randomTeleport.getRandomLocation(event.getCenter(), event.getMinRange(), event.getMaxRange()) : randomTeleport.getRandomLocation(name))
.thenAccept(location -> {
final CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
future.thenAccept(success -> {
if (success) {
userToTeleport.sendTl("tprSuccess");
}
});
userToTeleport.getAsyncTeleport().teleport(location, charge, PlayerTeleportEvent.TeleportCause.COMMAND, future);
});
throw new NoChargeException();
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
protected void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 2) {
throw new NotEnoughArgumentsException();
}
final RandomTeleport randomTeleport = ess.getRandomTeleport();
final User userToTeleport = getPlayer(server, sender, args, 1);
final String name = args[0];
final UserRandomTeleportEvent event = new UserRandomTeleportEvent(userToTeleport, name, randomTeleport.getCenter(name), randomTeleport.getMinRange(name), randomTeleport.getMaxRange(name));
server.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
(event.isModified() ? randomTeleport.getRandomLocation(event.getCenter(), event.getMinRange(), event.getMaxRange()) : randomTeleport.getRandomLocation(name))
.thenAccept(location -> {
final CompletableFuture<Boolean> future = getNewExceptionFuture(sender, commandLabel);
future.thenAccept(success -> {
if (success) {
userToTeleport.sendTl("tprSuccess");
}
});
userToTeleport.getAsyncTeleport().now(location, false, PlayerTeleportEvent.TeleportCause.COMMAND, future);
});
}
@Override
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
final RandomTeleport randomTeleport = ess.getRandomTeleport();
if (args.length == 1) {
if (randomTeleport.isPerLocationPermission()) {
return randomTeleport.listLocations().stream().filter(name -> sender.isAuthorized("essentials.tpr.location." + name)).collect(Collectors.toList());
} else {
return randomTeleport.listLocations();
}
} else if (args.length == 2 && sender.isAuthorized("essentials.tpr.others")) {
return getPlayers(server, sender);
}
return Collections.emptyList();
}
}

View File

@ -6,6 +6,7 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.StringUtil;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.TranslatableException;
import org.bukkit.Server;
import org.bukkit.entity.Player;
@ -18,11 +19,11 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
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));
}
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()) {
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));
}
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()) {
throw new PlayerNotFoundException();
}
@ -143,6 +144,6 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
}
public interface UserConsumer {
void accept(User user) throws PlayerNotFoundException, NotEnoughArgumentsException, PlayerExemptException, ChargeException, MaxMoneyException;
void accept(User user) throws NotEnoughArgumentsException, TranslatableException;
}
}

View File

@ -13,7 +13,6 @@ import com.earth2me.essentials.config.serializers.LocationTypeSerializer;
import com.earth2me.essentials.config.serializers.MailMessageSerializer;
import com.earth2me.essentials.config.serializers.MaterialTypeSerializer;
import com.earth2me.essentials.utils.AdventureUtil;
import net.ess3.api.InvalidWorldException;
import net.essentialsx.api.v2.services.mail.MailMessage;
import org.bukkit.Location;
import org.bukkit.Material;
@ -123,7 +122,7 @@ public class EssentialsConfiguration {
setInternal(path, LazyLocation.fromLocation(location));
}
public LazyLocation getLocation(final String path) throws InvalidWorldException {
public LazyLocation getLocation(final String path) {
final CommentedConfigurationNode node = path == null ? getRootNode() : getSection(path);
if (node == null) {
return null;

View File

@ -243,6 +243,10 @@ public final class Inventories {
}
public static boolean removeItemAmount(final Player player, final ItemStack toRemove, int amount) {
if (amount < 0) {
throw new IllegalArgumentException("Amount cannot be negative.");
}
final List<Integer> clearSlots = new ArrayList<>();
final ItemStack[] items = player.getInventory().getContents();

View File

@ -1,5 +1,6 @@
package com.earth2me.essentials.items;
import com.earth2me.essentials.Enchantments;
import com.earth2me.essentials.IConf;
import com.earth2me.essentials.User;
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.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.plugin.Plugin;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect;
import java.util.ArrayList;
@ -220,7 +219,7 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
if (meta.hasEnchants()) {
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:
final EnchantmentStorageMeta enchantmentStorageMeta = (EnchantmentStorageMeta) is.getItemMeta();
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;
}
@ -285,16 +284,8 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
serializeEffectMeta(sb, fireworkEffectMeta.getEffect());
}
} else if (MaterialUtil.isPotion(material)) {
final boolean splash;
final Collection<PotionEffect> effects;
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();
}
final boolean splash = ess.getPotionMetaProvider().isSplashPotion(is);
final Collection<PotionEffect> effects = ess.getPotionMetaProvider().getCustomEffects(is);
for (final PotionEffect e : effects) {
// 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(" ");
}
for (final org.bukkit.block.banner.Pattern p : shieldBannerMeta.getPatterns()) {
//noinspection removal
final String type = p.getPattern().getIdentifier();
final int color = p.getColor().getColor().asRGB();
sb.append(type).append(",").append(color).append(" ");
@ -324,7 +316,7 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
} else {
final BannerMeta bannerMeta = (BannerMeta) is.getItemMeta();
if (bannerMeta != null) {
DyeColor baseDyeColor = bannerMeta.getBaseColor();
DyeColor baseDyeColor = ess.getBannerDataProvider().getBaseColor(is);
if (baseDyeColor == null) {
baseDyeColor = MaterialUtil.getColorOf(material);
}
@ -335,6 +327,7 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
sb.append("basecolor:").append(basecolor).append(" ");
}
for (final org.bukkit.block.banner.Pattern p : bannerMeta.getPatterns()) {
//noinspection removal
final String type = p.getPattern().getIdentifier();
final int color = p.getColor().getColor().asRGB();
sb.append(type).append(",").append(color).append(" ");

View File

@ -9,13 +9,14 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
import net.ess3.provider.PotionMetaProvider;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionType;
import java.util.ArrayList;
import java.util.Collection;
@ -23,6 +24,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@ -127,14 +129,14 @@ public class FlatItemDb extends AbstractItemDb {
final ItemStack stack = new ItemStack(material);
stack.setAmount(material.getMaxStackSize());
final PotionData potionData = data.getPotionData();
final ItemMeta meta = stack.getItemMeta();
final ItemData.EssentialPotionData potionData = data.getPotionData();
if (potionData != null && meta instanceof PotionMeta) {
final PotionMeta potionMeta = (PotionMeta) meta;
potionMeta.setBasePotionData(potionData);
if (potionData != null && stack.getItemMeta() instanceof PotionMeta) {
ess.getPotionMetaProvider().setBasePotionType(stack, potionData.getType(), potionData.isExtended(), potionData.isUpgraded());
}
final ItemMeta meta = stack.getItemMeta();
// 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.
if (split.length > 1 && meta instanceof Damageable) {
@ -200,14 +202,14 @@ public class FlatItemDb extends AbstractItemDb {
throw new UnsupportedOperationException("Legacy IDs aren't supported on this version.");
}
private ItemData lookup(final ItemStack item) {
final Material type = item.getType();
private ItemData lookup(final ItemStack is) {
final Material type = is.getType();
if (MaterialUtil.isPotion(type) && item.getItemMeta() instanceof PotionMeta) {
final PotionData potion = ((PotionMeta) item.getItemMeta()).getBasePotionData();
return new ItemData(type, potion);
if (MaterialUtil.isPotion(type) && is.getItemMeta() instanceof PotionMeta) {
final PotionMetaProvider provider = ess.getPotionMetaProvider();
return new ItemData(type, new ItemData.EssentialPotionData(provider.getBasePotionType(is), provider.isUpgraded(is), provider.isExtended(is)));
} else if (type.toString().contains("SPAWNER")) {
final EntityType entity = ess.getSpawnerItemProvider().getEntityType(item);
final EntityType entity = ess.getSpawnerItemProvider().getEntityType(is);
return new ItemData(type, entity);
} else {
return new ItemData(type);
@ -224,14 +226,14 @@ public class FlatItemDb extends AbstractItemDb {
public static class ItemData {
private Material material;
private String[] fallbacks = null;
private PotionData potionData = null;
private EssentialPotionData potionData = null;
private EntityType entity = null;
ItemData(final Material material) {
this.material = material;
}
ItemData(final Material material, final PotionData potionData) {
ItemData(final Material material, final EssentialPotionData potionData) {
this.material = material;
this.potionData = potionData;
}
@ -267,7 +269,7 @@ public class FlatItemDb extends AbstractItemDb {
return material;
}
public PotionData getPotionData() {
public EssentialPotionData getPotionData() {
return this.potionData;
}
@ -294,5 +296,51 @@ public class FlatItemDb extends AbstractItemDb {
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
&& !senderUser.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()) {
if (onlineUser.isSocialSpyEnabled()
// Don't send socialspy messages to message sender/receiver to prevent spam
&& !onlineUser.equals(senderUser)
&& !onlineUser.equals(recipient)) {
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 {
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

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

View File

@ -46,7 +46,7 @@ public class SignBuy extends EssentialsSign {
charge.isAffordableFor(player);
if (!items.pay(player)) {
throw new ChargeException("Inventory full"); //TODO: TL
throw new ChargeException("inventoryFull");
}
charge.charge(player);
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());
}
final String enchantmentName = enchantment.getName().toLowerCase(Locale.ENGLISH);
final String enchantmentName = Enchantments.getRealName(enchantment);
if (level == 0) {
player.sendTl("enchantmentRemoved", enchantmentName.replace('_', ' '));
} else {

View File

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

View File

@ -0,0 +1,32 @@
package com.earth2me.essentials.signs;
import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.RandomTeleport;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.concurrent.CompletableFuture;
public class SignRandomTeleport extends EssentialsSign {
public SignRandomTeleport() {
super("RandomTeleport");
}
@Override
protected boolean onSignInteract(ISign sign, User player, String username, IEssentials ess) throws SignException, ChargeException, MaxMoneyException {
final String name = sign.getLine(1);
final RandomTeleport randomTeleport = ess.getRandomTeleport();
randomTeleport.getRandomLocation(name).thenAccept(location -> {
final CompletableFuture<Boolean> future = new CompletableFuture<>();
future.thenAccept(success -> {
if (success) {
player.sendTl("tprSuccess");
}
});
player.getAsyncTeleport().now(location, false, PlayerTeleportEvent.TeleportCause.COMMAND, future);
});
return true;
}
}

View File

@ -6,6 +6,7 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.commands.Commandrepair;
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
public class SignRepair extends EssentialsSign {
public SignRepair() {
@ -42,6 +43,8 @@ public class SignRepair extends EssentialsSign {
throw new NotEnoughArgumentsException();
}
} catch (final TranslatableException ex) {
throw new SignException(ex.getTlKey(), ex.getArgs());
} catch (final Exception ex) {
throw new SignException(ex, "errorWithMessage", ex.getMessage());
}

View File

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

View File

@ -4,6 +4,7 @@ import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import net.ess3.api.TranslatableException;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.util.concurrent.CompletableFuture;
@ -25,6 +26,10 @@ public class SignWarp extends EssentialsSign {
try {
ess.getWarps().getWarp(warpName);
} catch (final Exception ex) {
if (ex instanceof TranslatableException) {
final TranslatableException te = (TranslatableException) ex;
throw new SignException(ex, te.getTlKey(), te.getArgs());
}
throw new SignException(ex, "errorWithMessage", ex.getMessage());
}
final String group = sign.getLine(2);

View File

@ -25,7 +25,8 @@ public enum Signs {
TRADE(new SignTrade()),
WARP(new SignWarp()),
WEATHER(new SignWeather()),
WORKBENCH(new SignWorkbench());
WORKBENCH(new SignWorkbench()),
RANDOMTELEPORT(new SignRandomTeleport());
private final EssentialsSign sign;
Signs(final EssentialsSign sign) {

View File

@ -50,7 +50,7 @@ public final class AdventureUtil {
}
LEGACY_SERIALIZER = builder.build();
MINI_MESSAGE_NO_TAGS = MiniMessage.miniMessage();
MINI_MESSAGE_NO_TAGS = MiniMessage.builder().strict(true).build();
miniMessageInstance = createMiniMessageInstance();
}

View File

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

View File

@ -0,0 +1,70 @@
package com.earth2me.essentials.utils;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public final class RegistryUtil {
private static final Table<Class<?>, String, Object> registryCache = HashBasedTable.create();
private RegistryUtil() {
}
public static <T> Object[] values(Class<T> registry) {
if (registry.getEnumConstants() != null) {
return registry.getEnumConstants();
}
//noinspection unchecked
final T[] values = (T[]) registryCache.get(registry, "$values");
if (values != null) {
return values;
}
final List<T> set = new ArrayList<>();
for (final Field field : registry.getDeclaredFields()) {
try {
final Object value = field.get(null);
if (value != null && registry.isAssignableFrom(value.getClass())) {
//noinspection unchecked
set.add((T) value);
}
} catch (NullPointerException | IllegalAccessException ignored) {
}
}
//noinspection unchecked
final T[] array = (T[]) new Object[set.size()];
for (int i = 0; i < set.size(); i++) {
array[i] = set.get(i);
}
registryCache.put(registry, "$values", array);
return array;
}
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,11 @@ 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_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_6_R01 = BukkitVersion.fromString("1.20.6-R0.1-SNAPSHOT");
public static final BukkitVersion v1_21_R01 = BukkitVersion.fromString("1.21-R0.1-SNAPSHOT");
public static final BukkitVersion v1_21_3_R01 = BukkitVersion.fromString("1.21.3-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_3_R01);
public static final boolean PRE_FLATTENING = VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01);

View File

@ -1,18 +0,0 @@
package net.ess3.api;
/**
* Fired when trying to teleport a user to an invalid world. This usually only occurs if a world has been removed from
* the server and a player tries to teleport to a warp or home in that world.
*/
public class InvalidWorldException extends TranslatableException {
private final String world;
public InvalidWorldException(final String world) {
super("invalidWorld");
this.world = world;
}
public String getWorld() {
return this.world;
}
}

View File

@ -14,14 +14,17 @@ public class UserRandomTeleportEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final IUser user;
private String name;
private Location center;
private double minRange;
private double maxRange;
private boolean cancelled = false;
private boolean modified = false;
public UserRandomTeleportEvent(final IUser user, final Location center, final double minRange, final double maxRange) {
public UserRandomTeleportEvent(final IUser user, final String name, final Location center, final double minRange, final double maxRange) {
super(!Bukkit.isPrimaryThread());
this.user = user;
this.name = name;
this.center = center;
this.minRange = minRange;
this.maxRange = maxRange;
@ -35,11 +38,23 @@ public class UserRandomTeleportEvent extends Event implements Cancellable {
return user;
}
public String getName() {
return name;
}
public Location getCenter() {
return center;
}
/**
* Sets the center location to teleport from.
*
* @param center Center location.
*/
public void setCenter(final Location center) {
if (!this.center.equals(center)) {
modified = true;
}
this.center = center;
}
@ -47,7 +62,15 @@ public class UserRandomTeleportEvent extends Event implements Cancellable {
return minRange;
}
/**
* Sets the minimum range for the teleport.
*
* @param minRange Minimum range.
*/
public void setMinRange(final double minRange) {
if (this.minRange != minRange) {
modified = true;
}
this.minRange = minRange;
}
@ -55,7 +78,15 @@ public class UserRandomTeleportEvent extends Event implements Cancellable {
return maxRange;
}
/**
* Sets the maximum range for the teleport.
*
* @param maxRange Maximum range.
*/
public void setMaxRange(final double maxRange) {
if (this.maxRange != maxRange) {
modified = true;
}
this.maxRange = maxRange;
}
@ -69,6 +100,10 @@ public class UserRandomTeleportEvent extends Event implements Cancellable {
cancelled = b;
}
public boolean isModified() {
return modified;
}
@Override
public HandlerList getHandlers() {
return handlers;

View File

@ -213,6 +213,10 @@ socialspy-listen-muted-players: true
# If false, social spy will only monitor commands from the list above.
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.
# If you use another plugin to control speed and flight, you should change these to false.
@ -383,6 +387,7 @@ enabledSigns:
#- loom
#- smithing
#- workbench
#- randomteleport
# How many times per second can Essentials signs be interacted with per player.
# Values should be between 1-20, 20 being virtually no lag protection.
@ -931,7 +936,7 @@ chat:
# If you are using group formats make sure to remove the '#' to allow the setting to be read.
# Note: Group names are case-sensitive so you must match them up with your permission plugin.
# You can use permissions to control whether players can use formatting codes in their chat messages.
# See https://essentialsx.net/wiki/Color-Permissions.html for more information.
@ -1193,6 +1198,12 @@ respawn-at-home-bed: true
# When users die, should EssentialsSpawn respect users' respawn anchors?
respawn-at-anchor: false
# If configured, users will spawn at the random spawn location instead of the newbies spawnpoint.
random-spawn-location: "none"
# If configured, when users die, they will respawn at the random respawn location.
random-respawn-location: "none"
# Teleport all joining players to the spawnpoint
spawn-on-join: false
# The following value of `guests` states that all players in group `guests` will be teleported to spawn when joining.

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
# Configuration for the random teleport command.
# Some settings may be defaulted, and can be changed via the /settpr command in-game.
min-range: 0.0
default-location: '{world}'
excluded-biomes:
- cold_ocean
- deep_cold_ocean

View File

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

View File

@ -4,15 +4,15 @@ plugins {
dependencies {
compileOnly project(':EssentialsX')
implementation('net.dv8tion:JDA:5.0.0-beta.12') {
implementation('net.dv8tion:JDA:5.1.2') {
exclude(module: 'opus-java')
}
implementation 'com.github.MinnDevelopment:emoji-java:v6.1.0'
implementation('club.minnced:discord-webhooks:0.8.2') {
implementation('club.minnced:discord-webhooks:0.8.4') {
exclude(module: 'okhttp')
}
compileOnly 'org.apache.logging.log4j:log4j-core:2.17.1'
compileOnly 'me.clip:placeholderapi:2.10.9'
compileOnly 'me.clip:placeholderapi:2.11.6'
}
shadowJar {
@ -24,7 +24,7 @@ shadowJar {
include(dependency('com.squareup.okio:okio'))
include(dependency('com.squareup.okio:okio-jvm'))
include(dependency('org.apache.commons:commons-collections4'))
include(dependency('net.sf.trove4j:trove4j'))
include(dependency('net.sf.trove4j:core'))
include(dependency('com.fasterxml.jackson.core:jackson-databind'))
include(dependency('com.fasterxml.jackson.core:jackson-core'))
include(dependency('com.fasterxml.jackson.core:jackson-annotations'))

View File

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

View File

@ -12,6 +12,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.util.List;
@ -64,6 +65,9 @@ class EssentialsSpawnPlayerListener implements Listener {
return;
}
}
if (tryRandomTeleport(user, ess.getSettings().getRandomRespawnLocation())) {
return;
}
final Location spawn = spawns.getSpawn(user.getGroup());
if (spawn != null) {
event.setRespawnLocation(spawn);
@ -102,7 +106,9 @@ class EssentialsSpawnPlayerListener implements Listener {
final User user = ess.getUser(player);
if (!"none".equalsIgnoreCase(ess.getSettings().getNewbieSpawn())) {
final boolean spawnRandomly = tryRandomTeleport(user, ess.getSettings().getRandomSpawnLocation());
if (!spawnRandomly && !"none".equalsIgnoreCase(ess.getSettings().getNewbieSpawn())) {
ess.scheduleSyncDelayedTask(new NewPlayerTeleport(user), 1L);
}
@ -158,4 +164,15 @@ class EssentialsSpawnPlayerListener implements Listener {
}
}
}
private boolean tryRandomTeleport(final User user, final String name) {
if (!ess.getRandomTeleport().hasLocation(name)) {
return false;
}
ess.getRandomTeleport().getRandomLocation(name).thenAccept(location -> {
final CompletableFuture<Boolean> future = new CompletableFuture<>();
user.getAsyncTeleport().now(location, false, PlayerTeleportEvent.TeleportCause.PLUGIN, future);
});
return true;
}
}

View File

@ -1,13 +1,10 @@
package com.earth2me.essentials.xmpp;
import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.commands.EssentialsLoopCommand;
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
import com.earth2me.essentials.commands.PlayerExemptException;
import com.earth2me.essentials.commands.PlayerNotFoundException;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.TranslatableException;
import org.bukkit.Server;
public class Commandxmppspy extends EssentialsLoopCommand {
@ -16,7 +13,7 @@ public class Commandxmppspy extends EssentialsLoopCommand {
}
@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) {
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
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,
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.3.**
* **EssentialsX currently requires Java 8 or higher.** We recommend using the latest Java version supported by your
server software.
* **EssentialsX requires [Vault](http://dev.bukkit.org/bukkit-plugins/vault/) to enable using chat prefix/suffixes and

View File

@ -8,6 +8,6 @@ repositories {
dependencies {
implementation("net.kyori", "indra-common", "3.1.3")
implementation("com.github.johnrengelman", "shadow", "8.1.1")
implementation("xyz.jpenilla", "run-task", "2.2.3")
implementation("com.gradleup.shadow", "shadow-gradle-plugin", "8.3.3")
implementation("xyz.jpenilla", "run-task", "2.3.1")
}

View File

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

View File

@ -10,7 +10,7 @@ plugins {
val baseExtension = extensions.create<EssentialsBaseExtension>("essentials", project)
val checkstyleVersion = "8.36.2"
val spigotVersion = "1.20.4-R0.1-SNAPSHOT"
val spigotVersion = "1.21.3-R0.1-SNAPSHOT"
val junit5Version = "5.10.2"
val mockitoVersion = "3.12.4"
@ -75,6 +75,9 @@ tasks {
}
withType<Jar> {
archiveVersion.set(rootProject.ext["FULL_VERSION"] as String)
manifest {
attributes("paperweight-mappings-namespace" to "mojang")
}
}
withType<Sign> {
onlyIf { project.hasProperty("forceSign") }
@ -122,7 +125,7 @@ indra {
javaVersions {
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
strictVersions(false)
}

View File

@ -1,6 +1,6 @@
plugins {
id("essentials.module-conventions")
id("com.github.johnrengelman.shadow")
id("com.gradleup.shadow")
}
tasks {
@ -8,7 +8,7 @@ tasks {
archiveClassifier.set("unshaded")
}
shadowJar {
archiveClassifier.set(null)
archiveClassifier.set(null as String?)
}
}

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

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

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,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.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionType;
import java.util.Collection;
public interface PotionMetaProvider extends Provider {
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,71 +0,0 @@
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.PotionType;
import java.util.Map;
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;
}
@Override
public String getDescription() {
return "1.9+ Potion Meta Provider";
}
}

View File

@ -1,20 +0,0 @@
package net.ess3.provider.providers;
import net.ess3.provider.PotionMetaProvider;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
@SuppressWarnings("deprecation")
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;
}
@Override
public String getDescription() {
return "Legacy 1.8 Potion Meta Provider";
}
}

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_19_R1 = NMSVersion.fromString("v1_19_R1");
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 Table<Class<?>, String, Method> methodCache = HashBasedTable.create();
private static final Table<Class<?>, MethodParams, Method> methodParamCache = HashBasedTable.create();

View File

@ -16,7 +16,9 @@ public class ReflServerStateProvider implements ServerStateProvider {
MethodHandle isRunning = null;
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";
} else if (ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_19_R1)) {
MDFIVEMAGICLETTER = "u";

View File

@ -1,6 +1,6 @@
plugins {
id("essentials.base-conventions")
id("com.github.johnrengelman.shadow")
id("com.gradleup.shadow")
}
java {