package me.totalfreedom.totalfreedommod; import com.google.common.base.Strings; import io.papermc.lib.PaperLib; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.regex.Pattern; import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.player.FPlayer; import me.totalfreedom.totalfreedommod.player.PlayerData; import me.totalfreedom.totalfreedommod.util.FConverter; import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FSync; import me.totalfreedom.totalfreedommod.util.FUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; public class LoginProcess extends FreedomService { public static final int DEFAULT_PORT = 25565; public static final int MIN_USERNAME_LENGTH = 2; public static final int MAX_USERNAME_LENGTH = 20; public static final Pattern USERNAME_REGEX = Pattern.compile("^[\\w\\d_]{3,20}$"); private static boolean lockdownEnabled = false; public List TELEPORT_ON_JOIN = new ArrayList<>(); public List CLEAR_ON_JOIN = new ArrayList<>(); public static boolean isLockdownEnabled() { return lockdownEnabled; } public static void setLockdownEnabled(boolean lockdownEnabled) { LoginProcess.lockdownEnabled = lockdownEnabled; } @Override public void onStart() { } @Override public void onStop() { } /* * Banning and Permban checks are their respective services */ @EventHandler(priority = EventPriority.NORMAL) public void onPlayerPreLogin(AsyncPlayerPreLoginEvent event) { final Admin entry = plugin.al.getEntryByUuid(event.getUniqueId()); final boolean isAdmin = entry != null && entry.isActive(); // Check if the player is already online for (Player onlinePlayer : server.getOnlinePlayers()) { if (!onlinePlayer.getUniqueId().equals(event.getUniqueId())) { continue; } if (isAdmin) { event.allow(); FSync.playerKick(onlinePlayer, "An admin just logged in with the username you are using."); return; } event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, "Your username is already logged into this server."); return; } } @EventHandler(priority = EventPriority.HIGH) public void onPlayerLogin(PlayerLoginEvent event) { final Player player = event.getPlayer(); final String username = player.getName(); final UUID uuid = player.getUniqueId(); // Check username length if (username.length() < MIN_USERNAME_LENGTH || username.length() > MAX_USERNAME_LENGTH) { event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "Your username is an invalid length (must be between 3 and 20 characters long)."); return; } // Check username characters if (!USERNAME_REGEX.matcher(username).find()) { event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "Your username contains invalid characters."); return; } // Check force-IP match if (ConfigEntry.FORCE_IP_ENABLED.getBoolean()) { final String hostname = event.getHostname().replace("\u0000FML\u0000", ""); // Forge fix - https://github.com/TotalFreedom/TotalFreedomMod/issues/493 final String connectAddress = ConfigEntry.SERVER_ADDRESS.getString(); final int connectPort = server.getPort(); if (!hostname.equalsIgnoreCase(connectAddress + ":" + connectPort) && !hostname.equalsIgnoreCase(connectAddress + ".:" + connectPort)) { final int forceIpPort = ConfigEntry.FORCE_IP_PORT.getInteger(); event.disallow(PlayerLoginEvent.Result.KICK_OTHER, ConfigEntry.FORCE_IP_KICKMSG.getString() .replace("%address%", ConfigEntry.SERVER_ADDRESS.getString() + (forceIpPort == DEFAULT_PORT ? "" : ":" + forceIpPort))); return; } } // Validation below this point final Admin entry = plugin.al.getEntryByUuid(uuid); if (entry != null && entry.isActive()) // Check if player is admin { // Force-allow log in event.allow(); int count = server.getOnlinePlayers().size(); if (count >= server.getMaxPlayers()) { for (Player onlinePlayer : server.getOnlinePlayers()) { if (!plugin.al.isAdmin(onlinePlayer)) { onlinePlayer.kickPlayer("You have been kicked to free up room for an admin."); count--; } if (count < server.getMaxPlayers()) { break; } } } if (count >= server.getMaxPlayers()) { event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "The server is full and a player could not be kicked, sorry!"); return; } return; } // Player is not an admin // Server full check if (server.getOnlinePlayers().size() >= server.getMaxPlayers()) { event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "Sorry, but this server is full."); return; } // Admin-only mode if (ConfigEntry.ADMIN_ONLY_MODE.getBoolean()) { event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "Server is temporarily open to admins only."); return; } // Lockdown mode if (lockdownEnabled) { event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "Server is currently in lockdown mode."); return; } // Whitelist if (server.hasWhitelist() && !player.isWhitelisted()) { event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "You are not whitelisted on this server."); } } @EventHandler(priority = EventPriority.MONITOR) public void onPlayerJoin(PlayerJoinEvent event) { final Player player = event.getPlayer(); final FPlayer fPlayer = plugin.pl.getPlayer(player); final PlayerData playerData = plugin.pl.getData(player); // Sends a message to the player if they have never joined before (or simply lack player data). if (!event.getPlayer().hasPlayedBefore() && ConfigEntry.FIRST_JOIN_INFO_ENABLED.getBoolean()) { new BukkitRunnable() { @Override public void run() { ConfigEntry.FIRST_JOIN_INFO.getStringList().forEach(line -> FUtil.playerMsgCooler(player, line)); } }.runTaskLater(plugin, 20); } FUtil.playerTitle(player, ConfigEntry.SERVER_LOGIN_TITLE.getString(), ConfigEntry.SERVER_LOGIN_SUBTITLE.getString()); if (TELEPORT_ON_JOIN.contains(player.getName()) || ConfigEntry.AUTO_TP.getBoolean()) { int x = FUtil.randomInteger(-10000, 10000); int z = FUtil.randomInteger(-10000, 10000); int y = player.getWorld().getHighestBlockYAt(x, z) + 1; Location location = new Location(player.getLocation().getWorld(), x, y, z); PaperLib.teleportAsync(player, location); FUtil.playerMsgCooler(player, "You have been automatically teleported to a random location."); return; } if (!playerData.getIps().contains(FUtil.getIp(player))) { playerData.addIp(FUtil.getIp(player)); plugin.pl.save(playerData); } if (CLEAR_ON_JOIN.contains(player.getName()) || ConfigEntry.AUTO_CLEAR.getBoolean()) { player.getInventory().clear(); FUtil.playerMsgCooler(player, "Your inventory has been automatically cleared."); return; } if (!ConfigEntry.SERVER_TABLIST_HEADER.getString().isEmpty()) { player.sendPlayerListHeader(FUtil.miniMessage(ConfigEntry.SERVER_TABLIST_HEADER.getString())); } if (!ConfigEntry.SERVER_TABLIST_FOOTER.getString().isEmpty()) { player.sendPlayerListFooter(FUtil.miniMessage(ConfigEntry.SERVER_TABLIST_FOOTER.getString())); } if (!plugin.al.isAdmin(player)) { Component tag = playerData.getTag(); if (tag != null) { fPlayer.setTag(tag); } int noteCount = playerData.getNotes().size(); if (noteCount != 0) { plugin.cm.messageAllAdmins("This player has admin note.", Placeholder.unparsed("count", String.valueOf(noteCount)), Placeholder.unparsed("plural", noteCount > 1 ? "s" : "")); plugin.cm.messageAllAdmins("Do /notes list to view them.", Placeholder.unparsed("player", player.getName())); } } else { Admin admin = plugin.al.getAdmin(player); String format = admin.getAcFormat(); if (!Strings.isNullOrEmpty(format) && FConverter.needsConversion(admin.getAcFormat())) { player.sendMessage(FUtil.miniMessage("Converting your admin chat format...")); admin.setAcFormat(FConverter.convertAdminChatFormat(format)); plugin.al.save(admin); } } new BukkitRunnable() { @Override public void run() { if (ConfigEntry.ADMIN_ONLY_MODE.getBoolean()) { FUtil.playerMsgCooler(player, "Server is currently closed to non-admins."); } if (lockdownEnabled) { FUtil.playerMsgCooler(player, "Warning: Server is currenty in lockdown-mode, new players will not be able to join!"); } } }.runTaskLater(plugin, 20L); } }