mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-07-30 10:47:33 +02:00
Share the same force login mangement for less duplicate code
This commit is contained in:
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
Reference in New Issue
Block a user