diff --git a/buildnumber.properties b/buildnumber.properties index b3edf9b..4c2fdec 100644 --- a/buildnumber.properties +++ b/buildnumber.properties @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Sat May 30 20:10:27 CEST 2015 -build.number=1043 +#Sat May 30 20:46:17 CEST 2015 +build.number=1052 diff --git a/src/me/StevenLawson/TotalFreedomMod/Commands/Command_saconfig.java b/src/me/StevenLawson/TotalFreedomMod/Commands/Command_saconfig.java index 1f679a8..70d6121 100644 --- a/src/me/StevenLawson/TotalFreedomMod/Commands/Command_saconfig.java +++ b/src/me/StevenLawson/TotalFreedomMod/Commands/Command_saconfig.java @@ -57,7 +57,8 @@ public class Command_saconfig extends TFM_Command { final TFM_Admin admin = TFM_AdminList.getEntry(sender_p); - if (admin == null) { + if (admin == null) + { playerMsg("Could not find your admin entry! Please notify a developer.", ChatColor.RED); return true; } diff --git a/src/me/StevenLawson/TotalFreedomMod/Listener/TFM_PlayerListener.java b/src/me/StevenLawson/TotalFreedomMod/Listener/TFM_PlayerListener.java index 12250cf..7de5fd3 100644 --- a/src/me/StevenLawson/TotalFreedomMod/Listener/TFM_PlayerListener.java +++ b/src/me/StevenLawson/TotalFreedomMod/Listener/TFM_PlayerListener.java @@ -45,6 +45,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.block.LeavesDecayEvent; import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerInteractEvent; @@ -388,7 +389,7 @@ public class TFM_PlayerListener implements Listener final Player player = event.getPlayer(); final TFM_PlayerData playerdata = TFM_PlayerData.getPlayerData(player); // Check absolute value to account for negatives - if(Math.abs(event.getTo().getX()) >= MAX_XY_COORD || Math.abs(event.getTo().getZ()) >= MAX_XY_COORD) + if (Math.abs(event.getTo().getX()) >= MAX_XY_COORD || Math.abs(event.getTo().getZ()) >= MAX_XY_COORD) { event.setCancelled(true); // illegal position, cancel it } @@ -791,7 +792,7 @@ public class TFM_PlayerListener implements Listener final TFM_Player playerEntry; TFM_Log.info("[JOIN] " + TFM_Util.formatPlayer(player) + " joined the game with IP address: " + ip, true); // Check absolute value to account for negatives - if(Math.abs(player.getLocation().getX()) >= MAX_XY_COORD || Math.abs(player.getLocation().getZ()) >= MAX_XY_COORD) + if (Math.abs(player.getLocation().getX()) >= MAX_XY_COORD || Math.abs(player.getLocation().getZ()) >= MAX_XY_COORD) { player.teleport(player.getWorld().getSpawnLocation()); // Illegal position, teleport to spawn } @@ -911,26 +912,15 @@ public class TFM_PlayerListener implements Listener }.runTaskLater(TotalFreedomMod.plugin, 20L * 1L); } + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerPreLogin(AsyncPlayerPreLoginEvent event) + { + TFM_ServerInterface.handlePlayerPreLogin(event); + } + @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerLogin(PlayerLoginEvent event) { - if (TFM_ConfigEntry.FORCE_IP_ENABLED.getBoolean()) - { - final String hostname = event.getHostname().replace("FML", ""); // Forge fix - https://github.com/TotalFreedom/TotalFreedomMod/issues/493 - final String connectAddress = TFM_ConfigEntry.SERVER_ADDRESS.getString(); - final int connectPort = TotalFreedomMod.server.getPort(); - - if (!hostname.equalsIgnoreCase(connectAddress + ":" + connectPort) && !hostname.equalsIgnoreCase(connectAddress + ".:" + connectPort)) - { - final int forceIpPort = TFM_ConfigEntry.FORCE_IP_PORT.getInteger(); - event.disallow(PlayerLoginEvent.Result.KICK_OTHER, - TFM_ConfigEntry.FORCE_IP_KICKMSG.getString() - .replace("%address%", TFM_ConfigEntry.SERVER_ADDRESS.getString() + (forceIpPort == DEFAULT_PORT ? "" : ":" + forceIpPort))); - return; - } - - } - TFM_ServerInterface.handlePlayerLogin(event); } } diff --git a/src/me/StevenLawson/TotalFreedomMod/TFM_AdminList.java b/src/me/StevenLawson/TotalFreedomMod/TFM_AdminList.java index 68ef5d9..7941087 100644 --- a/src/me/StevenLawson/TotalFreedomMod/TFM_AdminList.java +++ b/src/me/StevenLawson/TotalFreedomMod/TFM_AdminList.java @@ -406,7 +406,7 @@ public class TFM_AdminList public static boolean isSuperAdminSafe(UUID uuid, String ip) { - if (TotalFreedomMod.server.getOnlineMode()) + if (TotalFreedomMod.server.getOnlineMode() && uuid != null) { return TFM_AdminList.getSuperUUIDs().contains(uuid); } diff --git a/src/me/StevenLawson/TotalFreedomMod/TFM_PermbanList.java b/src/me/StevenLawson/TotalFreedomMod/TFM_PermbanList.java index d888cbb..27d9e0e 100644 --- a/src/me/StevenLawson/TotalFreedomMod/TFM_PermbanList.java +++ b/src/me/StevenLawson/TotalFreedomMod/TFM_PermbanList.java @@ -7,6 +7,7 @@ import me.StevenLawson.TotalFreedomMod.Config.TFM_Config; public class TFM_PermbanList { + private static final List PERMBANNED_PLAYERS; private static final List PERMBANNED_IPS; diff --git a/src/me/StevenLawson/TotalFreedomMod/TFM_PlayerList.java b/src/me/StevenLawson/TotalFreedomMod/TFM_PlayerList.java index 7f985f4..418ee5f 100644 --- a/src/me/StevenLawson/TotalFreedomMod/TFM_PlayerList.java +++ b/src/me/StevenLawson/TotalFreedomMod/TFM_PlayerList.java @@ -11,65 +11,53 @@ import me.StevenLawson.TotalFreedomMod.Config.TFM_Config; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -public class TFM_PlayerList -{ +public class TFM_PlayerList { + private static final Map PLAYER_LIST = new HashMap(); - private TFM_PlayerList() - { + private TFM_PlayerList() { throw new AssertionError(); } - public static Set getAllPlayers() - { + public static Set getAllPlayers() { return Collections.unmodifiableSet(Sets.newHashSet(PLAYER_LIST.values())); } - public static void load() - { + public static void load() { PLAYER_LIST.clear(); // Load online players - for (Player player : Bukkit.getOnlinePlayers()) - { + for (Player player : Bukkit.getOnlinePlayers()) { getEntry(player); } TFM_Log.info("Loaded playerdata for " + PLAYER_LIST.size() + " players"); } - public static void saveAll() - { - for (TFM_Player entry : PLAYER_LIST.values()) - { + public static void saveAll() { + for (TFM_Player entry : PLAYER_LIST.values()) { save(entry); } } // May return null - public static TFM_Player getEntry(UUID uuid) - { - if (PLAYER_LIST.containsKey(uuid)) - { + public static TFM_Player getEntry(UUID uuid) { + if (PLAYER_LIST.containsKey(uuid)) { return PLAYER_LIST.get(uuid); } final File configFile = getConfigFile(uuid); - if (!configFile.exists()) - { + if (!configFile.exists()) { return null; } final TFM_Player entry = new TFM_Player(uuid, getConfig(uuid)); - if (entry.isComplete()) - { + if (entry.isComplete()) { PLAYER_LIST.put(uuid, entry); return entry; - } - else - { + } else { TFM_Log.warning("Could not load entry: Entry is not complete!"); configFile.delete(); } @@ -77,13 +65,11 @@ public class TFM_PlayerList return null; } - public static TFM_Player getEntry(Player player) - { + public static TFM_Player getEntry(Player player) { final UUID uuid = TFM_UuidManager.getUniqueId(player); TFM_Player entry = getEntry(uuid); - if (entry != null) - { + if (entry != null) { return entry; } @@ -101,12 +87,10 @@ public class TFM_PlayerList return entry; } - public static void removeEntry(Player player) - { + public static void removeEntry(Player player) { final UUID uuid = TFM_UuidManager.getUniqueId(player); - if (!PLAYER_LIST.containsKey(uuid)) - { + if (!PLAYER_LIST.containsKey(uuid)) { return; } @@ -115,20 +99,16 @@ public class TFM_PlayerList PLAYER_LIST.remove(uuid); } - public static boolean existsEntry(Player player) - { + public static boolean existsEntry(Player player) { return existsEntry(TFM_UuidManager.getUniqueId(player)); } - public static boolean existsEntry(UUID uuid) - { + public static boolean existsEntry(UUID uuid) { return getConfigFile(uuid).exists(); } - public static void setUniqueId(TFM_Player entry, UUID newUuid) - { - if (entry.getUniqueId().equals(newUuid)) - { + public static void setUniqueId(TFM_Player entry, UUID newUuid) { + if (entry.getUniqueId().equals(newUuid)) { TFM_Log.warning("Not setting new UUID: UUIDs match!"); return; } @@ -147,16 +127,13 @@ public class TFM_PlayerList // Remove old entry PLAYER_LIST.remove(entry.getUniqueId()); final File oldFile = getConfigFile(entry.getUniqueId()); - if (oldFile.exists() && !oldFile.delete()) - { + if (oldFile.exists() && !oldFile.delete()) { TFM_Log.warning("Could not delete config: " + getConfigFile(entry.getUniqueId()).getName()); } } - public static void purgeAll() - { - for (File file : getConfigFolder().listFiles()) - { + public static void purgeAll() { + for (File file : getConfigFolder().listFiles()) { file.delete(); } @@ -164,27 +141,22 @@ public class TFM_PlayerList load(); } - public static File getConfigFolder() - { + public static File getConfigFolder() { return new File(TotalFreedomMod.plugin.getDataFolder(), "players"); } - public static File getConfigFile(UUID uuid) - { + public static File getConfigFile(UUID uuid) { return new File(getConfigFolder(), uuid + ".yml"); } - public static TFM_Config getConfig(UUID uuid) - { + public static TFM_Config getConfig(UUID uuid) { final TFM_Config config = new TFM_Config(TotalFreedomMod.plugin, getConfigFile(uuid), false); config.load(); return config; } - public static void save(TFM_Player entry) - { - if (!entry.isComplete()) - { + public static void save(TFM_Player entry) { + if (!entry.isComplete()) { throw new IllegalArgumentException("Entry is not complete!"); } diff --git a/src/me/StevenLawson/TotalFreedomMod/TFM_ServerInterface.java b/src/me/StevenLawson/TotalFreedomMod/TFM_ServerInterface.java index 4b46c4b..0f7ea8f 100644 --- a/src/me/StevenLawson/TotalFreedomMod/TFM_ServerInterface.java +++ b/src/me/StevenLawson/TotalFreedomMod/TFM_ServerInterface.java @@ -5,12 +5,14 @@ import java.util.List; import java.util.UUID; import java.util.regex.Pattern; import me.StevenLawson.TotalFreedomMod.Config.TFM_ConfigEntry; +import static me.StevenLawson.TotalFreedomMod.Listener.TFM_PlayerListener.DEFAULT_PORT; import net.minecraft.server.v1_8_R2.EntityPlayer; import net.minecraft.server.v1_8_R2.MinecraftServer; import net.minecraft.server.v1_8_R2.PropertyManager; import org.bukkit.ChatColor; import org.bukkit.Server; import org.bukkit.entity.Player; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent.Result; @@ -62,6 +64,29 @@ public class TFM_ServerInterface return MinecraftServer.getServer().getVersion(); } + public static void handlePlayerPreLogin(AsyncPlayerPreLoginEvent event) + { + final String ip = event.getAddress().getHostAddress().trim(); + final boolean isAdmin = TFM_AdminList.isSuperAdminSafe(null, ip); + + // 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(); + TFM_Sync.playerKick(onlinePlayer, "An admin just logged in with the username you are using."); + } + return; + } + } + public static void handlePlayerLogin(PlayerLoginEvent event) { final Server server = TotalFreedomMod.server; @@ -70,19 +95,38 @@ public class TFM_ServerInterface final String ip = event.getAddress().getHostAddress().trim(); final UUID uuid = TFM_UuidManager.newPlayer(player, ip); - // Perform username checks + // 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 (TFM_ConfigEntry.FORCE_IP_ENABLED.getBoolean()) + { + final String hostname = event.getHostname().replace("FML", ""); // Forge fix - https://github.com/TotalFreedom/TotalFreedomMod/issues/493 + final String connectAddress = TFM_ConfigEntry.SERVER_ADDRESS.getString(); + final int connectPort = TotalFreedomMod.server.getPort(); + + if (!hostname.equalsIgnoreCase(connectAddress + ":" + connectPort) && !hostname.equalsIgnoreCase(connectAddress + ".:" + connectPort)) + { + final int forceIpPort = TFM_ConfigEntry.FORCE_IP_PORT.getInteger(); + event.disallow(PlayerLoginEvent.Result.KICK_OTHER, + TFM_ConfigEntry.FORCE_IP_KICKMSG.getString() + .replace("%address%", TFM_ConfigEntry.SERVER_ADDRESS.getString() + (forceIpPort == DEFAULT_PORT ? "" : ":" + forceIpPort))); + return; + } + + } + // Check if player is admin // Not safe to use TFM_Util.isSuperAdmin(player) because player.getAddress() will return a null until after player login. final boolean isAdmin = TFM_AdminList.isSuperAdminSafe(uuid, ip); @@ -93,15 +137,6 @@ public class TFM_ServerInterface // Force-allow log in event.allow(); - // Kick players with the same name - for (Player onlinePlayer : server.getOnlinePlayers()) - { - if (onlinePlayer.getName().equalsIgnoreCase(username)) - { - onlinePlayer.kickPlayer("An admin just logged in with the username you are using."); - } - } - int count = server.getOnlinePlayers().size(); if (count >= server.getMaxPlayers()) { @@ -151,16 +186,6 @@ public class TFM_ServerInterface return; } - // Username already logged in - for (Player onlinePlayer : server.getOnlinePlayers()) - { - if (onlinePlayer.getName().equalsIgnoreCase(username)) - { - event.disallow(Result.KICK_OTHER, "Your username is already logged into this server."); - return; - } - } - // Whitelist if (isWhitelisted()) { diff --git a/src/me/StevenLawson/TotalFreedomMod/TFM_UuidManager.java b/src/me/StevenLawson/TotalFreedomMod/TFM_UuidManager.java index 086f02b..71fde30 100644 --- a/src/me/StevenLawson/TotalFreedomMod/TFM_UuidManager.java +++ b/src/me/StevenLawson/TotalFreedomMod/TFM_UuidManager.java @@ -25,20 +25,18 @@ import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; -public class TFM_UuidManager -{ +public class TFM_UuidManager { + public static final String TABLE_NAME = "uuids"; private static final TFM_SqliteDatabase SQL; private static final Statement FIND; private static final Statement UPDATE; - private TFM_UuidManager() - { + private TFM_UuidManager() { throw new AssertionError(); } - static - { + static { SQL = new TFM_SqliteDatabase( "uuids.db", TABLE_NAME, @@ -48,40 +46,34 @@ public class TFM_UuidManager UPDATE = SQL.addPreparedStatement("REPLACE INTO " + TABLE_NAME + " (username, uuid) VALUES (?, ?);"); } - public static void load() - { + public static void load() { // Init DB SQL.connect(); } - public static void close() - { + public static void close() { SQL.close(); } - public static int purge() - { + public static int purge() { return SQL.purge(); } - public static UUID newPlayer(Player player, String ip) - { + public static UUID newPlayer(Player player, String ip) { TFM_Log.info("Obtaining UUID for new player: " + player.getName()); final String username = player.getName().toLowerCase(); // Look in DB final UUID dbUuid = find(username); - if (dbUuid != null) - { + if (dbUuid != null) { return dbUuid; } // Find UUID and update in DB if not found // Try API UUID uuid = TFM_UuidResolver.getUUIDOf(username); - if (uuid == null) - { + if (uuid == null) { // Spoof uuid = generateSpoofUuid(username); } @@ -90,11 +82,9 @@ public class TFM_UuidManager return uuid; } - public static UUID getUniqueId(OfflinePlayer offlinePlayer) - { + public static UUID getUniqueId(OfflinePlayer offlinePlayer) { // Online check first - if (offlinePlayer.isOnline() && TFM_PlayerData.hasPlayerData(offlinePlayer.getPlayer())) - { + if (offlinePlayer.isOnline() && TFM_PlayerData.hasPlayerData(offlinePlayer.getPlayer())) { return TFM_PlayerData.getPlayerData(offlinePlayer.getPlayer()).getUniqueId(); } @@ -102,19 +92,16 @@ public class TFM_UuidManager return getUniqueId(offlinePlayer.getName()); } - public static UUID getUniqueId(String username) - { + public static UUID getUniqueId(String username) { // Look in DB final UUID dbUuid = find(username); - if (dbUuid != null) - { + if (dbUuid != null) { return dbUuid; } // Try API final UUID apiUuid = TFM_UuidResolver.getUUIDOf(username); - if (apiUuid != null) - { + if (apiUuid != null) { return apiUuid; } @@ -122,10 +109,8 @@ public class TFM_UuidManager return generateSpoofUuid(username); } - public static void rawSetUUID(String name, UUID uuid) - { - if (name == null || uuid == null || name.isEmpty()) - { + public static void rawSetUUID(String name, UUID uuid) { + if (name == null || uuid == null || name.isEmpty()) { TFM_Log.warning("Not setting raw UUID: name and uuid may not be null!"); return; } @@ -133,86 +118,67 @@ public class TFM_UuidManager update(name.toLowerCase().trim(), uuid); } - private static UUID find(String searchName) - { - if (!SQL.connect()) - { + private static UUID find(String searchName) { + if (!SQL.connect()) { return null; } final ResultSet result; - try - { + try { final PreparedStatement statement = FIND.getStatement(); statement.clearParameters(); statement.setString(1, searchName.toLowerCase()); result = statement.executeQuery(); - } - catch (Exception ex) - { + } catch (Exception ex) { TFM_Log.severe("Could not execute find statement!"); TFM_Log.severe(ex); return null; } - if (!TFM_SqlUtil.hasData(result)) - { + if (!TFM_SqlUtil.hasData(result)) { TFM_SqlUtil.close(result); return null; } - try - { + try { final String uuidString = result.getString("uuid"); return UUID.fromString(uuidString); - } - catch (Exception ex) - { + } catch (Exception ex) { TFM_Log.severe(ex); return null; - } - finally - { + } finally { TFM_SqlUtil.close(result); } } - private static boolean update(String username, UUID uuid) - { - if (!SQL.connect()) - { + private static boolean update(String username, UUID uuid) { + if (!SQL.connect()) { return false; } - try - { + try { final PreparedStatement statement = UPDATE.getStatement(); statement.clearParameters(); statement.setString(1, username.toLowerCase()); statement.setString(2, uuid.toString()); statement.executeUpdate(); return true; - } - catch (Exception ex) - { + } catch (Exception ex) { TFM_Log.severe("Could not execute update statement!"); TFM_Log.severe(ex); return false; } } - private static UUID generateSpoofUuid(String name) - { + private static UUID generateSpoofUuid(String name) { name = name.toLowerCase(); TFM_Log.info("Generating spoof UUID for " + name); - try - { + try { final MessageDigest digest = MessageDigest.getInstance("SHA1"); final byte[] result = digest.digest(name.getBytes()); final StringBuilder builder = new StringBuilder(); - for (int i = 0; i < result.length; i++) - { + for (int i = 0; i < result.length; i++) { builder.append(Integer.toString((result[i] & 0xff) + 0x100, 16).substring(1)); } @@ -222,36 +188,30 @@ public class TFM_UuidManager + "-" + builder.substring(12, 16) + "-" + builder.substring(16, 20) + "-" + builder.substring(20, 32)); - } - catch (NoSuchAlgorithmException ex) - { + } catch (NoSuchAlgorithmException ex) { TFM_Log.warning("Could not generate spoof UUID: SHA1 algorithm not found!"); } return UUID.randomUUID(); } - public static class TFM_UuidResolver implements Callable> - { + public static class TFM_UuidResolver implements Callable> { + private static final double PROFILES_PER_REQUEST = 100; private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; private final JSONParser jsonParser = new JSONParser(); private final List names; - public TFM_UuidResolver(List names) - { + public TFM_UuidResolver(List names) { this.names = ImmutableList.copyOf(names); } @Override - public Map call() - { + public Map call() { final Map uuidMap = new HashMap(); int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST); - for (int i = 0; i < requests; i++) - { - try - { + for (int i = 0; i < requests; i++) { + try { final URL url = new URL(PROFILE_URL); final HttpURLConnection connection = (HttpURLConnection) url.openConnection(); @@ -270,8 +230,7 @@ public class TFM_UuidManager final JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); - for (Object profile : array) - { + for (Object profile : array) { final JSONObject jsonProfile = (JSONObject) profile; final String id = (String) jsonProfile.get("id"); final String name = (String) jsonProfile.get("name"); @@ -284,13 +243,10 @@ public class TFM_UuidManager uuidMap.put(name, uuid); } - if (i != requests - 1) - { + if (i != requests - 1) { Thread.sleep(100L); } - } - catch (Exception ex) - { + } catch (Exception ex) { TFM_Log.severe("Could not resolve UUID(s) of " + StringUtils.join(names.subList(i * 100, Math.min((i + 1) * 100, names.size())), ", ")); //TFM_Log.severe(ex); @@ -299,9 +255,9 @@ public class TFM_UuidManager return uuidMap; } - public static UUID getUUIDOf(String name) - { + public static UUID getUUIDOf(String name) { return new TFM_UuidResolver(Arrays.asList(name)).call().get(name); } } + }