Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c414705
Adds pv use/see level methods to CorePlayer
EarthCow May 10, 2026
18fb581
Adds config NotifyVanishEnabledPlayersOnSilentMove
EarthCow May 10, 2026
82fc46f
Updates PV vanish levels on join
EarthCow May 11, 2026
44a1103
Silent notify vanish user impl
EarthCow May 11, 2026
f4681e2
Prevents triggerPlayer from being null
EarthCow May 11, 2026
b5bba78
Prevent extra List & extra loop
EarthCow May 13, 2026
713dc6b
Adds config NotifyRespectVanishLevels
EarthCow May 13, 2026
b8df48e
Impls NotifyRespectVanishLevels as outlined in 713dc6b
EarthCow May 13, 2026
70dda01
Updates outdated comment in CorePlayerListener
EarthCow May 14, 2026
7908acb
Bumps config version
EarthCow May 14, 2026
66a401a
Merge pull request #56 from RagingTech/feat/silent-notify-vanish-users
EarthCow May 14, 2026
8f254a4
Makes CorePlayer an abstract class & uses lombok
EarthCow May 14, 2026
eea966f
Merge pull request #58 from RagingTech/improvement/refactor-coreplayer
EarthCow May 14, 2026
9a94b17
Brings Auidence field to CorePlayer
EarthCow May 14, 2026
2d127ed
Corrects silent vanish level logic
EarthCow May 14, 2026
26406c4
Use proper parse target for sendSilentConsoleMessage
EarthCow May 14, 2026
ed385c1
Adds several test files
EarthCow May 14, 2026
5e7c95a
Merge pull request #59 from RagingTech/improvement/various-tests
EarthCow May 20, 2026
8b6db56
Adds PV MaxLevel to config
EarthCow May 20, 2026
cf6ccb5
Adds PV MaxLevel to PluginConfig
EarthCow May 20, 2026
330e883
Implements config pv max level
EarthCow May 22, 2026
02bf8ce
Merge pull request #60 from RagingTech/feat/pv-max-level-config-option
EarthCow May 22, 2026
704d494
Fixes pv vanish level util tests
EarthCow May 22, 2026
fd9603a
Merge pull request #61 from RagingTech/fix/pv-vanish-level-util-tests
EarthCow May 22, 2026
d5be5a7
Fix pv level 0 + njm.silent logic issue
EarthCow May 22, 2026
2a3d024
Merge pull request #62 from RagingTech/fix/pv-zero-level-njm-silent
EarthCow May 22, 2026
d5f76e7
Bump version
EarthCow May 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ dependencies {
testImplementation("org.mockito:mockito-core:5.19.0")
testImplementation("org.mockito:mockito-junit-jupiter:5.19.0")

testImplementation("org.sayandev:sayanvanish-api:1.7.0-SNAPSHOT")
testImplementation("net.luckperms:api:5.4")
testImplementation("net.kyori:adventure-text-serializer-plain:$adventureVersion")
testImplementation("io.github.miniplaceholders:miniplaceholders-api:3.0.1")
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Project metadata
group=xyz.earthcow.networkjoinmessages
version=3.5.1
version=3.6.0
description=A plugin handling join, leave and swap messages for proxy servers.

# Plugin.yml metadata
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package xyz.earthcow.networkjoinmessages.bungee.abstraction;

import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
Expand All @@ -12,18 +11,15 @@

import java.util.UUID;

public class BungeePlayer implements CorePlayer {
public class BungeePlayer extends CorePlayer {
private final ProxiedPlayer bungeePlayer;
private CoreBackendServer lastKnownConnectedServer;
private final Audience audience;
private String cachedLeaveMessage;
private boolean disconnecting = false;
private boolean premiumVanishHidden = false;

public BungeePlayer(ProxiedPlayer bungeePlayer) {
super(
new BungeeServer(bungeePlayer.getServer().getInfo()),
BungeeMain.getInstance().getAudiences().player(bungeePlayer)
);
this.bungeePlayer = bungeePlayer;
this.lastKnownConnectedServer = new BungeeServer(bungeePlayer.getServer().getInfo());
this.audience = BungeeMain.getInstance().getAudiences().player(bungeePlayer);
}

@Override
Expand All @@ -33,7 +29,7 @@ public String getName() {

@Override
public void sendMessage(Component component) {
audience.sendMessage(component);
getAudience().sendMessage(component);
}

@Override
Expand All @@ -56,56 +52,13 @@ public int getConnectionIdentity() {
public @Nullable CoreBackendServer getCurrentServer() {
Server server = bungeePlayer.getServer();
if (server == null) {
return lastKnownConnectedServer;
return getLastKnownConnectedServer();
}
return new BungeeServer(server.getInfo());
}

@Override
public @Nullable CoreBackendServer getLastKnownConnectedServer() {
return lastKnownConnectedServer;
}

@Override
public void setLastKnownConnectedServer(CoreBackendServer server) {
lastKnownConnectedServer = server;
}

@Override
public @NotNull Audience getAudience() {
return audience;
}

@Override
public boolean isInLimbo() {
return false;
}

@Override
public String getCachedLeaveMessage() {
return cachedLeaveMessage;
}
@Override
public void setCachedLeaveMessage(String cachedLeaveMessage) {
this.cachedLeaveMessage = cachedLeaveMessage;
}

@Override
public boolean isDisconnecting() {
return disconnecting;
}
@Override
public void setDisconnecting() {
this.disconnecting = true;
}

@Override
public boolean getPremiumVanishHidden() {
return premiumVanishHidden;
}

@Override
public void setPremiumVanishHidden(boolean premiumVanishHidden) {
this.premiumVanishHidden = premiumVanishHidden;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public Core(CorePlugin plugin, PremiumVanish premiumVanish) {

// Message building
MessageFormatter messageFormatter = new MessageFormatter(plugin, config, sayanVanishHook);
ReceiverResolver receiverResolver = new ReceiverResolver(plugin, config);
ReceiverResolver receiverResolver = new ReceiverResolver(plugin, config, sayanVanishHook != null, premiumVanish != null);
MessageHandler messageHandler = new MessageHandler(plugin, config, stateStore, placeholderResolver, receiverResolver);

// Player event helpers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import xyz.earthcow.networkjoinmessages.common.config.PluginConfig;
import xyz.earthcow.networkjoinmessages.common.player.PlayerStateStore;
import xyz.earthcow.networkjoinmessages.common.util.Formatter;
import xyz.earthcow.networkjoinmessages.common.MessageType;
import xyz.earthcow.networkjoinmessages.common.util.PlaceholderResolver;

import java.util.*;
Expand Down Expand Up @@ -99,11 +98,11 @@ public void broadcastMessage(String text, MessageType type, String from, String
public void broadcastMessage(
String text, MessageType type,
String from, String to,
@Nullable CorePlayer parseTarget,
@NotNull CorePlayer parseTarget,
boolean silent
) {
if (silent) {
broadcastSilentMessage(text, type, from, to, parseTarget);
broadcastSilentMessage(text, type, from, to, parseTarget, true);
return;
}

Expand All @@ -127,19 +126,19 @@ public void broadcastMessage(
}
}

private void broadcastSilentMessage(
@NotNull String text, @NotNull MessageType type,
@NotNull String from, @NotNull String to,
@Nullable CorePlayer parseTarget
public void broadcastSilentMessage(
@NotNull String text, @NotNull MessageType type,
@NotNull String from, @NotNull String to,
@NotNull CorePlayer triggerPlayer,
boolean isParseTarget
) {
sendSilentConsoleMessage(type, from, to, parseTarget);
CorePlayer parseTarget = isParseTarget ? triggerPlayer : null;

if (!config.isNotifyAdminsOnSilentMove()) return;
sendSilentConsoleMessage(type, from, to, parseTarget);

for (CorePlayer player : plugin.getAllPlayers()) {
if (player.hasPermission("networkjoinmessages.silent")) {
sendMessage(player, config.getSilentPrefix() + text, parseTarget);
}
if (!receiverResolver.isSilentReceiver(player, triggerPlayer)) continue;
sendMessage(player, config.getSilentPrefix() + text, parseTarget);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
package xyz.earthcow.networkjoinmessages.common.abstraction;

import lombok.Getter;
import lombok.Setter;
import net.kyori.adventure.audience.Audience;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.UUID;

public interface CorePlayer extends CoreCommandSender {
@Getter @Setter
public abstract class CorePlayer implements CoreCommandSender {
// Fields
private CoreBackendServer lastKnownConnectedServer;
private boolean disconnecting = false;
private String cachedLeaveMessage;
private Audience audience;
private boolean premiumVanishHidden = false;
private int premiumVanishUseLevel = 0;
private int premiumVanishSeeLevel = 0;

public CorePlayer(CoreBackendServer lastKnownConnectedServer, Audience audience) {
this.lastKnownConnectedServer = lastKnownConnectedServer;
this.audience = audience;
}

// Abstract
@NotNull
UUID getUniqueId();

int getConnectionIdentity();

@Nullable
CoreBackendServer getCurrentServer();

public abstract UUID getUniqueId();
public abstract int getConnectionIdentity();
@Nullable
CoreBackendServer getLastKnownConnectedServer();

void setLastKnownConnectedServer(CoreBackendServer server);

@NotNull
Audience getAudience();

boolean isInLimbo();

String getCachedLeaveMessage();
void setCachedLeaveMessage(String cachedLeaveMessage);

boolean isDisconnecting();
void setDisconnecting();

boolean getPremiumVanishHidden();
void setPremiumVanishHidden(boolean premiumVanishHidden);
public abstract CoreBackendServer getCurrentServer();
public abstract boolean isInLimbo();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package xyz.earthcow.networkjoinmessages.common.broadcast;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.earthcow.networkjoinmessages.common.abstraction.CoreBackendServer;
import xyz.earthcow.networkjoinmessages.common.abstraction.CorePlayer;
Expand All @@ -18,10 +19,15 @@ public final class ReceiverResolver {

private final CorePlugin plugin;
private final PluginConfig config;
private final boolean hasSayanVanish;
private final boolean hasPremiumVanish;

public ReceiverResolver(CorePlugin plugin, PluginConfig config) {

public ReceiverResolver(CorePlugin plugin, PluginConfig config, boolean hasSayanVanish, boolean hasPremiumVanish) {
this.plugin = plugin;
this.config = config;
this.hasSayanVanish = hasSayanVanish;
this.hasPremiumVanish = hasPremiumVanish;
}

// --- Audience resolution ---
Expand Down Expand Up @@ -77,6 +83,44 @@ private List<CorePlayer> resolve(
return receivers;
}

/**
* Determines if a player should receive a silent message.<br>
* A player will receive a silent message if any one of the following is true:
* <ol>
* <li>If {@code NotifyAdminsOnSilentMove} is enabled and the player holds the
* {@code networkjoinmessages.silent} permission</li>
* <li>If SayanVanish is present, {@code SVNotifyVanishEnabledPlayersOnSilentMove} is true, and the player holds
* the {@code sayanvanish.vanish.use} permission</li>
* <li>If PremiumVanish is present, {@code PVNotifyVanishEnabledPlayersOnSilentMove} is true, then if
* {@code PVNotifyRespectVanishLevels}:
* <ul>
* <li><b>Is true</b> and the player's {@code pv.see} level is the same as or greater than the trigger player's
* {@code pv.use} level</li>
* <li><b>Is false</b> and the player holds either {@code pv.use} or {@code pv.see}</li>
* </ul>
* </li>
* </ol>
* @param player The player to determine whether they are a silent receiver or not
* @param triggerPlayer The player who triggered a message
* @return Whether the player is a silent receiver (true) or not (false)
*/
public boolean isSilentReceiver(@NotNull CorePlayer player, @NotNull CorePlayer triggerPlayer) {
if (config.isNotifyAdminsOnSilentMove() && player.hasPermission("networkjoinmessages.silent"))
return true;
if (hasSayanVanish && config.isSVNotifyVanishEnabledPlayersOnSilentMove()
&& player.hasPermission("sayanvanish.vanish.use"))
return true;
if (hasPremiumVanish && config.isPVNotifyVanishEnabledPlayersOnSilentMove()) {
if (config.isPVNotifyRespectVanishLevels()) {
// If the trigger player has level 0 they must have networkjoinmessages.silent and no pv permissions
if (triggerPlayer.getPremiumVanishUseLevel() == 0) return false;
return player.getPremiumVanishSeeLevel() >= triggerPlayer.getPremiumVanishUseLevel();
}
return (player.hasPermission("pv.use") || player.hasPermission("pv.see"));
}
Comment thread
EarthCow marked this conversation as resolved.
return false;
}

// --- Blacklist / whitelist checks ---

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public final class PluginConfig {
@Getter private int leaveCacheDuration;
@Getter private int leaveJoinBufferDuration;
@Getter private long PPBRequestTimeout;
@Getter private int PVMaxLevel;

/**
* Default silent state for players with the {@code networkjoinmessages.silent} permission.
Expand Down Expand Up @@ -119,11 +120,14 @@ public final class PluginConfig {
// Third-party plugin integration flags
@Getter private boolean SVTreatVanishedPlayersAsSilent;
@Getter private boolean SVRemoveVanishedPlayersFromPlayerCount;
@Getter private boolean SVNotifyVanishEnabledPlayersOnSilentMove;
@Getter private boolean PVTreatVanishedPlayersAsSilent;
@Getter private boolean PVRemoveVanishedPlayersFromPlayerCount;
@Getter private boolean PVSpoofJoinMessageOnShow;
@Getter private boolean PVSpoofLeaveMessageOnHide;
@Getter private boolean PVTreatVanishedOnJoin;
@Getter private boolean PVNotifyVanishEnabledPlayersOnSilentMove;
@Getter private boolean PVNotifyRespectVanishLevels;
@Getter private boolean shouldSuppressLimboSwap;
@Getter private boolean shouldSuppressLimboJoin;
@Getter private boolean shouldSuppressLimboLeave;
Expand Down Expand Up @@ -219,17 +223,21 @@ public void reload() {
serverJoinMessageDisabled = config.getStringList("Settings.IgnoreJoinMessagesList");
serverLeaveMessageDisabled = config.getStringList("Settings.IgnoreLeaveMessagesList");

PPBRequestTimeout = config.getLong("OtherPlugins.PAPIProxyBridge.RequestTimeout");
SVTreatVanishedPlayersAsSilent = config.getBoolean("OtherPlugins.SayanVanish.TreatVanishedPlayersAsSilent");
SVRemoveVanishedPlayersFromPlayerCount = config.getBoolean("OtherPlugins.SayanVanish.RemoveVanishedPlayersFromPlayerCount");
PVTreatVanishedPlayersAsSilent = config.getBoolean("OtherPlugins.PremiumVanish.TreatVanishedPlayersAsSilent");
PVRemoveVanishedPlayersFromPlayerCount = config.getBoolean("OtherPlugins.PremiumVanish.RemoveVanishedPlayersFromPlayerCount");
PVSpoofJoinMessageOnShow = config.getBoolean("OtherPlugins.PremiumVanish.SpoofJoinMessageOnShow");
PVSpoofLeaveMessageOnHide = config.getBoolean("OtherPlugins.PremiumVanish.SpoofLeaveMessageOnHide");
PVTreatVanishedOnJoin = config.getBoolean("OtherPlugins.PremiumVanish.TreatVanishedOnJoin");
shouldSuppressLimboSwap = config.getBoolean("OtherPlugins.LimboAPI.SuppressSwapMessages");
shouldSuppressLimboJoin = config.getBoolean("OtherPlugins.LimboAPI.SuppressJoinMessages");
shouldSuppressLimboLeave = config.getBoolean("OtherPlugins.LimboAPI.SuppressLeaveMessages");
PPBRequestTimeout = config.getLong("OtherPlugins.PAPIProxyBridge.RequestTimeout");
SVTreatVanishedPlayersAsSilent = config.getBoolean("OtherPlugins.SayanVanish.TreatVanishedPlayersAsSilent");
SVRemoveVanishedPlayersFromPlayerCount = config.getBoolean("OtherPlugins.SayanVanish.RemoveVanishedPlayersFromPlayerCount");
SVNotifyVanishEnabledPlayersOnSilentMove = config.getBoolean("OtherPlugins.SayanVanish.NotifyVanishEnabledPlayersOnSilentMove");
PVTreatVanishedPlayersAsSilent = config.getBoolean("OtherPlugins.PremiumVanish.TreatVanishedPlayersAsSilent");
PVRemoveVanishedPlayersFromPlayerCount = config.getBoolean("OtherPlugins.PremiumVanish.RemoveVanishedPlayersFromPlayerCount");
PVSpoofJoinMessageOnShow = config.getBoolean("OtherPlugins.PremiumVanish.SpoofJoinMessageOnShow");
PVSpoofLeaveMessageOnHide = config.getBoolean("OtherPlugins.PremiumVanish.SpoofLeaveMessageOnHide");
PVTreatVanishedOnJoin = config.getBoolean("OtherPlugins.PremiumVanish.TreatVanishedOnJoin");
PVNotifyVanishEnabledPlayersOnSilentMove = config.getBoolean("OtherPlugins.PremiumVanish.NotifyVanishEnabledPlayersOnSilentMove");
PVNotifyRespectVanishLevels = config.getBoolean("OtherPlugins.PremiumVanish.NotifyRespectVanishLevels");
PVMaxLevel = config.getInt("OtherPlugins.PremiumVanish.MaxLevel");
shouldSuppressLimboSwap = config.getBoolean("OtherPlugins.LimboAPI.SuppressSwapMessages");
shouldSuppressLimboJoin = config.getBoolean("OtherPlugins.LimboAPI.SuppressJoinMessages");
shouldSuppressLimboLeave = config.getBoolean("OtherPlugins.LimboAPI.SuppressLeaveMessages");

plugin.getCoreLogger().setDebug(config.getBoolean("debug"));

Expand Down
Loading
Loading