Add advancement message type

This commit is contained in:
Josh Roy 2021-07-04 21:57:13 -04:00
parent 0a0416ae38
commit 3bc58264ea
9 changed files with 270 additions and 5 deletions

View File

@ -58,11 +58,12 @@ public final class MessageType {
public final static MessageType CHAT = new MessageType("chat", true);
public final static MessageType DEATH = new MessageType("death", true);
public final static MessageType AFK = new MessageType("afk", true);
public final static MessageType ADVANCEMENT = new MessageType("advancement", true);
public final static MessageType SERVER_START = new MessageType("server-start", false);
public final static MessageType SERVER_STOP = new MessageType("server-stop", false);
public final static MessageType KICK = new MessageType("kick", false);
public final static MessageType MUTE = new MessageType("mute", false);
private final static MessageType[] VALUES = new MessageType[]{JOIN, LEAVE, CHAT, DEATH, AFK, SERVER_START, SERVER_STOP, KICK, MUTE};
private final static MessageType[] VALUES = new MessageType[]{JOIN, LEAVE, CHAT, DEATH, AFK, ADVANCEMENT, SERVER_START, SERVER_STOP, KICK, MUTE};
/**
* Gets an array of all the default {@link MessageType MessageTypes}.

View File

@ -277,6 +277,18 @@ public class DiscordSettings implements IConf {
"username", "displayname");
}
public MessageFormat getAdvancementFormat(Player player) {
final String format = getFormatString("advancement");
final String filled;
if (plugin.isPAPI() && format != null) {
filled = me.clip.placeholderapi.PlaceholderAPI.setPlaceholders(player, format);
} else {
filled = format;
}
return generateMessageFormat(filled, ":medal: {displayname} has completed the advancement **{advancement}**!", false,
"username", "displayname", "advancement");
}
public String getStartMessage() {
return config.getString("messages.server-start", ":white_check_mark: The server has started!");
}

View File

@ -5,6 +5,7 @@ import club.minnced.discord.webhook.WebhookClientBuilder;
import club.minnced.discord.webhook.send.WebhookMessage;
import club.minnced.discord.webhook.send.WebhookMessageBuilder;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Guild;
@ -13,6 +14,8 @@ import net.dv8tion.jda.api.entities.Webhook;
import net.dv8tion.jda.api.events.ShutdownEvent;
import net.dv8tion.jda.api.hooks.EventListener;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.ess3.nms.refl.providers.AchievementListenerProvider;
import net.ess3.nms.refl.providers.AdvancementListenerProvider;
import net.essentialsx.api.v2.events.discord.DiscordMessageEvent;
import net.essentialsx.api.v2.services.discord.DiscordService;
import net.essentialsx.api.v2.services.discord.InteractionController;
@ -181,6 +184,17 @@ public class JDADiscordService implements DiscordService {
updateTypesRelay();
Bukkit.getPluginManager().registerEvents(new BukkitListener(this), plugin);
try {
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_12_0_R01)) {
Bukkit.getPluginManager().registerEvents(new AdvancementListenerProvider(), plugin);
} else {
Bukkit.getPluginManager().registerEvents(new AchievementListenerProvider(), plugin);
}
} catch (final Throwable e) {
logger.log(Level.WARNING, "Error while loading the achievement/advancement listener. You will not receive achievement/advancement notifications on Discord.", e);
}
getPlugin().getEss().scheduleSyncDelayedTask(() -> DiscordUtil.dispatchDiscordMessage(JDADiscordService.this, MessageType.DefaultTypes.SERVER_START, getSettings().getStartMessage(), true, null, null, null));
Bukkit.getServicesManager().register(DiscordService.class, this, plugin, ServicePriority.Normal);

View File

@ -7,6 +7,7 @@ import net.ess3.api.IUser;
import net.ess3.api.events.AfkStatusChangeEvent;
import net.ess3.api.events.MuteStatusChangeEvent;
import net.ess3.api.events.VanishStatusChangeEvent;
import net.ess3.provider.AbstractAchievementEvent;
import net.essentialsx.api.v2.events.AsyncUserDataLoadEvent;
import net.essentialsx.api.v2.events.discord.DiscordChatMessageEvent;
import net.essentialsx.api.v2.events.discord.DiscordMessageEvent;
@ -181,6 +182,23 @@ public class BukkitListener implements Listener {
event.getAffected().getBase().getUniqueId());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onAdvancement(AbstractAchievementEvent event) {
if (isVanishHide(event.getPlayer())) {
return;
}
sendDiscordMessage(MessageType.DefaultTypes.ADVANCEMENT,
MessageUtil.formatMessage(jda.getSettings().getAdvancementFormat(event.getPlayer()),
MessageUtil.sanitizeDiscordMarkdown(event.getPlayer().getName()),
MessageUtil.sanitizeDiscordMarkdown(event.getPlayer().getDisplayName()),
event.getName()),
false,
jda.getSettings().isShowAvatar() ? AVATAR_URL.replace("{uuid}", event.getPlayer().getUniqueId().toString()) : null,
jda.getSettings().isShowName() ? event.getPlayer().getName() : null,
event.getPlayer().getUniqueId());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onKick(PlayerKickEvent event) {
if (isVanishHide(event.getPlayer())) {

View File

@ -110,6 +110,8 @@ message-types:
death: primary
# AFK status change messages sent when a player's AFK status changes.
afk: primary
# Achievement/advancement messages sent when a player is awarded an achievement/advancement.
advancement: primary
# Message sent when the server starts up.
server-start: primary
# Message sent when the server shuts down.
@ -296,10 +298,6 @@ messages:
# - {deathmessage}: The full default death message used in game
# ... PlaceholderAPI placeholders are also supported here too!
death: ":skull: {deathmessage}"
# This is the message sent to discord when the server starts.
server-start: ":white_check_mark: The server has started!"
# This is the message sent to discord when the server stops.
server-stop: ":octagonal_sign: The server has stopped!"
# This is the message sent to discord when a player becomes afk.
# The following placeholders can be used here:
# - {username}: The name of the user who became afk
@ -312,6 +310,17 @@ messages:
# - {displayname}: The display name of the user who is no longer afk
# ... PlaceholderAPI placeholders are also supported here too!
un-afk: ":keyboard: {displayname} is no longer AFK!"
# This is the message sent to Discord when a player is awarded an advancement.
# The following placeholders can be used here:
# - {username}: The name of the user who was awarded the advancement.
# - {displayname}: The display name of the user who was awarded the advancement.
# - {advancement}: The name of the advancement.
# ... PlaceholderAPI placeholders are also supported here too!
advancement: ":medal: {displayname} has completed the advancement **{advancement}**!"
# This is the message sent to discord when the server starts.
server-start: ":white_check_mark: The server has started!"
# This is the message sent to discord when the server stops.
server-stop: ":octagonal_sign: The server has stopped!"
# This is the message sent to discord when a player is kicked from the server.
# The following placeholders can be used here:
# - {username}: The name of the user who got kicked

View File

@ -0,0 +1,34 @@
package net.ess3.provider;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class AbstractAchievementEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private final Player player;
private final String name;
public AbstractAchievementEvent(Player player, String name) {
this.player = player;
this.name = name;
}
public Player getPlayer() {
return player;
}
public String getName() {
return name;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -61,6 +61,10 @@ public final class ReflUtil {
return nmsVersionObject;
}
public static boolean isMojMap() {
return getNmsVersionObject().getMajor() == 99;
}
public static Class<?> getNMSClass(final String className) {
return getClassCached("net.minecraft.server" + (ReflUtil.getNmsVersionObject().isLowerThan(ReflUtil.V1_17_R1) ? "." + getNMSVersion() : "") + "." + className);
}

View File

@ -0,0 +1,127 @@
package net.ess3.nms.refl.providers;
import net.ess3.provider.AbstractAchievementEvent;
import org.bukkit.Achievement;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerAchievementAwardedEvent;
@SuppressWarnings("deprecation")
public class AchievementListenerProvider implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onAchievement(final PlayerAchievementAwardedEvent event) {
Bukkit.getPluginManager().callEvent(new AbstractAchievementEvent(event.getPlayer(), getAchievementName(event.getAchievement())));
}
private String getAchievementName(final Achievement achievement) {
switch (achievement) {
case OPEN_INVENTORY: {
return "Taking Inventory";
}
case MINE_WOOD: {
return "Getting Wood";
}
case BUILD_WORKBENCH: {
return "Benchmarking";
}
case BUILD_PICKAXE: {
return "Time to Mine!";
}
case BUILD_FURNACE: {
return "Hot Topic";
}
case ACQUIRE_IRON: {
return "Acquire Hardware!";
}
case BUILD_HOE: {
return "Time to Farm!";
}
case MAKE_BREAD: {
return "Bake Bread";
}
case BAKE_CAKE: {
return "The Lie";
}
case BUILD_BETTER_PICKAXE: {
return "Getting an Upgrade";
}
case COOK_FISH: {
return "Delicious Fish";
}
case ON_A_RAIL: {
return "On A Rail";
}
case BUILD_SWORD: {
return "Time to Strike";
}
case KILL_ENEMY: {
return "Monster Hunter";
}
case KILL_COW: {
return "Cow Tipper";
}
case FLY_PIG: {
return "When Pigs Fly!";
}
case SNIPE_SKELETON: {
return "Sniper Duel";
}
case GET_DIAMONDS: {
return "DIAMONDS!";
}
case NETHER_PORTAL: {
return "We Need to Go Deeper";
}
case GHAST_RETURN: {
return "Return to Sender";
}
case GET_BLAZE_ROD: {
return "Into Fire";
}
case BREW_POTION: {
return "Local Brewery";
}
case END_PORTAL: {
return "The End?";
}
case THE_END: {
return "The End.";
}
case ENCHANTMENTS: {
return "Enchanter";
}
case OVERKILL: {
return "Overkill";
}
case BOOKCASE: {
return "Librarian";
}
case EXPLORE_ALL_BIOMES: {
return "Adventuring Time";
}
case SPAWN_WITHER: {
return "The Beginning?";
}
case KILL_WITHER: {
return "The Beginning.";
}
case FULL_BEACON: {
return "Beaconator";
}
case BREED_COW: {
return "Repopulation";
}
case DIAMONDS_TO_YOU: {
return "Diamonds to you!";
}
case OVERPOWERED: {
return "Overpowered";
}
default: {
throw new IllegalStateException();
}
}
}
}

View File

@ -0,0 +1,46 @@
package net.ess3.nms.refl.providers;
import net.ess3.nms.refl.ReflUtil;
import net.ess3.provider.AbstractAchievementEvent;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerAdvancementDoneEvent;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public class AdvancementListenerProvider implements Listener {
private final Object language;
private final MethodHandle languageGetOrDefault;
public AdvancementListenerProvider() throws Throwable {
final Class<?> languageClass;
if (ReflUtil.isMojMap()) {
languageClass = ReflUtil.getClassCached("net.minecraft.locale.Language");
} else if (ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_17_R1)) {
languageClass = ReflUtil.getClassCached("net.minecraft.locale.LocaleLanguage");
} else {
languageClass = ReflUtil.getNMSClass("LocaleLanguage");
}
final MethodHandles.Lookup lookup = MethodHandles.lookup();
//noinspection ConstantConditions
language = lookup.findStatic(languageClass, ReflUtil.isMojMap() ? "getInstance" : "a", MethodType.methodType(languageClass)).invoke();
languageGetOrDefault = lookup.findVirtual(languageClass, ReflUtil.isMojMap() ? "getOrDefault" : "a", MethodType.methodType(String.class, String.class));
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onAdvancement(final PlayerAdvancementDoneEvent event) {
try {
final String key = "advancements." + event.getAdvancement().getKey().getKey().replace('/', '.') + ".title";
final String translation = (String) languageGetOrDefault.invoke(language, key);
if (!key.equals(translation)) {
Bukkit.getPluginManager().callEvent(new AbstractAchievementEvent(event.getPlayer(), translation));
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}