Use Instant for timestamps

This commit is contained in:
games647
2017-10-01 17:11:06 +02:00
parent dce44295d0
commit 105e00b7e8
24 changed files with 122 additions and 101 deletions

View File

@ -13,9 +13,9 @@ The actions that cause the issue
This can be found by running `/pl` This can be found by running `/pl`
### Environment description ### Environment description
Standalone server/Bungeecord network, SQLite/MySql, ... Standalone server/Bungeecord network, SQLite/MySQL, ...
### Plugin version: ### Plugin version or build number (don't write latest):
This can be found by running `/version plugin-name` This can be found by running `/version plugin-name`
### Error Log: ### Error Log:

View File

@ -37,7 +37,8 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
* fastlogin.command.import * fastlogin.command.import
### 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/)
* [Spigot](https://www.spigotmc.org) 1.7+ * [Spigot](https://www.spigotmc.org) 1.7+
* 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)
@ -77,5 +78,6 @@ Put your stats id from the BungeeCord config into this file
5. Download and Install FastLogin on BungeeCord AND Spigot 5. Download and Install FastLogin on BungeeCord AND Spigot
6. Check your database settings in the config of FastLogin on BungeeCord 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 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)

View File

@ -2,8 +2,8 @@ package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.bukkit.commands.CrackedCommand; import com.github.games647.fastlogin.bukkit.commands.CrackedCommand;
import com.github.games647.fastlogin.bukkit.commands.PremiumCommand; import com.github.games647.fastlogin.bukkit.commands.PremiumCommand;
import com.github.games647.fastlogin.bukkit.listener.JoinListener;
import com.github.games647.fastlogin.bukkit.listener.BungeeListener; import com.github.games647.fastlogin.bukkit.listener.BungeeListener;
import com.github.games647.fastlogin.bukkit.listener.JoinListener;
import com.github.games647.fastlogin.bukkit.listener.protocollib.LoginSkinApplyListener; import com.github.games647.fastlogin.bukkit.listener.protocollib.LoginSkinApplyListener;
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener; import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener; import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
@ -17,11 +17,11 @@ import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.net.HostAndPort; import com.google.common.net.HostAndPort;
import java.nio.file.Path;
import java.security.KeyPair; import java.security.KeyPair;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.logging.Level;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -188,6 +188,11 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
sender.sendPluginMessage(this, getName(), dataOutput.toByteArray()); sender.sendPluginMessage(this, getName(), dataOutput.toByteArray());
} }
@Override
public Path getPluginFolder() {
return getDataFolder().toPath();
}
@Override @Override
public Logger getLog() { public Logger getLog() {
return logger; return logger;
@ -206,6 +211,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
@Override @Override
public MojangApiConnector makeApiConnector(List<String> addresses, int requests, List<HostAndPort> proxies) { public MojangApiConnector makeApiConnector(List<String> addresses, int requests, List<HostAndPort> proxies) {
return new MojangApiBukkit(getLog(), addresses, requests, proxies); return new MojangApiBukkit(logger, addresses, requests, proxies);
} }
} }

View File

@ -12,7 +12,6 @@ import java.net.HttpURLConnection;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -23,7 +22,7 @@ public class MojangApiBukkit extends MojangApiConnector {
"username=%s&serverId=%s&ip=%s"; "username=%s&serverId=%s&ip=%s";
public MojangApiBukkit(Logger logger, Collection<String> localAddresses, int rateLimit public MojangApiBukkit(Logger logger, Collection<String> localAddresses, int rateLimit
, List<HostAndPort> proxies) { , Iterable<HostAndPort> proxies) {
super(logger, localAddresses, rateLimit, proxies); super(logger, localAddresses, rateLimit, proxies);
} }

View File

@ -93,9 +93,7 @@ public class CrazyLoginHook implements AuthPlugin<Player> {
//create a fake account - this will be saved to the database with the password=FAILEDLOADING //create a fake account - this will be saved to the database with the password=FAILEDLOADING
//user cannot login with that password unless the admin uses plain text //user cannot login with that password unless the admin uses plain text
//this automatically marks the player as logged in //this automatically marks the player as logged in
playerData = new LoginPlayerData(player); crazyDatabase.save(new LoginPlayerData(player));
crazyDatabase.save(playerData);
return forceLogin(player); return forceLogin(player);
} }

