Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
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,42 @@ 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()) {
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 @@ -119,11 +119,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 +222,20 @@ 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");
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import xyz.earthcow.networkjoinmessages.common.storage.PlayerJoinTracker;
import xyz.earthcow.networkjoinmessages.common.MessageType;
import xyz.earthcow.networkjoinmessages.common.util.PlaceholderResolver;
import xyz.earthcow.networkjoinmessages.common.util.PremiumVanishLevelUtil;

/**
* Routes platform-level player events (join, swap, disconnect) to the appropriate handlers.
Expand Down Expand Up @@ -100,7 +101,7 @@ public void onDisconnect(@NotNull CorePlayer player) {
plugin.getCoreLogger().debug("Duplicate disconnect ignored for " + player.getName());
return;
}
player.setDisconnecting();
player.setDisconnecting(true);

if (shouldSkipLeave(player)) {
cleanup(player);
Expand All @@ -119,8 +120,13 @@ private void handleJoin(@NotNull CorePlayer player, @NotNull CoreBackendServer s
player.setLastKnownConnectedServer(server);

PremiumVanish pv = plugin.getVanishAPI();
if (pv != null && pv.isVanished(player.getUniqueId())) {
player.setPremiumVanishHidden(true);
if (pv != null) {
if (config.isPVNotifyVanishEnabledPlayersOnSilentMove() && config.isPVNotifyRespectVanishLevels()) {
PremiumVanishLevelUtil.updateVanishLevels(player);
}
if (pv.isVanished(player.getUniqueId())) {
player.setPremiumVanishHidden(true);
}
}

leaveMessageCache.refresh(player);
Expand Down Expand Up @@ -166,8 +172,8 @@ private void broadcastLeave(@NotNull CorePlayer player) {
boolean silent = silenceChecker.isSilent(player);
String serverName = player.getCurrentServer().getName();

// Pass null as parseTarget — player is gone, placeholders already resolved in cache
messageHandler.broadcastMessage(message, MessageType.LEAVE, serverName, "", null, silent);
// Pass player as triggerPlayer but false for isParseTarget as the placeholders are already resolved in cache
messageHandler.broadcastSilentMessage(message, MessageType.LEAVE, serverName, "", player, false);
fireLeaveEvent(player, serverName, message, silent);
}

Expand Down
Loading
Loading