Share the same force login mangement for less duplicate code

This commit is contained in:
games647
2016-09-22 10:56:31 +02:00
parent 91f41c55de
commit bebb04bdea
23 changed files with 475 additions and 444 deletions

View File

@ -1,72 +0,0 @@
package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
import com.google.common.base.Charsets;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.io.File;
import java.io.InputStreamReader;
import java.util.List;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Logger;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
public class BukkitCore extends FastLoginCore<Player> {
private final FastLoginBukkit plugin;
public BukkitCore(FastLoginBukkit plugin) {
super(plugin.getConfig().getValues(false));
this.plugin = plugin;
}
@Override
public File getDataFolder() {
return plugin.getDataFolder();
}
@Override
public Logger getLogger() {
return plugin.getLogger();
}
@Override
public ThreadFactory getThreadFactory() {
String pluginName = plugin.getName();
return new ThreadFactoryBuilder()
.setNameFormat(pluginName + " Database Pool Thread #%1$d")
//Hikari create daemons by default
.setDaemon(true)
.build();
}
@Override
public void loadMessages() {
plugin.saveResource("messages.yml", false);
File messageFile = new File(plugin.getDataFolder(), "messages.yml");
YamlConfiguration messageConfig = YamlConfiguration.loadConfiguration(messageFile);
InputStreamReader defaultReader = new InputStreamReader(plugin.getResource("messages.yml"), Charsets.UTF_8);
YamlConfiguration defaults = YamlConfiguration.loadConfiguration(defaultReader);
messageConfig.setDefaults(defaults);
messageConfig.getKeys(false).forEach((key) -> {
String message = ChatColor.translateAlternateColorCodes('&', messageConfig.getString(key));
if (!message.isEmpty()) {
localeMessages.put(key, message);
}
});
}
@Override
public MojangApiConnector makeApiConnector(Logger logger, List<String> addresses, int requests) {
return new MojangApiBukkit(logger, addresses, requests);
}
}

View File

