From 86ff20b6c904a4d86c54ec52b5939c952b85443a Mon Sep 17 00:00:00 2001 From: games647 Date: Wed, 30 Sep 2015 18:55:41 +0200 Subject: [PATCH] Replacing old inventory protecting with safe packet modifications using ProtocolLib. Instead of clearing the inventory of players and storing it's contents in a file, we now prevent the server from sending the inventory packet if the player is not logged in. The player will see a empty inventory, but has still his items stored on the server. Therefore we don't need to modify the player's inventory and we won't make any inventory corrupted. Fixes Xephi/AuthMeReloaded#203, Fixes Xephi/AuthMeReloaded#193, Fixes Xephi/AuthMeReloaded#191, Fixes Xephi/AuthMeReloaded#148 Remove dead code + Fix empty inventory on the unregister command Fix NPE if ProtocolLib isn't enabled or installed --- pom.xml | 8 + src/main/java/fr/xephi/authme/AuthMe.java | 1571 +++++++++-------- .../authme/cache/backup/DataFileCache.java | 21 +- .../xephi/authme/cache/backup/JsonCache.java | 92 +- .../xephi/authme/cache/limbo/LimboCache.java | 23 +- .../xephi/authme/cache/limbo/LimboPlayer.java | 33 - .../authme/commands/UnregisterCommand.java | 6 +- .../authme/events/ProtectInventoryEvent.java | 9 +- .../authme/events/RestoreInventoryEvent.java | 16 +- .../authme/events/StoreInventoryEvent.java | 12 +- .../listener/AuthMeInventoryListener.java | 101 ++ .../authme/listener/AuthMeServerListener.java | 7 + .../authme/process/join/AsyncronousJoin.java | 611 ++++--- .../login/ProcessSyncronousPlayerLogin.java | 7 +- .../process/logout/AsyncronousLogout.java | 172 +- .../authme/process/quit/AsyncronousQuit.java | 203 +-- .../quit/ProcessSyncronousPlayerQuit.java | 97 +- .../ProcessSyncronousPasswordRegister.java | 8 +- src/main/resources/plugin.yml | 4 +- 19 files changed, 1464 insertions(+), 1537 deletions(-) create mode 100644 src/main/java/fr/xephi/authme/listener/AuthMeInventoryListener.java diff --git a/pom.xml b/pom.xml index 7f69ac979..f797a2c68 100644 --- a/pom.xml +++ b/pom.xml @@ -294,6 +294,14 @@ true + + + com.comphenix.protocol + ProtocolLib + 3.4.0 + true + + net.milkbowl.vault diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index 58d7b39da..efabc5de2 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -1,781 +1,790 @@ -package fr.xephi.authme; - -import com.earth2me.essentials.Essentials; -import com.onarandombox.MultiverseCore.MultiverseCore; -import fr.xephi.authme.api.API; -import fr.xephi.authme.api.NewAPI; -import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.cache.backup.JsonCache; -import fr.xephi.authme.cache.limbo.LimboCache; -import fr.xephi.authme.cache.limbo.LimboPlayer; -import fr.xephi.authme.commands.*; -import fr.xephi.authme.converter.Converter; -import fr.xephi.authme.converter.ForceFlatToSqlite; -import fr.xephi.authme.datasource.*; -import fr.xephi.authme.listener.*; -import fr.xephi.authme.modules.ModuleManager; -import fr.xephi.authme.plugin.manager.BungeeCordMessage; -import fr.xephi.authme.plugin.manager.EssSpawn; -import fr.xephi.authme.process.Management; -import fr.xephi.authme.settings.Messages; -import fr.xephi.authme.settings.OtherAccounts; -import fr.xephi.authme.settings.Settings; -import fr.xephi.authme.settings.Spawn; -import net.milkbowl.vault.permission.Permission; -import net.minelink.ctplus.CombatTagPlus; -import org.apache.logging.log4j.LogManager; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Server; -import org.bukkit.World; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.plugin.PluginManager; -import org.bukkit.plugin.RegisteredServiceProvider; -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.scheduler.BukkitTask; -import org.mcstats.Metrics; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.URL; -import java.net.URLConnection; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Logger; - -public class AuthMe extends JavaPlugin { - - private static AuthMe authme; - - private final Server server = getServer(); - private final Logger authmeLogger = Logger.getLogger("AuthMe"); - public Management management; - public NewAPI api; - public SendMailSSL mail; - private Settings settings; - private Messages m; - public DataManager dataManager; - public DataSource database; - private JsonCache playerBackup; - public OtherAccounts otherAccounts; - public Location essentialsSpawn; - public boolean legacyChestShop = false; - public boolean antibotMod = false; - public boolean delayedAntiBot = true; - - // Hooks TODO: move into modules - public Permission permission; - public Essentials ess; - public MultiverseCore multiverse; - public CombatTagPlus combatTagPlus; - - // Manager - private ModuleManager moduleManager; - - // TODO: Create Manager for fields below - public ConcurrentHashMap sessions = new ConcurrentHashMap<>(); - public ConcurrentHashMap captcha = new ConcurrentHashMap<>(); - public ConcurrentHashMap cap = new ConcurrentHashMap<>(); - public ConcurrentHashMap realIp = new ConcurrentHashMap<>(); - - public static AuthMe getInstance() { - return authme; - } - - public Settings getSettings() { - return settings; - } - - public void setMessages(Messages m) { - this.m = m; - } - - public Messages getMessages() { - return m; - } - - - @Override - public void onEnable() { - // Set the Instance - authme = this; - - // TODO: split the plugin in more modules - moduleManager = new ModuleManager(this); - @SuppressWarnings("unused") - int loaded = moduleManager.loadModules(); - - // TODO: remove vault as hard dependency - PluginManager pm = server.getPluginManager(); - - // Setup the Logger - authmeLogger.setParent(this.getLogger()); - - // Load settings and custom configurations - // TODO: new configuration style (more files) - try { - settings = new Settings(this); - Settings.reload(); - } catch (Exception e) { - ConsoleLogger.writeStackTrace(e); - ConsoleLogger.showError("Can't load the configuration file... Something went wrong, to avoid security issues the server will shutdown!"); - server.shutdown(); - return; - } - - // Setup otherAccounts file - otherAccounts = OtherAccounts.getInstance(); - - // Setup messages - m = Messages.getInstance(); - - // Start the metrics service - // TODO: add a setting to disable metrics - try { - Metrics metrics = new Metrics(this); - metrics.start(); - ConsoleLogger.info("Metrics started successfully!"); - } catch (Exception e) { - // Failed to submit the metrics data - ConsoleLogger.writeStackTrace(e); - ConsoleLogger.showError("Can't start Metrics! The plugin will work anyway..."); - } - - // Set Console Filter - if (Settings.removePassword) { - ConsoleFilter filter = new ConsoleFilter(); - this.getLogger().setFilter(filter); - Bukkit.getLogger().setFilter(filter); - Logger.getLogger("Minecraft").setFilter(filter); - authmeLogger.setFilter(filter); - // Set Log4J Filter - try { - Class.forName("org.apache.logging.log4j.core.Filter"); - setLog4JFilter(); - } catch (ClassNotFoundException | NoClassDefFoundError e) { - ConsoleLogger.info("You're using Minecraft 1.6.x or older, Log4J support will be disabled"); - } - } - - // AntiBot delay - if (Settings.enableAntiBot) { - Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() { - - @Override - public void run() { - delayedAntiBot = false; - } - }, 2400); - } - - // Download GeoIp.dat file - Utils.checkGeoIP(); - - // Load MailApi if needed - if (!Settings.getmailAccount.isEmpty() && !Settings.getmailPassword.isEmpty()) { - mail = new SendMailSSL(this); - } - - // Find Permissions - checkVault(); - - // Check Combat Tag Plus Version - checkCombatTagPlus(); - - // Check Multiverse - checkMultiverse(); - - // Check PerWorldInventories Version - checkPerWorldInventories(); - - // Check ChestShop - checkChestShop(); - - // Check Essentials - checkEssentials(); - - // Do backup on start if enabled - if (Settings.isBackupActivated && Settings.isBackupOnStart) { - // Do backup and check return value! - if (new PerformBackup(this).doBackup()) { - ConsoleLogger.info("Backup performed correctly"); - } else { - ConsoleLogger.showError("Error while performing the backup!"); - } - } - - // Connect to the database and setup tables - try { - setupDatabase(); - } catch (Exception e) { - ConsoleLogger.writeStackTrace(e); - ConsoleLogger.showError(e.getMessage()); - ConsoleLogger.showError("Fatal error occurred during database connection! Authme initialization ABORTED!"); - stopOrUnload(); - return; - } - - // Setup the inventory backup - playerBackup = new JsonCache(this); - - // Set the DataManager - dataManager = new DataManager(this); - - // Setup the new API - api = new NewAPI(this); - // Setup the old deprecated API - new API(this); - - // Setup Management - management = new Management(this); - - // Bungeecord hook - if (Settings.bungee) { - Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); - Bukkit.getMessenger().registerIncomingPluginChannel(this, "BungeeCord", new BungeeCordMessage(this)); - } - - // Legacy chestshop hook - if (legacyChestShop) { - pm.registerEvents(new AuthMeChestShopListener(this), this); - ConsoleLogger.info("Hooked successfully with ChestShop!"); - } - - // Reload support hook - if (Settings.reloadSupport) { - if (database != null) { - int playersOnline = Utils.getOnlinePlayers().size(); - if (playersOnline < 1) { - database.purgeLogged(); - } else { - for (PlayerAuth auth : database.getLoggedPlayers()) { - if (auth == null) - continue; - auth.setLastLogin(new Date().getTime()); - database.updateSession(auth); - PlayerCache.getInstance().addPlayer(auth); - } - } - } - } - - // Register events - pm.registerEvents(new AuthMePlayerListener(this), this); - pm.registerEvents(new AuthMeBlockListener(this), this); - pm.registerEvents(new AuthMeEntityListener(this), this); - pm.registerEvents(new AuthMeServerListener(this), this); - - // Register commands - getCommand("authme").setExecutor(new AdminCommand(this)); - getCommand("register").setExecutor(new RegisterCommand(this)); - getCommand("login").setExecutor(new LoginCommand(this)); - getCommand("changepassword").setExecutor(new ChangePasswordCommand(this)); - getCommand("logout").setExecutor(new LogoutCommand(this)); - getCommand("unregister").setExecutor(new UnregisterCommand(this)); - getCommand("email").setExecutor(new EmailCommand(this)); - getCommand("captcha").setExecutor(new CaptchaCommand(this)); - getCommand("converter").setExecutor(new ConverterCommand(this)); - - // Purge on start if enabled - autoPurge(); - - // Start Email recall task if needed - recallEmail(); - - // Configuration Security Warnings - if (!Settings.isForceSingleSessionEnabled) { - ConsoleLogger.showError("WARNING!!! By disabling ForceSingleSession, your server protection is inadequate!"); - } - if (Settings.getSessionTimeout == 0 && Settings.isSessionsEnabled) { - ConsoleLogger.showError("WARNING!!! You set session timeout to 0, this may cause security issues!"); - } - - // Sponsor messages - ConsoleLogger.info("AuthMe hooks perfectly with the VERYGAMES server hosting!"); - ConsoleLogger.info("Development builds are available on our jenkins, thanks to f14stelt."); - ConsoleLogger.info("Do you want a good gameserver? Look at our sponsor GameHosting.it leader in Italy as Game Server Provider!"); - - // Successful message - ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " correctly enabled!"); - } - - @Override - public void onDisable() { - // Save player data - Collection players = Utils.getOnlinePlayers(); - if (players != null) { - for (Player player : players) { - this.savePlayer(player); - } - } - - // Close the database - if (database != null) { - database.close(); - } - - // Do backup on stop if enabled - if (Settings.isBackupActivated && Settings.isBackupOnStop) { - boolean Backup = new PerformBackup(this).doBackup(); - if (Backup) - ConsoleLogger.info("Backup performed correctly."); - else ConsoleLogger.showError("Error while performing the backup!"); - } - - // Unload modules - moduleManager.unloadModules(); - - // Disabled correctly - ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " disabled!"); - } - - // Stop/unload the server/plugin as defined in the configuration - public void stopOrUnload() { - if (Settings.isStopEnabled) { - ConsoleLogger.showError("THE SERVER IS GOING TO SHUTDOWN AS DEFINED IN THE CONFIGURATION!"); - server.shutdown(); - } else { - server.getPluginManager().disablePlugin(AuthMe.getInstance()); - } - } - - // Show the exception message and stop/unload the server/plugin as defined in the configuration - public void stopOrUnload(Exception e) { - ConsoleLogger.showError(e.getMessage()); - stopOrUnload(); - } - - // Initialize and setup the database - public void setupDatabase() throws Exception { - // Backend MYSQL - FILE - SQLITE - SQLITEHIKARI - boolean isSQLite = false; - switch (Settings.getDataSource) { - case FILE: - database = new FlatFile(); - break; - case MYSQL: - database = new MySQL(); - break; - case SQLITE: - database = new SQLite(); - isSQLite = true; - break; - case SQLITEHIKARI: - database = new SQLite_HIKARI(); - isSQLite = true; - break; - } - - if (isSQLite) { - server.getScheduler().runTaskAsynchronously(this, new Runnable() { - @Override - public void run() { - int accounts = database.getAccountsRegistered(); - if (accounts >= 4000) - ConsoleLogger.showError("YOU'RE USING THE SQLITE DATABASE WITH " + accounts + "+ ACCOUNTS, FOR BETTER PERFORMANCES, PLEASE UPGRADE TO MYSQL!!"); - } - }); - } - - if (Settings.isCachingEnabled) { - database = new CacheDataSource(this, database); - } else { - database = new DatabaseCalls(database); - } - - if (Settings.getDataSource == DataSource.DataSourceType.FILE) { - Converter converter = new ForceFlatToSqlite(database, this); - server.getScheduler().runTaskAsynchronously(this, converter); - ConsoleLogger.showError("FlatFile backend has been detected and is now deprecated, next time server starts up, it will be changed to SQLite... Conversion will be started Asynchronously, it will not drop down your performance !"); - ConsoleLogger.showError("If you want to keep FlatFile, set file again into config at backend, but this message and this change will appear again at the next restart"); - } - } - - // Set the console filter to remove the passwords - private void setLog4JFilter() { - Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() { - - @Override - public void run() { - org.apache.logging.log4j.core.Logger coreLogger = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger(); - coreLogger.addFilter(new Log4JFilter()); - } - }); - } - - // Check the presence of the Vault plugin and a permissions provider - public void checkVault() { - if (server.getPluginManager().isPluginEnabled("Vault")) { - RegisteredServiceProvider permissionProvider = server.getServicesManager().getRegistration(net.milkbowl.vault.permission.Permission.class); - if (permissionProvider != null) { - permission = permissionProvider.getProvider(); - ConsoleLogger.info("Vault detected, hooking with the " + permission.getName() + " permissions system..."); - } else { - ConsoleLogger.showError("Vault detected, but I can't find any permissions plugin to hook with!"); - } - } else { - permission = null; - } - } - - // Check the version of the ChestShop plugin - public void checkChestShop() { - if (Settings.legacyChestShop && server.getPluginManager().isPluginEnabled("ChestShop")) { - String rawver = com.Acrobot.ChestShop.ChestShop.getVersion(); - double version; - try { - version = Double.valueOf(rawver.split(" ")[0]); - } catch (NumberFormatException nfe) { - try { - version = Double.valueOf(rawver.split("t")[0]); - } catch (NumberFormatException nfee) { - legacyChestShop = false; - return; - } - } - if (version >= 3.813) { - return; - } - if (version < 3.50) { - ConsoleLogger.showError("Please Update your ChestShop version! Bugs may occur!"); - return; - } - legacyChestShop = true; - } else { - legacyChestShop = false; - } - } - - // Check PerWorldInventories version - public void checkPerWorldInventories() { - if (server.getPluginManager().isPluginEnabled("PerWorldInventories")) { - double version = 0; - String ver = server.getPluginManager().getPlugin("PerWorldInventories").getDescription().getVersion(); - try { - version = Double.valueOf(ver.split(" ")[0]); - } catch (NumberFormatException nfe) { - try { - version = Double.valueOf(ver.split("t")[0]); - } catch (NumberFormatException ignore) { - } - } - if (version < 1.57) { - ConsoleLogger.showError("Please Update your PerWorldInventories version! INVENTORY WIPE may occur!"); - } - } - } - - // Get the Multiverse plugin - public void checkMultiverse() { - if (Settings.multiverse && server.getPluginManager().isPluginEnabled("Multiverse-Core")) { - try { - multiverse = (MultiverseCore) server.getPluginManager().getPlugin("Multiverse-Core"); - ConsoleLogger.info("Hooked correctly with Multiverse-Core"); - } catch (Exception | NoClassDefFoundError ignored) { - multiverse = null; - } - } else { - multiverse = null; - } - } - - // Get the Essentials plugin - public void checkEssentials() { - if (server.getPluginManager().isPluginEnabled("Essentials")) { - try { - ess = (Essentials) server.getPluginManager().getPlugin("Essentials"); - ConsoleLogger.info("Hooked correctly with Essentials"); - } catch (Exception | NoClassDefFoundError ingnored) { - ess = null; - } - } else { - ess = null; - } - if (server.getPluginManager().isPluginEnabled("EssentialsSpawn")) { - try { - essentialsSpawn = new EssSpawn().getLocation(); - ConsoleLogger.info("Hooked correctly with EssentialsSpawn"); - } catch (Exception e) { - essentialsSpawn = null; - ConsoleLogger.showError("Can't read the /plugins/Essentials/spawn.yml file!"); - } - } else { - essentialsSpawn = null; - } - } - - // Check the presence of CombatTag - public void checkCombatTagPlus() { - if (server.getPluginManager().isPluginEnabled("CombatTagPlus")) { - try { - combatTagPlus = (CombatTagPlus) server.getPluginManager().getPlugin("CombatTagPlus"); - ConsoleLogger.info("Hooked correctly with CombatTagPlus"); - } catch (Exception | NoClassDefFoundError ingnored) { - combatTagPlus = null; - } - } else { - combatTagPlus = null; - } - } - - // Check if a player/command sender have a permission - public boolean authmePermissible(Player player, String perm) { - if (player.hasPermission(perm)) { - return true; - } else if (permission != null) { - return permission.playerHas(player, perm); - } - return false; - } - - public boolean authmePermissible(CommandSender sender, String perm) { - if (sender.hasPermission(perm)) { - return true; - } else if (permission != null) { - return permission.has(sender, perm); - } - return false; - } - - // Save Player Data - public void savePlayer(Player player) { - if ((Utils.isNPC(player)) || (Utils.isUnrestricted(player))) { - return; - } - String name = player.getName().toLowerCase(); - if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead() && Settings.isSaveQuitLocationEnabled) { - final PlayerAuth auth = new PlayerAuth(player.getName().toLowerCase(), player.getLocation().getX(), player.getLocation().getY(), player.getLocation().getZ(), player.getWorld().getName(), player.getName()); - database.updateQuitLoc(auth); - } - if (LimboCache.getInstance().hasLimboPlayer(name)) { - LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name); - if (Settings.protectInventoryBeforeLogInEnabled) { - player.getInventory().setArmorContents(limbo.getArmour()); - player.getInventory().setContents(limbo.getInventory()); - } - if (!Settings.noTeleport) { - player.teleport(limbo.getLoc()); - } - Utils.addNormal(player, limbo.getGroup()); - player.setOp(limbo.getOperator()); - limbo.getTimeoutTaskId().cancel(); - LimboCache.getInstance().deleteLimboPlayer(name); - if (this.playerBackup.doesCacheExist(player)) { - this.playerBackup.removeCache(player); - } - } - PlayerCache.getInstance().removePlayer(name); - database.setUnlogged(name); - player.saveData(); - } - - // Select the player to kick when a vip player join the server when full - public Player generateKickPlayer(Collection collection) { - Player player = null; - for (Player p : collection) { - if (!(authmePermissible(p, "authme.vip"))) { - player = p; - break; - } - } - return player; - } - - // Purge inactive players from the database, as defined in the configuration - private void autoPurge() { - if (!Settings.usePurge) { - return; - } - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.DATE, -(Settings.purgeDelay)); - long until = calendar.getTimeInMillis(); - List cleared = database.autoPurgeDatabase(until); - if (cleared == null) { - return; - } - if (cleared.isEmpty()) { - return; - } - ConsoleLogger.info("AutoPurging the Database: " + cleared.size() + " accounts removed!"); - if (Settings.purgeEssentialsFile && this.ess != null) - dataManager.purgeEssentials(cleared); // name to UUID convertion needed with latest versions - if (Settings.purgePlayerDat) - dataManager.purgeDat(cleared); // name to UUID convertion needed with latest versions of MC - if (Settings.purgeLimitedCreative) - dataManager.purgeLimitedCreative(cleared); - if (Settings.purgeAntiXray) - dataManager.purgeAntiXray(cleared); // IDK if it uses UUID or names... (Actually it purges only names!) - if (Settings.purgePermissions) - dataManager.purgePermissions(cleared, permission); - } - - // Return the spawn location of a player - public Location getSpawnLocation(Player player) { - World world = player.getWorld(); - String[] spawnPriority = Settings.spawnPriority.split(","); - Location spawnLoc = world.getSpawnLocation(); - for (int i = spawnPriority.length - 1; i >= 0; i--) { - String s = spawnPriority[i]; - if (s.equalsIgnoreCase("default") && getDefaultSpawn(world) != null) - spawnLoc = getDefaultSpawn(world); - if (s.equalsIgnoreCase("multiverse") && getMultiverseSpawn(world) != null) - spawnLoc = getMultiverseSpawn(world); - if (s.equalsIgnoreCase("essentials") && getEssentialsSpawn() != null) - spawnLoc = getEssentialsSpawn(); - if (s.equalsIgnoreCase("authme") && getAuthMeSpawn(player) != null) - spawnLoc = getAuthMeSpawn(player); - } - if (spawnLoc == null) { - spawnLoc = world.getSpawnLocation(); - } - return spawnLoc; - } - - // Return the default spawnpoint of a world - private Location getDefaultSpawn(World world) { - return world.getSpawnLocation(); - } - - // Return the multiverse spawnpoint of a world - private Location getMultiverseSpawn(World world) { - if (multiverse != null && Settings.multiverse) { - try { - return multiverse.getMVWorldManager().getMVWorld(world).getSpawnLocation(); - } catch (Exception e) { - e.printStackTrace(); - } - } - return null; - } - - // Return the essentials spawnpoint - private Location getEssentialsSpawn() { - if (essentialsSpawn != null) { - return essentialsSpawn; - } - return null; - } - - // Return the authme soawnpoint - private Location getAuthMeSpawn(Player player) { - if ((!database.isAuthAvailable(player.getName().toLowerCase()) || !player.hasPlayedBefore()) && (Spawn.getInstance().getFirstSpawn() != null)) { - return Spawn.getInstance().getFirstSpawn(); - } - if (Spawn.getInstance().getSpawn() != null) { - return Spawn.getInstance().getSpawn(); - } - return player.getWorld().getSpawnLocation(); - } - - public void switchAntiBotMod(boolean mode) { - this.antibotMod = mode; - Settings.switchAntiBotMod(mode); - } - - private void recallEmail() { - if (!Settings.recallEmail) - return; - Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable() { - - @Override - public void run() { - for (Player player : Utils.getOnlinePlayers()) { - if (player.isOnline()) { - String name = player.getName().toLowerCase(); - if (database.isAuthAvailable(name)) - if (PlayerCache.getInstance().isAuthenticated(name)) { - String email = database.getAuth(name).getEmail(); - if (email == null || email.isEmpty() || email.equalsIgnoreCase("your@email.com")) - m.send(player, "add_email"); - } - } - } - } - }, 1, 1200 * Settings.delayRecall); - } - - public String replaceAllInfos(String message, Player player) { - int playersOnline = Utils.getOnlinePlayers().size(); - message = message.replace("&", "\u00a7"); - message = message.replace("{PLAYER}", player.getName()); - message = message.replace("{ONLINE}", "" + playersOnline); - message = message.replace("{MAXPLAYERS}", "" + server.getMaxPlayers()); - message = message.replace("{IP}", getIP(player)); - message = message.replace("{LOGINS}", "" + PlayerCache.getInstance().getLogged()); - message = message.replace("{WORLD}", player.getWorld().getName()); - message = message.replace("{SERVER}", server.getServerName()); - message = message.replace("{VERSION}", server.getBukkitVersion()); - message = message.replace("{COUNTRY}", Utils.getCountryName(getIP(player))); - return message; - } - - public String getIP(Player player) { - String name = player.getName().toLowerCase(); - String ip = player.getAddress().getAddress().getHostAddress(); - if (Settings.bungee) { - if (realIp.containsKey(name)) - ip = realIp.get(name); - } - if (Settings.checkVeryGames) - if (getVeryGamesIP(player) != null) - ip = getVeryGamesIP(player); - return ip; - } - - public boolean isLoggedIp(String name, String ip) { - int count = 0; - for (Player player : Utils.getOnlinePlayers()) { - if (ip.equalsIgnoreCase(getIP(player)) && database.isLogged(player.getName().toLowerCase()) && !player.getName().equalsIgnoreCase(name)) - count++; - } - return count >= Settings.getMaxLoginPerIp; - } - - public boolean hasJoinedIp(String name, String ip) { - int count = 0; - for (Player player : Utils.getOnlinePlayers()) { - if (ip.equalsIgnoreCase(getIP(player)) && !player.getName().equalsIgnoreCase(name)) - count++; - } - return count >= Settings.getMaxJoinPerIp; - } - - /** - * Get Player real IP through VeryGames method - * - * @param player player - */ - @Deprecated - public String getVeryGamesIP(Player player) { - String realIP = player.getAddress().getAddress().getHostAddress(); - String sUrl = "http://monitor-1.verygames.net/api/?action=ipclean-real-ip&out=raw&ip=%IP%&port=%PORT%"; - sUrl = sUrl.replace("%IP%", player.getAddress().getAddress().getHostAddress()).replace("%PORT%", "" + player.getAddress().getPort()); - try { - URL url = new URL(sUrl); - URLConnection urlc = url.openConnection(); - BufferedReader in = new BufferedReader(new InputStreamReader(urlc.getInputStream())); - String inputLine = in.readLine(); - if (inputLine != null && !inputLine.isEmpty() && !inputLine.equalsIgnoreCase("error") && !inputLine.contains("error")) { - realIP = inputLine; - } - } catch (Exception ignored) { - } - return realIP; - } - - @Deprecated - public String getCountryCode(String ip) { - return Utils.getCountryCode(ip); - } - - @Deprecated - public String getCountryName(String ip) { - return Utils.getCountryName(ip); - } - -} +package fr.xephi.authme; + +import com.comphenix.protocol.ProtocolLibrary; +import com.earth2me.essentials.Essentials; +import com.onarandombox.MultiverseCore.MultiverseCore; +import fr.xephi.authme.api.API; +import fr.xephi.authme.api.NewAPI; +import fr.xephi.authme.cache.auth.PlayerAuth; +import fr.xephi.authme.cache.auth.PlayerCache; +import fr.xephi.authme.cache.backup.JsonCache; +import fr.xephi.authme.cache.limbo.LimboCache; +import fr.xephi.authme.cache.limbo.LimboPlayer; +import fr.xephi.authme.commands.*; +import fr.xephi.authme.converter.Converter; +import fr.xephi.authme.converter.ForceFlatToSqlite; +import fr.xephi.authme.datasource.*; +import fr.xephi.authme.listener.*; +import fr.xephi.authme.modules.ModuleManager; +import fr.xephi.authme.plugin.manager.BungeeCordMessage; +import fr.xephi.authme.plugin.manager.EssSpawn; +import fr.xephi.authme.process.Management; +import fr.xephi.authme.settings.Messages; +import fr.xephi.authme.settings.OtherAccounts; +import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.Spawn; +import net.milkbowl.vault.permission.Permission; +import net.minelink.ctplus.CombatTagPlus; +import org.apache.logging.log4j.LogManager; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Server; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitTask; +import org.mcstats.Metrics; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Logger; + +public class AuthMe extends JavaPlugin { + + private static AuthMe authme; + + private final Server server = getServer(); + private final Logger authmeLogger = Logger.getLogger("AuthMe"); + public Management management; + public NewAPI api; + public SendMailSSL mail; + private Settings settings; + private Messages m; + public DataManager dataManager; + public DataSource database; + private JsonCache playerBackup; + public OtherAccounts otherAccounts; + public Location essentialsSpawn; + public boolean legacyChestShop = false; + public boolean antibotMod = false; + public boolean delayedAntiBot = true; + + // Hooks TODO: move into modules + public Permission permission; + public Essentials ess; + public MultiverseCore multiverse; + public CombatTagPlus combatTagPlus; + public AuthMeInventoryListener inventoryProtector; + + // Manager + private ModuleManager moduleManager; + + // TODO: Create Manager for fields below + public ConcurrentHashMap sessions = new ConcurrentHashMap<>(); + public ConcurrentHashMap captcha = new ConcurrentHashMap<>(); + public ConcurrentHashMap cap = new ConcurrentHashMap<>(); + public ConcurrentHashMap realIp = new ConcurrentHashMap<>(); + + public static AuthMe getInstance() { + return authme; + } + + public Settings getSettings() { + return settings; + } + + public void setMessages(Messages m) { + this.m = m; + } + + public Messages getMessages() { + return m; + } + + + @Override + public void onEnable() { + // Set the Instance + authme = this; + + // TODO: split the plugin in more modules + moduleManager = new ModuleManager(this); + @SuppressWarnings("unused") + int loaded = moduleManager.loadModules(); + + // TODO: remove vault as hard dependency + PluginManager pm = server.getPluginManager(); + + // Setup the Logger + authmeLogger.setParent(this.getLogger()); + + // Load settings and custom configurations + // TODO: new configuration style (more files) + try { + settings = new Settings(this); + Settings.reload(); + } catch (Exception e) { + ConsoleLogger.writeStackTrace(e); + ConsoleLogger.showError("Can't load the configuration file... Something went wrong, to avoid security issues the server will shutdown!"); + server.shutdown(); + return; + } + + // Setup otherAccounts file + otherAccounts = OtherAccounts.getInstance(); + + // Setup messages + m = Messages.getInstance(); + + // Start the metrics service + // TODO: add a setting to disable metrics + try { + Metrics metrics = new Metrics(this); + metrics.start(); + ConsoleLogger.info("Metrics started successfully!"); + } catch (Exception e) { + // Failed to submit the metrics data + ConsoleLogger.writeStackTrace(e); + ConsoleLogger.showError("Can't start Metrics! The plugin will work anyway..."); + } + + // Set Console Filter + if (Settings.removePassword) { + ConsoleFilter filter = new ConsoleFilter(); + this.getLogger().setFilter(filter); + Bukkit.getLogger().setFilter(filter); + Logger.getLogger("Minecraft").setFilter(filter); + authmeLogger.setFilter(filter); + // Set Log4J Filter + try { + Class.forName("org.apache.logging.log4j.core.Filter"); + setLog4JFilter(); + } catch (ClassNotFoundException | NoClassDefFoundError e) { + ConsoleLogger.info("You're using Minecraft 1.6.x or older, Log4J support will be disabled"); + } + } + + // AntiBot delay + if (Settings.enableAntiBot) { + Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() { + + @Override + public void run() { + delayedAntiBot = false; + } + }, 2400); + } + + // Download GeoIp.dat file + Utils.checkGeoIP(); + + // Load MailApi if needed + if (!Settings.getmailAccount.isEmpty() && !Settings.getmailPassword.isEmpty()) { + mail = new SendMailSSL(this); + } + + // Find Permissions + checkVault(); + + // Check Combat Tag Plus Version + checkCombatTagPlus(); + + // Check Multiverse + checkMultiverse(); + + // Check PerWorldInventories Version + checkPerWorldInventories(); + + // Check ChestShop + checkChestShop(); + + // Check Essentials + checkEssentials(); + + //Check if the protocollib is available. If so we could listen for inventory protection + checkProtocolLib(); + + // Do backup on start if enabled + if (Settings.isBackupActivated && Settings.isBackupOnStart) { + // Do backup and check return value! + if (new PerformBackup(this).doBackup()) { + ConsoleLogger.info("Backup performed correctly"); + } else { + ConsoleLogger.showError("Error while performing the backup!"); + } + } + + // Connect to the database and setup tables + try { + setupDatabase(); + } catch (Exception e) { + ConsoleLogger.writeStackTrace(e); + ConsoleLogger.showError(e.getMessage()); + ConsoleLogger.showError("Fatal error occurred during database connection! Authme initialization ABORTED!"); + stopOrUnload(); + return; + } + + // Setup the inventory backup + playerBackup = new JsonCache(); + + // Set the DataManager + dataManager = new DataManager(this); + + // Setup the new API + api = new NewAPI(this); + // Setup the old deprecated API + new API(this); + + // Setup Management + management = new Management(this); + + // Bungeecord hook + if (Settings.bungee) { + Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); + Bukkit.getMessenger().registerIncomingPluginChannel(this, "BungeeCord", new BungeeCordMessage(this)); + } + + // Legacy chestshop hook + if (legacyChestShop) { + pm.registerEvents(new AuthMeChestShopListener(this), this); + ConsoleLogger.info("Hooked successfully with ChestShop!"); + } + + // Reload support hook + if (Settings.reloadSupport) { + if (database != null) { + int playersOnline = Utils.getOnlinePlayers().size(); + if (playersOnline < 1) { + database.purgeLogged(); + } else { + for (PlayerAuth auth : database.getLoggedPlayers()) { + if (auth == null) + continue; + auth.setLastLogin(new Date().getTime()); + database.updateSession(auth); + PlayerCache.getInstance().addPlayer(auth); + } + } + } + } + + // Register events + pm.registerEvents(new AuthMePlayerListener(this), this); + pm.registerEvents(new AuthMeBlockListener(this), this); + pm.registerEvents(new AuthMeEntityListener(this), this); + pm.registerEvents(new AuthMeServerListener(this), this); + + // Register commands + getCommand("authme").setExecutor(new AdminCommand(this)); + getCommand("register").setExecutor(new RegisterCommand(this)); + getCommand("login").setExecutor(new LoginCommand(this)); + getCommand("changepassword").setExecutor(new ChangePasswordCommand(this)); + getCommand("logout").setExecutor(new LogoutCommand(this)); + getCommand("unregister").setExecutor(new UnregisterCommand(this)); + getCommand("email").setExecutor(new EmailCommand(this)); + getCommand("captcha").setExecutor(new CaptchaCommand(this)); + getCommand("converter").setExecutor(new ConverterCommand(this)); + + // Purge on start if enabled + autoPurge(); + + // Start Email recall task if needed + recallEmail(); + + // Configuration Security Warnings + if (!Settings.isForceSingleSessionEnabled) { + ConsoleLogger.showError("WARNING!!! By disabling ForceSingleSession, your server protection is inadequate!"); + } + if (Settings.getSessionTimeout == 0 && Settings.isSessionsEnabled) { + ConsoleLogger.showError("WARNING!!! You set session timeout to 0, this may cause security issues!"); + } + + // Sponsor messages + ConsoleLogger.info("AuthMe hooks perfectly with the VERYGAMES server hosting!"); + ConsoleLogger.info("Development builds are available on our jenkins, thanks to f14stelt."); + ConsoleLogger.info("Do you want a good gameserver? Look at our sponsor GameHosting.it leader in Italy as Game Server Provider!"); + + // Successful message + ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " correctly enabled!"); + } + + @Override + public void onDisable() { + // Save player data + Collection players = Utils.getOnlinePlayers(); + if (players != null) { + for (Player player : players) { + this.savePlayer(player); + } + } + + // Close the database + if (database != null) { + database.close(); + } + + // Do backup on stop if enabled + if (Settings.isBackupActivated && Settings.isBackupOnStop) { + boolean Backup = new PerformBackup(this).doBackup(); + if (Backup) + ConsoleLogger.info("Backup performed correctly."); + else ConsoleLogger.showError("Error while performing the backup!"); + } + + // Unload modules + moduleManager.unloadModules(); + + // Disabled correctly + ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " disabled!"); + } + + // Stop/unload the server/plugin as defined in the configuration + public void stopOrUnload() { + if (Settings.isStopEnabled) { + ConsoleLogger.showError("THE SERVER IS GOING TO SHUTDOWN AS DEFINED IN THE CONFIGURATION!"); + server.shutdown(); + } else { + server.getPluginManager().disablePlugin(AuthMe.getInstance()); + } + } + + // Show the exception message and stop/unload the server/plugin as defined in the configuration + public void stopOrUnload(Exception e) { + ConsoleLogger.showError(e.getMessage()); + stopOrUnload(); + } + + // Initialize and setup the database + public void setupDatabase() throws Exception { + // Backend MYSQL - FILE - SQLITE - SQLITEHIKARI + boolean isSQLite = false; + switch (Settings.getDataSource) { + case FILE: + database = new FlatFile(); + break; + case MYSQL: + database = new MySQL(); + break; + case SQLITE: + database = new SQLite(); + isSQLite = true; + break; + case SQLITEHIKARI: + database = new SQLite_HIKARI(); + isSQLite = true; + break; + } + + if (isSQLite) { + server.getScheduler().runTaskAsynchronously(this, new Runnable() { + @Override + public void run() { + int accounts = database.getAccountsRegistered(); + if (accounts >= 4000) + ConsoleLogger.showError("YOU'RE USING THE SQLITE DATABASE WITH " + accounts + "+ ACCOUNTS, FOR BETTER PERFORMANCES, PLEASE UPGRADE TO MYSQL!!"); + } + }); + } + + if (Settings.isCachingEnabled) { + database = new CacheDataSource(this, database); + } else { + database = new DatabaseCalls(database); + } + + if (Settings.getDataSource == DataSource.DataSourceType.FILE) { + Converter converter = new ForceFlatToSqlite(database, this); + server.getScheduler().runTaskAsynchronously(this, converter); + ConsoleLogger.showError("FlatFile backend has been detected and is now deprecated, next time server starts up, it will be changed to SQLite... Conversion will be started Asynchronously, it will not drop down your performance !"); + ConsoleLogger.showError("If you want to keep FlatFile, set file again into config at backend, but this message and this change will appear again at the next restart"); + } + } + + // Set the console filter to remove the passwords + private void setLog4JFilter() { + Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() { + + @Override + public void run() { + org.apache.logging.log4j.core.Logger coreLogger = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger(); + coreLogger.addFilter(new Log4JFilter()); + } + }); + } + + // Check the presence of the Vault plugin and a permissions provider + public void checkVault() { + if (server.getPluginManager().isPluginEnabled("Vault")) { + RegisteredServiceProvider permissionProvider = server.getServicesManager().getRegistration(net.milkbowl.vault.permission.Permission.class); + if (permissionProvider != null) { + permission = permissionProvider.getProvider(); + ConsoleLogger.info("Vault detected, hooking with the " + permission.getName() + " permissions system..."); + } else { + ConsoleLogger.showError("Vault detected, but I can't find any permissions plugin to hook with!"); + } + } else { + permission = null; + } + } + + // Check the version of the ChestShop plugin + public void checkChestShop() { + if (Settings.legacyChestShop && server.getPluginManager().isPluginEnabled("ChestShop")) { + String rawver = com.Acrobot.ChestShop.ChestShop.getVersion(); + double version; + try { + version = Double.valueOf(rawver.split(" ")[0]); + } catch (NumberFormatException nfe) { + try { + version = Double.valueOf(rawver.split("t")[0]); + } catch (NumberFormatException nfee) { + legacyChestShop = false; + return; + } + } + if (version >= 3.813) { + return; + } + if (version < 3.50) { + ConsoleLogger.showError("Please Update your ChestShop version! Bugs may occur!"); + return; + } + legacyChestShop = true; + } else { + legacyChestShop = false; + } + } + + // Check PerWorldInventories version + public void checkPerWorldInventories() { + if (server.getPluginManager().isPluginEnabled("PerWorldInventories")) { + double version = 0; + String ver = server.getPluginManager().getPlugin("PerWorldInventories").getDescription().getVersion(); + try { + version = Double.valueOf(ver.split(" ")[0]); + } catch (NumberFormatException nfe) { + try { + version = Double.valueOf(ver.split("t")[0]); + } catch (NumberFormatException ignore) { + } + } + if (version < 1.57) { + ConsoleLogger.showError("Please Update your PerWorldInventories version! INVENTORY WIPE may occur!"); + } + } + } + + // Get the Multiverse plugin + public void checkMultiverse() { + if (Settings.multiverse && server.getPluginManager().isPluginEnabled("Multiverse-Core")) { + try { + multiverse = (MultiverseCore) server.getPluginManager().getPlugin("Multiverse-Core"); + ConsoleLogger.info("Hooked correctly with Multiverse-Core"); + } catch (Exception | NoClassDefFoundError ignored) { + multiverse = null; + } + } else { + multiverse = null; + } + } + + // Get the Essentials plugin + public void checkEssentials() { + if (server.getPluginManager().isPluginEnabled("Essentials")) { + try { + ess = (Essentials) server.getPluginManager().getPlugin("Essentials"); + ConsoleLogger.info("Hooked correctly with Essentials"); + } catch (Exception | NoClassDefFoundError ingnored) { + ess = null; + } + } else { + ess = null; + } + if (server.getPluginManager().isPluginEnabled("EssentialsSpawn")) { + try { + essentialsSpawn = new EssSpawn().getLocation(); + ConsoleLogger.info("Hooked correctly with EssentialsSpawn"); + } catch (Exception e) { + essentialsSpawn = null; + ConsoleLogger.showError("Can't read the /plugins/Essentials/spawn.yml file!"); + } + } else { + essentialsSpawn = null; + } + } + + // Check the presence of CombatTag + public void checkCombatTagPlus() { + if (server.getPluginManager().isPluginEnabled("CombatTagPlus")) { + try { + combatTagPlus = (CombatTagPlus) server.getPluginManager().getPlugin("CombatTagPlus"); + ConsoleLogger.info("Hooked correctly with CombatTagPlus"); + } catch (Exception | NoClassDefFoundError ingnored) { + combatTagPlus = null; + } + } else { + combatTagPlus = null; + } + } + + public void checkProtocolLib() { + if (server.getPluginManager().isPluginEnabled("ProtocolLib")) { + inventoryProtector = new AuthMeInventoryListener(this); + ProtocolLibrary.getProtocolManager().addPacketListener(inventoryProtector); + } + } + + // Check if a player/command sender have a permission + public boolean authmePermissible(Player player, String perm) { + if (player.hasPermission(perm)) { + return true; + } else if (permission != null) { + return permission.playerHas(player, perm); + } + return false; + } + + public boolean authmePermissible(CommandSender sender, String perm) { + if (sender.hasPermission(perm)) { + return true; + } else if (permission != null) { + return permission.has(sender, perm); + } + return false; + } + + // Save Player Data + public void savePlayer(Player player) { + if ((Utils.isNPC(player)) || (Utils.isUnrestricted(player))) { + return; + } + String name = player.getName().toLowerCase(); + if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead() && Settings.isSaveQuitLocationEnabled) { + final PlayerAuth auth = new PlayerAuth(player.getName().toLowerCase(), player.getLocation().getX(), player.getLocation().getY(), player.getLocation().getZ(), player.getWorld().getName(), player.getName()); + database.updateQuitLoc(auth); + } + if (LimboCache.getInstance().hasLimboPlayer(name)) { + LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name); + if (!Settings.noTeleport) { + player.teleport(limbo.getLoc()); + } + + Utils.addNormal(player, limbo.getGroup()); + player.setOp(limbo.getOperator()); + limbo.getTimeoutTaskId().cancel(); + LimboCache.getInstance().deleteLimboPlayer(name); + if (this.playerBackup.doesCacheExist(player)) { + this.playerBackup.removeCache(player); + } + } + PlayerCache.getInstance().removePlayer(name); + database.setUnlogged(name); + player.saveData(); + } + + // Select the player to kick when a vip player join the server when full + public Player generateKickPlayer(Collection collection) { + Player player = null; + for (Player p : collection) { + if (!(authmePermissible(p, "authme.vip"))) { + player = p; + break; + } + } + return player; + } + + // Purge inactive players from the database, as defined in the configuration + private void autoPurge() { + if (!Settings.usePurge) { + return; + } + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DATE, -(Settings.purgeDelay)); + long until = calendar.getTimeInMillis(); + List cleared = database.autoPurgeDatabase(until); + if (cleared == null) { + return; + } + if (cleared.isEmpty()) { + return; + } + ConsoleLogger.info("AutoPurging the Database: " + cleared.size() + " accounts removed!"); + if (Settings.purgeEssentialsFile && this.ess != null) + dataManager.purgeEssentials(cleared); // name to UUID convertion needed with latest versions + if (Settings.purgePlayerDat) + dataManager.purgeDat(cleared); // name to UUID convertion needed with latest versions of MC + if (Settings.purgeLimitedCreative) + dataManager.purgeLimitedCreative(cleared); + if (Settings.purgeAntiXray) + dataManager.purgeAntiXray(cleared); // IDK if it uses UUID or names... (Actually it purges only names!) + if (Settings.purgePermissions) + dataManager.purgePermissions(cleared, permission); + } + + // Return the spawn location of a player + public Location getSpawnLocation(Player player) { + World world = player.getWorld(); + String[] spawnPriority = Settings.spawnPriority.split(","); + Location spawnLoc = world.getSpawnLocation(); + for (int i = spawnPriority.length - 1; i >= 0; i--) { + String s = spawnPriority[i]; + if (s.equalsIgnoreCase("default") && getDefaultSpawn(world) != null) + spawnLoc = getDefaultSpawn(world); + if (s.equalsIgnoreCase("multiverse") && getMultiverseSpawn(world) != null) + spawnLoc = getMultiverseSpawn(world); + if (s.equalsIgnoreCase("essentials") && getEssentialsSpawn() != null) + spawnLoc = getEssentialsSpawn(); + if (s.equalsIgnoreCase("authme") && getAuthMeSpawn(player) != null) + spawnLoc = getAuthMeSpawn(player); + } + if (spawnLoc == null) { + spawnLoc = world.getSpawnLocation(); + } + return spawnLoc; + } + + // Return the default spawnpoint of a world + private Location getDefaultSpawn(World world) { + return world.getSpawnLocation(); + } + + // Return the multiverse spawnpoint of a world + private Location getMultiverseSpawn(World world) { + if (multiverse != null && Settings.multiverse) { + try { + return multiverse.getMVWorldManager().getMVWorld(world).getSpawnLocation(); + } catch (Exception e) { + e.printStackTrace(); + } + } + return null; + } + + // Return the essentials spawnpoint + private Location getEssentialsSpawn() { + if (essentialsSpawn != null) { + return essentialsSpawn; + } + return null; + } + + // Return the authme soawnpoint + private Location getAuthMeSpawn(Player player) { + if ((!database.isAuthAvailable(player.getName().toLowerCase()) || !player.hasPlayedBefore()) && (Spawn.getInstance().getFirstSpawn() != null)) { + return Spawn.getInstance().getFirstSpawn(); + } + if (Spawn.getInstance().getSpawn() != null) { + return Spawn.getInstance().getSpawn(); + } + return player.getWorld().getSpawnLocation(); + } + + public void switchAntiBotMod(boolean mode) { + this.antibotMod = mode; + Settings.switchAntiBotMod(mode); + } + + private void recallEmail() { + if (!Settings.recallEmail) + return; + Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable() { + + @Override + public void run() { + for (Player player : Utils.getOnlinePlayers()) { + if (player.isOnline()) { + String name = player.getName().toLowerCase(); + if (database.isAuthAvailable(name)) + if (PlayerCache.getInstance().isAuthenticated(name)) { + String email = database.getAuth(name).getEmail(); + if (email == null || email.isEmpty() || email.equalsIgnoreCase("your@email.com")) + m.send(player, "add_email"); + } + } + } + } + }, 1, 1200 * Settings.delayRecall); + } + + public String replaceAllInfos(String message, Player player) { + int playersOnline = Utils.getOnlinePlayers().size(); + message = message.replace("&", "\u00a7"); + message = message.replace("{PLAYER}", player.getName()); + message = message.replace("{ONLINE}", "" + playersOnline); + message = message.replace("{MAXPLAYERS}", "" + server.getMaxPlayers()); + message = message.replace("{IP}", getIP(player)); + message = message.replace("{LOGINS}", "" + PlayerCache.getInstance().getLogged()); + message = message.replace("{WORLD}", player.getWorld().getName()); + message = message.replace("{SERVER}", server.getServerName()); + message = message.replace("{VERSION}", server.getBukkitVersion()); + message = message.replace("{COUNTRY}", Utils.getCountryName(getIP(player))); + return message; + } + + public String getIP(Player player) { + String name = player.getName().toLowerCase(); + String ip = player.getAddress().getAddress().getHostAddress(); + if (Settings.bungee) { + if (realIp.containsKey(name)) + ip = realIp.get(name); + } + if (Settings.checkVeryGames) + if (getVeryGamesIP(player) != null) + ip = getVeryGamesIP(player); + return ip; + } + + public boolean isLoggedIp(String name, String ip) { + int count = 0; + for (Player player : Utils.getOnlinePlayers()) { + if (ip.equalsIgnoreCase(getIP(player)) && database.isLogged(player.getName().toLowerCase()) && !player.getName().equalsIgnoreCase(name)) + count++; + } + return count >= Settings.getMaxLoginPerIp; + } + + public boolean hasJoinedIp(String name, String ip) { + int count = 0; + for (Player player : Utils.getOnlinePlayers()) { + if (ip.equalsIgnoreCase(getIP(player)) && !player.getName().equalsIgnoreCase(name)) + count++; + } + return count >= Settings.getMaxJoinPerIp; + } + + /** + * Get Player real IP through VeryGames method + * + * @param player player + */ + @Deprecated + public String getVeryGamesIP(Player player) { + String realIP = player.getAddress().getAddress().getHostAddress(); + String sUrl = "http://monitor-1.verygames.net/api/?action=ipclean-real-ip&out=raw&ip=%IP%&port=%PORT%"; + sUrl = sUrl.replace("%IP%", player.getAddress().getAddress().getHostAddress()).replace("%PORT%", "" + player.getAddress().getPort()); + try { + URL url = new URL(sUrl); + URLConnection urlc = url.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(urlc.getInputStream())); + String inputLine = in.readLine(); + if (inputLine != null && !inputLine.isEmpty() && !inputLine.equalsIgnoreCase("error") && !inputLine.contains("error")) { + realIP = inputLine; + } + } catch (Exception ignored) { + } + return realIP; + } + + @Deprecated + public String getCountryCode(String ip) { + return Utils.getCountryCode(ip); + } + + @Deprecated + public String getCountryName(String ip) { + return Utils.getCountryName(ip); + } + +} diff --git a/src/main/java/fr/xephi/authme/cache/backup/DataFileCache.java b/src/main/java/fr/xephi/authme/cache/backup/DataFileCache.java index 6644166fc..5aa40ddef 100644 --- a/src/main/java/fr/xephi/authme/cache/backup/DataFileCache.java +++ b/src/main/java/fr/xephi/authme/cache/backup/DataFileCache.java @@ -1,36 +1,17 @@ package fr.xephi.authme.cache.backup; -import org.bukkit.inventory.ItemStack; - public class DataFileCache { - private ItemStack[] inventory; - private ItemStack[] armor; private String group; private boolean operator; private boolean flying; - public DataFileCache(ItemStack[] inventory, ItemStack[] armor) { - this(inventory, armor, "", false, false); - } - - public DataFileCache(ItemStack[] inventory, ItemStack[] armor, - String group, boolean operator, boolean flying) { - this.inventory = inventory; - this.armor = armor; + public DataFileCache(String group, boolean operator, boolean flying) { this.group = group; this.operator = operator; this.flying = flying; } - public ItemStack[] getInventory() { - return inventory; - } - - public ItemStack[] getArmour() { - return armor; - } - public String getGroup() { return group; } diff --git a/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java b/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java index 760def963..1e66e0aa6 100644 --- a/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java +++ b/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java @@ -3,20 +3,13 @@ package fr.xephi.authme.cache.backup; import com.google.common.base.Charsets; import com.google.common.io.Files; import com.google.gson.*; -import fr.xephi.authme.AuthMe; + import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.Utils; import fr.xephi.authme.settings.Settings; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.SkullMeta; -import org.bukkit.util.io.BukkitObjectInputStream; -import org.bukkit.util.io.BukkitObjectOutputStream; -import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; +import org.bukkit.entity.Player; + import java.io.File; import java.io.IOException; import java.lang.reflect.Type; @@ -24,11 +17,9 @@ import java.lang.reflect.Type; public class JsonCache { private final Gson gson; - private final AuthMe plugin; private final File cacheDir; - public JsonCache(AuthMe plugin) { - this.plugin = plugin; + public JsonCache() { cacheDir = Settings.CACHE_FOLDER; if (!cacheDir.exists() && !cacheDir.isDirectory() && !cacheDir.mkdir()) { ConsoleLogger.showError("Failed to create cache directory."); @@ -99,49 +90,8 @@ public class JsonCache { jsonObject.addProperty("operator", dataFileCache.getOperator()); jsonObject.addProperty("flying", dataFileCache.isFlying()); - JsonArray arr; - ItemStack[] contents; - - // inventory - contents = dataFileCache.getInventory(); - arr = new JsonArray(); - putItems(contents, arr); - jsonObject.add("inventory", arr); - - // armour - contents = dataFileCache.getArmour(); - arr = new JsonArray(); - putItems(contents, arr); - jsonObject.add("armour", arr); - return jsonObject; } - - private void putItems(ItemStack[] contents, JsonArray target) { - for (ItemStack item : contents) { - if (item == null) { - item = new ItemStack(Material.AIR); - } - JsonObject val = new JsonObject(); - if (item.getType() == Material.SKULL_ITEM) { - SkullMeta meta = (SkullMeta) item.getItemMeta(); - if (meta.hasOwner() && (meta.getOwner() == null || meta.getOwner().isEmpty())) { - item.setItemMeta(plugin.getServer().getItemFactory().getItemMeta(Material.SKULL_ITEM)); - } - } - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - BukkitObjectOutputStream objectOut = new BukkitObjectOutputStream(baos); - objectOut.writeObject(item); - objectOut.close(); - val.addProperty("item", Base64Coder.encodeLines(baos.toByteArray())); - } catch (IOException e) { - e.printStackTrace(); - continue; - } - target.add(val); - } - } } private static class PlayerDataDeserializer implements JsonDeserializer { @@ -166,39 +116,7 @@ public class JsonCache { flying = e.getAsBoolean(); } - JsonArray arr; - ItemStack[] inv = null; - ItemStack[] armour = null; - - if (jsonObject.has("inventory")) { - arr = jsonObject.get("inventory").getAsJsonArray(); - inv = getItems(arr); - } - - if (jsonObject.has("armour")) { - arr = jsonObject.get("armour").getAsJsonArray(); - armour = getItems(arr); - } - - return new DataFileCache(inv, armour, group, operator, flying); - } - - private ItemStack[] getItems(JsonArray arr) { - ItemStack[] contents = new ItemStack[arr.size()]; - for (int i = 0; i < arr.size(); i++) { - JsonObject item = arr.get(i).getAsJsonObject(); - String encoded = item.get("item").getAsString(); - byte[] decoded = Base64Coder.decodeLines(encoded); - try { - ByteArrayInputStream baos = new ByteArrayInputStream(decoded); - BukkitObjectInputStream objectIn = new BukkitObjectInputStream(baos); - contents[i] = (ItemStack) objectIn.readObject(); - objectIn.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - return contents; + return new DataFileCache(group, operator, flying); } } diff --git a/src/main/java/fr/xephi/authme/cache/limbo/LimboCache.java b/src/main/java/fr/xephi/authme/cache/limbo/LimboCache.java index 366bc60af..1ab123b62 100644 --- a/src/main/java/fr/xephi/authme/cache/limbo/LimboCache.java +++ b/src/main/java/fr/xephi/authme/cache/limbo/LimboCache.java @@ -11,7 +11,6 @@ import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; import java.util.concurrent.ConcurrentHashMap; @@ -25,15 +24,13 @@ public class LimboCache { private LimboCache(AuthMe plugin) { this.plugin = plugin; this.cache = new ConcurrentHashMap<>(); - this.playerData = new JsonCache(plugin); + this.playerData = new JsonCache(); } public void addLimboPlayer(Player player) { String name = player.getName().toLowerCase(); Location loc = player.getLocation(); GameMode gameMode = player.getGameMode(); - ItemStack[] arm; - ItemStack[] inv; boolean operator = false; String playerGroup = ""; boolean flying = false; @@ -42,12 +39,10 @@ public class LimboCache { final StoreInventoryEvent event = new StoreInventoryEvent(player, playerData); Bukkit.getServer().getPluginManager().callEvent(event); if (!event.isCancelled() && event.getInventory() != null && event.getArmor() != null) { - inv = event.getInventory(); - arm = event.getArmor(); - } else { - inv = null; - arm = null; + player.getInventory().setContents(event.getInventory()); + player.getInventory().setArmorContents(event.getArmor()); } + DataFileCache cache = playerData.readCache(player); if (cache != null) { playerGroup = cache.getGroup(); @@ -58,12 +53,10 @@ public class LimboCache { StoreInventoryEvent event = new StoreInventoryEvent(player); Bukkit.getServer().getPluginManager().callEvent(event); if (!event.isCancelled() && event.getInventory() != null && event.getArmor() != null) { - inv = event.getInventory(); - arm = event.getArmor(); - } else { - inv = null; - arm = null; + player.getInventory().setContents(event.getInventory()); + player.getInventory().setArmorContents(event.getArmor()); } + operator = player.isOp(); flying = player.isFlying(); if (plugin.permission != null) { @@ -93,7 +86,7 @@ public class LimboCache { if (player.isDead()) { loc = plugin.getSpawnLocation(player); } - cache.put(name, new LimboPlayer(name, loc, inv, arm, gameMode, operator, playerGroup, flying)); + cache.put(name, new LimboPlayer(name, loc, gameMode, operator, playerGroup, flying)); } public void addLimboPlayer(Player player, String group) { diff --git a/src/main/java/fr/xephi/authme/cache/limbo/LimboPlayer.java b/src/main/java/fr/xephi/authme/cache/limbo/LimboPlayer.java index 702ddb38f..f4ae0466f 100644 --- a/src/main/java/fr/xephi/authme/cache/limbo/LimboPlayer.java +++ b/src/main/java/fr/xephi/authme/cache/limbo/LimboPlayer.java @@ -2,14 +2,11 @@ package fr.xephi.authme.cache.limbo; import org.bukkit.GameMode; import org.bukkit.Location; -import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitTask; public class LimboPlayer { private String name; - private ItemStack[] inventory; - private ItemStack[] armour; private Location loc = null; private BukkitTask timeoutTaskId = null; private BukkitTask messageTaskId = null; @@ -18,19 +15,6 @@ public class LimboPlayer { private String group = ""; private boolean flying = false; - public LimboPlayer(String name, Location loc, ItemStack[] inventory, - ItemStack[] armour, GameMode gameMode, boolean operator, - String group, boolean flying) { - this.name = name; - this.loc = loc; - this.inventory = inventory; - this.armour = armour; - this.gameMode = gameMode; - this.operator = operator; - this.group = group; - this.flying = flying; - } - public LimboPlayer(String name, Location loc, GameMode gameMode, boolean operator, String group, boolean flying) { this.name = name; @@ -54,22 +38,6 @@ public class LimboPlayer { return loc; } - public ItemStack[] getArmour() { - return armour; - } - - public ItemStack[] getInventory() { - return inventory; - } - - public void setArmour(ItemStack[] armour) { - this.armour = armour; - } - - public void setInventory(ItemStack[] inventory) { - this.inventory = inventory; - } - public GameMode getGameMode() { return gameMode; } @@ -105,5 +73,4 @@ public class LimboPlayer { public boolean isFlying() { return flying; } - } diff --git a/src/main/java/fr/xephi/authme/commands/UnregisterCommand.java b/src/main/java/fr/xephi/authme/commands/UnregisterCommand.java index 814757e1c..06f9b1478 100644 --- a/src/main/java/fr/xephi/authme/commands/UnregisterCommand.java +++ b/src/main/java/fr/xephi/authme/commands/UnregisterCommand.java @@ -18,7 +18,6 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitScheduler; @@ -34,7 +33,7 @@ public class UnregisterCommand implements CommandExecutor { public UnregisterCommand(AuthMe plugin) { this.plugin = plugin; - this.playerCache = new JsonCache(plugin); + this.playerCache = new JsonCache(); } @Override @@ -79,8 +78,7 @@ public class UnregisterCommand implements CommandExecutor { player.teleport(tpEvent.getTo()); } } - player.getInventory().setContents(new ItemStack[36]); - player.getInventory().setArmorContents(new ItemStack[4]); + player.saveData(); PlayerCache.getInstance().removePlayer(player.getName().toLowerCase()); if (!Settings.getRegisteredGroup.isEmpty()) diff --git a/src/main/java/fr/xephi/authme/events/ProtectInventoryEvent.java b/src/main/java/fr/xephi/authme/events/ProtectInventoryEvent.java index 10d5636b5..a09ad4eab 100644 --- a/src/main/java/fr/xephi/authme/events/ProtectInventoryEvent.java +++ b/src/main/java/fr/xephi/authme/events/ProtectInventoryEvent.java @@ -4,7 +4,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; /** - * + * * This event is call just after store inventory into cache and will empty the * player inventory. * @@ -18,12 +18,11 @@ public class ProtectInventoryEvent extends CustomEvent { private ItemStack[] emptyArmor = null; private Player player; - public ProtectInventoryEvent(Player player, ItemStack[] storedinventory, - ItemStack[] storedarmor) { + public ProtectInventoryEvent(Player player) { super(true); this.player = player; - this.storedinventory = storedinventory; - this.storedarmor = storedarmor; + this.storedinventory = player.getInventory().getContents(); + this.storedarmor = player.getInventory().getArmorContents(); this.emptyInventory = new ItemStack[36]; this.emptyArmor = new ItemStack[4]; } diff --git a/src/main/java/fr/xephi/authme/events/RestoreInventoryEvent.java b/src/main/java/fr/xephi/authme/events/RestoreInventoryEvent.java index c2c36ba42..c3069788b 100644 --- a/src/main/java/fr/xephi/authme/events/RestoreInventoryEvent.java +++ b/src/main/java/fr/xephi/authme/events/RestoreInventoryEvent.java @@ -4,8 +4,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; /** - * - * This event restore the inventory from cache + * This event restore the inventory. * * @author Xephi59 */ @@ -15,16 +14,14 @@ public class RestoreInventoryEvent extends CustomEvent { private ItemStack[] armor; private Player player; - public RestoreInventoryEvent(Player player, ItemStack[] inventory, - ItemStack[] armor) { + public RestoreInventoryEvent(Player player) { this.player = player; - this.inventory = inventory; - this.armor = armor; + this.inventory = player.getInventory().getContents(); + this.armor = player.getInventory().getArmorContents(); } - public RestoreInventoryEvent(Player player, ItemStack[] inventory, - ItemStack[] armor, boolean b) { - super(b); + public RestoreInventoryEvent(Player player, boolean async) { + super(async); this.player = player; this.inventory = inventory; this.armor = armor; @@ -53,5 +50,4 @@ public class RestoreInventoryEvent extends CustomEvent { public void setPlayer(Player player) { this.player = player; } - } diff --git a/src/main/java/fr/xephi/authme/events/StoreInventoryEvent.java b/src/main/java/fr/xephi/authme/events/StoreInventoryEvent.java index e8a78806c..18476525f 100644 --- a/src/main/java/fr/xephi/authme/events/StoreInventoryEvent.java +++ b/src/main/java/fr/xephi/authme/events/StoreInventoryEvent.java @@ -1,6 +1,5 @@ package fr.xephi.authme.events; -import fr.xephi.authme.cache.backup.DataFileCache; import fr.xephi.authme.cache.backup.JsonCache; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -24,14 +23,8 @@ public class StoreInventoryEvent extends CustomEvent { public StoreInventoryEvent(Player player, JsonCache jsonCache) { this.player = player; - DataFileCache cache = jsonCache.readCache(player); - if (cache != null) { - this.inventory = cache.getInventory(); - this.armor = cache.getArmour(); - } else { - this.inventory = player.getInventory().getContents(); - this.armor = player.getInventory().getArmorContents(); - } + this.inventory = player.getInventory().getContents(); + this.armor = player.getInventory().getArmorContents(); } public ItemStack[] getInventory() { @@ -57,5 +50,4 @@ public class StoreInventoryEvent extends CustomEvent { public void setPlayer(Player player) { this.player = player; } - } diff --git a/src/main/java/fr/xephi/authme/listener/AuthMeInventoryListener.java b/src/main/java/fr/xephi/authme/listener/AuthMeInventoryListener.java new file mode 100644 index 000000000..9b59a1483 --- /dev/null +++ b/src/main/java/fr/xephi/authme/listener/AuthMeInventoryListener.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2015 AuthMe-Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package fr.xephi.authme.listener; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; + +import fr.xephi.authme.AuthMe; +import fr.xephi.authme.cache.auth.PlayerCache; +import fr.xephi.authme.settings.Settings; + +import java.lang.reflect.InvocationTargetException; + +import java.util.Arrays; +import java.util.Collections; +import java.util.logging.Level; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public class AuthMeInventoryListener extends PacketAdapter { + + private static final int PLAYER_INVENTORY = 0; + //http://wiki.vg/Inventory#Inventory (0-4 crafting, 5-8 armor, 9-35 main inventory, 36-44 inventory) + //+1 because an index starts with 0 + private static final int PLAYER_CRAFTING_SIZE = 5; + private static final int HOTBAR_SIZE = 9; + + public AuthMeInventoryListener(AuthMe plugin) { + super(plugin, PacketType.Play.Server.SET_SLOT, PacketType.Play.Server.WINDOW_ITEMS); + } + + @Override + public void onPacketSending(PacketEvent packetEvent) { + Player player = packetEvent.getPlayer(); + PacketContainer packet = packetEvent.getPacket(); + + byte windowId = packet.getIntegers().read(0).byteValue(); + if (windowId == PLAYER_INVENTORY && Settings.protectInventoryBeforeLogInEnabled + && !PlayerCache.getInstance().isAuthenticated(player.getName())) { + packetEvent.setCancelled(true); + } + } + + public void sendInventoryPacket(Player player) { + ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); + PacketContainer inventoryPacket = protocolManager.createPacket(PacketType.Play.Server.WINDOW_ITEMS); + + //we are sending our own inventory + inventoryPacket.getIntegers().write(0, PLAYER_INVENTORY); + + ItemStack[] playerCrafting = new ItemStack[PLAYER_CRAFTING_SIZE]; + ItemStack[] armorContents = player.getInventory().getArmorContents(); + ItemStack[] mainInventory = player.getInventory().getContents(); + + //bukkit saves the armor in reversed order + Collections.reverse(Arrays.asList(armorContents)); + + //same main inventory. The hotbar is at the beginning but it should be at the end of the array + ItemStack[] hotbar = Arrays.copyOfRange(mainInventory, 0, HOTBAR_SIZE); + ItemStack[] storedInventory = Arrays.copyOfRange(mainInventory, HOTBAR_SIZE, mainInventory.length); + + //concat all parts of the inventory together + int inventorySize = playerCrafting.length + armorContents.length + mainInventory.length; + ItemStack[] completeInventory = new ItemStack[inventorySize]; + + System.arraycopy(playerCrafting, 0, completeInventory, 0, playerCrafting.length); + System.arraycopy(armorContents, 0, completeInventory, playerCrafting.length, armorContents.length); + + //storedInventory and hotbar + System.arraycopy(storedInventory, 0, completeInventory + , playerCrafting.length + armorContents.length, storedInventory.length); + System.arraycopy(hotbar, 0, completeInventory + , playerCrafting.length + armorContents.length + storedInventory.length, hotbar.length); + + inventoryPacket.getItemArrayModifier().write(0, completeInventory); + try { + protocolManager.sendServerPacket(player, inventoryPacket, false); + } catch (InvocationTargetException invocationExc) { + plugin.getLogger().log(Level.WARNING, "Error during inventory recovery", invocationExc); + } + } +} diff --git a/src/main/java/fr/xephi/authme/listener/AuthMeServerListener.java b/src/main/java/fr/xephi/authme/listener/AuthMeServerListener.java index d13e87383..22f714935 100644 --- a/src/main/java/fr/xephi/authme/listener/AuthMeServerListener.java +++ b/src/main/java/fr/xephi/authme/listener/AuthMeServerListener.java @@ -68,6 +68,10 @@ public class AuthMeServerListener implements Listener { plugin.permission = null; ConsoleLogger.showError("Vault has been disabled, unhook permissions!"); } + if (pluginName.equalsIgnoreCase("ProtocolLib")) { + plugin.inventoryProtector = null; + ConsoleLogger.showError("ProtocolLib has been disabled, unhook packet inventory protection!"); + } } @EventHandler(priority = EventPriority.HIGHEST) @@ -83,5 +87,8 @@ public class AuthMeServerListener implements Listener { plugin.checkCombatTagPlus(); if (pluginName.equalsIgnoreCase("Vault")) plugin.checkVault(); + if (pluginName.equalsIgnoreCase("ProtocolLib")) { + plugin.checkProtocolLib(); + } } } diff --git a/src/main/java/fr/xephi/authme/process/join/AsyncronousJoin.java b/src/main/java/fr/xephi/authme/process/join/AsyncronousJoin.java index 4df4928e7..9a31b8350 100644 --- a/src/main/java/fr/xephi/authme/process/join/AsyncronousJoin.java +++ b/src/main/java/fr/xephi/authme/process/join/AsyncronousJoin.java @@ -1,315 +1,296 @@ -package fr.xephi.authme.process.join; - -import fr.xephi.authme.AuthMe; -import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.Utils; -import fr.xephi.authme.Utils.GroupType; -import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.cache.backup.DataFileCache; -import fr.xephi.authme.cache.backup.JsonCache; -import fr.xephi.authme.cache.limbo.LimboCache; -import fr.xephi.authme.cache.limbo.LimboPlayer; -import fr.xephi.authme.datasource.DataSource; -import fr.xephi.authme.events.FirstSpawnTeleportEvent; -import fr.xephi.authme.events.ProtectInventoryEvent; -import fr.xephi.authme.events.SpawnTeleportEvent; -import fr.xephi.authme.listener.AuthMePlayerListener; -import fr.xephi.authme.settings.Messages; -import fr.xephi.authme.settings.Settings; -import fr.xephi.authme.settings.Spawn; -import fr.xephi.authme.task.MessageTask; -import fr.xephi.authme.task.TimeoutTask; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.scheduler.BukkitScheduler; -import org.bukkit.scheduler.BukkitTask; - -public class AsyncronousJoin { - - protected Player player; - protected DataSource database; - protected AuthMe plugin; - protected String name; - private Messages m = Messages.getInstance(); - private JsonCache playerBackup; - - public AsyncronousJoin(Player player, AuthMe plugin, DataSource database) { - this.player = player; - this.plugin = plugin; - this.database = database; - this.playerBackup = new JsonCache(plugin); - this.name = player.getName().toLowerCase(); - } - - public void process() { - if (AuthMePlayerListener.gameMode.containsKey(name)) - AuthMePlayerListener.gameMode.remove(name); - AuthMePlayerListener.gameMode.putIfAbsent(name, player.getGameMode()); - BukkitScheduler sched = plugin.getServer().getScheduler(); - - if (Utils.isNPC(player) || Utils.isUnrestricted(player)) { - return; - } - - if (plugin.ess != null && Settings.disableSocialSpy) { - plugin.ess.getUser(player).setSocialSpyEnabled(false); - } - - final String ip = plugin.getIP(player); - if (Settings.isAllowRestrictedIp && !Settings.getRestrictedIp(name, ip)) { - final GameMode gM = AuthMePlayerListener.gameMode.get(name); - sched.scheduleSyncDelayedTask(plugin, new Runnable() { - - @Override - public void run() { - AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true); - player.setGameMode(gM); - player.kickPlayer("You are not the Owner of this account, please try another name!"); - if (Settings.banUnsafeIp) - plugin.getServer().banIP(ip); - } - - }); - return; - } - if (Settings.getMaxJoinPerIp > 0 && !plugin.authmePermissible(player, "authme.allow2accounts") && !ip.equalsIgnoreCase("127.0.0.1") && !ip.equalsIgnoreCase("localhost")) { - if (plugin.hasJoinedIp(player.getName(), ip)) { - sched.scheduleSyncDelayedTask(plugin, new Runnable() { - - @Override - public void run() { - player.kickPlayer("A player with the same IP is already in game!"); - } - - }); - return; - } - } - final Location spawnLoc = plugin.getSpawnLocation(player); - final boolean isAuthAvailable = database.isAuthAvailable(name); - if (isAuthAvailable) { - if (Settings.isForceSurvivalModeEnabled && !Settings.forceOnlyAfterLogin) { - sched.scheduleSyncDelayedTask(plugin, new Runnable() { - - @Override - public void run() { - AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true); - Utils.forceGM(player); - } - - }); - } - if (!Settings.noTeleport) - if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) { - sched.scheduleSyncDelayedTask(plugin, new Runnable() { - - @Override - public void run() { - SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name)); - plugin.getServer().getPluginManager().callEvent(tpEvent); - if (!tpEvent.isCancelled()) { - if (player.isOnline() && tpEvent.getTo() != null) { - if (tpEvent.getTo().getWorld() != null) - player.teleport(tpEvent.getTo()); - } - } - } - - }); - } - placePlayerSafely(player, spawnLoc); - LimboCache.getInstance().updateLimboPlayer(player); - DataFileCache dataFile = new DataFileCache(LimboCache.getInstance().getLimboPlayer(name).getInventory(), LimboCache.getInstance().getLimboPlayer(name).getArmour()); - playerBackup.createCache(player, dataFile); - // protect inventory - if (Settings.protectInventoryBeforeLogInEnabled) { - LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(player.getName().toLowerCase()); - ProtectInventoryEvent ev = new ProtectInventoryEvent(player, limbo.getInventory(), limbo.getArmour()); - plugin.getServer().getPluginManager().callEvent(ev); - if (ev.isCancelled()) { - if (!Settings.noConsoleSpam) - ConsoleLogger.info("ProtectInventoryEvent has been cancelled for " + player.getName() + " ..."); - } else { - final ItemStack[] inv = ev.getEmptyArmor(); - final ItemStack[] armor = ev.getEmptyArmor(); - sched.scheduleSyncDelayedTask(plugin, new Runnable() { - - @Override - public void run() { - plugin.api.setPlayerInventory(player, inv, armor); - } - - }); - } - } - } else { - if (Settings.isForceSurvivalModeEnabled && !Settings.forceOnlyAfterLogin) { - sched.scheduleSyncDelayedTask(plugin, new Runnable() { - - @Override - public void run() { - AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true); - Utils.forceGM(player); - } - - }); - } - if (!Settings.unRegisteredGroup.isEmpty()) { - Utils.setGroup(player, Utils.GroupType.UNREGISTERED); - } - if (!Settings.isForcedRegistrationEnabled) { - return; - } - if (!Settings.noTeleport) - if (!needFirstspawn() && Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) { - sched.scheduleSyncDelayedTask(plugin, new Runnable() { - @Override - public void run() { - SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name)); - plugin.getServer().getPluginManager().callEvent(tpEvent); - if (!tpEvent.isCancelled()) { - if (player.isOnline() && tpEvent.getTo() != null) { - if (tpEvent.getTo().getWorld() != null) - player.teleport(tpEvent.getTo()); - } - } - } - - }); - } - - } - String[] msg; - if (Settings.emailRegistration) { - msg = isAuthAvailable ? m.send("login_msg") : m.send("reg_email_msg"); - } else { - msg = isAuthAvailable ? m.send("login_msg") : m.send("reg_msg"); - } - int time = Settings.getRegistrationTimeout * 20; - int msgInterval = Settings.getWarnMessageInterval; - if (time != 0) { - BukkitTask id = sched.runTaskLaterAsynchronously(plugin, new TimeoutTask(plugin, name, player), time); - if (!LimboCache.getInstance().hasLimboPlayer(name)) - LimboCache.getInstance().addLimboPlayer(player); - LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id); - } - if (!LimboCache.getInstance().hasLimboPlayer(name)) - LimboCache.getInstance().addLimboPlayer(player); - if (isAuthAvailable) { - Utils.setGroup(player, GroupType.NOTLOGGEDIN); - } else { - Utils.setGroup(player, GroupType.UNREGISTERED); - } - sched.scheduleSyncDelayedTask(plugin, new Runnable() { - - @Override - public void run() { - if (player.isOp()) - player.setOp(false); - if (player.getGameMode() != GameMode.CREATIVE && !Settings.isMovementAllowed) { - player.setAllowFlight(true); - player.setFlying(true); - } - player.setNoDamageTicks(Settings.getRegistrationTimeout * 20); - if (Settings.useEssentialsMotd) - player.performCommand("motd"); - if (Settings.applyBlindEffect) - player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, Settings.getRegistrationTimeout * 20, 2)); - if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) { - player.setWalkSpeed(0.0f); - player.setFlySpeed(0.0f); - } - } - - }); - if (Settings.isSessionsEnabled && isAuthAvailable && (PlayerCache.getInstance().isAuthenticated(name) || database.isLogged(name))) { - if (plugin.sessions.containsKey(name)) - plugin.sessions.get(name).cancel(); - plugin.sessions.remove(name); - PlayerAuth auth = database.getAuth(name); - if (auth != null && auth.getIp().equals(ip)) { - m.send(player, "valid_session"); - PlayerCache.getInstance().removePlayer(name); - database.setUnlogged(name); - plugin.management.performLogin(player, "dontneed", true); - } else if (Settings.sessionExpireOnIpChange) { - PlayerCache.getInstance().removePlayer(name); - database.setUnlogged(name); - m.send(player, "invalid_session"); - } - return; - } - BukkitTask msgT = sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name, msg, msgInterval)); - LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT); - } - - private boolean needFirstspawn() { - if (player.hasPlayedBefore()) - return false; - if (Spawn.getInstance().getFirstSpawn() == null || Spawn.getInstance().getFirstSpawn().getWorld() == null) - return false; - FirstSpawnTeleportEvent tpEvent = new FirstSpawnTeleportEvent(player, player.getLocation(), Spawn.getInstance().getFirstSpawn()); - plugin.getServer().getPluginManager().callEvent(tpEvent); - if (!tpEvent.isCancelled()) { - if (player.isOnline() && tpEvent.getTo() != null && tpEvent.getTo().getWorld() != null) { - final Location fLoc = tpEvent.getTo(); - Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { - - @Override - public void run() { - player.teleport(fLoc); - } - - }); - } - } - return true; - - } - - private void placePlayerSafely(final Player player, - final Location spawnLoc) { - Location loc = null; - if (spawnLoc == null) - return; - if (!Settings.noTeleport) - return; - if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) - return; - if (!player.hasPlayedBefore()) - return; - Block b = player.getLocation().getBlock(); - if (b.getType() == Material.PORTAL || b.getType() == Material.ENDER_PORTAL) { - m.send(player, "unsafe_spawn"); - if (spawnLoc.getWorld() != null) - loc = spawnLoc; - } else { - Block c = player.getLocation().add(0D, 1D, 0D).getBlock(); - if (c.getType() == Material.PORTAL || c.getType() == Material.ENDER_PORTAL) { - m.send(player, "unsafe_spawn"); - if (spawnLoc.getWorld() != null) - loc = spawnLoc; - } - } - if (loc != null) { - final Location floc = loc; - Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { - - @Override - public void run() { - player.teleport(floc); - } - - }); - } - } - -} +package fr.xephi.authme.process.join; + +import fr.xephi.authme.AuthMe; +import fr.xephi.authme.ConsoleLogger; +import fr.xephi.authme.Utils; +import fr.xephi.authme.Utils.GroupType; +import fr.xephi.authme.cache.auth.PlayerAuth; +import fr.xephi.authme.cache.auth.PlayerCache; +import fr.xephi.authme.cache.limbo.LimboCache; +import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.events.FirstSpawnTeleportEvent; +import fr.xephi.authme.events.ProtectInventoryEvent; +import fr.xephi.authme.events.SpawnTeleportEvent; +import fr.xephi.authme.listener.AuthMePlayerListener; +import fr.xephi.authme.settings.Messages; +import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.Spawn; +import fr.xephi.authme.task.MessageTask; +import fr.xephi.authme.task.TimeoutTask; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitScheduler; +import org.bukkit.scheduler.BukkitTask; + +public class AsyncronousJoin { + + protected Player player; + protected DataSource database; + protected AuthMe plugin; + protected String name; + private Messages m = Messages.getInstance(); + + public AsyncronousJoin(Player player, AuthMe plugin, DataSource database) { + this.player = player; + this.plugin = plugin; + this.database = database; + this.name = player.getName().toLowerCase(); + } + + public void process() { + if (AuthMePlayerListener.gameMode.containsKey(name)) + AuthMePlayerListener.gameMode.remove(name); + AuthMePlayerListener.gameMode.putIfAbsent(name, player.getGameMode()); + BukkitScheduler sched = plugin.getServer().getScheduler(); + + if (Utils.isNPC(player) || Utils.isUnrestricted(player)) { + return; + } + + if (plugin.ess != null && Settings.disableSocialSpy) { + plugin.ess.getUser(player).setSocialSpyEnabled(false); + } + + final String ip = plugin.getIP(player); + if (Settings.isAllowRestrictedIp && !Settings.getRestrictedIp(name, ip)) { + final GameMode gM = AuthMePlayerListener.gameMode.get(name); + sched.scheduleSyncDelayedTask(plugin, new Runnable() { + + @Override + public void run() { + AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true); + player.setGameMode(gM); + player.kickPlayer("You are not the Owner of this account, please try another name!"); + if (Settings.banUnsafeIp) + plugin.getServer().banIP(ip); + } + + }); + return; + } + if (Settings.getMaxJoinPerIp > 0 && !plugin.authmePermissible(player, "authme.allow2accounts") && !ip.equalsIgnoreCase("127.0.0.1") && !ip.equalsIgnoreCase("localhost")) { + if (plugin.hasJoinedIp(player.getName(), ip)) { + sched.scheduleSyncDelayedTask(plugin, new Runnable() { + + @Override + public void run() { + player.kickPlayer("A player with the same IP is already in game!"); + } + + }); + return; + } + } + final Location spawnLoc = plugin.getSpawnLocation(player); + final boolean isAuthAvailable = database.isAuthAvailable(name); + if (isAuthAvailable) { + if (Settings.isForceSurvivalModeEnabled && !Settings.forceOnlyAfterLogin) { + sched.scheduleSyncDelayedTask(plugin, new Runnable() { + + @Override + public void run() { + AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true); + Utils.forceGM(player); + } + + }); + } + if (!Settings.noTeleport) + if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) { + sched.scheduleSyncDelayedTask(plugin, new Runnable() { + + @Override + public void run() { + SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name)); + plugin.getServer().getPluginManager().callEvent(tpEvent); + if (!tpEvent.isCancelled()) { + if (player.isOnline() && tpEvent.getTo() != null) { + if (tpEvent.getTo().getWorld() != null) + player.teleport(tpEvent.getTo()); + } + } + } + + }); + } + placePlayerSafely(player, spawnLoc); + LimboCache.getInstance().updateLimboPlayer(player); + // protect inventory + if (Settings.protectInventoryBeforeLogInEnabled && plugin.inventoryProtector != null) { + ProtectInventoryEvent ev = new ProtectInventoryEvent(player); + plugin.getServer().getPluginManager().callEvent(ev); + if (ev.isCancelled()) { + plugin.inventoryProtector.sendInventoryPacket(player); + if (!Settings.noConsoleSpam) + ConsoleLogger.info("ProtectInventoryEvent has been cancelled for " + player.getName() + " ..."); + } + } + } else { + if (Settings.isForceSurvivalModeEnabled && !Settings.forceOnlyAfterLogin) { + sched.scheduleSyncDelayedTask(plugin, new Runnable() { + + @Override + public void run() { + AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true); + Utils.forceGM(player); + } + + }); + } + if (!Settings.unRegisteredGroup.isEmpty()) { + Utils.setGroup(player, Utils.GroupType.UNREGISTERED); + } + if (!Settings.isForcedRegistrationEnabled) { + return; + } + if (!Settings.noTeleport) + if (!needFirstspawn() && Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) { + sched.scheduleSyncDelayedTask(plugin, new Runnable() { + @Override + public void run() { + SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name)); + plugin.getServer().getPluginManager().callEvent(tpEvent); + if (!tpEvent.isCancelled()) { + if (player.isOnline() && tpEvent.getTo() != null) { + if (tpEvent.getTo().getWorld() != null) + player.teleport(tpEvent.getTo()); + } + } + } + + }); + } + + } + String[] msg; + if (Settings.emailRegistration) { + msg = isAuthAvailable ? m.send("login_msg") : m.send("reg_email_msg"); + } else { + msg = isAuthAvailable ? m.send("login_msg") : m.send("reg_msg"); + } + int time = Settings.getRegistrationTimeout * 20; + int msgInterval = Settings.getWarnMessageInterval; + if (time != 0) { + BukkitTask id = sched.runTaskLaterAsynchronously(plugin, new TimeoutTask(plugin, name, player), time); + if (!LimboCache.getInstance().hasLimboPlayer(name)) + LimboCache.getInstance().addLimboPlayer(player); + LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id); + } + if (!LimboCache.getInstance().hasLimboPlayer(name)) + LimboCache.getInstance().addLimboPlayer(player); + if (isAuthAvailable) { + Utils.setGroup(player, GroupType.NOTLOGGEDIN); + } else { + Utils.setGroup(player, GroupType.UNREGISTERED); + } + sched.scheduleSyncDelayedTask(plugin, new Runnable() { + + @Override + public void run() { + if (player.isOp()) + player.setOp(false); + if (player.getGameMode() != GameMode.CREATIVE && !Settings.isMovementAllowed) { + player.setAllowFlight(true); + player.setFlying(true); + } + player.setNoDamageTicks(Settings.getRegistrationTimeout * 20); + if (Settings.useEssentialsMotd) + player.performCommand("motd"); + if (Settings.applyBlindEffect) + player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, Settings.getRegistrationTimeout * 20, 2)); + if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) { + player.setWalkSpeed(0.0f); + player.setFlySpeed(0.0f); + } + } + + }); + if (Settings.isSessionsEnabled && isAuthAvailable && (PlayerCache.getInstance().isAuthenticated(name) || database.isLogged(name))) { + if (plugin.sessions.containsKey(name)) + plugin.sessions.get(name).cancel(); + plugin.sessions.remove(name); + PlayerAuth auth = database.getAuth(name); + if (auth != null && auth.getIp().equals(ip)) { + m.send(player, "valid_session"); + PlayerCache.getInstance().removePlayer(name); + database.setUnlogged(name); + plugin.management.performLogin(player, "dontneed", true); + } else if (Settings.sessionExpireOnIpChange) { + PlayerCache.getInstance().removePlayer(name); + database.setUnlogged(name); + m.send(player, "invalid_session"); + } + return; + } + BukkitTask msgT = sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name, msg, msgInterval)); + LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT); + } + + private boolean needFirstspawn() { + if (player.hasPlayedBefore()) + return false; + if (Spawn.getInstance().getFirstSpawn() == null || Spawn.getInstance().getFirstSpawn().getWorld() == null) + return false; + FirstSpawnTeleportEvent tpEvent = new FirstSpawnTeleportEvent(player, player.getLocation(), Spawn.getInstance().getFirstSpawn()); + plugin.getServer().getPluginManager().callEvent(tpEvent); + if (!tpEvent.isCancelled()) { + if (player.isOnline() && tpEvent.getTo() != null && tpEvent.getTo().getWorld() != null) { + final Location fLoc = tpEvent.getTo(); + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + + @Override + public void run() { + player.teleport(fLoc); + } + + }); + } + } + return true; + + } + + private void placePlayerSafely(final Player player, + final Location spawnLoc) { + Location loc = null; + if (spawnLoc == null) + return; + if (!Settings.noTeleport) + return; + if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) + return; + if (!player.hasPlayedBefore()) + return; + Block b = player.getLocation().getBlock(); + if (b.getType() == Material.PORTAL || b.getType() == Material.ENDER_PORTAL) { + m.send(player, "unsafe_spawn"); + if (spawnLoc.getWorld() != null) + loc = spawnLoc; + } else { + Block c = player.getLocation().add(0D, 1D, 0D).getBlock(); + if (c.getType() == Material.PORTAL || c.getType() == Material.ENDER_PORTAL) { + m.send(player, "unsafe_spawn"); + if (spawnLoc.getWorld() != null) + loc = spawnLoc; + } + } + if (loc != null) { + final Location floc = loc; + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + + @Override + public void run() { + player.teleport(floc); + } + + }); + } + } + +} diff --git a/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java b/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java index 28f9a861b..da0a42b2b 100644 --- a/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java +++ b/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java @@ -42,7 +42,7 @@ public class ProcessSyncronousPlayerLogin implements Runnable { this.name = player.getName().toLowerCase(); this.limbo = LimboCache.getInstance().getLimboPlayer(name); this.auth = database.getAuth(name); - this.playerCache = new JsonCache(plugin); + this.playerCache = new JsonCache(); } public LimboPlayer getLimbo() { @@ -92,10 +92,11 @@ public class ProcessSyncronousPlayerLogin implements Runnable { } protected void restoreInventory() { - RestoreInventoryEvent event = new RestoreInventoryEvent(player, limbo.getInventory(), limbo.getArmour()); + RestoreInventoryEvent event = new RestoreInventoryEvent(player); Bukkit.getServer().getPluginManager().callEvent(event); if (!event.isCancelled()) { plugin.api.setPlayerInventory(player, event.getInventory(), event.getArmor()); + plugin.inventoryProtector.sendInventoryPacket(player); } } @@ -128,7 +129,7 @@ public class ProcessSyncronousPlayerLogin implements Runnable { // Inventory - Make it after restore GameMode , cause we need to // restore the // right inventory in the right gamemode - if (Settings.protectInventoryBeforeLogInEnabled && player.hasPlayedBefore()) { + if (Settings.protectInventoryBeforeLogInEnabled && plugin.inventoryProtector != null) { restoreInventory(); } if (Settings.forceOnlyAfterLogin) { diff --git a/src/main/java/fr/xephi/authme/process/logout/AsyncronousLogout.java b/src/main/java/fr/xephi/authme/process/logout/AsyncronousLogout.java index d1f890ad4..0d4e40020 100644 --- a/src/main/java/fr/xephi/authme/process/logout/AsyncronousLogout.java +++ b/src/main/java/fr/xephi/authme/process/logout/AsyncronousLogout.java @@ -1,91 +1,81 @@ -package fr.xephi.authme.process.logout; - -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitScheduler; - -import fr.xephi.authme.AuthMe; -import fr.xephi.authme.Utils; -import fr.xephi.authme.Utils.GroupType; -import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.cache.backup.DataFileCache; -import fr.xephi.authme.cache.backup.JsonCache; -import fr.xephi.authme.cache.limbo.LimboCache; -import fr.xephi.authme.datasource.DataSource; -import fr.xephi.authme.events.AuthMeTeleportEvent; -import fr.xephi.authme.settings.Messages; -import fr.xephi.authme.settings.Settings; - -public class AsyncronousLogout { - - protected Player player; - protected String name; - protected AuthMe plugin; - protected DataSource database; - protected boolean canLogout = true; - private Messages m = Messages.getInstance(); - private JsonCache playerBackup; - - public AsyncronousLogout(Player player, AuthMe plugin, - DataSource database) { - this.player = player; - this.plugin = plugin; - this.database = database; - this.name = player.getName().toLowerCase(); - this.playerBackup = new JsonCache(plugin); - } - - private void preLogout() { - if (!PlayerCache.getInstance().isAuthenticated(name)) { - m.send(player, "not_logged_in"); - canLogout = false; - } - } - - public void process() { - preLogout(); - if (!canLogout) - return; - final Player p = player; - BukkitScheduler sched = p.getServer().getScheduler(); - PlayerAuth auth = PlayerCache.getInstance().getAuth(name); - database.updateSession(auth); - auth.setQuitLocX(p.getLocation().getX()); - auth.setQuitLocY(p.getLocation().getY()); - auth.setQuitLocZ(p.getLocation().getZ()); - auth.setWorld(p.getWorld().getName()); - database.updateQuitLoc(auth); - - PlayerCache.getInstance().removePlayer(name); - database.setUnlogged(name); - if (Settings.isTeleportToSpawnEnabled && !Settings.noTeleport) { - Location spawnLoc = plugin.getSpawnLocation(p); - final AuthMeTeleportEvent tpEvent = new AuthMeTeleportEvent(p, spawnLoc); - sched.scheduleSyncDelayedTask(plugin, new Runnable() { - - @Override - public void run() { - plugin.getServer().getPluginManager().callEvent(tpEvent); - if (!tpEvent.isCancelled()) { - if (tpEvent.getTo() != null) - p.teleport(tpEvent.getTo()); - } - } - }); - } - - if (LimboCache.getInstance().hasLimboPlayer(name)) - LimboCache.getInstance().deleteLimboPlayer(name); - LimboCache.getInstance().addLimboPlayer(player); - Utils.setGroup(player, GroupType.NOTLOGGEDIN); - if (Settings.protectInventoryBeforeLogInEnabled) { - player.getInventory().clear(); - // create cache file for handling lost of inventories on unlogged in - // status - DataFileCache playerData = new DataFileCache(LimboCache.getInstance().getLimboPlayer(name).getInventory(), LimboCache.getInstance().getLimboPlayer(name).getArmour()); - playerBackup.createCache(player, playerData); - } - sched.scheduleSyncDelayedTask(plugin, new ProcessSyncronousPlayerLogout(p, plugin)); - } -} +package fr.xephi.authme.process.logout; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitScheduler; + +import fr.xephi.authme.AuthMe; +import fr.xephi.authme.Utils; +import fr.xephi.authme.Utils.GroupType; +import fr.xephi.authme.cache.auth.PlayerAuth; +import fr.xephi.authme.cache.auth.PlayerCache; +import fr.xephi.authme.cache.limbo.LimboCache; +import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.events.AuthMeTeleportEvent; +import fr.xephi.authme.settings.Messages; +import fr.xephi.authme.settings.Settings; + +public class AsyncronousLogout { + + protected Player player; + protected String name; + protected AuthMe plugin; + protected DataSource database; + protected boolean canLogout = true; + private Messages m = Messages.getInstance(); + + public AsyncronousLogout(Player player, AuthMe plugin, + DataSource database) { + this.player = player; + this.plugin = plugin; + this.database = database; + this.name = player.getName().toLowerCase(); + } + + private void preLogout() { + if (!PlayerCache.getInstance().isAuthenticated(name)) { + m.send(player, "not_logged_in"); + canLogout = false; + } + } + + public void process() { + preLogout(); + if (!canLogout) + return; + final Player p = player; + BukkitScheduler sched = p.getServer().getScheduler(); + PlayerAuth auth = PlayerCache.getInstance().getAuth(name); + database.updateSession(auth); + auth.setQuitLocX(p.getLocation().getX()); + auth.setQuitLocY(p.getLocation().getY()); + auth.setQuitLocZ(p.getLocation().getZ()); + auth.setWorld(p.getWorld().getName()); + database.updateQuitLoc(auth); + + PlayerCache.getInstance().removePlayer(name); + database.setUnlogged(name); + if (Settings.isTeleportToSpawnEnabled && !Settings.noTeleport) { + Location spawnLoc = plugin.getSpawnLocation(p); + final AuthMeTeleportEvent tpEvent = new AuthMeTeleportEvent(p, spawnLoc); + sched.scheduleSyncDelayedTask(plugin, new Runnable() { + + @Override + public void run() { + plugin.getServer().getPluginManager().callEvent(tpEvent); + if (!tpEvent.isCancelled()) { + if (tpEvent.getTo() != null) + p.teleport(tpEvent.getTo()); + } + } + }); + } + + if (LimboCache.getInstance().hasLimboPlayer(name)) + LimboCache.getInstance().deleteLimboPlayer(name); + LimboCache.getInstance().addLimboPlayer(player); + Utils.setGroup(player, GroupType.NOTLOGGEDIN); + + sched.scheduleSyncDelayedTask(plugin, new ProcessSyncronousPlayerLogout(p, plugin)); + } +} diff --git a/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java b/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java index da594606b..26917e634 100644 --- a/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java +++ b/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java @@ -1,110 +1,93 @@ -package fr.xephi.authme.process.quit; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitTask; - -import fr.xephi.authme.AuthMe; -import fr.xephi.authme.Utils; -import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.cache.limbo.LimboCache; -import fr.xephi.authme.cache.limbo.LimboPlayer; -import fr.xephi.authme.datasource.DataSource; -import fr.xephi.authme.events.RestoreInventoryEvent; -import fr.xephi.authme.listener.AuthMePlayerListener; -import fr.xephi.authme.settings.Settings; - -public class AsyncronousQuit { - - protected AuthMe plugin; - protected DataSource database; - protected Player player; - private String name; - private ItemStack[] armor = null; - private ItemStack[] inv = null; - private boolean isOp = false; - private boolean isFlying = false; - private boolean needToChange = false; - private boolean isKick = false; - - public AsyncronousQuit(Player p, AuthMe plugin, DataSource database, - boolean isKick) { - this.player = p; - this.plugin = plugin; - this.database = database; - this.name = p.getName().toLowerCase(); - this.isKick = isKick; - } - - public void process() { - if (player == null) - return; - if (Utils.isNPC(player) || Utils.isUnrestricted(player)) { - return; - } - - String ip = plugin.getIP(player); - - if (PlayerCache.getInstance().isAuthenticated(name)) { - if (Settings.isSaveQuitLocationEnabled && database.isAuthAvailable(name)) { - Location loc = player.getLocation(); - PlayerAuth auth = new PlayerAuth(name, loc.getX(), loc.getY(), loc.getZ(), loc.getWorld().getName(), player.getName()); - database.updateQuitLoc(auth); - } - PlayerAuth auth = new PlayerAuth(name, ip, System.currentTimeMillis(), player.getName()); - database.updateSession(auth); - } - - if (LimboCache.getInstance().hasLimboPlayer(name)) { - LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name); - if (Settings.protectInventoryBeforeLogInEnabled && player.hasPlayedBefore()) { - inv = limbo.getInventory(); - armor = limbo.getArmour(); - } - if (limbo.getGroup() != null && !limbo.getGroup().equals("")) - Utils.addNormal(player, limbo.getGroup()); - needToChange = true; - isOp = limbo.getOperator(); - isFlying = limbo.isFlying(); - if (limbo.getTimeoutTaskId() != null) - limbo.getTimeoutTaskId().cancel(); - if (limbo.getMessageTaskId() != null) - limbo.getMessageTaskId().cancel(); - LimboCache.getInstance().deleteLimboPlayer(name); - } - if (Settings.isSessionsEnabled && !isKick) { - if (Settings.getSessionTimeout != 0) { - BukkitTask task = plugin.getServer().getScheduler().runTaskLaterAsynchronously(plugin, new Runnable() { - - @Override - public void run() { - PlayerCache.getInstance().removePlayer(name); - if (database.isLogged(name)) - database.setUnlogged(name); - plugin.sessions.remove(name); - } - - }, Settings.getSessionTimeout * 20 * 60); - plugin.sessions.put(name, task); - } - } else { - PlayerCache.getInstance().removePlayer(name); - database.setUnlogged(name); - } - AuthMePlayerListener.gameMode.remove(name); - final Player p = player; - RestoreInventoryEvent ev = new RestoreInventoryEvent(player, inv, armor, true); - Bukkit.getPluginManager().callEvent(ev); - if (ev.isCancelled()) { - inv = null; - armor = null; - } else { - inv = ev.getInventory(); - armor = ev.getArmor(); - } - Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new ProcessSyncronousPlayerQuit(plugin, p, inv, armor, isOp, isFlying, needToChange)); - } -} +package fr.xephi.authme.process.quit; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; + +import fr.xephi.authme.AuthMe; +import fr.xephi.authme.Utils; +import fr.xephi.authme.cache.auth.PlayerAuth; +import fr.xephi.authme.cache.auth.PlayerCache; +import fr.xephi.authme.cache.limbo.LimboCache; +import fr.xephi.authme.cache.limbo.LimboPlayer; +import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.listener.AuthMePlayerListener; +import fr.xephi.authme.settings.Settings; + +public class AsyncronousQuit { + + protected AuthMe plugin; + protected DataSource database; + protected Player player; + private String name; + private boolean isOp = false; + private boolean isFlying = false; + private boolean needToChange = false; + private boolean isKick = false; + + public AsyncronousQuit(Player p, AuthMe plugin, DataSource database, + boolean isKick) { + this.player = p; + this.plugin = plugin; + this.database = database; + this.name = p.getName().toLowerCase(); + this.isKick = isKick; + } + + public void process() { + if (player == null) + return; + if (Utils.isNPC(player) || Utils.isUnrestricted(player)) { + return; + } + + String ip = plugin.getIP(player); + + if (PlayerCache.getInstance().isAuthenticated(name)) { + if (Settings.isSaveQuitLocationEnabled && database.isAuthAvailable(name)) { + Location loc = player.getLocation(); + PlayerAuth auth = new PlayerAuth(name, loc.getX(), loc.getY(), loc.getZ(), loc.getWorld().getName(), player.getName()); + database.updateQuitLoc(auth); + } + PlayerAuth auth = new PlayerAuth(name, ip, System.currentTimeMillis(), player.getName()); + database.updateSession(auth); + } + + if (LimboCache.getInstance().hasLimboPlayer(name)) { + LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name); + if (limbo.getGroup() != null && !limbo.getGroup().equals("")) + Utils.addNormal(player, limbo.getGroup()); + needToChange = true; + isOp = limbo.getOperator(); + isFlying = limbo.isFlying(); + if (limbo.getTimeoutTaskId() != null) + limbo.getTimeoutTaskId().cancel(); + if (limbo.getMessageTaskId() != null) + limbo.getMessageTaskId().cancel(); + LimboCache.getInstance().deleteLimboPlayer(name); + } + if (Settings.isSessionsEnabled && !isKick) { + if (Settings.getSessionTimeout != 0) { + BukkitTask task = plugin.getServer().getScheduler().runTaskLaterAsynchronously(plugin, new Runnable() { + + @Override + public void run() { + PlayerCache.getInstance().removePlayer(name); + if (database.isLogged(name)) + database.setUnlogged(name); + plugin.sessions.remove(name); + } + + }, Settings.getSessionTimeout * 20 * 60); + plugin.sessions.put(name, task); + } + } else { + PlayerCache.getInstance().removePlayer(name); + database.setUnlogged(name); + } + + AuthMePlayerListener.gameMode.remove(name); + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new ProcessSyncronousPlayerQuit(plugin, player, isOp, isFlying, needToChange)); + } +} diff --git a/src/main/java/fr/xephi/authme/process/quit/ProcessSyncronousPlayerQuit.java b/src/main/java/fr/xephi/authme/process/quit/ProcessSyncronousPlayerQuit.java index 488134099..ea644270c 100644 --- a/src/main/java/fr/xephi/authme/process/quit/ProcessSyncronousPlayerQuit.java +++ b/src/main/java/fr/xephi/authme/process/quit/ProcessSyncronousPlayerQuit.java @@ -1,48 +1,49 @@ -package fr.xephi.authme.process.quit; - -import org.bukkit.GameMode; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import fr.xephi.authme.AuthMe; -import fr.xephi.authme.settings.Settings; - -public class ProcessSyncronousPlayerQuit implements Runnable { - - protected AuthMe plugin; - protected Player player; - protected boolean isOp; - protected boolean isFlying; - protected ItemStack[] inv; - protected ItemStack[] armor; - protected boolean needToChange; - - public ProcessSyncronousPlayerQuit(AuthMe plugin, Player player, - ItemStack[] inv, ItemStack[] armor, boolean isOp, boolean isFlying, - boolean needToChange) { - this.plugin = plugin; - this.player = player; - this.isOp = isOp; - this.isFlying = isFlying; - this.armor = armor; - this.inv = inv; - this.needToChange = needToChange; - } - - @Override - public void run() { - if (inv != null && armor != null) - plugin.api.setPlayerInventory(player, inv, armor); - if (needToChange) { - player.setOp(isOp); - if (player.getGameMode() != GameMode.CREATIVE && !Settings.isMovementAllowed) { - player.setAllowFlight(isFlying); - player.setFlying(isFlying); - } - } - try { - player.getVehicle().eject(); - } catch (Exception e) { - } - } -} +package fr.xephi.authme.process.quit; + +import org.bukkit.GameMode; +import org.bukkit.entity.Player; + +import fr.xephi.authme.AuthMe; +import fr.xephi.authme.events.RestoreInventoryEvent; +import fr.xephi.authme.settings.Settings; +import org.bukkit.Bukkit; + +public class ProcessSyncronousPlayerQuit implements Runnable { + + protected AuthMe plugin; + protected Player player; + protected boolean isOp; + protected boolean isFlying; + protected boolean needToChange; + + public ProcessSyncronousPlayerQuit(AuthMe plugin, Player player + , boolean isOp, boolean isFlying + , boolean needToChange) { + this.plugin = plugin; + this.player = player; + this.isOp = isOp; + this.isFlying = isFlying; + this.needToChange = needToChange; + } + + @Override + public void run() { + RestoreInventoryEvent ev = new RestoreInventoryEvent(player); + Bukkit.getPluginManager().callEvent(ev); + if (!ev.isCancelled()) { + plugin.api.setPlayerInventory(player, ev.getInventory(), ev.getArmor()); + } + + if (needToChange) { + player.setOp(isOp); + if (player.getGameMode() != GameMode.CREATIVE && !Settings.isMovementAllowed) { + player.setAllowFlight(isFlying); + player.setFlying(isFlying); + } + } + try { + player.getVehicle().eject(); + } catch (Exception e) { + } + } +} diff --git a/src/main/java/fr/xephi/authme/process/register/ProcessSyncronousPasswordRegister.java b/src/main/java/fr/xephi/authme/process/register/ProcessSyncronousPasswordRegister.java index 5a7a13532..ab0612d53 100644 --- a/src/main/java/fr/xephi/authme/process/register/ProcessSyncronousPasswordRegister.java +++ b/src/main/java/fr/xephi/authme/process/register/ProcessSyncronousPasswordRegister.java @@ -91,14 +91,17 @@ public class ProcessSyncronousPasswordRegister implements Runnable { player.teleport(tpEvent.getTo()); } } - if (Settings.protectInventoryBeforeLogInEnabled && limbo.getInventory() != null && limbo.getArmour() != null) { - RestoreInventoryEvent event = new RestoreInventoryEvent(player, limbo.getInventory(), limbo.getArmour()); + + if (Settings.protectInventoryBeforeLogInEnabled && plugin.inventoryProtector != null) { + RestoreInventoryEvent event = new RestoreInventoryEvent(player); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled() && event.getArmor() != null && event.getInventory() != null) { player.getInventory().setContents(event.getInventory()); player.getInventory().setArmorContents(event.getArmor()); + plugin.inventoryProtector.sendInventoryPacket(player); } } + limbo.getTimeoutTaskId().cancel(); limbo.getMessageTaskId().cancel(); LimboCache.getInstance().deleteLimboPlayer(name); @@ -153,6 +156,5 @@ public class ProcessSyncronousPasswordRegister implements Runnable { // Register is now finish , we can force all commands forceCommands(); - } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 6b2e6174a..276773ca5 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -4,7 +4,7 @@ website: http://dev.bukkit.org/bukkit-plugins/authme-reloaded/ description: AuthMe prevents people, which aren't logged in, from doing stuff like placing blocks, moving, typing commands or seeing the inventory of the player. main: fr.xephi.authme.AuthMe version: ${project.version} -softdepend: [Vault, ChestShop, Multiverse-Core, Citizens, CombatTag, Essentials, EssentialsSpawn, PerWorldInventories] +softdepend: [Vault, ChestShop, Multiverse-Core, Citizens, CombatTag, Essentials, EssentialsSpawn, PerWorldInventories, ProtocolLib] commands: register: description: Register an account @@ -22,7 +22,7 @@ commands: usage: /logout unregister: description: unregister your account - usage: /unregister password + usage: /unregister password authme: description: AuthMe op commands usage: '/authme reload|register playername password|changepassword playername password|unregister playername|version'