Merge branch '2.x' into build/junit-results-actions

This commit is contained in:
MD 2024-02-24 14:57:59 +00:00 committed by GitHub
commit 3881967d18
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 140 additions and 33 deletions

View File

@ -60,6 +60,7 @@ 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.ContainerProvider;
import net.ess3.provider.DamageEventProvider;
import net.ess3.provider.FormattedCommandAliasProvider;
import net.ess3.provider.ItemUnbreakableProvider;
import net.ess3.provider.KnownCommandsProvider;
@ -83,10 +84,12 @@ 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.LegacyDamageEventProvider;
import net.ess3.provider.providers.LegacyItemUnbreakableProvider;
import net.ess3.provider.providers.LegacyPlayerLocaleProvider;
import net.ess3.provider.providers.LegacyPotionMetaProvider;
import net.ess3.provider.providers.LegacySpawnEggProvider;
import net.ess3.provider.providers.ModernDamageEventProvider;
import net.ess3.provider.providers.ModernDataWorldInfoProvider;
import net.ess3.provider.providers.ModernItemUnbreakableProvider;
import net.ess3.provider.providers.ModernPersistentDataProvider;
@ -193,6 +196,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private transient WorldInfoProvider worldInfoProvider;
private transient PlayerLocaleProvider playerLocaleProvider;
private transient SignDataProvider signDataProvider;
private transient DamageEventProvider damageEventProvider;
private transient Kits kits;
private transient RandomTeleport randomTeleport;
private transient UpdateChecker updateChecker;
@ -475,6 +479,12 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
playerLocaleProvider = new LegacyPlayerLocaleProvider();
}
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_4_R01)) {
damageEventProvider = new ModernDamageEventProvider();
} else {
damageEventProvider = new LegacyDamageEventProvider();
}
execTimer.mark("Init(Providers)");
reload();
@ -625,6 +635,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
public void reload() {
Trade.closeLog();
if (bukkitAudience != null) {
bukkitAudience.close();
bukkitAudience = null;
}
for (final IConf iConf : confList) {
iConf.reloadConfig();
execTimer.mark("Reload(" + iConf.getClass().getSimpleName() + ")");
@ -863,7 +878,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
sender.sendMessage(command.getUsage().replace("<command>", commandLabel));
}
if (!ex.getMessage().isEmpty()) {
sender.sendMessage(ex.getMessage());
sender.sendComponent(AdventureUtil.miniMessage().deserialize(ex.getMessage()));
}
if (ex.getCause() != null && settings.isDebug()) {
ex.getCause().printStackTrace();
@ -1405,6 +1420,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
return playerLocaleProvider;
}
@Override
public DamageEventProvider getDamageEventProvider() {
return damageEventProvider;
}
@Override
public SignDataProvider getSignDataProvider() {
return signDataProvider;

View File

@ -10,6 +10,7 @@ import com.earth2me.essentials.updatecheck.UpdateChecker;
import com.earth2me.essentials.userstorage.IUserMap;
import net.ess3.nms.refl.providers.ReflOnlineModeProvider;
import net.ess3.provider.ContainerProvider;
import net.ess3.provider.DamageEventProvider;
import net.ess3.provider.FormattedCommandAliasProvider;
import net.ess3.provider.ItemUnbreakableProvider;
import net.ess3.provider.KnownCommandsProvider;
@ -183,5 +184,7 @@ public interface IEssentials extends Plugin {
PlayerLocaleProvider getPlayerLocaleProvider();
DamageEventProvider getDamageEventProvider();
PluginCommand getPluginCommand(String cmd);
}

View File

@ -16,6 +16,7 @@ import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.TranslatableException;
import net.ess3.api.events.AfkStatusChangeEvent;
import net.ess3.api.events.JailStatusChangeEvent;
import net.ess3.api.events.MuteStatusChangeEvent;
@ -225,7 +226,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
cooldownTime.add(Calendar.SECOND, (int) cooldown);
cooldownTime.add(Calendar.MILLISECOND, (int) ((cooldown * 1000.0) % 1000.0));
if (cooldownTime.after(now) && !isAuthorized("essentials.heal.cooldown.bypass")) {
throw new Exception(playerTl("timeBeforeHeal", DateUtil.formatDateDiff(cooldownTime.getTimeInMillis())));
throw new TranslatableException("timeBeforeHeal", DateUtil.formatDateDiff(cooldownTime.getTimeInMillis()));
}
}
setLastHealTimestamp(now.getTimeInMillis());

View File

@ -39,7 +39,7 @@ public class Commandbroadcastworld extends EssentialsCommand {
@Override
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
if (args.length < 2) {
throw new NotEnoughArgumentsException("world");
throw new NotEnoughArgumentsException();
}
final World world = ess.getWorld(args[0]);

View File

@ -29,8 +29,7 @@ public class Commandkill extends EssentialsLoopCommand {
if (sender.isPlayer() && user.isAuthorized("essentials.kill.exempt") && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.kill.force")) {
throw new PlayerExemptException("killExempt", matchPlayer.getDisplayName());
}
final EntityDamageEvent ede = new EntityDamageEvent(matchPlayer, sender.isPlayer() && sender.getPlayer().getName().equals(matchPlayer.getName()) ? EntityDamageEvent.DamageCause.SUICIDE : EntityDamageEvent.DamageCause.CUSTOM, Float.MAX_VALUE);
server.getPluginManager().callEvent(ede);
final EntityDamageEvent ede = ess.getDamageEventProvider().callDamageEvent(matchPlayer, sender.isPlayer() && sender.getPlayer().getName().equals(matchPlayer.getName()) ? EntityDamageEvent.DamageCause.SUICIDE : EntityDamageEvent.DamageCause.CUSTOM, Float.MAX_VALUE);
if (ede.isCancelled() && sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.kill.force")) {
return;
}

View File

@ -14,13 +14,12 @@ public class Commandsuicide extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final EntityDamageEvent ede = new EntityDamageEvent(user.getBase(), EntityDamageEvent.DamageCause.SUICIDE, Float.MAX_VALUE);
server.getPluginManager().callEvent(ede);
final EntityDamageEvent ede = ess.getDamageEventProvider().callDamageEvent(user.getBase(), EntityDamageEvent.DamageCause.SUICIDE, Float.MAX_VALUE);
ede.getEntity().setLastDamageCause(ede);
user.getBase().setHealth(0);
user.sendTl("suicideMessage");
user.setDisplayNick();
ess.broadcastTl(user, "suicideSuccess", user.getDisplayName());
ess.broadcastTl(user, "suicideSuccess", new Object[]{user.getDisplayName()});
}
@Override

View File

@ -1,6 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.DescParseTickFormat;
import com.earth2me.essentials.utils.NumberUtil;
import com.google.common.collect.Lists;
@ -95,12 +96,12 @@ public class Commandtime extends EssentialsCommand {
private void getWorldsTime(final CommandSource sender, final Collection<World> worlds) {
if (worlds.size() == 1) {
final Iterator<World> iter = worlds.iterator();
sender.sendMessage(DescParseTickFormat.format(iter.next().getTime()));
sender.sendComponent(AdventureUtil.miniMessage().deserialize(DescParseTickFormat.format(iter.next().getTime())));
return;
}
for (final World world : worlds) {
sender.sendTl("timeWorldCurrent", world.getName(), DescParseTickFormat.format(world.getTime()));
sender.sendTl("timeWorldCurrent", world.getName(), AdventureUtil.parsed(DescParseTickFormat.format(world.getTime())));
}
}

View File

@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.AdventureUtil;
import net.ess3.api.TranslatableException;
import org.bukkit.Material;
import org.bukkit.Server;
@ -29,7 +30,7 @@ public class Commandunlimited extends EssentialsCommand {
}
if (args[0].equalsIgnoreCase("list")) {
user.sendMessage(getList(user, target));
user.sendComponent(AdventureUtil.miniMessage().deserialize(getList(user, target)));
} else if (args[0].equalsIgnoreCase("clear")) {
for (final Material m : new HashSet<>(target.getUnlimited())) {
if (m == null) {
@ -56,7 +57,7 @@ public class Commandunlimited extends EssentialsCommand {
}
joiner.add(material.toString().toLowerCase(Locale.ENGLISH).replace("_", ""));
}
output.append(joiner.toString());
output.append(joiner);
return output.toString();
}

View File

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

View File

@ -125,6 +125,13 @@ public final class AdventureUtil {
return COLORS[index];
}
/**
* Convenience method for submodules to escape MiniMessage tags.
*/
public static String escapeTags(final String input) {
return miniMessage().escapeTags(input);
}
/**
* Parameters for a translation message are not parsed for MiniMessage by default to avoid injection. If you want
* a parameter to be parsed for MiniMessage you must wrap it in a ParsedPlaceholder by using this method.

View File

@ -227,8 +227,10 @@ public abstract class AbstractChatHandler {
server.getPluginManager().callEvent(spyEvent);
if (!spyEvent.isCancelled()) {
final String legacyString = AdventureUtil.miniToLegacy(String.format(spyEvent.getFormat(), AdventureUtil.legacyToMini(user.getDisplayName()), AdventureUtil.escapeTags(spyEvent.getMessage())));
for (final Player onlinePlayer : spyEvent.getRecipients()) {
onlinePlayer.sendMessage(String.format(spyEvent.getFormat(), user.getDisplayName(), spyEvent.getMessage()));
onlinePlayer.sendMessage(legacyString);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,8 +11,8 @@ val baseExtension = extensions.create<EssentialsBaseExtension>("essentials", pro
val checkstyleVersion = "8.36.2"
val spigotVersion = "1.20.4-R0.1-SNAPSHOT"
val junit5Version = "5.7.0"
val mockitoVersion = "3.2.0"
val junit5Version = "5.10.2"
val mockitoVersion = "3.12.4"
dependencies {
testImplementation("org.junit.jupiter", "junit-jupiter", junit5Version)
@ -26,6 +26,12 @@ dependencies {
}
}
tasks.test {
testLogging {
events("PASSED", "SKIPPED", "FAILED")
}
}
afterEvaluate {
if (baseExtension.injectBukkitApi.get()) {
dependencies {

View File

@ -0,0 +1,19 @@
package net.ess3.provider.providers;
import net.ess3.provider.DamageEventProvider;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent;
public class LegacyDamageEventProvider implements DamageEventProvider {
@Override
public EntityDamageEvent callDamageEvent(Player player, EntityDamageEvent.DamageCause cause, double damage) {
final EntityDamageEvent ede = new EntityDamageEvent(player, cause, damage);
player.getServer().getPluginManager().callEvent(ede);
return ede;
}
@Override
public String getDescription() {
return "Legacy Damage Event Provider";
}
}

View File

@ -0,0 +1,8 @@
package net.ess3.provider;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent;
public interface DamageEventProvider extends Provider {
EntityDamageEvent callDamageEvent(Player player, EntityDamageEvent.DamageCause cause, double damage);
}

View File

@ -0,0 +1,24 @@
package net.ess3.provider.providers;
import net.ess3.provider.DamageEventProvider;
import org.bukkit.damage.DamageSource;
import org.bukkit.damage.DamageType;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent;
@SuppressWarnings("UnstableApiUsage")
public class ModernDamageEventProvider implements DamageEventProvider {
private final DamageSource MAGIC_SOURCE = DamageSource.builder(DamageType.MAGIC).build();
@Override
public EntityDamageEvent callDamageEvent(Player player, EntityDamageEvent.DamageCause cause, double damage) {
final EntityDamageEvent ede = new EntityDamageEvent(player, cause, MAGIC_SOURCE, damage);
player.getServer().getPluginManager().callEvent(ede);
return ede;
}
@Override
public String getDescription() {
return "1.20.4+ Damage Event Provider";
}
}