diff --git a/bukkit/pom.xml b/bukkit/pom.xml
index 5caffc82..93de0a08 100644
--- a/bukkit/pom.xml
+++ b/bukkit/pom.xml
@@ -41,6 +41,10 @@
com.google.gson
fastlogin.gson
+
+ io.papermc.lib
+ fastlogin.paperlib
+
@@ -56,14 +60,10 @@
-
+
- spigot-repo
- https://hub.spigotmc.org/nexus/content/repositories/snapshots/
-
-
- false
-
+ papermc
+ https://papermc.io/repo/repository/maven-public/
@@ -108,14 +108,22 @@
${project.version}
-
+
- org.spigotmc
- spigot-api
+ com.destroystokyo.paper
+ paper-api
1.15.2-R0.1-SNAPSHOT
provided
+
+
+ io.papermc
+ paperlib
+ 1.0.6
+ compile
+
+
com.comphenix.protocol
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java
index 03943e2b..eacfdfed 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java
@@ -3,6 +3,7 @@ package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
+import com.github.games647.fastlogin.bukkit.listener.PaperPreLoginListener;
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
import com.github.games647.fastlogin.bukkit.listener.protocollib.SkinApplyListener;
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
@@ -11,6 +12,12 @@ import com.github.games647.fastlogin.core.CommonUtil;
import com.github.games647.fastlogin.core.PremiumStatus;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
+import io.papermc.lib.PaperLib;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.slf4j.Logger;
import java.net.InetSocketAddress;
import java.nio.file.Path;
@@ -19,12 +26,6 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.bukkit.plugin.PluginManager;
-import org.bukkit.plugin.java.JavaPlugin;
-import org.slf4j.Logger;
-
/**
* This plugin checks if a player has a paid account and if so tries to skip offline mode authentication.
*/
@@ -75,7 +76,11 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin
@@ -25,8 +28,22 @@ public class AuthMeHook implements AuthPlugin, Listener {
private final FastLoginBukkit plugin;
+ private final AuthMeApi authmeAPI;
+ private Management authmeManagement;
+
public AuthMeHook(FastLoginBukkit plugin) {
this.plugin = plugin;
+ this.authmeAPI = AuthMeApi.getInstance();
+
+ if (plugin.getConfig().getBoolean("respectIpLimit", false)) {
+ try {
+ Field managementField = this.authmeAPI.getClass().getDeclaredField("management");
+ managementField.setAccessible(true);
+ this.authmeManagement = (Management) managementField.get(this.authmeAPI);
+ } catch (NoSuchFieldException | IllegalAccessException exception) {
+ this.authmeManagement = null;
+ }
+ }
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@@ -41,25 +58,32 @@ public class AuthMeHook implements AuthPlugin, Listener {
@Override
public boolean forceLogin(Player player) {
- if (AuthMeApi.getInstance().isAuthenticated(player)) {
+ if (authmeAPI.isAuthenticated(player)) {
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
return false;
}
//skips registration and login
- AuthMeApi.getInstance().forceLogin(player);
+ authmeAPI.forceLogin(player);
return true;
}
@Override
public boolean isRegistered(String playerName) {
- return AuthMeApi.getInstance().isRegistered(playerName);
+ return authmeAPI.isRegistered(playerName);
}
@Override
+ //this automatically login the player too
public boolean forceRegister(Player player, String password) {
- //this automatically login the player too
- AuthMeApi.getInstance().forceRegister(player, password);
+ //if we have the management - we can trigger register with IP limit checks
+ if (authmeManagement != null) {
+ authmeManagement.performRegister(RegistrationMethod.PASSWORD_REGISTRATION,
+ ApiPasswordRegisterParams.of(player, password, true));
+ } else {
+ authmeAPI.forceRegister(player, password);
+ }
+
return true;
}
}
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/PaperPreLoginListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/PaperPreLoginListener.java
new file mode 100644
index 00000000..167ae006
--- /dev/null
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/PaperPreLoginListener.java
@@ -0,0 +1,41 @@
+package com.github.games647.fastlogin.bukkit.listener;
+
+import com.destroystokyo.paper.profile.ProfileProperty;
+import com.github.games647.craftapi.model.skin.Textures;
+import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
+import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
+import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
+
+public class PaperPreLoginListener implements Listener {
+
+ private final FastLoginBukkit plugin;
+
+ public PaperPreLoginListener(final FastLoginBukkit plugin) {
+ this.plugin = plugin;
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST)
+ //if paper is used - player skin must be set at pre login, otherwise usercache is used
+ //using usercache makes premium name change basically impossible
+ public void onAsyncPlayerPreLogin(AsyncPlayerPreLoginEvent event) {
+ if (event.getLoginResult() != Result.ALLOWED) {
+ return;
+ }
+
+ // event gives us only IP, not the port, so we need to loop through all the sessions
+ for (BukkitLoginSession session : plugin.getLoginSessions().values()) {
+ if (!event.getName().equals(session.getUsername())) {
+ continue;
+ }
+
+ session.getSkin().ifPresent(skin -> event.getPlayerProfile().setProperty(new ProfileProperty(Textures.KEY,
+ skin.getValue(), skin.getSignature())));
+ break;
+ }
+ }
+
+}
diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/SkinApplyListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/SkinApplyListener.java
index 5f1df7d9..fedaa357 100644
--- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/SkinApplyListener.java
+++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/SkinApplyListener.java
@@ -9,9 +9,6 @@ import com.comphenix.protocol.wrappers.WrappedSignedProperty;
import com.github.games647.craftapi.model.skin.Textures;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
-
-import java.lang.reflect.InvocationTargetException;
-
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -19,6 +16,8 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
+import java.lang.reflect.InvocationTargetException;
+
public class SkinApplyListener implements Listener {
private static final Class> GAME_PROFILE = MinecraftReflection.getGameProfileClass();
@@ -39,14 +38,12 @@ public class SkinApplyListener implements Listener {
Player player = loginEvent.getPlayer();
- if (plugin.getConfig().getBoolean("forwardSkin")) {
- //go through every session, because player.getAddress is null
- //loginEvent.getAddress is just a InetAddress not InetSocketAddress, so not unique enough
- for (BukkitLoginSession session : plugin.getLoginSessions().values()) {
- if (session.getUsername().equals(player.getName())) {
- session.getSkin().ifPresent(skin -> applySkin(player, skin.getValue(), skin.getSignature()));
- break;
- }
+ //go through every session, because player.getAddress is null
+ //loginEvent.getAddress is just a InetAddress not InetSocketAddress, so not unique enough
+ for (BukkitLoginSession session : plugin.getLoginSessions().values()) {
+ if (session.getUsername().equals(player.getName())) {
+ session.getSkin().ifPresent(skin -> applySkin(player, skin.getValue(), skin.getSignature()));
+ break;
}
}
}
diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml
index 6253ff98..37a313af 100644
--- a/core/src/main/resources/config.yml
+++ b/core/src/main/resources/config.yml
@@ -36,6 +36,15 @@ anti-bot:
# For more information: https://github.com/games647/FastLogin#why-do-players-have-to-invoke-a-command
autoRegister: false
+# Should FastLogin respect per IP limit of registrations (e.g. in AuthMe)
+# Because most auth plugins do their stuff async - FastLogin will still think the player was registered
+# To work best - you also need to enable auto-register-unknown
+#
+# If set to true - FastLogin will always attempt to register the player, even if the limit is exceeded
+# It is up to the auth plugin to handle the excessive registration
+# https://github.com/games647/FastLogin/issues/458
+respectIpLimit: false
+
# This is extra configuration option to the feature above. If we request a premium authentication from a player who
# isn't actual premium but used a premium username, the player will disconnect with the reason "invalid session" or
# "bad login".
@@ -127,6 +136,10 @@ nameChangeCheck: false
# the skin data is included in the Auth-Verification-Response sent by Mojang. If you want to use for other
# players like cracked player, you have to use other plugins.
#
+# If you use PaperSpigot - FastLogin will always try to set the skin, even if forwardSkin is set to false
+# It is needed to allow premium name change to work correctly
+# https://github.com/games647/FastLogin/issues/457
+#
# If you want to use skins for your cracked player, you need an additional plugin like
# ChangeSkin, SkinRestorer, ...
forwardSkin: true
diff --git a/core/src/main/resources/messages.yml b/core/src/main/resources/messages.yml
index 99221b51..fdc6cb84 100644
--- a/core/src/main/resources/messages.yml
+++ b/core/src/main/resources/messages.yml
@@ -53,10 +53,10 @@ player-unknown: '&4Player not in the database'
# The user skipped the authentication, because it was a premium player
auto-login: '&2Auto logged in'
-# The user was auto registered on the first join. The user account will be registered to protect it from cracked players
+# FastLogin attempted to auto register user. The user account is registered to protect it from cracked players
+# If FastLogin is respecting auth plugin IP limit - the registration may have failed, however the message is still displayed
# The password can be used if the mojang servers are down and you still want your premium users to login (PLANNED)
-auto-register: '&2Auto registered with password: %password
-You may want change it?'
+auto-register: '&2Tried auto registering with password: &7%password&2. You may want change it?'
# GameProfile is not able to toggle the premium state of other players
no-permission: '&4Not enough permissions'