mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-12-23 15:18:09 +01:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99b7367366 | ||
|
|
961b144efb | ||
|
|
dcd06ad613 | ||
|
|
c4c043e1c5 | ||
|
|
87aa9dd668 | ||
|
|
2838c06ab3 | ||
|
|
ae58e0539a | ||
|
|
624745728f | ||
|
|
d0287ec2b4 | ||
|
|
e6a4af92cc | ||
|
|
8f3920fa99 | ||
|
|
a723b2ddd3 | ||
|
|
5cf67127c7 | ||
|
|
e5309b9fa1 | ||
|
|
e439126294 | ||
|
|
59703bac4e | ||
|
|
bfaf390463 | ||
|
|
9e06fd7735 | ||
|
|
d56a0f9ff1 | ||
|
|
96fe190cac | ||
|
|
d4f5b547d4 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -40,4 +40,9 @@ hs_err_pid*
|
||||
gradle-app.setting
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
!gradle-wrapper.jar
|
||||
|
||||
# Project module targets
|
||||
bukkit/target
|
||||
universal/target
|
||||
bungee/target
|
||||
27
CHANGELOG.md
27
CHANGELOG.md
@@ -1,3 +1,30 @@
|
||||
######1.3
|
||||
|
||||
* Added support for AuthMe 3.X
|
||||
* Fixed premium logins if the server is not fully started
|
||||
* Added other command argument to /premium and /cracked
|
||||
* Added support for LogIt
|
||||
* Fixed 1.7 Minecraft support by removing guava 11+ only features -> Cauldron support
|
||||
* Fixed BungeeCord support in Cauldron
|
||||
|
||||
######1.2.1
|
||||
|
||||
* Fix premium status change notification message on BungeeCord
|
||||
|
||||
######1.2
|
||||
|
||||
* Fix race condition in BungeeCord
|
||||
* Fix dead lock in xAuth
|
||||
* Added API methods for plugins to set their own password generator
|
||||
* Added API methods for plugins to set their own auth plugin hook
|
||||
=> Added support for AdvancedLogin
|
||||
|
||||
######1.1
|
||||
|
||||
* Make the configuration options also work under BungeeCord (premiumUUID, forwardSkin)
|
||||
* Catch configuration loading exception if it's not spigot build
|
||||
* Fix config loading for older Spigot builds
|
||||
|
||||
######1.0
|
||||
|
||||
* Massive refactor to handle errors on force actions safely
|
||||
|
||||
47
README.md
47
README.md
@@ -3,7 +3,7 @@
|
||||
[](https://travis-ci.org/games647/FastLogin)
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8ZBULMAPN7MZC)
|
||||
|
||||
Checks if a minecraft player has a paid account (premium). If so, they can skip offline authentication (auth plugins).
|
||||
Checks if a Minecraft player has a paid account (premium). If so, they can skip offline authentication (auth plugins).
|
||||
So they don't need to enter passwords. This is also called auto login (auto-login).
|
||||
|
||||
###Features:
|
||||
@@ -26,23 +26,26 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
|
||||
***
|
||||
|
||||
###Commands:
|
||||
* /premium [player] Label the invoker as paid account
|
||||
* /cracked [player] Label the invoker as cracked account
|
||||
* /premium [player] Label the invoker or the argument as paid account
|
||||
* /cracked [player] Label the invoker or the argument as cracked account
|
||||
|
||||
###Permissions:
|
||||
* fastlogin.bukkit.command.premium
|
||||
* fastlogin.bukkit.command.cracked
|
||||
|
||||
###Requirements:
|
||||
* Plugin: [ProtocolLib](http://www.spigotmc.org/resources/protocollib.1997/)
|
||||
* Plugin: [ProtocolLib](http://www.spigotmc.org/resources/protocollib.1997/) or [ProtocolSupport](http://www.spigotmc.org/resources/protocolsupport.7201/)
|
||||
* Tested Bukkit/[Spigot](https://www.spigotmc.org) 1.9 (could also work with other versions)
|
||||
* Java 7+
|
||||
* Run Spigot and/or BungeeCord/Waterfall in offline mode (see server.properties or config.yml)
|
||||
* An auth plugin. Supported Plugins
|
||||
* An auth plugin. Supported plugins
|
||||
|
||||
####Bukkit/Spigot/PaperSPigot
|
||||
####Bukkit/Spigot/PaperSpigot
|
||||
|
||||
* [AuthMe](http://dev.bukkit.org/bukkit-plugins/authme-reloaded/)
|
||||
* [AuthMe (both 5.X and 3.X)](http://dev.bukkit.org/bukkit-plugins/authme-reloaded/)
|
||||
* [xAuth](http://dev.bukkit.org/bukkit-plugins/xauth/)
|
||||
* [LogIt](https://github.com/XziomekX/LogIt)
|
||||
* [AdvancedLogin (Paid)](https://www.spigotmc.org/resources/advancedlogin.10510/)
|
||||
* [CrazyLogin](http://dev.bukkit.org/bukkit-plugins/crazylogin/)
|
||||
* [LoginSecurity](http://dev.bukkit.org/bukkit-plugins/loginsecurity/)
|
||||
* [RoyalAuth](http://dev.bukkit.org/bukkit-plugins/royalauth/)
|
||||
@@ -58,10 +61,32 @@ https://www.spigotmc.org/resources/fastlogin.14153/history
|
||||
|
||||
***
|
||||
|
||||
###How to install
|
||||
|
||||
####Bukkit/Spigot/PaperSpigot
|
||||
|
||||
1. Download and install ProtocolLib
|
||||
2. Download and install FastLogin
|
||||
3. Set your server in offline mode by setting the value onlinemode in your server.properties to false
|
||||
|
||||
####BungeeCord/Waterfall
|
||||
|
||||
1. Activate BungeeCord in the Spigot configuration
|
||||
2. Restart your server
|
||||
3. Now there is proxy-whitelist file in the FastLogin folder
|
||||
Put your stats id from the BungeeCord config into this file
|
||||
4. Activate ipForward in your BungeeCord config
|
||||
5. Download and Install FastLogin on BungeeCord AND Spigot
|
||||
6. Check your database settings in the config of FastLogin on BungeeCord
|
||||
7. Set your proxy (BungeeCord) in offline mode by setting the value onlinemode in your config.yml to false
|
||||
8. (BungeeCord doesn't support SQLite per default, so you should change the configuration to MySQL or MariaDB)
|
||||
|
||||
***
|
||||
|
||||
###FAQ
|
||||
|
||||
####Index
|
||||
1. [How does minecraft logins work?](#how-does-minecraft-logins-work)
|
||||
1. [How does Minecraft logins work?](#how-does-minecraft-logins-work)
|
||||
2. [How does this plugin work?](#how-does-this-plugin-work)
|
||||
3. [Why does the plugin require offline mode?](#why-does-the-plugin-require-offline-mode)
|
||||
4. [Can cracked player join with premium usernames?](#can-cracked-player-join-with-premium-usernames)
|
||||
@@ -137,11 +162,7 @@ and Mojang account. Then the command can be executed. So someone different canno
|
||||
by buying the username.
|
||||
|
||||
####Does the plugin have BungeeCord support?
|
||||
Yes it has. Just activate ipForward in your BungeeCord config and place the plugin in the plugins folder of
|
||||
Bukkit/Spigot and BungeeCord. Then you have fill your BungeeCord Id (from the Stats-Option in the BungeeCord config)
|
||||
into the whitelist file of your Bukkit/Spigot server. For security reasons, don't post this Id on Forums.
|
||||
|
||||
This plugin will automatically detect if BungeeCord is running and handle premium checks on BungeeCord.
|
||||
Yes it has. See the how to install above.
|
||||
|
||||
####Could premium players have a premium UUID and Skin?
|
||||
Since 0.7 both features are implemented. You can check the config.yml in order to activate it.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.games647</groupId>
|
||||
<artifactId>fastlogin</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.3</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -40,6 +40,11 @@
|
||||
<url>http://repo.luricos.de/bukkit-plugins/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>logit-only-repo</id>
|
||||
<url>http://ci.ac3-servers.eu/job/LogIt-Classic/2/maven-repository/repository/</url>
|
||||
</repository>
|
||||
|
||||
<!--Github automatic maven builds-->
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
@@ -98,6 +103,18 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.lucaseasedup.logit</groupId>
|
||||
<artifactId>LogIt</artifactId>
|
||||
<version>SNAPSHOT</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.RoyalDev</groupId>
|
||||
<artifactId>RoyalAuth</artifactId>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.github.games647.fastlogin.bukkit;
|
||||
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class DefaultPasswordGenerator implements PasswordGenerator {
|
||||
|
||||
@Override
|
||||
public String getRandomPassword(Player player) {
|
||||
return RandomStringUtils.random(8, true, true);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,37 @@
|
||||
package com.github.games647.fastlogin.bukkit;
|
||||
|
||||
import com.avaje.ebeaninternal.api.ClassUtil;
|
||||
import com.comphenix.protocol.AsynchronousManager;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||
import com.comphenix.protocol.utility.SafeCacheBuilder;
|
||||
import com.github.games647.fastlogin.bukkit.commands.CrackedCommand;
|
||||
import com.github.games647.fastlogin.bukkit.commands.PremiumCommand;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.AuthMeHook;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.BukkitAuthPlugin;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.CrazyLoginHook;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.LogItHook;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.LoginSecurityHook;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.UltraAuthHook;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.xAuthHook;
|
||||
import com.github.games647.fastlogin.bukkit.listener.BukkitJoinListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.BungeeCordListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.EncryptionPacketListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.ProtocolSupportListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.StartPacketListener;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.reflect.ClassPath;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyPair;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
@@ -32,7 +39,7 @@ 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 {
|
||||
|
||||
|
||||
private static final int WORKER_THREADS = 5;
|
||||
|
||||
public static UUID parseId(String withoutDashes) {
|
||||
@@ -46,9 +53,9 @@ public class FastLoginBukkit extends JavaPlugin {
|
||||
//provide a immutable key pair to be thread safe | used for encrypting and decrypting traffic
|
||||
private final KeyPair keyPair = EncryptionUtil.generateKeyPair();
|
||||
|
||||
|
||||
private boolean bungeeCord;
|
||||
protected boolean bungeeCord;
|
||||
private Storage storage;
|
||||
private boolean serverStarted;
|
||||
|
||||
//this map is thread-safe for async access (Packet Listener)
|
||||
//SafeCacheBuilder is used in order to be version independent
|
||||
@@ -67,9 +74,20 @@ public class FastLoginBukkit extends JavaPlugin {
|
||||
|
||||
private BukkitAuthPlugin authPlugin;
|
||||
private final MojangApiConnector mojangApiConnector = new MojangApiConnector(this);
|
||||
|
||||
private PasswordGenerator passwordGenerator = new DefaultPasswordGenerator();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
try {
|
||||
if (ClassUtil.isPresent("org.spigotmc.SpigotConfig")) {
|
||||
bungeeCord = (boolean) FuzzyReflection.fromClass(Class.forName("org.spigotmc.SpigotConfig"))
|
||||
.getFieldByType("bungee", Boolean.TYPE).get(null);
|
||||
}
|
||||
} catch (Exception | NoSuchMethodError ex) {
|
||||
getLogger().warning("Cannot check bungeecord support. You use a non-spigot build");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
saveDefaultConfig();
|
||||
|
||||
if (getServer().getOnlineMode()) {
|
||||
@@ -79,18 +97,9 @@ public class FastLoginBukkit extends JavaPlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
bungeeCord = Bukkit.spigot().getConfig().getBoolean("settings.bungeecord");
|
||||
boolean hookFound = registerHooks();
|
||||
if (bungeeCord) {
|
||||
getLogger().info("BungeeCord setting detected. No auth plugin is required");
|
||||
} else if (!hookFound) {
|
||||
getLogger().info("No auth plugin were found and bungeecord is deactivated. "
|
||||
+ "Either one or both of the checks have to pass in order to use this plugin");
|
||||
setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bungeeCord) {
|
||||
setServerStarted();
|
||||
|
||||
//check for incoming messages from the bungeecord version of this plugin
|
||||
getServer().getMessenger().registerIncomingPluginChannel(this, getName(), new BungeeCordListener(this));
|
||||
getServer().getMessenger().registerOutgoingPluginChannel(this, getName());
|
||||
@@ -129,6 +138,22 @@ public class FastLoginBukkit extends JavaPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
//delay dependency setup because we load the plugin very early where plugins are initialized yet
|
||||
getServer().getScheduler().runTask(this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean hookFound = registerHooks();
|
||||
if (bungeeCord) {
|
||||
getLogger().info("BungeeCord setting detected. No auth plugin is required");
|
||||
} else if (!hookFound) {
|
||||
getLogger().warning("No auth plugin were found by this plugin "
|
||||
+ "(other plugins could hook into this after the intialization of this plugin)"
|
||||
+ "and bungeecord is deactivated. "
|
||||
+ "Either one or both of the checks have to pass in order to use this plugin");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
getServer().getPluginManager().registerEvents(new BukkitJoinListener(this), this);
|
||||
|
||||
//register commands using a unique name
|
||||
@@ -151,8 +176,12 @@ public class FastLoginBukkit extends JavaPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
public String generateStringPassword() {
|
||||
return RandomStringUtils.random(8, true, true);
|
||||
public String generateStringPassword(Player player) {
|
||||
return passwordGenerator.getRandomPassword(player);
|
||||
}
|
||||
|
||||
public void setPasswordGenerator(PasswordGenerator passwordGenerator) {
|
||||
this.passwordGenerator = passwordGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,9 +214,21 @@ public class FastLoginBukkit extends JavaPlugin {
|
||||
* @return interface to any supported auth plugin
|
||||
*/
|
||||
public BukkitAuthPlugin getAuthPlugin() {
|
||||
if (authPlugin == null) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ex) {
|
||||
Logger.getLogger(FastLoginBukkit.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
return authPlugin;
|
||||
}
|
||||
|
||||
public void setAuthPluginHook(BukkitAuthPlugin authPlugin) {
|
||||
this.authPlugin = authPlugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the a connection in order to access important features from the Mojang API.
|
||||
*
|
||||
@@ -200,22 +241,20 @@ public class FastLoginBukkit extends JavaPlugin {
|
||||
private boolean registerHooks() {
|
||||
BukkitAuthPlugin authPluginHook = null;
|
||||
try {
|
||||
String hooksPackage = this.getClass().getPackage().getName() + ".hooks";
|
||||
//Look through all classes in the hooks package and look for supporting plugins on the server
|
||||
for (ClassPath.ClassInfo clazzInfo : ClassPath.from(getClassLoader()).getTopLevelClasses(hooksPackage)) {
|
||||
//remove the hook suffix
|
||||
String pluginName = clazzInfo.getSimpleName().replace("Hook", "");
|
||||
Class<?> clazz = clazzInfo.load();
|
||||
List<Class<? extends BukkitAuthPlugin>> supportedHooks = Lists.newArrayList(AuthMeHook.class
|
||||
, CrazyLoginHook.class, LogItHook.class, LoginSecurityHook.class, UltraAuthHook.class
|
||||
, xAuthHook.class);
|
||||
for (Class<? extends BukkitAuthPlugin> clazz : supportedHooks) {
|
||||
String pluginName = clazz.getSimpleName().replace("Hook", "");
|
||||
//uses only member classes which uses AuthPlugin interface (skip interfaces)
|
||||
if (BukkitAuthPlugin.class.isAssignableFrom(clazz)
|
||||
//check only for enabled plugins. A single plugin could be disabled by plugin managers
|
||||
&& getServer().getPluginManager().isPluginEnabled(pluginName)) {
|
||||
authPluginHook = (BukkitAuthPlugin) clazz.newInstance();
|
||||
if (getServer().getPluginManager().getPlugin(pluginName) != null) {
|
||||
//check only for enabled plugins. A single plugin could be disabled by plugin managers
|
||||
authPluginHook = clazz.newInstance();
|
||||
getLogger().log(Level.INFO, "Hooking into auth plugin: {0}", pluginName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (InstantiationException | IllegalAccessException | IOException ex) {
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
getLogger().log(Level.SEVERE, "Couldn't load the integration class", ex);
|
||||
}
|
||||
|
||||
@@ -232,4 +271,20 @@ public class FastLoginBukkit extends JavaPlugin {
|
||||
public boolean isBungeeCord() {
|
||||
return bungeeCord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait before the server is fully started. This is workaround, because connections right on startup are not
|
||||
* injected by ProtocolLib
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isServerFullyStarted() {
|
||||
return serverStarted;
|
||||
}
|
||||
|
||||
public void setServerStarted() {
|
||||
if (!this.serverStarted) {
|
||||
this.serverStarted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
package com.github.games647.fastlogin.bukkit;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.hooks.BukkitAuthPlugin;
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
|
||||
public class ForceLoginTask implements Runnable {
|
||||
|
||||
protected final FastLoginBukkit plugin;
|
||||
private final Player player;
|
||||
protected final Player player;
|
||||
|
||||
public ForceLoginTask(FastLoginBukkit plugin, Player player) {
|
||||
this.plugin = plugin;
|
||||
@@ -20,56 +25,64 @@ public class ForceLoginTask implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!player.isOnline()) {
|
||||
if (!isOnlineThreadSafe()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//remove the bungeecord identifier
|
||||
//remove the bungeecord identifier if there is ones
|
||||
String id = '/' + player.getAddress().getAddress().getHostAddress() + ':' + player.getAddress().getPort();
|
||||
PlayerSession session = plugin.getSessions().get(id);
|
||||
|
||||
//blacklist this target player for BungeeCord Id brute force attacks
|
||||
player.setMetadata(plugin.getName(), new FixedMetadataValue(plugin, true));
|
||||
//check if it's the same player as we checked before
|
||||
|
||||
final BukkitAuthPlugin authPlugin = plugin.getAuthPlugin();
|
||||
if (session == null || !player.getName().equals(session.getUsername()) || authPlugin == null) {
|
||||
return;
|
||||
}
|
||||
BukkitAuthPlugin authPlugin = plugin.getAuthPlugin();
|
||||
|
||||
Storage storage = plugin.getStorage();
|
||||
PlayerProfile playerProfile = null;
|
||||
if (storage != null) {
|
||||
playerProfile = storage.getProfile(session.getUsername(), false);
|
||||
playerProfile = storage.getProfile(player.getName(), false);
|
||||
}
|
||||
|
||||
if (session.isVerified()) {
|
||||
boolean success = true;
|
||||
if (session == null) {
|
||||
//cracked player
|
||||
if (playerProfile != null) {
|
||||
playerProfile.setUuid(session.getUuid());
|
||||
playerProfile.setPremium(true);
|
||||
playerProfile.setUuid(null);
|
||||
playerProfile.setPremium(false);
|
||||
storage.save(playerProfile);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
if (session.needsRegistration()) {
|
||||
if (forceRegister(authPlugin, player)) {
|
||||
storage.save(playerProfile);
|
||||
}
|
||||
} else {
|
||||
if (forceLogin(authPlugin, player)) {
|
||||
storage.save(playerProfile);
|
||||
//check if it's the same player as we checked before
|
||||
} else if (player.getName().equals(session.getUsername())) {
|
||||
//premium player
|
||||
if (authPlugin == null) {
|
||||
//maybe only bungeecord plugin
|
||||
sendSuccessNotification();
|
||||
} else {
|
||||
boolean success = false;
|
||||
if (isOnlineThreadSafe() && session.isVerified()) {
|
||||
if (session.needsRegistration()) {
|
||||
success = forceRegister(authPlugin, player);
|
||||
} else {
|
||||
success = forceLogin(authPlugin, player);
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
//update only on success to prevent corrupt data
|
||||
if (playerProfile != null) {
|
||||
playerProfile.setUuid(session.getUuid());
|
||||
//save cracked players too
|
||||
playerProfile.setPremium(session.isVerified());
|
||||
storage.save(playerProfile);
|
||||
}
|
||||
|
||||
sendSuccessNotification();
|
||||
}
|
||||
}
|
||||
} else if (playerProfile != null) {
|
||||
storage.save(playerProfile);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean forceRegister(BukkitAuthPlugin authPlugin, Player player) {
|
||||
plugin.getLogger().log(Level.FINE, "Register player {0}", player.getName());
|
||||
|
||||
String generatedPassword = plugin.generateStringPassword();
|
||||
String generatedPassword = plugin.generateStringPassword(player);
|
||||
boolean success = authPlugin.forceRegister(player, generatedPassword);
|
||||
player.sendMessage(ChatColor.DARK_GREEN + "Auto registered with password: " + generatedPassword);
|
||||
player.sendMessage(ChatColor.DARK_GREEN + "You may want change it?");
|
||||
@@ -82,4 +95,30 @@ public class ForceLoginTask implements Runnable {
|
||||
player.sendMessage(ChatColor.DARK_GREEN + "Auto logged in");
|
||||
return success;
|
||||
}
|
||||
|
||||
private void sendSuccessNotification() {
|
||||
if (plugin.isBungeeCord()) {
|
||||
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
|
||||
dataOutput.writeUTF("SUCCESS");
|
||||
|
||||
player.sendPluginMessage(plugin, plugin.getName(), dataOutput.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOnlineThreadSafe() {
|
||||
//the playerlist isn't thread-safe
|
||||
Future<Boolean> onlineFuture = Bukkit.getScheduler().callSyncMethod(plugin, new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
return player.isOnline();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
return onlineFuture.get();
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to perform thread-safe online check", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.github.games647.fastlogin.bukkit;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface PasswordGenerator {
|
||||
|
||||
String getRandomPassword(Player player);
|
||||
}
|
||||
@@ -68,7 +68,7 @@ public class PlayerProfile {
|
||||
this.lastIp = lastIp;
|
||||
}
|
||||
|
||||
public long getLastLogin() {
|
||||
public synchronized long getLastLogin() {
|
||||
return lastLogin;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,15 +29,12 @@ public class CrackedCommand implements CommandExecutor {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Player player = (Player) sender;
|
||||
// UUID uuid = player.getUniqueId();
|
||||
|
||||
if (plugin.isBungeeCord()) {
|
||||
notifiyBungeeCord((Player) sender);
|
||||
notifiyBungeeCord(sender, sender.getName());
|
||||
sender.sendMessage(ChatColor.YELLOW + "Sending request...");
|
||||
} else {
|
||||
//todo: load async if it's not in the cache anymore
|
||||
final PlayerProfile profile = plugin.getStorage().getProfile(player.getName(), true);
|
||||
final PlayerProfile profile = plugin.getStorage().getProfile(sender.getName(), true);
|
||||
if (profile.isPremium()) {
|
||||
sender.sendMessage(ChatColor.DARK_GREEN + "Removed from the list of premium players");
|
||||
profile.setPremium(false);
|
||||
@@ -55,27 +52,58 @@ public class CrackedCommand implements CommandExecutor {
|
||||
|
||||
return true;
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "NOT IMPLEMENTED YET");
|
||||
//todo:
|
||||
// String playerName = args[0];
|
||||
// boolean existed = plugin.getEnabledPremium().remove(playerName);
|
||||
// if (existed) {
|
||||
// sender.sendMessage(ChatColor.DARK_GREEN + "Removed from the list of premium players");
|
||||
// notifiyBungeeCord((Player) sender);
|
||||
// } else {
|
||||
// sender.sendMessage(ChatColor.DARK_RED + "User is not in the premium list");
|
||||
// }
|
||||
if (!sender.hasPermission(command.getPermission() + ".other")) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Not enough permissions");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.isBungeeCord()) {
|
||||
notifiyBungeeCord(sender, args[0]);
|
||||
sender.sendMessage(ChatColor.YELLOW + "Sending request for player " + args[0] + "...");
|
||||
} else {
|
||||
//todo: load async if it's not in the cache anymore
|
||||
final PlayerProfile profile = plugin.getStorage().getProfile(args[0], true);
|
||||
if (profile == null) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Player not in the database");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (profile.isPremium()) {
|
||||
sender.sendMessage(ChatColor.DARK_GREEN + "Removed from the list of premium players");
|
||||
profile.setPremium(false);
|
||||
profile.setUuid(null);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
plugin.getStorage().save(profile);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Player is not in the premium list");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void notifiyBungeeCord(Player target) {
|
||||
private void notifiyBungeeCord(CommandSender sender, String target) {
|
||||
if (sender instanceof Player) {
|
||||
notifiyBungeeCord(sender, target);
|
||||
} else {
|
||||
//todo: add console support
|
||||
// Player firstPlayer = Iterables.getFirst(Bukkit.getOnlinePlayers(), null);
|
||||
// notifiyBungeeCord(firstPlayer, target);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifiyBungeeCord(Player sender, String target) {
|
||||
if (plugin.isBungeeCord()) {
|
||||
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
|
||||
dataOutput.writeUTF("OFF");
|
||||
dataOutput.writeUTF(target);
|
||||
|
||||
target.sendPluginMessage(plugin, plugin.getName(), dataOutput.toByteArray());
|
||||
plugin.getLogger().info("No player online to send a plugin message to the proxy");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,15 +34,12 @@ public class PremiumCommand implements CommandExecutor {
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
// UUID uuid = player.getUniqueId();
|
||||
|
||||
if (plugin.isBungeeCord()) {
|
||||
notifiyBungeeCord(player);
|
||||
notifiyBungeeCord(sender, sender.getName());
|
||||
sender.sendMessage(ChatColor.YELLOW + "Sending request...");
|
||||
} else {
|
||||
// //todo: load async if it's not in the cache anymore
|
||||
final PlayerProfile profile = plugin.getStorage().getProfile(player.getName(), true);
|
||||
final PlayerProfile profile = plugin.getStorage().getProfile(sender.getName(), true);
|
||||
if (profile.isPremium()) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "You are already on the premium list");
|
||||
} else {
|
||||
@@ -54,34 +51,66 @@ public class PremiumCommand implements CommandExecutor {
|
||||
plugin.getStorage().save(profile);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
sender.sendMessage(ChatColor.DARK_GREEN + "Added to the list of premium players");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "NOT IMPLEMENTED YET");
|
||||
//todo: async load
|
||||
// String playerName = args[0];
|
||||
// boolean didntexist = plugin.getEnabledPremium().add(playerName);
|
||||
// if (!didntexist) {
|
||||
// sender.sendMessage(ChatColor.DARK_RED + "You are already on the premium list");
|
||||
// } else {
|
||||
// sender.sendMessage(ChatColor.DARK_GREEN + "Added to the list of premium players");
|
||||
// }
|
||||
// notifiyBungeeCord();
|
||||
if (!sender.hasPermission(command.getPermission() + ".other")) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Not enough permissions");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.isBungeeCord()) {
|
||||
notifiyBungeeCord(sender, args[0]);
|
||||
sender.sendMessage(ChatColor.YELLOW + "Sending request...");
|
||||
} else {
|
||||
//todo: load async if it's not in the cache anymore
|
||||
final PlayerProfile profile = plugin.getStorage().getProfile(args[0], true);
|
||||
if (profile == null) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Player not in the database");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (profile.isPremium()) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Player is already on the premium list");
|
||||
} else {
|
||||
//todo: resolve uuid
|
||||
profile.setPremium(true);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
plugin.getStorage().save(profile);
|
||||
}
|
||||
});
|
||||
|
||||
sender.sendMessage(ChatColor.DARK_GREEN + "Added to the list of premium players");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void notifiyBungeeCord(Player target) {
|
||||
private void notifiyBungeeCord(CommandSender sender, String target) {
|
||||
if (sender instanceof Player) {
|
||||
notifiyBungeeCord(sender, target);
|
||||
} else {
|
||||
//todo: add console support
|
||||
// Player firstPlayer = Iterables.getFirst(Bukkit.getOnlinePlayers(), null);
|
||||
// notifiyBungeeCord(firstPlayer, target);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifiyBungeeCord(Player sender, String target) {
|
||||
if (plugin.isBungeeCord()) {
|
||||
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
|
||||
dataOutput.writeUTF("ON");
|
||||
dataOutput.writeUTF(target);
|
||||
|
||||
target.sendPluginMessage(plugin, plugin.getName(), dataOutput.toByteArray());
|
||||
sender.sendPluginMessage(plugin, plugin.getName(), dataOutput.toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.github.games647.fastlogin.bukkit.hooks;
|
||||
|
||||
import com.avaje.ebeaninternal.api.ClassUtil;
|
||||
|
||||
import fr.xephi.authme.api.API;
|
||||
import fr.xephi.authme.api.NewAPI;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -13,10 +16,21 @@ import org.bukkit.entity.Player;
|
||||
*/
|
||||
public class AuthMeHook implements BukkitAuthPlugin {
|
||||
|
||||
private final boolean isNewAPIAvailable;
|
||||
|
||||
public AuthMeHook() {
|
||||
this.isNewAPIAvailable = ClassUtil.isPresent("fr.xephi.authme.api.NewAPI");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceLogin(Player player) {
|
||||
//skips registration and login
|
||||
NewAPI.getInstance().forceLogin(player);
|
||||
if (isNewAPIAvailable) {
|
||||
NewAPI.getInstance().forceLogin(player);
|
||||
} else {
|
||||
API.forceLogin(player);
|
||||
}
|
||||
|
||||
//commented because the operation above is performed async -> race conditions
|
||||
// return NewAPI.getInstance().isAuthenticated(player);
|
||||
return true;
|
||||
@@ -24,12 +38,22 @@ public class AuthMeHook implements BukkitAuthPlugin {
|
||||
|
||||
@Override
|
||||
public boolean isRegistered(String playerName) throws Exception {
|
||||
return NewAPI.getInstance().isRegistered(playerName);
|
||||
if (isNewAPIAvailable) {
|
||||
return NewAPI.getInstance().isRegistered(playerName);
|
||||
} else {
|
||||
return API.isRegistered(playerName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceRegister(Player player, String password) {
|
||||
NewAPI.getInstance().forceRegister(player, password);
|
||||
if (isNewAPIAvailable) {
|
||||
NewAPI.getInstance().forceRegister(player, password);
|
||||
} else {
|
||||
API.registerPlayer(player.getName(), password);
|
||||
forceLogin(player);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class CrazyLoginHook implements BukkitAuthPlugin {
|
||||
|
||||
try {
|
||||
LoginPlayerData result = future.get();
|
||||
if (result != null) {
|
||||
if (result != null && result.isLoggedIn()) {
|
||||
//SQL-Queries should run async
|
||||
crazyLoginPlugin.getCrazyDatabase().saveWithoutPassword(result);
|
||||
return true;
|
||||
@@ -88,7 +88,7 @@ public class CrazyLoginHook implements BukkitAuthPlugin {
|
||||
|
||||
@Override
|
||||
public boolean forceRegister(final Player player, String password) {
|
||||
final CrazyLoginDataDatabase crazyDatabase = crazyLoginPlugin.getCrazyDatabase();
|
||||
CrazyLoginDataDatabase crazyDatabase = crazyLoginPlugin.getCrazyDatabase();
|
||||
|
||||
//this executes a sql query and accesses only thread safe collections so we can run it async
|
||||
LoginPlayerData playerData = crazyLoginPlugin.getPlayerData(player.getName());
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
||||
package com.github.games647.fastlogin.bukkit.hooks;
|
||||
|
||||
import io.github.lucaseasedup.logit.CancelledState;
|
||||
import io.github.lucaseasedup.logit.LogItCore;
|
||||
import io.github.lucaseasedup.logit.account.Account;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Github: https://github.com/XziomekX/LogIt
|
||||
* Project page:
|
||||
*
|
||||
* Bukkit: Unknown
|
||||
* Spigot: Unknown
|
||||
*/
|
||||
public class LogItHook implements BukkitAuthPlugin {
|
||||
|
||||
@Override
|
||||
public boolean forceLogin(Player player) {
|
||||
return LogItCore.getInstance().getSessionManager().startSession(player) == CancelledState.NOT_CANCELLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered(String playerName) throws Exception {
|
||||
return LogItCore.getInstance().getAccountManager().isRegistered(playerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceRegister(Player player, String password) {
|
||||
Account account = new Account(player.getName());
|
||||
account.changePassword(password);
|
||||
account.setLastActiveDate(System.currentTimeMillis() / 1000);
|
||||
account.setRegistrationDate(System.currentTimeMillis() / 1000);
|
||||
return LogItCore.getInstance().getAccountManager().insertAccount(account) == CancelledState.NOT_CANCELLED;
|
||||
}
|
||||
}
|
||||
@@ -72,15 +72,21 @@ public class LoginSecurityHook implements BukkitAuthPlugin {
|
||||
|
||||
@Override
|
||||
public boolean forceRegister(final Player player, final String password) {
|
||||
final DataManager dataManager = securityPlugin.data;
|
||||
DataManager dataManager = securityPlugin.data;
|
||||
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
final String uuidString = playerUUID.toString().replace("-", "");
|
||||
final InetAddress ipAddress = player.getAddress().getAddress();
|
||||
final String passwordHash = securityPlugin.hasher.hash(password);
|
||||
String uuidString = playerUUID.toString().replace("-", "");
|
||||
InetAddress ipAddress = player.getAddress().getAddress();
|
||||
String passwordHash = securityPlugin.hasher.hash(password);
|
||||
|
||||
//this executes a sql query without interacting with other parts so we can run it async.
|
||||
dataManager.register(uuidString, passwordHash, securityPlugin.hasher.getTypeId(), ipAddress.toString());
|
||||
return forceLogin(player);
|
||||
String storedPassword = dataManager.getPassword(uuidString);
|
||||
if (storedPassword != null && storedPassword.equals(passwordHash)) {
|
||||
//the register method silents any excpetion so check if our entry was saved
|
||||
return forceLogin(player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class RoyalAuthHook implements BukkitAuthPlugin {
|
||||
//not thread-safe
|
||||
authPlayer.login();
|
||||
|
||||
return true;
|
||||
return authPlayer.isLoggedIn();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,11 +32,10 @@ public class xAuthHook implements BukkitAuthPlugin {
|
||||
xAuthPlayer xAuthPlayer = xAuthPlugin.getPlayerManager().getPlayer(player);
|
||||
if (xAuthPlayer != null) {
|
||||
//we checked that the player is premium (paid account)
|
||||
//unprotect the inventory, op status...
|
||||
xAuthPlayer.setPremium(true);
|
||||
|
||||
xAuthPlugin.getPlayerManager().doLogin(xAuthPlayer);
|
||||
return true;
|
||||
//unprotect the inventory, op status...
|
||||
return xAuthPlugin.getPlayerManager().doLogin(xAuthPlayer);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -71,10 +70,7 @@ public class xAuthHook implements BukkitAuthPlugin {
|
||||
boolean registerSuccess = xAuthPlugin.getAuthClass(xAuthPlayer)
|
||||
.adminRegister(player.getName(), password, null);
|
||||
|
||||
if (registerSuccess) {
|
||||
//login in the player after registration
|
||||
return forceLogin(player);
|
||||
}
|
||||
return registerSuccess;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -82,7 +78,13 @@ public class xAuthHook implements BukkitAuthPlugin {
|
||||
});
|
||||
|
||||
try {
|
||||
return future.get();
|
||||
boolean success = future.get();
|
||||
if (success) {
|
||||
//login in the player after registration
|
||||
return forceLogin(player);
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
xAuthPlugin.getLogger().log(Level.SEVERE, "Failed to forceLogin", ex);
|
||||
return false;
|
||||
|
||||
@@ -9,8 +9,11 @@ import com.github.games647.fastlogin.bukkit.PlayerSession;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
/**
|
||||
@@ -19,7 +22,7 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
||||
*/
|
||||
public class BukkitJoinListener implements Listener {
|
||||
|
||||
private static final long DELAY_LOGIN = 1 * 20L / 2;
|
||||
private static final long DELAY_LOGIN = 20L / 2;
|
||||
|
||||
protected final FastLoginBukkit plugin;
|
||||
|
||||
@@ -27,12 +30,19 @@ public class BukkitJoinListener implements Listener {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
|
||||
if (loginEvent.getResult() == Result.ALLOWED && !plugin.isServerFullyStarted()) {
|
||||
loginEvent.disallow(Result.KICK_OTHER, "§cServer is not fully started yet. Please retry");
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
|
||||
final Player player = joinEvent.getPlayer();
|
||||
Player player = joinEvent.getPlayer();
|
||||
|
||||
//removing the session because we now use it
|
||||
final PlayerSession session = plugin.getSessions().get(player.getAddress().toString());
|
||||
PlayerSession session = plugin.getSessions().get(player.getAddress().toString());
|
||||
if (session != null && plugin.getConfig().getBoolean("forwardSkin")) {
|
||||
WrappedGameProfile gameProfile = WrappedGameProfile.fromPlayer(player);
|
||||
WrappedSignedProperty skin = session.getSkin();
|
||||
@@ -41,13 +51,15 @@ public class BukkitJoinListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
//Wait before auth plugin and we received a message from BungeeCord initializes the player
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, new ForceLoginTask(plugin, player), DELAY_LOGIN);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
|
||||
final Player player = quitEvent.getPlayer();
|
||||
Player player = quitEvent.getPlayer();
|
||||
|
||||
//prevent memory leaks
|
||||
player.removeMetadata(plugin.getName(), plugin);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.github.games647.fastlogin.bukkit.listener;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.bukkit.ForceLoginTask;
|
||||
import com.github.games647.fastlogin.bukkit.PlayerSession;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.BukkitAuthPlugin;
|
||||
import com.google.common.base.Charsets;
|
||||
@@ -54,17 +55,24 @@ public class BungeeCordListener implements PluginMessageListener {
|
||||
final Player checkedPlayer = plugin.getServer().getPlayerExact(playerName);
|
||||
//fail if target player is blacklisted because already authed or wrong bungeecord id
|
||||
if (checkedPlayer != null && !checkedPlayer.hasMetadata(plugin.getName())) {
|
||||
//blacklist this target player for BungeeCord Id brute force attacks
|
||||
player.setMetadata(plugin.getName(), new FixedMetadataValue(plugin, true));
|
||||
|
||||
//bungeecord UUID
|
||||
long mostSignificantBits = dataInput.readLong();
|
||||
long leastSignificantBits = dataInput.readLong();
|
||||
UUID sourceId = new UUID(mostSignificantBits, leastSignificantBits);
|
||||
plugin.getLogger().log(Level.FINEST, "Received proxy id {0} from {1}", new Object[]{sourceId, player});
|
||||
|
||||
//fail if BungeeCord support is disabled (id = null)
|
||||
if (sourceId.equals(proxyId)) {
|
||||
final PlayerSession playerSession = new PlayerSession(playerName);
|
||||
final String id = '/' + checkedPlayer.getAddress().getAddress().getHostAddress() + ':'
|
||||
+ checkedPlayer.getAddress().getPort();
|
||||
if ("AUTO_LOGIN".equalsIgnoreCase(subchannel)) {
|
||||
playerSession.setVerified(true);
|
||||
playerSession.setRegistered(true);
|
||||
plugin.getSessions().put(checkedPlayer.getAddress().toString(), playerSession);
|
||||
plugin.getSessions().put(id, playerSession);
|
||||
} else if ("AUTO_REGISTER".equalsIgnoreCase(subchannel)) {
|
||||
playerSession.setVerified(true);
|
||||
|
||||
@@ -75,7 +83,7 @@ public class BungeeCordListener implements PluginMessageListener {
|
||||
try {
|
||||
//we need to check if the player is registered on Bukkit too
|
||||
if (authPlugin != null && !authPlugin.isRegistered(playerName)) {
|
||||
plugin.getSessions().put(checkedPlayer.getAddress().toString(), playerSession);
|
||||
plugin.getSessions().put(id, playerSession);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to query isRegistered", ex);
|
||||
@@ -83,9 +91,8 @@ public class BungeeCordListener implements PluginMessageListener {
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
//blacklist target for the current login
|
||||
checkedPlayer.setMetadata(plugin.getName(), new FixedMetadataValue(plugin, true));
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new ForceLoginTask(plugin, player));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ public class EncryptionPacketListener extends PacketAdapter {
|
||||
*/
|
||||
@Override
|
||||
public void onPacketReceiving(PacketEvent packetEvent) {
|
||||
System.out.println("ENCRYPTION REQUEST");
|
||||
Player player = packetEvent.getPlayer();
|
||||
|
||||
//the player name is unknown to ProtocolLib (so getName() doesn't work) - now uses ip:port as key
|
||||
|
||||
@@ -25,6 +25,7 @@ public class ProtocolSupportListener implements Listener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onLoginStart(PlayerLoginStartEvent loginStartEvent) {
|
||||
plugin.setServerStarted();
|
||||
if (loginStartEvent.isLoginDenied()) {
|
||||
return;
|
||||
}
|
||||
@@ -34,6 +35,11 @@ public class ProtocolSupportListener implements Listener {
|
||||
//remove old data every time on a new login in order to keep the session only for one person
|
||||
plugin.getSessions().remove(username);
|
||||
|
||||
BukkitAuthPlugin authPlugin = plugin.getAuthPlugin();
|
||||
if (authPlugin == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerProfile playerProfile = plugin.getStorage().getProfile(username, true);
|
||||
if (playerProfile != null) {
|
||||
if (playerProfile.isPremium()) {
|
||||
@@ -42,7 +48,6 @@ public class ProtocolSupportListener implements Listener {
|
||||
}
|
||||
} else if (playerProfile.getUserId() == -1) {
|
||||
//user not exists in the db
|
||||
BukkitAuthPlugin authPlugin = plugin.getAuthPlugin();
|
||||
try {
|
||||
if (plugin.getConfig().getBoolean("autoRegister") && !authPlugin.isRegistered(username)) {
|
||||
UUID premiumUUID = plugin.getApiConnector().getPremiumUUID(username);
|
||||
|
||||
@@ -61,7 +61,9 @@ public class StartPacketListener extends PacketAdapter {
|
||||
*/
|
||||
@Override
|
||||
public void onPacketReceiving(PacketEvent packetEvent) {
|
||||
final Player player = packetEvent.getPlayer();
|
||||
plugin.setServerStarted();
|
||||
|
||||
Player player = packetEvent.getPlayer();
|
||||
|
||||
//this includes ip:port. Should be unique for an incoming login request with a timeout of 2 minutes
|
||||
String sessionKey = player.getAddress().toString();
|
||||
@@ -71,10 +73,16 @@ public class StartPacketListener extends PacketAdapter {
|
||||
|
||||
//player.getName() won't work at this state
|
||||
PacketContainer packet = packetEvent.getPacket();
|
||||
|
||||
String username = packet.getGameProfiles().read(0).getName();
|
||||
plugin.getLogger().log(Level.FINER, "Player {0} with {1} connecting to the server"
|
||||
, new Object[]{sessionKey, username});
|
||||
|
||||
BukkitAuthPlugin authPlugin = plugin.getAuthPlugin();
|
||||
if (authPlugin == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerProfile playerProfile = plugin.getStorage().getProfile(username, true);
|
||||
if (playerProfile != null) {
|
||||
if (playerProfile.isPremium()) {
|
||||
@@ -83,7 +91,6 @@ public class StartPacketListener extends PacketAdapter {
|
||||
}
|
||||
} else if (playerProfile.getUserId() == -1) {
|
||||
//user not exists in the db
|
||||
BukkitAuthPlugin authPlugin = plugin.getAuthPlugin();
|
||||
try {
|
||||
if (plugin.getConfig().getBoolean("autoRegister") && !authPlugin.isRegistered(username)) {
|
||||
UUID premiumUUID = plugin.getApiConnector().getPremiumUUID(username);
|
||||
|
||||
@@ -11,18 +11,22 @@ description: |
|
||||
website: ${project.url}
|
||||
dev-url: ${project.url}
|
||||
|
||||
# Load the plugin as early as possible to inject it for all players
|
||||
load: STARTUP
|
||||
|
||||
# Without Protocollib the plugin does not work at all
|
||||
depend: [ProtocolLib]
|
||||
|
||||
softdepend:
|
||||
- ProtocolSupport
|
||||
# Auth plugins
|
||||
- xAuth
|
||||
- AuthMe
|
||||
- CrazyLogin
|
||||
- LoginSecurity
|
||||
- RoyalAuth
|
||||
- UltraAuth
|
||||
# - xAuth
|
||||
# - AuthMe
|
||||
# - LogIt
|
||||
# - CrazyLogin
|
||||
# - LoginSecurity
|
||||
# - RoyalAuth
|
||||
# - UltraAuth
|
||||
|
||||
commands:
|
||||
${project.parent.name}:
|
||||
@@ -31,9 +35,9 @@ commands:
|
||||
usage: /<command> [player]
|
||||
permission: ${project.artifactId}.command.premium
|
||||
|
||||
unpremium:
|
||||
cracked:
|
||||
description: 'Label the invoker or the player specified as cracked if he was marked premium before'
|
||||
aliases: [cracked]
|
||||
aliases: [unpremium]
|
||||
usage: /<command> [player]
|
||||
permission: ${project.artifactId}.command.unpremium
|
||||
|
||||
@@ -47,11 +51,11 @@ permissions:
|
||||
children:
|
||||
${project.artifactId}.command.premium: true
|
||||
|
||||
${project.artifactId}.command.unpremium:
|
||||
${project.artifactId}.command.cracked:
|
||||
description: 'Label themselves as cracked'
|
||||
default: true
|
||||
|
||||
${project.artifactId}.command..unpremium.other:
|
||||
${project.artifactId}.command..cracked.other:
|
||||
description: 'Label others as cracked'
|
||||
children:
|
||||
${project.artifactId}.command.unpremium: true
|
||||
${project.artifactId}.command.cracked: true
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.games647</groupId>
|
||||
<artifactId>fastlogin</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.3</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.github.games647.fastlogin.bungee;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.listener.PlayerConnectionListener;
|
||||
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthHook;
|
||||
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthPlugin;
|
||||
import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
|
||||
import java.io.File;
|
||||
@@ -13,8 +15,9 @@ import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
|
||||
import net.md_5.bungee.Util;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
import net.md_5.bungee.config.ConfigurationProvider;
|
||||
@@ -25,17 +28,13 @@ import net.md_5.bungee.config.YamlConfiguration;
|
||||
*/
|
||||
public class FastLoginBungee extends Plugin {
|
||||
|
||||
public static UUID parseId(String withoutDashes) {
|
||||
return UUID.fromString(withoutDashes.substring(0, 8)
|
||||
+ "-" + withoutDashes.substring(8, 12)
|
||||
+ "-" + withoutDashes.substring(12, 16)
|
||||
+ "-" + withoutDashes.substring(16, 20)
|
||||
+ "-" + withoutDashes.substring(20, 32));
|
||||
}
|
||||
|
||||
private static final char[] CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
.toCharArray();
|
||||
|
||||
public static UUID parseId(String withoutDashes) {
|
||||
return Util.getUUID(withoutDashes);
|
||||
}
|
||||
|
||||
private BungeeAuthPlugin bungeeAuthPlugin;
|
||||
private final MojangApiConnector mojangApiConnector = new MojangApiConnector(this);
|
||||
private Storage storage;
|
||||
@@ -88,6 +87,7 @@ public class FastLoginBungee extends Plugin {
|
||||
|
||||
//events
|
||||
getProxy().getPluginManager().registerListener(this, new PlayerConnectionListener(this));
|
||||
getProxy().getPluginManager().registerListener(this, new PluginMessageListener(this));
|
||||
|
||||
//this is required to listen to messages from the server
|
||||
getProxy().registerChannel(getDescription().getName());
|
||||
|
||||
@@ -13,60 +13,62 @@ public class ForceLoginTask implements Runnable {
|
||||
|
||||
private final FastLoginBungee plugin;
|
||||
private final ProxiedPlayer player;
|
||||
private final Server server;
|
||||
|
||||
public ForceLoginTask(FastLoginBungee plugin, ProxiedPlayer player) {
|
||||
public ForceLoginTask(FastLoginBungee plugin, ProxiedPlayer player, Server server) {
|
||||
this.plugin = plugin;
|
||||
this.player = player;
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerProfile playerProfile = plugin.getStorage().getProfile(player.getName(), false);
|
||||
|
||||
if (playerProfile.getUserId() == -1) {
|
||||
playerProfile.setPremium(player.getPendingConnection().isOnlineMode());
|
||||
if (player.getPendingConnection().isOnlineMode()) {
|
||||
playerProfile.setUuid(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
//force login only on success
|
||||
if (player.getPendingConnection().isOnlineMode()) {
|
||||
Server server = player.getServer();
|
||||
|
||||
boolean autoRegister = plugin.getPendingAutoRegister().remove(player.getPendingConnection()) != null;
|
||||
|
||||
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
|
||||
//subchannel name
|
||||
if (autoRegister) {
|
||||
dataOutput.writeUTF("AUTO_REGISTER");
|
||||
} else {
|
||||
dataOutput.writeUTF("AUTO_LOGIN");
|
||||
}
|
||||
|
||||
//Data is sent through a random player. We have to tell the Bukkit version of this plugin the target
|
||||
dataOutput.writeUTF(player.getName());
|
||||
|
||||
//proxy identifier to check if it's a acceptable proxy
|
||||
UUID proxyId = UUID.fromString(plugin.getProxy().getConfig().getUuid());
|
||||
dataOutput.writeLong(proxyId.getMostSignificantBits());
|
||||
dataOutput.writeLong(proxyId.getLeastSignificantBits());
|
||||
|
||||
server.sendData(plugin.getDescription().getName(), dataOutput.toByteArray());
|
||||
|
||||
BungeeAuthPlugin authPlugin = plugin.getBungeeAuthPlugin();
|
||||
if (authPlugin != null) {
|
||||
if (authPlugin == null) {
|
||||
sendBukkitLoginNotification(autoRegister);
|
||||
} else if (player.isConnected()) {
|
||||
if (autoRegister) {
|
||||
String password = plugin.generateStringPassword();
|
||||
if (authPlugin.forceRegister(player, password)) {
|
||||
plugin.getStorage().save(playerProfile);
|
||||
sendBukkitLoginNotification(autoRegister);
|
||||
}
|
||||
} else if (authPlugin.forceLogin(player)) {
|
||||
plugin.getStorage().save(playerProfile);
|
||||
sendBukkitLoginNotification(autoRegister);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//cracked player
|
||||
//update only on success to prevent corrupt data
|
||||
playerProfile.setPremium(false);
|
||||
plugin.getStorage().save(playerProfile);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendBukkitLoginNotification(boolean autoRegister) {
|
||||
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
|
||||
//subchannel name
|
||||
if (autoRegister) {
|
||||
dataOutput.writeUTF("AUTO_REGISTER");
|
||||
} else {
|
||||
dataOutput.writeUTF("AUTO_LOGIN");
|
||||
}
|
||||
|
||||
//Data is sent through a random player. We have to tell the Bukkit version of this plugin the target
|
||||
dataOutput.writeUTF(player.getName());
|
||||
|
||||
//proxy identifier to check if it's a acceptable proxy
|
||||
UUID proxyId = UUID.fromString(plugin.getProxy().getConfig().getUuid());
|
||||
dataOutput.writeLong(proxyId.getMostSignificantBits());
|
||||
dataOutput.writeLong(proxyId.getLeastSignificantBits());
|
||||
|
||||
if (server != null) {
|
||||
server.sendData(plugin.getDescription().getName(), dataOutput.toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.github.games647.fastlogin.bungee;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
@@ -9,6 +10,7 @@ import java.net.URL;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.md_5.bungee.BungeeCord;
|
||||
|
||||
public class MojangApiConnector {
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
package com.github.games647.fastlogin.bungee;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthPlugin;
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
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;
|
||||
import net.md_5.bungee.api.event.PluginMessageEvent;
|
||||
import net.md_5.bungee.api.event.PreLoginEvent;
|
||||
import net.md_5.bungee.api.event.ServerConnectedEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
/**
|
||||
* Enables online mode logins for specified users and sends
|
||||
* plugin message to the Bukkit version of this plugin in
|
||||
* order to clear that the connection is online mode.
|
||||
*/
|
||||
public class PlayerConnectionListener implements Listener {
|
||||
|
||||
protected final FastLoginBungee plugin;
|
||||
|
||||
public PlayerConnectionListener(FastLoginBungee plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPreLogin(final PreLoginEvent preLoginEvent) {
|
||||
if (preLoginEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
preLoginEvent.registerIntent(plugin);
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PendingConnection connection = preLoginEvent.getConnection();
|
||||
String username = connection.getName();
|
||||
try {
|
||||
PlayerProfile playerProfile = plugin.getStorage().getProfile(username, true);
|
||||
if (playerProfile != null) {
|
||||
if (playerProfile.isPremium()) {
|
||||
if (playerProfile.getUserId() != -1) {
|
||||
connection.setOnlineMode(true);
|
||||
}
|
||||
} else if (playerProfile.getUserId() == -1) {
|
||||
//user not exists in the db
|
||||
BungeeAuthPlugin authPlugin = plugin.getBungeeAuthPlugin();
|
||||
if (plugin.getConfiguration().getBoolean("autoRegister")
|
||||
&& (authPlugin == null || !authPlugin.isRegistered(username))) {
|
||||
UUID premiumUUID = plugin.getMojangApiConnector().getPremiumUUID(username);
|
||||
if (premiumUUID != null) {
|
||||
plugin.getLogger().log(Level.FINER, "Player {0} uses a premium username", username);
|
||||
connection.setOnlineMode(true);
|
||||
plugin.getPendingAutoRegister().put(connection, new Object());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to check premium state", ex);
|
||||
} finally {
|
||||
preLoginEvent.completeIntent(plugin);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerConnected(ServerConnectedEvent serverConnectedEvent) {
|
||||
ProxiedPlayer player = serverConnectedEvent.getPlayer();
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, new ForceLoginTask(plugin, player));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPluginMessage(PluginMessageEvent pluginMessageEvent) {
|
||||
String channel = pluginMessageEvent.getTag();
|
||||
if (pluginMessageEvent.isCancelled() || !plugin.getDescription().getName().equals(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//the client shouldn't be able to read the messages in order to know something about server internal states
|
||||
//moreover the client shouldn't be able fake a running premium check by sending the result message
|
||||
pluginMessageEvent.setCancelled(true);
|
||||
|
||||
//check if the message is sent from the server
|
||||
if (Server.class.isAssignableFrom(pluginMessageEvent.getSender().getClass())) {
|
||||
byte[] data = pluginMessageEvent.getData();
|
||||
ByteArrayDataInput dataInput = ByteStreams.newDataInput(data);
|
||||
String subchannel = dataInput.readUTF();
|
||||
|
||||
final ProxiedPlayer forPlayer = (ProxiedPlayer) pluginMessageEvent.getReceiver();
|
||||
if ("ON".equals(subchannel)) {
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerProfile playerProfile = plugin.getStorage().getProfile(forPlayer.getName(), true);
|
||||
if (playerProfile.isPremium()) {
|
||||
if (forPlayer.isConnected()) {
|
||||
TextComponent textComponent = new TextComponent("You are already on the premium list");
|
||||
textComponent.setColor(ChatColor.DARK_RED);
|
||||
forPlayer.sendMessage(textComponent);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
playerProfile.setPremium(true);
|
||||
//todo: set uuid
|
||||
plugin.getStorage().save(playerProfile);
|
||||
}
|
||||
});
|
||||
} else if ("OFF".equals(subchannel)) {
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerProfile playerProfile = plugin.getStorage().getProfile(forPlayer.getName(), true);
|
||||
if (!playerProfile.isPremium()) {
|
||||
if (forPlayer.isConnected()) {
|
||||
TextComponent textComponent = new TextComponent("You are not in the premium list");
|
||||
textComponent.setColor(ChatColor.DARK_RED);
|
||||
forPlayer.sendMessage(textComponent);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
playerProfile.setPremium(false);
|
||||
playerProfile.setUuid(null);
|
||||
//todo: set uuid
|
||||
plugin.getStorage().save(playerProfile);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ public class PlayerProfile {
|
||||
this.lastIp = lastIp;
|
||||
}
|
||||
|
||||
public long getLastLogin() {
|
||||
public synchronized long getLastLogin() {
|
||||
return lastLogin;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,14 +25,14 @@ public class BungeeAuthHook implements BungeeAuthPlugin {
|
||||
private final Tables databaseConnection = new Tables();
|
||||
|
||||
@Override
|
||||
public boolean forceLogin(final ProxiedPlayer player) {
|
||||
public boolean forceLogin(ProxiedPlayer player) {
|
||||
//https://github.com/MatteCarra/BungeeAuth/blob/master/src/me/vik1395/BungeeAuth/Login.java#L92-95
|
||||
Main.plonline.add(player.getName());
|
||||
|
||||
//renamed from ct to databaseConnection
|
||||
// databaseConnection.setStatus(player.getName(), "online");
|
||||
final Class<?>[] parameterTypes = new Class<?>[]{String.class, String.class};
|
||||
final Object[] arguments = new Object[]{player.getName(), "online"};
|
||||
Class<?>[] parameterTypes = new Class<?>[]{String.class, String.class};
|
||||
Object[] arguments = new Object[]{player.getName(), "online"};
|
||||
|
||||
try {
|
||||
callProtected("setStatus", parameterTypes, arguments);
|
||||
@@ -56,7 +56,7 @@ public class BungeeAuthHook implements BungeeAuthPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceRegister(final ProxiedPlayer player, String password) {
|
||||
public boolean forceRegister(ProxiedPlayer player, String password) {
|
||||
//https://github.com/MatteCarra/BungeeAuth/blob/master/src/me/vik1395/BungeeAuth/Register.java#L102
|
||||
PasswordHandler ph = new PasswordHandler();
|
||||
Random rand = new Random();
|
||||
@@ -77,9 +77,9 @@ public class BungeeAuthHook implements BungeeAuthPlugin {
|
||||
//renamed t to databaseConnection
|
||||
// databaseConnection.newPlayerEntry(player.getName(), hash, pType, "", lastip, regdate, lastip, lastseen);
|
||||
|
||||
final Class<?>[] parameterTypes = new Class<?>[] {String.class, String.class, String.class, String.class
|
||||
Class<?>[] parameterTypes = new Class<?>[] {String.class, String.class, String.class, String.class
|
||||
, String.class, String.class, String.class, String.class};
|
||||
final Object[] arguments = new Object[] {player.getName(), hash, pType, "", lastip, regdate, lastip, lastseen};
|
||||
Object[] arguments = new Object[] {player.getName(), hash, pType, "", lastip, regdate, lastip, lastseen};
|
||||
|
||||
try {
|
||||
callProtected("newPlayerEntry", parameterTypes, arguments);
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.github.games647.fastlogin.bungee.listener;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||
import com.github.games647.fastlogin.bungee.ForceLoginTask;
|
||||
import com.github.games647.fastlogin.bungee.PlayerProfile;
|
||||
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthPlugin;
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.UUID;
|
||||
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.event.PostLoginEvent;
|
||||
import net.md_5.bungee.api.event.PreLoginEvent;
|
||||
import net.md_5.bungee.api.event.ServerConnectedEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.connection.InitialHandler;
|
||||
import net.md_5.bungee.connection.LoginResult;
|
||||
import net.md_5.bungee.connection.LoginResult.Property;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
/**
|
||||
* Enables online mode logins for specified users and sends
|
||||
* plugin message to the Bukkit version of this plugin in
|
||||
* order to clear that the connection is online mode.
|
||||
*/
|
||||
public class PlayerConnectionListener implements Listener {
|
||||
|
||||
protected final FastLoginBungee plugin;
|
||||
|
||||
public PlayerConnectionListener(FastLoginBungee plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPreLogin(final PreLoginEvent preLoginEvent) {
|
||||
if (preLoginEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
preLoginEvent.registerIntent(plugin);
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PendingConnection connection = preLoginEvent.getConnection();
|
||||
String username = connection.getName();
|
||||
try {
|
||||
PlayerProfile playerProfile = plugin.getStorage().getProfile(username, true);
|
||||
if (playerProfile != null) {
|
||||
if (playerProfile.isPremium()) {
|
||||
if (playerProfile.getUserId() != -1) {
|
||||
connection.setOnlineMode(true);
|
||||
}
|
||||
} else if (playerProfile.getUserId() == -1) {
|
||||
//user not exists in the db
|
||||
BungeeAuthPlugin authPlugin = plugin.getBungeeAuthPlugin();
|
||||
if (plugin.getConfiguration().getBoolean("autoRegister")
|
||||
&& (authPlugin == null || !authPlugin.isRegistered(username))) {
|
||||
UUID premiumUUID = plugin.getMojangApiConnector().getPremiumUUID(username);
|
||||
if (premiumUUID != null) {
|
||||
plugin.getLogger().log(Level.FINER, "Player {0} uses a premium username", username);
|
||||
connection.setOnlineMode(true);
|
||||
plugin.getPendingAutoRegister().put(connection, new Object());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to check premium state", ex);
|
||||
} finally {
|
||||
preLoginEvent.completeIntent(plugin);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLogin(PostLoginEvent loginEvent) {
|
||||
ProxiedPlayer player = loginEvent.getPlayer();
|
||||
PendingConnection connection = player.getPendingConnection();
|
||||
String username = connection.getName();
|
||||
if (connection.isOnlineMode()) {
|
||||
PlayerProfile playerProfile = plugin.getStorage().getProfile(player.getName(), false);
|
||||
playerProfile.setUuid(player.getUniqueId());
|
||||
|
||||
//bungeecord will do this automatically so override it on disabled option
|
||||
InitialHandler initialHandler = (InitialHandler) connection;
|
||||
if (!plugin.getConfiguration().getBoolean("premiumUuid")) {
|
||||
try {
|
||||
UUID offlineUUID = UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(Charsets.UTF_8));
|
||||
|
||||
Field idField = initialHandler.getClass().getDeclaredField("uniqueId");
|
||||
idField.setAccessible(true);
|
||||
idField.set(connection, offlineUUID);
|
||||
|
||||
//bungeecord doesn't support overriding the premium uuid
|
||||
// connection.setUniqueId(offlineUUID);
|
||||
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to set offline uuid", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!plugin.getConfiguration().getBoolean("forwardSkin")) {
|
||||
//this is null on offline mode
|
||||
LoginResult loginProfile = initialHandler.getLoginProfile();
|
||||
if (loginProfile != null) {
|
||||
loginProfile.setProperties(new Property[]{});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerConnected(ServerConnectedEvent serverConnectedEvent) {
|
||||
ProxiedPlayer player = serverConnectedEvent.getPlayer();
|
||||
ForceLoginTask loginTask = new ForceLoginTask(plugin, player, serverConnectedEvent.getServer());
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, loginTask);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.github.games647.fastlogin.bungee.listener;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||
import com.github.games647.fastlogin.bungee.PlayerProfile;
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.connection.Server;
|
||||
import net.md_5.bungee.api.event.PluginMessageEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
public class PluginMessageListener implements Listener {
|
||||
|
||||
protected final FastLoginBungee plugin;
|
||||
|
||||
public PluginMessageListener(FastLoginBungee plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPluginMessage(PluginMessageEvent pluginMessageEvent) {
|
||||
String channel = pluginMessageEvent.getTag();
|
||||
if (pluginMessageEvent.isCancelled() || !plugin.getDescription().getName().equals(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//the client shouldn't be able to read the messages in order to know something about server internal states
|
||||
//moreover the client shouldn't be able fake a running premium check by sending the result message
|
||||
pluginMessageEvent.setCancelled(true);
|
||||
|
||||
//check if the message is sent from the server
|
||||
if (Server.class.isAssignableFrom(pluginMessageEvent.getSender().getClass())) {
|
||||
readMessage(pluginMessageEvent);
|
||||
}
|
||||
}
|
||||
|
||||
private void readMessage(PluginMessageEvent pluginMessageEvent) {
|
||||
byte[] data = pluginMessageEvent.getData();
|
||||
ByteArrayDataInput dataInput = ByteStreams.newDataInput(data);
|
||||
String subchannel = dataInput.readUTF();
|
||||
|
||||
final ProxiedPlayer forPlayer = (ProxiedPlayer) pluginMessageEvent.getReceiver();
|
||||
if ("ON".equals(subchannel)) {
|
||||
final String playerName = dataInput.readUTF();
|
||||
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerProfile playerProfile = plugin.getStorage().getProfile(playerName, true);
|
||||
if (playerProfile.isPremium()) {
|
||||
if (forPlayer.isConnected()) {
|
||||
TextComponent textComponent = new TextComponent("You are already on the premium list");
|
||||
textComponent.setColor(ChatColor.DARK_RED);
|
||||
forPlayer.sendMessage(textComponent);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
playerProfile.setPremium(true);
|
||||
//todo: set uuid
|
||||
plugin.getStorage().save(playerProfile);
|
||||
TextComponent textComponent = new TextComponent("Added to the list of premium players");
|
||||
textComponent.setColor(ChatColor.DARK_GREEN);
|
||||
forPlayer.sendMessage(textComponent);
|
||||
}
|
||||
});
|
||||
} else if ("OFF".equals(subchannel)) {
|
||||
final String playerName = dataInput.readUTF();
|
||||
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerProfile playerProfile = plugin.getStorage().getProfile(playerName, true);
|
||||
if (!playerProfile.isPremium()) {
|
||||
if (forPlayer.isConnected()) {
|
||||
TextComponent textComponent = new TextComponent("You are not in the premium list");
|
||||
textComponent.setColor(ChatColor.DARK_RED);
|
||||
forPlayer.sendMessage(textComponent);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
playerProfile.setPremium(false);
|
||||
playerProfile.setUuid(null);
|
||||
plugin.getStorage().save(playerProfile);
|
||||
TextComponent textComponent = new TextComponent("Removed to the list of premium players");
|
||||
textComponent.setColor(ChatColor.DARK_GREEN);
|
||||
forPlayer.sendMessage(textComponent);
|
||||
}
|
||||
});
|
||||
} else if ("SUCCESS".equals(subchannel)) {
|
||||
if (forPlayer.getPendingConnection().isOnlineMode()) {
|
||||
//bukkit module successfully received and force logged in the user
|
||||
//update only on success to prevent corrupt data
|
||||
PlayerProfile playerProfile = plugin.getStorage().getProfile(forPlayer.getName(), false);
|
||||
playerProfile.setPremium(true);
|
||||
//we override this in the loginevent
|
||||
// playerProfile.setUuid(forPlayer.getUniqueId());
|
||||
plugin.getStorage().save(playerProfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
4
pom.xml
4
pom.xml
@@ -8,7 +8,7 @@
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>FastLogin</name>
|
||||
<version>1.0</version>
|
||||
<version>1.3</version>
|
||||
<inceptionYear>2015</inceptionYear>
|
||||
<url>https://www.spigotmc.org/resources/fastlogin.14153/</url>
|
||||
<description>
|
||||
@@ -96,7 +96,7 @@
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<version>1.7.20</version>
|
||||
<version>1.7.21</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.games647</groupId>
|
||||
<artifactId>fastlogin</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.3</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user