From 46cef7c52e61e5afcf8cbb1462f87ef9a406a8f1 Mon Sep 17 00:00:00 2001 From: IxPrumxI Date: Mon, 13 Jan 2025 07:01:33 +0300 Subject: [PATCH] Add required linking (Only kick implemented) --- .../discordsrv/fabric/FabricDiscordSRV.java | 3 + .../fabric/module/chat/FabricJoinModule.java | 8 + .../FabricRequiredLinkingModule.java | 292 ++++++++++++++++++ 3 files changed, 303 insertions(+) create mode 100644 fabric/src/main/java/com/discordsrv/fabric/requiredlinking/FabricRequiredLinkingModule.java diff --git a/fabric/src/main/java/com/discordsrv/fabric/FabricDiscordSRV.java b/fabric/src/main/java/com/discordsrv/fabric/FabricDiscordSRV.java index cfecd47d..15dcbbf3 100644 --- a/fabric/src/main/java/com/discordsrv/fabric/FabricDiscordSRV.java +++ b/fabric/src/main/java/com/discordsrv/fabric/FabricDiscordSRV.java @@ -29,6 +29,7 @@ import com.discordsrv.fabric.config.main.FabricConfig; import com.discordsrv.fabric.console.FabricConsole; import com.discordsrv.fabric.game.handler.FabricCommandHandler; import com.discordsrv.fabric.module.chat.*; +import com.discordsrv.fabric.requiredlinking.FabricRequiredLinkingModule; import com.discordsrv.fabric.player.FabricPlayerProvider; import com.discordsrv.fabric.plugin.FabricModManager; import com.discordsrv.common.AbstractDiscordSRV; @@ -83,6 +84,8 @@ public class FabricDiscordSRV extends AbstractDiscordSRV. + */ + +package com.discordsrv.fabric.requiredlinking; + +import com.discordsrv.fabric.FabricDiscordSRV; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.abstraction.player.IPlayer; +import com.discordsrv.common.config.main.linking.ServerRequiredLinkingConfig; +import com.discordsrv.common.feature.linking.LinkStore; +import com.discordsrv.common.feature.linking.requirelinking.ServerRequireLinkingModule; +import com.github.benmanes.caffeine.cache.Cache; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.kyori.adventure.platform.modcommon.MinecraftServerAudiences; +import net.kyori.adventure.text.Component; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + + +public class FabricRequiredLinkingModule extends ServerRequireLinkingModule { + + private boolean enabled = false; + private final Cache linkCheckRateLimit; + + public FabricRequiredLinkingModule(FabricDiscordSRV discordSRV) { + super(discordSRV); + this.linkCheckRateLimit = discordSRV.caffeineBuilder() + .expireAfterWrite(LinkStore.LINKING_CODE_RATE_LIMIT) + .build(); + + register(); + } + + @Override + public ServerRequiredLinkingConfig config() { + return discordSRV.config().requiredLinking; + } + + @Override + public void enable() { + super.enable(); + + this.enabled = true; + } + + public void register() { + ServerPlayConnectionEvents.INIT.register(this::onPlayerPreLogin); + + } + + @Override + public void disable() { + super.disable(); + + this.enabled = false; + } + + private final List loginsCancelled = new CopyOnWriteArrayList<>(); + + public boolean isLoginCancelled(UUID playerUUID) { + return loginsCancelled.contains(playerUUID); + } + + public void removeLoginCancelled(UUID playerUUID) { + loginsCancelled.remove(playerUUID); + } + + private void onPlayerPreLogin(ServerPlayNetworkHandler serverPlayNetworkHandler, MinecraftServer minecraftServer) { + if(!this.enabled) return; + + ServerRequiredLinkingConfig config = config(); + if (!config.enabled || config.action != ServerRequiredLinkingConfig.Action.KICK) { + return; + } + + ServerPlayerEntity player = serverPlayNetworkHandler.player; + UUID playerUUID = player.getUuid(); + String playerName = player.getName().getString(); + + Component kickReason = getBlockReason(playerUUID, playerName, true).join(); + if (kickReason != null) { + serverPlayNetworkHandler.disconnect(MinecraftServerAudiences.of(minecraftServer).asNative(kickReason)); + loginsCancelled.add(playerUUID); + } + } + + @Override + public void recheck(IPlayer player) { + getBlockReason(player.uniqueId(), player.username(), false).whenComplete((component, throwable) -> { + if (component != null) { + switch (action()) { + case KICK: + player.kick(component); + break; + case FREEZE: + freeze(player, component); + break; + } + } else if (action() == ServerRequiredLinkingConfig.Action.FREEZE) { + frozen.remove(player.uniqueId()); + } + }); + } + + public ServerRequiredLinkingConfig.Action action() { + return config().action; + } + + // + // Freeze - Not implemented yet + // + + private final Map frozen = new ConcurrentHashMap<>(); + private final List loginsHandled = new CopyOnWriteArrayList<>(); + + private boolean isFrozen(ServerPlayerEntity player) { + return frozen.containsKey(player.getUuid()); + } + + private void freeze(IPlayer player, Component blockReason) { + frozen.put(player.uniqueId(), blockReason); + player.sendMessage(blockReason); + } + +// @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) +// public void onAsyncPlayerPreLogin(AsyncPlayerPreLoginEvent event) { +// if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { +// return; +// } +// +// UUID playerUUID = event.getUniqueId(); +// loginsHandled.add(playerUUID); +// handleLogin(playerUUID, event.getName()); +// } +// +// @EventHandler(priority = EventPriority.MONITOR) +// public void onPlayerLogin(PlayerLoginEvent event) { +// if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { +// frozen.remove(event.getPlayer().getUniqueId()); +// } +// } +// +// @EventHandler(priority = EventPriority.LOWEST) +// public void onPlayerJoinLowest(PlayerJoinEvent event) { +// Player player = event.getPlayer(); +// UUID playerUUID = player.getUniqueId(); +// if (!loginsHandled.remove(playerUUID)) { +// handleLogin(playerUUID, player.getName()); +// } +// } +// +// @EventHandler(priority = EventPriority.MONITOR) +// public void onPlayerJoinMonitor(PlayerJoinEvent event) { +// UUID playerUUID = event.getPlayer().getUniqueId(); +// +// Component blockReason = frozen.get(playerUUID); +// if (blockReason == null) { +// return; +// } +// +// IPlayer srvPlayer = discordSRV.playerProvider().player(playerUUID); +// if (srvPlayer == null) { +// throw new IllegalStateException("Player not available: " + playerUUID); +// } +// +// srvPlayer.sendMessage(blockReason); +// } + + private void handleLogin(UUID playerUUID, String username) { + if (discordSRV.isShutdown()) { + return; + } else if (!discordSRV.isReady()) { + try { + discordSRV.waitForStatus(DiscordSRV.Status.CONNECTED); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + ServerRequiredLinkingConfig config = config(); + if (!config.enabled || config.action != ServerRequiredLinkingConfig.Action.FREEZE) { + return; + } + + Component blockReason = getBlockReason(playerUUID, username, false).join(); + if (blockReason != null) { + frozen.put(playerUUID, blockReason); + } + } + +// @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) +// public void onPlayerMove(PlayerMoveEvent event) { +// Component freezeReason = frozen.get(event.getPlayer().getUniqueId()); +// if (freezeReason == null) { +// return; +// } +// +// Location from = event.getFrom(), to = event.getTo(); +// if (from.getWorld().getName().equals(to.getWorld().getName()) +// && from.getBlockX() == to.getBlockX() +// && from.getBlockZ() == to.getBlockZ() +// && from.getBlockY() >= to.getBlockY()) { +// return; +// } +// +// event.setTo( +// new Location( +// from.getWorld(), +// from.getBlockX() + 0.5, +// from.getBlockY(), +// from.getBlockZ() + 0.5, +// from.getYaw(), +// from.getPitch() +// ) +// ); +// +// IPlayer player = discordSRV.playerProvider().player(event.getPlayer()); +// player.sendMessage(freezeReason); +// } +// +// @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) +// public void onAsyncPlayerChat(AsyncPlayerChatEvent event) { +// Component freezeReason = frozen.get(event.getPlayer().getUniqueId()); +// if (freezeReason == null) { +// event.getRecipients().removeIf(this::isFrozen); +// return; +// } +// +// event.setCancelled(true); +// +// IPlayer player = discordSRV.playerProvider().player(event.getPlayer()); +// player.sendMessage(freezeReason); +// } +// +// @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) +// public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { +// if (!isFrozen(event.getPlayer())) { +// return; +// } +// +// event.setCancelled(true); +// +// String message = event.getMessage(); +// if (message.startsWith("/")) message = message.substring(1); +// if (message.equals("discord link") || message.equals("link")) { +// IPlayer player = discordSRV.playerProvider().player(event.getPlayer()); +// +// if (linkCheckRateLimit.getIfPresent(player.uniqueId()) != null) { +// player.sendMessage(discordSRV.messagesConfig(player).pleaseWaitBeforeRunningThatCommandAgain.asComponent()); +// return; +// } +// linkCheckRateLimit.put(player.uniqueId(), true); +// +// player.sendMessage(Component.text("Checking...")); +// +// UUID uuid = player.uniqueId(); +// getBlockReason(uuid, player.username(), false).whenComplete((reason, t) -> { +// if (t != null) { +// return; +// } +// +// if (reason == null) { +// frozen.remove(uuid); +// } else { +// freeze(player, reason); +// } +// }); +// } +// } +}