forked from TuxCoding/FastLogin
Compare commits
50 Commits
add-postgr
...
2.0
Author | SHA1 | Date | |
---|---|---|---|
ad815777d4 | |||
9a400f5ae1 | |||
c7254034bb | |||
7a8e5a59d0 | |||
d04e421927 | |||
6005f0db44 | |||
f50004f50d | |||
b6b95d50e5 | |||
be2ec1e5a8 | |||
e9643ee3e2 | |||
f1b780c398 | |||
33d3c751b9 | |||
00c0bd3b7b | |||
492a17e7de | |||
c063e7b58d | |||
0c64597ff0 | |||
9c06401e69 | |||
1f9253895c | |||
41a23bb292 | |||
756b777056 | |||
204d25a739 | |||
07e19b590a | |||
bb78043d64 | |||
7b6d2062cf | |||
3473611b90 | |||
9fabc69ba9 | |||
5a782137af | |||
4068fd06db | |||
1419b7d357 | |||
690eabaa5e | |||
caf5188246 | |||
c905ca3d33 | |||
47b6835f37 | |||
884a4e0d65 | |||
0ac8481d92 | |||
f0209170c7 | |||
e63642b146 | |||
d58ef6b0a1 | |||
8e35c5df90 | |||
cf4d19aeca | |||
7479c8be87 | |||
1889c2605e | |||
3925b66511 | |||
3f47356d35 | |||
20c2126e53 | |||
e1335dccfe | |||
b9e94d3020 | |||
896e250fa2 | |||
815ff39c96 | |||
4100daa22a |
4
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
4
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@ -12,10 +12,6 @@ body:
|
|||||||
description: What behavior is observed?
|
description: What behavior is observed?
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: What did you expect?
|
|
||||||
description: What behavior is expected?
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Steps to reproduce
|
label: Steps to reproduce
|
||||||
|
12
.github/dependabot.yml
vendored
12
.github/dependabot.yml
vendored
@ -10,10 +10,10 @@ updates:
|
|||||||
interval: "monthly"
|
interval: "monthly"
|
||||||
|
|
||||||
# Maven project
|
# Maven project
|
||||||
- package-ecosystem: maven
|
- package-ecosystem: "maven"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: weekly
|
interval: "monthly"
|
||||||
|
|
||||||
groups:
|
groups:
|
||||||
production-dependencies:
|
production-dependencies:
|
||||||
@ -25,11 +25,3 @@ updates:
|
|||||||
# Plugin require special evaluation about their compatibility
|
# Plugin require special evaluation about their compatibility
|
||||||
- "com.lenis0012.bukkit:loginsecurity"
|
- "com.lenis0012.bukkit:loginsecurity"
|
||||||
- "com.comphenix.protocol:ProtocolLib"
|
- "com.comphenix.protocol:ProtocolLib"
|
||||||
|
|
||||||
ignore:
|
|
||||||
# HikariCP dropped Java 8 support with 5.0
|
|
||||||
- dependency-name: "com.zaxxer:HikariCP"
|
|
||||||
update-types: ["version-update:semver-major"]
|
|
||||||
# SnakeYAML has breaking changes with 2.0
|
|
||||||
- dependency-name: "org.yaml:snakeyaml"
|
|
||||||
update-types: ["version-update:semver-major"]
|
|
||||||
|
3
.github/workflows/codeql-analysis.yml
vendored
3
.github/workflows/codeql-analysis.yml
vendored
@ -25,8 +25,7 @@ jobs:
|
|||||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
actions: read
|
# Only allow 'write' permission for security, then all others default to read only
|
||||||
contents: read
|
|
||||||
security-events: write
|
security-events: write
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
|
26
.github/workflows/maven.yml
vendored
26
.github/workflows/maven.yml
vendored
@ -21,7 +21,8 @@ jobs:
|
|||||||
# Environment image - always use the newest OS
|
# Environment image - always use the newest OS
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
# With at least one permission given, all default to read
|
||||||
|
contents: read
|
||||||
|
|
||||||
# Run steps
|
# Run steps
|
||||||
steps:
|
steps:
|
||||||
@ -42,6 +43,25 @@ jobs:
|
|||||||
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums
|
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums
|
||||||
run: mvn test --batch-mode --threads 2.0C --no-snapshot-updates --strict-checksums --file pom.xml
|
run: mvn test --batch-mode --threads 2.0C --no-snapshot-updates --strict-checksums --file pom.xml
|
||||||
|
|
||||||
- name: Update dependency graph
|
dependency:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
# Write only necessary for dependency submission all others then default to read
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
# Run steps
|
||||||
|
steps:
|
||||||
|
# Pull changes
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# Setup Java
|
||||||
|
- name: Set up JDK
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version-file: '.java-version'
|
||||||
|
cache: 'maven'
|
||||||
|
|
||||||
|
- name: Submit Dependency Snapshot
|
||||||
if: ${{ github.event_name == 'push' }}
|
if: ${{ github.event_name == 'push' }}
|
||||||
uses: advanced-security/maven-dependency-submission-action@v4.0.0
|
uses: advanced-security/maven-dependency-submission-action@v4.0.3
|
||||||
|
26
CHANGELOG.md
26
CHANGELOG.md
@ -1,3 +1,29 @@
|
|||||||
|
# 2.0
|
||||||
|
|
||||||
|
## Major changes
|
||||||
|
|
||||||
|
* Bumped minimum Java version to 11 make use of modern Java performance features
|
||||||
|
* Report back if really still need the old versions
|
||||||
|
* Then we could make use of versioned code, but that requires more coding effort
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
* Support for HTTP/2 for contacting Mojang
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
* Updated many dependencies
|
||||||
|
|
||||||
|
## Removed
|
||||||
|
|
||||||
|
Dropped some features listed below. Please contact us if you still need them
|
||||||
|
|
||||||
|
* Dropped Java support < 11
|
||||||
|
* Removed configuration option to add multiple outgoing IPv4 towards Mojang
|
||||||
|
* Dropped support for ProtocolSupport seems to unsupported
|
||||||
|
|
||||||
|
[...] A lot of changes
|
||||||
|
|
||||||
### 1.11
|
### 1.11
|
||||||
|
|
||||||
* TODO: Replace reflection with methodhandles
|
* TODO: Replace reflection with methodhandles
|
||||||
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015-2023 games647 and contributors
|
Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
23
README.md
23
README.md
@ -8,14 +8,11 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
|
|||||||
* Detect paid accounts from others
|
* Detect paid accounts from others
|
||||||
* Automatically login paid accounts (premium)
|
* Automatically login paid accounts (premium)
|
||||||
* Support various of auth plugins
|
* Support various of auth plugins
|
||||||
* Cauldron support
|
|
||||||
* Forge/Sponge message support
|
|
||||||
* Premium UUID support
|
* Premium UUID support
|
||||||
* Forward skins
|
* Forward skins
|
||||||
* Detect username changed and will update the existing database record
|
* Detect username changed and will update the existing database record
|
||||||
* BungeeCord support
|
* BungeeCord/Velocity support
|
||||||
* Auto register new premium players
|
* Auto register new premium players
|
||||||
* Plugin: ProtocolSupport is supported and can be used as an alternative to ProtocolLib
|
|
||||||
* No client modifications needed
|
* No client modifications needed
|
||||||
* Good performance by using async operations
|
* Good performance by using async operations
|
||||||
* Locale messages
|
* Locale messages
|
||||||
@ -46,6 +43,7 @@ You can download them from here: https://ci.codemc.org/job/Games647/job/FastLogi
|
|||||||
|
|
||||||
fastlogin.bukkit.command.premium
|
fastlogin.bukkit.command.premium
|
||||||
fastlogin.bukkit.command.cracked
|
fastlogin.bukkit.command.cracked
|
||||||
|
|
||||||
fastlogin.command.premium.other
|
fastlogin.command.premium.other
|
||||||
fastlogin.command.cracked.other
|
fastlogin.command.cracked.other
|
||||||
|
|
||||||
@ -60,13 +58,15 @@ Possible values: `Premium`, `Cracked`, `Unknown`
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
* Java 17+ (Recommended)
|
* Java: 21+ recommended for improved multi-threading code by FastLogin
|
||||||
|
* Spigot: 8+
|
||||||
|
* BungeeCord and Velocity: 17+
|
||||||
* Server software in offlinemode:
|
* Server software in offlinemode:
|
||||||
* Spigot (or a fork e.g. Paper) 1.8.8+
|
* Spigot (or a fork e.g. Paper) 1.8.8+
|
||||||
* Protocol plugin:
|
* Protocol plugin:
|
||||||
* [ProtocolLib 5.1+](https://www.spigotmc.org/resources/protocollib.1997/) or
|
* [ProtocolLib 5.2+](https://www.spigotmc.org/resources/protocollib.1997/) or
|
||||||
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
|
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
|
||||||
* Latest BungeeCord (or a fork e.g. Waterfall) or Velocity
|
* Latest BungeeCord (or a fork e.g. Waterfall) or Velocity proxy
|
||||||
* An auth plugin.
|
* An auth plugin.
|
||||||
|
|
||||||
### Supported auth plugins
|
### Supported auth plugins
|
||||||
@ -85,7 +85,6 @@ Possible values: `Premium`, `Cracked`, `Unknown`
|
|||||||
#### BungeeCord/Waterfall
|
#### BungeeCord/Waterfall
|
||||||
|
|
||||||
* [BungeeAuth](https://www.spigotmc.org/resources/bungeeauth.493/)
|
* [BungeeAuth](https://www.spigotmc.org/resources/bungeeauth.493/)
|
||||||
* [BungeeAuthenticator](https://www.spigotmc.org/resources/bungeecordauthenticator.87669/)
|
|
||||||
|
|
||||||
## Network requests
|
## Network requests
|
||||||
|
|
||||||
@ -101,8 +100,8 @@ This plugin performs network requests to:
|
|||||||
### Spigot/Paper
|
### Spigot/Paper
|
||||||
|
|
||||||
1. Download and install ProtocolLib/ProtocolSupport
|
1. Download and install ProtocolLib/ProtocolSupport
|
||||||
2. Download and install FastLogin (or `FastLoginBukkit` for newer versions)
|
2. Download and install `FastLoginBukkit`
|
||||||
3. Set your server in offline mode by setting the value `onlinemode` in your server.properties to false
|
3. Set your server in offline mode by setting the value `onlinemode` in your server.properties to `false`
|
||||||
|
|
||||||
### BungeeCord/Waterfall or Velocity
|
### BungeeCord/Waterfall or Velocity
|
||||||
|
|
||||||
@ -117,8 +116,8 @@ Install the plugin on both platforms, that is proxy (BungeeCord or Velocity) and
|
|||||||
4. Activate ip forwarding in your proxy config
|
4. Activate ip forwarding in your proxy config
|
||||||
5. Check your database settings in the config of FastLogin on your proxy
|
5. Check your database settings in the config of FastLogin on your proxy
|
||||||
* The proxies only ship with a limited set of drivers where Spigot supports more. Therefore, these are supported:
|
* The proxies only ship with a limited set of drivers where Spigot supports more. Therefore, these are supported:
|
||||||
* BungeeCord: `com.mysql.jdbc.Driver` for MySQL/MariaDB
|
* BungeeCord: `mysql` for MySQL/MariaDB
|
||||||
* Velocity: `fastlogin.mariadb.jdbc.Driver` for MySQL/MariaDB
|
* Velocity: `mariadb` for MySQL/MariaDB
|
||||||
* Note the embedded file storage SQLite is not available
|
* Note the embedded file storage SQLite is not available
|
||||||
* MySQL/MariaDB requires an external database server running. Check your server provider if there is one available
|
* MySQL/MariaDB requires an external database server running. Check your server provider if there is one available
|
||||||
or install one.
|
or install one.
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015-2023 games647 and contributors
|
Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -30,7 +30,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<nettyVersion>4.1.79.Final</nettyVersion>
|
<maven.compiler.release>8</maven.compiler.release>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
@ -50,7 +50,7 @@
|
|||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.5.1</version>
|
<version>3.5.3</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||||
@ -98,7 +98,6 @@
|
|||||||
<filter>
|
<filter>
|
||||||
<artifact>*:*</artifact>
|
<artifact>*:*</artifact>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>META-INF/MANIFEST.MF</exclude>
|
|
||||||
<exclude>**/module-info.class</exclude>
|
<exclude>**/module-info.class</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</filter>
|
</filter>
|
||||||
@ -117,7 +116,7 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<!-- PaperSpigot API and PaperLib -->
|
<!-- PaperSpigot API, PaperLib, datafixupper and bungeecord-chat -->
|
||||||
<repository>
|
<repository>
|
||||||
<id>papermc</id>
|
<id>papermc</id>
|
||||||
<url>https://papermc.io/repo/repository/maven-public/</url>
|
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||||
@ -168,18 +167,11 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.yaml</groupId>
|
|
||||||
<artifactId>snakeyaml</artifactId>
|
|
||||||
<version>1.33</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- PaperSpigot API for correcting user cache usage -->
|
<!-- PaperSpigot API for correcting user cache usage -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.papermc.paper</groupId>
|
<groupId>io.papermc.paper</groupId>
|
||||||
<artifactId>paper-api</artifactId>
|
<artifactId>paper-api</artifactId>
|
||||||
<version>1.19-R0.1-SNAPSHOT</version>
|
<version>1.20.6-R0.1-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<!-- Use our own newer api version -->
|
<!-- Use our own newer api version -->
|
||||||
<exclusions>
|
<exclusions>
|
||||||
@ -187,13 +179,25 @@
|
|||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.ow2.asm</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mojang</groupId>
|
<groupId>com.mojang</groupId>
|
||||||
<artifactId>datafixerupper</artifactId>
|
<artifactId>datafixerupper</artifactId>
|
||||||
<version>5.0.28</version>
|
<version>7.1.15</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
@ -378,29 +382,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bouncycastle</groupId>
|
<groupId>org.bouncycastle</groupId>
|
||||||
<artifactId>bcprov-jdk18on</artifactId>
|
<artifactId>bcprov-jdk18on</artifactId>
|
||||||
<version>1.77</version>
|
<version>1.78.1</version>
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.netty</groupId>
|
|
||||||
<artifactId>netty-transport</artifactId>
|
|
||||||
<version>${nettyVersion}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.netty</groupId>
|
|
||||||
<artifactId>netty-codec</artifactId>
|
|
||||||
<version>${nettyVersion}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Provided by the spigot, required for testing ProtocolLib -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-lang</groupId>
|
|
||||||
<artifactId>commons-lang</artifactId>
|
|
||||||
<version>2.6</version>
|
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -26,7 +26,7 @@
|
|||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit;
|
||||||
|
|
||||||
import com.github.games647.craftapi.model.skin.SkinProperty;
|
import com.github.games647.craftapi.model.skin.SkinProperty;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -47,7 +47,6 @@ public class BukkitLoginSession extends LoginSession {
|
|||||||
private final ClientPublicKey clientPublicKey;
|
private final ClientPublicKey clientPublicKey;
|
||||||
|
|
||||||
private boolean verified;
|
private boolean verified;
|
||||||
|
|
||||||
private SkinProperty skinProperty;
|
private SkinProperty skinProperty;
|
||||||
|
|
||||||
public BukkitLoginSession(String username, byte[] verifyToken, ClientPublicKey publicKey, boolean registered,
|
public BukkitLoginSession(String username, byte[] verifyToken, ClientPublicKey publicKey, boolean registered,
|
||||||
@ -109,7 +108,7 @@ public class BukkitLoginSession extends LoginSession {
|
|||||||
*
|
*
|
||||||
* @param verified whether the player has valid session
|
* @param verified whether the player has valid session
|
||||||
*/
|
*/
|
||||||
public synchronized void setVerified(boolean verified) {
|
public synchronized void setVerifiedPremium(boolean verified) {
|
||||||
this.verified = verified;
|
this.verified = verified;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +117,7 @@ public class BukkitLoginSession extends LoginSession {
|
|||||||
*
|
*
|
||||||
* @return whether the player has a valid session
|
* @return whether the player has a valid session
|
||||||
*/
|
*/
|
||||||
public synchronized boolean isVerified() {
|
public synchronized boolean isVerifiedPremium() {
|
||||||
return verified;
|
return verified;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -25,7 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.AsyncScheduler;
|
import com.github.games647.fastlogin.core.scheduler.AsyncScheduler;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -25,15 +25,13 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit;
|
||||||
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.github.games647.fastlogin.bukkit.auth.AuthenticationBackend;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.ConnectionListener;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.ProtocolAuthentication;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.proxy.ProxyAuthentication;
|
||||||
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
|
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
|
||||||
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
|
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
|
import com.github.games647.fastlogin.bukkit.hook.DelayedAuthHook;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.PaperCacheListener;
|
|
||||||
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.task.DelayedAuthHook;
|
|
||||||
import com.github.games647.fastlogin.core.CommonUtil;
|
import com.github.games647.fastlogin.core.CommonUtil;
|
||||||
import com.github.games647.fastlogin.core.PremiumStatus;
|
import com.github.games647.fastlogin.core.PremiumStatus;
|
||||||
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
||||||
@ -41,6 +39,7 @@ import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
|||||||
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
||||||
|
import lombok.Getter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -53,6 +52,9 @@ import org.slf4j.Logger;
|
|||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -65,19 +67,34 @@ import java.util.concurrent.ConcurrentMap;
|
|||||||
public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<CommandSender> {
|
public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<CommandSender> {
|
||||||
|
|
||||||
//1 minutes should be enough as a timeout for bad internet connection (Server, Client and Mojang)
|
//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 ConcurrentMap<String, BukkitLoginSession> loginSession = CommonUtil.buildCache(
|
||||||
|
Duration.ofMinutes(1), -1
|
||||||
|
);
|
||||||
|
|
||||||
|
@Getter
|
||||||
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
|
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
private boolean serverStarted;
|
|
||||||
private BungeeManager bungeeManager;
|
|
||||||
private final BukkitScheduler scheduler;
|
private final BukkitScheduler scheduler;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final Collection<UUID> pendingConfirms = new HashSet<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
|
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
|
||||||
|
|
||||||
|
@Getter
|
||||||
private FloodgateService floodgateService;
|
private FloodgateService floodgateService;
|
||||||
private GeyserService geyserService;
|
private GeyserService geyserService;
|
||||||
|
|
||||||
private PremiumPlaceholder premiumPlaceholder;
|
private PremiumPlaceholder premiumPlaceholder;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private AuthenticationBackend backend;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private boolean initialized;
|
||||||
|
|
||||||
public FastLoginBukkit() {
|
public FastLoginBukkit() {
|
||||||
this.logger = CommonUtil.initializeLoggerService(getLogger());
|
this.logger = CommonUtil.initializeLoggerService(getLogger());
|
||||||
this.scheduler = new BukkitScheduler(this, logger);
|
this.scheduler = new BukkitScheduler(this, logger);
|
||||||
@ -99,52 +116,48 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bungeeManager = new BungeeManager(this);
|
backend = initializeAuthenticationBackend();
|
||||||
bungeeManager.initialize();
|
if (backend == null) {
|
||||||
|
logger.warn("Either ProtocolLib or ProtocolSupport have to be installed if you don't use BungeeCord");
|
||||||
PluginManager pluginManager = getServer().getPluginManager();
|
setEnabled(false);
|
||||||
if (bungeeManager.isEnabled()) {
|
return;
|
||||||
markInitialized();
|
|
||||||
} else {
|
|
||||||
if (!core.setupDatabase()) {
|
|
||||||
setEnabled(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pluginManager.isPluginEnabled("ProtocolSupport")) {
|
|
||||||
pluginManager.registerEvents(new ProtocolSupportListener(this, core.getAntiBot()), this);
|
|
||||||
} else if (pluginManager.isPluginEnabled("ProtocolLib")) {
|
|
||||||
ProtocolLibListener.register(this, core.getAntiBot(), core.getConfig().getBoolean("verifyClientKeys"));
|
|
||||||
|
|
||||||
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
|
|
||||||
if (!isPaper() && getConfig().getBoolean("forwardSkin")) {
|
|
||||||
pluginManager.registerEvents(new SkinApplyListener(this), this);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.warn("Either ProtocolLib or ProtocolSupport have to be installed if you don't use BungeeCord");
|
|
||||||
setEnabled(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//delay dependency setup because we load the plugin very early where plugins are initialized yet
|
backend.init(getServer().getPluginManager());
|
||||||
getServer().getScheduler().runTaskLater(this, new DelayedAuthHook(this), 5L);
|
PluginManager pluginManager = getServer().getPluginManager();
|
||||||
|
|
||||||
pluginManager.registerEvents(new ConnectionListener(this), this);
|
pluginManager.registerEvents(new ConnectionListener(this), this);
|
||||||
|
|
||||||
//if server is using paper - we need to add one more listener to correct the user cache usage
|
registerCommands();
|
||||||
if (isPaper()) {
|
|
||||||
pluginManager.registerEvents(new PaperCacheListener(this), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//register commands using a unique name
|
|
||||||
Optional.ofNullable(getCommand("premium")).ifPresent(c -> c.setExecutor(new PremiumCommand(this)));
|
|
||||||
Optional.ofNullable(getCommand("cracked")).ifPresent(c -> c.setExecutor(new CrackedCommand(this)));
|
|
||||||
|
|
||||||
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
|
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
|
||||||
premiumPlaceholder = new PremiumPlaceholder(this);
|
premiumPlaceholder = new PremiumPlaceholder(this);
|
||||||
premiumPlaceholder.register();
|
premiumPlaceholder.register();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// delay dependency setup because we load the plugin very early where plugins are initialized yet
|
||||||
|
getServer().getScheduler().runTaskLater(this, new DelayedAuthHook(this), 5L);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuthenticationBackend initializeAuthenticationBackend() {
|
||||||
|
AuthenticationBackend proxyVerifier = new ProxyAuthentication(this);
|
||||||
|
if (proxyVerifier.isAvailable()) {
|
||||||
|
return proxyVerifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.warn("Disabling Minecraft proxy configuration. Assuming direct connections from now on.");
|
||||||
|
AuthenticationBackend protocolAuthentication = new ProtocolAuthentication(this);
|
||||||
|
if (protocolAuthentication.isAvailable()) {
|
||||||
|
return protocolAuthentication;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerCommands() {
|
||||||
|
//register commands using a unique name
|
||||||
|
Optional.ofNullable(getCommand("premium")).ifPresent(c -> c.setExecutor(new PremiumCommand(this)));
|
||||||
|
Optional.ofNullable(getCommand("cracked")).ifPresent(c -> c.setExecutor(new CrackedCommand(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean initializeFloodgate() {
|
private boolean initializeFloodgate() {
|
||||||
@ -172,25 +185,13 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
core.close();
|
core.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bungeeManager != null) {
|
if (backend != null) {
|
||||||
bungeeManager.cleanup();
|
backend.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (premiumPlaceholder != null && getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
if (premiumPlaceholder != null && getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
||||||
try {
|
premiumPlaceholder.unregister();
|
||||||
premiumPlaceholder.unregister();
|
|
||||||
} catch (Exception | NoSuchMethodError exception) {
|
|
||||||
logger.error("Failed to unregister placeholder", exception);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getServer().getPluginManager().isPluginEnabled("ProtocolLib")) {
|
|
||||||
ProtocolLibrary.getProtocolManager().getAsynchronousManager().unregisterAsyncHandlers(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FastLoginCore<Player, CommandSender, FastLoginBukkit> getCore() {
|
|
||||||
return core;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -222,10 +223,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
loginSession.remove(id);
|
loginSession.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<UUID, PremiumStatus> getPremiumPlayers() {
|
|
||||||
return premiumPlayers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the premium status of an online player.
|
* Fetches the premium status of an online player.
|
||||||
* {@snippet :
|
* {@snippet :
|
||||||
@ -253,24 +250,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
return premiumPlayers.getOrDefault(onlinePlayer, PremiumStatus.UNKNOWN);
|
return premiumPlayers.getOrDefault(onlinePlayer, PremiumStatus.UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait before the server is fully started. This is workaround, because connections right on startup are not
|
|
||||||
* injected by ProtocolLib
|
|
||||||
*
|
|
||||||
* @return true if ProtocolLib can now intercept packets
|
|
||||||
*/
|
|
||||||
public boolean isServerFullyStarted() {
|
|
||||||
return serverStarted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void markInitialized() {
|
|
||||||
this.serverStarted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BungeeManager getBungeeManager() {
|
|
||||||
return bungeeManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Path getPluginFolder() {
|
public Path getPluginFolder() {
|
||||||
return getDataFolder().toPath();
|
return getDataFolder().toPath();
|
||||||
@ -303,12 +282,21 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
|
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FloodgateService getFloodgateService() {
|
public void setInitialized(boolean hookFound) {
|
||||||
return floodgateService;
|
if (backend instanceof ProxyAuthentication) {
|
||||||
|
logger.info("BungeeCord setting detected. No auth plugin is required");
|
||||||
|
} else if (!hookFound) {
|
||||||
|
logger.warn("No auth plugin were found by this plugin "
|
||||||
|
+ "(other plugins could hook into this after the initialization of this plugin)"
|
||||||
|
+ "and BungeeCord is deactivated. "
|
||||||
|
+ "Either one or both of the checks have to pass in order to use this plugin");
|
||||||
|
}
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeyserService getGeyserService() {
|
public ProxyAuthentication getBungeeManager() {
|
||||||
return geyserService;
|
return (ProxyAuthentication) backend;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -316,19 +304,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
if (floodgateService != null) {
|
if (floodgateService != null) {
|
||||||
return floodgateService;
|
return floodgateService;
|
||||||
}
|
}
|
||||||
|
|
||||||
return geyserService;
|
return geyserService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPaper() {
|
|
||||||
return isClassAvailable("com.destroystokyo.paper.PaperConfig").isPresent()
|
|
||||||
|| isClassAvailable("io.papermc.paper.configuration.Configuration").isPresent();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<Class<?>> isClassAvailable(String clazzName) {
|
|
||||||
try {
|
|
||||||
return Optional.of(Class.forName(clazzName));
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -74,11 +74,13 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String getAuthor() {
|
public @NotNull String getAuthor() {
|
||||||
|
//noinspection deprecation
|
||||||
return String.join(", ", plugin.getDescription().getAuthors());
|
return String.join(", ", plugin.getDescription().getAuthors());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String getVersion() {
|
public @NotNull String getVersion() {
|
||||||
|
//noinspection deprecation
|
||||||
return plugin.getDescription().getVersion();
|
return plugin.getDescription().getVersion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
|
||||||
|
public interface AuthenticationBackend {
|
||||||
|
|
||||||
|
boolean isAvailable();
|
||||||
|
|
||||||
|
void init(PluginManager pluginManager);
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,23 +23,17 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener;
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.bukkit.task.FloodgateAuthTask;
|
|
||||||
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
|
|
||||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.event.player.PlayerLoginEvent;
|
|
||||||
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
import org.bukkit.metadata.Metadatable;
|
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,14 +50,6 @@ public class ConnectionListener implements Listener {
|
|||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
|
||||||
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
|
|
||||||
removeBlockedStatus(loginEvent.getPlayer());
|
|
||||||
if (loginEvent.getResult() == Result.ALLOWED && !plugin.isServerFullyStarted()) {
|
|
||||||
loginEvent.disallow(Result.KICK_OTHER, plugin.getCore().getMessage("not-started"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
|
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
|
||||||
Player player = joinEvent.getPlayer();
|
Player player = joinEvent.getPlayer();
|
||||||
@ -102,21 +88,13 @@ public class ConnectionListener implements Listener {
|
|||||||
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getBungeeManager().markJoinEventFired(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
|
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
|
||||||
Player player = quitEvent.getPlayer();
|
Player player = quitEvent.getPlayer();
|
||||||
|
|
||||||
removeBlockedStatus(player);
|
plugin.getPendingConfirms().remove(player.getUniqueId());
|
||||||
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
|
|
||||||
plugin.getPremiumPlayers().remove(player.getUniqueId());
|
plugin.getPremiumPlayers().remove(player.getUniqueId());
|
||||||
plugin.getBungeeManager().cleanup(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeBlockedStatus(Metadatable player) {
|
|
||||||
player.removeMetadata(plugin.getName(), plugin);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.task;
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
@ -49,7 +49,7 @@ public class FloodgateAuthTask extends FloodgateManagement<Player, CommandSender
|
|||||||
BukkitLoginSession session = new BukkitLoginSession(player.getName(), isRegistered, profile);
|
BukkitLoginSession session = new BukkitLoginSession(player.getName(), isRegistered, profile);
|
||||||
|
|
||||||
// enable auto login based on the value of 'autoLoginFloodgate' in config.yml
|
// enable auto login based on the value of 'autoLoginFloodgate' in config.yml
|
||||||
session.setVerified(isAutoAuthAllowed(autoLoginFloodgate));
|
session.setVerifiedPremium(isAutoAuthAllowed(autoLoginFloodgate));
|
||||||
|
|
||||||
// run login task
|
// run login task
|
||||||
Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, session);
|
Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, session);
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.task;
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
@ -80,7 +80,7 @@ public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onForceActionSuccess(LoginSession session) {
|
public void onForceActionSuccess(LoginSession session) {
|
||||||
if (core.getPlugin().getBungeeManager().isEnabled()) {
|
if (core.getPlugin().getBungeeManager().isAvailable()) {
|
||||||
core.getPlugin().getBungeeManager().sendPluginMessage(player, new SuccessMessage());
|
core.getPlugin().getBungeeManager().sendPluginMessage(player, new SuccessMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,6 +103,6 @@ public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOnlineMode() {
|
public boolean isOnlineMode() {
|
||||||
return session.isVerified();
|
return session.isVerifiedPremium();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.SkinApplyListener;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public abstract class LocalAuthentication implements AuthenticationBackend {
|
||||||
|
|
||||||
|
protected final FastLoginBukkit plugin;
|
||||||
|
|
||||||
|
protected LocalAuthentication(FastLoginBukkit plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(PluginManager pluginManager) {
|
||||||
|
if (!plugin.getCore().setupDatabase()) {
|
||||||
|
plugin.setEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if server is using paper - we need to add one more listener to correct the user cache usage
|
||||||
|
if (isPaper()) {
|
||||||
|
pluginManager.registerEvents(new PaperCacheListener(plugin), plugin);
|
||||||
|
} else if (plugin.getConfig().getBoolean("forwardSkin")) {
|
||||||
|
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
|
||||||
|
pluginManager.registerEvents(new SkinApplyListener(plugin), plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPaper() {
|
||||||
|
return isClassAvailable("com.destroystokyo.paper.PaperConfig").isPresent()
|
||||||
|
|| isClassAvailable("io.papermc.paper.configuration.Configuration").isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Class<?>> isClassAvailable(String clazzName) {
|
||||||
|
try {
|
||||||
|
return Optional.of(Class.forName(clazzName));
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener;
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
import com.destroystokyo.paper.profile.ProfileProperty;
|
import com.destroystokyo.paper.profile.ProfileProperty;
|
||||||
import com.github.games647.craftapi.model.skin.Textures;
|
import com.github.games647.craftapi.model.skin.Textures;
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,10 +23,10 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.google.common.hash.Hasher;
|
import com.google.common.hash.Hasher;
|
||||||
import com.google.common.hash.Hashing;
|
import com.google.common.hash.Hashing;
|
||||||
import com.google.common.io.Resources;
|
import com.google.common.io.Resources;
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,14 +23,14 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
|
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
|
||||||
import com.github.games647.fastlogin.core.shared.JoinManagement;
|
import com.github.games647.fastlogin.core.shared.JoinManagement;
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
||||||
@ -97,7 +97,7 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
|
|||||||
}
|
}
|
||||||
|
|
||||||
String ip = player.getAddress().getAddress().getHostAddress();
|
String ip = player.getAddress().getAddress().getHostAddress();
|
||||||
core.getPendingLogin().put(ip + username, new Object());
|
core.addLoginAttempt(ip, username);
|
||||||
|
|
||||||
byte[] verify = source.getVerifyToken();
|
byte[] verify = source.getVerifyToken();
|
||||||
ClientPublicKey clientKey = source.getClientKey();
|
ClientPublicKey clientKey = source.getClientKey();
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.LocalAuthentication;
|
||||||
|
import com.github.games647.fastlogin.core.antibot.AntiBotService;
|
||||||
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerLoginEvent;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
|
||||||
|
public class ProtocolAuthentication extends LocalAuthentication implements Listener {
|
||||||
|
|
||||||
|
public ProtocolAuthentication(FastLoginBukkit plugin) {
|
||||||
|
super(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return plugin.getServer().getPluginManager().isPluginEnabled("ProtocolLib");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(PluginManager pluginManager) {
|
||||||
|
pluginManager.registerEvents(this, plugin);
|
||||||
|
|
||||||
|
FastLoginCore<Player, CommandSender, FastLoginBukkit> core = plugin.getCore();
|
||||||
|
AntiBotService antiBotService = core.getAntiBotService();
|
||||||
|
ProtocolLibListener.register(plugin, antiBotService, core.getConfig().getBoolean("verifyClientKeys"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
ProtocolLibrary.getProtocolManager().getAsynchronousManager().unregisterAsyncHandlers(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
|
||||||
|
if (loginEvent.getResult() == PlayerLoginEvent.Result.ALLOWED && !plugin.isInitialized()) {
|
||||||
|
loginEvent.disallow(PlayerLoginEvent.Result.KICK_OTHER, plugin.getCore().getMessage("not-started"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.comphenix.protocol.PacketType;
|
import com.comphenix.protocol.PacketType;
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
@ -32,6 +32,7 @@ import com.comphenix.protocol.events.PacketContainer;
|
|||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
import com.comphenix.protocol.injector.PacketFilterManager;
|
import com.comphenix.protocol.injector.PacketFilterManager;
|
||||||
import com.comphenix.protocol.injector.player.PlayerInjectionHandler;
|
import com.comphenix.protocol.injector.player.PlayerInjectionHandler;
|
||||||
|
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||||
@ -41,7 +42,7 @@ import com.comphenix.protocol.wrappers.Converters;
|
|||||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.github.games647.fastlogin.core.antibot.AntiBotService;
|
import com.github.games647.fastlogin.core.antibot.AntiBotService;
|
||||||
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
|
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
|
||||||
import com.mojang.datafixers.util.Either;
|
import com.mojang.datafixers.util.Either;
|
||||||
@ -51,6 +52,7 @@ import io.netty.util.AttributeKey;
|
|||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
@ -108,49 +110,70 @@ public class ProtocolLibListener extends PacketAdapter {
|
|||||||
public void onPacketReceiving(PacketEvent packetEvent) {
|
public void onPacketReceiving(PacketEvent packetEvent) {
|
||||||
if (packetEvent.isCancelled()
|
if (packetEvent.isCancelled()
|
||||||
|| plugin.getCore().getAuthPluginHook() == null
|
|| plugin.getCore().getAuthPluginHook() == null
|
||||||
|| !plugin.isServerFullyStarted()) {
|
|| !plugin.isInitialized()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getLog().info("New packet {} from {}", packetEvent.getPacketType(), packetEvent.getPlayer());
|
|
||||||
|
|
||||||
Player sender = packetEvent.getPlayer();
|
Player sender = packetEvent.getPlayer();
|
||||||
PacketType packetType = packetEvent.getPacketType();
|
PacketType packetType = getOverriddenType(packetEvent.getPacketType());
|
||||||
if (packetType == START) {
|
|
||||||
|
|
||||||
if (plugin.getFloodgateService() != null) {
|
plugin.getLog().info("New packet {} from {}", packetType, sender);
|
||||||
boolean success = processFloodgateTasks(packetEvent);
|
try {
|
||||||
// don't continue execution if the player was kicked by Floodgate
|
if (packetType == START) {
|
||||||
if (!success) {
|
if (plugin.getFloodgateService() != null) {
|
||||||
return;
|
boolean success = processFloodgateTasks(packetEvent);
|
||||||
|
// don't continue execution if the player was kicked by Floodgate
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PacketContainer packet = packetEvent.getPacket();
|
||||||
|
|
||||||
|
InetSocketAddress address = sender.getAddress();
|
||||||
|
String username = getUsername(packet);
|
||||||
|
|
||||||
|
Action action = antiBotService.onIncomingConnection(address, username);
|
||||||
|
switch (action) {
|
||||||
|
case Ignore:
|
||||||
|
// just ignore
|
||||||
|
return;
|
||||||
|
case Block:
|
||||||
|
String message = plugin.getCore().getMessage("kick-antibot");
|
||||||
|
sender.kickPlayer(message);
|
||||||
|
break;
|
||||||
|
case Continue:
|
||||||
|
default:
|
||||||
|
//player.getName() won't work at this state
|
||||||
|
onLoginStart(packetEvent, sender, username);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (packetType == ENCRYPTION_BEGIN) {
|
||||||
|
onEncryptionBegin(packetEvent, sender);
|
||||||
|
} else {
|
||||||
|
plugin.getLog().warn("Unknown packet type received {}", packetType);
|
||||||
}
|
}
|
||||||
|
} catch (FieldAccessException fieldAccessEx) {
|
||||||
PacketContainer packet = packetEvent.getPacket();
|
plugin.getLog().error("Failed to parse packet {}", packetEvent.getPacketType(), fieldAccessEx);
|
||||||
|
|
||||||
InetSocketAddress address = sender.getAddress();
|
|
||||||
String username = getUsername(packet);
|
|
||||||
|
|
||||||
Action action = antiBotService.onIncomingConnection(address, username);
|
|
||||||
switch (action) {
|
|
||||||
case Ignore:
|
|
||||||
// just ignore
|
|
||||||
return;
|
|
||||||
case Block:
|
|
||||||
String message = plugin.getCore().getMessage("kick-antibot");
|
|
||||||
sender.kickPlayer(message);
|
|
||||||
break;
|
|
||||||
case Continue:
|
|
||||||
default:
|
|
||||||
//player.getName() won't work at this state
|
|
||||||
onLoginStart(packetEvent, sender, username);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
onEncryptionBegin(packetEvent, sender);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @NotNull PacketType getOverriddenType(PacketType packetType) {
|
||||||
|
if (packetType.isDynamic()) {
|
||||||
|
String vanillaName = packetType.getPacketClass().getName();
|
||||||
|
plugin.getLog().info("Overriding packet type for unregistered packet type to fix ProtocolLib bug");
|
||||||
|
if (vanillaName.endsWith("ServerboundHelloPacket")) {
|
||||||
|
return START;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vanillaName.endsWith("ServerboundKeyPacket")) {
|
||||||
|
return ENCRYPTION_BEGIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return packetType;
|
||||||
|
}
|
||||||
|
|
||||||
private void onEncryptionBegin(PacketEvent packetEvent, Player sender) {
|
private void onEncryptionBegin(PacketEvent packetEvent, Player sender) {
|
||||||
byte[] sharedSecret = packetEvent.getPacket().getByteArrays().read(0);
|
byte[] sharedSecret = packetEvent.getPacket().getByteArrays().read(0);
|
||||||
|
|
||||||
@ -222,7 +245,7 @@ public class ProtocolLibListener extends PacketAdapter {
|
|||||||
PacketContainer packet = packetEvent.getPacket();
|
PacketContainer packet = packetEvent.getPacket();
|
||||||
Optional<ClientPublicKey> clientKey;
|
Optional<ClientPublicKey> clientKey;
|
||||||
if (new MinecraftVersion(1, 19, 3).atOrAbove()) {
|
if (new MinecraftVersion(1, 19, 3).atOrAbove()) {
|
||||||
// public key sent separate
|
// public key is sent separate
|
||||||
clientKey = Optional.empty();
|
clientKey = Optional.empty();
|
||||||
} else {
|
} else {
|
||||||
val profileKey = packet.getOptionals(BukkitConverters.getWrappedPublicKeyDataConverter())
|
val profileKey = packet.getOptionals(BukkitConverters.getWrappedPublicKeyDataConverter())
|
||||||
@ -247,7 +270,6 @@ public class ProtocolLibListener extends PacketAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
plugin.getLog().trace("GameProfile {} with {} connecting", sessionKey, username);
|
plugin.getLog().trace("GameProfile {} with {} connecting", sessionKey, username);
|
||||||
|
|
||||||
packetEvent.getAsyncMarker().incrementProcessingDelay();
|
packetEvent.getAsyncMarker().incrementProcessingDelay();
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,14 +23,14 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
import com.comphenix.protocol.ProtocolManager;
|
import com.comphenix.protocol.ProtocolManager;
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
import com.comphenix.protocol.reflect.StructureModifier;
|
import com.comphenix.protocol.reflect.StructureModifier;
|
||||||
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@ -51,7 +51,6 @@ class ProtocolLibLoginSource implements LoginSource {
|
|||||||
private final ClientPublicKey clientKey;
|
private final ClientPublicKey clientKey;
|
||||||
private final PublicKey publicKey;
|
private final PublicKey publicKey;
|
||||||
|
|
||||||
private final String serverId = "";
|
|
||||||
private byte[] verifyToken;
|
private byte[] verifyToken;
|
||||||
|
|
||||||
ProtocolLibLoginSource(Player player, Random random, PublicKey serverPublicKey, ClientPublicKey clientKey) {
|
ProtocolLibLoginSource(Player player, Random random, PublicKey serverPublicKey, ClientPublicKey clientKey) {
|
||||||
@ -72,7 +71,7 @@ class ProtocolLibLoginSource implements LoginSource {
|
|||||||
*/
|
*/
|
||||||
PacketContainer newPacket = new PacketContainer(ENCRYPTION_BEGIN);
|
PacketContainer newPacket = new PacketContainer(ENCRYPTION_BEGIN);
|
||||||
|
|
||||||
newPacket.getStrings().write(0, serverId);
|
newPacket.getStrings().write(0, "");
|
||||||
StructureModifier<PublicKey> keyModifier = newPacket.getSpecificModifier(PublicKey.class);
|
StructureModifier<PublicKey> keyModifier = newPacket.getSpecificModifier(PublicKey.class);
|
||||||
int verifyField = 0;
|
int verifyField = 0;
|
||||||
if (keyModifier.getFields().isEmpty()) {
|
if (keyModifier.getFields().isEmpty()) {
|
||||||
@ -84,6 +83,8 @@ class ProtocolLibLoginSource implements LoginSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newPacket.getByteArrays().write(verifyField, verifyToken);
|
newPacket.getByteArrays().write(verifyField, verifyToken);
|
||||||
|
// shouldAuthenticate, but why does this field even exist?
|
||||||
|
newPacket.getBooleans().writeSafely(0, true);
|
||||||
|
|
||||||
//serverId is an empty string
|
//serverId is an empty string
|
||||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket);
|
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket);
|
||||||
@ -115,10 +116,6 @@ class ProtocolLibLoginSource implements LoginSource {
|
|||||||
return clientKey;
|
return clientKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServerId() {
|
|
||||||
return serverId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getVerifyToken() {
|
public byte[] getVerifyToken() {
|
||||||
return verifyToken.clone();
|
return verifyToken.clone();
|
||||||
}
|
}
|
||||||
@ -128,7 +125,6 @@ class ProtocolLibLoginSource implements LoginSource {
|
|||||||
return this.getClass().getSimpleName() + '{'
|
return this.getClass().getSimpleName() + '{'
|
||||||
+ "player=" + player
|
+ "player=" + player
|
||||||
+ ", random=" + random
|
+ ", random=" + random
|
||||||
+ ", serverId='" + serverId + '\''
|
|
||||||
+ ", verifyToken=" + Arrays.toString(verifyToken)
|
+ ", verifyToken=" + Arrays.toString(verifyToken)
|
||||||
+ '}';
|
+ '}';
|
||||||
}
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||||
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
|
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
@ -47,8 +47,8 @@ import com.github.games647.craftapi.model.skin.SkinProperty;
|
|||||||
import com.github.games647.craftapi.resolver.MojangResolver;
|
import com.github.games647.craftapi.resolver.MojangResolver;
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.bukkit.InetUtils;
|
import com.github.games647.fastlogin.bukkit.auth.InetUtils;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@ -72,7 +72,6 @@ import static com.comphenix.protocol.PacketType.Login.Server.DISCONNECT;
|
|||||||
public class VerifyResponseTask implements Runnable {
|
public class VerifyResponseTask implements Runnable {
|
||||||
|
|
||||||
private static final String ENCRYPTION_CLASS_NAME = "MinecraftEncryption";
|
private static final String ENCRYPTION_CLASS_NAME = "MinecraftEncryption";
|
||||||
private static final Class<?> ENCRYPTION_CLASS;
|
|
||||||
private static final String ADDRESS_VERIFY_WARNING = "This indicates the use of reverse-proxy like HAProxy, "
|
private static final String ADDRESS_VERIFY_WARNING = "This indicates the use of reverse-proxy like HAProxy, "
|
||||||
+ "TCPShield, BungeeCord, Velocity, etc. "
|
+ "TCPShield, BungeeCord, Velocity, etc. "
|
||||||
+ "By default (configurable in the config) this plugin requests Mojang to verify the connecting IP "
|
+ "By default (configurable in the config) this plugin requests Mojang to verify the connecting IP "
|
||||||
@ -81,12 +80,6 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
+ "(keyword IP forwarding). This process will also be useful for other server "
|
+ "(keyword IP forwarding). This process will also be useful for other server "
|
||||||
+ "features like IP banning, so that it doesn't ban the proxy IP.";
|
+ "features like IP banning, so that it doesn't ban the proxy IP.";
|
||||||
|
|
||||||
static {
|
|
||||||
ENCRYPTION_CLASS = MinecraftReflection.getMinecraftClass(
|
|
||||||
"util." + ENCRYPTION_CLASS_NAME, ENCRYPTION_CLASS_NAME
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
private final FastLoginBukkit plugin;
|
||||||
private final PacketEvent packetEvent;
|
private final PacketEvent packetEvent;
|
||||||
private final KeyPair serverKey;
|
private final KeyPair serverKey;
|
||||||
@ -98,6 +91,8 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
private final byte[] sharedSecret;
|
private final byte[] sharedSecret;
|
||||||
|
|
||||||
private static Method encryptMethod;
|
private static Method encryptMethod;
|
||||||
|
private static Method encryptKeyMethod;
|
||||||
|
|
||||||
private static Method cipherMethod;
|
private static Method cipherMethod;
|
||||||
|
|
||||||
public VerifyResponseTask(FastLoginBukkit plugin, PacketEvent packetEvent,
|
public VerifyResponseTask(FastLoginBukkit plugin, PacketEvent packetEvent,
|
||||||
@ -159,11 +154,11 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
//user tried to fake an authentication
|
//user tried to fake an authentication
|
||||||
disconnect(
|
disconnect(
|
||||||
"invalid-session",
|
"invalid-session",
|
||||||
"Session server rejected incoming connection for GameProfile {} ({}). Possible reasons are"
|
"Session server rejected incoming connection for GameProfile {} ({}). Possible reasons are "
|
||||||
+ "1) Client IP address contacting Mojang and server during server join were different "
|
+ "1) Client IP address contacting Mojang and server during server join were different "
|
||||||
+ "(Do you use a reverse proxy? -> Enable IP forwarding, "
|
+ "(Do you use a reverse proxy? -> Enable IP forwarding, "
|
||||||
+ "or disable the feature in the config). "
|
+ "or disable the feature in the config). "
|
||||||
+ "2) Player is offline, but tried to bypass the authentication"
|
+ "2) Player is offline, but tried to bypass the authentication "
|
||||||
+ "3) Client uses an outdated username for connecting (Fix: Restart client)",
|
+ "3) Client uses an outdated username for connecting (Fix: Restart client)",
|
||||||
requestedUsername, address
|
requestedUsername, address
|
||||||
);
|
);
|
||||||
@ -173,12 +168,12 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
"The incoming request for player {} uses a local IP address",
|
"The incoming request for player {} uses a local IP address",
|
||||||
requestedUsername
|
requestedUsername
|
||||||
);
|
);
|
||||||
plugin.getLog().warn(ADDRESS_VERIFY_WARNING);
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getLog().warn("If you think this is an error, please verify that the incoming "
|
plugin.getLog().warn("If you think this is an error, please verify that the incoming "
|
||||||
+ "IP address {} is not associated with a server hosting company.", address);
|
+ "IP address {} is not associated with a server hosting company.", address);
|
||||||
plugin.getLog().warn(ADDRESS_VERIFY_WARNING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugin.getLog().warn(ADDRESS_VERIFY_WARNING);
|
||||||
}
|
}
|
||||||
} catch (IOException ioEx) {
|
} catch (IOException ioEx) {
|
||||||
disconnect("error-kick", "Failed to connect to session server", ioEx);
|
disconnect("error-kick", "Failed to connect to session server", ioEx);
|
||||||
@ -200,7 +195,7 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
|
|
||||||
session.setVerifiedUsername(realUsername);
|
session.setVerifiedUsername(realUsername);
|
||||||
session.setUuid(verification.getId());
|
session.setUuid(verification.getId());
|
||||||
session.setVerified(true);
|
session.setVerifiedPremium(true);
|
||||||
|
|
||||||
setPremiumUUID(session.getUuid());
|
setPremiumUUID(session.getUuid());
|
||||||
receiveFakeStartPacket(realUsername, session.getClientPublicKey(), session.getUuid());
|
receiveFakeStartPacket(realUsername, session.getClientPublicKey(), session.getUuid());
|
||||||
@ -237,20 +232,23 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
private boolean enableEncryption(SecretKey loginKey) throws IllegalArgumentException {
|
private boolean enableEncryption(SecretKey loginKey) throws IllegalArgumentException {
|
||||||
plugin.getLog().info("Enabling onlinemode encryption for {}", player.getAddress());
|
plugin.getLog().info("Enabling onlinemode encryption for {}", player.getAddress());
|
||||||
// Initialize method reflections
|
// Initialize method reflections
|
||||||
if (encryptMethod == null) {
|
if (encryptKeyMethod == null || encryptMethod == null) {
|
||||||
Class<?> networkManagerClass = MinecraftReflection.getNetworkManagerClass();
|
Class<?> networkManagerClass = MinecraftReflection.getNetworkManagerClass();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Try to get the old (pre MC 1.16.4) encryption method
|
// Try to get the old (pre MC 1.16.4) encryption method
|
||||||
encryptMethod = FuzzyReflection.fromClass(networkManagerClass)
|
encryptKeyMethod = FuzzyReflection.fromClass(networkManagerClass)
|
||||||
.getMethodByParameters("a", SecretKey.class);
|
.getMethodByParameters("a", SecretKey.class);
|
||||||
} catch (IllegalArgumentException exception) {
|
} catch (IllegalArgumentException exception) {
|
||||||
// Get the new encryption method
|
// Get the new encryption method
|
||||||
encryptMethod = FuzzyReflection.fromClass(networkManagerClass)
|
encryptMethod = FuzzyReflection.fromClass(networkManagerClass)
|
||||||
.getMethodByParameters("a", Cipher.class, Cipher.class);
|
.getMethodByParameters("a", Cipher.class, Cipher.class);
|
||||||
|
|
||||||
|
Class<?> encryptionClass = MinecraftReflection.getMinecraftClass(
|
||||||
|
"util." + ENCRYPTION_CLASS_NAME, ENCRYPTION_CLASS_NAME
|
||||||
|
);
|
||||||
|
|
||||||
// Get the needed Cipher helper method (used to generate ciphers from login key)
|
// Get the needed Cipher helper method (used to generate ciphers from login key)
|
||||||
cipherMethod = FuzzyReflection.fromClass(ENCRYPTION_CLASS)
|
cipherMethod = FuzzyReflection.fromClass(encryptionClass)
|
||||||
.getMethodByParameters("a", int.class, Key.class);
|
.getMethodByParameters("a", int.class, Key.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -259,9 +257,9 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
Object networkManager = this.getNetworkManager();
|
Object networkManager = this.getNetworkManager();
|
||||||
|
|
||||||
// If cipherMethod is null - use old encryption (pre MC 1.16.4), otherwise use the new cipher one
|
// If cipherMethod is null - use old encryption (pre MC 1.16.4), otherwise use the new cipher one
|
||||||
if (cipherMethod == null) {
|
if (encryptKeyMethod != null) {
|
||||||
// Encrypt/decrypt packet flow, this behaviour is expected by the client
|
// Encrypt/decrypt packet flow, this behaviour is expected by the client
|
||||||
encryptMethod.invoke(networkManager, loginKey);
|
encryptKeyMethod.invoke(networkManager, loginKey);
|
||||||
} else {
|
} else {
|
||||||
// Create ciphers from login key
|
// Create ciphers from login key
|
||||||
Object decryptionCipher = cipherMethod.invoke(null, Cipher.DECRYPT_MODE, loginKey);
|
Object decryptionCipher = cipherMethod.invoke(null, Cipher.DECRYPT_MODE, loginKey);
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib.packet;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib.packet;
|
||||||
|
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,9 +23,10 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit.auth.proxy;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.listener.BungeeListener;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.AuthenticationBackend;
|
||||||
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
||||||
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
||||||
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
||||||
@ -33,105 +34,65 @@ import com.google.common.io.ByteArrayDataOutput;
|
|||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.plugin.messaging.PluginMessageRecipient;
|
import org.bukkit.plugin.messaging.PluginMessageRecipient;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static com.github.games647.fastlogin.core.message.ChangePremiumMessage.CHANGE_CHANNEL;
|
import static com.github.games647.fastlogin.core.message.ChangePremiumMessage.CHANGE_CHANNEL;
|
||||||
import static com.github.games647.fastlogin.core.message.SuccessMessage.SUCCESS_CHANNEL;
|
import static com.github.games647.fastlogin.core.message.SuccessMessage.SUCCESS_CHANNEL;
|
||||||
import static java.util.stream.Collectors.toSet;
|
|
||||||
|
|
||||||
public class BungeeManager {
|
public class ProxyAuthentication implements AuthenticationBackend {
|
||||||
|
|
||||||
private static final String LEGACY_FILE_NAME = "proxy-whitelist.txt";
|
|
||||||
private static final String FILE_NAME = "allowed-proxies.txt";
|
|
||||||
|
|
||||||
//null if proxies allowed list is empty so bungeecord support is disabled
|
|
||||||
private Set<UUID> proxyIds;
|
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
private final FastLoginBukkit plugin;
|
||||||
private boolean enabled;
|
private ProxyVerifier verifier;
|
||||||
|
|
||||||
private final Collection<UUID> firedJoinEvents = new HashSet<>();
|
public ProxyAuthentication(FastLoginBukkit plugin) {
|
||||||
|
|
||||||
public BungeeManager(FastLoginBukkit plugin) {
|
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanup() {
|
|
||||||
//remove old blocked status
|
@Override
|
||||||
Bukkit.getOnlinePlayers().forEach(player -> player.removeMetadata(plugin.getName(), plugin));
|
public boolean isAvailable() {
|
||||||
|
return detectProxy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPluginMessage(PluginMessageRecipient player, ChannelMessage message) {
|
@Override
|
||||||
if (player != null) {
|
public void init(PluginManager pluginManager) {
|
||||||
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
|
verifier = new ProxyVerifier(plugin);
|
||||||
message.writeTo(dataOutput);
|
verifier.loadSecrets();
|
||||||
|
|
||||||
NamespaceKey channel = new NamespaceKey(plugin.getName(), message.getChannelName());
|
registerPluginChannels();
|
||||||
player.sendPluginMessage(plugin, channel.getCombinedName(), dataOutput.toByteArray());
|
|
||||||
|
pluginManager.registerEvents(new ProxyConnectionListener(plugin, verifier), plugin);
|
||||||
|
|
||||||
|
plugin.getLog().info("Found enabled proxy configuration");
|
||||||
|
plugin.getLog().info("Remember to follow the proxy guide to complete your setup");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerPluginChannels() {
|
||||||
|
Server server = Bukkit.getServer();
|
||||||
|
|
||||||
|
// check for incoming messages from the bungeecord version of this plugin
|
||||||
|
String groupId = plugin.getName();
|
||||||
|
String forceChannel = NamespaceKey.getCombined(groupId, LoginActionMessage.FORCE_CHANNEL);
|
||||||
|
server.getMessenger().registerIncomingPluginChannel(plugin, forceChannel, new ProxyListener(plugin, verifier));
|
||||||
|
|
||||||
|
// outgoing
|
||||||
|
String successChannel = new NamespaceKey(groupId, SUCCESS_CHANNEL).getCombinedName();
|
||||||
|
String changeChannel = new NamespaceKey(groupId, CHANGE_CHANNEL).getCombinedName();
|
||||||
|
server.getMessenger().registerOutgoingPluginChannel(plugin, successChannel);
|
||||||
|
server.getMessenger().registerOutgoingPluginChannel(plugin, changeChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
if (verifier != null) {
|
||||||
|
verifier.cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initialize() {
|
|
||||||
enabled = detectProxy();
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
proxyIds = loadBungeeCordIds();
|
|
||||||
if (proxyIds.isEmpty()) {
|
|
||||||
plugin.getLog().info("No valid IDs found. Minecraft proxy support cannot work in the current state");
|
|
||||||
}
|
|
||||||
|
|
||||||
registerPluginChannels();
|
|
||||||
plugin.getLog().info("Found enabled proxy configuration");
|
|
||||||
plugin.getLog().info("Remember to follow the proxy guide to complete your setup");
|
|
||||||
} else {
|
|
||||||
plugin.getLog().warn("Disabling Minecraft proxy configuration. Assuming direct connections from now on.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isProxySupported(String className, String fieldName)
|
|
||||||
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
|
||||||
return Class.forName(className).getDeclaredField(fieldName).getBoolean(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isVelocityEnabled()
|
|
||||||
throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, ClassNotFoundException,
|
|
||||||
NoSuchMethodException, InvocationTargetException {
|
|
||||||
try {
|
|
||||||
Class<?> globalConfig = Class.forName("io.papermc.paper.configuration.GlobalConfiguration");
|
|
||||||
Object global = globalConfig.getDeclaredMethod("get").invoke(null);
|
|
||||||
Object proxiesConfiguration = global.getClass().getDeclaredField("proxies").get(global);
|
|
||||||
|
|
||||||
Field velocitySectionField = proxiesConfiguration.getClass().getDeclaredField("velocity");
|
|
||||||
Object velocityConfig = velocitySectionField.get(proxiesConfiguration);
|
|
||||||
|
|
||||||
return velocityConfig.getClass().getDeclaredField("enabled").getBoolean(velocityConfig);
|
|
||||||
} catch (ClassNotFoundException classNotFoundException) {
|
|
||||||
// try again using the older Paper configuration, because the old class file still exists in newer versions
|
|
||||||
if (isProxySupported("com.destroystokyo.paper.PaperConfig", "velocitySupport")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean detectProxy() {
|
private boolean detectProxy() {
|
||||||
try {
|
try {
|
||||||
if (isProxySupported("org.spigotmc.SpigotConfig", "bungee")) {
|
if (isProxySupported("org.spigotmc.SpigotConfig", "bungee")) {
|
||||||
@ -155,82 +116,40 @@ public class BungeeManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerPluginChannels() {
|
private boolean isProxySupported(String className, String fieldName)
|
||||||
Server server = Bukkit.getServer();
|
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||||
|
return Class.forName(className).getDeclaredField(fieldName).getBoolean(null);
|
||||||
// check for incoming messages from the bungeecord version of this plugin
|
|
||||||
String groupId = plugin.getName();
|
|
||||||
String forceChannel = NamespaceKey.getCombined(groupId, LoginActionMessage.FORCE_CHANNEL);
|
|
||||||
server.getMessenger().registerIncomingPluginChannel(plugin, forceChannel, new BungeeListener(plugin));
|
|
||||||
|
|
||||||
// outgoing
|
|
||||||
String successChannel = new NamespaceKey(groupId, SUCCESS_CHANNEL).getCombinedName();
|
|
||||||
String changeChannel = new NamespaceKey(groupId, CHANGE_CHANNEL).getCombinedName();
|
|
||||||
server.getMessenger().registerOutgoingPluginChannel(plugin, successChannel);
|
|
||||||
server.getMessenger().registerOutgoingPluginChannel(plugin, changeChannel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<UUID> loadBungeeCordIds() {
|
private boolean isVelocityEnabled()
|
||||||
Path proxiesFile = plugin.getPluginFolder().resolve(FILE_NAME);
|
throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, ClassNotFoundException,
|
||||||
Path legacyFile = plugin.getPluginFolder().resolve(LEGACY_FILE_NAME);
|
NoSuchMethodException, InvocationTargetException {
|
||||||
try {
|
try {
|
||||||
if (Files.notExists(proxiesFile)) {
|
Class<?> globalConfig = Class.forName("io.papermc.paper.configuration.GlobalConfiguration");
|
||||||
if (Files.exists(legacyFile)) {
|
Object global = globalConfig.getDeclaredMethod("get").invoke(null);
|
||||||
Files.move(legacyFile, proxiesFile);
|
Object proxiesConfiguration = global.getClass().getDeclaredField("proxies").get(global);
|
||||||
}
|
|
||||||
|
|
||||||
if (Files.notExists(legacyFile)) {
|
Field velocitySectionField = proxiesConfiguration.getClass().getDeclaredField("velocity");
|
||||||
Files.createFile(proxiesFile);
|
Object velocityConfig = velocitySectionField.get(proxiesConfiguration);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Files.deleteIfExists(legacyFile);
|
return velocityConfig.getClass().getDeclaredField("enabled").getBoolean(velocityConfig);
|
||||||
try (Stream<String> lines = Files.lines(proxiesFile)) {
|
} catch (ClassNotFoundException classNotFoundException) {
|
||||||
return lines.map(String::trim).map(UUID::fromString).collect(toSet());
|
// try again using the older Paper configuration, because the old class file still exists in newer versions
|
||||||
|
if (isProxySupported("com.destroystokyo.paper.PaperConfig", "velocitySupport")) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
|
||||||
plugin.getLog().error("Failed to read proxies", ex);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
plugin.getLog().error("Failed to retrieve proxy Id. Disabling BungeeCord support", ex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Collections.emptySet();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isProxyAllowed(UUID proxyId) {
|
public void sendPluginMessage(PluginMessageRecipient player, ChannelMessage message) {
|
||||||
return proxyIds != null && proxyIds.contains(proxyId);
|
if (player != null) {
|
||||||
}
|
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
|
||||||
|
message.writeTo(dataOutput);
|
||||||
|
|
||||||
/**
|
NamespaceKey channel = new NamespaceKey(plugin.getName(), message.getChannelName());
|
||||||
* Mark the event to be fired including the task delay.
|
player.sendPluginMessage(plugin, channel.getCombinedName(), dataOutput.toByteArray());
|
||||||
*
|
}
|
||||||
* @param player joining player
|
|
||||||
*/
|
|
||||||
public synchronized void markJoinEventFired(Player player) {
|
|
||||||
firedJoinEvents.add(player.getUniqueId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the event fired including with the task delay. This necessary to restore the order of processing the
|
|
||||||
* BungeeCord messages after the PlayerJoinEvent fires including the delay.
|
|
||||||
* <p>
|
|
||||||
* If the join event fired, the delay exceeded, but it ran earlier and couldn't find the recently started login
|
|
||||||
* session. If not fired, we can start a new force login task. This will still match the requirement that we wait
|
|
||||||
* a certain time after the player join event fired.
|
|
||||||
*
|
|
||||||
* @param player joining player
|
|
||||||
* @return event fired including delay
|
|
||||||
*/
|
|
||||||
public synchronized boolean didJoinEventFired(Player player) {
|
|
||||||
return firedJoinEvents.contains(player.getUniqueId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Player quit clean up
|
|
||||||
*
|
|
||||||
* @param player joining player
|
|
||||||
*/
|
|
||||||
public synchronized void cleanup(Player player) {
|
|
||||||
firedJoinEvents.remove(player.getUniqueId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.github.games647.fastlogin.bukkit.auth.proxy;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.FloodgateAuthTask;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.ForceLoginTask;
|
||||||
|
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerLoginEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.metadata.Metadatable;
|
||||||
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
|
||||||
|
public class ProxyConnectionListener implements Listener {
|
||||||
|
|
||||||
|
private static final long DELAY_LOGIN = 20L / 2;
|
||||||
|
|
||||||
|
private final FastLoginBukkit plugin;
|
||||||
|
private final ProxyVerifier verifier;
|
||||||
|
|
||||||
|
public ProxyConnectionListener(FastLoginBukkit plugin, ProxyVerifier verifier) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.verifier = verifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeBlockedStatus(Metadatable player) {
|
||||||
|
player.removeMetadata(plugin.getName(), plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
|
||||||
|
removeBlockedStatus(loginEvent.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
|
||||||
|
Player player = joinEvent.getPlayer();
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||||
|
delayForceLogin(player);
|
||||||
|
// delay the login process to let auth plugins initialize the player
|
||||||
|
// Magic number however as there is no direct event from those plugins
|
||||||
|
}, DELAY_LOGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void delayForceLogin(Player player) {
|
||||||
|
// session exists so the player is ready for force login
|
||||||
|
// cases: Paper (firing BungeeCord message before PlayerJoinEvent) or not running BungeeCord and already
|
||||||
|
// having the login session from the login process
|
||||||
|
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
|
||||||
|
|
||||||
|
if (session == null) {
|
||||||
|
// Floodgate players usually don't have a session at this point
|
||||||
|
// exception: if force login by bungee message had been delayed
|
||||||
|
FloodgateService floodgateService = plugin.getFloodgateService();
|
||||||
|
if (floodgateService != null) {
|
||||||
|
FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(player.getUniqueId());
|
||||||
|
if (floodgatePlayer != null) {
|
||||||
|
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer);
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String sessionId = plugin.getSessionId(player.spigot().getRawAddress());
|
||||||
|
plugin.getLog().info("No on-going login session for player: {} with ID {}. ", player, sessionId);
|
||||||
|
plugin.getLog().info("Setups using Minecraft proxies will start delayed "
|
||||||
|
+ "when the command from the proxy is received");
|
||||||
|
} else {
|
||||||
|
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
verifier.markJoinEventFired(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
|
||||||
|
Player player = quitEvent.getPlayer();
|
||||||
|
|
||||||
|
removeBlockedStatus(player);
|
||||||
|
verifier.cleanup(player);
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,11 +23,11 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener;
|
package com.github.games647.fastlogin.bukkit.auth.proxy;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
|
import com.github.games647.fastlogin.bukkit.auth.ForceLoginTask;
|
||||||
import com.github.games647.fastlogin.core.PremiumStatus;
|
import com.github.games647.fastlogin.core.PremiumStatus;
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
||||||
@ -47,12 +47,14 @@ import java.util.UUID;
|
|||||||
* This class also receives the plugin message from the bungeecord version of this plugin in order to get notified if
|
* This class also receives the plugin message from the bungeecord version of this plugin in order to get notified if
|
||||||
* the connection is in online mode.
|
* the connection is in online mode.
|
||||||
*/
|
*/
|
||||||
public class BungeeListener implements PluginMessageListener {
|
public class ProxyListener implements PluginMessageListener {
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
private final FastLoginBukkit plugin;
|
||||||
|
private final ProxyVerifier verifier;
|
||||||
|
|
||||||
public BungeeListener(FastLoginBukkit plugin) {
|
public ProxyListener(FastLoginBukkit plugin, ProxyVerifier verifier) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
this.verifier = verifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -79,7 +81,7 @@ public class BungeeListener implements PluginMessageListener {
|
|||||||
plugin.getLog().warn("Received message {} from a blocked player {}", loginMessage, targetPlayer);
|
plugin.getLog().warn("Received message {} from a blocked player {}", loginMessage, targetPlayer);
|
||||||
} else {
|
} else {
|
||||||
UUID sourceId = loginMessage.getProxyId();
|
UUID sourceId = loginMessage.getProxyId();
|
||||||
if (plugin.getBungeeManager().isProxyAllowed(sourceId)) {
|
if (verifier.isProxyAllowed(sourceId)) {
|
||||||
readMessage(targetPlayer, loginMessage);
|
readMessage(targetPlayer, loginMessage);
|
||||||
} else {
|
} else {
|
||||||
plugin.getLog().warn("Received proxy id: {} that doesn't exist in the proxy file", sourceId);
|
plugin.getLog().warn("Received proxy id: {} that doesn't exist in the proxy file", sourceId);
|
||||||
@ -123,11 +125,11 @@ public class BungeeListener implements PluginMessageListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startLoginTaskIfReady(Player player, BukkitLoginSession session) {
|
private void startLoginTaskIfReady(Player player, BukkitLoginSession session) {
|
||||||
session.setVerified(true);
|
session.setVerifiedPremium(true);
|
||||||
plugin.putSession(player.spigot().getRawAddress(), session);
|
plugin.putSession(player.spigot().getRawAddress(), session);
|
||||||
|
|
||||||
// only start a new login task if the join event fired earlier. This event then didn't
|
// only start a new login task if the join event fired earlier. This event then didn't
|
||||||
boolean result = plugin.getBungeeManager().didJoinEventFired(player);
|
boolean result = verifier.didJoinEventFired(player);
|
||||||
plugin.getLog().info("Delaying force login until join event fired?: {}", result);
|
plugin.getLog().info("Delaying force login until join event fired?: {}", result);
|
||||||
if (result) {
|
if (result) {
|
||||||
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.github.games647.fastlogin.bukkit.auth.proxy;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.toSet;
|
||||||
|
|
||||||
|
public class ProxyVerifier {
|
||||||
|
|
||||||
|
private static final String LEGACY_FILE_NAME = "proxy-whitelist.txt";
|
||||||
|
private static final String FILE_NAME = "allowed-proxies.txt";
|
||||||
|
|
||||||
|
//null if proxies allowed list is empty so bungeecord support is disabled
|
||||||
|
private Set<UUID> proxyIds;
|
||||||
|
|
||||||
|
private final FastLoginBukkit plugin;
|
||||||
|
|
||||||
|
private final Collection<UUID> firedJoinEvents = new HashSet<>();
|
||||||
|
|
||||||
|
public ProxyVerifier(FastLoginBukkit plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanup() {
|
||||||
|
//remove old blocked status
|
||||||
|
Bukkit.getOnlinePlayers().forEach(player -> player.removeMetadata(plugin.getName(), plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadSecrets() {
|
||||||
|
proxyIds = loadBungeeCordIds();
|
||||||
|
if (proxyIds.isEmpty()) {
|
||||||
|
plugin.getLog().info("No valid IDs found. Minecraft proxy support cannot work in the current state");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<UUID> loadBungeeCordIds() {
|
||||||
|
Path proxiesFile = plugin.getPluginFolder().resolve(FILE_NAME);
|
||||||
|
Path legacyFile = plugin.getPluginFolder().resolve(LEGACY_FILE_NAME);
|
||||||
|
try {
|
||||||
|
if (Files.notExists(proxiesFile)) {
|
||||||
|
if (Files.exists(legacyFile)) {
|
||||||
|
Files.move(legacyFile, proxiesFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Files.notExists(legacyFile)) {
|
||||||
|
Files.createFile(proxiesFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Files.deleteIfExists(legacyFile);
|
||||||
|
try (Stream<String> lines = Files.lines(proxiesFile)) {
|
||||||
|
return lines.map(String::trim).map(UUID::fromString).collect(toSet());
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
plugin.getLog().error("Failed to read proxies", ex);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
plugin.getLog().error("Failed to retrieve proxy Id. Disabling BungeeCord support", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isProxyAllowed(UUID proxyId) {
|
||||||
|
return proxyIds != null && proxyIds.contains(proxyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the event to be fired including the task delay.
|
||||||
|
*
|
||||||
|
* @param player joining player
|
||||||
|
*/
|
||||||
|
public synchronized void markJoinEventFired(Player player) {
|
||||||
|
firedJoinEvents.add(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the event fired including with the task delay. This necessary to restore the order of processing the
|
||||||
|
* BungeeCord messages after the PlayerJoinEvent fires including the delay.
|
||||||
|
* <p>
|
||||||
|
* If the join event fired, the delay exceeded, but it ran earlier and couldn't find the recently started login
|
||||||
|
* session. If not fired, we can start a new force login task. This will still match the requirement that we wait
|
||||||
|
* a certain time after the player join event fired.
|
||||||
|
*
|
||||||
|
* @param player joining player
|
||||||
|
* @return event fired including delay
|
||||||
|
*/
|
||||||
|
public synchronized boolean didJoinEventFired(Player player) {
|
||||||
|
return firedJoinEvents.contains(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player quit clean up
|
||||||
|
*
|
||||||
|
* @param player joining player
|
||||||
|
*/
|
||||||
|
public synchronized void cleanup(Player player) {
|
||||||
|
firedJoinEvents.remove(player.getUniqueId());
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -63,10 +63,10 @@ public class CrackedCommand extends ToggleCommand {
|
|||||||
|
|
||||||
// todo: load async if
|
// todo: load async if
|
||||||
StoredProfile profile = plugin.getCore().getStorage().loadProfile(sender.getName());
|
StoredProfile profile = plugin.getCore().getStorage().loadProfile(sender.getName());
|
||||||
if (profile.isPremium()) {
|
if (profile.isOnlinemodePreferred()) {
|
||||||
plugin.getCore().sendLocaleMessage("remove-premium", sender);
|
plugin.getCore().sendLocaleMessage("remove-premium", sender);
|
||||||
|
|
||||||
profile.setPremium(false);
|
profile.setOnlinemodePreferred(false);
|
||||||
profile.setId(null);
|
profile.setId(null);
|
||||||
plugin.getScheduler().runAsync(() -> {
|
plugin.getScheduler().runAsync(() -> {
|
||||||
plugin.getCore().getStorage().save(profile);
|
plugin.getCore().getStorage().save(profile);
|
||||||
@ -95,12 +95,12 @@ public class CrackedCommand extends ToggleCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//existing player is already cracked
|
//existing player is already cracked
|
||||||
if (profile.isSaved() && !profile.isPremium()) {
|
if (profile.isExistingPlayer() && !profile.isOnlinemodePreferred()) {
|
||||||
plugin.getCore().sendLocaleMessage("not-premium-other", sender);
|
plugin.getCore().sendLocaleMessage("not-premium-other", sender);
|
||||||
} else {
|
} else {
|
||||||
plugin.getCore().sendLocaleMessage("remove-premium", sender);
|
plugin.getCore().sendLocaleMessage("remove-premium", sender);
|
||||||
|
|
||||||
profile.setPremium(false);
|
profile.setOnlinemodePreferred(false);
|
||||||
plugin.getScheduler().runAsync(() -> {
|
plugin.getScheduler().runAsync(() -> {
|
||||||
plugin.getCore().getStorage().save(profile);
|
plugin.getCore().getStorage().save(profile);
|
||||||
plugin.getServer().getPluginManager().callEvent(
|
plugin.getServer().getPluginManager().callEvent(
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -64,25 +64,25 @@ public class PremiumCommand extends ToggleCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UUID id = ((Player) sender).getUniqueId();
|
||||||
|
if (plugin.getConfig().getBoolean("premium-warning") && !plugin.getPendingConfirms().contains(id)) {
|
||||||
|
sender.sendMessage(plugin.getCore().getMessage("premium-warning"));
|
||||||
|
plugin.getPendingConfirms().add(id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (forwardPremiumCommand(sender, sender.getName())) {
|
if (forwardPremiumCommand(sender, sender.getName())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID id = ((Player) sender).getUniqueId();
|
plugin.getPendingConfirms().remove(id);
|
||||||
if (plugin.getConfig().getBoolean("premium-warning") && !plugin.getCore().getPendingConfirms().contains(id)) {
|
|
||||||
sender.sendMessage(plugin.getCore().getMessage("premium-warning"));
|
|
||||||
plugin.getCore().getPendingConfirms().add(id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.getCore().getPendingConfirms().remove(id);
|
|
||||||
//todo: load async
|
//todo: load async
|
||||||
StoredProfile profile = plugin.getCore().getStorage().loadProfile(sender.getName());
|
StoredProfile profile = plugin.getCore().getStorage().loadProfile(sender.getName());
|
||||||
if (profile.isPremium()) {
|
if (profile.isOnlinemodePreferred()) {
|
||||||
plugin.getCore().sendLocaleMessage("already-exists", sender);
|
plugin.getCore().sendLocaleMessage("already-exists", sender);
|
||||||
} else {
|
} else {
|
||||||
//todo: resolve uuid
|
//todo: resolve uuid
|
||||||
profile.setPremium(true);
|
profile.setOnlinemodePreferred(true);
|
||||||
plugin.getScheduler().runAsync(() -> {
|
plugin.getScheduler().runAsync(() -> {
|
||||||
plugin.getCore().getStorage().save(profile);
|
plugin.getCore().getStorage().save(profile);
|
||||||
plugin.getServer().getPluginManager().callEvent(
|
plugin.getServer().getPluginManager().callEvent(
|
||||||
@ -109,11 +109,11 @@ public class PremiumCommand extends ToggleCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profile.isPremium()) {
|
if (profile.isOnlinemodePreferred()) {
|
||||||
plugin.getCore().sendLocaleMessage("already-exists-other", sender);
|
plugin.getCore().sendLocaleMessage("already-exists-other", sender);
|
||||||
} else {
|
} else {
|
||||||
//todo: resolve uuid
|
//todo: resolve uuid
|
||||||
profile.setPremium(true);
|
profile.setOnlinemodePreferred(true);
|
||||||
plugin.getScheduler().runAsync(() -> {
|
plugin.getScheduler().runAsync(() -> {
|
||||||
plugin.getCore().getStorage().save(profile);
|
plugin.getCore().getStorage().save(profile);
|
||||||
plugin.getServer().getPluginManager().callEvent(
|
plugin.getServer().getPluginManager().callEvent(
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -26,6 +26,7 @@
|
|||||||
package com.github.games647.fastlogin.bukkit.command;
|
package com.github.games647.fastlogin.bukkit.command;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.proxy.ProxyAuthentication;
|
||||||
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
|
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
|
||||||
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -55,7 +56,7 @@ public abstract class ToggleCommand implements CommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean forwardBungeeCommand(CommandSender sender, String target, boolean activate) {
|
protected boolean forwardBungeeCommand(CommandSender sender, String target, boolean activate) {
|
||||||
if (plugin.getBungeeManager().isEnabled()) {
|
if (plugin.getBackend() instanceof ProxyAuthentication) {
|
||||||
sendBungeeActivateMessage(sender, target, activate);
|
sendBungeeActivateMessage(sender, target, activate);
|
||||||
plugin.getCore().sendLocaleMessage("wait-on-proxy", sender);
|
plugin.getCore().sendLocaleMessage("wait-on-proxy", sender);
|
||||||
return true;
|
return true;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -45,9 +45,9 @@ import java.lang.reflect.Field;
|
|||||||
* <p>
|
* <p>
|
||||||
* Project page:
|
* Project page:
|
||||||
* <p>
|
* <p>
|
||||||
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/authme-reloaded/">...</a>
|
* <a href="https://dev.bukkit.org/bukkit-plugins/authme-reloaded/">Bukkit</a>
|
||||||
* <p>
|
* <p>
|
||||||
* Spigot: <a href="https://www.spigotmc.org/resources/authme-reloaded.6269/">...</a>
|
* <a href="https://www.spigotmc.org/resources/authme-reloaded.6269/">Spigot</a>
|
||||||
*/
|
*/
|
||||||
public class AuthMeHook implements AuthPlugin<Player>, Listener {
|
public class AuthMeHook implements AuthPlugin<Player>, Listener {
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
|
|||||||
Player player = restoreSessionEvent.getPlayer();
|
Player player = restoreSessionEvent.getPlayer();
|
||||||
|
|
||||||
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
|
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
|
||||||
if (session != null && session.isVerified()) {
|
if (session != null && session.isVerifiedPremium()) {
|
||||||
restoreSessionEvent.setCancelled(true);
|
restoreSessionEvent.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -46,7 +46,7 @@ import java.util.concurrent.Future;
|
|||||||
* <p>
|
* <p>
|
||||||
* Project page:
|
* Project page:
|
||||||
* <p>
|
* <p>
|
||||||
* Bukkit: <a href="https://dev.bukkit.org/server-mods/crazylogin/">...</a>
|
* <a href="https://dev.bukkit.org/server-mods/crazylogin/">Bukkit</a>
|
||||||
*/
|
*/
|
||||||
public class CrazyLoginHook implements AuthPlugin<Player> {
|
public class CrazyLoginHook implements AuthPlugin<Player> {
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,15 +23,9 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.task;
|
package com.github.games647.fastlogin.bukkit.hook;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
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 com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -51,19 +45,7 @@ public class DelayedAuthHook implements Runnable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
boolean hookFound = isHookFound();
|
plugin.setInitialized(isHookFound());
|
||||||
if (plugin.getBungeeManager().isEnabled()) {
|
|
||||||
plugin.getLog().info("BungeeCord setting detected. No auth plugin is required");
|
|
||||||
} else if (!hookFound) {
|
|
||||||
plugin.getLog().warn("No auth plugin were found by this plugin "
|
|
||||||
+ "(other plugins could hook into this after the initialization of this plugin)"
|
|
||||||
+ "and BungeeCord is deactivated. "
|
|
||||||
+ "Either one or both of the checks have to pass in order to use this plugin");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hookFound) {
|
|
||||||
plugin.markInitialized();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isHookFound() {
|
private boolean isHookFound() {
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -39,9 +39,9 @@ import org.bukkit.entity.Player;
|
|||||||
* <p>
|
* <p>
|
||||||
* Project page:
|
* Project page:
|
||||||
* <p>
|
* <p>
|
||||||
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/loginsecurity/">...</a>
|
* <a href="https://dev.bukkit.org/bukkit-plugins/loginsecurity/">Bukkit</a>
|
||||||
* <p>
|
* <p>
|
||||||
* Spigot: <a href="https://www.spigotmc.org/resources/loginsecurity.19362/">...</a>
|
* <a href="https://www.spigotmc.org/resources/loginsecurity.19362/">Spigot</a>
|
||||||
*/
|
*/
|
||||||
public class LoginSecurityHook implements AuthPlugin<Player> {
|
public class LoginSecurityHook implements AuthPlugin<Player> {
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -38,9 +38,9 @@ import java.util.concurrent.Future;
|
|||||||
/**
|
/**
|
||||||
* Project page:
|
* Project page:
|
||||||
* <p>
|
* <p>
|
||||||
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/ultraauth-aa/">...</a>
|
* <a href="https://dev.bukkit.org/bukkit-plugins/ultraauth-aa/">Bukkit</a>
|
||||||
* <p>
|
* <p>
|
||||||
* Spigot: <a href="https://www.spigotmc.org/resources/ultraauth.17044/">...</a>
|
* <a href="https://www.spigotmc.org/resources/ultraauth.17044/">Spigot</a>
|
||||||
*/
|
*/
|
||||||
public class UltraAuthHook implements AuthPlugin<Player> {
|
public class UltraAuthHook implements AuthPlugin<Player> {
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -40,7 +40,7 @@ import java.util.concurrent.Future;
|
|||||||
* <p>
|
* <p>
|
||||||
* Project page:
|
* Project page:
|
||||||
* <p>
|
* <p>
|
||||||
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/xauth/">...</a>
|
* <a href="https://dev.bukkit.org/bukkit-plugins/xauth/">Bukkit</a>
|
||||||
*/
|
*/
|
||||||
public class XAuthHook implements AuthPlugin<Player> {
|
public class XAuthHook implements AuthPlugin<Player> {
|
||||||
|
|
||||||
|
@ -1,139 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocolsupport;
|
|
||||||
|
|
||||||
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.antibot.AntiBotService;
|
|
||||||
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
|
|
||||||
import com.github.games647.fastlogin.core.shared.JoinManagement;
|
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
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.PlayerProfileCompleteEvent;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class ProtocolSupportListener extends JoinManagement<Player, CommandSender, ProtocolLoginSource>
|
|
||||||
implements Listener {
|
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
|
||||||
private final AntiBotService antiBotService;
|
|
||||||
|
|
||||||
public ProtocolSupportListener(FastLoginBukkit plugin, AntiBotService antiBotService) {
|
|
||||||
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
|
|
||||||
|
|
||||||
this.plugin = plugin;
|
|
||||||
this.antiBotService = antiBotService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onLoginStart(PlayerLoginStartEvent loginStartEvent) {
|
|
||||||
if (loginStartEvent.isLoginDenied() || plugin.getCore().getAuthPluginHook() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String username = loginStartEvent.getConnection().getProfile().getName();
|
|
||||||
InetSocketAddress address = loginStartEvent.getConnection().getRawAddress();
|
|
||||||
plugin.getLog().info("Incoming login request for {} from {}", username, address);
|
|
||||||
|
|
||||||
Action action = antiBotService.onIncomingConnection(address, username);
|
|
||||||
switch (action) {
|
|
||||||
case Ignore:
|
|
||||||
// just ignore
|
|
||||||
return;
|
|
||||||
case Block:
|
|
||||||
String message = plugin.getCore().getMessage("kick-antibot");
|
|
||||||
loginStartEvent.denyLogin(message);
|
|
||||||
break;
|
|
||||||
case Continue:
|
|
||||||
default:
|
|
||||||
//remove old data every time on a new login in order to keep the session only for one person
|
|
||||||
plugin.removeSession(address);
|
|
||||||
|
|
||||||
ProtocolLoginSource source = new ProtocolLoginSource(loginStartEvent);
|
|
||||||
super.onLogin(username, source);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onConnectionClosed(ConnectionCloseEvent closeEvent) {
|
|
||||||
InetSocketAddress address = closeEvent.getConnection().getRawAddress();
|
|
||||||
plugin.removeSession(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPropertiesResolve(PlayerProfileCompleteEvent profileCompleteEvent) {
|
|
||||||
InetSocketAddress address = profileCompleteEvent.getConnection().getRawAddress();
|
|
||||||
|
|
||||||
BukkitLoginSession session = plugin.getSession(address);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
source.enableOnlinemode();
|
|
||||||
|
|
||||||
String ip = source.getAddress().getAddress().getHostAddress();
|
|
||||||
plugin.getCore().getPendingLogin().put(ip + username, new Object());
|
|
||||||
|
|
||||||
BukkitLoginSession playerSession = new BukkitLoginSession(username, registered, profile);
|
|
||||||
plugin.putSession(source.getAddress(), playerSession);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startCrackedSession(ProtocolLoginSource source, StoredProfile profile, String username) {
|
|
||||||
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
|
|
||||||
plugin.putSession(source.getAddress(), loginSession);
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,12 +25,11 @@ softdepend:
|
|||||||
- floodgate
|
- floodgate
|
||||||
# Auth plugins
|
# Auth plugins
|
||||||
- AuthMe
|
- AuthMe
|
||||||
|
- CrazyLogin
|
||||||
- LoginSecurity
|
- LoginSecurity
|
||||||
- SodionAuth
|
|
||||||
- xAuth
|
|
||||||
- LogIt
|
- LogIt
|
||||||
- UltraAuth
|
- UltraAuth
|
||||||
- CrazyLogin
|
- xAuth
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
${project.parent.name}:
|
${project.parent.name}:
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -41,8 +41,10 @@ class FastLoginBukkitTest {
|
|||||||
val msg = CommonUtil.translateColorCodes(message);
|
val msg = CommonUtil.translateColorCodes(message);
|
||||||
assertEquals(msg, "§x00002a00002b§lText");
|
assertEquals(msg, "§x00002a00002b§lText");
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
val components = TextComponent.fromLegacyText(msg);
|
val components = TextComponent.fromLegacyText(msg);
|
||||||
val expected = "{\"bold\":true,\"color\":\"#00a00b\",\"text\":\"Text\"}";
|
val expected = "{\"bold\":true,\"color\":\"#00a00b\",\"text\":\"Text\"}";
|
||||||
|
//noinspection deprecation
|
||||||
assertEquals(ComponentSerializer.toString(components), expected);
|
assertEquals(ComponentSerializer.toString(components), expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,10 +23,10 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.SignatureTestData.SignatureData;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.SignatureTestData.SignatureData;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.google.common.hash.Hashing;
|
import com.google.common.hash.Hashing;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -60,7 +60,7 @@ class EncryptionUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testVerifyToken() {
|
void testVerifyToken() {
|
||||||
val random = ThreadLocalRandom.current();
|
@SuppressWarnings("SharedThreadLocalRandom") val random = ThreadLocalRandom.current();
|
||||||
byte[] token = EncryptionUtil.generateVerifyToken(random);
|
byte[] token = EncryptionUtil.generateVerifyToken(random);
|
||||||
|
|
||||||
assertAll(
|
assertAll(
|
||||||
@ -88,7 +88,7 @@ class EncryptionUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testExpiredClientKey() throws Exception {
|
void testExpiredClientKey() throws Exception {
|
||||||
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
val clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
||||||
|
|
||||||
// Client expires at the exact second mentioned, so use it for verification
|
// Client expires at the exact second mentioned, so use it for verification
|
||||||
val expiredTimestamp = clientKey.expiry();
|
val expiredTimestamp = clientKey.expiry();
|
||||||
@ -105,7 +105,7 @@ class EncryptionUtilTest {
|
|||||||
"client_keys/invalid_wrong_signature.json"
|
"client_keys/invalid_wrong_signature.json"
|
||||||
})
|
})
|
||||||
void testInvalidClientKey(String clientKeySource) throws Exception {
|
void testInvalidClientKey(String clientKeySource) throws Exception {
|
||||||
val clientKey = ResourceLoader.loadClientKey(clientKeySource);
|
val clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey(clientKeySource);
|
||||||
Instant expireTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
Instant expireTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
||||||
|
|
||||||
assertFalse(EncryptionUtil.verifyClientKey(clientKey, expireTimestamp, null));
|
assertFalse(EncryptionUtil.verifyClientKey(clientKey, expireTimestamp, null));
|
||||||
@ -113,7 +113,7 @@ class EncryptionUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testValidClientKey() throws Exception {
|
void testValidClientKey() throws Exception {
|
||||||
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
val clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
||||||
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
||||||
|
|
||||||
assertTrue(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp, null));
|
assertTrue(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp, null));
|
||||||
@ -121,7 +121,7 @@ class EncryptionUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testValid191ClientKey() throws Exception {
|
void testValid191ClientKey() throws Exception {
|
||||||
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
|
val clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
|
||||||
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
||||||
|
|
||||||
val ownerPremiumId = UUID.fromString("0aaa2c13-922a-411b-b655-9b8c08404695");
|
val ownerPremiumId = UUID.fromString("0aaa2c13-922a-411b-b655-9b8c08404695");
|
||||||
@ -130,7 +130,7 @@ class EncryptionUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testIncorrect191ClientOwner() throws Exception {
|
void testIncorrect191ClientOwner() throws Exception {
|
||||||
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
|
val clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
|
||||||
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
||||||
|
|
||||||
val ownerPremiumId = UUID.fromString("61699b2e-d327-4a01-9f1e-0ea8c3f06bc6");
|
val ownerPremiumId = UUID.fromString("61699b2e-d327-4a01-9f1e-0ea8c3f06bc6");
|
||||||
@ -170,7 +170,7 @@ class EncryptionUtilTest {
|
|||||||
void testServerIdHash() throws Exception {
|
void testServerIdHash() throws Exception {
|
||||||
val serverId = "";
|
val serverId = "";
|
||||||
val sharedSecret = generateSharedKey();
|
val sharedSecret = generateSharedKey();
|
||||||
val serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
|
val serverPK = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
|
||||||
|
|
||||||
String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
|
String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
|
||||||
assertEquals(EncryptionUtil.getServerIdHashString(serverId, sharedSecret, serverPK), sessionHash);
|
assertEquals(EncryptionUtil.getServerIdHashString(serverId, sharedSecret, serverPK), sessionHash);
|
||||||
@ -200,7 +200,7 @@ class EncryptionUtilTest {
|
|||||||
void testServerIdHashWrongSecret() throws Exception {
|
void testServerIdHashWrongSecret() throws Exception {
|
||||||
val serverId = "";
|
val serverId = "";
|
||||||
val sharedSecret = generateSharedKey();
|
val sharedSecret = generateSharedKey();
|
||||||
val serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
|
val serverPK = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
|
||||||
|
|
||||||
String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
|
String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
|
||||||
assertNotEquals(EncryptionUtil.getServerIdHashString("", generateSharedKey(), serverPK), sessionHash);
|
assertNotEquals(EncryptionUtil.getServerIdHashString("", generateSharedKey(), serverPK), sessionHash);
|
||||||
@ -219,7 +219,7 @@ class EncryptionUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testValidSignedNonce() throws Exception {
|
void testValidSignedNonce() throws Exception {
|
||||||
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
ClientPublicKey clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
||||||
SignatureTestData testData = SignatureTestData.fromResource("signature/valid_signature.json");
|
SignatureTestData testData = SignatureTestData.fromResource("signature/valid_signature.json");
|
||||||
assertTrue(verifySignedNonce(testData, clientKey));
|
assertTrue(verifySignedNonce(testData, clientKey));
|
||||||
}
|
}
|
||||||
@ -231,7 +231,7 @@ class EncryptionUtilTest {
|
|||||||
"signature/incorrect_signature.json",
|
"signature/incorrect_signature.json",
|
||||||
})
|
})
|
||||||
void testIncorrectNonce(String signatureSource) throws Exception {
|
void testIncorrectNonce(String signatureSource) throws Exception {
|
||||||
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
ClientPublicKey clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
||||||
SignatureTestData testData = SignatureTestData.fromResource(signatureSource);
|
SignatureTestData testData = SignatureTestData.fromResource(signatureSource);
|
||||||
assertFalse(verifySignedNonce(testData, clientKey));
|
assertFalse(verifySignedNonce(testData, clientKey));
|
||||||
}
|
}
|
||||||
@ -239,7 +239,7 @@ class EncryptionUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
void testWrongPublicKeySigned() throws Exception {
|
void testWrongPublicKeySigned() throws Exception {
|
||||||
// load a different public key
|
// load a different public key
|
||||||
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/invalid_wrong_key.json");
|
ClientPublicKey clientKey = com.github.games647.fastlogin.bukkit.auth.protocollib.ResourceLoader.loadClientKey("client_keys/invalid_wrong_key.json");
|
||||||
SignatureTestData testData = SignatureTestData.fromResource("signature/valid_signature.json");
|
SignatureTestData testData = SignatureTestData.fromResource("signature/valid_signature.json");
|
||||||
assertFalse(verifySignedNonce(testData, clientKey));
|
assertFalse(verifySignedNonce(testData, clientKey));
|
||||||
}
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,9 +23,9 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.google.common.io.Resources;
|
import com.google.common.io.Resources;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
@ -50,6 +50,10 @@ import java.util.Base64;
|
|||||||
|
|
||||||
public class ResourceLoader {
|
public class ResourceLoader {
|
||||||
|
|
||||||
|
private ResourceLoader() {
|
||||||
|
// Utility
|
||||||
|
}
|
||||||
|
|
||||||
public static RSAPrivateKey parsePrivateKey(String keySpec)
|
public static RSAPrivateKey parsePrivateKey(String keySpec)
|
||||||
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
|
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
try (
|
try (
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.google.common.io.Resources;
|
import com.google.common.io.Resources;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.comphenix.protocol.injector.packet.PacketRegistry;
|
import com.comphenix.protocol.injector.packet.PacketRegistry;
|
||||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
import com.comphenix.protocol.reflect.accessors.Accessors;
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.task;
|
package com.github.games647.fastlogin.bukkit.hook;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
import lombok.val;
|
import lombok.val;
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015-2023 games647 and contributors
|
Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -40,6 +40,10 @@
|
|||||||
<artifactId>fastlogin.bungee</artifactId>
|
<artifactId>fastlogin.bungee</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.release>17</maven.compiler.release>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<!--Represents the main plugin-->
|
<!--Represents the main plugin-->
|
||||||
<name>FastLoginBungee</name>
|
<name>FastLoginBungee</name>
|
||||||
|
|
||||||
@ -47,20 +51,12 @@
|
|||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.5.1</version>
|
<version>3.5.3</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<minimizeJar>true</minimizeJar>
|
<minimizeJar>true</minimizeJar>
|
||||||
|
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||||
<artifactSet>
|
|
||||||
<excludes>
|
|
||||||
<!--Those classes are already present in BungeeCord version-->
|
|
||||||
<exclude>net.md-5:bungeecord-config</exclude>
|
|
||||||
<exclude>com.google.code.gson:gson</exclude>
|
|
||||||
<exclude>com.google.guava:guava</exclude>
|
|
||||||
</excludes>
|
|
||||||
</artifactSet>
|
|
||||||
<relocations>
|
<relocations>
|
||||||
<relocation>
|
<relocation>
|
||||||
<pattern>com.zaxxer.hikari</pattern>
|
<pattern>com.zaxxer.hikari</pattern>
|
||||||
@ -82,6 +78,7 @@
|
|||||||
<artifact>*:*</artifact>
|
<artifact>*:*</artifact>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>META-INF/MANIFEST.MF</exclude>
|
<exclude>META-INF/MANIFEST.MF</exclude>
|
||||||
|
<exclude>**/module-info</exclude>
|
||||||
<exclude>**/module-info.class</exclude>
|
<exclude>**/module-info.class</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</filter>
|
</filter>
|
||||||
@ -120,13 +117,33 @@
|
|||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>fastlogin.core</artifactId>
|
<artifactId>fastlogin.core</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
|
<!--Those classes are already present in BungeeCord version-->
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>net.md-5</groupId>
|
||||||
|
<artifactId>bungeecord-config</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<!-- Exclude snakeyaml, because it is included in BungeeCord with the correct version -->
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.yaml</groupId>
|
||||||
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--BungeeCord with also the part outside the API-->
|
<!--BungeeCord with also the part outside the API-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-proxy</artifactId>
|
<artifactId>bungeecord-proxy</artifactId>
|
||||||
<version>1.19-R0.1-SNAPSHOT</version>
|
<version>1.20-R0.2-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<!-- Use our own newer api version -->
|
<!-- Use our own newer api version -->
|
||||||
<exclusions>
|
<exclusions>
|
||||||
@ -135,13 +152,14 @@
|
|||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>mysql</groupId>
|
<groupId>com.mysql</groupId>
|
||||||
<artifactId>*</artifactId>
|
<artifactId>*</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-native</artifactId>
|
<artifactId>bungeecord-native</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
|
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-query</artifactId>
|
<artifactId>bungeecord-query</artifactId>
|
||||||
@ -150,6 +168,11 @@
|
|||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-slf4j</artifactId>
|
<artifactId>bungeecord-slf4j</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
|
|
||||||
|
<exclusion>
|
||||||
|
<groupId>net.sf.jopt-simple</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>org.apache.maven</groupId>
|
<groupId>org.apache.maven</groupId>
|
||||||
<artifactId>*</artifactId>
|
<artifactId>*</artifactId>
|
||||||
@ -158,6 +181,10 @@
|
|||||||
<groupId>org.apache.maven.resolver</groupId>
|
<groupId>org.apache.maven.resolver</groupId>
|
||||||
<artifactId>*</artifactId>
|
<artifactId>*</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -54,9 +54,15 @@ public class BungeeLoginSource implements LoginSource {
|
|||||||
preLoginEvent.setCancelled(true);
|
preLoginEvent.setCancelled(true);
|
||||||
|
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
preLoginEvent.setCancelReason(new ComponentBuilder("Kicked").color(ChatColor.WHITE).create());
|
preLoginEvent.setReason(
|
||||||
|
TextComponent.fromArray(
|
||||||
|
new ComponentBuilder("Kicked").color(ChatColor.WHITE).create()
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
preLoginEvent.setCancelReason(TextComponent.fromLegacyText(message));
|
preLoginEvent.setReason(
|
||||||
|
TextComponent.fromArray(
|
||||||
|
TextComponent.fromLegacyText(message)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +78,7 @@ public class BungeeLoginSource implements LoginSource {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.getClass().getSimpleName() + '{'
|
return this.getClass().getSimpleName() + '{'
|
||||||
+ "connection=" + connection
|
+ "connection=" + connection
|
||||||
+ '}';
|
+ '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -28,7 +28,6 @@ package com.github.games647.fastlogin.bungee;
|
|||||||
import com.github.games647.fastlogin.bungee.hook.BungeeAuthHook;
|
import com.github.games647.fastlogin.bungee.hook.BungeeAuthHook;
|
||||||
import com.github.games647.fastlogin.bungee.listener.ConnectListener;
|
import com.github.games647.fastlogin.bungee.listener.ConnectListener;
|
||||||
import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
|
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.CommonUtil;
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
||||||
@ -38,6 +37,7 @@ import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
|
|||||||
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
||||||
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
||||||
import com.github.games647.fastlogin.core.message.SuccessMessage;
|
import com.github.games647.fastlogin.core.message.SuccessMessage;
|
||||||
|
import com.github.games647.fastlogin.core.scheduler.AsyncScheduler;
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.collect.MapMaker;
|
||||||
@ -98,7 +98,7 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
|||||||
//events
|
//events
|
||||||
PluginManager pluginManager = getProxy().getPluginManager();
|
PluginManager pluginManager = getProxy().getPluginManager();
|
||||||
|
|
||||||
Listener connectListener = new ConnectListener(this, core.getAntiBot());
|
Listener connectListener = new ConnectListener(this, core.getAntiBotService());
|
||||||
pluginManager.registerListener(this, connectListener);
|
pluginManager.registerListener(this, connectListener);
|
||||||
pluginManager.registerListener(this, new PluginMessageListener(this));
|
pluginManager.registerListener(this, new PluginMessageListener(this));
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -71,25 +71,43 @@ public class ConnectListener implements Listener {
|
|||||||
private static final String UUID_FIELD_NAME = "uniqueId";
|
private static final String UUID_FIELD_NAME = "uniqueId";
|
||||||
protected static final MethodHandle UNIQUE_ID_SETTER;
|
protected static final MethodHandle UNIQUE_ID_SETTER;
|
||||||
|
|
||||||
|
private static final String REWRITE_ID_NAME = "rewriteId";
|
||||||
|
protected static final MethodHandle REWRITE_ID_SETTER;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
MethodHandle setHandle = null;
|
MethodHandle uniqueIdHandle = null;
|
||||||
|
MethodHandle rewriterHandle = null;
|
||||||
try {
|
try {
|
||||||
Lookup lookup = MethodHandles.lookup();
|
Lookup lookup = MethodHandles.lookup();
|
||||||
|
|
||||||
|
// test for implementation class availability
|
||||||
Class.forName("net.md_5.bungee.connection.InitialHandler");
|
Class.forName("net.md_5.bungee.connection.InitialHandler");
|
||||||
|
uniqueIdHandle = getHandlerSetter(lookup, UUID_FIELD_NAME);
|
||||||
Field uuidField = InitialHandler.class.getDeclaredField(UUID_FIELD_NAME);
|
try {
|
||||||
uuidField.setAccessible(true);
|
rewriterHandle = getHandlerSetter(lookup, REWRITE_ID_NAME);
|
||||||
setHandle = lookup.unreflectSetter(uuidField);
|
} catch (NoSuchFieldException noSuchFieldEx) {
|
||||||
|
Logger logger = LoggerFactory.getLogger(ConnectListener.class);
|
||||||
|
logger.error(
|
||||||
|
"Rewrite field not found. Setting only legacy BungeeCord field"
|
||||||
|
);
|
||||||
|
}
|
||||||
} catch (ReflectiveOperationException reflectiveOperationException) {
|
} catch (ReflectiveOperationException reflectiveOperationException) {
|
||||||
Logger logger = LoggerFactory.getLogger(ConnectListener.class);
|
Logger logger = LoggerFactory.getLogger(ConnectListener.class);
|
||||||
logger.error(
|
logger.error(
|
||||||
"Cannot find Bungee initial handler; Disabling premium UUID and skin won't work.",
|
"Cannot find Bungee UUID field implementation; Disabling premium UUID and skin won't work.",
|
||||||
reflectiveOperationException
|
reflectiveOperationException
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIQUE_ID_SETTER = setHandle;
|
UNIQUE_ID_SETTER = uniqueIdHandle;
|
||||||
|
REWRITE_ID_SETTER = rewriterHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MethodHandle getHandlerSetter(Lookup lookup, String fieldName)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
Field uuidField = InitialHandler.class.getDeclaredField(fieldName);
|
||||||
|
uuidField.setAccessible(true);
|
||||||
|
return lookup.unreflectSetter(uuidField);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final FastLoginBungee plugin;
|
private final FastLoginBungee plugin;
|
||||||
@ -179,6 +197,12 @@ public class ConnectListener implements Listener {
|
|||||||
// So we have to do it with reflection
|
// So we have to do it with reflection
|
||||||
UNIQUE_ID_SETTER.invokeExact(connection, offlineUUID);
|
UNIQUE_ID_SETTER.invokeExact(connection, offlineUUID);
|
||||||
|
|
||||||
|
// if available set rewrite id to forward the UUID for newer BungeeCord versions since
|
||||||
|
// https://github.com/SpigotMC/BungeeCord/commit/1be25b6c74ec2be4b15adf8ca53a0497f01e2afe
|
||||||
|
if (REWRITE_ID_SETTER != null) {
|
||||||
|
REWRITE_ID_SETTER.invokeExact(connection, offlineUUID);
|
||||||
|
}
|
||||||
|
|
||||||
String format = "Overridden UUID from {} to {} (based of {}) on {}";
|
String format = "Overridden UUID from {} to {} (based of {}) on {}";
|
||||||
plugin.getLog().info(format, oldPremiumId, offlineUUID, username, connection);
|
plugin.getLog().info(format, oldPremiumId, offlineUUID, username, connection);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@ -209,9 +233,6 @@ public class ConnectListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// delay sending force command, because Paper will process the login event asynchronously
|
|
||||||
// In this case it means that the force command (plugin message) is already received and processed while
|
|
||||||
// player is still in the login phase and reported to be offline.
|
|
||||||
Runnable loginTask = new ForceLoginTask(plugin.getCore(), player, server, session);
|
Runnable loginTask = new ForceLoginTask(plugin.getCore(), player, server, session);
|
||||||
plugin.getScheduler().runAsync(loginTask);
|
plugin.getScheduler().runAsync(loginTask);
|
||||||
}
|
}
|
||||||
@ -220,6 +241,5 @@ public class ConnectListener implements Listener {
|
|||||||
public void onDisconnect(PlayerDisconnectEvent disconnectEvent) {
|
public void onDisconnect(PlayerDisconnectEvent disconnectEvent) {
|
||||||
ProxiedPlayer player = disconnectEvent.getPlayer();
|
ProxiedPlayer player = disconnectEvent.getPlayer();
|
||||||
plugin.getSession().remove(player.getPendingConnection());
|
plugin.getSession().remove(player.getPendingConnection());
|
||||||
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -37,7 +37,6 @@ import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|||||||
import com.google.common.io.ByteArrayDataInput;
|
import com.google.common.io.ByteArrayDataInput;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import net.md_5.bungee.api.connection.Server;
|
import net.md_5.bungee.api.connection.Server;
|
||||||
import net.md_5.bungee.api.event.PluginMessageEvent;
|
import net.md_5.bungee.api.event.PluginMessageEvent;
|
||||||
@ -96,15 +95,6 @@ public class PluginMessageListener implements Listener {
|
|||||||
String playerName = changeMessage.getPlayerName();
|
String playerName = changeMessage.getPlayerName();
|
||||||
boolean isSourceInvoker = changeMessage.isSourceInvoker();
|
boolean isSourceInvoker = changeMessage.isSourceInvoker();
|
||||||
if (changeMessage.shouldEnable()) {
|
if (changeMessage.shouldEnable()) {
|
||||||
if (playerName.equals(forPlayer.getName()) && plugin.getCore().getConfig().get("premium-warning", true)
|
|
||||||
&& !core.getPendingConfirms().contains(forPlayer.getUniqueId())) {
|
|
||||||
String message = core.getMessage("premium-warning");
|
|
||||||
forPlayer.sendMessage(TextComponent.fromLegacyText(message));
|
|
||||||
core.getPendingConfirms().add(forPlayer.getUniqueId());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
core.getPendingConfirms().remove(forPlayer.getUniqueId());
|
|
||||||
Runnable task = new AsyncToggleMessage(core, forPlayer, playerName, true, isSourceInvoker);
|
Runnable task = new AsyncToggleMessage(core, forPlayer, playerName, true, isSourceInvoker);
|
||||||
plugin.getScheduler().runAsync(task);
|
plugin.getScheduler().runAsync(task);
|
||||||
} else {
|
} else {
|
||||||
@ -131,7 +121,7 @@ public class PluginMessageListener implements Listener {
|
|||||||
loginSession.setRegistered(true);
|
loginSession.setRegistered(true);
|
||||||
|
|
||||||
if (!loginSession.isAlreadySaved()) {
|
if (!loginSession.isAlreadySaved()) {
|
||||||
playerProfile.setPremium(true);
|
playerProfile.setOnlinemodePreferred(true);
|
||||||
plugin.getCore().getStorage().save(playerProfile);
|
plugin.getCore().getStorage().save(playerProfile);
|
||||||
loginSession.setAlreadySaved(true);
|
loginSession.setAlreadySaved(true);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -81,7 +81,7 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
|
|||||||
plugin.getSession().put(source.getConnection(), new BungeeLoginSession(username, registered, profile));
|
plugin.getSession().put(source.getConnection(), new BungeeLoginSession(username, registered, profile));
|
||||||
|
|
||||||
String ip = source.getAddress().getAddress().getHostAddress();
|
String ip = source.getAddress().getAddress().getHostAddress();
|
||||||
plugin.getCore().getPendingLogin().put(ip + username, new Object());
|
plugin.getCore().addLoginAttempt(ip, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -64,12 +64,12 @@ public class AsyncToggleMessage implements Runnable {
|
|||||||
private void turnOffPremium() {
|
private void turnOffPremium() {
|
||||||
StoredProfile playerProfile = core.getStorage().loadProfile(targetPlayer);
|
StoredProfile playerProfile = core.getStorage().loadProfile(targetPlayer);
|
||||||
//existing player is already cracked
|
//existing player is already cracked
|
||||||
if (playerProfile.isSaved() && !playerProfile.isPremium()) {
|
if (playerProfile.isExistingPlayer() && !playerProfile.isOnlinemodePreferred()) {
|
||||||
sendMessage("not-premium");
|
sendMessage("not-premium");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerProfile.setPremium(false);
|
playerProfile.setOnlinemodePreferred(false);
|
||||||
playerProfile.setId(null);
|
playerProfile.setId(null);
|
||||||
core.getStorage().save(playerProfile);
|
core.getStorage().save(playerProfile);
|
||||||
PremiumToggleReason reason = (!isPlayerSender || !sender.getName().equalsIgnoreCase(playerProfile.getName()))
|
PremiumToggleReason reason = (!isPlayerSender || !sender.getName().equalsIgnoreCase(playerProfile.getName()))
|
||||||
@ -81,12 +81,12 @@ public class AsyncToggleMessage implements Runnable {
|
|||||||
|
|
||||||
private void activatePremium() {
|
private void activatePremium() {
|
||||||
StoredProfile playerProfile = core.getStorage().loadProfile(targetPlayer);
|
StoredProfile playerProfile = core.getStorage().loadProfile(targetPlayer);
|
||||||
if (playerProfile.isPremium()) {
|
if (playerProfile.isOnlinemodePreferred()) {
|
||||||
sendMessage("already-exists");
|
sendMessage("already-exists");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerProfile.setPremium(true);
|
playerProfile.setOnlinemodePreferred(true);
|
||||||
core.getStorage().save(playerProfile);
|
core.getStorage().save(playerProfile);
|
||||||
PremiumToggleReason reason = (!isPlayerSender || !sender.getName().equalsIgnoreCase(playerProfile.getName()))
|
PremiumToggleReason reason = (!isPlayerSender || !sender.getName().equalsIgnoreCase(playerProfile.getName()))
|
||||||
? PremiumToggleReason.COMMAND_OTHER : PremiumToggleReason.COMMAND_SELF;
|
? PremiumToggleReason.COMMAND_OTHER : PremiumToggleReason.COMMAND_SELF;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -11,8 +11,6 @@ author: games647, https://github.com/games647/FastLogin/graphs/contributors
|
|||||||
softDepends:
|
softDepends:
|
||||||
# BungeeCord auth plugins
|
# BungeeCord auth plugins
|
||||||
- BungeeAuth
|
- BungeeAuth
|
||||||
- BungeeCordAuthenticatorBungee
|
|
||||||
- SodionAuth
|
|
||||||
# Bedrock Player Bridge
|
# Bedrock Player Bridge
|
||||||
- Geyser-BungeeCord
|
- Geyser-BungeeCord
|
||||||
- floodgate
|
- floodgate
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015-2023 games647 and contributors
|
Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -29,35 +29,6 @@
|
|||||||
<!DOCTYPE module PUBLIC
|
<!DOCTYPE module PUBLIC
|
||||||
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
|
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
|
||||||
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
Checkstyle configuration that checks the sun coding conventions from:
|
|
||||||
|
|
||||||
- the Java Language Specification at
|
|
||||||
https://docs.oracle.com/javase/specs/jls/se11/html/index.html
|
|
||||||
|
|
||||||
- the Sun Code Conventions at https://www.oracle.com/java/technologies/javase/codeconventions-contents.html
|
|
||||||
|
|
||||||
- the Javadoc guidelines at
|
|
||||||
https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html
|
|
||||||
|
|
||||||
- the JDK Api documentation https://docs.oracle.com/en/java/javase/11/
|
|
||||||
|
|
||||||
- some best practices
|
|
||||||
|
|
||||||
Checkstyle is very configurable. Be sure to read the documentation at
|
|
||||||
https://checkstyle.org (or in your downloaded distribution).
|
|
||||||
|
|
||||||
Most Checks are configurable, be sure to consult the documentation.
|
|
||||||
|
|
||||||
To completely disable a check, just comment it out or delete it from the file.
|
|
||||||
To suppress certain violations please review suppression filters.
|
|
||||||
|
|
||||||
Finally, it is worth reading the documentation.
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<module name="Checker">
|
<module name="Checker">
|
||||||
<!--
|
<!--
|
||||||
If you set the basedir property below, then all reported file
|
If you set the basedir property below, then all reported file
|
||||||
@ -227,7 +198,5 @@
|
|||||||
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
|
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
|
||||||
<property name="checkFormat" value="$1"/>
|
<property name="checkFormat" value="$1"/>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
</module>
|
</module>
|
||||||
|
99
core/pom.xml
99
core/pom.xml
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015-2023 games647 and contributors
|
Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -39,6 +39,11 @@
|
|||||||
<artifactId>fastlogin.core</artifactId>
|
<artifactId>fastlogin.core</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<!-- Still force Java 8 for the remaining project -->
|
||||||
|
<maven.compiler.release>8</maven.compiler.release>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<name>FastLoginCore</name>
|
<name>FastLoginCore</name>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
@ -55,7 +60,7 @@
|
|||||||
</repository>
|
</repository>
|
||||||
<!-- Floodgate -->
|
<!-- Floodgate -->
|
||||||
<repository>
|
<repository>
|
||||||
<id>opencollab-snapshot</id>
|
<id>opencollab</id>
|
||||||
<url>https://repo.opencollab.dev/maven-snapshots/</url>
|
<url>https://repo.opencollab.dev/maven-snapshots/</url>
|
||||||
<releases>
|
<releases>
|
||||||
<enabled>false</enabled>
|
<enabled>false</enabled>
|
||||||
@ -68,7 +73,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
<version>3.3.0</version>
|
<version>3.4.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<archive>
|
<archive>
|
||||||
<manifestEntries>
|
<manifestEntries>
|
||||||
@ -80,6 +85,39 @@
|
|||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>jdk21</id>
|
||||||
|
<activation>
|
||||||
|
<jdk>[21,)</jdk>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>jdk21</id>
|
||||||
|
<goals>
|
||||||
|
<goal>compile</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<release>21</release>
|
||||||
|
<compileSourceRoots>
|
||||||
|
<compileSourceRoot>${project.basedir}/src/main/java21</compileSourceRoot>
|
||||||
|
</compileSourceRoots>
|
||||||
|
<multiReleaseOutput>true</multiReleaseOutput>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- Libraries that we shade into the project -->
|
<!-- Libraries that we shade into the project -->
|
||||||
|
|
||||||
@ -87,7 +125,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.zaxxer</groupId>
|
<groupId>com.zaxxer</groupId>
|
||||||
<artifactId>HikariCP</artifactId>
|
<artifactId>HikariCP</artifactId>
|
||||||
<version>4.0.3</version>
|
<version>5.1.0</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<!-- HikariCP uses an old version of this API that has a typo in the service interface -->
|
<!-- HikariCP uses an old version of this API that has a typo in the service interface -->
|
||||||
<!-- We will use the api provided by the jdk14 dependency -->
|
<!-- We will use the api provided by the jdk14 dependency -->
|
||||||
@ -102,14 +140,21 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-jdk14</artifactId>
|
<artifactId>slf4j-jdk14</artifactId>
|
||||||
<version>2.0.11</version>
|
<version>2.0.13</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- snakeyaml is present in Bungee, Spigot, Cauldron, so we could use this independent implementation -->
|
<!-- snakeyaml is present in Bungee, Spigot, so we could use this independent implementation -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-config</artifactId>
|
<artifactId>bungeecord-config</artifactId>
|
||||||
<version>1.19-R0.1-SNAPSHOT</version>
|
<version>1.20-R0.2-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- This is optional in BungeeCord-config, so we include it here manually -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.yaml</groupId>
|
||||||
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
<version>2.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--Floodgate for Xbox Live Authentication-->
|
<!--Floodgate for Xbox Live Authentication-->
|
||||||
@ -158,46 +203,10 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.games647</groupId>
|
<groupId>com.github.games647</groupId>
|
||||||
<artifactId>craftapi</artifactId>
|
<artifactId>craftapi</artifactId>
|
||||||
<version>0.6.2</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee, Velocity) -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.guava</groupId>
|
|
||||||
<artifactId>guava</artifactId>
|
|
||||||
<!-- Old version for velocity -->
|
|
||||||
<version>25.1-jre</version>
|
|
||||||
<!-- Exclude compile time dependencies not marked as such on upstream -->
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>com.google.code.findbugs</groupId>
|
|
||||||
<artifactId>jsr305</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.checkerframework</groupId>
|
|
||||||
<artifactId>checker-qual</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>com.google.errorprone</groupId>
|
|
||||||
<artifactId>error_prone_annotations</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>com.google.j2objc</groupId>
|
|
||||||
<artifactId>j2objc-annotations</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>animal-sniffer-annotations</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.gson</groupId>
|
|
||||||
<artifactId>gson</artifactId>
|
|
||||||
<version>2.10.1</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Database driver included in Spigot -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.xerial</groupId>
|
<groupId>org.xerial</groupId>
|
||||||
<artifactId>sqlite-jdbc</artifactId>
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -32,8 +32,8 @@ import org.slf4j.jul.JDK14LoggerAdapter;
|
|||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public final class CommonUtil {
|
public final class CommonUtil {
|
||||||
@ -41,11 +41,11 @@ public final class CommonUtil {
|
|||||||
private static final char COLOR_CHAR = '&';
|
private static final char COLOR_CHAR = '&';
|
||||||
private static final char TRANSLATED_CHAR = '§';
|
private static final char TRANSLATED_CHAR = '§';
|
||||||
|
|
||||||
public static <K, V> ConcurrentMap<K, V> buildCache(int expireAfterWrite, int maxSize) {
|
public static <K, V> ConcurrentMap<K, V> buildCache(Duration expireAfterWrite, int maxSize) {
|
||||||
CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
|
CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
|
||||||
|
|
||||||
if (expireAfterWrite > 0) {
|
if (expireAfterWrite != null) {
|
||||||
builder.expireAfterWrite(expireAfterWrite, TimeUnit.MINUTES);
|
builder.expireAfterWrite(expireAfterWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxSize > 0) {
|
if (maxSize > 0) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -29,8 +29,6 @@ import com.github.games647.craftapi.model.auth.Verification;
|
|||||||
import com.github.games647.craftapi.resolver.MojangResolver;
|
import com.github.games647.craftapi.resolver.MojangResolver;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -44,38 +42,9 @@ import java.util.Optional;
|
|||||||
*/
|
*/
|
||||||
public class ProxyAgnosticMojangResolver extends MojangResolver {
|
public class ProxyAgnosticMojangResolver extends MojangResolver {
|
||||||
|
|
||||||
private static final String HOST = "sessionserver.mojang.com";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A formatting string containing a URL used to call the {@code hasJoined} method on mojang session servers.
|
|
||||||
* <p>
|
|
||||||
* Formatting parameters:
|
|
||||||
* 1. The username of the player in question
|
|
||||||
* 2. The serverId of this server
|
|
||||||
*/
|
|
||||||
public static final String ENDPOINT = "https://" + HOST + "/session/minecraft/hasJoined?username=%s&serverId=%s";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Verification> hasJoined(String username, String serverHash, InetAddress hostIp)
|
public Optional<Verification> hasJoined(String username, String serverHash, InetAddress hostIp)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
String url = String.format(ENDPOINT, username, serverHash);
|
return super.hasJoined(username, serverHash, null);
|
||||||
|
|
||||||
HttpURLConnection conn = this.getConnection(url);
|
|
||||||
int responseCode = conn.getResponseCode();
|
|
||||||
|
|
||||||
Verification verification = null;
|
|
||||||
|
|
||||||
// Mojang session servers send HTTP 204 (NO CONTENT) when the authentication seems invalid
|
|
||||||
// If that's not our case, the authentication is valid, and so we can parse the response.
|
|
||||||
if (responseCode != HttpURLConnection.HTTP_NO_CONTENT) {
|
|
||||||
verification = this.parseRequest(conn, this::parseVerification);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Optional.ofNullable(verification);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Functional implementation of InputStreamAction, used in hasJoined method in parseRequest call
|
|
||||||
protected Verification parseVerification(InputStream input) throws IOException {
|
|
||||||
return this.readJson(input, Verification.class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -34,8 +34,8 @@ public interface PasswordGenerator<P> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a password for a non-registered player
|
* Generate a password for a non-registered player
|
||||||
* @param player
|
* @param player player representation
|
||||||
* @return daw
|
* @return generated password
|
||||||
*/
|
*/
|
||||||
String getRandomPassword(P player);
|
String getRandomPassword(P player);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,44 +23,36 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocolsupport;
|
package com.github.games647.fastlogin.core.scheduler;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
import org.slf4j.Logger;
|
||||||
import protocolsupport.api.events.PlayerLoginStartEvent;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.time.Duration;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class ProtocolLoginSource implements LoginSource {
|
public abstract class AbstractAsyncScheduler {
|
||||||
|
|
||||||
private final PlayerLoginStartEvent loginStartEvent;
|
protected final Logger logger;
|
||||||
|
protected final Executor processingPool;
|
||||||
|
protected final AtomicInteger currentlyRunning = new AtomicInteger();
|
||||||
|
|
||||||
public ProtocolLoginSource(PlayerLoginStartEvent loginStartEvent) {
|
public AbstractAsyncScheduler(Logger logger, Executor processingPool) {
|
||||||
this.loginStartEvent = loginStartEvent;
|
this.logger = logger;
|
||||||
|
this.processingPool = processingPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public abstract CompletableFuture<Void> runAsync(Runnable task);
|
||||||
public void enableOnlinemode() {
|
|
||||||
loginStartEvent.setOnlineMode(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public abstract CompletableFuture<Void> runAsyncDelayed(Runnable task, Duration delay);
|
||||||
public void kick(String message) {
|
|
||||||
loginStartEvent.denyLogin(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
protected void process(Runnable task) {
|
||||||
public InetSocketAddress getAddress() {
|
currentlyRunning.incrementAndGet();
|
||||||
return loginStartEvent.getConnection().getRawAddress();
|
try {
|
||||||
}
|
task.run();
|
||||||
|
} finally {
|
||||||
public PlayerLoginStartEvent getLoginStartEvent() {
|
currentlyRunning.getAndDecrement();
|
||||||
return loginStartEvent;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.getClass().getSimpleName() + '{'
|
|
||||||
+ "loginStartEvent=" + loginStartEvent
|
|
||||||
+ '}';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,13 +23,13 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.core;
|
package com.github.games647.fastlogin.core.scheduler;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This limits the number of threads that are used at maximum. Thread creation can be very heavy for the CPU and
|
* This limits the number of threads that are used at maximum. Thread creation can be very heavy for the CPU and
|
||||||
@ -38,25 +38,14 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
* is limited by the size of our database pool. The goal is to separate concerns into processing and blocking only
|
* is limited by the size of our database pool. The goal is to separate concerns into processing and blocking only
|
||||||
* threads.
|
* threads.
|
||||||
*/
|
*/
|
||||||
public class AsyncScheduler {
|
public class AsyncScheduler extends AbstractAsyncScheduler {
|
||||||
|
|
||||||
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 Executor processingPool;
|
|
||||||
|
|
||||||
private final AtomicInteger currentlyRunning = new AtomicInteger();
|
|
||||||
|
|
||||||
public AsyncScheduler(Logger logger, Executor processingPool) {
|
public AsyncScheduler(Logger logger, Executor processingPool) {
|
||||||
this.logger = logger;
|
super(logger, processingPool);
|
||||||
this.processingPool = processingPool;
|
logger.info("Using legacy scheduler");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public CompletableFuture<Void> runAsync(Runnable task) {
|
public CompletableFuture<Void> runAsync(Runnable task) {
|
||||||
return CompletableFuture.runAsync(() -> process(task), processingPool).exceptionally(error -> {
|
return CompletableFuture.runAsync(() -> process(task), processingPool).exceptionally(error -> {
|
||||||
logger.warn("Error occurred on thread pool", error);
|
logger.warn("Error occurred on thread pool", error);
|
||||||
@ -64,12 +53,22 @@ public class AsyncScheduler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void process(Runnable task) {
|
@Override
|
||||||
currentlyRunning.incrementAndGet();
|
public CompletableFuture<Void> runAsyncDelayed(Runnable task, Duration delay) {
|
||||||
try {
|
return CompletableFuture.runAsync(() -> {
|
||||||
task.run();
|
currentlyRunning.incrementAndGet();
|
||||||
} finally {
|
try {
|
||||||
currentlyRunning.getAndDecrement();
|
Thread.sleep(delay.toMillis());
|
||||||
}
|
process(task);
|
||||||
|
} catch (InterruptedException interruptedException) {
|
||||||
|
// restore interrupt flag
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
} finally {
|
||||||
|
currentlyRunning.getAndDecrement();
|
||||||
|
}
|
||||||
|
}, processingPool).exceptionally(error -> {
|
||||||
|
logger.warn("Error occurred on thread pool", error);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -55,12 +55,12 @@ import java.net.Proxy.Type;
|
|||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
@ -78,8 +78,10 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
private static final long MAX_EXPIRE_RATE = 1_000_000;
|
private static final long MAX_EXPIRE_RATE = 1_000_000;
|
||||||
|
|
||||||
private final Map<String, String> localeMessages = new ConcurrentHashMap<>();
|
private final Map<String, String> localeMessages = new ConcurrentHashMap<>();
|
||||||
private final ConcurrentMap<String, Object> pendingLogin = CommonUtil.buildCache(5, -1);
|
private final ConcurrentMap<String, Object> pendingLogin = CommonUtil.buildCache(
|
||||||
private final Collection<UUID> pendingConfirms = new HashSet<>();
|
Duration.ofMinutes(5), -1
|
||||||
|
);
|
||||||
|
|
||||||
private final T plugin;
|
private final T plugin;
|
||||||
|
|
||||||
private MojangResolver resolver;
|
private MojangResolver resolver;
|
||||||
@ -119,7 +121,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
|
|
||||||
// Initialize the resolver based on the config parameter
|
// Initialize the resolver based on the config parameter
|
||||||
this.resolver = this.config.getBoolean("useProxyAgnosticResolver", false)
|
this.resolver = this.config.getBoolean("useProxyAgnosticResolver", false)
|
||||||
? new ProxyAgnosticMojangResolver() : new MojangResolver();
|
? new ProxyAgnosticMojangResolver() : new MojangResolver();
|
||||||
|
|
||||||
antiBot = createAntiBotService(config.getSection("anti-bot"));
|
antiBot = createAntiBotService(config.getSection("anti-bot"));
|
||||||
Set<Proxy> proxies = config.getStringList("proxies")
|
Set<Proxy> proxies = config.getStringList("proxies")
|
||||||
@ -140,7 +142,6 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
|
|
||||||
resolver.setMaxNameRequests(config.getInt("mojang-request-limit"));
|
resolver.setMaxNameRequests(config.getInt("mojang-request-limit"));
|
||||||
resolver.setProxySelector(new RotatingProxySelector(proxies));
|
resolver.setProxySelector(new RotatingProxySelector(proxies));
|
||||||
resolver.setOutgoingAddresses(addresses);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AntiBotService createAntiBotService(Configuration botSection) {
|
private AntiBotService createAntiBotService(Configuration botSection) {
|
||||||
@ -160,12 +161,12 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
|
|
||||||
Action action = Action.Ignore;
|
Action action = Action.Ignore;
|
||||||
switch (botSection.getString("action", "ignore")) {
|
switch (botSection.getString("action", "ignore")) {
|
||||||
case "ignore":
|
|
||||||
action = Action.Ignore;
|
|
||||||
break;
|
|
||||||
case "block":
|
case "block":
|
||||||
action = Action.Block;
|
action = Action.Block;
|
||||||
break;
|
break;
|
||||||
|
case "ignore":
|
||||||
|
action = Action.Ignore;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
plugin.getLog().warn("Invalid anti bot action - defaulting to ignore");
|
plugin.getLog().warn("Invalid anti bot action - defaulting to ignore");
|
||||||
}
|
}
|
||||||
@ -272,19 +273,23 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
this.passwordGenerator = passwordGenerator;
|
this.passwordGenerator = passwordGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConcurrentMap<String, Object> getPendingLogin() {
|
public void addLoginAttempt(String ip, String username) {
|
||||||
return pendingLogin;
|
pendingLogin.put(ip + username, new Object());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<UUID> getPendingConfirms() {
|
public boolean hasFailedLogin(String ip, String username) {
|
||||||
return pendingConfirms;
|
if (!config.get("secondAttemptCracked", false)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pendingLogin.remove(ip + username) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthPlugin<P> getAuthPluginHook() {
|
public AuthPlugin<P> getAuthPluginHook() {
|
||||||
return authPlugin;
|
return authPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AntiBotService getAntiBot() {
|
public AntiBotService getAntiBotService() {
|
||||||
return antiBot;
|
return antiBot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -82,7 +82,7 @@ public abstract class FloodgateManagement<P extends C, C, L extends LoginSession
|
|||||||
|
|
||||||
profile = core.getStorage().loadProfile(username);
|
profile = core.getStorage().loadProfile(username);
|
||||||
|
|
||||||
if (profile.isSaved()) {
|
if (profile.isExistingPlayer()) {
|
||||||
if (profile.isFloodgateMigrated()) {
|
if (profile.isFloodgateMigrated()) {
|
||||||
if (profile.getFloodgate() == FloodgateState.TRUE && isLinked) {
|
if (profile.getFloodgate() == FloodgateState.TRUE && isLinked) {
|
||||||
core.getPlugin().getLog()
|
core.getPlugin().getLog()
|
||||||
@ -121,7 +121,7 @@ public abstract class FloodgateManagement<P extends C, C, L extends LoginSession
|
|||||||
//maybe Bungee without auth plugin
|
//maybe Bungee without auth plugin
|
||||||
if (authPlugin == null) {
|
if (authPlugin == null) {
|
||||||
if (profile != null) {
|
if (profile != null) {
|
||||||
isRegistered = profile.isPremium();
|
isRegistered = profile.isOnlinemodePreferred();
|
||||||
} else {
|
} else {
|
||||||
isRegistered = false;
|
isRegistered = false;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -47,7 +47,7 @@ public enum FloodgateState {
|
|||||||
*/
|
*/
|
||||||
NOT_MIGRATED(3);
|
NOT_MIGRATED(3);
|
||||||
|
|
||||||
private int value;
|
private final int value;
|
||||||
|
|
||||||
FloodgateState(int value) {
|
FloodgateState(int value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -81,7 +81,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
|
|||||||
//update only on success to prevent corrupt data
|
//update only on success to prevent corrupt data
|
||||||
if (playerProfile != null) {
|
if (playerProfile != null) {
|
||||||
playerProfile.setId(session.getUuid());
|
playerProfile.setId(session.getUuid());
|
||||||
playerProfile.setPremium(true);
|
playerProfile.setOnlinemodePreferred(true);
|
||||||
storage.save(playerProfile);
|
storage.save(playerProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
|
|||||||
} else if (playerProfile != null) {
|
} else if (playerProfile != null) {
|
||||||
//cracked player
|
//cracked player
|
||||||
playerProfile.setId(null);
|
playerProfile.setId(null);
|
||||||
playerProfile.setPremium(false);
|
playerProfile.setOnlinemodePreferred(false);
|
||||||
storage.save(playerProfile);
|
storage.save(playerProfile);
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -48,8 +48,6 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onLogin(String username, S source) {
|
public void onLogin(String username, S source) {
|
||||||
core.getPlugin().getLog().info("Handling player {}", username);
|
|
||||||
|
|
||||||
//check if the player is connecting through Bedrock Edition
|
//check if the player is connecting through Bedrock Edition
|
||||||
if (bedrockService != null && bedrockService.isBedrockConnection(username)) {
|
if (bedrockService != null && bedrockService.isBedrockConnection(username)) {
|
||||||
//perform Bedrock specific checks and skip Java checks if no longer needed
|
//perform Bedrock specific checks and skip Java checks if no longer needed
|
||||||
@ -59,7 +57,6 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StoredProfile profile = core.getStorage().loadProfile(username);
|
StoredProfile profile = core.getStorage().loadProfile(username);
|
||||||
|
|
||||||
//can't be a premium Java player, if it's not saved in the database
|
//can't be a premium Java player, if it's not saved in the database
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
return;
|
return;
|
||||||
@ -74,62 +71,65 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
|||||||
} else {
|
} else {
|
||||||
profile.setFloodgate(FloodgateState.FALSE);
|
profile.setFloodgate(FloodgateState.FALSE);
|
||||||
core.getPlugin().getLog().info(
|
core.getPlugin().getLog().info(
|
||||||
"Player {} will be migrated to the v2 database schema as a JAVA user", username);
|
"Player {} will be migrated to the v2 database schema as a JAVA user", username
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
callFastLoginPreLoginEvent(username, source, profile);
|
callFastLoginPreLoginEvent(username, source, profile);
|
||||||
|
|
||||||
Configuration config = core.getConfig();
|
|
||||||
|
|
||||||
String ip = source.getAddress().getAddress().getHostAddress();
|
String ip = source.getAddress().getAddress().getHostAddress();
|
||||||
profile.setLastIp(ip);
|
profile.setLastIp(ip);
|
||||||
try {
|
if (profile.isExistingPlayer()) {
|
||||||
if (profile.isSaved()) {
|
if (profile.isOnlinemodePreferred()) {
|
||||||
if (profile.isPremium()) {
|
core.getPlugin().getLog().info("Requesting premium login for registered player: {}", username);
|
||||||
core.getPlugin().getLog().info("Requesting premium login for registered player: {}", username);
|
requestPremiumLogin(source, profile, username, true);
|
||||||
requestPremiumLogin(source, profile, username, true);
|
|
||||||
} else {
|
|
||||||
if (isValidUsername(source, profile)) {
|
|
||||||
startCrackedSession(source, profile, username);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (core.getPendingLogin().remove(ip + username) != null && config.get("secondAttemptCracked", false)) {
|
if (isValidUsername(source, profile)) {
|
||||||
core.getPlugin().getLog().info("Second attempt login -> cracked {}", username);
|
|
||||||
|
|
||||||
//first login request failed so make a cracked session
|
|
||||||
startCrackedSession(source, profile, username);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<Profile> premiumUUID = Optional.empty();
|
|
||||||
if (config.get("nameChangeCheck", false) || config.get("autoRegister", false)) {
|
|
||||||
premiumUUID = core.getResolver().findProfile(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!premiumUUID.isPresent()
|
|
||||||
|| (!checkNameChange(source, username, premiumUUID.get())
|
|
||||||
&& !checkPremiumName(source, username, profile))) {
|
|
||||||
//nothing detected the player as premium -> start a cracked session
|
|
||||||
if (core.getConfig().get("switchMode", false)) {
|
|
||||||
source.kick(core.getMessage("switch-kick-message"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
startCrackedSession(source, profile, username);
|
startCrackedSession(source, profile, username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
performNewPlayerLogin(username, source, ip, profile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performNewPlayerLogin(String username, S source, String ip, StoredProfile profile) {
|
||||||
|
try {
|
||||||
|
if (core.hasFailedLogin(ip, username)) {
|
||||||
|
core.getPlugin().getLog().info("Second attempt login -> cracked {}", username);
|
||||||
|
|
||||||
|
//first login request failed so make a cracked session
|
||||||
|
startCrackedSession(source, profile, username);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Configuration config = core.getConfig();
|
||||||
|
Optional<Profile> premiumUUID = Optional.empty();
|
||||||
|
if (config.get("nameChangeCheck", false) || config.get("autoRegister", false)) {
|
||||||
|
premiumUUID = core.getResolver().findProfile(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (premiumUUID.isPresent()
|
||||||
|
|| (!isNameChanged(source, username, premiumUUID.get())
|
||||||
|
&& !isUsernameAvailable(source, username, profile))) {
|
||||||
|
//nothing detected the player as premium -> start a cracked session
|
||||||
|
if (core.getConfig().get("switchMode", false)) {
|
||||||
|
source.kick(core.getMessage("switch-kick-message"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
startCrackedSession(source, profile, username);
|
||||||
|
}
|
||||||
} catch (RateLimitException rateLimitEx) {
|
} catch (RateLimitException rateLimitEx) {
|
||||||
core.getPlugin().getLog().error("Mojang's rate limit reached for {}. The public IPv4 address of this"
|
core.getPlugin().getLog().error("Mojang's rate limit reached for {}. The public IPv4 address of this"
|
||||||
+ " server issued more than 600 Name -> UUID requests within 10 minutes. After those 10"
|
+ " server issued more than 600 Name -> UUID requests within 10 minutes. After those 10"
|
||||||
+ " minutes we can make requests again.", username);
|
+ " minutes we can make requests again.", username);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
core.getPlugin().getLog().error("Failed to check premium state for {}", username, ex);
|
|
||||||
core.getPlugin().getLog().error("Failed to check premium state of {}", username, ex);
|
core.getPlugin().getLog().error("Failed to check premium state of {}", username, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isValidUsername(LoginSource source, StoredProfile profile) throws Exception {
|
protected boolean isValidUsername(LoginSource source, StoredProfile profile) {
|
||||||
if (bedrockService != null && bedrockService.isUsernameForbidden(profile)) {
|
if (bedrockService != null && bedrockService.isUsernameForbidden(profile)) {
|
||||||
core.getPlugin().getLog().info("Floodgate Prefix detected on cracked player");
|
core.getPlugin().getLog().info("Floodgate Prefix detected on cracked player");
|
||||||
source.kick("Your username contains illegal characters");
|
source.kick("Your username contains illegal characters");
|
||||||
@ -139,7 +139,7 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkPremiumName(S source, String username, StoredProfile profile) throws Exception {
|
private boolean isUsernameAvailable(S source, String username, StoredProfile profile) throws Exception {
|
||||||
core.getPlugin().getLog().info("GameProfile {} uses a premium username", username);
|
core.getPlugin().getLog().info("GameProfile {} uses a premium username", username);
|
||||||
if (core.getConfig().get("autoRegister", false) && (authHook == null || !authHook.isRegistered(username))) {
|
if (core.getConfig().get("autoRegister", false) && (authHook == null || !authHook.isRegistered(username))) {
|
||||||
requestPremiumLogin(source, profile, username, false);
|
requestPremiumLogin(source, profile, username, false);
|
||||||
@ -149,7 +149,7 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkNameChange(S source, String username, Profile profile) {
|
private boolean isNameChanged(S source, String username, Profile profile) {
|
||||||
//user not exists in the db
|
//user not exists in the db
|
||||||
if (core.getConfig().get("nameChangeCheck", false)) {
|
if (core.getConfig().get("nameChangeCheck", false)) {
|
||||||
StoredProfile storedProfile = core.getStorage().loadProfile(profile.getId());
|
StoredProfile storedProfile = core.getStorage().loadProfile(profile.getId());
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -29,9 +29,9 @@ import java.net.InetSocketAddress;
|
|||||||
|
|
||||||
public interface LoginSource {
|
public interface LoginSource {
|
||||||
|
|
||||||
void enableOnlinemode() throws Exception;
|
void enableOnlinemode();
|
||||||
|
|
||||||
void kick(String message) throws Exception;
|
void kick(String message);
|
||||||
|
|
||||||
InetSocketAddress getAddress();
|
InetSocketAddress getAddress();
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 games647 and contributors
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -25,16 +25,19 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.core.shared;
|
package com.github.games647.fastlogin.core.shared;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.AsyncScheduler;
|
|
||||||
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
||||||
|
import com.github.games647.fastlogin.core.scheduler.AsyncScheduler;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public interface PlatformPlugin<C> {
|
public interface PlatformPlugin<C> {
|
||||||
|
|
||||||
|
Pattern PATTERN = Pattern.compile("%nl%");
|
||||||
|
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
Path getPluginFolder();
|
Path getPluginFolder();
|
||||||
@ -48,7 +51,7 @@ public interface PlatformPlugin<C> {
|
|||||||
boolean isPluginInstalled(String name);
|
boolean isPluginInstalled(String name);
|
||||||
|
|
||||||
default void sendMultiLineMessage(C receiver, String message) {
|
default void sendMultiLineMessage(C receiver, String message) {
|
||||||
for (String line : message.split("%nl%")) {
|
for (String line : PATTERN.split(message)) {
|
||||||
sendMessage(receiver, line);
|
sendMessage(receiver, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user