Merge the Bukkit and BungeeCord version together to a universal plugin

This commit is contained in:
games647
2015-11-14 20:03:24 +01:00
parent c3f8e59a9a
commit f8c10d6890
30 changed files with 377 additions and 354 deletions

2
.gitignore vendored
View File

@ -39,4 +39,4 @@ hs_err_pid*
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
!gradle-wrapper.jar

View File

@ -1,3 +1,7 @@
######0.3.1
* Improved BungeeCord security
#####0.3
* Added BungeeCord support

View File

@ -3,7 +3,7 @@
[![Build Status](https://travis-ci.org/games647/FastLogin.svg?branch=master)](https://travis-ci.org/games647/FastLogin)
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.
So they don't need to enter passwords. This is also called auto login (auto-login).
###Features:
* Detect paid accounts from others
@ -12,8 +12,9 @@ So they don't need to enter passwords. This is also called auto login.
* Experimental Cauldron support
* BungeeCord support
* No client modifications needed
* Good performance by async non blocking operations
* Good performance by using async non blocking operations
* Free
* Open source
***
@ -118,8 +119,10 @@ 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. This plugin will automatically detect if BungeeCord is running and so handle checks
there.
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.
####Could premium players have a premium UUID and Skin?
Something like that is possible, but is not yet implemented.

116
bukkit/pom.xml Normal file
View File

@ -0,0 +1,116 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin-parent</artifactId>
<version>0.3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<!--This have to be in lowercase because it's used by plugin.yml-->
<artifactId>fastlogin.bukkit</artifactId>
<packaging>jar</packaging>
<name>FastLoginBukkit</name>
<repositories>
<!--Bukkit-Server-API -->
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<!--ProtocolLib-->
<repository>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/content/groups/public/</url>
</repository>
<!--Authme Reloaded-->
<repository>
<id>xephi-repo</id>
<url>http://ci.xephi.fr/plugin/repository/everything/</url>
</repository>
<!--xAuth-->
<repository>
<id>luricos.de-repo</id>
<url>http://repo.luricos.de/bukkit-plugins/</url>
</repository>
</repositories>
<dependencies>
<!--Server API-->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Library for listening and sending Minecraft packets-->
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>3.6.5-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<!--Login Plugins-->
<dependency>
<groupId>fr.xephi</groupId>
<artifactId>authme</artifactId>
<version>5.1-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>de.luricos.bukkit</groupId>
<artifactId>xAuth</artifactId>
<version>2.6</version>
<optional>true</optional>
<!--These artifacts produce conflicts on downloading-->
<exclusions>
<exclusion>
<groupId>net.gravitydevelopment.updater</groupId>
<artifactId>updater</artifactId>
</exclusion>
<exclusion>
<groupId>net.ess3</groupId>
<artifactId>EssentialsGroupManager</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--No maven repository :(-->
<dependency>
<groupId>de.st_ddt.crazy</groupId>
<artifactId>CrazyCore</artifactId>
<version>10.7.7</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/CrazyCore v10.7.7.jar</systemPath>
</dependency>
<dependency>
<groupId>de.st_ddt.crazy</groupId>
<artifactId>CrazyLogin</artifactId>
<version>7.23</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/CrazyLogin v7.23.2.jar</systemPath>
</dependency>
<!--Maven repo down :(-->
<dependency>
<groupId>me.lenis0012.ls</groupId>
<artifactId>LoginSecurity</artifactId>
<version>2.0.10</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/LoginSecurity v2.0.10.jar</systemPath>
</dependency>
</dependencies>
</project>

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin;
package com.github.games647.fastlogin.bukkit;
import com.google.common.base.Charsets;

View File

@ -1,14 +1,14 @@
package com.github.games647.fastlogin;
package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.bukkit.listener.BukkitJoinListener;
import com.github.games647.fastlogin.bukkit.listener.StartPacketListener;
import com.github.games647.fastlogin.bukkit.listener.BungeeCordListener;
import com.github.games647.fastlogin.bukkit.listener.EncryptionPacketListener;
import com.github.games647.fastlogin.bukkit.listener.HandshakePacketListener;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.utility.SafeCacheBuilder;
import com.github.games647.fastlogin.hooks.AuthPlugin;
import com.github.games647.fastlogin.listener.BukkitJoinListener;
import com.github.games647.fastlogin.listener.BungeeCordListener;
import com.github.games647.fastlogin.listener.EncryptionPacketListener;
import com.github.games647.fastlogin.listener.HandshakePacketListener;
import com.github.games647.fastlogin.listener.StartPacketListener;
import com.github.games647.fastlogin.bukkit.hooks.AuthPlugin;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Sets;
@ -29,7 +29,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 FastLogin extends JavaPlugin {
public class FastLoginBukkit extends JavaPlugin {
//http connection, read timeout and user agent for a connection to mojang api servers
private static final int TIMEOUT = 1 * 1000;
@ -86,7 +86,8 @@ public class FastLogin extends JavaPlugin {
getCommand("premium").setExecutor(new PremiumCommand(this));
//check for incoming messages from the bungeecord version of this plugin
getServer().getMessenger().registerIncomingPluginChannel(this, this.getName(), new BungeeCordListener(this));
getServer().getMessenger().registerIncomingPluginChannel(this, getName(), new BungeeCordListener(this));
getServer().getMessenger().registerOutgoingPluginChannel(this, getName());
}
@Override
@ -95,6 +96,11 @@ public class FastLogin extends JavaPlugin {
session.clear();
enabledPremium.clear();
bungeeCordUsers.clear();
//remove old blacklists
for (Player player : getServer().getOnlinePlayers()) {
player.removeMetadata(getName(), this);
}
}
/**

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin;
package com.github.games647.fastlogin.bukkit;
import org.apache.commons.lang.ArrayUtils;

View File

@ -1,5 +1,7 @@
package com.github.games647.fastlogin;
package com.github.games647.fastlogin.bukkit;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@ -13,9 +15,9 @@ import org.bukkit.entity.Player;
*/
public class PremiumCommand implements CommandExecutor {
private final FastLogin plugin;
private final FastLoginBukkit plugin;
public PremiumCommand(FastLogin plugin) {
public PremiumCommand(FastLoginBukkit plugin) {
this.plugin = plugin;
}
@ -31,9 +33,17 @@ public class PremiumCommand implements CommandExecutor {
String playerName = sender.getName();
plugin.getEnabledPremium().add(playerName);
sender.sendMessage(ChatColor.DARK_GREEN + "Added to the list of premium players");
notifiyBungeeCord((Player) sender);
return true;
}
return true;
}
private void notifiyBungeeCord(Player target) {
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
dataOutput.writeUTF("ACTIVE");
target.sendPluginMessage(plugin, plugin.getName(), dataOutput.toByteArray());
}
}

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.hooks;
package com.github.games647.fastlogin.bukkit.hooks;
import fr.xephi.authme.api.NewAPI;

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.hooks;
package com.github.games647.fastlogin.bukkit.hooks;
import org.bukkit.entity.Player;

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.hooks;
package com.github.games647.fastlogin.bukkit.hooks;
import de.st_ddt.crazylogin.CrazyLogin;
import de.st_ddt.crazylogin.data.LoginPlayerData;

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.hooks;
package com.github.games647.fastlogin.bukkit.hooks;
import com.lenis0012.bukkit.ls.LoginSecurity;

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.hooks;
package com.github.games647.fastlogin.bukkit.hooks;
import de.luricos.bukkit.xAuth.xAuth;
import de.luricos.bukkit.xAuth.xAuthPlayer;

View File

@ -0,0 +1,66 @@
package com.github.games647.fastlogin.bukkit.listener;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.PlayerSession;
import com.github.games647.fastlogin.bukkit.hooks.AuthPlugin;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.metadata.FixedMetadataValue;
/**
* This listener tells authentication plugins if the player has a premium account and we checked it successfully.
* So the plugin can skip authentication.
*/
public class BukkitJoinListener implements Listener {
private static final long DELAY_LOGIN = 1 * 20L / 2;
protected final FastLoginBukkit plugin;
protected final AuthPlugin authPlugin;
public BukkitJoinListener(FastLoginBukkit plugin, AuthPlugin authPlugin) {
this.plugin = plugin;
this.authPlugin = authPlugin;
}
@EventHandler(ignoreCancelled = true)
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
final Player player = joinEvent.getPlayer();
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
String address = player.getAddress().toString();
//removing the session because we now use it
PlayerSession session = plugin.getSessions().remove(address);
if (player.isOnline()) {
//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
if (session != null && player.getName().equals(session.getUsername()) && session.isVerified()) {
plugin.getLogger().log(Level.FINE, "Logging player {0} in", player.getName());
authPlugin.forceLogin(player);
}
}
}
//Wait before auth plugin and we received a message from BungeeCord initializes the player
}, DELAY_LOGIN);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
final Player player = quitEvent.getPlayer();
//prevent memory leaks
player.removeMetadata(plugin.getName(), plugin);
}
}

View File

@ -1,7 +1,7 @@
package com.github.games647.fastlogin.listener;
package com.github.games647.fastlogin.bukkit.listener;
import com.github.games647.fastlogin.FastLogin;
import com.github.games647.fastlogin.PlayerSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.PlayerSession;
import com.google.common.base.Charsets;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
@ -13,23 +13,24 @@ import java.util.UUID;
import java.util.logging.Level;
import org.bukkit.entity.Player;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.plugin.messaging.PluginMessageListener;
/**
* Responsible for receiving messages from a BungeeCord instance.
*
* This class also receives the plugin message from the bungeecord version of this plugin in order to
* get notified if the connection is in online mode.
* This class also receives the plugin message from the bungeecord version of this plugin in order to get notified if
* the connection is in online mode.
*/
public class BungeeCordListener implements PluginMessageListener {
private static final String FILE_NAME = "proxy-whitelist.txt";
private final FastLogin plugin;
private final FastLoginBukkit plugin;
//null if whitelist is empty so bungeecord support is disabled
private final UUID proxyId;
public BungeeCordListener(FastLogin plugin) {
public BungeeCordListener(FastLoginBukkit plugin) {
this.plugin = plugin;
this.proxyId = loadBungeeCordId();
}
@ -44,23 +45,30 @@ public class BungeeCordListener implements PluginMessageListener {
String subchannel = dataInput.readUTF();
plugin.getLogger().log(Level.FINEST, "Received plugin message for subchannel {0} from {1}"
, new Object[]{subchannel, player});
if ("Checked".equalsIgnoreCase(subchannel)) {
//bungeecord UUID
long mostSignificantBits = dataInput.readLong();
long leastSignificantBits = dataInput.readLong();
UUID sourceId = new UUID(mostSignificantBits, leastSignificantBits);
//fails too if no proxy id is specified in the whitelist file
if (sourceId.equals(proxyId)) {
//make sure the proxy is allowed to transfer data to us
String playerName = dataInput.readUTF();
//check if the player is still online or disconnected
Player checkedPlayer = plugin.getServer().getPlayerExact(playerName);
if (checkedPlayer != null && checkedPlayer.isOnline()) {
if ("CHECKED".equalsIgnoreCase(subchannel)) {
//make sure the proxy is allowed to transfer data to us
String playerName = dataInput.readUTF();
//check if the player is still online or disconnected
Player checkedPlayer = plugin.getServer().getPlayerExact(playerName);
if (checkedPlayer != null && checkedPlayer.isOnline()
//fail if target player is blacklisted because already authed or wrong bungeecord id
&& !checkedPlayer.hasMetadata(plugin.getName())) {
//bungeecord UUID
long mostSignificantBits = dataInput.readLong();
long leastSignificantBits = dataInput.readLong();
UUID sourceId = new UUID(mostSignificantBits, leastSignificantBits);
//fail if BungeeCord support is disabled (id = null)
if (sourceId.equals(proxyId)) {
PlayerSession playerSession = new PlayerSession(playerName, null, null);
playerSession.setVerified(true);
//put it only if the user doesn't has a session open
//so that the player have to send the bungeecord packet and cannot skip the verification then
plugin.getSessions().putIfAbsent(checkedPlayer.getAddress().toString(), playerSession);
} else {
//blacklist target for the current login
checkedPlayer.setMetadata(plugin.getName(), new FixedMetadataValue(plugin, true));
}
}
}

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.listener;
package com.github.games647.fastlogin.bukkit.listener;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolManager;
@ -9,9 +9,9 @@ import com.comphenix.protocol.injector.server.TemporaryPlayerFactory;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.github.games647.fastlogin.EncryptionUtil;
import com.github.games647.fastlogin.FastLogin;
import com.github.games647.fastlogin.PlayerSession;
import com.github.games647.fastlogin.bukkit.EncryptionUtil;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.PlayerSession;
import java.io.BufferedReader;
import java.io.InputStreamReader;
@ -54,9 +54,9 @@ public class EncryptionPacketListener extends PacketAdapter {
private final ProtocolManager protocolManager;
//hides the inherit Plugin plugin field, but we need this type
private final FastLogin plugin;
private final FastLoginBukkit plugin;
public EncryptionPacketListener(FastLogin plugin, ProtocolManager protocolManger) {
public EncryptionPacketListener(FastLoginBukkit plugin, ProtocolManager protocolManger) {
//run async in order to not block the server, because we make api calls to Mojang
super(params(plugin, PacketType.Login.Client.ENCRYPTION_BEGIN).optionAsync());

View File

@ -1,10 +1,10 @@
package com.github.games647.fastlogin.listener;
package com.github.games647.fastlogin.bukkit.listener;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.github.games647.fastlogin.FastLogin;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import java.util.logging.Level;
@ -27,9 +27,9 @@ import java.util.logging.Level;
public class HandshakePacketListener extends PacketAdapter {
//hides the inherit Plugin plugin field, but we need a more detailed type than just Plugin
private final FastLogin plugin;
private final FastLoginBukkit plugin;
public HandshakePacketListener(FastLogin plugin) {
public HandshakePacketListener(FastLoginBukkit plugin) {
//run async in order to not block the server, because we are making api calls to Mojang
super(params(plugin, PacketType.Handshake.Client.SET_PROTOCOL).optionAsync());

View File

@ -1,12 +1,12 @@
package com.github.games647.fastlogin.listener;
package com.github.games647.fastlogin.bukkit.listener;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.github.games647.fastlogin.FastLogin;
import com.github.games647.fastlogin.PlayerSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.PlayerSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
@ -40,14 +40,14 @@ public class StartPacketListener extends PacketAdapter {
private final ProtocolManager protocolManager;
//hides the inherit Plugin plugin field, but we need a more detailed type than just Plugin
private final FastLogin plugin;
private final FastLoginBukkit plugin;
//just create a new once on plugin enable. This used for verify token generation
private final Random random = new Random();
//compile the pattern on plugin enable
private final Pattern playernameMatcher = Pattern.compile(VALID_PLAYERNAME);
public StartPacketListener(FastLogin plugin, ProtocolManager protocolManger) {
public StartPacketListener(FastLoginBukkit plugin, ProtocolManager protocolManger) {
//run async in order to not block the server, because we are making api calls to Mojang
super(params(plugin, PacketType.Login.Client.START).optionAsync());

View File

@ -1,6 +1,6 @@
# project informations for Bukkit in order to register our plugin with all it components
# ${project.name} are variables from Maven (pom.xml) which will be replaced after the build
name: ${project.name}
# ${-} are variables from Maven (pom.xml) which will be replaced after the build
name: ${project.parent.name}
version: ${project.version}
main: ${project.groupId}.${project.artifactId}.${project.name}
@ -21,13 +21,13 @@ softdepend:
- LoginSecurity
commands:
${project.artifactId}.:
${project.parent.name}:
description: 'Label the invoker or the player specified as premium'
aliases: [prem, premium, loginfast]
usage: /<command> [player]
permission: ${project.artifactId}.command.premium
permissions:
${project.artifactId}.command.premium:
${project.parent.name}.command.premium:
description: 'Label themselves as premium using a command'
default: true

View File

@ -2,82 +2,19 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.games647</groupId>
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin-parent</artifactId>
<version>0.3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<!--This have to be in lowercase because it's used by plugin.yml-->
<artifactId>fastloginbungee</artifactId>
<artifactId>fastlogin.bungee</artifactId>
<packaging>jar</packaging>
<name>FastLogin</name>
<version>0.1</version>
<inceptionYear>2015</inceptionYear>
<url>https://github.com/games647/FastLogin</url>
<description>
Automatically logins premium (paid accounts) player on a offline mode server
</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--Possibility to deploy directly to the plugins folder-->
<outputDir>${basedir}/target</outputDir>
</properties>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/games647/FastLogin/issues</url>
</issueManagement>
<scm>
<url>https://github.com/games647/FastLogin</url>
<connection>scm:git:git://github.com/games647/FastLogin.git</connection>
<developerConnection>scm:git:ssh://git@github.com:games647/FastLogin.git</developerConnection>
</scm>
<build>
<defaultGoal>install</defaultGoal>
<!--Just use the project name to replace an old version of the plugin if the user does only copy-paste-->
<finalName>${project.name}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
<!--false means actual true http://jira.codehaus.org/browse/MCOMPILER-209-->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<outputDirectory>${outputDir}</outputDirectory>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<!--Replace variables-->
<filtering>true</filtering>
</resource>
<!--Add the license to jar in order to see it in the final jar-->
<resource>
<directory>${basedir}</directory>
<includes>
<include>LICENSE</include>
</includes>
</resource>
</resources>
</build>
<!--Represents the main plugin-->
<name>FastLoginBungee</name>
<repositories>
<!-- BungeeCord -->

View File

@ -1,4 +1,4 @@
package com.github.games647.fastloginbungee;
package com.github.games647.fastlogin.bungee;
import com.google.common.collect.Sets;
@ -10,7 +10,7 @@ import net.md_5.bungee.api.plugin.Plugin;
* BungeeCord version of FastLogin. This plugin keeps track
* on online mode connections.
*/
public class FastLogin extends Plugin {
public class FastLoginBungee extends Plugin {
private final Set<String> enabledPremium = Sets.newConcurrentHashSet();
@ -19,8 +19,8 @@ public class FastLogin extends Plugin {
//events
getProxy().getPluginManager().registerListener(this, new PlayerConnectionListener(this));
//commands
getProxy().getPluginManager().registerCommand(this, new PremiumCommand(this));
//this is required to listen to messages from the server
getProxy().registerChannel(getDescription().getName());
}
/**

View File

@ -1,5 +1,6 @@
package com.github.games647.fastloginbungee;
package com.github.games647.fastlogin.bungee;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
@ -21,9 +22,9 @@ import net.md_5.bungee.event.EventHandler;
*/
public class PlayerConnectionListener implements Listener {
private final FastLogin plugin;
private final FastLoginBungee plugin;
public PlayerConnectionListener(FastLogin plugin) {
public PlayerConnectionListener(FastLoginBungee plugin) {
this.plugin = plugin;
}
@ -50,16 +51,16 @@ public class PlayerConnectionListener implements Listener {
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
//subchannel name
dataOutput.writeUTF("Checked");
dataOutput.writeUTF("CHECKED");
//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());
//Data is sent through a random player. We have to tell the Bukkit version of this plugin the target
dataOutput.writeUTF(player.getName());
server.sendData(plugin.getDescription().getName(), dataOutput.toByteArray());
}
}
@ -74,5 +75,16 @@ public class PlayerConnectionListener implements Listener {
//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();
if ("ACTIVE".equals(subchannel)) {
ProxiedPlayer forPlayer = (ProxiedPlayer) pluginMessageEvent.getReceiver();
plugin.getEnabledPremium().add(forPlayer.getName());
}
}
}
}

View File

@ -1,38 +0,0 @@
package com.github.games647.fastloginbungee;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
/**
* Let players activate the fastlogin method on a BungeeCord instance.
*/
public class PremiumCommand extends Command {
private final FastLogin plugin;
public PremiumCommand(FastLogin plugin) {
super(plugin.getDescription().getName()
, plugin.getDescription().getName() + ".command." + "premium"
, "prem" , "premium", "loginfast");
this.plugin = plugin;
}
@Override
public void execute(CommandSender sender, String[] args) {
if (!(sender instanceof ProxiedPlayer)) {
sender.sendMessage(new ComponentBuilder("Only player can invoke this command")
.color(ChatColor.DARK_RED)
.create());
return;
}
plugin.getEnabledPremium().add(sender.getName());
sender.sendMessage(new ComponentBuilder("Added to the list of premium players")
.color(ChatColor.DARK_GREEN)
.create());
}
}

View File

@ -1,8 +1,8 @@
# project informations for BungeeCord
# This file will be prioritised over plugin.yml which can be also used for Bungee
# This make it easy to combine BungeeCord and Bukkit support in one plugin
name: ${project.name}
# ${...} will be automatically replaced by Maven
name: ${project.parent.name}
# ${-} will be automatically replaced by Maven
main: ${project.groupId}.${project.artifactId}.${project.name}
version: ${project.version}

127
pom.xml
View File

@ -4,23 +4,27 @@
<groupId>com.github.games647</groupId>
<!--This have to be in lowercase because it's used by plugin.yml-->
<artifactId>fastlogin</artifactId>
<packaging>jar</packaging>
<artifactId>fastlogin-parent</artifactId>
<packaging>pom</packaging>
<name>FastLogin</name>
<version>0.3</version>
<inceptionYear>2015</inceptionYear>
<url>https://github.com/games647/FastLogin</url>
<url>https://www.spigotmc.org/resources/fastlogin.14153/</url>
<description>
Automatically logins premium (paid accounts) player on a offline mode server
</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--Possibility to deploy directly to the plugins folder-->
<outputDir>${basedir}/target</outputDir>
</properties>
<modules>
<module>bukkit</module>
<module>bungee</module>
<module>universal</module>
</modules>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/games647/FastLogin/issues</url>
@ -41,7 +45,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
@ -51,15 +55,6 @@
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<outputDirectory>${outputDir}</outputDirectory>
</configuration>
</plugin>
</plugins>
<resources>
@ -71,110 +66,12 @@
<!--Add the license to jar in order to see it in the final jar-->
<resource>
<directory>${basedir}</directory>
<!--Parent folder-->
<directory>${basedir}/..</directory>
<includes>
<include>LICENSE</include>
</includes>
</resource>
</resources>
</build>
<repositories>
<!--Bukkit-Server-API -->
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<!--ProtocolLib-->
<repository>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/content/groups/public/</url>
</repository>
<!--Authme Reloaded-->
<repository>
<id>xephi-repo</id>
<url>http://ci.xephi.fr/plugin/repository/everything/</url>
</repository>
<!--xAuth-->
<repository>
<id>luricos.de-repo</id>
<url>http://repo.luricos.de/bukkit-plugins/</url>
</repository>
</repositories>
<dependencies>
<!--Server API-->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Library for listening and sending Minecraft packets-->
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>3.6.5-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<!--Login Plugins-->
<dependency>
<groupId>fr.xephi</groupId>
<artifactId>authme</artifactId>
<version>5.1-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>de.luricos.bukkit</groupId>
<artifactId>xAuth</artifactId>
<version>2.6</version>
<optional>true</optional>
<!--These artifacts produce conflicts on downloading-->
<exclusions>
<exclusion>
<groupId>net.gravitydevelopment.updater</groupId>
<artifactId>updater</artifactId>
</exclusion>
<exclusion>
<groupId>net.ess3</groupId>
<artifactId>EssentialsGroupManager</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--No maven repository :(-->
<dependency>
<groupId>de.st_ddt.crazy</groupId>
<artifactId>CrazyCore</artifactId>
<version>10.7.7</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/CrazyCore v10.7.7.jar</systemPath>
</dependency>
<dependency>
<groupId>de.st_ddt.crazy</groupId>
<artifactId>CrazyLogin</artifactId>
<version>7.23</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/CrazyLogin v7.23.2.jar</systemPath>
</dependency>
<!--Maven repo down :(-->
<dependency>
<groupId>me.lenis0012.ls</groupId>
<artifactId>LoginSecurity</artifactId>
<version>2.0.10</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/LoginSecurity v2.0.10.jar</systemPath>
</dependency>
</dependencies>
</project>

View File

@ -1,53 +0,0 @@
package com.github.games647.fastlogin.listener;
import com.github.games647.fastlogin.FastLogin;
import com.github.games647.fastlogin.PlayerSession;
import com.github.games647.fastlogin.hooks.AuthPlugin;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
/**
* This listener tells authentication plugins if the player has a premium account and we checked it successfully. So the
* plugin can skip authentication.
*/
public class BukkitJoinListener implements Listener {
private static final long DELAY_LOGIN = 2 * 20L;
protected final FastLogin plugin;
protected final AuthPlugin authPlugin;
public BukkitJoinListener(FastLogin plugin, AuthPlugin authPlugin) {
this.plugin = plugin;
this.authPlugin = authPlugin;
}
@EventHandler(ignoreCancelled = true)
public void onJoin(PlayerJoinEvent joinEvent) {
final Player player = joinEvent.getPlayer();
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
String address = player.getAddress().toString();
//removing the session because we now use it
PlayerSession session = plugin.getSessions().remove(address);
//check if it's the same player as we checked before
if (player.isOnline() && session != null
&& player.getName().equals(session.getUsername()) && session.isVerified()) {
plugin.getLogger().log(Level.FINE, "Logging player {0} in", player.getName());
authPlugin.forceLogin(player);
}
}
//Wait before auth plugin and we received a message from BungeeCord initializes the player
}, DELAY_LOGIN);
}
}

55
universal/pom.xml Normal file
View File

@ -0,0 +1,55 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin-parent</artifactId>
<version>0.3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>fastlogin-universal</artifactId>
<packaging>jar</packaging>
<name>FastLoginUniversal</name>
<build>
<defaultGoal>package</defaultGoal>
<finalName>${project.parent.name}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>false</shadedArtifactAttached>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>fastlogin.bukkit</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>fastlogin.bungee</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>