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
@@ -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());
}
}