package me.StevenLawson.TotalFreedomMod; import com.earth2me.essentials.utils.DateUtil; import me.StevenLawson.TotalFreedomMod.admin.AdminList; import me.StevenLawson.TotalFreedomMod.ban.Ban; import me.StevenLawson.TotalFreedomMod.ban.BanManager; import me.StevenLawson.TotalFreedomMod.ban.PermbanList; import me.StevenLawson.TotalFreedomMod.bridge.EssentialsBridge; import me.StevenLawson.TotalFreedomMod.config.ConfigurationEntry; import me.StevenLawson.TotalFreedomMod.discord.bridge.DiscordBridge; import me.StevenLawson.TotalFreedomMod.player.UUIDManager; import me.StevenLawson.TotalFreedomMod.util.SynchronousUtil; import me.StevenLawson.TotalFreedomMod.util.Utilities; import net.md_5.bungee.api.chat.TextComponent; import net.minecraft.server.v1_8_R3.EntityPlayer; import net.minecraft.server.v1_8_R3.MinecraftServer; import net.minecraft.server.v1_8_R3.PropertyManager; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent.Result; import java.lang.management.ManagementFactory; import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.regex.Pattern; import static me.StevenLawson.TotalFreedomMod.listener.PlayerListener.DEFAULT_PORT; public class Server { public static final String COMPILE_NMS_VERSION = "v1_8_R2"; public static final Pattern USERNAME_REGEX = Pattern.compile("^[\\w\\d_]{3,20}$"); public static void setOnlineMode(boolean mode) { final PropertyManager manager = MinecraftServer.getServer().getPropertyManager(); manager.setProperty("online-mode", mode); manager.savePropertiesFile(); } public static int purgeWhitelist() { String[] whitelisted = MinecraftServer.getServer().getPlayerList().getWhitelisted(); int size = whitelisted.length; for (EntityPlayer player : MinecraftServer.getServer().getPlayerList().players) { MinecraftServer.getServer().getPlayerList().getWhitelist().remove(player.getProfile()); } try { MinecraftServer.getServer().getPlayerList().getWhitelist().save(); } catch (Exception ex) { Log.warning("Could not purge the whitelist!"); Log.warning(ex); } return size; } public static boolean isWhitelisted() { return MinecraftServer.getServer().getPlayerList().getHasWhitelist(); } public static List getWhitelisted() { return Arrays.asList(MinecraftServer.getServer().getPlayerList().getWhitelisted()); } public static String getVersion() { return MinecraftServer.getServer().getVersion(); } public static void handlePlayerPreLogin(AsyncPlayerPreLoginEvent event) { final String ip = event.getAddress().getHostAddress().trim(); final boolean isAdmin = AdminList.isSuperAdminSafe(null, ip); TextComponent textComponent = new TextComponent(String.format("%s is attempting to join with IP %s.", event.getName(), Utilities.getFuzzyIp(ip))); textComponent.setColor(ChatColor.GRAY.asBungee()); for (org.bukkit.entity.Player player : Bukkit.getOnlinePlayers()) { if (AdminList.isSuperAdmin(player)) { player.spigot().sendMessage(textComponent); } } DiscordBridge.transmitAdminMessage(textComponent.getText()); // Check if the player is already online for (Player onlinePlayer : TotalFreedomMod.server.getOnlinePlayers()) { if (!onlinePlayer.getName().equalsIgnoreCase(event.getName())) { continue; } if (!isAdmin) { event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, "Your username is already logged into this server."); } else { event.allow(); SynchronousUtil.playerKick(onlinePlayer, "An admin just logged in with the username you are using."); } return; } } public static void handlePlayerLogin(PlayerLoginEvent event) { final org.bukkit.Server server = TotalFreedomMod.server; final Player player = event.getPlayer(); final String username = player.getName(); final String ip = event.getAddress().getHostAddress().trim(); final UUID uuid = UUIDManager.newPlayer(player, ip); // Check username length if (username.length() < 3 || username.length() > TotalFreedomMod.MAX_USERNAME_LENGTH) { event.disallow(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(Result.KICK_OTHER, "Your username contains invalid characters."); return; } // Check force-IP match if (ConfigurationEntry.FORCE_IP_ENABLED.getBoolean()) { final String hostname = event.getHostname().replace("FML", ""); // Forge fix - https://github.com/TotalFreedom/TotalFreedomMod/issues/493 final String connectAddress = ConfigurationEntry.SERVER_ADDRESS.getString(); final int connectPort = TotalFreedomMod.server.getPort(); if (!hostname.equalsIgnoreCase(connectAddress + ":" + connectPort) && !hostname.equalsIgnoreCase(connectAddress + ".:" + connectPort)) { final int forceIpPort = ConfigurationEntry.FORCE_IP_PORT.getInteger(); event.disallow(PlayerLoginEvent.Result.KICK_OTHER, ConfigurationEntry.FORCE_IP_KICKMSG.getString() .replace("%address%", ConfigurationEntry.SERVER_ADDRESS.getString() + (forceIpPort == DEFAULT_PORT ? "" : ":" + forceIpPort))); return; } } // Check if player is admin // Not safe to use Utilities.isSuperAdmin(player) because player.getAddress() will return a null until after player login. final boolean isAdmin = AdminList.isSuperAdminSafe(uuid, ip); // Validation below this point if (isAdmin) // Player is superadmin { // Force-allow log in event.allow(); int count = server.getOnlinePlayers().size(); if (count >= server.getMaxPlayers()) { for (Player onlinePlayer : server.getOnlinePlayers()) { if (!AdminList.isSuperAdmin(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(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(Result.KICK_FULL, "Sorry, but this server is full."); return; } // Admin-only mode if (ConfigurationEntry.ADMIN_ONLY_MODE.getBoolean()) { event.disallow(Result.KICK_OTHER, "Server is temporarily open to admins only."); return; } // Lockdown mode if (TotalFreedomMod.lockdownEnabled) { event.disallow(Result.KICK_OTHER, "Server is currently in lockdown mode."); return; } // Whitelist if (isWhitelisted()) { if (!getWhitelisted().contains(username.toLowerCase())) { event.disallow(Result.KICK_OTHER, "You are not whitelisted on this server."); return; } } // UUID ban if (BanManager.isUuidBanned(uuid)) { final Ban ban = BanManager.getByUuid(uuid); event.disallow(Result.KICK_OTHER, ban.getKickMessage()); return; } // IP ban if (BanManager.isIpBanned(ip)) { final Ban ban = BanManager.getByIp(ip); event.disallow(Result.KICK_OTHER, ban.getKickMessage()); return; } // Permbanned IPs for (String testIp : PermbanList.getPermbannedIps()) { if (Utilities.fuzzyIpMatch(testIp, ip, 4)) { event.disallow(Result.KICK_OTHER, ChatColor.RED + "Your IP address is permanently banned from this server.\n" + "Release procedures are available at\n" + ChatColor.GOLD + ConfigurationEntry.SERVER_PERMBAN_URL.getString()); return; } } // Permbanned usernames for (String testPlayer : PermbanList.getPermbannedPlayers()) { if (testPlayer.equalsIgnoreCase(username)) { event.disallow(Result.KICK_OTHER, ChatColor.RED + "Your username is permanently banned from this server.\n" + "Release procedures are available at\n" + ChatColor.GOLD + ConfigurationEntry.SERVER_PERMBAN_URL.getString()); return; } } } public static double getTPS() { return EssentialsBridge.getEssentialsPlugin().getTimer().getAverageTPS(); } public static double getMaxMem() { return Runtime.getRuntime().maxMemory() / 1024f / 1024f; } public static double getTotalMem() { return Runtime.getRuntime().totalMemory() / 1024f / 1024f; } public static double getFreeMem() { return Runtime.getRuntime().freeMemory() / 1024f / 1024f; } public static String getUptime() { return DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime()); } }