@ -14,22 +14,32 @@ import com.github.games647.fastlogin.bukkit.listener.protocollib.StartPacketList
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
import com.github.games647.fastlogin.bukkit.tasks.DelayedAuthHook;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import com.google.common.collect.Iterables;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import java.io.Reader;
import java.security.KeyPair;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
/**
* This plugin checks if a player has a paid account and if so tries to skip offline mode authentication.
*/
public class FastLoginBukkit extends JavaPlugin {
public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<CommandSender> {
private static final int WORKER_THREADS = 3;
@ -37,7 +47,7 @@ public class FastLoginBukkit extends JavaPlugin {
private final KeyPair keyPair = EncryptionUtil.generateKeyPair();
private boolean bungeeCord;
private BukkitCore core;
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
private boolean serverStarted;
//1 minutes should be enough as a timeout for bad internet connection (Server, Client and Mojang)
@ -45,11 +55,8 @@ public class FastLoginBukkit extends JavaPlugin {
@Override
public void onEnable() {
saveDefaultConfig();
core = new BukkitCore(this);
core.loadMessages();
core.setApiConnector();
core = new FastLoginCore<>(this);
core.load();
try {
if (ClassUtil.isPresent("org.spigotmc.SpigotConfig")) {
bungeeCord = Class.forName("org.spigotmc.SpigotConfig").getDeclaredField("bungee").getBoolean(null);
@ -119,7 +126,7 @@ public class FastLoginBukkit extends JavaPlugin {
getServer().getOnlinePlayers().forEach(player -> player.removeMetadata(getName(), this));
}
public BukkitCore getCore() {
public FastLoginCore<Player, CommandSender, FastLoginBukkit> getCore() {
return core;
}
@ -187,4 +194,31 @@ public class FastLoginBukkit extends JavaPlugin {
dataOutput.writeUTF(target);
sender.sendPluginMessage(this, getName(), dataOutput.toByteArray());
}
@Override
public Map<String, Object> loadYamlFile(Reader reader) {
YamlConfiguration config = YamlConfiguration.loadConfiguration(reader);
return config.getValues(false);
}
@Override
public void sendMessage(CommandSender receiver, String message) {
receiver.sendMessage(message);
}
@Override
public String translateColorCodes(char colorChar, String rawMessage) {
return ChatColor.translateAlternateColorCodes(colorChar, rawMessage);
}
@Override
public ThreadFactory getThreadFactory() {
//not required here to make a custom thread factory
return null;
}
@Override
public MojangApiConnector makeApiConnector(Logger logger, List<String> addresses, int requests) {
return new MojangApiBukkit(logger, addresses, requests);
}
}

View File

@ -28,15 +28,12 @@ public class CrackedCommand implements CommandExecutor {
if (plugin.isBungeeCord()) {
plugin.sendBungeeActivateMessage(sender, sender.getName(), false);
String message = plugin.getCore().getMessage("wait-on-proxy");
if (message != null) {
sender.sendMessage(message);
}
plugin.getCore().sendLocaleMessage("wait-on-proxy", sender);
} else {
//todo: load async if
PlayerProfile profile = plugin.getCore().getStorage().loadProfile(sender.getName());
if (profile.isPremium()) {
sender.sendMessage(plugin.getCore().getMessage("remove-premium"));
plugin.getCore().sendLocaleMessage("remove-premium", sender);
profile.setPremium(false);
profile.setUuid(null);
@ -44,7 +41,7 @@ public class CrackedCommand implements CommandExecutor {
plugin.getCore().getStorage().save(profile);
});
} else {
sender.sendMessage(plugin.getCore().getMessage("not-premium"));
plugin.getCore().sendLocaleMessage("not-premium", sender);
}
}
@ -58,16 +55,13 @@ public class CrackedCommand implements CommandExecutor {
private void onCrackedOther(CommandSender sender, Command command, String[] args) {
if (!sender.hasPermission(command.getPermission() + ".other")) {
sender.sendMessage(plugin.getCore().getMessage("no-permission"));
plugin.getCore().sendLocaleMessage("no-permission", sender);
return;
}
if (plugin.isBungeeCord()) {
plugin.sendBungeeActivateMessage(sender, args[0], false);
String message = plugin.getCore().getMessage("wait-on-proxy");
if (message != null) {
sender.sendMessage(message);
}
plugin.getCore().sendLocaleMessage("wait-on-proxy", sender);
} else {
//todo: load async
PlayerProfile profile = plugin.getCore().getStorage().loadProfile(args[0]);
@ -78,9 +72,10 @@ public class CrackedCommand implements CommandExecutor {
//existing player is already cracked
if (profile.getUserId() != -1 && !profile.isPremium()) {
sender.sendMessage(plugin.getCore().getMessage("not-premium-other"));
plugin.getCore().sendLocaleMessage("not-premium-other", sender);
} else {
sender.sendMessage(plugin.getCore().getMessage("remove-premium"));
plugin.getCore().sendLocaleMessage("remove-premium", sender);
profile.setPremium(false);
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
plugin.getCore().getStorage().save(profile);

View File

@ -1,19 +1,21 @@
package com.github.games647.fastlogin.bukkit.commands;
import com.github.games647.fastlogin.bukkit.BukkitCore;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.AuthStorage;
import com.github.games647.fastlogin.core.importer.ImportPlugin;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class ImportCommand implements CommandExecutor {
private final BukkitCore core;
private final FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
public ImportCommand(BukkitCore core) {
public ImportCommand(FastLoginCore<Player, CommandSender, FastLoginBukkit> core) {
this.core = core;
}

View File

@ -29,16 +29,13 @@ public class PremiumCommand implements CommandExecutor {
if (args.length == 0) {
if (!(sender instanceof Player)) {
//console or command block
sender.sendMessage(plugin.getCore().getMessage("no-console"));
plugin.getCore().sendLocaleMessage("no-console", sender);
return true;
}
if (plugin.isBungeeCord()) {
plugin.sendBungeeActivateMessage(sender, sender.getName(), true);
String message = plugin.getCore().getMessage("wait-on-proxy");
if (message != null) {
sender.sendMessage(message);
}
plugin.getCore().sendLocaleMessage("wait-on-proxy", sender);
} else {
UUID id = ((Player) sender).getUniqueId();
if (plugin.getConfig().getBoolean("premium-warning")
@ -52,7 +49,7 @@ public class PremiumCommand implements CommandExecutor {
//todo: load async
PlayerProfile profile = plugin.getCore().getStorage().loadProfile(sender.getName());
if (profile.isPremium()) {
sender.sendMessage(plugin.getCore().getMessage("already-exists"));
plugin.getCore().sendLocaleMessage("already-exists", sender);
} else {
//todo: resolve uuid
profile.setPremium(true);
@ -60,7 +57,7 @@ public class PremiumCommand implements CommandExecutor {
plugin.getCore().getStorage().save(profile);
});
sender.sendMessage(plugin.getCore().getMessage("add-premium"));
plugin.getCore().sendLocaleMessage("add-premium", sender);
}
}
@ -74,26 +71,23 @@ public class PremiumCommand implements CommandExecutor {
private void onPremiumOther(CommandSender sender, Command command, String[] args) {
if (!sender.hasPermission(command.getPermission() + ".other")) {
sender.sendMessage(plugin.getCore().getMessage("no-permission"));
plugin.getCore().sendLocaleMessage("no-permission", sender);
return ;
}
if (plugin.isBungeeCord()) {
plugin.sendBungeeActivateMessage(sender, args[0], true);
String message = plugin.getCore().getMessage("wait-on-proxy");
if (message != null) {
sender.sendMessage(message);
}
plugin.getCore().sendLocaleMessage("wait-on-proxy", sender);
} else {
//todo: load async
PlayerProfile profile = plugin.getCore().getStorage().loadProfile(args[0]);
if (profile == null) {
sender.sendMessage(plugin.getCore().getMessage("player-unknown"));
plugin.getCore().sendLocaleMessage("player-unknown", sender);
return;
}
if (profile.isPremium()) {
sender.sendMessage(plugin.getCore().getMessage("already-exists-other"));
plugin.getCore().sendLocaleMessage("already-exists-other", sender);
} else {
//todo: resolve uuid
profile.setPremium(true);
@ -101,7 +95,7 @@ public class PremiumCommand implements CommandExecutor {
plugin.getCore().getStorage().save(profile);
});
sender.sendMessage(plugin.getCore().getMessage("add-premium-other"));
plugin.getCore().sendLocaleMessage("add-premium-other", sender);
}
}
}

View File

@ -40,7 +40,8 @@ public class BukkitJoinListener implements Listener {
if (!plugin.isBungeeCord()) {
//Wait before auth plugin and we received a message from BungeeCord initializes the player
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, new ForceLoginTask(plugin, player), DELAY_LOGIN);
ForceLoginTask forceLoginTask = new ForceLoginTask(plugin.getCore(), player);
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, forceLoginTask, DELAY_LOGIN);
}
}

View File

@ -81,7 +81,7 @@ public class BungeeCordListener implements PluginMessageListener {
BukkitLoginSession playerSession = new BukkitLoginSession(playerName, true);
playerSession.setVerified(true);
plugin.getSessions().put(id, playerSession);
Bukkit.getScheduler().runTaskAsynchronously(plugin, new ForceLoginTask(plugin, player));
Bukkit.getScheduler().runTaskAsynchronously(plugin, new ForceLoginTask(plugin.getCore(), player));
} else if ("AUTO_REGISTER".equalsIgnoreCase(subchannel)) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
AuthPlugin<Player> authPlugin = plugin.getCore().getAuthPluginHook();
@ -91,7 +91,7 @@ public class BungeeCordListener implements PluginMessageListener {
BukkitLoginSession playerSession = new BukkitLoginSession(playerName, false);
playerSession.setVerified(true);
plugin.getSessions().put(id, playerSession);
new ForceLoginTask(plugin, player).run();
new ForceLoginTask(plugin.getCore(), player).run();
}
} catch (Exception ex) {
plugin.getLogger().log(Level.SEVERE, "Failed to query isRegistered", ex);

View File

@ -9,10 +9,12 @@ import com.github.games647.fastlogin.core.shared.JoinManagement;
import java.util.Random;
import java.util.logging.Level;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class NameCheckTask extends JoinManagement<Player, ProtocolLibLoginSource> implements Runnable {
public class NameCheckTask extends JoinManagement<Player, CommandSender, ProtocolLibLoginSource>
implements Runnable {
private final FastLoginBukkit plugin;
private final PacketEvent packetEvent;

View File

@ -51,9 +51,6 @@ public class VerifyResponseTask implements Runnable {
disconnect(plugin.getCore().getMessage("invalid-requst"), true
, "Player {0} tried to send encryption response at invalid state", fromPlayer.getAddress());
} else {
String ip = fromPlayer.getAddress().getAddress().getHostAddress();
plugin.getCore().getPendingLogins().remove(ip + session.getUsername());
verifyResponse(session);
}
} finally {

View File

@ -2,11 +2,12 @@ package com.github.games647.fastlogin.bukkit.listener.protocolsupport;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.shared.JoinManagement;
import com.github.games647.fastlogin.core.PlayerProfile;
import com.github.games647.fastlogin.core.shared.JoinManagement;
import java.net.InetSocketAddress;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -14,7 +15,8 @@ import org.bukkit.event.Listener;
import protocolsupport.api.events.PlayerLoginStartEvent;
import protocolsupport.api.events.PlayerPropertiesResolveEvent;
public class ProtocolSupportListener extends JoinManagement<Player, ProtocolLoginSource> implements Listener {
public class ProtocolSupportListener extends JoinManagement<Player, CommandSender, ProtocolLoginSource>
implements Listener {
private final FastLoginBukkit plugin;
@ -26,7 +28,6 @@ public class ProtocolSupportListener extends JoinManagement<Player, ProtocolLogi
@EventHandler
public void onLoginStart(PlayerLoginStartEvent loginStartEvent) {
plugin.setServerStarted();
if (loginStartEvent.isLoginDenied() || plugin.getCore().getAuthPluginHook() == null) {
return;
}
@ -47,9 +48,6 @@ public class ProtocolSupportListener extends JoinManagement<Player, ProtocolLogi
//skin was resolved -> premium player
if (propertiesResolveEvent.hasProperty("textures") && session != null) {
String ip = address.getAddress().getHostAddress();
plugin.getCore().getPendingLogins().remove(ip + session.getUsername());
session.setVerified(true);
}
}

View File

@ -2,9 +2,9 @@ package com.github.games647.fastlogin.bukkit.tasks;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.AuthStorage;
import com.github.games647.fastlogin.core.PlayerProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.ForceLoginMangement;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
@ -12,119 +12,52 @@ import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class ForceLoginTask implements Runnable {
public class ForceLoginTask extends ForceLoginMangement<Player, CommandSender, BukkitLoginSession, FastLoginBukkit> {
private final FastLoginBukkit plugin;
private final Player player;
public ForceLoginTask(FastLoginBukkit plugin, Player player) {
this.plugin = plugin;
this.player = player;
public ForceLoginTask(FastLoginCore<Player, CommandSender, FastLoginBukkit> core, Player player) {
super(core, player);
}
@Override
public void run() {
if (!isOnlineThreadSafe()) {
return;
}
//remove the bungeecord identifier if there is ones
String id = '/' + player.getAddress().getAddress().getHostAddress() + ':' + player.getAddress().getPort();
BukkitLoginSession session = plugin.getSessions().remove(id);
if (session == null) {
return;
}
session = core.getPlugin().getSessions().remove(id);
AuthStorage storage = plugin.getCore().getStorage();
PlayerProfile playerProfile = session.getProfile();
//check if it's the same player as we checked before
if (session.isVerified() && player.getName().equals(session.getUsername())) {
//premium player
AuthPlugin<Player> authPlugin = plugin.getCore().getAuthPluginHook();
if (authPlugin == null) {
//maybe only bungeecord plugin
sendSuccessNotification();
} else {
boolean success = false;
if (isOnlineThreadSafe()) {
if (plugin.getConfig().getBoolean("autoLogin")) {
if (session.needsRegistration()) {
success = forceRegister(authPlugin, player);
} else {
success = forceLogin(authPlugin, player);
}
} else {
success = true;
}
}
if (success) {
//update only on success to prevent corrupt data
if (playerProfile != null) {
playerProfile.setUuid(session.getUuid());
//save cracked players too
playerProfile.setPremium(true);
storage.save(playerProfile);
}
sendSuccessNotification();
}
}
} else {
//cracked player
if (playerProfile != null) {
playerProfile.setUuid(null);
playerProfile.setPremium(false);
storage.save(playerProfile);
}
}
super.run();
}
private boolean forceRegister(AuthPlugin<Player> authPlugin, Player player) {
plugin.getLogger().log(Level.FINE, "Register player {0}", player.getName());
String generatedPassword = plugin.getCore().getPasswordGenerator().getRandomPassword(player);
boolean success = authPlugin.forceRegister(player, generatedPassword);
String message = plugin.getCore().getMessage("auto-register");
if (success && message != null) {
message = message.replace("%password", generatedPassword);
player.sendMessage(message);
}
return success;
}
private boolean forceLogin(AuthPlugin<Player> authPlugin, Player player) {
plugin.getLogger().log(Level.FINE, "Logging player {0} in", player.getName());
boolean success = authPlugin.forceLogin(player);
String message = plugin.getCore().getMessage("auto-login");
if (success && message != null) {
player.sendMessage(message);
}
return success;
}
private void sendSuccessNotification() {
if (plugin.isBungeeCord()) {
@Override
public void onForceActionSuccess(LoginSession session) {
if (core.getPlugin().isBungeeCord()) {
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
dataOutput.writeUTF("SUCCESS");
player.sendPluginMessage(plugin, plugin.getName(), dataOutput.toByteArray());
player.sendPluginMessage(core.getPlugin(), core.getPlugin().getName(), dataOutput.toByteArray());
}
}
private boolean isOnlineThreadSafe() {
@Override
public String getName(Player player) {
return player.getName();
}
@Override
public boolean isOnline(Player player) {
try {
//the playerlist isn't thread-safe
return Bukkit.getScheduler().callSyncMethod(plugin, player::isOnline).get();
return Bukkit.getScheduler().callSyncMethod(core.getPlugin(), player::isOnline).get();
} catch (InterruptedException | ExecutionException ex) {
plugin.getLogger().log(Level.SEVERE, "Failed to perform thread-safe online check", ex);
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to perform thread-safe online check", ex);
return false;
}
}
@Override
public boolean isOnlineMode() {
return session.isVerified() && player.getName().equals(session.getUsername());
}
}

View File

@ -1,87 +0,0 @@
package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
public class BungeeCore extends FastLoginCore<ProxiedPlayer> {
private static Map<String, Object> generateConfigMap(Configuration config) {
return config.getKeys().stream()
.filter(key -> config.get(key) != null)
.collect(Collectors.toMap(key -> key, config::get));
}
private final FastLoginBungee plugin;
public BungeeCore(FastLoginBungee plugin, Configuration config) {
super(generateConfigMap(config));
this.plugin = plugin;
}
@Override
public File getDataFolder() {
return plugin.getDataFolder();
}
@Override
public Logger getLogger() {
return plugin.getLogger();
}
@Override
@SuppressWarnings("deprecation")
public ThreadFactory getThreadFactory() {
String pluginName = plugin.getDescription().getName();
return new ThreadFactoryBuilder()
.setNameFormat(pluginName + " Database Pool Thread #%1$d")
//Hikari create daemons by default
.setDaemon(true)
.setThreadFactory(new GroupedThreadFactory(plugin, pluginName))
.build();
}
@Override
public void loadMessages() {
try {
plugin.saveDefaultFile("messages.yml");
ConfigurationProvider configProvider = ConfigurationProvider.getProvider(YamlConfiguration.class);
Configuration defaults = configProvider.load(getClass().getResourceAsStream("/messages.yml"));
File messageFile = new File(getDataFolder(), "messages.yml");
Configuration messageConfig = configProvider.load(messageFile, defaults);
messageConfig.getKeys().forEach(key -> {
String message = ChatColor.translateAlternateColorCodes('&', messageConfig.getString(key));
if (!message.isEmpty()) {
localeMessages.put(key, message);
}
});
} catch (IOException ex) {
getLogger().log(Level.SEVERE, "Failed to load messages", ex);
}
}
@Override
public MojangApiConnector makeApiConnector(Logger logger, List<String> addresses, int requests) {
return new MojangApiBungee(logger, addresses, requests);
}
}

View File

@ -3,17 +3,31 @@ package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthHook;
import com.github.games647.fastlogin.bungee.listener.PlayerConnectionListener;
import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import com.google.common.collect.Maps;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
@ -21,24 +35,23 @@ import net.md_5.bungee.config.YamlConfiguration;
/**
* BungeeCord version of FastLogin. This plugin keeps track on online mode connections.
*/
public class FastLoginBungee extends Plugin {
public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSender> {
private final ConcurrentMap<PendingConnection, BungeeLoginSession> session = Maps.newConcurrentMap();
private BungeeCore core;
private FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core;
private Configuration config;
@Override
public void onEnable() {
saveDefaultFile("config.yml");
try {
File configFile = new File(getDataFolder(), "config.yml");
ConfigurationProvider provider = ConfigurationProvider.getProvider(YamlConfiguration.class);
Configuration defaults = provider.load(getResourceAsStream("config.yml"));
config = provider.load(configFile, defaults);
core = new BungeeCore(this, config);
core = new FastLoginCore<>(this);
core.load();
if (!core.setupDatabase()) {
return;
}
@ -47,9 +60,6 @@ public class FastLoginBungee extends Plugin {
return;
}
core.setApiConnector();
core.loadMessages();
//events
getProxy().getPluginManager().registerListener(this, new PlayerConnectionListener(this));
getProxy().getPluginManager().registerListener(this, new PluginMessageListener(this));
@ -92,7 +102,7 @@ public class FastLoginBungee extends Plugin {
}
}
public BungeeCore getCore() {
public FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> getCore() {
return core;
}
@ -111,4 +121,39 @@ public class FastLoginBungee extends Plugin {
getLogger().info("Hooked into BungeeAuth");
}
}
@Override
public String getName() {
return getDescription().getName();
}
@Override
public Map<String, Object> loadYamlFile(Reader reader) {
ConfigurationProvider configProvider = ConfigurationProvider.getProvider(YamlConfiguration.class);
Configuration config = configProvider.load(reader);
return config.getKeys().stream()
.filter(key -> config.get(key) != null)
.collect(Collectors.toMap(key -> key, config::get));
}
@Override
public void sendMessage(CommandSender receiver, String message) {
receiver.sendMessage(TextComponent.fromLegacyText(message));
}
@Override
public String translateColorCodes(char colorChar, String rawMessage) {
return ChatColor.translateAlternateColorCodes(colorChar, rawMessage);
}
@Override
@SuppressWarnings("deprecation")
public ThreadFactory getThreadFactory() {
return new GroupedThreadFactory(this, getName());
}
@Override
public MojangApiConnector makeApiConnector(Logger logger, List<String> addresses, int requests) {
return new MojangApiBungee(logger, addresses, requests);
}
}

View File

@ -2,16 +2,18 @@ package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.core.AuthStorage;
import com.github.games647.fastlogin.core.importer.ImportPlugin;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
public class ImportCommand extends Command {
private final BungeeCore core;
private final FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core;
public ImportCommand(FastLoginBungee plugin) {
super("import-db", plugin.getDescription().getName().toLowerCase() + ".import");

View File

@ -14,6 +14,7 @@ import java.util.logging.Level;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.event.LoginEvent;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PreLoginEvent;
@ -62,9 +63,6 @@ public class PlayerConnectionListener implements Listener {
PendingConnection connection = loginEvent.getConnection();
String username = connection.getName();
if (connection.isOnlineMode()) {
String ip = connection.getAddress().getAddress().getHostAddress();
plugin.getCore().getPendingLogins().remove(ip + username);
LoginSession session = plugin.getSession().get(connection);
session.setUuid(connection.getUniqueId());
@ -100,7 +98,9 @@ public class PlayerConnectionListener implements Listener {
@EventHandler
public void onServerConnected(ServerConnectedEvent serverConnectedEvent) {
ProxiedPlayer player = serverConnectedEvent.getPlayer();
ForceLoginTask loginTask = new ForceLoginTask(plugin, player, serverConnectedEvent.getServer());
Server server = serverConnectedEvent.getServer();
ForceLoginTask loginTask = new ForceLoginTask(plugin.getCore(), player, server);
ProxyServer.getInstance().getScheduler().runAsync(plugin, loginTask);
}

View File

@ -6,11 +6,13 @@ import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.core.PlayerProfile;
import com.github.games647.fastlogin.core.shared.JoinManagement;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.AsyncEvent;
public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, BungeeLoginSource> implements Runnable {
public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSender, BungeeLoginSource>
implements Runnable {
private final FastLoginBungee plugin;
private final AsyncEvent<?> preLoginEvent;

View File

@ -1,19 +1,22 @@
package com.github.games647.fastlogin.bungee.tasks;
import com.github.games647.fastlogin.bungee.BungeeCore;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.core.PlayerProfile;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class AsyncToggleMessage implements Runnable {
private final BungeeCore core;
private final FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core;
private final ProxiedPlayer fromPlayer;
private final String targetPlayer;
private final boolean toPremium;
public AsyncToggleMessage(BungeeCore core, ProxiedPlayer fromPlayer, String targetPlayer, boolean toPremium) {
public AsyncToggleMessage(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core
, ProxiedPlayer fromPlayer, String targetPlayer, boolean toPremium) {
this.core = core;
this.fromPlayer = fromPlayer;
this.targetPlayer = targetPlayer;

View File

@ -2,119 +2,66 @@ package com.github.games647.fastlogin.bungee.tasks;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.core.PlayerProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.ForceLoginMangement;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import java.util.UUID;
import java.util.logging.Level;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
public class ForceLoginTask implements Runnable {
public class ForceLoginTask extends ForceLoginMangement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> {
private final FastLoginBungee plugin;
private final ProxiedPlayer player;
private final Server server;
public ForceLoginTask(FastLoginBungee plugin, ProxiedPlayer player, Server server) {
this.plugin = plugin;
this.player = player;
public ForceLoginTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core
, ProxiedPlayer player, Server server) {
super(core, player);
this.server = server;
}
@Override
public void run() {
try {
PendingConnection pendingConnection = player.getPendingConnection();
BungeeLoginSession session = plugin.getSession().get(pendingConnection);
PendingConnection pendingConnection = player.getPendingConnection();
session = core.getPlugin().getSession().get(pendingConnection);
if (session == null || !player.isConnected()) {
plugin.getLogger().log(Level.FINE, "Invalid session player {0} propaly left the server", player);
return;
}
super.run();
PlayerProfile playerProfile = session.getProfile();
//force login only on success
if (pendingConnection.isOnlineMode()) {
boolean autoRegister = session.needsRegistration();
//2fa authentication - no need to send bukkit force login notification and so we also don't need
// to wait for a response -> save immediatly
if (!plugin.getConfig().getBoolean("autoLogin")) {
playerProfile.setPremium(true);
plugin.getCore().getStorage().save(playerProfile);
session.setAlreadySaved(true);
}
AuthPlugin<ProxiedPlayer> authPlugin = plugin.getCore().getAuthPluginHook();
if (authPlugin == null) {
//save will happen on success message from bukkit
sendBukkitLoginNotification(autoRegister);
} else if (session.needsRegistration()) {
forceRegister(session, authPlugin);
} else if (authPlugin.forceLogin(player)) {
forceLogin(session, authPlugin);
}
} else {
//cracked player
if (!session.isAlreadySaved()) {
playerProfile.setPremium(false);
plugin.getCore().getStorage().save(playerProfile);
session.setAlreadySaved(true);
}
}
} catch (Exception ex) {
plugin.getLogger().log(Level.INFO, "ERROR ON FORCE LOGIN", ex);
if (!isOnlineMode()) {
session.setAlreadySaved(true);
}
}
private void forceRegister(BungeeLoginSession session, AuthPlugin<ProxiedPlayer> authPlugin) {
@Override
public boolean forceLogin(ProxiedPlayer player) {
if (session.isAlreadyLogged()) {
sendBukkitLoginNotification(true);
return;
return true;
}
session.setAlreadyLogged(true);
String password = plugin.getCore().getPasswordGenerator().getRandomPassword(player);
if (authPlugin.forceRegister(player, password)) {
//save will happen on success message from bukkit
sendBukkitLoginNotification(true);
String message = plugin.getCore().getMessage("auto-register");
if (message != null) {
message = message.replace("%password", password);
player.sendMessage(TextComponent.fromLegacyText(message));
}
}
return super.forceLogin(player);
}
private void forceLogin(BungeeLoginSession session, AuthPlugin<ProxiedPlayer> authPlugin) {
@Override
public boolean forceRegister(ProxiedPlayer player) {
if (session.isAlreadyLogged()) {
sendBukkitLoginNotification(false);
return;
return true;
}
session.setAlreadyLogged(true);
if (authPlugin.forceLogin(player)) {
//save will happen on success message from bukkit
sendBukkitLoginNotification(false);
String message = plugin.getCore().getMessage("auto-login");
if (message != null) {
player.sendMessage(TextComponent.fromLegacyText(message));
}
}
return super.forceRegister(player);
}
private void sendBukkitLoginNotification(boolean autoRegister) {
@Override
public void onForceActionSuccess(LoginSession session) {
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
//subchannel name
if (autoRegister) {
if (session.needsRegistration()) {
dataOutput.writeUTF("AUTO_REGISTER");
} else {
dataOutput.writeUTF("AUTO_LOGIN");
@ -124,12 +71,27 @@ public class ForceLoginTask implements Runnable {
dataOutput.writeUTF(player.getName());
//proxy identifier to check if it's a acceptable proxy
UUID proxyId = UUID.fromString(plugin.getProxy().getConfig().getUuid());
UUID proxyId = UUID.fromString(core.getPlugin().getProxy().getConfig().getUuid());
dataOutput.writeLong(proxyId.getMostSignificantBits());
dataOutput.writeLong(proxyId.getLeastSignificantBits());
if (server != null) {
server.sendData(plugin.getDescription().getName(), dataOutput.toByteArray());
server.sendData(core.getPlugin().getName(), dataOutput.toByteArray());
}
}
@Override
public String getName(ProxiedPlayer player) {
return player.getName();
}
@Override
public boolean isOnline(ProxiedPlayer player) {
return !player.isConnected();
}
@Override
public boolean isOnlineMode() {
return player.getPendingConnection().isOnlineMode();
}
}

View File

@ -1,6 +1,7 @@
package com.github.games647.fastlogin.core;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
@ -12,19 +13,20 @@ import java.sql.Statement;
import java.util.Calendar;
import java.util.Locale;
import java.util.UUID;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Level;
public class AuthStorage {
private static final String PREMIUM_TABLE = "premium";
private final FastLoginCore<?> core;
private final FastLoginCore<?, ?, ?> core;
private final HikariDataSource dataSource;
//a try to fix https://www.spigotmc.org/threads/fastlogin.101192/page-26#post-1874647
private final Calendar calendar = Calendar.getInstance(Locale.US);
public AuthStorage(FastLoginCore<?> core, String driver, String host, int port, String databasePath
public AuthStorage(FastLoginCore<?, ?, ?> core, String driver, String host, int port, String databasePath
, String user, String pass) {
this.core = core;
@ -32,9 +34,20 @@ public class AuthStorage {
databaseConfig.setUsername(user);
databaseConfig.setPassword(pass);
databaseConfig.setDriverClassName(driver);
databaseConfig.setThreadFactory(core.getThreadFactory());
databasePath = databasePath.replace("{pluginDir}", core.getDataFolder().getAbsolutePath());
ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder()
.setNameFormat(core.getPlugin().getName() + " Database Pool Thread #%1$d")
//Hikari create daemons by default
.setDaemon(true);
ThreadFactory platformThreadFactory = core.getPlugin().getThreadFactory();
if (platformThreadFactory != null) {
threadFactoryBuilder.setThreadFactory(platformThreadFactory);
}
databaseConfig.setThreadFactory(threadFactoryBuilder.build());
databasePath = databasePath.replace("{pluginDir}", core.getPlugin().getDataFolder().getAbsolutePath());
String jdbcUrl = "jdbc:";
if (driver.contains("sqlite")) {
@ -134,7 +147,7 @@ public class AuthStorage {
return crackedProfile;
}
} catch (SQLException sqlEx) {
core.getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
} finally {
closeQuietly(con);
closeQuietly(loadStmt);
@ -165,7 +178,7 @@ public class AuthStorage {
return playerProfile;
}
} catch (SQLException sqlEx) {
core.getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
} finally {
closeQuietly(con);
closeQuietly(loadStmt);
@ -226,7 +239,7 @@ public class AuthStorage {
return true;
} catch (SQLException ex) {
core.getLogger().log(Level.SEVERE, "Failed to save playerProfile", ex);
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to save playerProfile", ex);
} finally {
closeQuietly(con);
closeQuietly(updateStmt);
@ -246,7 +259,7 @@ public class AuthStorage {
try {
closeable.close();
} catch (Exception closeEx) {
core.getLogger().log(Level.SEVERE, "Failed to close connection", closeEx);
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to close connection", closeEx);
}
}
}

View File

@ -12,25 +12,31 @@ import com.github.games647.fastlogin.core.importer.Importer;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.Sets;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @param <P> Player class
* @param <C> CommandSender
* @param <T> Plugin class
*/
public abstract class FastLoginCore<P> {
public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
public static <K, V> ConcurrentMap<K, V> buildCache(int expireAfterWrite, int maxSize) {
CompatibleCacheBuilder<Object, Object> builder = CompatibleCacheBuilder.newBuilder();
@ -64,21 +70,62 @@ public abstract class FastLoginCore<P> {
private final ConcurrentMap<String, Object> pendingLogins = FastLoginCore.buildCache(5, 0);
private final Set<UUID> pendingConfirms = Sets.newHashSet();
private final SharedConfig sharedConfig;
private final T plugin;
private SharedConfig sharedConfig;
private MojangApiConnector apiConnector;
private AuthStorage storage;
private PasswordGenerator<P> passwordGenerator = new DefaultPasswordGenerator<>();
private AuthPlugin<P> authPlugin;
public FastLoginCore(Map<String, Object> config) {
this.sharedConfig = new SharedConfig(config);
public FastLoginCore(T plugin) {
this.plugin = plugin;
}
public void setApiConnector() {
public void load() {
saveDefaultFile("messages.yml");
saveDefaultFile("config.yml");
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("config.yml")));
sharedConfig = new SharedConfig(plugin.loadYamlFile(reader));
reader.close();
reader = Files.newBufferedReader(new File(plugin.getDataFolder(), "config.yml").toPath());
sharedConfig.getConfigValues().putAll(plugin.loadYamlFile(reader));
reader.close();
reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("messages.yml")));
reader = Files.newBufferedReader(new File(plugin.getDataFolder(), "messages.yml").toPath());
Map<String, Object> messageConfig = plugin.loadYamlFile(reader);
reader.close();
reader = Files.newBufferedReader(new File(plugin.getDataFolder(), "messages.yml").toPath());
messageConfig.putAll(plugin.loadYamlFile(reader));
for (Entry<String, Object> entry : messageConfig.entrySet()) {
String message = plugin.translateColorCodes('&', (String) entry.getValue());
if (!message.isEmpty()) {
localeMessages.put(entry.getKey(), message);
}
}
reader.close();
} catch (IOException ioEx) {
plugin.getLogger().log(Level.INFO, "Failed to load yaml files", ioEx);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
plugin.getLogger().log(Level.SEVERE, null, ex);
}
}
}
List<String> ipAddresses = sharedConfig.get("ip-addresses");
int requestLimit = sharedConfig.get("mojang-request-limit");
this.apiConnector = makeApiConnector(getLogger(), ipAddresses, requestLimit);
this.apiConnector = plugin.makeApiConnector(plugin.getLogger(), ipAddresses, requestLimit);
}
public MojangApiConnector getApiConnector() {
@ -89,20 +136,21 @@ public abstract class FastLoginCore<P> {
return storage;
}
public abstract File getDataFolder();
public T getPlugin() {
return plugin;
}
public abstract Logger getLogger();
public abstract ThreadFactory getThreadFactory();
public void sendLocaleMessage(String key, C receiver) {
String message = localeMessages.get(key);
if (message != null) {
plugin.sendMessage(receiver, message);
}
}
public String getMessage(String key) {
return localeMessages.get(key);
}
public abstract void loadMessages();
public abstract MojangApiConnector makeApiConnector(Logger logger, List<String> addresses, int requests);
public boolean setupDatabase() {
String driver = sharedConfig.get("driver");
String host = sharedConfig.get("host", "");
@ -117,27 +165,27 @@ public abstract class FastLoginCore<P> {
storage.createTables();
return true;
} catch (Exception ex) {
getLogger().log(Level.SEVERE, "Failed to setup database. Disabling plugin...", ex);
plugin.getLogger().log(Level.SEVERE, "Failed to setup database. Disabling plugin...", ex);
return false;
}
}
public boolean importDatabase(ImportPlugin plugin, boolean sqlite, AuthStorage storage, String host, String database
public boolean importDatabase(ImportPlugin importPlugin, boolean sqlite, AuthStorage storage, String host, String database
, String username, String pass) {
if (sqlite && (plugin == ImportPlugin.BPA || plugin == ImportPlugin.ELDZI)) {
if (sqlite && (importPlugin == ImportPlugin.BPA || importPlugin == ImportPlugin.ELDZI)) {
throw new IllegalArgumentException("These plugins doesn't support flat file databases");
}
Importer importer;
try {
importer = plugin.getImporter().newInstance();
importer = importPlugin.getImporter().newInstance();
} catch (Exception ex) {
getLogger().log(Level.SEVERE, "Couldn't not setup importer class", ex);
plugin.getLogger().log(Level.SEVERE, "Couldn't not setup importer class", ex);
return false;
}
try {
if (sqlite && plugin == ImportPlugin.AUTO_IN) {
if (sqlite && importPlugin == ImportPlugin.AUTO_IN) {
//load sqlite driver
Class.forName("org.sqlite.JDBC");
@ -154,9 +202,9 @@ public abstract class FastLoginCore<P> {
return true;
}
} catch (ClassNotFoundException ex) {
getLogger().log(Level.SEVERE, "Cannot find SQL driver. Do you removed it?", ex);
plugin.getLogger().log(Level.SEVERE, "Cannot find SQL driver. Do you removed it?", ex);
} catch (SQLException ex) {
getLogger().log(Level.SEVERE, "Couldn't import data. Aborting...", ex);
plugin.getLogger().log(Level.SEVERE, "Couldn't import data. Aborting...", ex);
}
return false;
@ -190,6 +238,28 @@ public abstract class FastLoginCore<P> {
this.authPlugin = authPlugin;
}
public void saveDefaultFile(String fileName) {
if (!plugin.getDataFolder().exists()) {
plugin.getDataFolder().mkdir();
}
File configFile = new File(plugin.getDataFolder(), fileName);
if (!configFile.exists()) {
InputStream in = getClass().getClassLoader().getResourceAsStream(fileName);
try {
Files.copy(in, configFile.toPath());
} catch (IOException ioExc) {
plugin.getLogger().log(Level.SEVERE, "Error saving default " + fileName, ioExc);
} finally {
try {
in.close();
} catch (IOException ex) {
plugin.getLogger().log(Level.SEVERE, null, ex);
}
}
}
}
public void close() {
if (storage != null) {
storage.close();

View File

@ -0,0 +1,110 @@
package com.github.games647.fastlogin.core.shared;
import com.github.games647.fastlogin.core.AuthStorage;
import com.github.games647.fastlogin.core.PlayerProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import java.util.logging.Level;
public abstract class ForceLoginMangement<P extends C, C, L extends LoginSession, T extends PlatformPlugin<C>>
implements Runnable {
protected final FastLoginCore<P, C, T> core;
protected final P player;
protected L session;
public ForceLoginMangement(FastLoginCore<P, C, T> core, P player) {
this.core = core;
this.player = player;
}
@Override
public void run() {
if (!isOnline(player) || session == null) {
return;
}
AuthStorage storage = core.getStorage();
PlayerProfile playerProfile = session.getProfile();
try {
if (isOnlineMode()) {
//premium player
AuthPlugin<P> authPlugin = core.getAuthPluginHook();
if (authPlugin == null) {
//maybe only bungeecord plugin
onForceActionSuccess(session);
} else {
boolean success = false;
if (isOnline(player)) {
if (core.getConfig().get("autoLogin", true)) {
if (session.needsRegistration()) {
success = forceRegister(player);
} else {
success = forceLogin(player);
}
} else {
success = true;
}
}
if (success) {
//update only on success to prevent corrupt data
if (playerProfile != null) {
playerProfile.setUuid(session.getUuid());
//save cracked players too
playerProfile.setPremium(true);
storage.save(playerProfile);
}
onForceActionSuccess(session);
}
}
} else {
//cracked player
if (playerProfile != null) {
playerProfile.setUuid(null);
playerProfile.setPremium(false);
storage.save(playerProfile);
}
}
} catch (Exception ex) {
core.getPlugin().getLogger().log(Level.INFO, "ERROR ON FORCE LOGIN", ex);
}
}
public boolean forceRegister(P player) {
core.getPlugin().getLogger().log(Level.FINE, "Register player {0}", getName(player));
String generatedPassword = core.getPasswordGenerator().getRandomPassword(player);
boolean success = core.getAuthPluginHook().forceRegister(player, generatedPassword);
String message = core.getMessage("auto-register");
if (success && message != null) {
message = message.replace("%password", generatedPassword);
core.getPlugin().sendMessage(player, message);
}
return success;
}
public boolean forceLogin(P player) {
core.getPlugin().getLogger().log(Level.FINE, "Logging player {0} in", getName(player));
boolean success = core.getAuthPluginHook().forceLogin(player);
if (success) {
core.sendLocaleMessage("auto-login", player);
}
return success;
}
public abstract void onForceActionSuccess(LoginSession session);
public abstract String getName(P player);
public abstract boolean isOnline(P player);
public abstract boolean isOnlineMode();
}

View File

@ -7,12 +7,12 @@ import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import java.util.UUID;
import java.util.logging.Level;
public abstract class JoinManagement<T, S extends LoginSource> {
public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
protected final FastLoginCore<T> core;
protected final AuthPlugin<T> authHook;
protected final FastLoginCore<P, C, ?> core;
protected final AuthPlugin<P> authHook;
public JoinManagement(FastLoginCore<T> core, AuthPlugin<T> authHook) {
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook) {
this.core = core;
this.authHook = authHook;
}
@ -30,7 +30,7 @@ public abstract class JoinManagement<T, S extends LoginSource> {
try {
if (profile.getUserId() == -1) {
if (core.getPendingLogins().remove(ip + username) != null && config.get("secondAttemptCracked", false)) {
core.getLogger().log(Level.INFO, "Second attempt login -> cracked {0}", username);
core.getPlugin().getLogger().log(Level.INFO, "Second attempt login -> cracked {0}", username);
//first login request failed so make a cracked session
startCrackedSession(source, profile, username);
@ -39,7 +39,7 @@ public abstract class JoinManagement<T, S extends LoginSource> {
UUID premiumUUID = null;
if (config.get("nameChangeCheck", false) || config.get("autoRegister", false)) {
core.getLogger().log(Level.FINER, "Player {0} uses a premium username", username);
core.getPlugin().getLogger().log(Level.FINER, "Player {0} uses a premium username", username);
premiumUUID = core.getApiConnector().getPremiumUUID(username);
}
@ -61,7 +61,7 @@ public abstract class JoinManagement<T, S extends LoginSource> {
startCrackedSession(source, profile, username);
}
} catch (Exception ex) {
core.getLogger().log(Level.SEVERE, "Failed to check premium state", ex);
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to check premium state", ex);
}
}
@ -80,7 +80,7 @@ public abstract class JoinManagement<T, S extends LoginSource> {
PlayerProfile profile = core.getStorage().loadProfile(premiumUUID);
if (profile != null) {
//uuid exists in the database
core.getLogger().log(Level.FINER, "Player {0} changed it's username", premiumUUID);
core.getPlugin().getLogger().log(Level.FINER, "Player {0} changed it's username", premiumUUID);
//update the username to the new one in the database
profile.setPlayerName(username);

View File

@ -0,0 +1,27 @@
package com.github.games647.fastlogin.core.shared;
import java.io.File;
import java.io.Reader;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Logger;
public interface PlatformPlugin<C> {
String getName();
File getDataFolder();
Logger getLogger();
Map<String, Object> loadYamlFile(Reader reader);
void sendMessage(C receiver, String message);
ThreadFactory getThreadFactory();
String translateColorCodes(char colorChar, String rawMessage);
MojangApiConnector makeApiConnector(Logger logger, List<String> addresses, int requests);
}