Second try

This commit is contained in:
Gabriele C 2019-10-16 14:19:53 +02:00
parent 74b301870f
commit 9a59738b81
10 changed files with 149 additions and 105 deletions

View File

@ -20,6 +20,7 @@ import fr.xephi.authme.listener.PlayerListener19;
import fr.xephi.authme.listener.PlayerListener19Spigot;
import fr.xephi.authme.listener.ServerListener;
import fr.xephi.authme.output.ConsoleLoggerFactory;
import fr.xephi.authme.process.AsyncUserScheduler;
import fr.xephi.authme.security.crypts.Sha256;
import fr.xephi.authme.service.BackupService;
import fr.xephi.authme.service.BukkitService;
@ -67,6 +68,7 @@ public class AuthMe extends JavaPlugin {
private Settings settings;
private DataSource database;
private BukkitService bukkitService;
private AsyncUserScheduler asyncUserScheduler;
private Injector injector;
private BackupService backupService;
private ConsoleLogger logger;
@ -250,6 +252,7 @@ public class AuthMe extends JavaPlugin {
void instantiateServices(Injector injector) {
database = injector.getSingleton(DataSource.class);
bukkitService = injector.getSingleton(BukkitService.class);
asyncUserScheduler = injector.getSingleton(AsyncUserScheduler.class);
commandHandler = injector.getSingleton(CommandHandler.class);
backupService = injector.getSingleton(BackupService.class);

View File

@ -6,6 +6,7 @@ import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.ConsoleLoggerFactory;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.process.AsyncUserScheduler;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.service.BukkitService;
@ -40,6 +41,9 @@ public class RegisterAdminCommand implements ExecutableCommand {
@Inject
private ValidationService validationService;
@Inject
private AsyncUserScheduler asyncUserScheduler;
@Override
public void executeCommand(final CommandSender sender, List<String> arguments) {
// Get the player name and password
@ -54,7 +58,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
return;
}
bukkitService.runTaskOptionallyAsync(() -> {
asyncUserScheduler.runTask(playerName, () -> {
if (dataSource.isAuthAvailable(playerNameLowerCase)) {
commonService.send(sender, MessageKey.NAME_ALREADY_REGISTERED);
return;

View File

@ -5,6 +5,7 @@ import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.process.AsyncUserScheduler;
import fr.xephi.authme.service.BukkitService;
import fr.xephi.authme.service.CommonService;
import fr.xephi.authme.service.ValidationService;
@ -33,6 +34,9 @@ public class SetEmailCommand implements ExecutableCommand {
@Inject
private ValidationService validationService;
@Inject
private AsyncUserScheduler asyncUserScheduler;
@Override
public void executeCommand(final CommandSender sender, List<String> arguments) {
// Get the player name and email address
@ -45,34 +49,31 @@ public class SetEmailCommand implements ExecutableCommand {
return;
}
bukkitService.runTaskOptionallyAsync(new Runnable() {
@Override
public void run() {
// Validate the user
PlayerAuth auth = dataSource.getAuth(playerName);
if (auth == null) {
commonService.send(sender, MessageKey.UNKNOWN_USER);
return;
} else if (!validationService.isEmailFreeForRegistration(playerEmail, sender)) {
commonService.send(sender, MessageKey.EMAIL_ALREADY_USED_ERROR);
return;
}
// Set the email address
auth.setEmail(playerEmail);
if (!dataSource.updateEmail(auth)) {
commonService.send(sender, MessageKey.ERROR);
return;
}
// Update the player cache
if (playerCache.getAuth(playerName) != null) {
playerCache.updatePlayer(auth);
}
// Show a status message
commonService.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS);
asyncUserScheduler.runTask(playerName, () -> {
// Validate the user
PlayerAuth auth = dataSource.getAuth(playerName);
if (auth == null) {
commonService.send(sender, MessageKey.UNKNOWN_USER);
return;
} else if (!validationService.isEmailFreeForRegistration(playerEmail, sender)) {
commonService.send(sender, MessageKey.EMAIL_ALREADY_USED_ERROR);
return;
}
// Set the email address
auth.setEmail(playerEmail);
if (!dataSource.updateEmail(auth)) {
commonService.send(sender, MessageKey.ERROR);
return;
}
// Update the player cache
if (playerCache.getAuth(playerName) != null) {
playerCache.updatePlayer(auth);
}
// Show a status message
commonService.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS);
});
}
}

View File

@ -231,9 +231,11 @@ public class PlayerListener implements Listener {
}
if (antiBotService.wasPlayerKicked(player.getName())) {
System.err.println(player.getName() + " QUIT PROCESS SKIPPED DUE TO ANTIBOT");
return;
}
System.err.println(player.getName() + " STARTING QUIT PROCESS DUE TO QUIT");
management.performQuit(player);
}
@ -249,6 +251,7 @@ public class PlayerListener implements Listener {
final Player player = event.getPlayer();
if (!antiBotService.wasPlayerKicked(player.getName())) {
System.err.println(player.getName() + " STARTING QUIT PROCESS DUE TO KICK");
management.performQuit(player);
}
}

View File

@ -0,0 +1,82 @@
package fr.xephi.authme.process;
import fr.xephi.authme.service.BukkitService;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import javax.inject.Inject;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Function;
public class AsyncUserScheduler {
@Inject
private BukkitService bukkitService;
private KeyedSequentialScheduler<String> asyncUserScheduler;
AsyncUserScheduler() {
this.asyncUserScheduler = new KeyedSequentialScheduler<>(runnable ->
bukkitService.runTaskAsynchronously(runnable));
}
public void runTask(String playerName, Runnable runnable) {
if (bukkitService.isUseAsyncTasks()) {
asyncUserScheduler.submit(playerName.toLowerCase(), runnable);
} else {
runnable.run();
}
}
public void runTask(Player player, Runnable runnable) {
runTask(player.getName(), runnable);
}
public class KeyedSequentialScheduler<K> {
private Map<K, SequentialExecutor> executors;
private Function<Runnable, BukkitTask> scheduler;
public KeyedSequentialScheduler(Function<Runnable, BukkitTask> scheduler) {
this.executors = new LinkedHashMap<>();
this.scheduler = scheduler;
}
public void submit(K key, Runnable runnable) {
SequentialExecutor executor = executors.get(key);
if (executor == null) {
executor = new SequentialExecutor(scheduler, () -> executors.remove(key));
executors.put(key, executor);
}
executor.submit(runnable);
}
}
public class SequentialExecutor {
private Queue<Runnable> queue;
private Function<Runnable, BukkitTask> scheduler;
private Runnable callback;
private BukkitTask executor;
public SequentialExecutor(Function<Runnable, BukkitTask> scheduler, Runnable callback) {
this.queue = new LinkedBlockingQueue<>();
this.scheduler = scheduler;
this.callback = callback;
}
public void submit(Runnable task) {
queue.add(task);
if (executor == null || executor.isCancelled()) {
executor = scheduler.apply(() -> {
while (!queue.isEmpty()) {
queue.poll().run();
}
callback.run();
});
}
}
}
}

View File

@ -30,6 +30,8 @@ public class Management {
@Inject
private BukkitService bukkitService;
@Inject
private AsyncUserScheduler asyncUserScheduler;
// Processes
@Inject
@ -51,115 +53,51 @@ public class Management {
@Inject
private AsyncChangePassword asyncChangePassword;
private KeyedSequentialScheduler<String> asyncUserScheduler;
Management() {
this.asyncUserScheduler = new KeyedSequentialScheduler<>(runnable ->
bukkitService.runTaskAsynchronously(runnable));
}
public class KeyedSequentialScheduler<K> {
private Map<K, SequentialExecutor> executors;
private Function<Runnable, BukkitTask> scheduler;
public KeyedSequentialScheduler(Function<Runnable, BukkitTask> scheduler) {
this.executors = new LinkedHashMap<>();
this.scheduler = scheduler;
}
public void submit(K key, Runnable runnable) {
SequentialExecutor executor = executors.get(key);
if (executor == null) {
executor = new SequentialExecutor(scheduler, () -> executors.remove(key));
executors.put(key, executor);
}
executor.submit(runnable);
}
}
public class SequentialExecutor {
private Queue<Runnable> queue;
private Function<Runnable, BukkitTask> scheduler;
private Runnable callback;
private BukkitTask executor;
public SequentialExecutor(Function<Runnable, BukkitTask> scheduler, Runnable callback) {
this.queue = new LinkedBlockingQueue<>();
this.scheduler = scheduler;
this.callback = callback;
}
public void submit(Runnable task) {
queue.add(task);
if (executor == null || executor.isCancelled()) {
executor = scheduler.apply(() -> {
while (!queue.isEmpty()) {
queue.poll().run();
}
callback.run();
});
}
}
}
public void performLogin(Player player, String password) {
runTask(player, () -> asynchronousLogin.login(player, password));
asyncUserScheduler.runTask(player, () -> asynchronousLogin.login(player, password));
}
public void forceLogin(Player player) {
runTask(player, () -> asynchronousLogin.forceLogin(player));
asyncUserScheduler.runTask(player, () -> asynchronousLogin.forceLogin(player));
}
public void performLogout(Player player) {
runTask(player, () -> asynchronousLogout.logout(player));
asyncUserScheduler.runTask(player, () -> asynchronousLogout.logout(player));
}
public <P extends RegistrationParameters> void performRegister(RegistrationMethod<P> variant, P parameters) {
runTask(parameters.getPlayer(), () -> asyncRegister.register(variant, parameters));
asyncUserScheduler.runTask(parameters.getPlayer(), () -> asyncRegister.register(variant, parameters));
}
public void performUnregister(Player player, String password) {
runTask(player, () -> asynchronousUnregister.unregister(player, password));
asyncUserScheduler.runTask(player, () -> asynchronousUnregister.unregister(player, password));
}
public void performUnregisterByAdmin(CommandSender initiator, String name, Player player) {
runTask(name, () -> asynchronousUnregister.adminUnregister(initiator, name, player));
asyncUserScheduler.runTask(name, () -> asynchronousUnregister.adminUnregister(initiator, name, player));
}
public void performJoin(Player player) {
runTask(player, () -> asynchronousJoin.processJoin(player));
asyncUserScheduler.runTask(player, () -> asynchronousJoin.processJoin(player));
}
public void performQuit(Player player) {
runTask(player, () -> asynchronousQuit.processQuit(player));
asyncUserScheduler.runTask(player, () -> asynchronousQuit.processQuit(player));
}
public void performAddEmail(Player player, String newEmail) {
runTask(player, () -> asyncAddEmail.addEmail(player, newEmail));
asyncUserScheduler.runTask(player, () -> asyncAddEmail.addEmail(player, newEmail));
}
public void performChangeEmail(Player player, String oldEmail, String newEmail) {
runTask(player, () -> asyncChangeEmail.changeEmail(player, oldEmail, newEmail));
asyncUserScheduler.runTask(player, () -> asyncChangeEmail.changeEmail(player, oldEmail, newEmail));
}
public void performPasswordChange(Player player, String oldPassword, String newPassword) {
runTask(player, () -> asyncChangePassword.changePassword(player, oldPassword, newPassword));
asyncUserScheduler.runTask(player, () -> asyncChangePassword.changePassword(player, oldPassword, newPassword));
}
public void performPasswordChangeAsAdmin(CommandSender sender, String playerName, String newPassword) {
runTask(playerName, () -> asyncChangePassword.changePasswordAsAdmin(sender, playerName, newPassword));
}
private void runTask(String playerName, Runnable runnable) {
if (bukkitService.isUseAsyncTasks()) {
asyncUserScheduler.submit(playerName.toLowerCase(), runnable);
} else {
runnable.run();
}
}
private void runTask(Player player, Runnable runnable) {
runTask(player.getName(), runnable);
asyncUserScheduler.runTask(playerName, () -> asyncChangePassword.changePasswordAsAdmin(sender, playerName, newPassword));
}
}

View File

@ -7,6 +7,7 @@ import fr.xephi.authme.events.ProtectInventoryEvent;
import fr.xephi.authme.output.ConsoleLoggerFactory;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.AsyncUserScheduler;
import fr.xephi.authme.process.AsynchronousProcess;
import fr.xephi.authme.process.login.AsynchronousLogin;
import fr.xephi.authme.service.BukkitService;
@ -72,6 +73,9 @@ public class AsynchronousJoin implements AsynchronousProcess {
@Inject
private SessionService sessionService;
@Inject
private AsyncUserScheduler asyncUserScheduler;
AsynchronousJoin() {
}
@ -122,11 +126,12 @@ public class AsynchronousJoin implements AsynchronousProcess {
// Session logic
if (sessionService.canResumeSession(player)) {
logger.warning("SESSION LOGIN");
service.send(player, MessageKey.SESSION_RECONNECTION);
// Run commands
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
() -> commandManager.runCommandsOnSessionLogin(player));
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player));
asyncUserScheduler.runTask(player, () -> asynchronousLogin.forceLogin(player));
return;
}
} else if (!service.getProperty(RegistrationSettings.FORCE)) {

View File

@ -112,8 +112,10 @@ public class AsynchronousLogin implements AsynchronousProcess {
* @param player the player to log in
*/
public void forceLogin(Player player) {
logger.warning("FORCED LOGIN REQUEST");
PlayerAuth auth = getPlayerAuth(player);
if (auth != null) {
logger.warning("FORCED LOGIN");
performLogin(player, auth);
}
}
@ -129,6 +131,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
private PlayerAuth getPlayerAuth(Player player) {
final String name = player.getName().toLowerCase();
if (playerCache.isAuthenticated(name)) {
logger.warning("PLAYER WAS ALREADY LOGGED IN CACHE!");
service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
return null;
}
@ -149,6 +152,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
final String ip = PlayerUtils.getPlayerIp(player);
if (hasReachedMaxLoggedInPlayersForIp(player, ip)) {
logger.warning("REACHED MAX LOGGED IN PLAYERS FOR IP!");
service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
return null;
}
@ -262,6 +266,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
logger.fine(player.getName() + " logged in!");
// makes player loggedin
logger.warning(player.getName() + " BEING ADDED TO CACHE AS LOGGED IN");
playerCache.updatePlayer(auth);
dataSource.setLogged(name);
sessionService.grantSession(name);

View File

@ -66,6 +66,7 @@ public class AsynchronousLogout implements AsynchronousProcess {
bungeeSender.sendAuthMeBungeecordMessage(MessageType.REFRESH_QUITLOC, name);
}
System.err.println(player.getName() + " BEING REMOVED FROM CACHE DUE TO LOGOUT");
playerCache.removePlayer(name);
codeManager.unverify(name);
database.setUnlogged(name);

View File

@ -68,6 +68,7 @@ public class AsynchronousQuit implements AsynchronousProcess {
if (player == null || validationService.isUnrestricted(player.getName())) {
return;
}
System.err.println(player.getName() + " QUIT PROCESS STARTED");
final String name = player.getName().toLowerCase();
final boolean wasLoggedIn = playerCache.isAuthenticated(name);
@ -92,6 +93,7 @@ public class AsynchronousQuit implements AsynchronousProcess {
}
//always unauthenticate the player - use session only for auto logins on the same ip
System.err.println(player.getName() + " BEING REMOVED FROM CACHE DUE TO QUIT");
playerCache.removePlayer(name);
codeManager.unverify(name);