From e9237a0d4c87b71e109dbec901602dab8c555371 Mon Sep 17 00:00:00 2001 From: BlvckBytes Date: Fri, 15 May 2026 18:54:21 +0200 Subject: [PATCH 1/3] implemented config-option vanish-fake-join-leave, analogous to EssentialsDiscord --- .../essentials/EssentialsPlayerListener.java | 64 ++++++++++++++----- .../com/earth2me/essentials/ISettings.java | 2 + .../com/earth2me/essentials/Settings.java | 5 ++ Essentials/src/main/resources/config.yml | 3 + 4 files changed, 58 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 3b8c2f6e3f4..36e49157cc8 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java +++ b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java @@ -21,6 +21,7 @@ import io.papermc.paper.event.player.PlayerServerFullCheckEvent; import net.ess3.api.IEssentials; import net.ess3.api.events.AfkStatusChangeEvent; +import net.ess3.api.events.VanishStatusChangeEvent; import net.ess3.provider.CommandSendListenerProvider; import net.ess3.provider.FormattedCommandAliasProvider; import net.ess3.provider.InventoryViewProvider; @@ -32,6 +33,7 @@ import net.essentialsx.api.v2.events.AsyncUserDataLoadEvent; import org.bukkit.BanEntry; import org.bukkit.BanList; +import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; @@ -297,14 +299,7 @@ public void onPlayerQuit(final PlayerQuitEvent event) { if (hideJoinQuitMessages() || ess.getSettings().allowSilentJoinQuit() && user.isAuthorized("essentials.silentquit")) { event.setQuitMessage(null); } else if (ess.getSettings().isCustomQuitMessage() && event.getQuitMessage() != null) { - final Player player = event.getPlayer(); - final String msg = ess.getSettings().getCustomQuitMessage() - .replace("{PLAYER}", player.getDisplayName()) - .replace("{USERNAME}", player.getName()) - .replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size() - 1)) // Subtract 1 as the leaving player is still online during this time - .replace("{UPTIME}", DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime())) - .replace("{PREFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getPrefix(player))) - .replace("{SUFFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getSuffix(player))); + final String msg = buildQuitMessage(user); event.setQuitMessage(msg.isEmpty() ? null : msg); } @@ -341,6 +336,50 @@ public void onPlayerQuit(final PlayerQuitEvent event) { user.dispose(); } + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onVanishStatusChange(final VanishStatusChangeEvent event) { + if (!ess.getSettings().isVanishFakeJoinLeave()) { + return; + } + + if (event.getValue()) { + final String quitMessage = buildQuitMessage((User) event.getAffected()); + + if (!quitMessage.isEmpty()) { + Bukkit.broadcastMessage(quitMessage); + } + + return; + } + + final String joinMessage = buildJoinMessage((User) event.getAffected(), false, null); + + if (!joinMessage.isEmpty()) { + Bukkit.broadcastMessage(joinMessage); + } + } + + private String buildJoinMessage(final User user, boolean newUsername, String lastAccountName) { + return (newUsername && ess.getSettings().isCustomNewUsernameMessage() ? ess.getSettings().getCustomNewUsernameMessage() : ess.getSettings().getCustomJoinMessage()) + .replace("{PLAYER}", user.getDisplayName()).replace("{USERNAME}", user.getName()) + .replace("{UNIQUE}", NumberFormat.getInstance().format(ess.getUsers().getUserCount())) + .replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size())) + .replace("{UPTIME}", DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime())) + .replace("{PREFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getPrefix(user.getBase()))) + .replace("{SUFFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getSuffix(user.getBase()))) + .replace("{OLDUSERNAME}", lastAccountName == null ? "" : lastAccountName); + } + + private String buildQuitMessage(final User user) { + return ess.getSettings().getCustomQuitMessage() + .replace("{PLAYER}", user.getDisplayName()) + .replace("{USERNAME}", user.getName()) + .replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size() - 1)) // Subtract 1 as the leaving player is still online during this time + .replace("{UPTIME}", DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime())) + .replace("{PREFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getPrefix(user.getBase()))) + .replace("{SUFFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getSuffix(user.getBase()))); + } + @SuppressWarnings("UnstableApiUsage") private final class JoinListener1_21 implements Listener { private final Map newUserLocales = new ConcurrentHashMap<>(); @@ -458,14 +497,7 @@ private void joinFlow(final User user, final long currentTime, final String mess } else if (message == null || hideJoinQuitMessages()) { effectiveMessage = null; } else if (ess.getSettings().isCustomJoinMessage()) { - final String msg = (newUsername && ess.getSettings().isCustomNewUsernameMessage() ? ess.getSettings().getCustomNewUsernameMessage() : ess.getSettings().getCustomJoinMessage()) - .replace("{PLAYER}", user.getDisplayName()).replace("{USERNAME}", user.getName()) - .replace("{UNIQUE}", NumberFormat.getInstance().format(ess.getUsers().getUserCount())) - .replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size())) - .replace("{UPTIME}", DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime())) - .replace("{PREFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getPrefix(user.getBase()))) - .replace("{SUFFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getSuffix(user.getBase()))) - .replace("{OLDUSERNAME}", lastAccountName == null ? "" : lastAccountName); + final String msg = buildJoinMessage(user, newUsername, lastAccountName); effectiveMessage = msg.isEmpty() ? null : msg; } else if (ess.getSettings().allowSilentJoinQuit()) { effectiveMessage = message; diff --git a/Essentials/src/main/java/com/earth2me/essentials/ISettings.java b/Essentials/src/main/java/com/earth2me/essentials/ISettings.java index 11566ca0459..bfbf1be0b47 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/ISettings.java +++ b/Essentials/src/main/java/com/earth2me/essentials/ISettings.java @@ -229,6 +229,8 @@ public interface ISettings extends IConf { boolean sleepIgnoresVanishedPlayers(); + boolean isVanishFakeJoinLeave(); + boolean isAfkListName(); String getAfkListName(); diff --git a/Essentials/src/main/java/com/earth2me/essentials/Settings.java b/Essentials/src/main/java/com/earth2me/essentials/Settings.java index fbec7ea904a..f9cba63f351 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/Settings.java +++ b/Essentials/src/main/java/com/earth2me/essentials/Settings.java @@ -1350,6 +1350,11 @@ public boolean sleepIgnoresVanishedPlayers() { return config.getBoolean("sleep-ignores-vanished-player", true); } + @Override + public boolean isVanishFakeJoinLeave() { + return config.getBoolean("vanish-fake-join-leave", false); + } + public String _getAfkListName() { return FormatUtil.replaceFormat(config.getString("afk-list-name", "none")); } diff --git a/Essentials/src/main/resources/config.yml b/Essentials/src/main/resources/config.yml index eb441235b6b..d5bd052a3ca 100644 --- a/Essentials/src/main/resources/config.yml +++ b/Essentials/src/main/resources/config.yml @@ -544,6 +544,9 @@ sleep-ignores-afk-players: true # Players with the permission 'essentials.sleepingignored' will always be ignored. sleep-ignores-vanished-player: true +# Whether or not fake join and leave messages should be sent to the ingame-chat when a player toggles vanish. +vanish-fake-join-leave: false + # Change the player's /list name when they are AFK. This is none by default, which specifies that Essentials # should not interfere with the AFK player's /list name. # You may use color codes, {USERNAME} for the player's name, or {PLAYER} for the player's display name. From b004315459b25021bf059815052fd9f72f9bc491 Mon Sep 17 00:00:00 2001 From: BlvckBytes Date: Fri, 15 May 2026 19:09:46 +0200 Subject: [PATCH 2/3] the vanish-fake-join-leave messages now fall back to vanilla format, if applicable --- .../essentials/EssentialsPlayerListener.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java index 36e49157cc8..dd825e2b42e 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java +++ b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java @@ -34,6 +34,7 @@ import org.bukkit.BanEntry; import org.bukkit.BanList; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; @@ -343,20 +344,21 @@ public void onVanishStatusChange(final VanishStatusChangeEvent event) { } if (event.getValue()) { - final String quitMessage = buildQuitMessage((User) event.getAffected()); + String quitMessage = buildQuitMessage((User) event.getAffected()); - if (!quitMessage.isEmpty()) { - Bukkit.broadcastMessage(quitMessage); - } + if (quitMessage.isEmpty()) + quitMessage = ChatColor.YELLOW + event.getAffected().getName() + " left the game"; + Bukkit.broadcastMessage(quitMessage); return; } - final String joinMessage = buildJoinMessage((User) event.getAffected(), false, null); + String joinMessage = buildJoinMessage((User) event.getAffected(), false, null); - if (!joinMessage.isEmpty()) { - Bukkit.broadcastMessage(joinMessage); - } + if (joinMessage.isEmpty()) + joinMessage = ChatColor.YELLOW + event.getAffected().getName() + " joined the game"; + + Bukkit.broadcastMessage(joinMessage); } private String buildJoinMessage(final User user, boolean newUsername, String lastAccountName) { From 304953956a3ae3c5be7a957bab094657835645e4 Mon Sep 17 00:00:00 2001 From: BlvckBytes Date: Fri, 15 May 2026 19:21:00 +0200 Subject: [PATCH 3/3] fixed vanish-fake-join-leave detecting custom join/quit messages when falling back --- .../essentials/EssentialsPlayerListener.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java index dd825e2b42e..e8321e1890a 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java +++ b/Essentials/src/main/java/com/earth2me/essentials/EssentialsPlayerListener.java @@ -344,19 +344,19 @@ public void onVanishStatusChange(final VanishStatusChangeEvent event) { } if (event.getValue()) { - String quitMessage = buildQuitMessage((User) event.getAffected()); + String quitMessage = ChatColor.YELLOW + event.getAffected().getName() + " left the game"; - if (quitMessage.isEmpty()) - quitMessage = ChatColor.YELLOW + event.getAffected().getName() + " left the game"; + if (ess.getSettings().isCustomQuitMessage()) + quitMessage = buildQuitMessage((User) event.getAffected());; Bukkit.broadcastMessage(quitMessage); return; } - String joinMessage = buildJoinMessage((User) event.getAffected(), false, null); + String joinMessage = ChatColor.YELLOW + event.getAffected().getName() + " joined the game"; - if (joinMessage.isEmpty()) - joinMessage = ChatColor.YELLOW + event.getAffected().getName() + " joined the game"; + if (ess.getSettings().isCustomJoinMessage()) + joinMessage = buildJoinMessage((User) event.getAffected(), false, null);; Bukkit.broadcastMessage(joinMessage); }