View File

@ -6,6 +6,9 @@ import io.github.lucaseasedup.logit.CancelledState;
import io.github.lucaseasedup.logit.LogItCore; import io.github.lucaseasedup.logit.LogItCore;
import io.github.lucaseasedup.logit.account.Account; import io.github.lucaseasedup.logit.account.Account;
import io.github.lucaseasedup.logit.session.SessionManager; import io.github.lucaseasedup.logit.session.SessionManager;
import java.time.Instant;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
/** /**
@ -22,7 +25,6 @@ public class LogItHook implements AuthPlugin<Player> {
SessionManager sessionManager = LogItCore.getInstance().getSessionManager(); SessionManager sessionManager = LogItCore.getInstance().getSessionManager();
return sessionManager.isSessionAlive(player) return sessionManager.isSessionAlive(player)
|| sessionManager.startSession(player) == CancelledState.NOT_CANCELLED; || sessionManager.startSession(player) == CancelledState.NOT_CANCELLED;
} }
@Override @Override
@ -34,8 +36,10 @@ public class LogItHook implements AuthPlugin<Player> {
public boolean forceRegister(Player player, String password) { public boolean forceRegister(Player player, String password) {
Account account = new Account(player.getName()); Account account = new Account(player.getName());
account.changePassword(password); account.changePassword(password);
account.setLastActiveDate(System.currentTimeMillis() / 1000);
account.setRegistrationDate(System.currentTimeMillis() / 1000); Instant now = Instant.now();
account.setLastActiveDate(now.getEpochSecond());
account.setRegistrationDate(now.getEpochSecond());
return LogItCore.getInstance().getAccountManager().insertAccount(account) == CancelledState.NOT_CANCELLED; return LogItCore.getInstance().getAccountManager().insertAccount(account) == CancelledState.NOT_CANCELLED;
} }
} }

View File

@ -95,7 +95,7 @@ public class BungeeListener implements PluginMessageListener {
} }
public Set<UUID> loadBungeeCordIds() { public Set<UUID> loadBungeeCordIds() {
Path whitelistFile = plugin.getDataFolder().toPath().resolve(FILE_NAME); Path whitelistFile = plugin.getPluginFolder().resolve(FILE_NAME);
try { try {
if (Files.notExists(whitelistFile)) { if (Files.notExists(whitelistFile)) {
Files.createFile(whitelistFile); Files.createFile(whitelistFile);

View File

@ -23,7 +23,8 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
private final Player player; private final Player player;
private final String username; private final String username;
public NameCheckTask(FastLoginBukkit plugin, PacketEvent packetEvent, Random random, Player player, String username) { public NameCheckTask(FastLoginBukkit plugin, PacketEvent packetEvent, Random random,
Player player, String username) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook()); super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
this.plugin = plugin; this.plugin = plugin;
@ -45,7 +46,8 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
//minecraft server implementation //minecraft server implementation
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L161 //https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L161
@Override @Override
public void requestPremiumLogin(ProtocolLibLoginSource source, PlayerProfile profile, String username, boolean registered) { public void requestPremiumLogin(ProtocolLibLoginSource source, PlayerProfile profile
, String username, boolean registered) {
try { try {
source.setOnlineMode(); source.setOnlineMode();
} catch (Exception ex) { } catch (Exception ex) {

View File

@ -52,13 +52,15 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
} }
@Override @Override
public void requestPremiumLogin(ProtocolLoginSource source, PlayerProfile profile, String username, boolean registered) { public void requestPremiumLogin(ProtocolLoginSource source, PlayerProfile profile, String username
, boolean registered) {
source.setOnlineMode(); source.setOnlineMode();
String ip = source.getAddress().getAddress().getHostAddress(); String ip = source.getAddress().getAddress().getHostAddress();
plugin.getCore().getPendingLogin().put(ip + username, new Object()); plugin.getCore().getPendingLogin().put(ip + username, new Object());
BukkitLoginSession playerSession = new BukkitLoginSession(username, null, null, registered, profile); BukkitLoginSession playerSession = new BukkitLoginSession(username, null, null
, registered, profile);
plugin.getLoginSessions().put(source.getAddress().toString(), playerSession); plugin.getLoginSessions().put(source.getAddress().toString(), playerSession);
if (plugin.getConfig().getBoolean("premiumUuid")) { if (plugin.getConfig().getBoolean("premiumUuid")) {
source.getLoginStartEvent().setUseOnlineModeUUID(true); source.getLoginStartEvent().setUseOnlineModeUUID(true);

View File

@ -9,7 +9,9 @@ import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.PlatformPlugin; import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.net.HostAndPort; import com.google.common.net.HostAndPort;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
@ -79,6 +81,11 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
return getDescription().getName(); return getDescription().getName();
} }
@Override
public Path getPluginFolder() {
return getDataFolder().toPath();
}
@Override @Override
public Logger getLog() { public Logger getLog() {
return logger; return logger;
@ -92,11 +99,16 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
@Override @Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public ThreadFactory getThreadFactory() { public ThreadFactory getThreadFactory() {
return new GroupedThreadFactory(this, getName()); return new ThreadFactoryBuilder()
.setNameFormat(core.getPlugin().getName() + " Database Pool Thread #%1$d")
//Hikari create daemons by default
.setDaemon(true)
.setThreadFactory(new GroupedThreadFactory(this, getName()))
.build();
} }
@Override @Override
public MojangApiConnector makeApiConnector(List<String> addresses, int requests, List<HostAndPort> proxies) { public MojangApiConnector makeApiConnector(List<String> addresses, int requests, List<HostAndPort> proxies) {
return new MojangApiConnector(getLog(), addresses, requests, proxies); return new MojangApiConnector(logger, addresses, requests, proxies);
} }
} }

View File

@ -33,6 +33,7 @@ import net.md_5.bungee.event.EventPriority;
public class ConnectListener implements Listener { public class ConnectListener implements Listener {
private final FastLoginBungee plugin; private final FastLoginBungee plugin;
private final Property[] emptyProperties = {};
public ConnectListener(FastLoginBungee plugin) { public ConnectListener(FastLoginBungee plugin) {
this.plugin = plugin; this.plugin = plugin;
@ -89,7 +90,7 @@ public class ConnectListener implements Listener {
//this is null on offline mode //this is null on offline mode
LoginResult loginProfile = initialHandler.getLoginProfile(); LoginResult loginProfile = initialHandler.getLoginProfile();
if (loginProfile != null) { if (loginProfile != null) {
loginProfile.setProperties(new Property[]{}); loginProfile.setProperties(emptyProperties);
} }
} }
} }

View File

@ -42,7 +42,8 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
} }
@Override @Override
public void requestPremiumLogin(BungeeLoginSource source, PlayerProfile profile, String username, boolean registered) { public void requestPremiumLogin(BungeeLoginSource source, PlayerProfile profile,
String username, boolean registered) {
source.setOnlineMode(); source.setOnlineMode();
plugin.getSession().put(source.getConnection(), new BungeeLoginSession(username, registered, profile)); plugin.getSession().put(source.getConnection(), new BungeeLoginSession(username, registered, profile));

View File

@ -15,7 +15,8 @@ import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server; import net.md_5.bungee.api.connection.Server;
public class ForceLoginTask extends ForceLoginManagement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> { public class ForceLoginTask
extends ForceLoginManagement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> {
private final Server server; private final Server server;

View File

@ -1,7 +1,6 @@
package com.github.games647.fastlogin.core; package com.github.games647.fastlogin.core;
import com.github.games647.fastlogin.core.shared.FastLoginCore; import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
@ -10,14 +9,24 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.time.Instant;
import java.util.Properties; import java.util.Properties;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import static java.sql.Statement.RETURN_GENERATED_KEYS;
public class AuthStorage { public class AuthStorage {
private static final String PREMIUM_TABLE = "premium"; private static final String PREMIUM_TABLE = "premium";
private static final String LOAD_BY_NAME = "SELECT * FROM " + PREMIUM_TABLE + " WHERE Name=? LIMIT 1";
private static final String LOAD_BY_UUID = "SELECT * FROM " + PREMIUM_TABLE + " WHERE UUID=? LIMIT 1";
private static final String INSERT_PROFILE = "INSERT INTO " + PREMIUM_TABLE + " (UUID, Name, Premium, LastIp) "
+ "VALUES (?, ?, ?, ?) ";
private static final String UPDATE_PROFILE = "UPDATE " + PREMIUM_TABLE
+ " SET UUID=?, Name=?, Premium=?, LastIp=?, LastLogin=CURRENT_TIMESTAMP WHERE UserID=?";
private final FastLoginCore<?, ?, ?> core; private final FastLoginCore<?, ?, ?> core;
private final HikariDataSource dataSource; private final HikariDataSource dataSource;
@ -38,22 +47,18 @@ public class AuthStorage {
ThreadFactory platformThreadFactory = core.getPlugin().getThreadFactory(); ThreadFactory platformThreadFactory = core.getPlugin().getThreadFactory();
if (platformThreadFactory != null) { if (platformThreadFactory != null) {
config.setThreadFactory(new ThreadFactoryBuilder() config.setThreadFactory(platformThreadFactory);
.setNameFormat(core.getPlugin().getName() + " Database Pool Thread #%1$d")
//Hikari create daemons by default
.setDaemon(true)
.setThreadFactory(platformThreadFactory)
.build());
} }
databasePath = databasePath.replace("{pluginDir}", core.getPlugin().getDataFolder().getAbsolutePath()); String pluginFolder = core.getPlugin().getPluginFolder().toAbsolutePath().toString();
databasePath = databasePath.replace("{pluginDir}", pluginFolder);
String jdbcUrl = "jdbc:"; String jdbcUrl = "jdbc:";
if (driver.contains("sqlite")) { if (driver.contains("sqlite")) {
jdbcUrl += "sqlite" + "://" + databasePath; jdbcUrl += "sqlite://" + databasePath;
config.setConnectionTestQuery("SELECT 1"); config.setConnectionTestQuery("SELECT 1");
} else { } else {
jdbcUrl += "mysql" + "://" + host + ':' + port + '/' + databasePath; jdbcUrl += "mysql://" + host + ':' + port + '/' + databasePath;
} }
config.setJdbcUrl(jdbcUrl); config.setJdbcUrl(jdbcUrl);
@ -84,8 +89,7 @@ public class AuthStorage {
public PlayerProfile loadProfile(String name) { public PlayerProfile loadProfile(String name) {
try (Connection con = dataSource.getConnection(); try (Connection con = dataSource.getConnection();
PreparedStatement loadStmt = con.prepareStatement("SELECT * FROM " PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_NAME)) {
+ PREMIUM_TABLE + " WHERE Name=? LIMIT 1")) {
loadStmt.setString(1, name); loadStmt.setString(1, name);
try (ResultSet resultSet = loadStmt.executeQuery()) { try (ResultSet resultSet = loadStmt.executeQuery()) {
@ -96,7 +100,7 @@ public class AuthStorage {
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(); Instant lastLogin = resultSet.getTimestamp(6).toInstant();
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, "");
@ -111,8 +115,7 @@ public class AuthStorage {
public PlayerProfile loadProfile(UUID uuid) { public PlayerProfile loadProfile(UUID uuid) {
try (Connection con = dataSource.getConnection(); try (Connection con = dataSource.getConnection();
PreparedStatement loadStmt = con.prepareStatement("SELECT * FROM " PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_UUID)) {
+ PREMIUM_TABLE + " WHERE UUID=? LIMIT 1")) {
loadStmt.setString(1, uuid.toString().replace("-", "")); loadStmt.setString(1, uuid.toString().replace("-", ""));
try (ResultSet resultSet = loadStmt.executeQuery()) { try (ResultSet resultSet = loadStmt.executeQuery()) {
@ -122,7 +125,7 @@ public class AuthStorage {
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(); Instant lastLogin = resultSet.getTimestamp(6).toInstant();
return new PlayerProfile(userId, uuid, name, premium, lastIp, lastLogin); return new PlayerProfile(userId, uuid, name, premium, lastIp, lastLogin);
} }
} }
@ -138,8 +141,7 @@ public class AuthStorage {
UUID uuid = playerProfile.getUuid(); UUID uuid = playerProfile.getUuid();
if (playerProfile.getUserId() == -1) { if (playerProfile.getUserId() == -1) {
try (PreparedStatement saveStmt = con.prepareStatement("INSERT INTO " + PREMIUM_TABLE try (PreparedStatement saveStmt = con.prepareStatement(INSERT_PROFILE, RETURN_GENERATED_KEYS)) {
+ " (UUID, Name, Premium, LastIp) VALUES (?, ?, ?, ?) ", Statement.RETURN_GENERATED_KEYS)) {
if (uuid == null) { if (uuid == null) {
saveStmt.setString(1, null); saveStmt.setString(1, null);
} else { } else {
@ -159,8 +161,7 @@ public class AuthStorage {
} }
} }
} else { } else {
try (PreparedStatement saveStmt = con.prepareStatement("UPDATE " + PREMIUM_TABLE try (PreparedStatement saveStmt = con.prepareStatement(UPDATE_PROFILE)) {
+ " SET UUID=?, Name=?, Premium=?, LastIp=?, LastLogin=CURRENT_TIMESTAMP WHERE UserID=?")) {
if (uuid == null) { if (uuid == null) {
saveStmt.setString(1, null); saveStmt.setString(1, null);
} else { } else {

View File

@ -136,8 +136,9 @@ public class CompatibleCacheBuilder<K, V> {
* <p> * <p>
* <p> * <p>
* When {@code size} is zero, elements will be evicted immediately after being loaded into the cache. This has the * When {@code size} is zero, elements will be evicted immediately after being loaded into the cache. This has the
* same effect as invoking {@link #expireAfterWrite expireAfterWrite}{@code (0, unit)} or {@link #expireAfterAccess expireAfterAccess}{@code (0, * same effect as invoking {@link #expireAfterWrite expireAfterWrite}{@code (0, unit)} or
* unit)}. It can be useful in testing, or to disable caching temporarily without a code change. * {@link #expireAfterAccess expireAfterAccess}{@code (0,unit)}.
* It can be useful in testing, or to disable caching temporarily without a code change.
* *
* @param size the maximum size of the cache * @param size the maximum size of the cache
* @return This for chaining * @return This for chaining
@ -180,7 +181,8 @@ public class CompatibleCacheBuilder<K, V> {
* @throws IllegalStateException if a removal listener was already set * @throws IllegalStateException if a removal listener was already set
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <K1 extends K, V1 extends V> CompatibleCacheBuilder<K1, V1> removalListener(RemovalListener<? super K1, ? super V1> listener) { public <K1 extends K, V1 extends V> CompatibleCacheBuilder<K1, V1> removalListener(
RemovalListener<? super K1, ? super V1> listener) {
builder.removalListener(listener); builder.removalListener(listener);
return (CompatibleCacheBuilder<K1, V1>) this; return (CompatibleCacheBuilder<K1, V1>) this;
} }

View File

@ -1,5 +1,6 @@
package com.github.games647.fastlogin.core; package com.github.games647.fastlogin.core;
import java.time.Instant;
import java.util.UUID; import java.util.UUID;
public class PlayerProfile { public class PlayerProfile {
@ -11,9 +12,9 @@ public class PlayerProfile {
private UUID uuid; private UUID uuid;
private boolean premium; private boolean premium;
private String lastIp; private String lastIp;
private long lastLogin; private Instant lastLogin;
public PlayerProfile(long userId, UUID uuid, String playerName, boolean premium, String lastIp, long lastLogin) { public PlayerProfile(long userId, UUID uuid, String playerName, boolean premium, String lastIp, Instant lastLogin) {
this.userId = userId; this.userId = userId;
this.uuid = uuid; this.uuid = uuid;
this.playerName = playerName; this.playerName = playerName;
@ -23,7 +24,7 @@ public class PlayerProfile {
} }
public PlayerProfile(UUID uuid, String playerName, boolean premium, String lastIp) { public PlayerProfile(UUID uuid, String playerName, boolean premium, String lastIp) {
this(-1, uuid, playerName, premium, lastIp, System.currentTimeMillis()); this(-1, uuid, playerName, premium, lastIp, Instant.now());
} }
public synchronized String getPlayerName() { public synchronized String getPlayerName() {
@ -66,11 +67,11 @@ public class PlayerProfile {
this.lastIp = lastIp; this.lastIp = lastIp;
} }
public synchronized long getLastLogin() { public synchronized Instant getLastLogin() {
return lastLogin; return lastLogin;
} }
public synchronized void setLastLogin(long lastLogin) { public synchronized void setLastLogin(Instant lastLogin) {
this.lastLogin = lastLogin; this.lastLogin = lastLogin;
} }
} }

View File

@ -3,7 +3,8 @@ package com.github.games647.fastlogin.core.hooks;
/** /**
* Represents a supporting authentication plugin in BungeeCord and Bukkit/Spigot/... servers * Represents a supporting authentication plugin in BungeeCord and Bukkit/Spigot/... servers
* *
* @param <P> either org.bukkit.entity.GameProfile for Bukkit or net.md_5.bungee.api.connection.ProxiedPlayer for BungeeCord * @param <P> either org.bukkit.entity.GameProfile for Bukkit or net.md_5.bungee.api.connection.ProxiedPlayer
* for BungeeCord
*/ */
public interface AuthPlugin<P> { public interface AuthPlugin<P> {

View File

@ -20,6 +20,8 @@ import java.net.Proxy;
import java.net.Proxy.Type; import java.net.Proxy.Type;
import java.net.URL; import java.net.URL;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.time.Duration;
import java.time.Instant;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -53,7 +55,7 @@ public class MojangApiConnector {
private final SSLSocketFactory sslFactory; private final SSLSocketFactory sslFactory;
private final int rateLimit; private final int rateLimit;
private long lastRateLimit; private Instant lastRateLimit;
protected final Gson gson = new GsonBuilder().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create(); protected final Gson gson = new GsonBuilder().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create();
protected final Logger logger; protected final Logger logger;
@ -72,9 +74,6 @@ public class MojangApiConnector {
this.proxies = Iterables.cycle(proxyBuilder).iterator(); this.proxies = Iterables.cycle(proxyBuilder).iterator();
} }
/**
* @return null on non-premium
*/
public Optional<UUID> getPremiumUUID(String playerName) { public Optional<UUID> getPremiumUUID(String playerName) {
if (!validNameMatcher.matcher(playerName).matches()) { if (!validNameMatcher.matcher(playerName).matches()) {
//check if it's a valid player name //check if it's a valid player name
@ -83,7 +82,7 @@ public class MojangApiConnector {
try { try {
HttpsURLConnection connection; HttpsURLConnection connection;
if (requests.size() >= rateLimit || System.currentTimeMillis() - lastRateLimit < 1_000 * 60 * 10) { if (requests.size() >= rateLimit || Duration.between(lastRateLimit, Instant.now()).getSeconds() < 60 * 10) {
synchronized (proxies) { synchronized (proxies) {
if (proxies.hasNext()) { if (proxies.hasNext()) {
connection = getConnection(UUID_LINK + playerName, proxies.next()); connection = getConnection(UUID_LINK + playerName, proxies.next());
@ -103,7 +102,7 @@ public class MojangApiConnector {
} }
} else if (connection.getResponseCode() == RATE_LIMIT_CODE) { } else if (connection.getResponseCode() == RATE_LIMIT_CODE) {
logger.info("RATE_LIMIT REACHED"); logger.info("RATE_LIMIT REACHED");
lastRateLimit = System.currentTimeMillis(); lastRateLimit = Instant.now();
if (!connection.usingProxy()) { if (!connection.usingProxy()) {
return getPremiumUUID(playerName); return getPremiumUUID(playerName);
} }
@ -153,25 +152,25 @@ public class MojangApiConnector {
} }
private SSLSocketFactory buildAddresses(Logger logger, Collection<String> localAddresses) { private SSLSocketFactory buildAddresses(Logger logger, Collection<String> localAddresses) {
if (localAddresses.isEmpty()) { if (!localAddresses.isEmpty()) {
return HttpsURLConnection.getDefaultSSLSocketFactory(); return HttpsURLConnection.getDefaultSSLSocketFactory();
} else {
Set<InetAddress> addresses = Sets.newHashSet();
for (String localAddress : localAddresses) {
try {
InetAddress address = InetAddress.getByName(localAddress);
if (!address.isAnyLocalAddress()) {
logger.warn("Submitted IP-Address is not local {0}", address);
continue;
}
addresses.add(address);
} catch (UnknownHostException ex) {
logger.error("IP-Address is unknown to us", ex);
}
}
return new BalancedSSLFactory(HttpsURLConnection.getDefaultSSLSocketFactory(), addresses);
} }
Set<InetAddress> addresses = Sets.newHashSet();
for (String localAddress : localAddresses) {
try {
InetAddress address = InetAddress.getByName(localAddress);
if (!address.isAnyLocalAddress()) {
logger.warn("Submitted IP-Address is not local {}", address);
continue;
}
addresses.add(address);
} catch (UnknownHostException ex) {
logger.error("IP-Address is unknown to us", ex);
}
}
return new BalancedSSLFactory(HttpsURLConnection.getDefaultSSLSocketFactory(), addresses);
} }
} }

View File

@ -2,13 +2,11 @@ package com.github.games647.fastlogin.core.mojang;
public class SkinProperties { public class SkinProperties {
private final String name = "textures";
private String value; private String value;
private String signature; private String signature;
public String getName() {
return "textures";
}
public String getValue() { public String getValue() {
return value; return value;
} }

View File

@ -11,18 +11,10 @@ import java.util.UUID;
public class UUIDTypeAdapter extends TypeAdapter<UUID> { public class UUIDTypeAdapter extends TypeAdapter<UUID> {
public void write(JsonWriter out, UUID value) throws IOException { public void write(JsonWriter out, UUID value) throws IOException {
out.value(fromUUID(value)); out.value(value.toString().replace("-", ""));
} }
public UUID read(JsonReader in) throws IOException { public UUID read(JsonReader in) throws IOException {
return fromString(in.nextString()); return CommonUtil.parseId(in.nextString());
}
public static String fromUUID(UUID value) {
return value.toString().replace("-", "");
}
public static UUID fromString(String input) {
return CommonUtil.parseId(input);
} }
} }

View File

@ -90,7 +90,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
defaults = configProvider.load(defaultStream); defaults = configProvider.load(defaultStream);
} }
File file = new File(plugin.getDataFolder(), fileName); File file = plugin.getPluginFolder().resolve(fileName).toFile();
return configProvider.load(file, defaults); return configProvider.load(file, defaults);
} }
@ -167,7 +167,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
} }
public void saveDefaultFile(String fileName) { public void saveDefaultFile(String fileName) {
Path dataFolder = plugin.getDataFolder().toPath(); Path dataFolder = plugin.getPluginFolder();
try { try {
Files.createDirectories(dataFolder); Files.createDirectories(dataFolder);

View File

@ -3,7 +3,7 @@ package com.github.games647.fastlogin.core.shared;
import com.github.games647.fastlogin.core.mojang.MojangApiConnector; import com.github.games647.fastlogin.core.mojang.MojangApiConnector;
import com.google.common.net.HostAndPort; import com.google.common.net.HostAndPort;
import java.io.File; import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
@ -13,7 +13,7 @@ public interface PlatformPlugin<C> {
String getName(); String getName();
File getDataFolder(); Path getPluginFolder();
Logger getLog(); Logger getLog();

View File

@ -62,8 +62,8 @@ premiumUuid: false
# #### Case 1 # #### Case 1
# nameChangeCheck = false ----- autoRegister = false # nameChangeCheck = false ----- autoRegister = false
# #
# GameProfile logins as cracked until the player invoked the command /premium. Then we could override the existing database # GameProfile logins as cracked until the player invoked the command /premium. Then we could override the existing
# record. # database record.
# #
# #### Case 2 # #### Case 2
# #
@ -128,8 +128,8 @@ premium-warning: true
# Once the limit is reached, new players are always logged in as cracked until the rate-limit is expired. # Once the limit is reached, new players are always logged in as cracked until the rate-limit is expired.
# (to the next ten minutes) # (to the next ten minutes)
# #
# The limit is IP-wide. If you have multiple IPv4-addresses you specify them here. FastLogin will then use it in rotating # The limit is IP-wide. If you have multiple IPv4-addresses you specify them here. FastLogin will then use it in
# order --> 5 different IP-addresses 5 * 600 per 10 minutes # rotating order --> 5 different IP-addresses 5 * 600 per 10 minutes
# If this list is empty only the default one will be used # If this list is empty only the default one will be used
# #
# Lists are created like this: # Lists are created like this:

View File

@ -86,7 +86,7 @@ invalid-session: '&4Invalid session'
# The client sent a malicious packet without a login request packet # The client sent a malicious packet without a login request packet
invalid-requst: '&4Invalid request' invalid-requst: '&4Invalid request'
# Message if the bukkit isn't fully started to inject the packets # Message if the Bukkit isn't fully started to inject the packets
not-started: '&cServer is not fully started yet. Please retry' not-started: '&cServer is not fully started yet. Please retry'
# Warning message if a user invoked /premium command # Warning message if a user invoked /premium command