mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-12-23 07:12:39 +01:00
Compare commits
72 Commits
drop-proto
...
authme-ses
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18d2ba5095 | ||
|
|
65469ed579 | ||
|
|
8ecb5657d3 | ||
|
|
b0cf6e39c7 | ||
|
|
88a526b5bf | ||
|
|
57b84509da | ||
|
|
e0bc7d914c | ||
|
|
f1933f735a | ||
|
|
f69154418e | ||
|
|
74b13231f8 | ||
|
|
79627e3b60 | ||
|
|
1722ab3267 | ||
|
|
fdc0485f05 | ||
|
|
1068ddbadd | ||
|
|
b0d5bd606c | ||
|
|
1e59101ada | ||
|
|
46ac3c74e4 | ||
|
|
d22af0f42e | ||
|
|
2cc078773b | ||
|
|
c1b8b60bf7 | ||
|
|
c54d6eecfc | ||
|
|
0cf6c4c188 | ||
|
|
282467d21b | ||
|
|
e8a5dc7433 | ||
|
|
4b45932d6a | ||
|
|
1375cf3997 | ||
|
|
5a5cf016d9 | ||
|
|
2c7e569653 | ||
|
|
94c5fe302e | ||
|
|
c80012ddb1 | ||
|
|
17361b1b54 | ||
|
|
426b458a58 | ||
|
|
62a8b939cc | ||
|
|
327c8c4c9d | ||
|
|
fbbe7a735a | ||
|
|
4110ce2fa2 | ||
|
|
28743d23bf | ||
|
|
145bd95679 | ||
|
|
3fe17cf8d9 | ||
|
|
3446d4c443 | ||
|
|
c528433079 | ||
|
|
25858ea11f | ||
|
|
204ffbb2ee | ||
|
|
9c1ba81cbe | ||
|
|
15c5857c4f | ||
|
|
4b0ad3b186 | ||
|
|
101f7207a9 | ||
|
|
64175fe9e8 | ||
|
|
f7a10d86eb | ||
|
|
542aabad73 | ||
|
|
260b93a565 | ||
|
|
6604cca8bd | ||
|
|
c172b1ec84 | ||
|
|
9b0b8f5fcb | ||
|
|
20104b2b00 | ||
|
|
fd76d2448e | ||
|
|
53a1821a9d | ||
|
|
1c6f4e82e0 | ||
|
|
084afef899 | ||
|
|
8a9eed3a74 | ||
|
|
1ea6d929b1 | ||
|
|
ddc3aa9279 | ||
|
|
2a79a9511b | ||
|
|
791df26702 | ||
|
|
cdf1988f2f | ||
|
|
f476c091bb | ||
|
|
352c72df64 | ||
|
|
2cd0b194aa | ||
|
|
f2e42019d6 | ||
|
|
82ec71e8d0 | ||
|
|
6d207d62ba | ||
|
|
889dab3152 |
@@ -1,6 +1,14 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Something isn't working
|
||||
title: ''
|
||||
labels: 'bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
[//]: # (Lines in this format are considered as comments and will not be displayed.)
|
||||
[//]: #
|
||||
[//]: # (Before reporting make sure you're running the **latest build** of the plugin and checked for duplicate issues!)
|
||||
[//]: # (Before reporting make sure you're running the **latest build** of the plugin and checked for existing issues!)
|
||||
|
||||
### What behaviour is observed:
|
||||
[//]: # (What happened?)
|
||||
@@ -11,18 +19,23 @@
|
||||
### Steps/models to reproduce:
|
||||
[//]: # (The actions that cause the issue. Please explain it in detail)
|
||||
|
||||
### Screenshots (if applicable)
|
||||
[//]: # (You can drop the files here directly)
|
||||
|
||||
### Plugin list:
|
||||
[//]: # (This can be found by running `/pl`)
|
||||
|
||||
### Environment description
|
||||
[//]: # (Server software with exact version number, Minecraft version, SQLite/MySQL, ...)
|
||||
[//]: # (Server software with exact version number, Minecraft version, SQLite/MySQL/MariaDB, ...)
|
||||
|
||||
### Plugin version or build number (don't write latest):
|
||||
[//]: # (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)
|
||||
### Server Log:
|
||||
[//]: # (No images please - only the textual representation)
|
||||
[Hastebin](https://hastebin.com/) / [Gist](https://gist.github.com/) link of the error, stacktrace or the complete log (if any)
|
||||
|
||||
### Configuration:
|
||||
[//]: # (No images please - only the textual representation)
|
||||
[//]: # (remember to delete any sensitive data)
|
||||
[Hastebin](https://hastebin.com/) / [Gist](https://gist.github.com/) link of your config.yml file
|
||||
22
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
Normal file
22
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: Enhancement request
|
||||
about: New feature or change request
|
||||
title: ''
|
||||
labels: 'enhancement'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
[//]: # (Lines in this format are considered as comments and will not be displayed.)
|
||||
|
||||
### Is your feature request related to a problem? Please describe.
|
||||
[//]: # (A clear and concise description of what the problem is. Ex. I'm always frustrated when [...])
|
||||
|
||||
### Describe the solution you'd like
|
||||
[//]: # (A clear and concise description of what you want to happen.)
|
||||
|
||||
### Describe alternatives you've considered
|
||||
[//]: # (A clear and concise description of any alternative solutions or features you've considered.)
|
||||
|
||||
### Additional context
|
||||
[//]: # (Add any other context or screenshots about the feature request here.)
|
||||
10
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Question
|
||||
about: You want to ask something
|
||||
title: ''
|
||||
labels: 'question'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
8
.github/pull_request_template.md
vendored
Normal file
8
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
[//]: # (Lines in this format are considered as comments and will not be displayed.)
|
||||
[//]: # (If your work is in progress, please consider making a draft pull request.)
|
||||
|
||||
### Summary of your change
|
||||
[//]: # (Example: motiviation, enhancement)
|
||||
|
||||
### Related issue
|
||||
[//]: # (Reference it using '#NUMBER'. Ex: Fixes/Related #...)
|
||||
42
.github/workflows/maven.yml
vendored
Normal file
42
.github/workflows/maven.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
# Human readable name
|
||||
name: Java CI
|
||||
|
||||
# Build on every push and pull request regardless of the branch
|
||||
# Wiki: https://help.github.com/en/actions/reference/events-that-trigger-workflows
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
# job id
|
||||
build_and_test:
|
||||
|
||||
# Environment image - always newest OS
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Run steps
|
||||
steps:
|
||||
# Pull changes
|
||||
- uses: actions/checkout@v2
|
||||
# Cache artifacts - however this has the downside that we don't get notified of
|
||||
# artifact resolution failures like invalid repository
|
||||
# Nevertheless the repositories should be more stable and it makes no sense to pull
|
||||
# a same version every time
|
||||
# A dry run would make more sense
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
# Setup Java
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v1.3.0
|
||||
with:
|
||||
# Use Java 8, because it's minimum required version
|
||||
java-version: 8
|
||||
# Build and test (included in package)
|
||||
- name: Build with Maven and test
|
||||
# Run non-interactive, package (with compile+test),
|
||||
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums to validate posssible errors in depdendencies
|
||||
run: mvn --batch-mode package --no-snapshot-updates --strict-checksums --file pom.xml
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -15,6 +15,7 @@ nb-configuration.xml
|
||||
|
||||
# Maven
|
||||
target/
|
||||
pom.xml.versionsBackup
|
||||
|
||||
# Gradle
|
||||
.gradle
|
||||
|
||||
13
.travis.yml
13
.travis.yml
@@ -1,13 +0,0 @@
|
||||
# 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/
|
||||
sudo: false
|
||||
|
||||
# This is a java project
|
||||
language: java
|
||||
|
||||
script: mvn test -B
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
- oraclejdk9
|
||||
56
README.md
56
README.md
@@ -3,7 +3,7 @@
|
||||
Checks if a Minecraft player has a paid account (premium). If so, they can skip offline authentication (auth plugins).
|
||||
So they don't need to enter passwords. This is also called auto login (auto-login).
|
||||
|
||||
### Features:
|
||||
## Features
|
||||
|
||||
* Detect paid accounts from others
|
||||
* Automatically login paid accounts (premium)
|
||||
@@ -20,31 +20,43 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
|
||||
* Good performance by using async non blocking operations
|
||||
* Locale messages
|
||||
* Import the database from similar plugins
|
||||
* Free
|
||||
* Open source
|
||||
|
||||
## Development builds
|
||||
|
||||
Development builds of this project can be acquired at the provided CI (continuous integration) server. It contains the
|
||||
latest changes from the Source-Code in preparation for the following release. This means they could contain new
|
||||
features, bug fixes and other changes since the last release.
|
||||
|
||||
Nevertheless builds are only tested using a small set of automated and a few manual tests. Therefore they **could**
|
||||
contain new bugs and are likely to be less stable than released versions.
|
||||
|
||||
https://ci.codemc.org/job/Games647/job/FastLogin/changes
|
||||
|
||||
***
|
||||
|
||||
### Commands:
|
||||
## Commands
|
||||
|
||||
/premium [player] Label the invoker or the argument as paid account
|
||||
/cracked [player] Label the invoker or the argument as cracked account
|
||||
|
||||
### Permissions:
|
||||
## Permissions
|
||||
|
||||
fastlogin.bukkit.command.premium
|
||||
fastlogin.bukkit.command.cracked
|
||||
fastlogin.command.premium.other
|
||||
fastlogin.command.cracked.other
|
||||
fastlogin.command.import
|
||||
|
||||
### Requirements:
|
||||
* 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+
|
||||
## Requirements
|
||||
|
||||
* Plugin:
|
||||
* [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or
|
||||
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
|
||||
* [Spigot](https://www.spigotmc.org) 1.8.8+
|
||||
* Java 8+
|
||||
* Run Spigot and/or BungeeCord/Waterfall in offline mode (see server.properties or config.yml)
|
||||
* An auth plugin. Supported plugins
|
||||
|
||||
#### Bukkit/Spigot/Paper
|
||||
### Bukkit/Spigot/Paper
|
||||
|
||||
* [AuthMe (5.X)](https://dev.bukkit.org/bukkit-plugins/authme-reloaded/)
|
||||
* [xAuth](https://dev.bukkit.org/bukkit-plugins/xauth/)
|
||||
@@ -54,28 +66,36 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
|
||||
* [LoginSecurity](https://dev.bukkit.org/bukkit-plugins/loginsecurity/)
|
||||
* [UltraAuth](https://dev.bukkit.org/bukkit-plugins/ultraauth-aa/)
|
||||
|
||||
#### BungeeCord/Waterfall
|
||||
### BungeeCord/Waterfall
|
||||
|
||||
* [BungeeAuth](https://www.spigotmc.org/resources/bungeeauth.493/)
|
||||
|
||||
## Network requests
|
||||
|
||||
This plugin performs network requests to:
|
||||
|
||||
* https://api.mojang.com - retrieving uuid data to decide if we should activate premium login
|
||||
* https://sessionserver.mojang.com - verify if the player is the owner of that account
|
||||
|
||||
***
|
||||
|
||||
### How to install
|
||||
## How to install
|
||||
|
||||
#### Bukkit/Spigot/Paper
|
||||
### Bukkit/Spigot/Paper
|
||||
|
||||
1. Download and install ProtocolLib
|
||||
2. Download and install FastLogin
|
||||
1. Download and install ProtocolLib/ProtocolSupport
|
||||
2. Download and install FastLogin (or FastLoginBukkit for newer versions)
|
||||
3. Set your server in offline mode by setting the value onlinemode in your server.properties to false
|
||||
|
||||
#### BungeeCord/Waterfall
|
||||
### BungeeCord/Waterfall
|
||||
|
||||
1. Activate BungeeCord in the Spigot configuration
|
||||
2. Restart your server
|
||||
3. Now there is proxy-whitelist file in the FastLogin folder
|
||||
Put your stats id from the BungeeCord config into this file
|
||||
4. Activate ipForward in your BungeeCord config
|
||||
5. Download and Install FastLogin on BungeeCord AND Spigot (on the servers where your login plugin is)
|
||||
5. Download and Install FastLogin (or FastLoginBungee in newer versions) on BungeeCord AND Spigot
|
||||
(on the servers where your login plugin is or where player should be able to execute the commands of FastLogin)
|
||||
6. Check your database settings in the config of FastLogin on BungeeCord
|
||||
7. Set your proxy (BungeeCord) in offline mode by setting the value onlinemode in your config.yml to false
|
||||
8. You should *always* firewall your Spigot server that it's only accessible through BungeeCord
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<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">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.github.games647</groupId>
|
||||
<artifactId>fastlogin</artifactId>
|
||||
<version>1.11</version>
|
||||
<version>1.11-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.2.2</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
@@ -56,44 +56,52 @@
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<!--Bukkit-Server-API -->
|
||||
<!-- Bukkit-Server-API -->
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
<!-- Disable snapshot release policy to speed up, when finding a artifact -->
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
|
||||
<!--LoginSecurity-->
|
||||
<repository>
|
||||
<id>lenis0012-repo</id>
|
||||
<url>http://ci.lenis0012.com/plugin/repository/everything/</url>
|
||||
</repository>
|
||||
|
||||
<!--ProtocolLib-->
|
||||
<!-- ProtocolLib -->
|
||||
<repository>
|
||||
<id>dmulloy2-repo</id>
|
||||
<url>http://repo.dmulloy2.net/content/groups/public/</url>
|
||||
<url>https://repo.dmulloy2.net/nexus/repository/public/</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<!--AuthMe Reloaded and xAuth -->
|
||||
<!-- AuthMe Reloaded, xAuth and LoginSecurity -->
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public/</url>
|
||||
<id>codemc-releases</id>
|
||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
|
||||
<!--GitHub automatic maven builds-->
|
||||
<!-- GitHub automatic maven builds -->
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<!--PlaceholderAPI -->
|
||||
<!-- PlaceholderAPI -->
|
||||
<repository>
|
||||
<id>placeholderapi</id>
|
||||
<url>http://repo.extendedclip.com/content/repositories/placeholderapi/</url>
|
||||
<url>https://repo.extendedclip.com/content/repositories/placeholderapi</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<!--Common plugin component-->
|
||||
<dependency>
|
||||
<groupId>com.github.games647</groupId>
|
||||
<artifactId>fastlogin.core</artifactId>
|
||||
@@ -112,22 +120,24 @@
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>4.3.0</version>
|
||||
<version>4.5.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Changing onlinemode on login process-->
|
||||
<dependency>
|
||||
<groupId>com.github.ProtocolSupport</groupId>
|
||||
<artifactId>ProtocolSupport</artifactId>
|
||||
<!--4.25.dev-->
|
||||
<version>a4f060dc46</version>
|
||||
<!--4.29.dev after commit about API improvements-->
|
||||
<version>3a80c661fe</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Provide premium placeholders-->
|
||||
<dependency>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
<version>2.8.4</version>
|
||||
<version>2.10.4</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
@@ -156,7 +166,7 @@
|
||||
<dependency>
|
||||
<groupId>com.lenis0012.bukkit</groupId>
|
||||
<artifactId>loginsecurity</artifactId>
|
||||
<version>2.1.7</version>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
|
||||
@@ -6,8 +6,6 @@ import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
|
||||
/**
|
||||
* Represents a client connecting to the server.
|
||||
*
|
||||
@@ -15,6 +13,8 @@ import org.apache.commons.lang.ArrayUtils;
|
||||
*/
|
||||
public class BukkitLoginSession extends LoginSession {
|
||||
|
||||
private static final byte[] EMPTY_ARRAY = {};
|
||||
|
||||
private final String serverId;
|
||||
private final byte[] verifyToken;
|
||||
|
||||
@@ -27,17 +27,22 @@ public class BukkitLoginSession extends LoginSession {
|
||||
super(username, registered, profile);
|
||||
|
||||
this.serverId = serverId;
|
||||
this.verifyToken = ArrayUtils.clone(verifyToken);
|
||||
this.verifyToken = verifyToken.clone();
|
||||
}
|
||||
|
||||
//available for BungeeCord
|
||||
public BukkitLoginSession(String username, boolean registered) {
|
||||
this(username, "", ArrayUtils.EMPTY_BYTE_ARRAY, registered, null);
|
||||
this(username, "", EMPTY_ARRAY, registered, null);
|
||||
}
|
||||
|
||||
//cracked player
|
||||
public BukkitLoginSession(String username, StoredProfile profile) {
|
||||
this(username, "", ArrayUtils.EMPTY_BYTE_ARRAY, false, profile);
|
||||
this(username, "", EMPTY_ARRAY, false, profile);
|
||||
}
|
||||
|
||||
//ProtocolSupport
|
||||
public BukkitLoginSession(String username, boolean registered, StoredProfile profile) {
|
||||
this(username, "", EMPTY_ARRAY, registered, profile);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,8 +52,8 @@ public class BukkitLoginSession extends LoginSession {
|
||||
*
|
||||
* @return the verify token from the server
|
||||
*/
|
||||
public byte[] getVerifyToken() {
|
||||
return ArrayUtils.clone(verifyToken);
|
||||
public synchronized byte[] getVerifyToken() {
|
||||
return verifyToken.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.github.games647.fastlogin.bukkit;
|
||||
|
||||
import com.github.games647.fastlogin.core.AsyncScheduler;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class BukkitScheduler extends AsyncScheduler {
|
||||
|
||||
private final Plugin plugin;
|
||||
private final Executor syncExecutor;
|
||||
|
||||
public BukkitScheduler(Plugin plugin, Logger logger, ThreadFactory threadFactory) {
|
||||
super(logger, threadFactory);
|
||||
this.plugin = plugin;
|
||||
|
||||
syncExecutor = r -> Bukkit.getScheduler().runTask(plugin, r);
|
||||
}
|
||||
|
||||
public Executor getSyncExecutor() {
|
||||
return syncExecutor;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -83,28 +82,24 @@ public class EncryptionUtil {
|
||||
/**
|
||||
* Decrypts the content and extracts the key spec.
|
||||
*
|
||||
* @param cipher decryption cipher
|
||||
* @param privateKey private key of the server
|
||||
* @param cipher decryption cipher initialized with the private key
|
||||
* @param sharedKey the encrypted shared key
|
||||
* @return shared secret key
|
||||
* @throws GeneralSecurityException
|
||||
* @throws GeneralSecurityException if it fails to decrypt the data
|
||||
*/
|
||||
public static SecretKey decryptSharedKey(Cipher cipher, PrivateKey privateKey, byte[] sharedKey)
|
||||
throws GeneralSecurityException {
|
||||
return new SecretKeySpec(decrypt(cipher, privateKey, sharedKey), "AES");
|
||||
public static SecretKey decryptSharedKey(Cipher cipher, byte[] sharedKey) throws GeneralSecurityException {
|
||||
return new SecretKeySpec(decrypt(cipher, sharedKey), "AES");
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypted the given data using the cipher.
|
||||
*
|
||||
* @param cipher decryption cypher
|
||||
* @param key server private key
|
||||
* @param cipher decryption cypher initialized with the private key
|
||||
* @param data the encrypted data
|
||||
* @return clear text data
|
||||
* @throws GeneralSecurityException if it fails to initialize and decrypt the data
|
||||
* @throws GeneralSecurityException if it fails to decrypt the data
|
||||
*/
|
||||
public static byte[] decrypt(Cipher cipher, PrivateKey key, byte[] data) throws GeneralSecurityException {
|
||||
cipher.init(Cipher.DECRYPT_MODE, key);
|
||||
public static byte[] decrypt(Cipher cipher, byte[] data) throws GeneralSecurityException {
|
||||
return cipher.doFinal(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package com.github.games647.fastlogin.bukkit;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.commands.CrackedCommand;
|
||||
import com.github.games647.fastlogin.bukkit.commands.PremiumCommand;
|
||||
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
|
||||
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
|
||||
import com.github.games647.fastlogin.bukkit.listener.BungeeListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.SkinApplyListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
|
||||
import com.github.games647.fastlogin.bukkit.tasks.DelayedAuthHook;
|
||||
import com.github.games647.fastlogin.bukkit.task.DelayedAuthHook;
|
||||
import com.github.games647.fastlogin.core.CommonUtil;
|
||||
import com.github.games647.fastlogin.core.PremiumStatus;
|
||||
import com.github.games647.fastlogin.core.messages.ChannelMessage;
|
||||
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
||||
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
||||
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
@@ -29,6 +31,9 @@ import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.messaging.PluginMessageRecipient;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import static com.github.games647.fastlogin.core.message.ChangePremiumMessage.CHANGE_CHANNEL;
|
||||
import static com.github.games647.fastlogin.core.message.SuccessMessage.SUCCESS_CHANNEL;
|
||||
|
||||
/**
|
||||
* This plugin checks if a player has a paid account and if so tries to skip offline mode authentication.
|
||||
*/
|
||||
@@ -36,17 +41,24 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
|
||||
//1 minutes should be enough as a timeout for bad internet connection (Server, Client and Mojang)
|
||||
private final ConcurrentMap<String, BukkitLoginSession> loginSession = CommonUtil.buildCache(1, -1);
|
||||
private final Logger logger = CommonUtil.createLoggerFromJDK(getLogger());
|
||||
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
|
||||
private final Logger logger;
|
||||
|
||||
private boolean serverStarted;
|
||||
private boolean bungeeCord;
|
||||
private final BukkitScheduler scheduler;
|
||||
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
|
||||
|
||||
public FastLoginBukkit() {
|
||||
this.logger = CommonUtil.createLoggerFromJDK(getLogger());
|
||||
this.scheduler = new BukkitScheduler(this, logger, getThreadFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
core = new FastLoginCore<>(this);
|
||||
core.load();
|
||||
|
||||
try {
|
||||
bungeeCord = Class.forName("org.spigotmc.SpigotConfig").getDeclaredField("bungee").getBoolean(null);
|
||||
} catch (ClassNotFoundException notFoundEx) {
|
||||
@@ -66,9 +78,15 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
if (bungeeCord) {
|
||||
setServerStarted();
|
||||
|
||||
//check for incoming messages from the bungeecord version of this plugin
|
||||
getServer().getMessenger().registerIncomingPluginChannel(this, getName(), new BungeeListener(this));
|
||||
getServer().getMessenger().registerOutgoingPluginChannel(this, getName());
|
||||
// check for incoming messages from the bungeecord version of this plugin
|
||||
String forceChannel = NamespaceKey.getCombined(getName(), LoginActionMessage.FORCE_CHANNEL);
|
||||
getServer().getMessenger().registerIncomingPluginChannel(this, forceChannel, new BungeeListener(this));
|
||||
|
||||
// outgoing
|
||||
String successChannel = new NamespaceKey(getName(), SUCCESS_CHANNEL).getCombinedName();
|
||||
String changeChannel = new NamespaceKey(getName(), CHANGE_CHANNEL).getCombinedName();
|
||||
getServer().getMessenger().registerOutgoingPluginChannel(this, successChannel);
|
||||
getServer().getMessenger().registerOutgoingPluginChannel(this, changeChannel);
|
||||
} else {
|
||||
if (!core.setupDatabase()) {
|
||||
setEnabled(false);
|
||||
@@ -167,10 +185,10 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
public void sendPluginMessage(PluginMessageRecipient player, ChannelMessage message) {
|
||||
if (player != null) {
|
||||
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
|
||||
dataOutput.writeUTF(message.getChannelName());
|
||||
|
||||
message.writeTo(dataOutput);
|
||||
player.sendPluginMessage(this, this.getName(), dataOutput.toByteArray());
|
||||
|
||||
NamespaceKey channel = new NamespaceKey(getName(), message.getChannelName());
|
||||
player.sendPluginMessage(this, channel.getCombinedName(), dataOutput.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +202,11 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
return logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitScheduler getScheduler() {
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(CommandSender receiver, String message) {
|
||||
receiver.sendMessage(message);
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package com.github.games647.fastlogin.bukkit;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.clip.placeholderapi.PlaceholderHook;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
|
||||
public class PremiumPlaceholder extends PlaceholderHook {
|
||||
public class PremiumPlaceholder extends PlaceholderExpansion {
|
||||
|
||||
private static final String PLACEHOLDER_VARIABLE = "fastlogin_status";
|
||||
|
||||
private final FastLoginBukkit plugin;
|
||||
|
||||
@@ -16,25 +17,37 @@ public class PremiumPlaceholder extends PlaceholderHook {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public static void register(FastLoginBukkit plugin) {
|
||||
PremiumPlaceholder placeholderHook = new PremiumPlaceholder(plugin);
|
||||
PlaceholderAPI.registerPlaceholderHook(PLACEHOLDER_VARIABLE, placeholderHook);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onPlaceholderRequest(Player player, String variable) {
|
||||
if (player != null && "fastlogin_status".contains(variable)) {
|
||||
List<MetadataValue> metadata = player.getMetadata(plugin.getName());
|
||||
if (metadata == null) {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
if (metadata.isEmpty()) {
|
||||
return "cracked";
|
||||
} else {
|
||||
return "premium";
|
||||
}
|
||||
if (player != null && PLACEHOLDER_VARIABLE.equals(variable)) {
|
||||
return plugin.getStatus(player.getUniqueId()).name();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void register(FastLoginBukkit plugin) {
|
||||
PlaceholderAPI.registerPlaceholderHook(plugin, new PremiumPlaceholder(plugin));
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return PLACEHOLDER_VARIABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlugin() {
|
||||
return plugin.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthor() {
|
||||
return plugin.getDescription().getAuthors().stream().collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return plugin.getName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package com.github.games647.fastlogin.bukkit.commands;
|
||||
package com.github.games647.fastlogin.bukkit.command;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@@ -44,7 +43,7 @@ public class CrackedCommand extends ToggleCommand {
|
||||
|
||||
profile.setPremium(false);
|
||||
profile.setId(null);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
plugin.getScheduler().runAsync(() -> {
|
||||
plugin.getCore().getStorage().save(profile);
|
||||
});
|
||||
} else {
|
||||
@@ -76,7 +75,7 @@ public class CrackedCommand extends ToggleCommand {
|
||||
plugin.getCore().sendLocaleMessage("remove-premium", sender);
|
||||
|
||||
profile.setPremium(false);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
plugin.getScheduler().runAsync(() -> {
|
||||
plugin.getCore().getStorage().save(profile);
|
||||
});
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
package com.github.games647.fastlogin.bukkit.commands;
|
||||
package com.github.games647.fastlogin.bukkit.command;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -56,7 +55,7 @@ public class PremiumCommand extends ToggleCommand {
|
||||
} else {
|
||||
//todo: resolve uuid
|
||||
profile.setPremium(true);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
plugin.getScheduler().runAsync(() -> {
|
||||
plugin.getCore().getStorage().save(profile);
|
||||
});
|
||||
|
||||
@@ -85,7 +84,7 @@ public class PremiumCommand extends ToggleCommand {
|
||||
} else {
|
||||
//todo: resolve uuid
|
||||
profile.setPremium(true);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
plugin.getScheduler().runAsync(() -> {
|
||||
plugin.getCore().getStorage().save(profile);
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.github.games647.fastlogin.bukkit.commands;
|
||||
package com.github.games647.fastlogin.bukkit.command;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.messages.ChangePremiumMessage;
|
||||
import com.github.games647.fastlogin.core.messages.ChannelMessage;
|
||||
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
|
||||
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.github.games647.fastlogin.bukkit.event;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class BukkitFastLoginAutoLoginEvent extends Event implements FastLoginAutoLoginEvent, Cancellable {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private final LoginSession session;
|
||||
private final StoredProfile profile;
|
||||
private boolean cancelled;
|
||||
|
||||
public BukkitFastLoginAutoLoginEvent(LoginSession session, StoredProfile profile) {
|
||||
super(true);
|
||||
|
||||
this.session = session;
|
||||
this.profile = profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProfile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.github.games647.fastlogin.bukkit.event;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class BukkitFastLoginPreLoginEvent extends Event implements FastLoginPreLoginEvent {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private final String username;
|
||||
private final LoginSource source;
|
||||
private final StoredProfile profile;
|
||||
|
||||
public BukkitFastLoginPreLoginEvent(String username, LoginSource source, StoredProfile profile) {
|
||||
super(true);
|
||||
|
||||
this.username = username;
|
||||
this.source = source;
|
||||
this.profile = profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginSource getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProfile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,11 @@
|
||||
package com.github.games647.fastlogin.bukkit.hooks;
|
||||
package com.github.games647.fastlogin.bukkit.hook;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
|
||||
import fr.xephi.authme.api.v3.AuthMeApi;
|
||||
import fr.xephi.authme.events.RestoreSessionEvent;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
/**
|
||||
@@ -29,24 +25,13 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onSessionRestore(RestoreSessionEvent restoreSessionEvent) {
|
||||
Player player = restoreSessionEvent.getPlayer();
|
||||
|
||||
String id = '/' + player.getAddress().getAddress().getHostAddress() + ':' + player.getAddress().getPort();
|
||||
BukkitLoginSession session = plugin.getLoginSessions().get(id);
|
||||
if (session != null && session.isVerified()) {
|
||||
restoreSessionEvent.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceLogin(Player player) {
|
||||
//skips registration and login
|
||||
if (AuthMeApi.getInstance().isAuthenticated(player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//skips registration and login
|
||||
AuthMeApi.getInstance().forceLogin(player);
|
||||
return true;
|
||||
}
|
||||
@@ -58,7 +43,7 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
|
||||
|
||||
@Override
|
||||
public boolean forceRegister(Player player, String password) {
|
||||
//this automatically registers the player too
|
||||
//this automatically login the player too
|
||||
AuthMeApi.getInstance().forceRegister(player, password);
|
||||
return true;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.github.games647.fastlogin.bukkit.hooks;
|
||||
package com.github.games647.fastlogin.bukkit.hook;
|
||||
|
||||
import com.comphenix.protocol.reflect.FieldUtils;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
|
||||
@@ -13,7 +14,6 @@ import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.apache.commons.lang.reflect.FieldUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.github.games647.fastlogin.bukkit.hooks;
|
||||
package com.github.games647.fastlogin.bukkit.hook;
|
||||
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.github.games647.fastlogin.bukkit.hooks;
|
||||
package com.github.games647.fastlogin.bukkit.hook;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
@@ -11,7 +11,7 @@ import com.lenis0012.bukkit.loginsecurity.session.action.RegisterAction;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* GitHub: https://github.com/lenis0012/LoginSecurity-2
|
||||
* GitHub: https://github.com/lenis0012/LoginSecurity-2
|
||||
* <p>
|
||||
* Project page:
|
||||
* <p>
|
||||
@@ -30,8 +30,8 @@ public class LoginSecurityHook implements AuthPlugin<Player> {
|
||||
@Override
|
||||
public boolean forceLogin(Player player) {
|
||||
PlayerSession session = LoginSecurity.getSessionManager().getPlayerSession(player);
|
||||
return session.isAuthorized() || session.performAction(new LoginAction(AuthService.PLUGIN, plugin)).isSuccess();
|
||||
|
||||
return session.isAuthorized()
|
||||
|| session.performAction(new LoginAction(AuthService.PLUGIN, plugin)).isSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.github.games647.fastlogin.bukkit.hooks;
|
||||
package com.github.games647.fastlogin.bukkit.hook;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.github.games647.fastlogin.bukkit.hooks;
|
||||
package com.github.games647.fastlogin.bukkit.hook;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
@@ -2,11 +2,11 @@ package com.github.games647.fastlogin.bukkit.listener;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.bukkit.tasks.ForceLoginTask;
|
||||
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
|
||||
import com.github.games647.fastlogin.core.PremiumStatus;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import com.github.games647.fastlogin.core.messages.LoginActionMessage;
|
||||
import com.github.games647.fastlogin.core.messages.LoginActionMessage.Type;
|
||||
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
||||
import com.github.games647.fastlogin.core.message.LoginActionMessage.Type;
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
@@ -46,16 +46,7 @@ public class BungeeListener implements PluginMessageListener {
|
||||
|
||||
@Override
|
||||
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
|
||||
if (!channel.equals(plugin.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
ByteArrayDataInput dataInput = ByteStreams.newDataInput(message);
|
||||
String subChannel = dataInput.readUTF();
|
||||
if (!"LoginAction".equals(subChannel)) {
|
||||
plugin.getLog().info("Unknown sub channel {}", subChannel);
|
||||
return;
|
||||
}
|
||||
|
||||
LoginActionMessage loginMessage = new LoginActionMessage();
|
||||
loginMessage.readFrom(dataInput);
|
||||
@@ -70,6 +61,8 @@ public class BungeeListener implements PluginMessageListener {
|
||||
|
||||
//fail if target player is blacklisted because already authenticated or wrong bungeecord id
|
||||
if (checkedPlayer.hasMetadata(plugin.getName())) {
|
||||
plugin.getLog().warn("Received message {} from a blacklisted player {}", loginMessage, checkedPlayer);
|
||||
} else {
|
||||
//fail if BungeeCord support is disabled (id = null)
|
||||
UUID sourceId = loginMessage.getProxyId();
|
||||
if (proxyIds.contains(sourceId)) {
|
||||
@@ -77,8 +70,6 @@ public class BungeeListener implements PluginMessageListener {
|
||||
} else {
|
||||
plugin.getLog().warn("Received proxy id: {} that doesn't exist in the proxy whitelist file", sourceId);
|
||||
}
|
||||
} else {
|
||||
plugin.getLog().warn("Received message {} from a blacklisted player {}", loginMessage, checkedPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,16 +80,12 @@ public class BungeeListener implements PluginMessageListener {
|
||||
InetSocketAddress address = player.getAddress();
|
||||
String id = '/' + address.getAddress().getHostAddress() + ':' + address.getPort();
|
||||
if (type == Type.LOGIN) {
|
||||
plugin.getPremiumPlayers().put(player.getUniqueId(), PremiumStatus.PREMIUM);
|
||||
|
||||
BukkitLoginSession playerSession = new BukkitLoginSession(playerName, true);
|
||||
playerSession.setVerified(true);
|
||||
plugin.getLoginSessions().put(id, playerSession);
|
||||
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, new ForceLoginTask(plugin.getCore(), player), 20L);
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, new ForceLoginTask(plugin.getCore(), player), 10L);
|
||||
} else if (type == Type.REGISTER) {
|
||||
plugin.getPremiumPlayers().put(player.getUniqueId(), PremiumStatus.PREMIUM);
|
||||
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> {
|
||||
AuthPlugin<Player> authPlugin = plugin.getCore().getAuthPluginHook();
|
||||
try {
|
||||
@@ -112,8 +99,9 @@ public class BungeeListener implements PluginMessageListener {
|
||||
} catch (Exception ex) {
|
||||
plugin.getLog().error("Failed to query isRegistered for player: {}", player, ex);
|
||||
}
|
||||
}, 20L);
|
||||
}, 10L);
|
||||
} else if (type == Type.CRACKED) {
|
||||
//we don't start a force login task here so update it manually
|
||||
plugin.getPremiumPlayers().put(player.getUniqueId(), PremiumStatus.CRACKED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.github.games647.fastlogin.bukkit.listener;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.bukkit.tasks.ForceLoginTask;
|
||||
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -38,6 +38,7 @@ public class ConnectionListener implements Listener {
|
||||
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
|
||||
Player player = joinEvent.getPlayer();
|
||||
|
||||
removeBlacklistStatus(player);
|
||||
if (!plugin.isBungeeEnabled()) {
|
||||
//Wait before auth plugin and we received a message from BungeeCord initializes the player
|
||||
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player);
|
||||
@@ -48,9 +49,13 @@ public class ConnectionListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
|
||||
Player player = quitEvent.getPlayer();
|
||||
player.removeMetadata(plugin.getName(), plugin);
|
||||
removeBlacklistStatus(player);
|
||||
|
||||
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
|
||||
plugin.getPremiumPlayers().remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
private void removeBlacklistStatus(Player player) {
|
||||
player.removeMetadata(plugin.getName(), plugin);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@ import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.JoinManagement;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.util.Random;
|
||||
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -46,6 +48,13 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, ProtocolLibLoginSource source, StoredProfile profile) {
|
||||
BukkitFastLoginPreLoginEvent event = new BukkitFastLoginPreLoginEvent(username, source, profile);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
//Minecraft server implementation
|
||||
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L161
|
||||
@Override
|
||||
|
||||
@@ -11,7 +11,6 @@ import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import java.security.KeyPair;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import static com.comphenix.protocol.PacketType.Login.Client.ENCRYPTION_BEGIN;
|
||||
@@ -67,7 +66,7 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
|
||||
packetEvent.getAsyncMarker().incrementProcessingDelay();
|
||||
Runnable verifyTask = new VerifyResponseTask(plugin, packetEvent, sender, sharedSecret, keyPair);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, verifyTask);
|
||||
plugin.getScheduler().runAsync(verifyTask);
|
||||
}
|
||||
|
||||
private void onLogin(PacketEvent packetEvent, Player player) {
|
||||
@@ -85,6 +84,6 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
|
||||
packetEvent.getAsyncMarker().incrementProcessingDelay();
|
||||
Runnable nameCheckTask = new NameCheckTask(plugin, packetEvent, random, player, username, keyPair.getPublic());
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, nameCheckTask);
|
||||
plugin.getScheduler().runAsync(nameCheckTask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import java.security.PublicKey;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import static com.comphenix.protocol.PacketType.Login.Server.DISCONNECT;
|
||||
@@ -43,7 +42,7 @@ public class ProtocolLibLoginSource implements LoginSource {
|
||||
verifyToken = EncryptionUtil.generateVerifyToken(random);
|
||||
|
||||
/*
|
||||
* Packet Information: http://wiki.vg/Protocol#Encryption_Request
|
||||
* Packet Information: https://wiki.vg/Protocol#Encryption_Request
|
||||
*
|
||||
* ServerID="" (String) key=public server key verifyToken=random 4 byte array
|
||||
*/
|
||||
@@ -85,7 +84,7 @@ public class ProtocolLibLoginSource implements LoginSource {
|
||||
}
|
||||
|
||||
public byte[] getVerifyToken() {
|
||||
return ArrayUtils.clone(verifyToken);
|
||||
return verifyToken.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,7 +6,7 @@ import com.comphenix.protocol.reflect.accessors.MethodAccessor;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
|
||||
import com.github.games647.craftapi.model.skin.SkinProperty;
|
||||
import com.github.games647.craftapi.model.skin.Textures;
|
||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
|
||||
@@ -54,14 +54,14 @@ public class SkinApplyListener implements Listener {
|
||||
private void applySkin(Player player, String skinData, String signature) {
|
||||
WrappedGameProfile gameProfile = WrappedGameProfile.fromPlayer(player);
|
||||
|
||||
WrappedSignedProperty skin = WrappedSignedProperty.fromValues(SkinProperty.TEXTURE_KEY, skinData, signature);
|
||||
WrappedSignedProperty skin = WrappedSignedProperty.fromValues(Textures.KEY, skinData, signature);
|
||||
try {
|
||||
gameProfile.getProperties().put(SkinProperty.TEXTURE_KEY, skin);
|
||||
gameProfile.getProperties().put(Textures.KEY, skin);
|
||||
} catch (ClassCastException castException) {
|
||||
//Cauldron, MCPC, Thermos, ...
|
||||
Object map = GET_PROPERTIES.invoke(gameProfile.getHandle());
|
||||
try {
|
||||
MethodUtils.invokeMethod(map, "put", new Object[]{SkinProperty.TEXTURE_KEY, skin.getHandle()});
|
||||
MethodUtils.invokeMethod(map, "put", new Object[]{Textures.KEY, skin.getHandle()});
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
|
||||
plugin.getLog().error("Error setting premium skin of: {}", player, ex);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public class VerifyResponseTask implements Runnable {
|
||||
try {
|
||||
BukkitLoginSession session = plugin.getLoginSessions().get(player.getAddress().toString());
|
||||
if (session == null) {
|
||||
disconnect(plugin.getCore().getMessage("invalid-request"), true
|
||||
disconnect("invalid-request", true
|
||||
, "GameProfile {0} tried to send encryption response at invalid state", player.getAddress());
|
||||
} else {
|
||||
verifyResponse(session);
|
||||
@@ -81,8 +81,9 @@ public class VerifyResponseTask implements Runnable {
|
||||
SecretKey loginKey;
|
||||
try {
|
||||
cipher = Cipher.getInstance(privateKey.getAlgorithm());
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
|
||||
loginKey = EncryptionUtil.decryptSharedKey(cipher, privateKey, sharedSecret);
|
||||
loginKey = EncryptionUtil.decryptSharedKey(cipher, sharedSecret);
|
||||
} catch (GeneralSecurityException securityEx) {
|
||||
disconnect("error-kick", false, "Cannot decrypt received contents", securityEx);
|
||||
return;
|
||||
@@ -113,18 +114,19 @@ public class VerifyResponseTask implements Runnable {
|
||||
session.setSkinProperty(properties[0]);
|
||||
}
|
||||
|
||||
session.setUuid(response.get().getId());
|
||||
session.setVerified(true);
|
||||
setPremiumUUID(session.getUuid());
|
||||
|
||||
setPremiumUUID(session.getUuid());
|
||||
receiveFakeStartPacket(username);
|
||||
} else {
|
||||
//user tried to fake a authentication
|
||||
disconnect(plugin.getCore().getMessage("invalid-session"), true
|
||||
disconnect("invalid-session", true
|
||||
, "GameProfile {0} ({1}) tried to log in with an invalid session ServerId: {2}"
|
||||
, session.getUsername(), socketAddress, serverId);
|
||||
}
|
||||
} catch (IOException ioEx) {
|
||||
disconnect("error-kick", false, "Failed to connect to sessionserver", ioEx);
|
||||
disconnect("error-kick", false, "Failed to connect to session server", ioEx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,9 +149,9 @@ public class VerifyResponseTask implements Runnable {
|
||||
byte[] responseVerify = packetEvent.getPacket().getByteArrays().read(1);
|
||||
|
||||
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L182
|
||||
if (!Arrays.equals(requestVerify, EncryptionUtil.decrypt(cipher, privateKey, responseVerify))) {
|
||||
if (!Arrays.equals(requestVerify, EncryptionUtil.decrypt(cipher, responseVerify))) {
|
||||
//check if the verify token are equal to the server sent one
|
||||
disconnect(plugin.getCore().getMessage("invalid-verify-token"), true
|
||||
disconnect("invalid-verify-token", true
|
||||
, "GameProfile {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}"
|
||||
, session.getUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
|
||||
return false;
|
||||
@@ -188,14 +190,14 @@ public class VerifyResponseTask implements Runnable {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void disconnect(String kickReason, boolean debug, String logMessage, Object... arguments) {
|
||||
private void disconnect(String reasonKey, boolean debug, String logMessage, Object... arguments) {
|
||||
if (debug) {
|
||||
plugin.getLog().debug(logMessage, arguments);
|
||||
} else {
|
||||
plugin.getLog().error(logMessage, arguments);
|
||||
}
|
||||
|
||||
kickPlayer(plugin.getCore().getMessage(kickReason));
|
||||
kickPlayer(plugin.getCore().getMessage(reasonKey));
|
||||
}
|
||||
|
||||
private void kickPlayer(String reason) {
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
package com.github.games647.fastlogin.bukkit.listener.protocolsupport;
|
||||
|
||||
import com.github.games647.craftapi.model.skin.SkinProperty;
|
||||
import com.github.games647.craftapi.UUIDAdapter;
|
||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.JoinManagement;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import protocolsupport.api.events.ConnectionCloseEvent;
|
||||
import protocolsupport.api.events.PlayerLoginStartEvent;
|
||||
import protocolsupport.api.events.PlayerPropertiesResolveEvent;
|
||||
import protocolsupport.api.events.PlayerProfileCompleteEvent;
|
||||
|
||||
public class ProtocolSupportListener extends JoinManagement<Player, CommandSender, ProtocolLoginSource>
|
||||
implements Listener {
|
||||
@@ -33,7 +36,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
|
||||
return;
|
||||
}
|
||||
|
||||
String username = loginStartEvent.getName();
|
||||
String username = loginStartEvent.getConnection().getProfile().getName();
|
||||
InetSocketAddress address = loginStartEvent.getAddress();
|
||||
|
||||
//remove old data every time on a new login in order to keep the session only for one person
|
||||
@@ -49,16 +52,28 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPropertiesResolve(PlayerPropertiesResolveEvent propertiesResolveEvent) {
|
||||
InetSocketAddress address = propertiesResolveEvent.getAddress();
|
||||
public void onPropertiesResolve(PlayerProfileCompleteEvent profileCompleteEvent) {
|
||||
InetSocketAddress address = profileCompleteEvent.getAddress();
|
||||
BukkitLoginSession session = plugin.getLoginSessions().get(address.toString());
|
||||
|
||||
//skin was resolved -> premium player
|
||||
if (propertiesResolveEvent.hasProperty(SkinProperty.TEXTURE_KEY) && session != null) {
|
||||
if (session != null && profileCompleteEvent.getConnection().getProfile().isOnlineMode()) {
|
||||
session.setVerified(true);
|
||||
|
||||
if (!plugin.getConfig().getBoolean("premiumUuid")) {
|
||||
String username = Optional.ofNullable(profileCompleteEvent.getForcedName())
|
||||
.orElse(profileCompleteEvent.getConnection().getProfile().getName());
|
||||
profileCompleteEvent.setForcedUUID(UUIDAdapter.generateOfflineId(username));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, ProtocolLoginSource source, StoredProfile profile) {
|
||||
BukkitFastLoginPreLoginEvent event = new BukkitFastLoginPreLoginEvent(username, source, profile);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPremiumLogin(ProtocolLoginSource source, StoredProfile profile, String username
|
||||
, boolean registered) {
|
||||
@@ -67,11 +82,10 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
|
||||
String ip = source.getAddress().getAddress().getHostAddress();
|
||||
plugin.getCore().getPendingLogin().put(ip + username, new Object());
|
||||
|
||||
BukkitLoginSession playerSession = new BukkitLoginSession(username, null, null
|
||||
, registered, profile);
|
||||
BukkitLoginSession playerSession = new BukkitLoginSession(username, registered, profile);
|
||||
plugin.getLoginSessions().put(source.getAddress().toString(), playerSession);
|
||||
if (plugin.getConfig().getBoolean("premiumUuid")) {
|
||||
source.getLoginStartEvent().setUseOnlineModeUUID(true);
|
||||
source.getLoginStartEvent().setOnlineMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.github.games647.fastlogin.bukkit.tasks;
|
||||
package com.github.games647.fastlogin.bukkit.task;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.AuthMeHook;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.CrazyLoginHook;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.LogItHook;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.LoginSecurityHook;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.UltraAuthHook;
|
||||
import com.github.games647.fastlogin.bukkit.hooks.xAuthHook;
|
||||
import com.github.games647.fastlogin.bukkit.hook.AuthMeHook;
|
||||
import com.github.games647.fastlogin.bukkit.hook.CrazyLoginHook;
|
||||
import com.github.games647.fastlogin.bukkit.hook.LogItHook;
|
||||
import com.github.games647.fastlogin.bukkit.hook.LoginSecurityHook;
|
||||
import com.github.games647.fastlogin.bukkit.hook.UltraAuthHook;
|
||||
import com.github.games647.fastlogin.bukkit.hook.xAuthHook;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
@@ -1,14 +1,18 @@
|
||||
package com.github.games647.fastlogin.bukkit.tasks;
|
||||
package com.github.games647.fastlogin.bukkit.task;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.messages.SuccessMessage;
|
||||
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginAutoLoginEvent;
|
||||
import com.github.games647.fastlogin.core.PremiumStatus;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.message.SuccessMessage;
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.github.games647.fastlogin.core.shared.ForceLoginManagement;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -28,11 +32,25 @@ public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender,
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//blacklist this target player for BungeeCord Id brute force attacks
|
||||
//blacklist this target player for BungeeCord ID brute force attacks
|
||||
FastLoginBukkit plugin = core.getPlugin();
|
||||
player.setMetadata(core.getPlugin().getName(), new FixedMetadataValue(plugin, true));
|
||||
|
||||
super.run();
|
||||
|
||||
PremiumStatus status = PremiumStatus.CRACKED;
|
||||
if (isOnlineMode()) {
|
||||
status = PremiumStatus.PREMIUM;
|
||||
}
|
||||
|
||||
plugin.getPremiumPlayers().put(player.getUniqueId(), status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FastLoginAutoLoginEvent callFastLoginAutoLoginEvent(LoginSession session, StoredProfile profile) {
|
||||
BukkitFastLoginAutoLoginEvent event = new BukkitFastLoginAutoLoginEvent(session, profile);
|
||||
core.getPlugin().getServer().getPluginManager().callEvent(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,6 +78,10 @@ public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender,
|
||||
|
||||
@Override
|
||||
public boolean isOnlineMode() {
|
||||
if (session == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return session.isVerified() && player.getName().equals(session.getUsername());
|
||||
}
|
||||
}
|
||||
@@ -11,14 +11,21 @@ description: |
|
||||
website: ${project.url}
|
||||
dev-url: ${project.url}
|
||||
|
||||
# Load the plugin as early as possible to inject it for all players
|
||||
load: STARTUP
|
||||
# This plugin don't have to be transformed for compatibility with Minecraft >= 1.13
|
||||
api-version: '1.13'
|
||||
|
||||
softdepend:
|
||||
# We depend either ProtocolLib or ProtocolSupport
|
||||
- ProtocolSupport
|
||||
- ProtocolLib
|
||||
- PlaceholderAPI
|
||||
# Auth plugins
|
||||
- AuthMe
|
||||
- LoginSecurity
|
||||
- xAuth
|
||||
- LogIt
|
||||
- UltraAuth
|
||||
- CrazyLogin
|
||||
|
||||
commands:
|
||||
${project.parent.name}:
|
||||
|
||||
BIN
bungee/lib/BungeeAuth-1.4.jar
Normal file
BIN
bungee/lib/BungeeAuth-1.4.jar
Normal file
Binary file not shown.
@@ -1,11 +1,11 @@
|
||||
<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">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.github.games647</groupId>
|
||||
<artifactId>fastlogin</artifactId>
|
||||
<version>1.11</version>
|
||||
<version>1.11-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.2.2</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
@@ -56,18 +56,14 @@
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>vik1395-repo</id>
|
||||
<url>https://vik1395.github.io/repo.vik1395.me/repositories</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public/</url>
|
||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<!--Common plugin component-->
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>fastlogin.core</artifactId>
|
||||
@@ -78,21 +74,17 @@
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-proxy</artifactId>
|
||||
<version>1.12-SNAPSHOT</version>
|
||||
<version>1.14-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Login plugin-->
|
||||
<dependency>
|
||||
<groupId>me.vik1395</groupId>
|
||||
<artifactId>BungeeAuth</artifactId>
|
||||
<version>1.4</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/lib/BungeeAuth-1.4.jar</systemPath>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -12,28 +12,28 @@ public class BungeeLoginSession extends LoginSession {
|
||||
super(username, registered, profile);
|
||||
}
|
||||
|
||||
public void setRegistered(boolean registered) {
|
||||
public synchronized void setRegistered(boolean registered) {
|
||||
this.registered = registered;
|
||||
}
|
||||
|
||||
public boolean isAlreadySaved() {
|
||||
public synchronized boolean isAlreadySaved() {
|
||||
return alreadySaved;
|
||||
}
|
||||
|
||||
public void setAlreadySaved(boolean alreadySaved) {
|
||||
public synchronized void setAlreadySaved(boolean alreadySaved) {
|
||||
this.alreadySaved = alreadySaved;
|
||||
}
|
||||
|
||||
public boolean isAlreadyLogged() {
|
||||
public synchronized boolean isAlreadyLogged() {
|
||||
return alreadyLogged;
|
||||
}
|
||||
|
||||
public void setAlreadyLogged(boolean alreadyLogged) {
|
||||
public synchronized void setAlreadyLogged(boolean alreadyLogged) {
|
||||
this.alreadyLogged = alreadyLogged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public synchronized String toString() {
|
||||
return this.getClass().getSimpleName() + '{' +
|
||||
"alreadySaved=" + alreadySaved +
|
||||
", alreadyLogged=" + alreadyLogged +
|
||||
|
||||
@@ -4,15 +4,20 @@ import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
import net.md_5.bungee.api.event.PreLoginEvent;
|
||||
|
||||
public class BungeeLoginSource implements LoginSource {
|
||||
|
||||
private final PendingConnection connection;
|
||||
private final PreLoginEvent preLoginEvent;
|
||||
|
||||
public BungeeLoginSource(PendingConnection connection) {
|
||||
public BungeeLoginSource(PendingConnection connection, PreLoginEvent preLoginEvent) {
|
||||
this.connection = connection;
|
||||
this.preLoginEvent = preLoginEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -22,7 +27,12 @@ public class BungeeLoginSource implements LoginSource {
|
||||
|
||||
@Override
|
||||
public void kick(String message) {
|
||||
connection.disconnect(TextComponent.fromLegacyText(message));
|
||||
preLoginEvent.setCancelled(true);
|
||||
|
||||
if (message != null)
|
||||
preLoginEvent.setCancelReason(TextComponent.fromLegacyText(message));
|
||||
else
|
||||
preLoginEvent.setCancelReason(new ComponentBuilder("Kicked").color(ChatColor.WHITE).create());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package com.github.games647.fastlogin.bungee;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthHook;
|
||||
import com.github.games647.fastlogin.bungee.hook.BungeeAuthHook;
|
||||
import com.github.games647.fastlogin.bungee.listener.ConnectListener;
|
||||
import com.github.games647.fastlogin.bungee.listener.MessageListener;
|
||||
import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
|
||||
import com.github.games647.fastlogin.core.AsyncScheduler;
|
||||
import com.github.games647.fastlogin.core.CommonUtil;
|
||||
import com.github.games647.fastlogin.core.messages.ChannelMessage;
|
||||
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
|
||||
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
||||
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
||||
import com.github.games647.fastlogin.core.message.SuccessMessage;
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
||||
import com.google.common.collect.MapMaker;
|
||||
@@ -34,11 +38,13 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
||||
private final ConcurrentMap<PendingConnection, BungeeLoginSession> session = new MapMaker().weakKeys().makeMap();
|
||||
|
||||
private FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core;
|
||||
private AsyncScheduler scheduler;
|
||||
private Logger logger;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
logger = CommonUtil.createLoggerFromJDK(getLogger());
|
||||
scheduler = new AsyncScheduler(logger, getThreadFactory());
|
||||
|
||||
core = new FastLoginCore<>(this);
|
||||
core.load();
|
||||
@@ -48,10 +54,11 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
||||
|
||||
//events
|
||||
getProxy().getPluginManager().registerListener(this, new ConnectListener(this));
|
||||
getProxy().getPluginManager().registerListener(this, new MessageListener(this));
|
||||
getProxy().getPluginManager().registerListener(this, new PluginMessageListener(this));
|
||||
|
||||
//this is required to listen to messages from the server
|
||||
getProxy().registerChannel(getName());
|
||||
//this is required to listen to incoming messages from the server
|
||||
getProxy().registerChannel(NamespaceKey.getCombined(getName(), ChangePremiumMessage.CHANGE_CHANNEL));
|
||||
getProxy().registerChannel(NamespaceKey.getCombined(getName(), SuccessMessage.SUCCESS_CHANNEL));
|
||||
|
||||
registerHook();
|
||||
}
|
||||
@@ -82,10 +89,10 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
||||
public void sendPluginMessage(Server server, ChannelMessage message) {
|
||||
if (server != null) {
|
||||
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
|
||||
dataOutput.writeUTF(message.getChannelName());
|
||||
|
||||
message.writeTo(dataOutput);
|
||||
server.sendData(core.getPlugin().getName(), dataOutput.toByteArray());
|
||||
|
||||
NamespaceKey channel = new NamespaceKey(getName(), message.getChannelName());
|
||||
server.sendData(channel.getCombinedName(), dataOutput.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,10 +120,15 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
||||
@SuppressWarnings("deprecation")
|
||||
public ThreadFactory getThreadFactory() {
|
||||
return new ThreadFactoryBuilder()
|
||||
.setNameFormat(core.getPlugin().getName() + " Database Pool Thread #%1$d")
|
||||
.setNameFormat(getName() + " Pool Thread #%1$d")
|
||||
//Hikari create daemons by default
|
||||
.setDaemon(true)
|
||||
.setThreadFactory(new GroupedThreadFactory(this, getName()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncScheduler getScheduler() {
|
||||
return scheduler;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.github.games647.fastlogin.bungee.event;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||
import net.md_5.bungee.api.plugin.Cancellable;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
public class BungeeFastLoginAutoLoginEvent extends Event implements FastLoginAutoLoginEvent, Cancellable {
|
||||
|
||||
private final LoginSession session;
|
||||
private final StoredProfile profile;
|
||||
private boolean cancelled;
|
||||
|
||||
public BungeeFastLoginAutoLoginEvent(LoginSession session, StoredProfile profile) {
|
||||
this.session = session;
|
||||
this.profile = profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProfile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.github.games647.fastlogin.bungee.event;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
public class BungeeFastLoginPreLoginEvent extends Event implements FastLoginPreLoginEvent {
|
||||
|
||||
private final String username;
|
||||
private final LoginSource source;
|
||||
private final StoredProfile profile;
|
||||
|
||||
public BungeeFastLoginPreLoginEvent(String username, LoginSource source, StoredProfile profile) {
|
||||
this.username = username;
|
||||
this.source = source;
|
||||
this.profile = profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginSource getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProfile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.github.games647.fastlogin.bungee.hooks;
|
||||
package com.github.games647.fastlogin.bungee.hook;
|
||||
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
|
||||
@@ -2,15 +2,14 @@ package com.github.games647.fastlogin.bungee.listener;
|
||||
|
||||
import com.github.games647.craftapi.UUIDAdapter;
|
||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||
import com.github.games647.fastlogin.bungee.tasks.AsyncPremiumCheck;
|
||||
import com.github.games647.fastlogin.bungee.tasks.ForceLoginTask;
|
||||
import com.github.games647.fastlogin.bungee.task.AsyncPremiumCheck;
|
||||
import com.github.games647.fastlogin.bungee.task.ForceLoginTask;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.UUID;
|
||||
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.connection.Server;
|
||||
@@ -48,7 +47,7 @@ public class ConnectListener implements Listener {
|
||||
|
||||
PendingConnection connection = preLoginEvent.getConnection();
|
||||
Runnable asyncPremiumCheck = new AsyncPremiumCheck(plugin, preLoginEvent, connection);
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, asyncPremiumCheck);
|
||||
plugin.getScheduler().runAsync(asyncPremiumCheck);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
@@ -101,7 +100,7 @@ public class ConnectListener implements Listener {
|
||||
Server server = serverConnectedEvent.getServer();
|
||||
|
||||
Runnable loginTask = new ForceLoginTask(plugin.getCore(), player, server);
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, loginTask);
|
||||
plugin.getScheduler().runAsync(loginTask);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
||||
@@ -2,9 +2,11 @@ package com.github.games647.fastlogin.bungee.listener;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
|
||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||
import com.github.games647.fastlogin.bungee.tasks.AsyncToggleMessage;
|
||||
import com.github.games647.fastlogin.bungee.task.AsyncToggleMessage;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.messages.ChangePremiumMessage;
|
||||
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
|
||||
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
||||
import com.github.games647.fastlogin.core.message.SuccessMessage;
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
@@ -12,7 +14,6 @@ import com.google.common.io.ByteStreams;
|
||||
import java.util.Arrays;
|
||||
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.connection.Server;
|
||||
@@ -20,18 +21,24 @@ import net.md_5.bungee.api.event.PluginMessageEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
public class MessageListener implements Listener {
|
||||
public class PluginMessageListener implements Listener {
|
||||
|
||||
private final FastLoginBungee plugin;
|
||||
|
||||
public MessageListener(FastLoginBungee plugin) {
|
||||
private final String successChannel;
|
||||
private final String changeChannel;
|
||||
|
||||
public PluginMessageListener(FastLoginBungee plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
this.successChannel = new NamespaceKey(plugin.getName(), SuccessMessage.SUCCESS_CHANNEL).getCombinedName();
|
||||
this.changeChannel = new NamespaceKey(plugin.getName(), ChangePremiumMessage.CHANGE_CHANNEL).getCombinedName();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPluginMessage(PluginMessageEvent pluginMessageEvent) {
|
||||
String channel = pluginMessageEvent.getTag();
|
||||
if (pluginMessageEvent.isCancelled() || !plugin.getName().equals(channel)) {
|
||||
if (pluginMessageEvent.isCancelled() || !channel.startsWith(plugin.getName().toLowerCase())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -48,17 +55,16 @@ public class MessageListener implements Listener {
|
||||
byte[] data = Arrays.copyOf(pluginMessageEvent.getData(), pluginMessageEvent.getData().length);
|
||||
ProxiedPlayer forPlayer = (ProxiedPlayer) pluginMessageEvent.getReceiver();
|
||||
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> readMessage(forPlayer, data));
|
||||
plugin.getScheduler().runAsync(() -> readMessage(forPlayer, channel, data));
|
||||
}
|
||||
|
||||
private void readMessage(ProxiedPlayer forPlayer, byte[] data) {
|
||||
private void readMessage(ProxiedPlayer forPlayer, String channel, byte[] data) {
|
||||
FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core = plugin.getCore();
|
||||
|
||||
ByteArrayDataInput dataInput = ByteStreams.newDataInput(data);
|
||||
String subChannel = dataInput.readUTF();
|
||||
if ("Success".equals(subChannel)) {
|
||||
if (successChannel.equals(channel)) {
|
||||
onSuccessMessage(forPlayer);
|
||||
} else if ("ChangeStatus".equals(subChannel)) {
|
||||
} else if (changeChannel.equals(channel)) {
|
||||
ChangePremiumMessage changeMessage = new ChangePremiumMessage();
|
||||
changeMessage.readFrom(dataInput);
|
||||
|
||||
@@ -75,10 +81,10 @@ public class MessageListener implements Listener {
|
||||
|
||||
core.getPendingConfirms().remove(forPlayer.getUniqueId());
|
||||
Runnable task = new AsyncToggleMessage(core, forPlayer, playerName, true, isSourceInvoker);
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, task);
|
||||
plugin.getScheduler().runAsync(task);
|
||||
} else {
|
||||
Runnable task = new AsyncToggleMessage(core, forPlayer, playerName, false, isSourceInvoker);
|
||||
ProxyServer.getInstance().getScheduler().runAsync(plugin, task);
|
||||
plugin.getScheduler().runAsync(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,28 @@
|
||||
package com.github.games647.fastlogin.bungee.tasks;
|
||||
package com.github.games647.fastlogin.bungee.task;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
|
||||
import com.github.games647.fastlogin.bungee.BungeeLoginSource;
|
||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginPreLoginEvent;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.JoinManagement;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
||||
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.AsyncEvent;
|
||||
import net.md_5.bungee.api.event.PreLoginEvent;
|
||||
import net.md_5.bungee.connection.InitialHandler;
|
||||
|
||||
public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSender, BungeeLoginSource>
|
||||
implements Runnable {
|
||||
|
||||
private final FastLoginBungee plugin;
|
||||
private final AsyncEvent<?> preLoginEvent;
|
||||
private final PreLoginEvent preLoginEvent;
|
||||
|
||||
private final PendingConnection connection;
|
||||
|
||||
public AsyncPremiumCheck(FastLoginBungee plugin, AsyncEvent<?> preLoginEvent, PendingConnection connection) {
|
||||
public AsyncPremiumCheck(FastLoginBungee plugin, PreLoginEvent preLoginEvent, PendingConnection connection) {
|
||||
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
|
||||
|
||||
this.plugin = plugin;
|
||||
@@ -35,12 +37,19 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
|
||||
InitialHandler initialHandler = (InitialHandler) connection;
|
||||
String username = initialHandler.getLoginRequest().getData();
|
||||
try {
|
||||
super.onLogin(username, new BungeeLoginSource(connection));
|
||||
super.onLogin(username, new BungeeLoginSource(connection, preLoginEvent));
|
||||
} finally {
|
||||
preLoginEvent.completeIntent(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, BungeeLoginSource source,
|
||||
StoredProfile profile) {
|
||||
return plugin.getProxy().getPluginManager()
|
||||
.callEvent(new BungeeFastLoginPreLoginEvent(username, source, profile));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPremiumLogin(BungeeLoginSource source, StoredProfile profile,
|
||||
String username, boolean registered) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.github.games647.fastlogin.bungee.tasks;
|
||||
package com.github.games647.fastlogin.bungee.task;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
@@ -1,16 +1,19 @@
|
||||
package com.github.games647.fastlogin.bungee.tasks;
|
||||
package com.github.games647.fastlogin.bungee.task;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
|
||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||
import com.github.games647.fastlogin.core.messages.ChannelMessage;
|
||||
import com.github.games647.fastlogin.core.messages.LoginActionMessage;
|
||||
import com.github.games647.fastlogin.core.messages.LoginActionMessage.Type;
|
||||
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginAutoLoginEvent;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
||||
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
||||
import com.github.games647.fastlogin.core.message.LoginActionMessage.Type;
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.github.games647.fastlogin.core.shared.ForceLoginManagement;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
@@ -51,10 +54,15 @@ public class ForceLoginTask
|
||||
return super.forceLogin(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FastLoginAutoLoginEvent callFastLoginAutoLoginEvent(LoginSession session, StoredProfile profile) {
|
||||
return core.getPlugin().getProxy().getPluginManager()
|
||||
.callEvent(new BungeeFastLoginAutoLoginEvent(session, profile));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceRegister(ProxiedPlayer player) {
|
||||
return session.isAlreadyLogged() || super.forceRegister(player);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,7 +70,7 @@ public class ForceLoginTask
|
||||
//sub channel name
|
||||
Type type = Type.LOGIN;
|
||||
if (session.needsRegistration()) {
|
||||
type = Type.LOGIN;
|
||||
type = Type.REGISTER;
|
||||
}
|
||||
|
||||
UUID proxyId = UUID.fromString(ProxyServer.getInstance().getConfig().getUuid());
|
||||
36
core/pom.xml
36
core/pom.xml
@@ -1,11 +1,11 @@
|
||||
<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">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.github.games647</groupId>
|
||||
<artifactId>fastlogin</artifactId>
|
||||
<version>1.11</version>
|
||||
<version>1.11-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -18,11 +18,13 @@
|
||||
<repository>
|
||||
<id>luck-repo</id>
|
||||
<url>https://ci.lucko.me/plugin/repository/everything</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public/</url>
|
||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
@@ -33,21 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>2.7.8</version>
|
||||
<version>3.4.2</version>
|
||||
</dependency>
|
||||
|
||||
<!--Logging framework implements slf4j which is required by hikari-->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<version>1.7.25</version>
|
||||
</dependency>
|
||||
|
||||
<!--GSON is not at the right position for Minecraft 1.7-->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.2.4</version>
|
||||
<version>1.7.30</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snakeyaml is present in Bungee, Spigot, Cauldron and so we could use this independent implementation -->
|
||||
@@ -63,20 +58,25 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--Common component for contacting the Mojang API-->
|
||||
<dependency>
|
||||
<groupId>com.github.games647</groupId>
|
||||
<artifactId>craftapi</artifactId>
|
||||
<version>0.1.3-SNAPSHOT</version>
|
||||
<version>0.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee, Cauldron) -->
|
||||
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee) -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<!-- The Uranium project (fork of Cauldron) uses 17.0 like Spigot 1.8 as experimental feature -->
|
||||
<!-- Project url: https://github.com/UraniumMC/Uranium -->
|
||||
<version>10.0.1</version>
|
||||
<version>17.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.2.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.github.games647.fastlogin.core;
|
||||
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* This limits the number of threads that are used at maximum. Thread creation can be very heavy for the CPU and
|
||||
* context switching between threads too. However we need many threads for blocking HTTP and database calls.
|
||||
* Nevertheless this number can be further limited, because the number of actually working database threads
|
||||
* is limited by the size of our database pool. The goal is to separate concerns into processing and blocking only
|
||||
* threads.
|
||||
*/
|
||||
public class AsyncScheduler {
|
||||
|
||||
private static final int MAX_CAPACITY = 1024;
|
||||
|
||||
//todo: single thread for delaying and scheduling tasks
|
||||
private final Logger logger;
|
||||
|
||||
// 30 threads are still too many - the optimal solution is to separate into processing and blocking threads
|
||||
// where processing threads could only be max number of cores while blocking threads could be minimized using
|
||||
// non-blocking I/O and a single event executor
|
||||
private final ExecutorService processingPool;
|
||||
|
||||
/*
|
||||
private final ExecutorService databaseExecutor = new ThreadPoolExecutor(1, 10,
|
||||
0L, TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<>(MAX_CAPACITY));
|
||||
*/
|
||||
|
||||
public AsyncScheduler(Logger logger, ThreadFactory threadFactory) {
|
||||
this.logger = logger;
|
||||
processingPool = new ThreadPoolExecutor(6, 32,
|
||||
60L, TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<>(MAX_CAPACITY), threadFactory);
|
||||
}
|
||||
|
||||
/*
|
||||
public <R> CompletableFuture<R> runDatabaseTask(Supplier<R> databaseTask) {
|
||||
return CompletableFuture.supplyAsync(databaseTask, databaseExecutor)
|
||||
.exceptionally(error -> {
|
||||
logger.warn("Error occurred on thread pool", error);
|
||||
return null;
|
||||
})
|
||||
// change context to the processing pool
|
||||
.thenApplyAsync(r -> r, processingPool);
|
||||
}
|
||||
*/
|
||||
|
||||
public CompletableFuture<Void> runAsync(Runnable task) {
|
||||
return CompletableFuture.runAsync(task, processingPool).exceptionally(error -> {
|
||||
logger.warn("Error occurred on thread pool", error);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
MoreExecutors.shutdownAndAwaitTermination(processingPool, 1, TimeUnit.MINUTES);
|
||||
//MoreExecutors.shutdownAndAwaitTermination(databaseExecutor, 1, TimeUnit.MINUTES);
|
||||
}
|
||||
}
|
||||
@@ -22,40 +22,34 @@ public class AuthStorage {
|
||||
|
||||
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 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 (?, ?, ?, ?) ";
|
||||
// limit not necessary here, because it's unique
|
||||
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 HikariDataSource dataSource;
|
||||
|
||||
public AuthStorage(FastLoginCore<?, ?, ?> core, String driver, String host, int port, String databasePath
|
||||
, String user, String pass, boolean useSSL) {
|
||||
public AuthStorage(FastLoginCore<?, ?, ?> core, String host, int port, String databasePath,
|
||||
HikariConfig config, boolean useSSL) {
|
||||
this.core = core;
|
||||
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setPoolName(core.getPlugin().getName());
|
||||
|
||||
config.setUsername(user);
|
||||
config.setPassword(pass);
|
||||
config.setDriverClassName(driver);
|
||||
|
||||
//a try to fix https://www.spigotmc.org/threads/fastlogin.101192/page-26#post-1874647
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("date_string_format", "yyyy-MM-dd HH:mm:ss");
|
||||
properties.setProperty("useSSL", String.valueOf(useSSL));
|
||||
config.setDataSourceProperties(properties);
|
||||
|
||||
ThreadFactory platformThreadFactory = core.getPlugin().getThreadFactory();
|
||||
if (platformThreadFactory != null) {
|
||||
config.setThreadFactory(platformThreadFactory);
|
||||
}
|
||||
|
||||
String jdbcUrl = "jdbc:";
|
||||
if (driver.contains("sqlite")) {
|
||||
if (config.getDriverClassName().contains("sqlite")) {
|
||||
String pluginFolder = core.getPlugin().getPluginFolder().toAbsolutePath().toString();
|
||||
databasePath = databasePath.replace("{pluginDir}", pluginFolder);
|
||||
|
||||
@@ -64,6 +58,13 @@ public class AuthStorage {
|
||||
config.setMaximumPoolSize(1);
|
||||
} else {
|
||||
jdbcUrl += "mysql://" + host + ':' + port + '/' + databasePath;
|
||||
// enable MySQL specific optimizations
|
||||
// default prepStmtCacheSize 25 - amount of cached statements - enough for us
|
||||
// default prepStmtCacheSqlLimit 256 - length of SQL - our queries are not longer
|
||||
// disabled by default - will return the same prepared statement instance
|
||||
config.addDataSourceProperty("cachePrepStmts", true);
|
||||
// default false - available in newer versions caches the statements server-side
|
||||
config.addDataSourceProperty("useServerPrepStmts", true);
|
||||
}
|
||||
|
||||
config.setJdbcUrl(jdbcUrl);
|
||||
@@ -71,23 +72,27 @@ public class AuthStorage {
|
||||
}
|
||||
|
||||
public void createTables() throws SQLException {
|
||||
// choose surrogate PK(ID), because UUID can be null for offline players
|
||||
// if UUID is always Premium UUID we would have to update offline player entries on insert
|
||||
// name cannot be PK, because it can be changed for premium players
|
||||
String createDataStmt = "CREATE TABLE IF NOT EXISTS `" + PREMIUM_TABLE + "` ("
|
||||
+ "`UserID` INTEGER PRIMARY KEY AUTO_INCREMENT, "
|
||||
+ "`UUID` CHAR(36), "
|
||||
+ "`Name` VARCHAR(16) NOT NULL, "
|
||||
+ "`Premium` BOOLEAN NOT NULL, "
|
||||
+ "`LastIp` VARCHAR(255) NOT NULL, "
|
||||
+ "`LastLogin` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "
|
||||
//the premium shouldn't steal the cracked account by changing the name
|
||||
+ "UNIQUE (`Name`) "
|
||||
+ ')';
|
||||
|
||||
if (dataSource.getJdbcUrl().contains("sqlite")) {
|
||||
createDataStmt = createDataStmt.replace("AUTO_INCREMENT", "AUTOINCREMENT");
|
||||
}
|
||||
|
||||
//todo: add unique uuid index usage
|
||||
try (Connection con = dataSource.getConnection();
|
||||
Statement createStmt = con.createStatement()) {
|
||||
String createDataStmt = "CREATE TABLE IF NOT EXISTS " + PREMIUM_TABLE + " ("
|
||||
+ "UserID INTEGER PRIMARY KEY AUTO_INCREMENT, "
|
||||
+ "UUID CHAR(36), "
|
||||
+ "Name VARCHAR(16) NOT NULL, "
|
||||
+ "Premium BOOLEAN NOT NULL, "
|
||||
+ "LastIp VARCHAR(255) NOT NULL, "
|
||||
+ "LastLogin TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "
|
||||
//the premium shouldn't steal the cracked account by changing the name
|
||||
+ "UNIQUE (Name) "
|
||||
+ ')';
|
||||
|
||||
if (dataSource.getJdbcUrl().contains("sqlite")) {
|
||||
createDataStmt = createDataStmt.replace("AUTO_INCREMENT", "AUTOINCREMENT");
|
||||
}
|
||||
|
||||
createStmt.executeUpdate(createDataStmt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class StoredProfile extends Profile {
|
||||
|
||||
private long rowId;
|
||||
@@ -45,7 +43,7 @@ public class StoredProfile extends Profile {
|
||||
this.rowId = generatedId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
// can be null
|
||||
public synchronized UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package com.github.games647.fastlogin.core.hooks;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class DefaultPasswordGenerator<P> implements PasswordGenerator<P> {
|
||||
|
||||
private static final int PASSWORD_LENGTH = 8;
|
||||
private static final char[] PASSWORD_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
.toCharArray();
|
||||
|
||||
@@ -13,9 +15,10 @@ public class DefaultPasswordGenerator<P> implements PasswordGenerator<P> {
|
||||
@Override
|
||||
public String getRandomPassword(P player) {
|
||||
StringBuilder generatedPassword = new StringBuilder(8);
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
generatedPassword.append(PASSWORD_CHARACTERS[random.nextInt(PASSWORD_CHARACTERS.length - 1)]);
|
||||
}
|
||||
IntStream.rangeClosed(1, PASSWORD_LENGTH)
|
||||
.map(i -> random.nextInt(PASSWORD_CHARACTERS.length - 1))
|
||||
.mapToObj(pos -> PASSWORD_CHARACTERS[pos])
|
||||
.forEach(generatedPassword::append);
|
||||
|
||||
return generatedPassword.toString();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.github.games647.fastlogin.core.messages;
|
||||
package com.github.games647.fastlogin.core.message;
|
||||
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
|
||||
public class ChangePremiumMessage implements ChannelMessage {
|
||||
|
||||
public static final String CHANGE_CHANNEL = "ch-st";
|
||||
|
||||
private String playerName;
|
||||
private boolean willEnable;
|
||||
private boolean isSourceInvoker;
|
||||
@@ -33,7 +35,7 @@ public class ChangePremiumMessage implements ChannelMessage {
|
||||
|
||||
@Override
|
||||
public String getChannelName() {
|
||||
return "ChangeStatus";
|
||||
return CHANGE_CHANNEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.github.games647.fastlogin.core.messages;
|
||||
package com.github.games647.fastlogin.core.message;
|
||||
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.github.games647.fastlogin.core.messages;
|
||||
package com.github.games647.fastlogin.core.message;
|
||||
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
@@ -7,6 +7,8 @@ import java.util.UUID;
|
||||
|
||||
public class LoginActionMessage implements ChannelMessage {
|
||||
|
||||
public static final String FORCE_CHANNEL = "force";
|
||||
|
||||
private Type type;
|
||||
|
||||
private String playerName;
|
||||
@@ -60,7 +62,7 @@ public class LoginActionMessage implements ChannelMessage {
|
||||
|
||||
@Override
|
||||
public String getChannelName() {
|
||||
return "LoginAction";
|
||||
return FORCE_CHANNEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.github.games647.fastlogin.core.message;
|
||||
|
||||
public class NamespaceKey {
|
||||
|
||||
private static final char SEPARATOR_CHAR = ':';
|
||||
|
||||
private final String namespace;
|
||||
private final String key;
|
||||
|
||||
private final String combined;
|
||||
|
||||
public NamespaceKey(String namespace, String key) {
|
||||
this.namespace = namespace.toLowerCase();
|
||||
this.key = key.toLowerCase();
|
||||
|
||||
this.combined = this.namespace + SEPARATOR_CHAR + this.key;
|
||||
}
|
||||
|
||||
public String getCombinedName() {
|
||||
return combined;
|
||||
}
|
||||
|
||||
public static String getCombined(String namespace, String key) {
|
||||
return new NamespaceKey(namespace, key).combined;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
package com.github.games647.fastlogin.core.messages;
|
||||
package com.github.games647.fastlogin.core.message;
|
||||
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
|
||||
public class SuccessMessage implements ChannelMessage {
|
||||
|
||||
public static final String SUCCESS_CHANNEL = "succ";
|
||||
|
||||
@Override
|
||||
public String getChannelName() {
|
||||
return "Success";
|
||||
return SUCCESS_CHANNEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -8,9 +8,11 @@ import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import com.github.games647.fastlogin.core.hooks.DefaultPasswordGenerator;
|
||||
import com.github.games647.fastlogin.core.hooks.PasswordGenerator;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
@@ -74,7 +76,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
.forEach((key, message) -> {
|
||||
String colored = CommonUtil.translateColorCodes((String) message);
|
||||
if (!colored.isEmpty()) {
|
||||
localeMessages.put(key, colored);
|
||||
localeMessages.put(key, colored.replace("/newline", "\n"));
|
||||
}
|
||||
});
|
||||
} catch (IOException ioEx) {
|
||||
@@ -103,15 +105,26 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
}
|
||||
|
||||
private Configuration loadFile(String fileName) throws IOException {
|
||||
Configuration defaults;
|
||||
|
||||
ConfigurationProvider configProvider = ConfigurationProvider.getProvider(YamlConfiguration.class);
|
||||
|
||||
Configuration defaults;
|
||||
try (InputStream defaultStream = getClass().getClassLoader().getResourceAsStream(fileName)) {
|
||||
defaults = configProvider.load(defaultStream);
|
||||
}
|
||||
|
||||
Path file = plugin.getPluginFolder().resolve(fileName);
|
||||
return configProvider.load(Files.newBufferedReader(file), defaults);
|
||||
|
||||
Configuration config;
|
||||
try (Reader reader = Files.newBufferedReader(file)) {
|
||||
config = configProvider.load(reader, defaults);
|
||||
}
|
||||
|
||||
//explicitly add keys here, because Configuration.getKeys doesn't return the keys from the default configuration
|
||||
for (String key : defaults.getKeys()) {
|
||||
config.set(key, config.get(key));
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
public MojangResolver getResolver() {
|
||||
@@ -129,7 +142,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
public void sendLocaleMessage(String key, C receiver) {
|
||||
String message = localeMessages.get(key);
|
||||
if (message != null) {
|
||||
plugin.sendMessage(receiver, message);
|
||||
plugin.sendMultiLineMessage(receiver, message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,8 +151,9 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
}
|
||||
|
||||
public boolean setupDatabase() {
|
||||
String driver = config.getString("driver");
|
||||
if (!checkDriver(driver)) {
|
||||
HikariConfig databaseConfig = new HikariConfig();
|
||||
databaseConfig.setDriverClassName(config.getString("driver"));
|
||||
if (!checkDriver(databaseConfig.getDriverClassName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -147,12 +161,15 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
int port = config.get("port", 3306);
|
||||
String database = config.getString("database");
|
||||
|
||||
String user = config.get("username", "");
|
||||
String password = config.get("password", "");
|
||||
|
||||
boolean useSSL = config.get("useSSL", false);
|
||||
|
||||
storage = new AuthStorage(this, driver, host, port, database, user, password, useSSL);
|
||||
databaseConfig.setUsername(config.get("username", ""));
|
||||
databaseConfig.setPassword(config.getString("password"));
|
||||
|
||||
databaseConfig.setConnectionTimeout(config.getInt("timeout", 30) * 1_000L);
|
||||
databaseConfig.setMaxLifetime(config.getInt("lifetime", 30) * 1_000L);
|
||||
|
||||
storage = new AuthStorage(this, host, port, database, databaseConfig, useSSL);
|
||||
try {
|
||||
storage.createTables();
|
||||
return true;
|
||||
@@ -175,7 +192,6 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public Configuration getConfig() {
|
||||
return config;
|
||||
}
|
||||
@@ -224,6 +240,9 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
}
|
||||
|
||||
public void close() {
|
||||
plugin.getLog().info("Safely shutting down scheduler. This could take up to one minute.");
|
||||
plugin.getScheduler().shutdown();
|
||||
|
||||
if (storage != null) {
|
||||
storage.close();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.github.games647.fastlogin.core.shared;
|
||||
import com.github.games647.fastlogin.core.AuthStorage;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||
|
||||
public abstract class ForceLoginManagement<P extends C, C, L extends LoginSession, T extends PlatformPlugin<C>>
|
||||
implements Runnable {
|
||||
@@ -24,7 +25,6 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
|
||||
}
|
||||
|
||||
AuthStorage storage = core.getStorage();
|
||||
|
||||
StoredProfile playerProfile = session.getProfile();
|
||||
try {
|
||||
if (isOnlineMode()) {
|
||||
@@ -41,7 +41,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
|
||||
|| (core.getConfig().get("auto-register-unknown", false)
|
||||
&& !authPlugin.isRegistered(playerName))) {
|
||||
success = forceRegister(player);
|
||||
} else {
|
||||
} else if (!callFastLoginAutoLoginEvent(session, playerProfile).isCancelled()) {
|
||||
success = forceLogin(player);
|
||||
}
|
||||
}
|
||||
@@ -85,8 +85,8 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
|
||||
|
||||
public boolean forceLogin(P player) {
|
||||
core.getPlugin().getLog().info("Logging player {} in", getName(player));
|
||||
boolean success = core.getAuthPluginHook().forceLogin(player);
|
||||
|
||||
boolean success = core.getAuthPluginHook().forceLogin(player);
|
||||
if (success) {
|
||||
core.sendLocaleMessage("auto-login", player);
|
||||
}
|
||||
@@ -94,6 +94,8 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
|
||||
return success;
|
||||
}
|
||||
|
||||
public abstract FastLoginAutoLoginEvent callFastLoginAutoLoginEvent(LoginSession session, StoredProfile profile);
|
||||
|
||||
public abstract void onForceActionSuccess(LoginSession session);
|
||||
|
||||
public abstract String getName(P player);
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.github.games647.craftapi.model.Profile;
|
||||
import com.github.games647.craftapi.resolver.RateLimitException;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -25,6 +26,8 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
||||
return;
|
||||
}
|
||||
|
||||
callFastLoginPreLoginEvent(username, source, profile);
|
||||
|
||||
Configuration config = core.getConfig();
|
||||
|
||||
String ip = source.getAddress().getAddress().getHostAddress();
|
||||
@@ -101,6 +104,8 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, S source, StoredProfile profile);
|
||||
|
||||
public abstract void requestPremiumLogin(S source, StoredProfile profile, String username, boolean registered);
|
||||
|
||||
public abstract void startCrackedSession(S source, StoredProfile profile, String username);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.github.games647.fastlogin.core.shared;
|
||||
|
||||
import com.github.games647.fastlogin.core.AsyncScheduler;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
@@ -15,7 +18,20 @@ public interface PlatformPlugin<C> {
|
||||
|
||||
void sendMessage(C receiver, String message);
|
||||
|
||||
AsyncScheduler getScheduler();
|
||||
|
||||
default void sendMultiLineMessage(C receiver, String message) {
|
||||
for (String line : message.split("%nl%")) {
|
||||
sendMessage(receiver, line);
|
||||
}
|
||||
}
|
||||
|
||||
default ThreadFactory getThreadFactory() {
|
||||
return null;
|
||||
return new ThreadFactoryBuilder()
|
||||
.setNameFormat(getName() + " Pool Thread #%1$d")
|
||||
// Hikari create daemons by default and we could daemon threads for our own scheduler too
|
||||
// because we safely shutdown
|
||||
.setDaemon(true)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.github.games647.fastlogin.core.shared.event;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||
|
||||
public interface FastLoginAutoLoginEvent extends FastLoginCancellableEvent {
|
||||
LoginSession getSession();
|
||||
StoredProfile getProfile();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.github.games647.fastlogin.core.shared.event;
|
||||
|
||||
public interface FastLoginCancellableEvent {
|
||||
|
||||
boolean isCancelled();
|
||||
void setCancelled(boolean cancelled);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.github.games647.fastlogin.core.shared.event;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||
|
||||
public interface FastLoginPreLoginEvent {
|
||||
|
||||
String getUsername();
|
||||
LoginSource getSource();
|
||||
StoredProfile getProfile();
|
||||
}
|
||||
@@ -161,17 +161,22 @@ autoLogin: true
|
||||
# Recommended is the use of MariaDB (a better version of MySQL)
|
||||
|
||||
# Single file SQLite database
|
||||
driver: org.sqlite.JDBC
|
||||
driver: 'org.sqlite.JDBC'
|
||||
# File location
|
||||
database: '{pluginDir}/FastLogin.db'
|
||||
|
||||
# MySQL/MariaDB
|
||||
#driver: com.mysql.jdbc.Driver
|
||||
#host: 127.0.0.1
|
||||
# If you want to enable it uncomment only the lines below this not this line.
|
||||
#driver: 'com.mysql.jdbc.Driver'
|
||||
#host: '127.0.0.1'
|
||||
#port: 3306
|
||||
#database: fastlogin
|
||||
#username: myUser
|
||||
#password: myPassword
|
||||
#database: 'fastlogin'
|
||||
#username: 'myUser'
|
||||
#password: 'myPassword'
|
||||
|
||||
# Advanced Connection Pool settings in seconds
|
||||
#timeout: 30
|
||||
#lifetime: 30
|
||||
|
||||
# It's strongly recommended to enable SSL and setup a SSL certificate if the MySQL server isn't running on the same
|
||||
# machine
|
||||
|
||||
25
pom.xml
25
pom.xml
@@ -1,5 +1,5 @@
|
||||
<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">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.github.games647</groupId>
|
||||
@@ -8,11 +8,11 @@
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>FastLogin</name>
|
||||
<version>1.11</version>
|
||||
<version>1.11-SNAPSHOT</version>
|
||||
|
||||
<url>https://www.spigotmc.org/resources/fastlogin.14153/</url>
|
||||
<description>
|
||||
Automatically logins premium (paid accounts) player on a offline mode server
|
||||
Automatically login premium (paid accounts) player on a offline mode server
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
@@ -21,8 +21,9 @@
|
||||
<!-- Set default for non-git clones -->
|
||||
<git.commit.id>Unknown</git.commit.id>
|
||||
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<java.version>1.8</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
@@ -31,6 +32,18 @@
|
||||
<module>bungee</module>
|
||||
</modules>
|
||||
|
||||
<!--Deployment configuration for the Maven repository-->
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>codemc-snapshots</id>
|
||||
<url>https://repo.codemc.io/repository/maven-snapshots/</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>codemc-releases</id>
|
||||
<url>https://repo.codemc.io/repository/maven-releases/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<build>
|
||||
<!--Just use the project name to replace an old version of the plugin if the user does only copy-paste-->
|
||||
<finalName>${project.name}</finalName>
|
||||
@@ -39,7 +52,7 @@
|
||||
<plugin>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
<version>2.2.4</version>
|
||||
<version>4.0.0</version>
|
||||
<configuration>
|
||||
<failOnNoGitDirectory>false</failOnNoGitDirectory>
|
||||
</configuration>
|
||||
|
||||
Reference in New Issue
Block a user