forked from TuxCoding/FastLogin
Clean up using IDE inspections
This commit is contained in:
25
.github/ISSUE_TEMPLATE.md
vendored
Normal file
25
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#### Make sure you are running the latest build of the plugin and checked for duplicate issues!
|
||||||
|
|
||||||
|
### What behaviour is observed:
|
||||||
|
What happened?
|
||||||
|
|
||||||
|
### What behaviour is expected:
|
||||||
|
What did you expect?
|
||||||
|
|
||||||
|
### Steps/models to reproduce:
|
||||||
|
The actions that cause the issue
|
||||||
|
|
||||||
|
### Plugin list:
|
||||||
|
This can be found by running `/pl`
|
||||||
|
|
||||||
|
### Environment description
|
||||||
|
Standalone server/Bungeecord network, SQLite/MySql, ...
|
||||||
|
|
||||||
|
### Plugin version:
|
||||||
|
This can be found by running `/version plugin-name`
|
||||||
|
|
||||||
|
### Error Log:
|
||||||
|
[Hastebin](https://hastebin.com/) / [Gist](https://gist.github.com/) link of the error or stacktrace (if any)
|
||||||
|
|
||||||
|
### Configuration:
|
||||||
|
[Hastebin](https://hastebin.com/) / [Gist](https://gist.github.com/) link of your config.yml file (remember to delete any sensitive data)
|
19
.gitignore
vendored
19
.gitignore
vendored
@ -3,22 +3,21 @@
|
|||||||
/.project
|
/.project
|
||||||
/.settings
|
/.settings
|
||||||
|
|
||||||
# netbeans
|
# NetBeans
|
||||||
/nbproject
|
*/nbproject
|
||||||
nb-configuration.xml
|
nb-configuration.xml
|
||||||
/bukkit/nbproject/
|
|
||||||
|
|
||||||
# maven
|
# maven
|
||||||
/target
|
*/target
|
||||||
|
|
||||||
# vim
|
# vim
|
||||||
.*.sw[a-p]
|
.*.sw[a-p]
|
||||||
|
|
||||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
# virtual machine crash logs, see https://www.java.com/en/download/help/error_hotspot.xml
|
||||||
hs_err_pid*
|
hs_err_pid*
|
||||||
|
|
||||||
# various other potential build files
|
# various other potential build files
|
||||||
/build
|
*/build/
|
||||||
/bin
|
/bin
|
||||||
/dist
|
/dist
|
||||||
/manifest.mf
|
/manifest.mf
|
||||||
@ -27,7 +26,7 @@ hs_err_pid*
|
|||||||
# Mac filesystem dust
|
# Mac filesystem dust
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# intellij
|
# IntelliJ
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
*.iws
|
*.iws
|
||||||
@ -41,9 +40,3 @@ gradle-app.setting
|
|||||||
|
|
||||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
# 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
|
|
||||||
core/target
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Use https://travis-ci.org/ for automatic tests
|
# Use https://travis-ci.org/ for automatic testing
|
||||||
|
|
||||||
# speed up testing https://blog.travis-ci.com/2014-12-17-faster-builds-with-container-based-infrastructure/
|
# speed up testing https://blog.travis-ci.com/2014-12-17-faster-builds-with-container-based-infrastructure/
|
||||||
sudo: false
|
sudo: false
|
||||||
@ -8,5 +8,4 @@ language: java
|
|||||||
|
|
||||||
script: mvn compile test
|
script: mvn compile test
|
||||||
|
|
||||||
# We run on 8
|
|
||||||
jdk: [oraclejdk8]
|
jdk: [oraclejdk8]
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
### 1.11
|
### 1.11
|
||||||
|
|
||||||
|
* Drop support for deprecated AuthMe API
|
||||||
|
* Remove legacy database migration code
|
||||||
* Drop support for RoyalAuth, because it doesn't seem to be supported anymore
|
* Drop support for RoyalAuth, because it doesn't seem to be supported anymore
|
||||||
* Clean up client-server encryption -> use only one cipher per connection, simplify code
|
* Clean up client-server encryption -> use only one cipher per connection, simplify code
|
||||||
|
|
||||||
|
102
README.md
102
README.md
@ -28,7 +28,6 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
|
|||||||
### Commands:
|
### Commands:
|
||||||
* /premium [player] Label the invoker or the argument as paid account
|
* /premium [player] Label the invoker or the argument as paid account
|
||||||
* /cracked [player] Label the invoker or the argument as cracked account
|
* /cracked [player] Label the invoker or the argument as cracked account
|
||||||
* /importdb <autoIn/bpa/eldzi> <mysql/sqlite> [host:port] [database] [username] [password] - Imports the database from another plugin
|
|
||||||
|
|
||||||
### Permissions:
|
### Permissions:
|
||||||
* fastlogin.bukkit.command.premium
|
* fastlogin.bukkit.command.premium
|
||||||
@ -39,7 +38,7 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
|
|||||||
|
|
||||||
### Requirements:
|
### Requirements:
|
||||||
* Plugin: [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
|
* Plugin: [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
|
||||||
* Tested Bukkit/[Spigot](https://www.spigotmc.org) 1.9 (could also work with other versions)
|
* Tested [Spigot](https://www.spigotmc.org) 1.8+ (could also work with other versions)
|
||||||
* Java 8+
|
* Java 8+
|
||||||
* Run Spigot and/or BungeeCord/Waterfall in offline mode (see server.properties or config.yml)
|
* 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
|
||||||
@ -58,10 +57,6 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
|
|||||||
|
|
||||||
* [BungeeAuth](https://www.spigotmc.org/resources/bungeeauth.493/)
|
* [BungeeAuth](https://www.spigotmc.org/resources/bungeeauth.493/)
|
||||||
|
|
||||||
### Downloads
|
|
||||||
|
|
||||||
https://www.spigotmc.org/resources/fastlogin.14153/history
|
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
### How to install
|
### How to install
|
||||||
@ -84,98 +79,3 @@ Put your stats id from the BungeeCord config into this file
|
|||||||
7. Set your proxy (BungeeCord) in offline mode by setting the value onlinemode in your config.yml to false
|
7. Set your proxy (BungeeCord) in offline mode by setting the value onlinemode in your config.yml to false
|
||||||
8. You should *always* firewall your spigot server that it's only accessible through BungeeCord https://www.spigotmc.org/wiki/bungeecord-installation/#post-installation
|
8. You should *always* firewall your spigot server that it's only accessible through BungeeCord https://www.spigotmc.org/wiki/bungeecord-installation/#post-installation
|
||||||
9. (BungeeCord doesn't support SQLite per default, so you should change the configuration to MySQL or MariaDB)
|
9. (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)
|
|
||||||
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)
|
|
||||||
5. [Why do players have to invoke a command?](#why-do-players-have-to-invoke-a-command)
|
|
||||||
6. [What happens if a paid account joins with a used username?](#what-happens-if-a-paid-account-joins-with-a-used-username)
|
|
||||||
7. [Does the plugin have BungeeCord support?](#does-the-plugin-have-bungeecord-support)
|
|
||||||
8. [Could premium players have a premium UUID and Skin?](#could-premium-players-have-a-premium-uuid-and-skin)
|
|
||||||
9. [Is this plugin compatible with Cauldron?](#is-this-plugin-compatible-with-cauldron)
|
|
||||||
|
|
||||||
#### How does minecraft logins work?
|
|
||||||
###### Online Mode
|
|
||||||
1. Client -> Server: I want to login, here is my username
|
|
||||||
2. Server -> Client: Okay. I'm in online mode so here is my public key for encryption and my server id
|
|
||||||
3. Client -> Mojang: I'm player "xyz". I want to join a server with that server id
|
|
||||||
4. Mojang -> Client: Session data checked. You can continue
|
|
||||||
5. Client -> Server: I received a successful response from Mojang. Here our shared secret key
|
|
||||||
6. Server -> Mojang: Does the player "xyz" with this shared secret key has a valid account to join me?
|
|
||||||
7. Mojang -> Server: Yes, the player has the following additionally properties (UUID, Skin)
|
|
||||||
8. Client and Server: encrypt all following communication packet
|
|
||||||
9. Server -> Client: Everything checked you can play now
|
|
||||||
|
|
||||||
|
|
||||||
###### Offline Mode
|
|
||||||
In offline mode step 2-7 is skipped. So a login request is directly followed by 8.
|
|
||||||
|
|
||||||
###### More details
|
|
||||||
http://wiki.vg/Protocol#Login
|
|
||||||
|
|
||||||
#### How does this plugin work?
|
|
||||||
By using ProtocolLib, this plugin works as a proxy between the client and server. This plugin will fake that the server
|
|
||||||
runs in online mode. It does everything an online mode server would do. This will be for example, generating keys or
|
|
||||||
checking for valid sessions. Because everything is the same compared to an offline mode login after an encrypted
|
|
||||||
connection, we will intercept only **login** packets of **premium** players.
|
|
||||||
|
|
||||||
1. Player is connecting to the server.
|
|
||||||
2. Plugin checks if the username we received activated the fast login method (i.e. using command)
|
|
||||||
3. Run a check if the username is currently used by a paid account.
|
|
||||||
(We don't know yet if the client connecting is premium)
|
|
||||||
4. Request an Mojang Session Server authentication
|
|
||||||
5. On response check if all data is correct
|
|
||||||
6. Encrypt the connection
|
|
||||||
7. On success intercept all related login packets and fake a new login packet as a normal offline login
|
|
||||||
|
|
||||||
#### Why does the plugin require offline mode?
|
|
||||||
1. As you can see in the question "how does minecraft login works", offline mode is equivalent to online mode except of
|
|
||||||
the encryption and session checks on login. So we can intercept and cancel the first packets for premium players and
|
|
||||||
enable an encrypted connection. Then we send a new fake packet in order to pretend that this a new login request from
|
|
||||||
a offline mode player. The server will handle the rest.
|
|
||||||
2. Some plugins check if the server is in online mode. If so, they could process the real offline (cracked) accounts
|
|
||||||
incorrectly. For example, a plugin tries to fetch the UUID from Mojang, but the name of the player is not associated to
|
|
||||||
a paid account.
|
|
||||||
3. Servers, who allow cracked players and just speed up logins for premium players, are **already** in offline mode.
|
|
||||||
|
|
||||||
#### Can cracked player join with premium usernames?
|
|
||||||
Yes, indeed. Therefore the command for toggling the fast login method exists.
|
|
||||||
|
|
||||||
#### Why do players have to invoke a command?
|
|
||||||
1. It's a secure way to make sure a person with a paid account cannot steal the account
|
|
||||||
of a cracked player that has the same username. The player have to proof first that it's his own account.
|
|
||||||
2. We only receive the username from the player on login. We could check if that username is associated
|
|
||||||
to a paid account but if we request a online mode login from a cracked player (who uses a username from
|
|
||||||
a paid account), the player will disconnect with the reason "bad login" or "Invalid session". There is no way to change
|
|
||||||
that message on the server side (without client modifications), because it's a connection between the Client and the
|
|
||||||
session-server.
|
|
||||||
3. If a premium player would skip registration too, a player of a cracked account could later still register the
|
|
||||||
account and would claim and steal the account from the premium player. Because commands cannot be invoked unless the
|
|
||||||
player has a account or is logged in, protects this method also premium players
|
|
||||||
|
|
||||||
### What happens if a paid account joins with a used username?
|
|
||||||
The player on the server have to activate the feature of this plugin by command. If a person buys the username
|
|
||||||
of his own account, it's still secured. A normal offline mode login makes sure he's the owner of the server account
|
|
||||||
and Mojang account. Then the command can be executed. So someone different cannot steal the account of cracked player
|
|
||||||
by buying the username.
|
|
||||||
|
|
||||||
#### Does the plugin have BungeeCord support?
|
|
||||||
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.
|
|
||||||
|
|
||||||
#### Is this plugin compatible with Cauldron?
|
|
||||||
It's not tested yet, but all needed methods also exists in Cauldron so it could work together.
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
### Useful Links:
|
|
||||||
* [Login Protocol](http://wiki.vg/Protocol#Login)
|
|
||||||
* [Protocol Encryption](http://wiki.vg/Protocol_Encryption)
|
|
||||||
|
@ -65,7 +65,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.spigotmc</groupId>
|
<groupId>org.spigotmc</groupId>
|
||||||
<artifactId>spigot-api</artifactId>
|
<artifactId>spigot-api</artifactId>
|
||||||
<version>1.12-R0.1-SNAPSHOT</version>
|
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
|
|
||||||
public void sendBungeeActivateMessage(CommandSender sender, String target, boolean activate) {
|
public void sendBungeeActivateMessage(CommandSender sender, String target, boolean activate) {
|
||||||
if (sender instanceof Player) {
|
if (sender instanceof Player) {
|
||||||
notifyBungeeCord((Player) sender, target, activate, sender instanceof Player);
|
notifyBungeeCord((Player) sender, target, activate, true);
|
||||||
} else {
|
} else {
|
||||||
Player firstPlayer = Iterables.getFirst(getServer().getOnlinePlayers(), null);
|
Player firstPlayer = Iterables.getFirst(getServer().getOnlinePlayers(), null);
|
||||||
if (firstPlayer == null) {
|
if (firstPlayer == null) {
|
||||||
@ -134,7 +134,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyBungeeCord(firstPlayer, target, activate, sender instanceof Player);
|
notifyBungeeCord(firstPlayer, target, activate, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import java.io.InputStreamReader;
|
|||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.List;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -24,41 +24,44 @@ public class MojangApiBukkit extends MojangApiConnector {
|
|||||||
private static final String HAS_JOINED_URL = "https://sessionserver.mojang.com/session/minecraft/hasJoined?" +
|
private static final String HAS_JOINED_URL = "https://sessionserver.mojang.com/session/minecraft/hasJoined?" +
|
||||||
"username=%s&serverId=%s";
|
"username=%s&serverId=%s";
|
||||||
|
|
||||||
public MojangApiBukkit(Logger logger, List<String> localAddresses, int rateLimit, Map<String, Integer> proxies) {
|
public MojangApiBukkit(Logger logger, Collection<String> localAddresses, int rateLimit
|
||||||
|
, Map<String, Integer> proxies) {
|
||||||
super(logger, localAddresses, rateLimit, proxies);
|
super(logger, localAddresses, rateLimit, proxies);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasJoinedServer(LoginSession session, String serverId, InetSocketAddress ip) {
|
public boolean hasJoinedServer(LoginSession session, String serverId, InetSocketAddress ip) {
|
||||||
BukkitLoginSession playerSession = (BukkitLoginSession) session;
|
BukkitLoginSession playerSession = (BukkitLoginSession) session;
|
||||||
|
|
||||||
|
String url = String.format(HAS_JOINED_URL, playerSession.getUsername(), serverId);
|
||||||
try {
|
try {
|
||||||
String url = String.format(HAS_JOINED_URL, playerSession.getUsername(), serverId);
|
|
||||||
if (ip != null) {
|
if (ip != null) {
|
||||||
url += "&ip=" + URLEncoder.encode(ip.getAddress().getHostAddress(), "UTF-8");
|
url += "&ip=" + URLEncoder.encode(ip.getAddress().getHostAddress(), "UTF-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpURLConnection conn = getConnection(url);
|
HttpURLConnection conn = getConnection(url);
|
||||||
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
|
||||||
String line = reader.readLine();
|
String line = reader.readLine();
|
||||||
if (line != null && !"null".equals(line)) {
|
if (line != null && !"null".equals(line)) {
|
||||||
//validate parsing
|
//validate parsing
|
||||||
//http://wiki.vg/Protocol_Encryption#Server
|
//http://wiki.vg/Protocol_Encryption#Server
|
||||||
JSONObject userData = (JSONObject) JSONValue.parseWithException(line);
|
JSONObject userData = (JSONObject) JSONValue.parseWithException(line);
|
||||||
String uuid = (String) userData.get("id");
|
String uuid = (String) userData.get("id");
|
||||||
playerSession.setUuid(FastLoginCore.parseId(uuid));
|
playerSession.setUuid(FastLoginCore.parseId(uuid));
|
||||||
|
|
||||||
JSONArray properties = (JSONArray) userData.get("properties");
|
JSONArray properties = (JSONArray) userData.get("properties");
|
||||||
JSONObject skinProperty = (JSONObject) properties.get(0);
|
JSONObject skinProperty = (JSONObject) properties.get(0);
|
||||||
|
|
||||||
String propertyName = (String) skinProperty.get("name");
|
String propertyName = (String) skinProperty.get("name");
|
||||||
if ("textures".equals(propertyName)) {
|
if ("textures".equals(propertyName)) {
|
||||||
String skinValue = (String) skinProperty.get("value");
|
String skinValue = (String) skinProperty.get("value");
|
||||||
String signature = (String) skinProperty.get("signature");
|
String signature = (String) skinProperty.get("signature");
|
||||||
playerSession.setSkin(skinValue, signature);
|
playerSession.setSkin(skinValue, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
//catch not only io-exceptions also parse and NPE on unexpected json format
|
//catch not only io-exceptions also parse and NPE on unexpected json format
|
||||||
|
@ -34,7 +34,7 @@ public class PremiumPlaceholder extends PlaceholderHook {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean register(FastLoginBukkit plugin) {
|
public static void register(FastLoginBukkit plugin) {
|
||||||
return PlaceholderAPI.registerPlaceholderHook(plugin, new PremiumPlaceholder(plugin));
|
PlaceholderAPI.registerPlaceholderHook(plugin, new PremiumPlaceholder(plugin));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,9 @@ public class LogItHook implements AuthPlugin<Player> {
|
|||||||
@Override
|
@Override
|
||||||
public boolean forceLogin(Player player) {
|
public boolean forceLogin(Player player) {
|
||||||
SessionManager sessionManager = LogItCore.getInstance().getSessionManager();
|
SessionManager sessionManager = LogItCore.getInstance().getSessionManager();
|
||||||
if (sessionManager.isSessionAlive(player)) {
|
return sessionManager.isSessionAlive(player)
|
||||||
return true;
|
|| sessionManager.startSession(player) == CancelledState.NOT_CANCELLED;
|
||||||
}
|
|
||||||
|
|
||||||
return sessionManager.startSession(player) == CancelledState.NOT_CANCELLED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -24,11 +24,8 @@ public class LoginSecurityHook implements AuthPlugin<Player> {
|
|||||||
@Override
|
@Override
|
||||||
public boolean forceLogin(Player player) {
|
public boolean forceLogin(Player player) {
|
||||||
PlayerSession session = LoginSecurity.getSessionManager().getPlayerSession(player);
|
PlayerSession session = LoginSecurity.getSessionManager().getPlayerSession(player);
|
||||||
if (session.isAuthorized()) {
|
return session.isAuthorized() || session.performAction(new LoginAction(AuthService.PLUGIN, plugin)).isSuccess();
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return session.performAction(new LoginAction(AuthService.PLUGIN, plugin)).isSuccess();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,11 +52,7 @@ public class UltraAuthHook implements AuthPlugin<Player> {
|
|||||||
@Override
|
@Override
|
||||||
public boolean forceRegister(Player player, String password) {
|
public boolean forceRegister(Player player, String password) {
|
||||||
UltraAuthAPI.setPlayerPasswordOnline(player, password);
|
UltraAuthAPI.setPlayerPasswordOnline(player, password);
|
||||||
if (PlayerManager.getInstance().checkPlayerPassword(player, password)) {
|
//the register method silents any exception so check if our entry was saved
|
||||||
//the register method silents any exception so check if our entry was saved
|
return PlayerManager.getInstance().checkPlayerPassword(player, password) && forceLogin(player);
|
||||||
return forceLogin(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,15 +63,11 @@ public class xAuthHook implements AuthPlugin<Player> {
|
|||||||
//not thread-safe
|
//not thread-safe
|
||||||
Future<Boolean> future = Bukkit.getScheduler().callSyncMethod(xAuthPlugin, () -> {
|
Future<Boolean> future = Bukkit.getScheduler().callSyncMethod(xAuthPlugin, () -> {
|
||||||
xAuthPlayer xAuthPlayer = xAuthPlugin.getPlayerManager().getPlayer(player);
|
xAuthPlayer xAuthPlayer = xAuthPlugin.getPlayerManager().getPlayer(player);
|
||||||
if (xAuthPlayer != null) {
|
//this should run async because the plugin executes a sql query, but the method
|
||||||
//this should run async because the plugin executes a sql query, but the method
|
//accesses non thread-safe collections :(
|
||||||
//accesses non thread-safe collections :(
|
return xAuthPlayer != null
|
||||||
|
&& xAuthPlugin.getAuthClass(xAuthPlayer).adminRegister(player.getName(), password, null);
|
||||||
|
|
||||||
return xAuthPlugin.getAuthClass(xAuthPlayer)
|
|
||||||
.adminRegister(player.getName(), password, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.github.games647.fastlogin.bungee;
|
package com.github.games647.fastlogin.bungee;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthHook;
|
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthHook;
|
||||||
import com.github.games647.fastlogin.bungee.listener.PlayerConnectionListener;
|
import com.github.games647.fastlogin.bungee.listener.ConnectionListener;
|
||||||
import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
|
import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
|
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
|
||||||
@ -46,7 +46,7 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
|||||||
}
|
}
|
||||||
|
|
||||||
//events
|
//events
|
||||||
getProxy().getPluginManager().registerListener(this, new PlayerConnectionListener(this));
|
getProxy().getPluginManager().registerListener(this, new ConnectionListener(this));
|
||||||
getProxy().getPluginManager().registerListener(this, new PluginMessageListener(this));
|
getProxy().getPluginManager().registerListener(this, new PluginMessageListener(this));
|
||||||
|
|
||||||
//this is required to listen to messages from the server
|
//this is required to listen to messages from the server
|
||||||
|
@ -4,7 +4,7 @@ import com.github.games647.fastlogin.core.shared.LoginSession;
|
|||||||
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
|
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.List;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@ -12,7 +12,8 @@ import net.md_5.bungee.BungeeCord;
|
|||||||
|
|
||||||
public class MojangApiBungee extends MojangApiConnector {
|
public class MojangApiBungee extends MojangApiConnector {
|
||||||
|
|
||||||
public MojangApiBungee(Logger logger, List<String> localAddresses, int rateLimit, Map<String, Integer> proxies) {
|
public MojangApiBungee(Logger logger, Collection<String> localAddresses, int rateLimit
|
||||||
|
, Map<String, Integer> proxies) {
|
||||||
super(logger, localAddresses, rateLimit, proxies);
|
super(logger, localAddresses, rateLimit, proxies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,11 +21,8 @@ public class BungeeAuthHook implements AuthPlugin<ProxiedPlayer> {
|
|||||||
@Override
|
@Override
|
||||||
public boolean forceLogin(ProxiedPlayer player) {
|
public boolean forceLogin(ProxiedPlayer player) {
|
||||||
String playerName = player.getName();
|
String playerName = player.getName();
|
||||||
if (Main.plonline.contains(playerName)) {
|
return Main.plonline.contains(playerName) || requestHandler.forceLogin(playerName);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return requestHandler.forceLogin(playerName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,11 +31,11 @@ import net.md_5.bungee.event.EventPriority;
|
|||||||
* plugin message to the Bukkit version of this plugin in
|
* plugin message to the Bukkit version of this plugin in
|
||||||
* order to clear that the connection is online mode.
|
* order to clear that the connection is online mode.
|
||||||
*/
|
*/
|
||||||
public class PlayerConnectionListener implements Listener {
|
public class ConnectionListener implements Listener {
|
||||||
|
|
||||||
private final FastLoginBungee plugin;
|
private final FastLoginBungee plugin;
|
||||||
|
|
||||||
public PlayerConnectionListener(FastLoginBungee plugin) {
|
public ConnectionListener(FastLoginBungee plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
@ -54,11 +54,8 @@ public class ForceLoginTask extends ForceLoginManagement<ProxiedPlayer, CommandS
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean forceRegister(ProxiedPlayer player) {
|
public boolean forceRegister(ProxiedPlayer player) {
|
||||||
if (session.isAlreadyLogged()) {
|
return session.isAlreadyLogged() || super.forceRegister(player);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.forceRegister(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -62,12 +62,8 @@ public class AuthStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void createTables() throws SQLException {
|
public void createTables() throws SQLException {
|
||||||
Connection con = null;
|
try (Connection con = dataSource.getConnection();
|
||||||
Statement createStmt = null;
|
Statement createStmt = con.createStatement()) {
|
||||||
try {
|
|
||||||
con = dataSource.getConnection();
|
|
||||||
createStmt = con.createStatement();
|
|
||||||
|
|
||||||
String createDataStmt = "CREATE TABLE IF NOT EXISTS " + PREMIUM_TABLE + " ("
|
String createDataStmt = "CREATE TABLE IF NOT EXISTS " + PREMIUM_TABLE + " ("
|
||||||
+ "UserID INTEGER PRIMARY KEY AUTO_INCREMENT, "
|
+ "UserID INTEGER PRIMARY KEY AUTO_INCREMENT, "
|
||||||
+ "UUID CHAR(36), "
|
+ "UUID CHAR(36), "
|
||||||
@ -84,132 +80,106 @@ public class AuthStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createStmt.executeUpdate(createDataStmt);
|
createStmt.executeUpdate(createDataStmt);
|
||||||
} finally {
|
|
||||||
closeQuietly(con);
|
|
||||||
closeQuietly(createStmt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerProfile loadProfile(String name) {
|
public PlayerProfile loadProfile(String name) {
|
||||||
Connection con = null;
|
try (Connection con = dataSource.getConnection();
|
||||||
PreparedStatement loadStmt = null;
|
PreparedStatement loadStmt = con.prepareStatement("SELECT * FROM "
|
||||||
ResultSet resultSet = null;
|
+ PREMIUM_TABLE + " WHERE Name=? LIMIT 1")) {
|
||||||
try {
|
|
||||||
con = dataSource.getConnection();
|
|
||||||
loadStmt = con.prepareStatement("SELECT * FROM " + PREMIUM_TABLE + " WHERE Name=? LIMIT 1");
|
|
||||||
loadStmt.setString(1, name);
|
loadStmt.setString(1, name);
|
||||||
|
|
||||||
resultSet = loadStmt.executeQuery();
|
try (ResultSet resultSet = loadStmt.executeQuery()) {
|
||||||
if (resultSet.next()) {
|
if (resultSet.next()) {
|
||||||
long userId = resultSet.getInt(1);
|
long userId = resultSet.getInt(1);
|
||||||
|
|
||||||
UUID uuid = FastLoginCore.parseId(resultSet.getString(2));
|
UUID uuid = FastLoginCore.parseId(resultSet.getString(2));
|
||||||
|
|
||||||
boolean premium = resultSet.getBoolean(4);
|
boolean premium = resultSet.getBoolean(4);
|
||||||
String lastIp = resultSet.getString(5);
|
String lastIp = resultSet.getString(5);
|
||||||
long lastLogin = resultSet.getTimestamp(6).getTime();
|
long lastLogin = resultSet.getTimestamp(6).getTime();
|
||||||
return new PlayerProfile(userId, uuid, name, premium, lastIp, lastLogin);
|
return new PlayerProfile(userId, uuid, name, premium, lastIp, lastLogin);
|
||||||
} else {
|
} else {
|
||||||
return new PlayerProfile(null, name, false, "");
|
return new PlayerProfile(null, name, false, "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (SQLException sqlEx) {
|
} catch (SQLException sqlEx) {
|
||||||
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
|
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
|
||||||
} finally {
|
|
||||||
closeQuietly(con);
|
|
||||||
closeQuietly(loadStmt);
|
|
||||||
closeQuietly(resultSet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerProfile loadProfile(UUID uuid) {
|
public PlayerProfile loadProfile(UUID uuid) {
|
||||||
Connection con = null;
|
try (Connection con = dataSource.getConnection();
|
||||||
PreparedStatement loadStmt = null;
|
PreparedStatement loadStmt = con.prepareStatement("SELECT * FROM "
|
||||||
ResultSet resultSet = null;
|
+ PREMIUM_TABLE + " WHERE UUID=? LIMIT 1")) {
|
||||||
try {
|
|
||||||
con = dataSource.getConnection();
|
|
||||||
loadStmt = con.prepareStatement("SELECT * FROM " + PREMIUM_TABLE + " WHERE UUID=? LIMIT 1");
|
|
||||||
loadStmt.setString(1, uuid.toString().replace("-", ""));
|
loadStmt.setString(1, uuid.toString().replace("-", ""));
|
||||||
|
|
||||||
resultSet = loadStmt.executeQuery();
|
try (ResultSet resultSet = loadStmt.executeQuery()) {
|
||||||
if (resultSet.next()) {
|
if (resultSet.next()) {
|
||||||
long userId = resultSet.getInt(1);
|
long userId = resultSet.getInt(1);
|
||||||
|
|
||||||
String name = resultSet.getString(3);
|
String name = resultSet.getString(3);
|
||||||
boolean premium = resultSet.getBoolean(4);
|
boolean premium = resultSet.getBoolean(4);
|
||||||
String lastIp = resultSet.getString(5);
|
String lastIp = resultSet.getString(5);
|
||||||
long lastLogin = resultSet.getTimestamp(6).getTime();
|
long lastLogin = resultSet.getTimestamp(6).getTime();
|
||||||
return new PlayerProfile(userId, uuid, name, premium, lastIp, lastLogin);
|
return new PlayerProfile(userId, uuid, name, premium, lastIp, lastLogin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (SQLException sqlEx) {
|
} catch (SQLException sqlEx) {
|
||||||
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
|
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx);
|
||||||
} finally {
|
|
||||||
closeQuietly(con);
|
|
||||||
closeQuietly(loadStmt);
|
|
||||||
closeQuietly(resultSet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean save(PlayerProfile playerProfile) {
|
public boolean save(PlayerProfile playerProfile) {
|
||||||
Connection con = null;
|
try (Connection con = dataSource.getConnection()) {
|
||||||
PreparedStatement updateStmt = null;
|
|
||||||
PreparedStatement saveStmt = null;
|
|
||||||
|
|
||||||
ResultSet generatedKeys = null;
|
|
||||||
try {
|
|
||||||
con = dataSource.getConnection();
|
|
||||||
|
|
||||||
UUID uuid = playerProfile.getUuid();
|
UUID uuid = playerProfile.getUuid();
|
||||||
|
|
||||||
if (playerProfile.getUserId() == -1) {
|
if (playerProfile.getUserId() == -1) {
|
||||||
saveStmt = con.prepareStatement("INSERT INTO " + PREMIUM_TABLE
|
try (PreparedStatement saveStmt = con.prepareStatement("INSERT INTO " + PREMIUM_TABLE
|
||||||
+ " (UUID, Name, Premium, LastIp) VALUES (?, ?, ?, ?) ", Statement.RETURN_GENERATED_KEYS);
|
+ " (UUID, Name, Premium, LastIp) VALUES (?, ?, ?, ?) ", Statement.RETURN_GENERATED_KEYS)) {
|
||||||
|
if (uuid == null) {
|
||||||
|
saveStmt.setString(1, null);
|
||||||
|
} else {
|
||||||
|
saveStmt.setString(1, uuid.toString().replace("-", ""));
|
||||||
|
}
|
||||||
|
|
||||||
if (uuid == null) {
|
saveStmt.setString(2, playerProfile.getPlayerName());
|
||||||
saveStmt.setString(1, null);
|
saveStmt.setBoolean(3, playerProfile.isPremium());
|
||||||
} else {
|
saveStmt.setString(4, playerProfile.getLastIp());
|
||||||
saveStmt.setString(1, uuid.toString().replace("-", ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
saveStmt.setString(2, playerProfile.getPlayerName());
|
saveStmt.execute();
|
||||||
saveStmt.setBoolean(3, playerProfile.isPremium());
|
|
||||||
saveStmt.setString(4, playerProfile.getLastIp());
|
|
||||||
|
|
||||||
saveStmt.execute();
|
try (ResultSet generatedKeys = saveStmt.getGeneratedKeys()) {
|
||||||
|
if (generatedKeys != null && generatedKeys.next()) {
|
||||||
generatedKeys = saveStmt.getGeneratedKeys();
|
playerProfile.setUserId(generatedKeys.getInt(1));
|
||||||
if (generatedKeys != null && generatedKeys.next()) {
|
}
|
||||||
playerProfile.setUserId(generatedKeys.getInt(1));
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
saveStmt = con.prepareStatement("UPDATE " + PREMIUM_TABLE
|
try (PreparedStatement saveStmt = con.prepareStatement("UPDATE " + PREMIUM_TABLE
|
||||||
+ " SET UUID=?, Name=?, Premium=?, LastIp=?, LastLogin=CURRENT_TIMESTAMP WHERE UserID=?");
|
+ " SET UUID=?, Name=?, Premium=?, LastIp=?, LastLogin=CURRENT_TIMESTAMP WHERE UserID=?")) {
|
||||||
|
if (uuid == null) {
|
||||||
|
saveStmt.setString(1, null);
|
||||||
|
} else {
|
||||||
|
saveStmt.setString(1, uuid.toString().replace("-", ""));
|
||||||
|
}
|
||||||
|
|
||||||
if (uuid == null) {
|
saveStmt.setString(2, playerProfile.getPlayerName());
|
||||||
saveStmt.setString(1, null);
|
saveStmt.setBoolean(3, playerProfile.isPremium());
|
||||||
} else {
|
saveStmt.setString(4, playerProfile.getLastIp());
|
||||||
saveStmt.setString(1, uuid.toString().replace("-", ""));
|
|
||||||
|
saveStmt.setLong(5, playerProfile.getUserId());
|
||||||
|
saveStmt.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
saveStmt.setString(2, playerProfile.getPlayerName());
|
|
||||||
saveStmt.setBoolean(3, playerProfile.isPremium());
|
|
||||||
saveStmt.setString(4, playerProfile.getLastIp());
|
|
||||||
|
|
||||||
saveStmt.setLong(5, playerProfile.getUserId());
|
|
||||||
saveStmt.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to save playerProfile", ex);
|
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to save playerProfile", ex);
|
||||||
} finally {
|
|
||||||
closeQuietly(con);
|
|
||||||
closeQuietly(updateStmt);
|
|
||||||
closeQuietly(saveStmt);
|
|
||||||
closeQuietly(generatedKeys);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -218,14 +188,4 @@ public class AuthStorage {
|
|||||||
public void close() {
|
public void close() {
|
||||||
dataSource.close();
|
dataSource.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeQuietly(AutoCloseable closeable) {
|
|
||||||
if (closeable != null) {
|
|
||||||
try {
|
|
||||||
closeable.close();
|
|
||||||
} catch (Exception closeEx) {
|
|
||||||
core.getPlugin().getLogger().log(Level.SEVERE, "Failed to close connection", closeEx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -83,41 +83,18 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
saveDefaultFile("messages.yml");
|
saveDefaultFile("messages.yml");
|
||||||
saveDefaultFile("config.yml");
|
saveDefaultFile("config.yml");
|
||||||
|
|
||||||
BufferedReader reader = null;
|
|
||||||
try {
|
try {
|
||||||
reader = new BufferedReader(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("config.yml")));
|
sharedConfig = new SharedConfig(loadFile("config.yml"));
|
||||||
sharedConfig = new SharedConfig(plugin.loadYamlFile(reader));
|
Map<String, Object> messages = loadFile("messages.yml");
|
||||||
reader.close();
|
|
||||||
|
|
||||||
reader = Files.newBufferedReader(plugin.getDataFolder().toPath().resolve("config.yml"));
|
for (Entry<String, Object> entry : messages.entrySet()) {
|
||||||
sharedConfig.getConfigValues().putAll(plugin.loadYamlFile(reader));
|
|
||||||
reader.close();
|
|
||||||
|
|
||||||
reader = new BufferedReader(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("messages.yml")));
|
|
||||||
reader = Files.newBufferedReader(plugin.getDataFolder().toPath().resolve("messages.yml"));
|
|
||||||
Map<String, Object> messageConfig = plugin.loadYamlFile(reader);
|
|
||||||
reader.close();
|
|
||||||
|
|
||||||
reader = Files.newBufferedReader(plugin.getDataFolder().toPath().resolve("messages.yml"));
|
|
||||||
messageConfig.putAll(plugin.loadYamlFile(reader));
|
|
||||||
for (Entry<String, Object> entry : messageConfig.entrySet()) {
|
|
||||||
String message = plugin.translateColorCodes('&', (String) entry.getValue());
|
String message = plugin.translateColorCodes('&', (String) entry.getValue());
|
||||||
if (!message.isEmpty()) {
|
if (!message.isEmpty()) {
|
||||||
localeMessages.put(entry.getKey(), message);
|
localeMessages.put(entry.getKey(), message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.close();
|
|
||||||
} catch (IOException ioEx) {
|
} catch (IOException ioEx) {
|
||||||
plugin.getLogger().log(Level.INFO, "Failed to load yaml files", ioEx);
|
plugin.getLogger().log(Level.INFO, "Failed to load yaml files", ioEx);
|
||||||
} finally {
|
|
||||||
if (reader != null) {
|
|
||||||
try {
|
|
||||||
reader.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
plugin.getLogger().log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> ipAddresses = sharedConfig.get("ip-addresses");
|
List<String> ipAddresses = sharedConfig.get("ip-addresses");
|
||||||
@ -130,6 +107,22 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
this.apiConnector = plugin.makeApiConnector(plugin.getLogger(), ipAddresses, requestLimit, proxies);
|
this.apiConnector = plugin.makeApiConnector(plugin.getLogger(), ipAddresses, requestLimit, proxies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> loadFile(String fileName) throws IOException {
|
||||||
|
Map<String, Object> values;
|
||||||
|
|
||||||
|
try (InputStream defaultStream = getClass().getClassLoader().getResourceAsStream(fileName);
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(defaultStream))) {
|
||||||
|
values = plugin.loadYamlFile(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Path file = plugin.getDataFolder().toPath().resolve(fileName);
|
||||||
|
try (BufferedReader reader = Files.newBufferedReader(file)) {
|
||||||
|
values.putAll(plugin.loadYamlFile(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
public MojangApiConnector getApiConnector() {
|
public MojangApiConnector getApiConnector() {
|
||||||
return apiConnector;
|
return apiConnector;
|
||||||
}
|
}
|
||||||
@ -213,17 +206,10 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
|
|
||||||
Path configFile = dataFolder.resolve(fileName);
|
Path configFile = dataFolder.resolve(fileName);
|
||||||
if (Files.notExists(configFile)) {
|
if (Files.notExists(configFile)) {
|
||||||
InputStream in = getClass().getClassLoader().getResourceAsStream(fileName);
|
try (InputStream in = getClass().getClassLoader().getResourceAsStream(fileName)) {
|
||||||
try {
|
|
||||||
Files.copy(in, configFile);
|
Files.copy(in, configFile);
|
||||||
} catch (IOException ioExc) {
|
} catch (IOException ioExc) {
|
||||||
plugin.getLogger().log(Level.SEVERE, "Error saving default " + fileName, ioExc);
|
plugin.getLogger().log(Level.SEVERE, "Error saving default " + fileName, ioExc);
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
plugin.getLogger().log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,10 +92,11 @@ public abstract class MojangApiConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
|
||||||
String line = reader.readLine();
|
String line = reader.readLine();
|
||||||
if (!"null".equals(line)) {
|
if (!"null".equals(line)) {
|
||||||
return FastLoginCore.parseId(getUUIDFromJson(line));
|
return FastLoginCore.parseId(getUUIDFromJson(line));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (connection.getResponseCode() == RATE_LIMIT_CODE) {
|
} else if (connection.getResponseCode() == RATE_LIMIT_CODE) {
|
||||||
logger.info("RATE_LIMIT REACHED");
|
logger.info("RATE_LIMIT REACHED");
|
||||||
|
Reference in New Issue
Block a user