Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
9 changes: 8 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,18 @@ repositories {
// Elytrium
maven("https://maven.elytrium.net/repo/")
// SayanDevelopment
maven("https://repo.sayandev.org/snapshots") {
// Invalid SSL certificate local jar file utilized for the time being
flatDir {
dirs("libs")
content {
includeGroup("org.sayandev")
}
}
// maven("https://repo.sayandev.org/snapshots") {
// content {
// includeGroup("org.sayandev")
// }
// }
}

dependencies {
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.3.0
version=3.4.0
description=A plugin handling join, leave and swap messages for proxy servers.

# Plugin.yml metadata
Expand Down
Binary file added libs/sayanvanish-api-1.7.0-SNAPSHOT.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@ public void runTaskAsync(Runnable task) {
getProxy().getScheduler().runAsync(this, task);
}

@Override
public int runTaskAsyncLater(Runnable task, int timeInMillisecondsLater) {
return getProxy().getScheduler().schedule(this, task, timeInMillisecondsLater, TimeUnit.MILLISECONDS).getId();
}

@Override
public boolean isPluginLoaded(String pluginName) {
return getProxy().getPluginManager().getPlugin(pluginName) != null;
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/xyz/earthcow/networkjoinmessages/common/Storage.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ public final class Storage {
@Getter
private int leaveCacheDuration;

@Getter
private int leaveJoinBufferDuration;

/**
* The default silent state of a player joining with the networkjoinmessages.silent permission
* Default: true - Someone joining with the permission will be silent (not send a join message)
Expand Down Expand Up @@ -147,6 +150,8 @@ public final class Storage {
private boolean PVSpoofJoinMessageOnShow;
@Getter
private boolean PVSpoofLeaveMessageOnHide;
@Getter
private boolean PVTreatVanishedOnJoin;
// LimboAPI
@Getter
private boolean shouldSuppressLimboSwap;
Expand Down Expand Up @@ -217,6 +222,7 @@ public void setUpDefaultValuesFromConfig() {
/// Settings

this.leaveCacheDuration = config.getInt("Settings.LeaveNetworkMessageCacheDuration");
this.leaveJoinBufferDuration = config.getInt("Settings.LeaveJoinBufferDuration");

this.silentJoinDefaultState = config.getBoolean("Settings.SilentJoinDefaultState");

Expand Down Expand Up @@ -258,6 +264,7 @@ public void setUpDefaultValuesFromConfig() {
this.PVRemoveVanishedPlayersFromPlayerCount = config.getBoolean("OtherPlugins.PremiumVanish.RemoveVanishedPlayersFromPlayerCount");
this.PVSpoofJoinMessageOnShow = config.getBoolean("OtherPlugins.PremiumVanish.SpoofJoinMessageOnShow");
this.PVSpoofLeaveMessageOnHide = config.getBoolean("OtherPlugins.PremiumVanish.SpoofLeaveMessageOnHide");
this.PVTreatVanishedOnJoin = config.getBoolean("OtherPlugins.PremiumVanish.TreatVanishedOnJoin");

this.shouldSuppressLimboSwap = config.getBoolean("OtherPlugins.LimboAPI.SuppressSwapMessages");
this.shouldSuppressLimboJoin = config.getBoolean("OtherPlugins.LimboAPI.SuppressJoinMessages");
Expand Down Expand Up @@ -292,6 +299,16 @@ public void setUpDefaultValuesFromConfig() {
);
this.leaveCacheDuration = 0;
}

// Verify leave join buffer duration
if (leaveJoinBufferDuration < 0) {
plugin.getCoreLogger()
.info(
"Setting error: Settings.LeaveJoinBufferDuration " +
"requires a non-negative value. Defaulting to 0."
);
this.leaveJoinBufferDuration = 0;
}
}

public boolean getSilentMessageState(CorePlayer player) {
Expand Down Expand Up @@ -692,6 +709,7 @@ public Collection<CustomChart> getCustomCharts() {

customCharts.add(new SimplePie("premium_vanish_vanished_are_silent", () -> String.valueOf(PVTreatVanishedPlayersAsSilent)));
customCharts.add(new SimplePie("premium_vanish_remove_vanished_from_player_count", () -> String.valueOf(PVRemoveVanishedPlayersFromPlayerCount)));
customCharts.add(new SimplePie("premium_vanish_treat_vanished_on_join", () -> String.valueOf(PVTreatVanishedOnJoin)));

customCharts.add(new SimplePie("limbo_api_suppress_swap", () -> String.valueOf(shouldSuppressLimboSwap)));
customCharts.add(new SimplePie("limbo_api_suppress_join", () -> String.valueOf(shouldSuppressLimboJoin)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public interface CorePlugin {
void cancelTask(int taskId);
int runTaskRepeatedly(Runnable task, int timeInSecondsLater);
void runTaskAsync(Runnable task);
int runTaskAsyncLater(Runnable task, int timeInMillisecondsLater);

boolean isPluginLoaded(String pluginName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
import xyz.earthcow.networkjoinmessages.common.util.H2PlayerJoinTracker;
import xyz.earthcow.networkjoinmessages.common.util.MessageType;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public class CorePlayerListener {

private final CorePlugin plugin;
Expand All @@ -22,11 +26,15 @@ public class CorePlayerListener {

private H2PlayerJoinTracker firstJoinTracker;

private final Map<UUID, Integer> leaveJoinBuffer;

@Nullable
private final SayanVanishHook sayanVanishHook;

@Nullable
private final PremiumVanish premiumVanish;

private final String PVJoinVanishedPerm = "pv.joinvanished";

public CorePlayerListener(CorePlugin plugin, Storage storage, MessageHandler messageHandler, @Nullable SayanVanishHook sayanVanishHook, @Nullable PremiumVanish premiumVanish) {
this.plugin = plugin;
Expand All @@ -42,6 +50,8 @@ public CorePlayerListener(CorePlugin plugin, Storage storage, MessageHandler mes
plugin.getCoreLogger().debug("Exception: " + ex);
}

this.leaveJoinBuffer = new ConcurrentHashMap<>();

}

/**
Expand All @@ -51,13 +61,14 @@ public CorePlayerListener(CorePlugin plugin, Storage storage, MessageHandler mes
*/
private boolean isSilentEvent(@NotNull CorePlayer player) {
// Event is silent if, the player has a silent message state OR
// premiumVanish is present, the treat vanished players as silent option is true, and the player is vanished
// premiumVanish is present, the treat vanished players as silent option is true, and the player is vanished or
// the TreatVanishedOnJoin option is enabled and the player has the pv.joinvanished permission
plugin.getCoreLogger().debug("Checking if the event for player " + player.getName() + " should been silent:");
plugin.getCoreLogger().debug(String.format(
"silent message state: %s,%n" +
"SayanVanish hook is NOT null: %s, SVTreatVanishedPlayersAsSilent: %s, SayanVanish player is vanished: %s,%n" +
"PremiumVanish hook is NOT null: %s, PVTreatVanishedPlayersAsSilent: %s, PremiumVanish player is vanished: %s,%n" +
"PremiumVanish event hidden: %s"
"PremiumVanish event hidden: %s, PVTreatVanishedOnJoin: %s, Player has pv.joinvanished permission: %s"
,
storage.getSilentMessageState(player),
sayanVanishHook != null,
Expand All @@ -66,12 +77,18 @@ private boolean isSilentEvent(@NotNull CorePlayer player) {
premiumVanish != null,
storage.isPVTreatVanishedPlayersAsSilent(),
premiumVanish != null ? premiumVanish.isVanished(player.getUniqueId()) : "NA",
player.getPremiumVanishHidden()
player.getPremiumVanishHidden(),
storage.isPVTreatVanishedOnJoin(),
player.hasPermission(PVJoinVanishedPerm)
));
if (storage.isPVTreatVanishedOnJoin() && player.hasPermission(PVJoinVanishedPerm)) {
player.setPremiumVanishHidden(true);
}
return storage.getSilentMessageState(player) ||
(sayanVanishHook != null && storage.isSVTreatVanishedPlayersAsSilent() && sayanVanishHook.isVanished(player))
||
(premiumVanish != null && storage.isPVTreatVanishedPlayersAsSilent() && (premiumVanish.isVanished(player.getUniqueId()) || player.getPremiumVanishHidden()));
(premiumVanish != null && storage.isPVTreatVanishedPlayersAsSilent()
&& (premiumVanish.isVanished(player.getUniqueId()) || player.getPremiumVanishHidden()));
}

private boolean shouldNotBroadcast(@NotNull CorePlayer player, @NotNull MessageType type) {
Expand Down Expand Up @@ -135,6 +152,14 @@ private boolean shouldNotBroadcast(@NotNull CorePlayer player, @NotNull MessageT
" - suppress limbo join");
return true;
}

Integer leaveJoinBufferTaskId = leaveJoinBuffer.remove(player.getUniqueId());
if (leaveJoinBufferTaskId != null) {
plugin.cancelTask(leaveJoinBufferTaskId);
plugin.getCoreLogger().debug("Skipping " + player.getName() +
" - returned within LeaveJoinBufferDuration");
return true;
}
}
case LEAVE -> {
if (!storage.isConnected(player) || !storage.isLeaveNetworkMessageEnabled() || storage.isBlacklisted(player)) {
Expand All @@ -149,6 +174,17 @@ private boolean shouldNotBroadcast(@NotNull CorePlayer player, @NotNull MessageT
" - suppress limbo leave");
return true;
}

if (storage.getLeaveJoinBufferDuration() > 0 && leaveJoinBuffer.get(player.getUniqueId()) == null) {
leaveJoinBuffer.put(player.getUniqueId(), plugin.runTaskAsyncLater(() -> {
this.broadcastLeaveMessage(player);
leaveJoinBuffer.remove(player.getUniqueId());
},
storage.getLeaveJoinBufferDuration()));
plugin.getCoreLogger().debug("Skipping " + player.getName() +
" - allotting buffer time to rejoin before broadcasting leave message");
return true;
}
}
}
return false;
Expand Down Expand Up @@ -301,6 +337,14 @@ public void onDisconnect(@NotNull CorePlayer player) {
return;
}

broadcastLeaveMessage(player);

plugin.getPlayerManager().removePlayer(player.getUniqueId());
storage.setConnected(player, false);
messageHandler.stopLeaveCacheTaskForPlayer(player);
}

private void broadcastLeaveMessage(@NotNull CorePlayer player) {
String message = player.getCachedLeaveMessage();

// Silent
Expand All @@ -312,18 +356,14 @@ public void onDisconnect(@NotNull CorePlayer player) {
Component formattedMessage = Formatter.deserialize(message);
// Call the custom NetworkLeaveEvent
NetworkLeaveEvent networkLeaveEvent = new NetworkLeaveEvent(
player,
player.getCurrentServer().getName(),
storage.getServerDisplayName(player.getCurrentServer().getName()),
isSilent,
Formatter.serialize(formattedMessage),
Formatter.sanitize(formattedMessage)
player,
player.getCurrentServer().getName(),
storage.getServerDisplayName(player.getCurrentServer().getName()),
isSilent,
Formatter.serialize(formattedMessage),
Formatter.sanitize(formattedMessage)
);
plugin.fireEvent(networkLeaveEvent);

plugin.getPlayerManager().removePlayer(player.getUniqueId());
storage.setConnected(player, false);
messageHandler.stopLeaveCacheTaskForPlayer(player);
}

public H2PlayerJoinTracker getPlayerJoinTracker() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public CorePremiumVanishListener(@NotNull CoreLogger logger, @NotNull Storage st
}

public void handlePremiumVanishShow(@NotNull CorePlayer p) {
if (!p.getPremiumVanishHidden()) {
return;
}
logger.debug("Setting PremiumVanishHidden to FALSE for player " + p.getName());
p.setPremiumVanishHidden(false);
if (storage.isPVSpoofJoinMessageOnShow()) {
Expand All @@ -26,6 +29,9 @@ public void handlePremiumVanishShow(@NotNull CorePlayer p) {
}

public void handlePremiumVanishHide(@NotNull CorePlayer p) {
if (p.getPremiumVanishHidden()) {
return;
}
logger.debug("Setting PremiumVanishHidden to TRUE for player " + p.getName());
p.setPremiumVanishHidden(true);
if (storage.isPVSpoofLeaveMessageOnHide()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@

import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Plugin(
Expand Down Expand Up @@ -72,7 +71,8 @@ public class VelocityMain implements CorePlugin {

private VelocityDiscordListener velocityDiscordListener = null;

private final List<ScheduledTask> tasks = new ArrayList<>();
private final AtomicInteger nextTaskId = new AtomicInteger(0);
private final Map<Integer, ScheduledTask> tasks = new ConcurrentHashMap<>();

@Inject
public VelocityMain(ProxyServer proxy, Logger logger, @DataDirectory Path dataDirectory, Metrics.Factory metricsFactory) {
Expand Down Expand Up @@ -181,26 +181,44 @@ public void unregisterDiscordListener() {

@Override
public void cancelTask(int taskId) {
try {
tasks.get(taskId).cancel();
} catch (IndexOutOfBoundsException ignored) {
ScheduledTask task = tasks.remove(taskId);
if (task != null) {
task.cancel();
}
}

@Override
public int runTaskRepeatedly(Runnable task, int timeInSecondsLater) {
tasks.add(
proxy.getScheduler().buildTask(this, task)
.delay(timeInSecondsLater, TimeUnit.SECONDS).repeat(timeInSecondsLater, TimeUnit.SECONDS).schedule()
int taskId = nextTaskId.getAndIncrement();
tasks.put(taskId, proxy.getScheduler().buildTask(this, task)
.delay(timeInSecondsLater, TimeUnit.SECONDS)
.repeat(timeInSecondsLater, TimeUnit.SECONDS)
.schedule()
);
return tasks.size() - 1;
return taskId;
}

@Override
public void runTaskAsync(Runnable task) {
proxy.getScheduler().buildTask(this, task).schedule();
}

@Override
public int runTaskAsyncLater(Runnable task, int timeInMillisecondsLater) {
int taskId = nextTaskId.getAndIncrement();
tasks.put(
taskId,
proxy.getScheduler().buildTask(this, () -> {
try {
task.run();
} finally {
this.cancelTask(taskId);
}
}).delay(timeInMillisecondsLater, TimeUnit.MILLISECONDS).schedule()
);
return taskId;
}

@Override
public boolean isPluginLoaded(String pluginName) {
return proxy.getPluginManager().isLoaded(pluginName.toLowerCase());
Expand Down
10 changes: 9 additions & 1 deletion src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ Settings:
# server swap.
LeaveNetworkMessageCacheDuration: 45

# Designate how long, in milliseconds, the plugin will wait before sending the leave network message for a player.
# This allows them to rejoin with no join message and cancel the sending of the leave network message altogether.
# Helps prevent spam from players with a weak internet connection. 1500 is recommended.
LeaveJoinBufferDuration: 0

# Should players with the networkjoinmessages.silent permission be silenced by default?
# It will be set to this for all players after a reboot. They can toggle it for themselves with the /njoinspoof toggle command
SilentJoinDefaultState: true
Expand Down Expand Up @@ -210,6 +215,9 @@ OtherPlugins:
SpoofJoinMessageOnShow: true
# Spoof a leave message automatically when a player vanishes (hides)
SpoofLeaveMessageOnHide: true
# Treats a player with the permission pv.joinvanished as vanished on join (permission must be set on the proxy)
# This is to be used in conjunction with the PremiumVanish 'AutoVanishOnJoin' option
TreatVanishedOnJoin: false
LimboAPI:
# No swap messages for players swapping to or from limbo servers
SuppressSwapMessages: true
Expand All @@ -220,4 +228,4 @@ OtherPlugins:

debug: false
# Do not touch this
config-version: 11
config-version: 12