Add options to join & leave to ignore the messages if the player leaves/joins within the specified amount of milliseconds

This commit is contained in:
Vankka 2024-06-21 17:00:48 +03:00
parent 5983148d1a
commit 3ee90712e9
No known key found for this signature in database
GPG Key ID: 62E48025ED4E7EBB
5 changed files with 104 additions and 5 deletions

View File

@ -38,14 +38,19 @@ public abstract class MainConfig implements Config {
public static final String FILE_NAME = "config.yaml";
@Constants({DocumentationURLs.ELT_FORMAT, DocumentationURLs.DISCORD_MARKDOWN, DocumentationURLs.PLACEHOLDERS})
@Constants({
ConnectionConfig.FILE_NAME,
DocumentationURLs.ELT_FORMAT,
DocumentationURLs.DISCORD_MARKDOWN,
DocumentationURLs.PLACEHOLDERS
})
public static final String HEADER = String.join("\n", Arrays.asList(
"Welcome to the DiscordSRV configuration file",
"",
"Looking for the \"BotToken\" option? It has been moved into the " + ConnectionConfig.FILE_NAME,
"Need help with the format for Minecraft messages? %1",
"Need help with Discord markdown? %2",
"List of placeholders %3"
"Looking for the \"BotToken\" option? It has been moved into the %1",
"Need help with the format for Minecraft messages? %2",
"Need help with Discord markdown? %3",
"List of placeholders %4"
));
@Override

View File

@ -46,6 +46,9 @@ public class JoinMessageConfig implements IMessageConfig {
@Constants.Comment("discordsrv.silentjoin")
public boolean enableSilentPermission = true;
@Comment("Ignore if the player leaves within the given amount of milliseconds. This will delay sending the join message")
public long ignoreIfLeftWithinMS = 250;
@Override
public boolean enabled() {
return enabled;

View File

@ -44,6 +44,9 @@ public class LeaveMessageConfig implements IMessageConfig {
@Constants.Comment("discordsrv.silentquit")
public boolean enableSilentPermission = true;
@Comment("Ignore if the player joined within the given amount of milliseconds")
public long ignoreIfJoinedWithinMS = 250;
@Override
public boolean enabled() {
return enabled;

View File

@ -29,16 +29,25 @@ import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.component.util.ComponentUtil;
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
import com.discordsrv.common.config.main.generic.IMessageConfig;
import com.discordsrv.common.event.events.player.PlayerDisconnectedEvent;
import com.discordsrv.common.permission.Permission;
import com.discordsrv.common.player.IPlayer;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class JoinMessageModule extends AbstractGameMessageModule<IMessageConfig, JoinMessageReceiveEvent> {
private final Map<UUID, Runnable> delayedTasks = new HashMap<>();
public JoinMessageModule(DiscordSRV discordSRV) {
super(discordSRV, "JOIN_MESSAGES");
}
@ -63,9 +72,47 @@ public class JoinMessageModule extends AbstractGameMessageModule<IMessageConfig,
logger().info(player.username() + " is joining silently, join message will not be sent");
return CompletableFuture.completedFuture(null);
}
long delay = config.joinMessages().ignoreIfLeftWithinMS;
if (player != null && delay > 0) {
UUID playerUUID = player.uniqueId();
CompletableFuture<Void> completableFuture = new CompletableFuture<>();
synchronized (delayedTasks) {
Future<?> future = discordSRV.scheduler().runLater(() -> {
CompletableFuture<Void> forward = super.forwardToChannel(event, player, config);
synchronized (delayedTasks) {
delayedTasks.remove(playerUUID);
}
try {
completableFuture.complete(forward.get());
} catch (ExecutionException e) {
completableFuture.completeExceptionally(e.getCause());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, Duration.ofMillis(delay));
delayedTasks.put(playerUUID, () -> {
completableFuture.complete(null);
future.cancel(true);
});
}
return completableFuture;
}
return super.forwardToChannel(event, player, config);
}
@Subscribe
public void onPlayerDisconnected(PlayerDisconnectedEvent event) {
IPlayer player = event.player();
Runnable cancel = delayedTasks.remove(player.uniqueId());
if (cancel != null) {
cancel.run();
logger().info(player.username() + " left within timeout period, join message will not be sent");
}
}
@Override
public IMessageConfig mapConfig(JoinMessageReceiveEvent event, BaseChannelConfig channelConfig) {
return channelConfig.joinMessages().getForEvent(event);

View File

@ -29,20 +29,50 @@ import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.component.util.ComponentUtil;
import com.discordsrv.common.config.main.channels.LeaveMessageConfig;
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
import com.discordsrv.common.event.events.player.PlayerConnectedEvent;
import com.discordsrv.common.permission.Permission;
import com.discordsrv.common.player.IPlayer;
import net.kyori.adventure.text.Component;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
public class LeaveMessageModule extends AbstractGameMessageModule<LeaveMessageConfig, LeaveMessageReceiveEvent> {
private final Map<UUID, Pair<Long, Future<?>>> playersJoinedRecently = new ConcurrentHashMap<>();
public LeaveMessageModule(DiscordSRV discordSRV) {
super(discordSRV, "LEAVE_MESSAGES");
}
@Subscribe
public void onPlayerConnected(PlayerConnectedEvent event) {
UUID playerUUID = event.player().uniqueId();
Pair<Long, Future<?>> pair = playersJoinedRecently.remove(playerUUID);
if (pair != null) {
pair.getValue().cancel(true);
}
long maxMS = 0;
for (BaseChannelConfig channel : discordSRV.channelConfig().getAllChannels()) {
long ms = channel.leaveMessages.ignoreIfJoinedWithinMS;
if (maxMS < ms) {
maxMS = ms;
}
}
if (maxMS > 0) {
long currentTime = System.currentTimeMillis();
Future<?> removeFuture = discordSRV.scheduler().runLater(() -> playersJoinedRecently.remove(playerUUID), Duration.ofMillis(maxMS));
playersJoinedRecently.put(playerUUID, Pair.of(currentTime, removeFuture));
}
}
@Subscribe(priority = EventPriority.LAST)
public void onLeaveMessageReceive(LeaveMessageReceiveEvent event) {
if (checkCancellation(event) || checkProcessor(event)) {
@ -59,6 +89,17 @@ public class LeaveMessageModule extends AbstractGameMessageModule<LeaveMessageCo
@Nullable IPlayer player,
@NotNull BaseChannelConfig config
) {
if (player != null) {
Pair<Long, Future<?>> pair = playersJoinedRecently.remove(player.uniqueId());
if (pair != null) {
long delta = System.currentTimeMillis() - pair.getKey();
if (delta < config.leaveMessages.ignoreIfJoinedWithinMS) {
logger().info(player.username() + " joined within timeout period, join message will not be sent");
return CompletableFuture.completedFuture(null);
}
}
}
if (config.leaveMessages.enableSilentPermission && player != null && player.hasPermission(Permission.SILENT_QUIT)) {
logger().info(player.username() + " is leaving silently, leave message will not be sent");
return CompletableFuture.completedFuture(null);