From 499baf7bab880d6d5fd8b10def6ccd3ffee5dfab Mon Sep 17 00:00:00 2001 From: Garsooon Date: Mon, 6 Oct 2025 18:57:56 +0900 Subject: [PATCH 1/9] Stop players /ignore'ing staff JPerms groups --- .../essentials/commands/Commandignore.java | 55 ++++++++++++++++++- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java index 724111197..4284d1941 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java @@ -2,8 +2,19 @@ import com.earth2me.essentials.User; import com.earth2me.essentials.Util; +import org.bukkit.ChatColor; import org.bukkit.Server; +import com.johnymuffin.jperms.beta.JohnyPerms; +import com.johnymuffin.jperms.beta.JohnyPermsAPI; +import com.johnymuffin.jperms.core.models.PermissionsUser; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.FileReader; +import java.util.UUID; public class Commandignore extends EssentialsCommand { @@ -11,6 +22,24 @@ public Commandignore() { super("ignore"); } + private UUID getUUIDFromCache(String playerName) { + try { + JSONParser parser = new JSONParser(); + JSONArray arr = (JSONArray) parser.parse(new FileReader("uuidcache.json")); + for (Object obj : arr) { + JSONObject entry = (JSONObject) obj; + String name = (String) entry.get("name"); + if (name != null && name.equalsIgnoreCase(playerName)) { + String uuidStr = (String) entry.get("uuid"); + return UUID.fromString(uuidStr); + } + } + } catch (Exception e) { + // Sil + } + return null; + } + @Override protected void run(Server server, User user, String commandLabel, String[] args) throws Exception { if (args.length < 1) { @@ -26,6 +55,28 @@ protected void run(Server server, User user, String commandLabel, String[] args) throw new Exception(Util.i18n("playerNotFound")); } String name = u.getName(); + + if (server.getPluginManager().getPlugin("JPerms") != null) { + JohnyPerms permsPlugin = (JohnyPerms) server.getPluginManager().getPlugin("JPerms"); + if (permsPlugin != null) { + JohnyPermsAPI permsAPI = new JohnyPermsAPI(permsPlugin); + UUID uuid = getUUIDFromCache(name); + if (uuid != null) { + PermissionsUser jpUser = permsAPI.getUser(uuid); + if (jpUser != null) { + String groupName = jpUser.getGroup().getName().toLowerCase().trim(); + if (groupName.equals("trial helper") || + groupName.equals("helper") || + groupName.equals("moderator") || + groupName.equals("admin")) { + user.sendMessage(ChatColor.RED + "You cannot ignore staff members!"); + return; + } + } + } + } + } + if (user.isIgnoredPlayer(name)) { user.setIgnoredPlayer(name, false); user.sendMessage(Util.format("unignorePlayer", u.getName())); @@ -34,6 +85,4 @@ protected void run(Server server, User user, String commandLabel, String[] args) user.sendMessage(Util.format("ignorePlayer", u.getName())); } } - - -} +} \ No newline at end of file From 34a1d60a439193050c9a394dafa5a4956a194c56 Mon Sep 17 00:00:00 2001 From: Garsooon <46406077+Garsooon@users.noreply.github.com> Date: Wed, 8 Oct 2025 08:30:39 +0000 Subject: [PATCH 2/9] Update trial helper group name --- .../java/com/earth2me/essentials/commands/Commandignore.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java index 4284d1941..e3e9d47c3 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java @@ -65,7 +65,7 @@ protected void run(Server server, User user, String commandLabel, String[] args) PermissionsUser jpUser = permsAPI.getUser(uuid); if (jpUser != null) { String groupName = jpUser.getGroup().getName().toLowerCase().trim(); - if (groupName.equals("trial helper") || + if (groupName.equals("trial") || groupName.equals("helper") || groupName.equals("moderator") || groupName.equals("admin")) { @@ -85,4 +85,4 @@ protected void run(Server server, User user, String commandLabel, String[] args) user.sendMessage(Util.format("ignorePlayer", u.getName())); } } -} \ No newline at end of file +} From ddd93ae91a2528504b8dfe1aad9d36ae6d7b194e Mon Sep 17 00:00:00 2001 From: Rhys B Date: Fri, 24 Oct 2025 12:44:54 +1000 Subject: [PATCH 3/9] Refactors ignore command for staff exemption Changes the ignore command to use the `essentials.ignore.exempt` permission instead of relying on JPerms for staff identification. This allows admins to easily configure staff members who cannot be ignored, regardless of their group membership. Also, ensures that exempted players are automatically unignored by all other players upon joining. --- .../essentials/EssentialsPlayerListener.java | 19 +++++++++++++++ .../essentials/commands/Commandignore.java | 23 ++++--------------- .../src/main/resources/messages.properties | 1 + 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java index 4ddfade21..ebbf04afa 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java +++ b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java @@ -17,6 +17,8 @@ import java.util.logging.Level; import java.util.logging.Logger; +import static org.bukkit.Bukkit.getPlayer; + public class EssentialsPlayerListener extends PlayerListener { private static final Logger LOGGER = Logger.getLogger("Minecraft"); @@ -57,6 +59,23 @@ public void onPlayerChat(final PlayerChatEvent event) { if (ess.getSettings().changeDisplayName()) { user.setDisplayName(user.getNick()); } + + // If the user has ignore exempt permission, unignore them for all players + if (user.hasPermission("essentials.ignore.exempt") || user.isOp()) { + for (Player p : ess.getServer().getOnlinePlayers()) { + // Skip self + if(p.getName().equalsIgnoreCase(user.getName())) { + continue; + } + + User u = ess.getUser(p); + + // If the viewer is ignoring the poster, unignore them + if (u.isIgnoredPlayer(user.getName())) { + u.setIgnoredPlayer(user.getName(), false); + } + } + } } @Override diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java index e3e9d47c3..dfa9ba05d 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java @@ -56,25 +56,10 @@ protected void run(Server server, User user, String commandLabel, String[] args) } String name = u.getName(); - if (server.getPluginManager().getPlugin("JPerms") != null) { - JohnyPerms permsPlugin = (JohnyPerms) server.getPluginManager().getPlugin("JPerms"); - if (permsPlugin != null) { - JohnyPermsAPI permsAPI = new JohnyPermsAPI(permsPlugin); - UUID uuid = getUUIDFromCache(name); - if (uuid != null) { - PermissionsUser jpUser = permsAPI.getUser(uuid); - if (jpUser != null) { - String groupName = jpUser.getGroup().getName().toLowerCase().trim(); - if (groupName.equals("trial") || - groupName.equals("helper") || - groupName.equals("moderator") || - groupName.equals("admin")) { - user.sendMessage(ChatColor.RED + "You cannot ignore staff members!"); - return; - } - } - } - } + if(u.hasPermission("essentials.ignore.exempt") || u.isOp()) { + user.setIgnoredPlayer(name, false); // Ensure they are not ignored. This is useful if an op/exempt player was ignored before gaining exempt status. + user.sendMessage(Util.format("ignoreExempt", u.getName())); + return; } if (user.isIgnoredPlayer(name)) { diff --git a/Essentials/src/main/resources/messages.properties b/Essentials/src/main/resources/messages.properties index 09771525a..8ba15d3dd 100644 --- a/Essentials/src/main/resources/messages.properties +++ b/Essentials/src/main/resources/messages.properties @@ -324,6 +324,7 @@ unableToSpawnMob = Unable to spawn mob. unbannedIP = Unbanned IP address. unbannedPlayer = Unbanned player. unignorePlayer = You are not ignoring player {0} anymore. +ignoreExempt = \u00a7cYou cannot ignore that player. unknownItemId = Unknown item id: {0} unknownItemInList = Unknown item {0} in {1} list. unknownItemName = Unknown item name: {0} From c028056f052a29f413106a84e9240c95e404f4dd Mon Sep 17 00:00:00 2001 From: Rhys B Date: Fri, 24 Oct 2025 13:26:09 +1000 Subject: [PATCH 4/9] Code for /mail to get sent via Discord (#11) * Prototype code for /mail to get sent via Discord * Remove ] * Resolve stale pr conflicts * Versioning * Fix merge error * Enhances Discord mail integration Improves the Discord mail forwarding feature by: - Ensuring mail forwarding only occurs if both Discord plugins are enabled. - Preventing forwarding to online players. - Preventing forwarding to players who have disabled the feature. - Adds logging for successful and failed Discord mail attempts. - Fixes a typo in the UserData class that was preventing UUID's being set correctly. --------- Co-authored-by: Garsooon Co-authored-by: Garsooon <46406077+Garsooon@users.noreply.github.com> --- Essentials/pom.xml | 8 +- .../essentials/EssentialsPlayerListener.java | 2 + .../com/earth2me/essentials/UserData.java | 55 ++++- .../essentials/commands/Commandmail.java | 217 ++++++++++-------- .../johnymuffin/essentials/ESSAdvConfig.java | 3 + .../main/resources/examples/bpermissions.yml | 1 + .../resources/examples/permissionsbukkit.yml | 1 + .../main/resources/examples/permissionsex.yml | 1 + .../src/main/resources/messages.properties | 4 + .../src/main/resources/messages_da.properties | 1 + .../src/main/resources/messages_de.properties | 1 + .../src/main/resources/messages_en.properties | 1 + .../src/main/resources/messages_fr.properties | 1 + .../src/main/resources/messages_nl.properties | 1 + Essentials/src/main/resources/plugin.yml | 2 +- EssentialsChat/pom.xml | 2 +- EssentialsGeoIP/pom.xml | 2 +- EssentialsProtect/pom.xml | 14 +- EssentialsSpawn/pom.xml | 2 +- pom.xml | 2 +- 20 files changed, 199 insertions(+), 122 deletions(-) diff --git a/Essentials/pom.xml b/Essentials/pom.xml index 5786062b7..a1eab4994 100644 --- a/Essentials/pom.xml +++ b/Essentials/pom.xml @@ -8,7 +8,7 @@ com.earth2me.essentialss essentials-parent - 2.6.9 + 2.7.0 ../pom.xml @@ -76,6 +76,12 @@ 1.1.3 + + com.johnymuffin.beta + discordauth + 1.1.3 + + net.dv8tion JDA diff --git a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java index 4ddfade21..a2d1ffc30 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java +++ b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java @@ -208,6 +208,8 @@ public void onPlayerJoin(final PlayerJoinEvent event) { ess.getBackup().onPlayerJoin(); final User user = ess.getUser(event.getPlayer()); + user.setUUID(event.getPlayer().getUniqueId()); // Set the UUID of the player + //we do not know the ip address on playerlogin so we need to do this here. if (user.isIpBanned()) { final String banReason = user.getBanReason(); diff --git a/Essentials/src/main/java/com/earth2me/essentials/UserData.java b/Essentials/src/main/java/com/earth2me/essentials/UserData.java index f60febb5d..665f22fad 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/UserData.java +++ b/Essentials/src/main/java/com/earth2me/essentials/UserData.java @@ -5,11 +5,9 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import javax.annotation.Nullable; import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.logging.Logger; @@ -41,6 +39,9 @@ public abstract class UserData extends PlayerExtension implements IConf { private boolean isSocialSpyEnabled; private boolean isNPC; + private UUID uuid; + private boolean receiveMailOnDiscord; + protected UserData(Player base, IEssentials ess) { super(base, ess); File folder = new File(ess.getDataFolder(), "userdata"); @@ -77,6 +78,8 @@ public final void reloadConfig() { geolocation = _getGeoLocation(); isSocialSpyEnabled = _isSocialSpyEnabled(); isNPC = _isNPC(); + uuid = _getUUID(); + receiveMailOnDiscord = _getReceiveMailOnDiscord(); } private double _getMoney() { @@ -617,4 +620,48 @@ public void setNPC(boolean set) { config.setProperty("npc", set); config.save(); } + + public void setUUID(UUID uuid) { + this.uuid = uuid; + config.setProperty("uuid", uuid.toString()); + config.save(); + } + + @Nullable + private UUID _getUUID() { + String uuid = config.getString("uuid"); + if (uuid == null) { + return null; + } + + try { + return UUID.fromString(uuid); + } catch (IllegalArgumentException e) { + logger.warning("Invalid UUID in user data for " + getName() + ": " + uuid + ". UUID will be removed."); + config.removeProperty("uuid"); + config.save(); + } + + return null; + } + + @Nullable + public UUID getUUID() { + return uuid; + } + + private boolean _getReceiveMailOnDiscord() { + return config.getBoolean("receiveMailOnDiscord", true); // Default to true + } + + public boolean getReceiveMailOnDiscord() { + return receiveMailOnDiscord; + } + + public void setReceiveMailOnDiscord(boolean receiveMailOnDiscord) { + this.receiveMailOnDiscord = receiveMailOnDiscord; + config.setProperty("receiveMailOnDiscord", receiveMailOnDiscord); + config.save(); + } + } diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandmail.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandmail.java index 027c82ece..ad6cbd037 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandmail.java +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandmail.java @@ -2,12 +2,20 @@ import com.earth2me.essentials.User; import com.earth2me.essentials.Util; +import com.johnymuffin.beta.discordauth.DiscordAuthentication; +import com.johnymuffin.discordcore.DiscordCore; +import com.johnymuffin.essentials.ESSAdvConfig; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.JDA; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.util.List; +import java.util.UUID; +import java.util.logging.Level; public class Commandmail extends EssentialsCommand { private final String CAN_SEND_MAIL_PERMISSION_NODE = "essentials.mail.send"; @@ -19,122 +27,133 @@ public Commandmail() { } @Override - public void run( - Server server, - CommandSender sender, - String commandLabel, - String[] args - ) throws NotEnoughArgumentsException { + public void run(Server server, CommandSender sender, String commandLabel, String[] args) throws Exception { this.server = server; - User user = ess.getUser(sender); - int argCount = args.length; - - boolean success = false; - if(argCount == 1) - success = oneParameter(args[0], user); - else if(argCount >= 3) - success = threeParameter(args, user); - - if(!success) - throw new NotEnoughArgumentsException(); - } - private boolean oneParameter(String arg, User user) { - switch(arg) { - case "read": - return read(user); - case "clear": - return clear(user); + if (args.length >= 1 && "read".equalsIgnoreCase(args[0])) { + List mail = user.getMails(); + if (mail.isEmpty()) { + user.sendMessage(Util.i18n("noMail")); + return; + } + for (String s : mail) { + user.sendMessage(s); + } + user.sendMessage(Util.i18n("mailClear")); + return; } - - return false; - } - - private boolean threeParameter(String[] args, User user) { - String subCommand = args[0]; - String to = args[1]; - String message = getFinalArg(args, 2); - - // yes this is stupid, but its done for consistancy with the oneParameter() function - switch(subCommand) { - case "send": - return send(to, message, user); + if (args.length >= 3 && "send".equalsIgnoreCase(args[0])) { + if (!user.isAuthorized(CAN_SEND_MAIL_PERMISSION_NODE)) { + throw new Exception(Util.i18n("noMailSendPerm")); + } + + Player player = server.getPlayer(args[1]); + User u; + if (player != null) { + u = ess.getUser(player); + } else { + u = ess.getOfflineUser(args[1]); + } + if (u == null) { + throw new Exception(Util.format("playerNeverOnServer", args[1])); + } + + if (!u.isIgnoredPlayer(user.getName())) { + u.addMail(ChatColor.stripColor(user.getDisplayName()) + ": " + getFinalArg(args, 2)); + + boolean forwardToDiscord = ESSAdvConfig.getInstance().getConfigBoolean("settings.mail.send-to-discord.enabled"); + try { + forwardMailToDiscord(user, u, args); + } catch (Exception e) { + System.out.println("Failed to forward mail to Discord for " + u.getName() + "."); + e.printStackTrace(); + } + + } + user.sendMessage(Util.i18n("mailSent")); + return; } - - return false; - } - - private boolean read(User user) { - List mails = user.getMails(); - - if (mails.isEmpty()) { - String noMailMessage = Util.i18n("noMail"); - user.sendMessage(noMailMessage); - - return true; + if (args.length >= 1 && "clear".equalsIgnoreCase(args[0])) { + user.setMails(null); + user.sendMessage(Util.i18n("mailCleared")); + return; } - - for (String mail : mails) { - user.sendMessage(mail); + if(args.length == 1 && "discord".equalsIgnoreCase(args[0])) { + if (!user.isAuthorized("essentials.mail.discord")) { + throw new Exception(Util.i18n("noMailDiscordPerm")); + } + user.setReceiveMailOnDiscord(!user.getReceiveMailOnDiscord()); + boolean receiveMailOnDiscord = user.getReceiveMailOnDiscord(); + user.sendMessage(Util.i18n(receiveMailOnDiscord ? "mailDiscordEnabled" : "mailDiscordDisabled")); + return; } - - String clearMessage = Util.i18n("mailClear"); - user.sendMessage(clearMessage); - - return true; + throw new NotEnoughArgumentsException(); } - private boolean clear(User user) { - user.setMails(null); + private void forwardMailToDiscord(User sender, User recipient, String[] args) { - String clearedMailMessage = Util.i18n("mailCleared"); - user.sendMessage(clearedMailMessage); - - return true; - } - - private boolean send(String to, String message, User user) { - if (!canSendMail(user)) { - String noPermissionMessage = Util.i18n("noMailSendPerm"); - user.sendMessage(noPermissionMessage); - - return true; + // Check if both DiscordAuthentication and DiscordCore plugins are enabled + if (!(Bukkit.getPluginManager().isPluginEnabled("DiscordAuthentication") && Bukkit.getPluginManager().isPluginEnabled("DiscordCore"))) { + return; } - User toUser = findUser(to); - if (toUser == null) { - String neverSeenMessage = Util.format("playerNeverOnServer", to); - user.sendMessage(neverSeenMessage); - - return true; + // Check if recipient is online or has disabled mail forwarding + if (recipient.isOnline()) { + return; } - String mailSentMessage = Util.i18n("mailSent"); - user.sendMessage(mailSentMessage); - - if (hasIgnoredPlayer(toUser, user)) - return true; - - String mailMessage = ChatColor.stripColor(user.getDisplayName()) + ": " + message; - toUser.addMail(mailMessage); - - return true; - } - - private User findUser(String playerName) { - Player player = server.getPlayer(playerName); - if (player == null) - return ess.getOfflineUser(playerName); + // Check if recipient has disabled mail forwarding + if (!recipient.getReceiveMailOnDiscord()) { + return; + } - return ess.getUser(player); - } - private boolean hasIgnoredPlayer(User recipient, User sender) { - return recipient.isIgnoredPlayer(sender.getName()); + DiscordAuthentication plugin = (DiscordAuthentication) Bukkit.getPluginManager().getPlugin("DiscordAuthentication"); + String targetUsername = recipient.getName(); + UUID targetUUID = recipient.getUUID(); + + if (targetUUID != null) { + String discordID = plugin.getData().getDiscordIDFromUUID(String.valueOf(targetUUID)); + + if (discordID != null) { + log(Level.INFO, "Mail sent from " + sender.getName() + " to " + targetUsername + " forwarding to Discord ID: " + discordID); + DiscordCore discordCore = (DiscordCore) Bukkit.getPluginManager().getPlugin("DiscordCore"); + JDA jda = discordCore.getDiscordBot().getJda(); + + jda.retrieveUserById(discordID).queue(discordUser -> { + if (discordUser != null) { + discordUser.openPrivateChannel().queue(privateChannel -> { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setAuthor(ChatColor.stripColor(sender.getDisplayName()), null, "https://skins.legacyminecraft.com/avatars/" + sender.getBase().getUniqueId()); + embedBuilder.setTitle("Forwarded Mail from Minecraft Server"); + embedBuilder.setDescription("You have received a new mail message on the Minecraft server from " + sender.getName() + ".\n\n**Message:**\n" + getFinalArg(args, 2) + "\n\n*Note: You can use `/mail discord` in-game to toggle receiving mail via Discord.*"); + embedBuilder.setFooter("Essentials (RetroMC fork) - Mail Command", "https://wiki.retromc.org/images/1/1a/Retromcnew.png"); + embedBuilder.setColor(0x00FF00); + privateChannel.sendMessage(embedBuilder.build()).queue(); + + Bukkit.getScheduler().callSyncMethod(ess, () -> { + sender.sendMessage(Util.format("mailSentDiscord", discordUser.getAsTag())); + return null; + }); + }, throwable -> { + log(Level.WARNING, "Failed to send a message to user with Discord ID: " + discordID + ". Reason: " + throwable.getMessage()); + }); + } else { + log(Level.WARNING, "User with Discord ID " + discordID + " could not be found in any mutual guild."); + } + }, throwable -> { + log(Level.WARNING, "Failed to retrieve user with Discord ID: " + discordID + ". Reason: " + throwable.getMessage()); + }); + } else { + log(Level.INFO, "No Discord ID found for UUID: " + targetUUID + " when attempting to forward mail to Discord."); + } + } else { + log(Level.WARNING, "Failed to send mail to " + targetUsername + " on Discord: No UUID found in Essentials data."); + } } - private boolean canSendMail(User user) { - return user.isAuthorized(CAN_SEND_MAIL_PERMISSION_NODE); + private void log(Level level, String message) { + ess.getServer().getLogger().log(level, "[" + ess.getDescription().getName() + "] " + message); } } diff --git a/Essentials/src/main/java/com/johnymuffin/essentials/ESSAdvConfig.java b/Essentials/src/main/java/com/johnymuffin/essentials/ESSAdvConfig.java index fc64054d0..2f0cf2fb8 100644 --- a/Essentials/src/main/java/com/johnymuffin/essentials/ESSAdvConfig.java +++ b/Essentials/src/main/java/com/johnymuffin/essentials/ESSAdvConfig.java @@ -38,6 +38,9 @@ private void write() { generateConfigOption("discord.channel-id", "0"); + generateConfigOption("settings.mail.send-to-discord.enabled", false); + generateConfigOption("settings.mail.send-to-discord.info", "This will send mail that a player receives to them via Discord if they have linked their account with Discord Authentication Core."); + } private void generateConfigOption(String key, Object defaultValue) { diff --git a/Essentials/src/main/resources/examples/bpermissions.yml b/Essentials/src/main/resources/examples/bpermissions.yml index 9ba493fae..7253febaf 100644 --- a/Essentials/src/main/resources/examples/bpermissions.yml +++ b/Essentials/src/main/resources/examples/bpermissions.yml @@ -26,6 +26,7 @@ groups: - essentials.kit.tools - essentials.mail - essentials.mail.send + - essentials.mail.discord - essentials.me - essentials.msg - essentials.nick diff --git a/Essentials/src/main/resources/examples/permissionsbukkit.yml b/Essentials/src/main/resources/examples/permissionsbukkit.yml index 243752232..5b2ed5c2b 100644 --- a/Essentials/src/main/resources/examples/permissionsbukkit.yml +++ b/Essentials/src/main/resources/examples/permissionsbukkit.yml @@ -34,6 +34,7 @@ groups: essentials.kit.tools: true essentials.mail: true essentials.mail.send: true + essentials.mail.discord: true essentials.me: true essentials.msg: true essentials.nick: true diff --git a/Essentials/src/main/resources/examples/permissionsex.yml b/Essentials/src/main/resources/examples/permissionsex.yml index 47407cd62..6e9bf2b5c 100644 --- a/Essentials/src/main/resources/examples/permissionsex.yml +++ b/Essentials/src/main/resources/examples/permissionsex.yml @@ -32,6 +32,7 @@ groups: - essentials.kit.tools - essentials.mail - essentials.mail.send + - essentials.mail.discord - essentials.me - essentials.msg - essentials.nick diff --git a/Essentials/src/main/resources/messages.properties b/Essentials/src/main/resources/messages.properties index 09771525a..4ee7a2853 100644 --- a/Essentials/src/main/resources/messages.properties +++ b/Essentials/src/main/resources/messages.properties @@ -370,3 +370,7 @@ year = year years = years youAreHealed = \u00a77You have been healed. youHaveNewMail = \u00a7cYou have {0} messages!\u00a7f Type \u00a77/mail read\u00a7f to view your mail. +mailSentDiscord = \u00a77Mail sent to {0} via Discord. +mailDiscordEnabled = \u00a77You will now receive mail on Discord. +mailDiscordDisabled = \u00a77You will no longer receive mail on Discord. +noMailDiscordPerm = \u00a7cYou do not have permission to alter Discord mail settings. \ No newline at end of file diff --git a/Essentials/src/main/resources/messages_da.properties b/Essentials/src/main/resources/messages_da.properties index e5f306466..a4fedde0d 100644 --- a/Essentials/src/main/resources/messages_da.properties +++ b/Essentials/src/main/resources/messages_da.properties @@ -358,3 +358,4 @@ year = \u00e5r years = \u00e5r youAreHealed = \u00a77Du er blevet helbredt. youHaveNewMail = \u00a7cDu har {0} beskeder!\u00a7f Type \u00a77/post l\u00e6s\u00a7f for at se din post. +mailSentDiscord = \u00a77Mail sent to {0} via Discord. \ No newline at end of file diff --git a/Essentials/src/main/resources/messages_de.properties b/Essentials/src/main/resources/messages_de.properties index 489d734e6..90d2d9828 100644 --- a/Essentials/src/main/resources/messages_de.properties +++ b/Essentials/src/main/resources/messages_de.properties @@ -358,3 +358,4 @@ year = Jahr years = Jahre youAreHealed = \u00a77Du wurdest geheilt. youHaveNewMail = \u00a7cDu hast {0} Nachrichten!\u00a7f Schreibe \u00a77/mail read\u00a7f um deine Nachrichten anzuzeigen. +mailSentDiscord = \u00a77Mail sent to {0} via Discord. \ No newline at end of file diff --git a/Essentials/src/main/resources/messages_en.properties b/Essentials/src/main/resources/messages_en.properties index a83cca2f2..c0c18d51f 100644 --- a/Essentials/src/main/resources/messages_en.properties +++ b/Essentials/src/main/resources/messages_en.properties @@ -360,3 +360,4 @@ year = year years = years youAreHealed = \u00a77You have been healed. youHaveNewMail = \u00a7cYou have {0} messages!\u00a7f Type \u00a77/mail read\u00a7f to view your mail. +mailSentDiscord = \u00a77Mail sent to {0} via Discord. \ No newline at end of file diff --git a/Essentials/src/main/resources/messages_fr.properties b/Essentials/src/main/resources/messages_fr.properties index 61854255d..ec9bf52a1 100644 --- a/Essentials/src/main/resources/messages_fr.properties +++ b/Essentials/src/main/resources/messages_fr.properties @@ -358,3 +358,4 @@ year = ann\u00e9e years = ann\u00e9es youAreHealed = \u00a77Vous avez \u00e9t\u00e9 soign\u00e9. youHaveNewMail = \u00a7cVous avez {0} messages! \u00a7fEntrez \u00a77/mail read\u00a7f pour voir votre courrier. +mailSentDiscord = \u00a77Mail sent to {0} via Discord. diff --git a/Essentials/src/main/resources/messages_nl.properties b/Essentials/src/main/resources/messages_nl.properties index acabd87f8..3e5b60c84 100644 --- a/Essentials/src/main/resources/messages_nl.properties +++ b/Essentials/src/main/resources/messages_nl.properties @@ -358,3 +358,4 @@ year = jaar years = jaren youAreHealed = \u00a77Je bent genezen. youHaveNewMail = \u00a7cJe hebt {0} berichten!\u00a7f Type \u00a77/mail read\u00a7f om je berichten te bekijken. +mailSentDiscord = \u00a77Mail sent to {0} via Discord. \ No newline at end of file diff --git a/Essentials/src/main/resources/plugin.yml b/Essentials/src/main/resources/plugin.yml index a6e067acd..ef72402a6 100644 --- a/Essentials/src/main/resources/plugin.yml +++ b/Essentials/src/main/resources/plugin.yml @@ -183,7 +183,7 @@ commands: usage: / [warp] mail: description: Manages inter-player, intra-server mail. - usage: / [read|clear|send [to] [message]] + usage: / [read|clear|send|discord] [to] [message] aliases: [email] me: description: Describes an action in the context of the player. diff --git a/EssentialsChat/pom.xml b/EssentialsChat/pom.xml index 6d7a29570..cbd3866c8 100644 --- a/EssentialsChat/pom.xml +++ b/EssentialsChat/pom.xml @@ -8,7 +8,7 @@ com.earth2me.essentialss essentials-parent - 2.6.9 + 2.7.0 ../pom.xml diff --git a/EssentialsGeoIP/pom.xml b/EssentialsGeoIP/pom.xml index 4abfa6810..8de8d406b 100644 --- a/EssentialsGeoIP/pom.xml +++ b/EssentialsGeoIP/pom.xml @@ -8,7 +8,7 @@ com.earth2me.essentialss essentials-parent - 2.6.9 + 2.7.0 ../pom.xml diff --git a/EssentialsProtect/pom.xml b/EssentialsProtect/pom.xml index 67d9f0820..066386499 100644 --- a/EssentialsProtect/pom.xml +++ b/EssentialsProtect/pom.xml @@ -8,7 +8,7 @@ com.earth2me.essentialss essentials-parent - 2.6.9 + 2.7.0 ../pom.xml @@ -57,18 +57,6 @@ ${project.version} - - com.mchange - c3p0 - 0.9.5.5 - - - - com.mchange - mchange-commons-java - 0.2.20 - - \ No newline at end of file diff --git a/EssentialsSpawn/pom.xml b/EssentialsSpawn/pom.xml index 4b3a3a721..1452904b2 100644 --- a/EssentialsSpawn/pom.xml +++ b/EssentialsSpawn/pom.xml @@ -8,7 +8,7 @@ com.earth2me.essentialss essentials-parent - 2.6.9 + 2.7.0 ../pom.xml diff --git a/pom.xml b/pom.xml index c5b0c3c0a..800880972 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.earth2me.essentialss essentials-parent - 2.6.9 + 2.7.0 pom From ecf737553c39f982c469ac54af31ad7b3637c738 Mon Sep 17 00:00:00 2001 From: Rhys B Date: Fri, 24 Oct 2025 13:31:32 +1000 Subject: [PATCH 5/9] Resolve build issues --- EssentialsProtect/pom.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/EssentialsProtect/pom.xml b/EssentialsProtect/pom.xml index 066386499..3ed08cc0c 100644 --- a/EssentialsProtect/pom.xml +++ b/EssentialsProtect/pom.xml @@ -57,6 +57,18 @@ ${project.version} + + com.mchange + c3p0 + 0.9.5.5 + + + + com.mchange + mchange-commons-java + 0.2.20 + + \ No newline at end of file From d0c82b4fc12f732b297e223d225fae476c8007aa Mon Sep 17 00:00:00 2001 From: Garsooon Date: Mon, 6 Oct 2025 18:57:56 +0900 Subject: [PATCH 6/9] Stop players /ignore'ing staff JPerms groups --- .../essentials/commands/Commandignore.java | 55 ++++++++++++++++++- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java index 724111197..4284d1941 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java @@ -2,8 +2,19 @@ import com.earth2me.essentials.User; import com.earth2me.essentials.Util; +import org.bukkit.ChatColor; import org.bukkit.Server; +import com.johnymuffin.jperms.beta.JohnyPerms; +import com.johnymuffin.jperms.beta.JohnyPermsAPI; +import com.johnymuffin.jperms.core.models.PermissionsUser; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.FileReader; +import java.util.UUID; public class Commandignore extends EssentialsCommand { @@ -11,6 +22,24 @@ public Commandignore() { super("ignore"); } + private UUID getUUIDFromCache(String playerName) { + try { + JSONParser parser = new JSONParser(); + JSONArray arr = (JSONArray) parser.parse(new FileReader("uuidcache.json")); + for (Object obj : arr) { + JSONObject entry = (JSONObject) obj; + String name = (String) entry.get("name"); + if (name != null && name.equalsIgnoreCase(playerName)) { + String uuidStr = (String) entry.get("uuid"); + return UUID.fromString(uuidStr); + } + } + } catch (Exception e) { + // Sil + } + return null; + } + @Override protected void run(Server server, User user, String commandLabel, String[] args) throws Exception { if (args.length < 1) { @@ -26,6 +55,28 @@ protected void run(Server server, User user, String commandLabel, String[] args) throw new Exception(Util.i18n("playerNotFound")); } String name = u.getName(); + + if (server.getPluginManager().getPlugin("JPerms") != null) { + JohnyPerms permsPlugin = (JohnyPerms) server.getPluginManager().getPlugin("JPerms"); + if (permsPlugin != null) { + JohnyPermsAPI permsAPI = new JohnyPermsAPI(permsPlugin); + UUID uuid = getUUIDFromCache(name); + if (uuid != null) { + PermissionsUser jpUser = permsAPI.getUser(uuid); + if (jpUser != null) { + String groupName = jpUser.getGroup().getName().toLowerCase().trim(); + if (groupName.equals("trial helper") || + groupName.equals("helper") || + groupName.equals("moderator") || + groupName.equals("admin")) { + user.sendMessage(ChatColor.RED + "You cannot ignore staff members!"); + return; + } + } + } + } + } + if (user.isIgnoredPlayer(name)) { user.setIgnoredPlayer(name, false); user.sendMessage(Util.format("unignorePlayer", u.getName())); @@ -34,6 +85,4 @@ protected void run(Server server, User user, String commandLabel, String[] args) user.sendMessage(Util.format("ignorePlayer", u.getName())); } } - - -} +} \ No newline at end of file From 33e437cac86997fc72cd8893e4e8fb33cef5388b Mon Sep 17 00:00:00 2001 From: Garsooon <46406077+Garsooon@users.noreply.github.com> Date: Wed, 8 Oct 2025 08:30:39 +0000 Subject: [PATCH 7/9] Update trial helper group name --- .../java/com/earth2me/essentials/commands/Commandignore.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java index 4284d1941..e3e9d47c3 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java @@ -65,7 +65,7 @@ protected void run(Server server, User user, String commandLabel, String[] args) PermissionsUser jpUser = permsAPI.getUser(uuid); if (jpUser != null) { String groupName = jpUser.getGroup().getName().toLowerCase().trim(); - if (groupName.equals("trial helper") || + if (groupName.equals("trial") || groupName.equals("helper") || groupName.equals("moderator") || groupName.equals("admin")) { @@ -85,4 +85,4 @@ protected void run(Server server, User user, String commandLabel, String[] args) user.sendMessage(Util.format("ignorePlayer", u.getName())); } } -} \ No newline at end of file +} From 55d69a3d715ca03dda0d83bf28e714cfbe01ccca Mon Sep 17 00:00:00 2001 From: Rhys B Date: Fri, 24 Oct 2025 12:44:54 +1000 Subject: [PATCH 8/9] Refactors ignore command for staff exemption Changes the ignore command to use the `essentials.ignore.exempt` permission instead of relying on JPerms for staff identification. This allows admins to easily configure staff members who cannot be ignored, regardless of their group membership. Also, ensures that exempted players are automatically unignored by all other players upon joining. --- .../essentials/EssentialsPlayerListener.java | 19 +++++++++++++++ .../essentials/commands/Commandignore.java | 23 ++++--------------- .../src/main/resources/messages.properties | 1 + 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java index a2d1ffc30..8f890c87c 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java +++ b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java @@ -17,6 +17,8 @@ import java.util.logging.Level; import java.util.logging.Logger; +import static org.bukkit.Bukkit.getPlayer; + public class EssentialsPlayerListener extends PlayerListener { private static final Logger LOGGER = Logger.getLogger("Minecraft"); @@ -57,6 +59,23 @@ public void onPlayerChat(final PlayerChatEvent event) { if (ess.getSettings().changeDisplayName()) { user.setDisplayName(user.getNick()); } + + // If the user has ignore exempt permission, unignore them for all players + if (user.hasPermission("essentials.ignore.exempt") || user.isOp()) { + for (Player p : ess.getServer().getOnlinePlayers()) { + // Skip self + if(p.getName().equalsIgnoreCase(user.getName())) { + continue; + } + + User u = ess.getUser(p); + + // If the viewer is ignoring the poster, unignore them + if (u.isIgnoredPlayer(user.getName())) { + u.setIgnoredPlayer(user.getName(), false); + } + } + } } @Override diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java index e3e9d47c3..dfa9ba05d 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandignore.java @@ -56,25 +56,10 @@ protected void run(Server server, User user, String commandLabel, String[] args) } String name = u.getName(); - if (server.getPluginManager().getPlugin("JPerms") != null) { - JohnyPerms permsPlugin = (JohnyPerms) server.getPluginManager().getPlugin("JPerms"); - if (permsPlugin != null) { - JohnyPermsAPI permsAPI = new JohnyPermsAPI(permsPlugin); - UUID uuid = getUUIDFromCache(name); - if (uuid != null) { - PermissionsUser jpUser = permsAPI.getUser(uuid); - if (jpUser != null) { - String groupName = jpUser.getGroup().getName().toLowerCase().trim(); - if (groupName.equals("trial") || - groupName.equals("helper") || - groupName.equals("moderator") || - groupName.equals("admin")) { - user.sendMessage(ChatColor.RED + "You cannot ignore staff members!"); - return; - } - } - } - } + if(u.hasPermission("essentials.ignore.exempt") || u.isOp()) { + user.setIgnoredPlayer(name, false); // Ensure they are not ignored. This is useful if an op/exempt player was ignored before gaining exempt status. + user.sendMessage(Util.format("ignoreExempt", u.getName())); + return; } if (user.isIgnoredPlayer(name)) { diff --git a/Essentials/src/main/resources/messages.properties b/Essentials/src/main/resources/messages.properties index 4ee7a2853..763de83e1 100644 --- a/Essentials/src/main/resources/messages.properties +++ b/Essentials/src/main/resources/messages.properties @@ -324,6 +324,7 @@ unableToSpawnMob = Unable to spawn mob. unbannedIP = Unbanned IP address. unbannedPlayer = Unbanned player. unignorePlayer = You are not ignoring player {0} anymore. +ignoreExempt = \u00a7cYou cannot ignore that player. unknownItemId = Unknown item id: {0} unknownItemInList = Unknown item {0} in {1} list. unknownItemName = Unknown item name: {0} From c7f777c84c147550c1eb3efa4e081fc60f66aaa5 Mon Sep 17 00:00:00 2001 From: Rhys B Date: Fri, 24 Oct 2025 13:40:27 +1000 Subject: [PATCH 9/9] Make ignore check occur earlier --- .../essentials/EssentialsPlayerListener.java | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java index 8f890c87c..bb227d093 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java +++ b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java @@ -43,22 +43,6 @@ public void onPlayerRespawn(final PlayerRespawnEvent event) { @Override public void onPlayerChat(final PlayerChatEvent event) { final User user = ess.getUser(event.getPlayer()); - if (user.isMuted()) { - event.setCancelled(true); - user.sendMessage(Util.i18n("playerMuted")); - LOGGER.info(Util.format("mutedUserSpeaks", user.getName())); - } - final Iterator it = event.getRecipients().iterator(); - while (it.hasNext()) { - final User u = ess.getUser(it.next()); - if (u.isIgnoredPlayer(user.getName())) { - it.remove(); - } - } - user.updateActivity(true); - if (ess.getSettings().changeDisplayName()) { - user.setDisplayName(user.getNick()); - } // If the user has ignore exempt permission, unignore them for all players if (user.hasPermission("essentials.ignore.exempt") || user.isOp()) { @@ -76,6 +60,23 @@ public void onPlayerChat(final PlayerChatEvent event) { } } } + + if (user.isMuted()) { + event.setCancelled(true); + user.sendMessage(Util.i18n("playerMuted")); + LOGGER.info(Util.format("mutedUserSpeaks", user.getName())); + } + final Iterator it = event.getRecipients().iterator(); + while (it.hasNext()) { + final User u = ess.getUser(it.next()); + if (u.isIgnoredPlayer(user.getName())) { + it.remove(); + } + } + user.updateActivity(true); + if (ess.getSettings().changeDisplayName()) { + user.setDisplayName(user.getNick()); + } } @Override