mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2026-08-30 17:04:12 +02:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9249c1ea8c | ||
|
|
fd33523189 | ||
|
|
5af43170da | ||
|
|
eb51f0c83c | ||
|
|
5bdf2f4c9e | ||
|
|
155c98d601 | ||
|
|
a8f3155fc5 |
@@ -1,6 +1,6 @@
|
|||||||
name: 🐞 Bug Report
|
name: 🐞 Bug Report
|
||||||
description: Something isn't working, broken, not expected behavior
|
description: Something isn't working, broken, not expected behavior
|
||||||
labels: [ bug ]
|
labels: [bug]
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
@@ -12,6 +12,10 @@ 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
|
||||||
@@ -32,7 +36,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Server log
|
label: Server log
|
||||||
description: The error, stacktrace or link the complete log. You can use the links above for long versions.
|
description: The error, stacktrace or link the complete log. You can use the links above for long versions.
|
||||||
placeholder: https://www.toptal.com/developers/hastebin / https://gist.github.com/
|
placeholder: https://hastebin.com/ / https://gist.github.com/
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: Plugin version
|
label: Plugin version
|
||||||
@@ -55,11 +59,9 @@ body:
|
|||||||
label: Relevance
|
label: Relevance
|
||||||
description: Check list for previous tickets
|
description: Check list for previous tickets
|
||||||
options:
|
options:
|
||||||
- label: |
|
- label: I tried the latest build (build refers to development builds not necessary a release version)
|
||||||
I tried the [latest build](https://ci.codemc.io/job/Games647/job/FastLogin/)
|
|
||||||
(build refers to development builds not necessary a release version; i.e. v1.10 is out of date)
|
|
||||||
required: true
|
required: true
|
||||||
- label: |
|
- label: |
|
||||||
I checked for existing tickets -
|
I checked for existing tickets -
|
||||||
If there are, please vote them with a thumbs reaction and not create new ones
|
If there are, please vote them with a thumps reaction and not create new ones
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
name: 💡 Enhancement request
|
||||||
|
about: New feature or change request
|
||||||
|
title: ''
|
||||||
|
labels: 'enhancement'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[//]: # (Lines in this format are considered as comments and will not be displayed.)
|
||||||
|
[//]: # (Before reporting make sure you're running the **latest build** of the plugin and checked for existing issues!)
|
||||||
|
|
||||||
|
[//]: # (This ticket is about suggestions for a feature or particular enhancement)
|
||||||
|
|
||||||
|
### Is your feature request related to a problem? Please describe.
|
||||||
|
[//]: # (A clear and concise description of what the problem is. Ex. I'm always frustrated when [...])
|
||||||
|
|
||||||
|
### Describe the solution you'd like
|
||||||
|
[//]: # (A clear and concise description of what you want to happen.)
|
||||||
|
|
||||||
|
### Describe alternatives you've considered
|
||||||
|
[//]: # (A clear and concise description of any alternative solutions or features you've considered.)
|
||||||
|
|
||||||
|
### Additional context
|
||||||
|
[//]: # (Add any other context or screenshots about the feature request here.)
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
name: 💡 Enhancement request
|
|
||||||
description: New feature or change request
|
|
||||||
labels: [ enhancement ]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
This ticket is about suggestions for a feature or particular enhancement.
|
|
||||||
Feedback about this form is appreciated.
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Is your feature request related to a problem? Please describe.
|
|
||||||
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Describe the solution you'd like
|
|
||||||
description: A clear and concise description of what you want to happen.
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Describe alternatives you've considered
|
|
||||||
description: A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
- type: dropdown
|
|
||||||
attributes:
|
|
||||||
label: Platform
|
|
||||||
description: Server software - choose your proxy software if you have multiple servers
|
|
||||||
options:
|
|
||||||
- Spigot
|
|
||||||
- BungeeCord
|
|
||||||
- Velocity
|
|
||||||
- All / Shared
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Relevance
|
|
||||||
description: Check list for previous tickets
|
|
||||||
options:
|
|
||||||
- label: |
|
|
||||||
I checked for existing tickets -
|
|
||||||
If there are, please vote them with a thumbs reaction and not create new ones
|
|
||||||
required: true
|
|
||||||
+2
-18
@@ -10,23 +10,7 @@ updates:
|
|||||||
interval: "monthly"
|
interval: "monthly"
|
||||||
|
|
||||||
# Maven project
|
# Maven project
|
||||||
- package-ecosystem: "maven"
|
- package-ecosystem: maven
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "monthly"
|
interval: weekly
|
||||||
|
|
||||||
groups:
|
|
||||||
production-dependencies:
|
|
||||||
dependency-type: "production"
|
|
||||||
development-dependencies:
|
|
||||||
dependency-type: "development"
|
|
||||||
exclude-patterns:
|
|
||||||
# Create single PR for these
|
|
||||||
# Plugin require special evaluation about their compatibility
|
|
||||||
- "com.lenis0012.bukkit:loginsecurity"
|
|
||||||
- "com.comphenix.protocol:ProtocolLib"
|
|
||||||
|
|
||||||
ignore:
|
|
||||||
# HikariCP dropped Java 8 support with 5.0
|
|
||||||
- dependency-name: "com.zaxxer:HikariCP"
|
|
||||||
update-types: ["version-update:semver-major"]
|
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
[//]: # (Lines in this format are considered as comments and will not be displayed.)
|
[//]: # (Lines in this format are considered as comments and will not be displayed.)
|
||||||
|
|
||||||
[//]: # (If your work is in progress, please consider making a draft pull request.)
|
[//]: # (If your work is in progress, please consider making a draft pull request.)
|
||||||
|
|
||||||
### Summary of your change
|
### Summary of your change
|
||||||
|
|
||||||
[//]: # (Example: motivation, enhancement)
|
[//]: # (Example: motivation, enhancement)
|
||||||
|
|
||||||
### Related issue
|
### Related issue
|
||||||
|
|
||||||
[//]: # (Reference it using '#NUMBER'. Ex: Fixes/Related #...)
|
[//]: # (Reference it using '#NUMBER'. Ex: Fixes/Related #...)
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
# Configure how the release notes are generated for GitHub releases
|
|
||||||
|
|
||||||
changelog:
|
|
||||||
# List of authors (like bots) and labels to exclude from pull requests
|
|
||||||
exclude:
|
|
||||||
labels:
|
|
||||||
- ignore-for-release
|
|
||||||
categories:
|
|
||||||
- title: 🛠 Breaking Changes
|
|
||||||
labels:
|
|
||||||
- Semver-Major
|
|
||||||
- breaking-change
|
|
||||||
- title: 🎉 Exciting New Features
|
|
||||||
labels:
|
|
||||||
- Semver-Minor
|
|
||||||
- enhancement
|
|
||||||
- title: 🐞 Bugfixes
|
|
||||||
labels:
|
|
||||||
- bug
|
|
||||||
- title: 👒 Dependencies
|
|
||||||
labels:
|
|
||||||
- dependencies
|
|
||||||
- title: Other Changes
|
|
||||||
labels:
|
|
||||||
- "*"
|
|
||||||
@@ -4,61 +4,63 @@
|
|||||||
name: "CodeQL"
|
name: "CodeQL"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_run:
|
# Scan only for push on the primary branch for now
|
||||||
workflows: ["Maven Build"]
|
push:
|
||||||
branches: [main]
|
branches: [ main ]
|
||||||
types:
|
pull_request:
|
||||||
- completed
|
branches: [ main ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# job i
|
# job i
|
||||||
analyze:
|
analyze:
|
||||||
|
|
||||||
# Display name
|
# Display name
|
||||||
name: Analyze
|
name: Analyze
|
||||||
|
|
||||||
# Environment
|
# Environment
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
# Languages to scan
|
||||||
|
language: [ 'java' ]
|
||||||
|
|
||||||
permissions:
|
steps:
|
||||||
# Only allow write for security, then all others default to read only
|
- name: Checkout repository
|
||||||
security-events: write
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
strategy:
|
# Setup Java
|
||||||
fail-fast: true
|
- name: Set up JDK
|
||||||
matrix:
|
uses: actions/setup-java@v3
|
||||||
# Languages to scan
|
with:
|
||||||
language: [ 'java' ]
|
distribution: 'temurin'
|
||||||
|
java-version: 18
|
||||||
|
cache: 'maven'
|
||||||
|
|
||||||
steps:
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Checkout repository
|
- name: Initialize CodeQL
|
||||||
uses: actions/checkout@v4
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Cache build process too like in the maven config
|
||||||
- name: Initialize CodeQL
|
- uses: actions/cache@v3.0.4
|
||||||
uses: github/codeql-action/init@v3
|
with:
|
||||||
with:
|
path: ~/.m2/repository
|
||||||
languages: ${{ matrix.language }}
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-maven-
|
||||||
|
|
||||||
# Setup Java
|
# Auto build attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
- name: Set up JDK
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
uses: actions/setup-java@v4
|
- name: Autobuild
|
||||||
with:
|
uses: github/codeql-action/autobuild@v2
|
||||||
distribution: 'temurin'
|
|
||||||
java-version-file: '.java-version'
|
|
||||||
cache: 'maven'
|
|
||||||
|
|
||||||
# Manually start the autobuild process, because autobuild always selects Java 8 as build toolchain, but
|
- name: Perform CodeQL Analysis
|
||||||
# we are doing cross-crompiling from a newer Java version
|
uses: github/codeql-action/analyze@v2
|
||||||
- name: Build with Maven
|
|
||||||
# Extracted from autobuild
|
|
||||||
run: mvn package -f "pom.xml" --batch-mode -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip -DskipTests -Dmaven.test.skip.exec -Dlicense.skip=true -Drat.skip=true -Dspotless.check.skip=true -t /home/runner/.m2/toolchains.xml
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v3
|
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
||||||
|
|||||||
+28
-53
@@ -2,66 +2,41 @@
|
|||||||
# including making pull requests review easier
|
# including making pull requests review easier
|
||||||
|
|
||||||
# Human-readable name in the actions tab
|
# Human-readable name in the actions tab
|
||||||
name: Maven Build
|
name: Java CI
|
||||||
|
|
||||||
# Build on every pull request regardless of the branch
|
# Build on every pull request regardless of the branch
|
||||||
# Wiki: https://help.github.com/en/actions/reference/events-that-trigger-workflows
|
# Wiki: https://help.github.com/en/actions/reference/events-that-trigger-workflows
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# job id
|
# job id
|
||||||
build_and_test:
|
build_and_test:
|
||||||
|
|
||||||
# Environment image - always use the newest OS
|
# Environment image - always use the newest OS
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
|
||||||
# With at least one permission given, all default to read
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
# Run steps
|
# Run steps
|
||||||
steps:
|
steps:
|
||||||
# Pull changes
|
# Pull changes
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
# Setup Java
|
# Setup Java
|
||||||
- name: Set up JDK
|
- name: Set up JDK
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version-file: '.java-version'
|
java-version: 18
|
||||||
cache: 'maven'
|
cache: 'maven'
|
||||||
|
|
||||||
# Build and test (included in package)
|
# Build and test (included in package)
|
||||||
- name: Build with Maven and test
|
- name: Build with Maven and test
|
||||||
# Run non-interactive, package (with compile+test),
|
# Run non-interactive, package (with compile+test),
|
||||||
# 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 to validate
|
||||||
run: mvn test --batch-mode --threads 2.0C --no-snapshot-updates --strict-checksums --file pom.xml
|
# possible errors in dependencies
|
||||||
|
run: mvn test --batch-mode --threads 2.0C --no-snapshot-updates --strict-checksums --file pom.xml
|
||||||
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' }}
|
|
||||||
uses: advanced-security/maven-dependency-submission-action@v5.0.0
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
# Latest GitHub Action java release that is installed on the runners
|
|
||||||
21
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
# Contributing Guide
|
|
||||||
|
|
||||||
## Architectural overview
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
graph TB
|
|
||||||
subgraph "Minecraft Server Platforms"
|
|
||||||
SPIGOT["Spigot/Paper<br/>(Bukkit Module)"]
|
|
||||||
BUNGEE["BungeeCord<br/>(Proxy Module)"]
|
|
||||||
VELOCITY["Velocity<br/>(Velocity Module)"]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph "FastLogin Core"
|
|
||||||
CORE["FastLoginCore<br/>Main Logic Engine"]
|
|
||||||
SESSION["LoginSession<br/>Session Management"]
|
|
||||||
AUTH["AuthPlugin Hook<br/>Auth Integration"]
|
|
||||||
RESOLVER["ProxyAgnosticMojangResolver<br/>Profile Resolution"]
|
|
||||||
STORAGE["SQLStorage<br/>Database Layer"]
|
|
||||||
ANTIBOT["AntiBotService<br/>Rate Limiting"]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph "Bedrock Support"
|
|
||||||
FLOODGATE["FloodgateManagement<br/>Bedrock Players"]
|
|
||||||
GEYSER["GeyserService<br/>Geyser Integration"]
|
|
||||||
BEDROCK["BedrockService<br/>Base Service"]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph "External Services"
|
|
||||||
MOJANG["Mojang API<br/>api.mojang.com"]
|
|
||||||
SESSION_SERVER["Session Server<br/>sessionserver.mojang.com"]
|
|
||||||
DATABASE[(SQL Database<br/>MySQL/SQLite)]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph "Async Processing"
|
|
||||||
SCHEDULER["AbstractAsyncScheduler<br/>Thread Pool Management"]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph "Messaging"
|
|
||||||
MESSAGES["ChannelMessage<br/>Proxy Messages <br/>(i.e. BungeeCord)"]
|
|
||||||
NAMEKEY["NamespaceKey<br/>Message Routing"]
|
|
||||||
end
|
|
||||||
|
|
||||||
SPIGOT -->|loads| CORE
|
|
||||||
BUNGEE -->|loads| CORE
|
|
||||||
VELOCITY -->|loads| CORE
|
|
||||||
|
|
||||||
CORE -->|manages| SESSION
|
|
||||||
CORE -->|uses| AUTH
|
|
||||||
CORE -->|resolves profiles| RESOLVER
|
|
||||||
CORE -->|persists data| STORAGE
|
|
||||||
CORE -->|checks rate limits| ANTIBOT
|
|
||||||
CORE -->|handles bedrock| FLOODGATE
|
|
||||||
|
|
||||||
FLOODGATE -->|extends| BEDROCK
|
|
||||||
GEYSER -->|extends| BEDROCK
|
|
||||||
|
|
||||||
RESOLVER -->|queries| MOJANG
|
|
||||||
RESOLVER -->|verifies| SESSION_SERVER
|
|
||||||
|
|
||||||
STORAGE -->|connects to| DATABASE
|
|
||||||
|
|
||||||
CORE -->|schedules async| SCHEDULER
|
|
||||||
|
|
||||||
MESSAGES -->|uses| NAMEKEY
|
|
||||||
CORE -->|sends via| MESSAGES
|
|
||||||
|
|
||||||
AUTH -.->|delegates to| SPIGOT
|
|
||||||
AUTH -.->|delegates to| BUNGEE
|
|
||||||
|
|
||||||
ANTIBOT -->|rate limits| RESOLVER
|
|
||||||
```
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015-2024 games647 and contributors
|
Copyright (c) 2015-2022 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
|
||||||
@@ -19,3 +19,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
# FastLogin
|
# FastLogin
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Checks if a Minecraft player has a paid account (premium). If so, they can skip offline authentication (auth plugins).
|
Checks if a Minecraft player has a paid account (premium). If so, they can skip offline authentication (auth plugins).
|
||||||
So they don't need to enter passwords. This is also called auto login (auto-login).
|
So they don't need to enter passwords. This is also called auto login (auto-login).
|
||||||
|
|
||||||
@@ -10,11 +8,14 @@ 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/Velocity support
|
* BungeeCord 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
|
||||||
@@ -32,42 +33,10 @@ Development builds contain the latest changes from the Source-Code. They are ble
|
|||||||
but also include features, enhancements and bug fixes that are not yet in a released version. If you click on the left
|
but also include features, enhancements and bug fixes that are not yet in a released version. If you click on the left
|
||||||
side on `Changes`, you can see iterative change sets leading to a specific build.
|
side on `Changes`, you can see iterative change sets leading to a specific build.
|
||||||
|
|
||||||
You can download them from here: [CodeMC(Jenkins)](https://ci.codemc.org/job/Games647/job/FastLogin/)
|
You can download them from here: https://ci.codemc.org/job/Games647/job/FastLogin/
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
## Technical Authentication
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
sequenceDiagram
|
|
||||||
autonumber
|
|
||||||
participant C as Client
|
|
||||||
participant S as Server
|
|
||||||
participant M as Mojang
|
|
||||||
|
|
||||||
C->>S: LOGIN_START (name)
|
|
||||||
Note over S: DB: check if username is saved as premium
|
|
||||||
S->>C: ENCRYPTION_REQUEST
|
|
||||||
Note right of C: Offline clients terminates connection here
|
|
||||||
Note right of C: In Offlinemode: LOGIN_SUCCESS is sent directly
|
|
||||||
|
|
||||||
rect rgb(240, 240, 240)
|
|
||||||
C->>M: POST /session/minecraft/join
|
|
||||||
C->>S: ENCRYPTION_RESPONSE
|
|
||||||
Note right of C: Client starts encrypting
|
|
||||||
end
|
|
||||||
|
|
||||||
Note over S: Decrypt and verify token
|
|
||||||
S->>M: GET /hasJoined (async)
|
|
||||||
M->>S: {uuid, name, skin}
|
|
||||||
|
|
||||||
Note over S: Server encrypts traffic
|
|
||||||
Note over S: Inject skin and premium UUID
|
|
||||||
S->>S: Re-inject LOGIN_START(name)
|
|
||||||
|
|
||||||
S->>C: LOGIN_SUCCESS
|
|
||||||
```
|
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
/premium [player] Label the invoker or the argument as paid account
|
/premium [player] Label the invoker or the argument as paid account
|
||||||
@@ -77,7 +46,6 @@ sequenceDiagram
|
|||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -92,15 +60,13 @@ Possible values: `Premium`, `Cracked`, `Unknown`
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
* Java: 21+ recommended for improved multi-threading code by FastLogin
|
* Java 17+
|
||||||
* 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.3+ with development build above 720](https://www.spigotmc.org/resources/protocollib.1997/) or
|
* [ProtocolLib 5.0+](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 proxy
|
* Latest BungeeCord (or a fork e.g. Waterfall)
|
||||||
* An auth plugin.
|
* An auth plugin.
|
||||||
|
|
||||||
### Supported auth plugins
|
### Supported auth plugins
|
||||||
@@ -119,6 +85,7 @@ 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
|
||||||
|
|
||||||
@@ -134,8 +101,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 `FastLoginBukkit`
|
2. Download and install FastLogin (or `FastLoginBukkit` for newer versions)
|
||||||
3. Set your server in offline mode by setting the value `onlinemode` in your server.properties to `false`
|
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
|
||||||
|
|
||||||
@@ -145,13 +112,13 @@ Install the plugin on both platforms, that is proxy (BungeeCord or Velocity) and
|
|||||||
* This is often found in `spigot.yml` or `paper.yml`
|
* This is often found in `spigot.yml` or `paper.yml`
|
||||||
2. Restart the backend server
|
2. Restart the backend server
|
||||||
3. Now there is `allowed-proxies.txt` file in the FastLogin folder of the restarted server
|
3. Now there is `allowed-proxies.txt` file in the FastLogin folder of the restarted server
|
||||||
* BungeeCord: Put your `stats`-id from the BungeeCord config into this file
|
* BungeeCord: Put your `stats-id` from the BungeeCord config into this file
|
||||||
* Velocity: On plugin startup the plugin generates a `proxyId.txt` inside the plugins folder of the proxy
|
* Velocity: On plugin startup the plugin generates a `proxyId.txt` inside the plugins folder of the proxy
|
||||||
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: `mysql` for MySQL/MariaDB
|
* BungeeCord: `com.mysql.jdbc.Driver` for MySQL/MariaDB
|
||||||
* Velocity: `mariadb` for MySQL/MariaDB
|
* Velocity: `fastlogin.mariadb.jdbc.Driver` 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.
|
||||||
|
|||||||
+53
-58
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015-2024 games647 and contributors
|
Copyright (c) 2015-2022 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,12 +25,12 @@
|
|||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.release>8</maven.compiler.release>
|
<nettyVersion>4.1.77.Final</nettyVersion>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
@@ -50,15 +50,11 @@
|
|||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.6.0</version>
|
<version>3.3.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||||
<relocations>
|
<relocations>
|
||||||
<relocation>
|
|
||||||
<pattern>org.yaml.snakeyaml</pattern>
|
|
||||||
<shadedPattern>fastlogin.yaml</shadedPattern>
|
|
||||||
</relocation>
|
|
||||||
<relocation>
|
<relocation>
|
||||||
<pattern>com.zaxxer.hikari</pattern>
|
<pattern>com.zaxxer.hikari</pattern>
|
||||||
<shadedPattern>fastlogin.hikari</shadedPattern>
|
<shadedPattern>fastlogin.hikari</shadedPattern>
|
||||||
@@ -90,14 +86,14 @@
|
|||||||
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
|
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
|
||||||
<!-- Located in META-INF/services -->
|
<!-- Located in META-INF/services -->
|
||||||
<transformers>
|
<transformers>
|
||||||
<transformer
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||||
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
|
||||||
</transformers>
|
</transformers>
|
||||||
<minimizeJar>true</minimizeJar>
|
<minimizeJar>true</minimizeJar>
|
||||||
<filters>
|
<filters>
|
||||||
<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>
|
||||||
@@ -116,10 +112,10 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<!-- PaperSpigot API, PaperLib, datafixupper and bungeecord-chat -->
|
<!-- PaperSpigot API and PaperLib -->
|
||||||
<repository>
|
<repository>
|
||||||
<id>papermc</id>
|
<id>papermc</id>
|
||||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
|
||||||
<!-- ProtocolLib -->
|
<!-- ProtocolLib -->
|
||||||
@@ -168,7 +164,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.papermc.paper</groupId>
|
<groupId>io.papermc.paper</groupId>
|
||||||
<artifactId>paper-api</artifactId>
|
<artifactId>paper-api</artifactId>
|
||||||
<version>1.21.6-R0.1-SNAPSHOT</version>
|
<version>1.19-R0.1-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<!-- Use our own newer api version -->
|
<!-- Use our own newer api version -->
|
||||||
<exclusions>
|
<exclusions>
|
||||||
@@ -176,25 +172,20 @@
|
|||||||
<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>
|
||||||
|
|
||||||
|
<!-- PaperLib for checking if server uses PaperSpigot -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.papermc</groupId>
|
||||||
|
<artifactId>paperlib</artifactId>
|
||||||
|
<version>1.0.7</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mojang</groupId>
|
<groupId>com.mojang</groupId>
|
||||||
<artifactId>datafixerupper</artifactId>
|
<artifactId>datafixerupper</artifactId>
|
||||||
<version>7.1.15</version>
|
<version>5.0.28</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
@@ -208,7 +199,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.comphenix.protocol</groupId>
|
<groupId>com.comphenix.protocol</groupId>
|
||||||
<artifactId>ProtocolLib</artifactId>
|
<artifactId>ProtocolLib</artifactId>
|
||||||
<version>5.3.0</version>
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
@@ -237,11 +228,15 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.geysermc.floodgate</groupId>
|
<groupId>org.geysermc.floodgate</groupId>
|
||||||
<artifactId>api</artifactId>
|
<artifactId>api</artifactId>
|
||||||
<version>${floodgate.version}</version>
|
<version>2.2.0-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>*</groupId>
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.geysermc.cumulus</groupId>
|
||||||
<artifactId>*</artifactId>
|
<artifactId>*</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
@@ -249,7 +244,7 @@
|
|||||||
|
|
||||||
<!-- Bedrock player bridge -->
|
<!-- Bedrock player bridge -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.geysermc.geyser</groupId>
|
<groupId>org.geysermc</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>${geyser.version}</version>
|
<version>${geyser.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
@@ -263,23 +258,17 @@
|
|||||||
|
|
||||||
<!-- We need the API, but it was excluded above -->
|
<!-- We need the API, but it was excluded above -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.geysermc.geyser</groupId>
|
<groupId>org.geysermc</groupId>
|
||||||
<artifactId>api</artifactId>
|
<artifactId>geyser-api</artifactId>
|
||||||
<version>${geyser.version}</version>
|
<version>${geyser.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>*</groupId>
|
|
||||||
<artifactId>*</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--Provide premium placeholders-->
|
<!--Provide premium placeholders-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>me.clip</groupId>
|
<groupId>me.clip</groupId>
|
||||||
<artifactId>placeholderapi</artifactId>
|
<artifactId>placeholderapi</artifactId>
|
||||||
<version>2.11.6</version>
|
<version>2.11.2</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
@@ -294,7 +283,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>fr.xephi</groupId>
|
<groupId>fr.xephi</groupId>
|
||||||
<artifactId>authme</artifactId>
|
<artifactId>authme</artifactId>
|
||||||
<version>5.6.0</version>
|
<version>5.6.0-beta2</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
@@ -308,7 +297,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.lenis0012.bukkit</groupId>
|
<groupId>com.lenis0012.bukkit</groupId>
|
||||||
<artifactId>loginsecurity</artifactId>
|
<artifactId>loginsecurity</artifactId>
|
||||||
<version>3.3.0</version>
|
<version>3.1</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
@@ -348,22 +337,6 @@
|
|||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.zigazajc007</groupId>
|
|
||||||
<artifactId>Passky</artifactId>
|
|
||||||
<version>v3.0.0</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
<optional>true</optional>
|
|
||||||
|
|
||||||
<!-- Exclude dependencies to prevent potential version conflicts-->
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>*</groupId>
|
|
||||||
<artifactId>*</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!--No maven repository :(-->
|
<!--No maven repository :(-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.st_ddt.crazy</groupId>
|
<groupId>de.st_ddt.crazy</groupId>
|
||||||
@@ -395,7 +368,29 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bouncycastle</groupId>
|
<groupId>org.bouncycastle</groupId>
|
||||||
<artifactId>bcprov-jdk18on</artifactId>
|
<artifactId>bcprov-jdk18on</artifactId>
|
||||||
<version>1.80</version>
|
<version>1.71</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-transport</artifactId>
|
||||||
|
<version>${nettyVersion}</version>
|
||||||
|
<scope>test</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-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,15 +27,16 @@ 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.listener.protocollib.packet.ClientPublicKey;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
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 org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a client connecting to the server.
|
* Represents a client connecting to the server.
|
||||||
* <p>
|
*
|
||||||
* This session is invalid if the player disconnects or the login was successful
|
* This session is invalid if the player disconnects or the login was successful
|
||||||
*/
|
*/
|
||||||
public class BukkitLoginSession extends LoginSession {
|
public class BukkitLoginSession extends LoginSession {
|
||||||
@@ -47,6 +48,7 @@ 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,
|
||||||
@@ -74,7 +76,7 @@ public class BukkitLoginSession extends LoginSession {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the verify-token the server sent to the client.
|
* Gets the verify-token the server sent to the client.
|
||||||
* <p>
|
*
|
||||||
* Empty if it's a BungeeCord connection
|
* Empty if it's a BungeeCord connection
|
||||||
*
|
*
|
||||||
* @return verify token from the server
|
* @return verify token from the server
|
||||||
@@ -108,7 +110,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 setVerifiedPremium(boolean verified) {
|
public synchronized void setVerified(boolean verified) {
|
||||||
this.verified = verified;
|
this.verified = verified;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +119,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 isVerifiedPremium() {
|
public synchronized boolean isVerified() {
|
||||||
return verified;
|
return verified;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,13 +25,14 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.scheduler.AsyncScheduler;
|
import com.github.games647.fastlogin.core.AsyncScheduler;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
public class BukkitScheduler extends AsyncScheduler {
|
public class BukkitScheduler extends AsyncScheduler {
|
||||||
|
|
||||||
private final Executor syncExecutor;
|
private final Executor syncExecutor;
|
||||||
@@ -39,7 +40,7 @@ public class BukkitScheduler extends AsyncScheduler {
|
|||||||
public BukkitScheduler(Plugin plugin, Logger logger) {
|
public BukkitScheduler(Plugin plugin, Logger logger) {
|
||||||
super(logger, command -> Bukkit.getScheduler().runTaskAsynchronously(plugin, command));
|
super(logger, command -> Bukkit.getScheduler().runTaskAsynchronously(plugin, command));
|
||||||
|
|
||||||
syncExecutor = task -> Bukkit.getScheduler().runTask(plugin, task);
|
syncExecutor = r -> Bukkit.getScheduler().runTask(plugin, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Executor getSyncExecutor() {
|
public Executor getSyncExecutor() {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -31,11 +31,6 @@ import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
|||||||
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
||||||
import com.google.common.io.ByteArrayDataOutput;
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import io.papermc.paper.configuration.ServerConfiguration;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Server;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.plugin.messaging.PluginMessageRecipient;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@@ -49,6 +44,11 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.messaging.PluginMessageRecipient;
|
||||||
|
|
||||||
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;
|
import static java.util.stream.Collectors.toSet;
|
||||||
@@ -94,10 +94,6 @@ public class BungeeManager {
|
|||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
proxyIds = loadBungeeCordIds();
|
proxyIds = loadBungeeCordIds();
|
||||||
if (proxyIds.isEmpty()) {
|
|
||||||
plugin.getLog().info("No valid IDs found. Minecraft proxy support cannot work in the current state");
|
|
||||||
}
|
|
||||||
|
|
||||||
registerPluginChannels();
|
registerPluginChannels();
|
||||||
plugin.getLog().info("Found enabled proxy configuration");
|
plugin.getLog().info("Found enabled proxy configuration");
|
||||||
plugin.getLog().info("Remember to follow the proxy guide to complete your setup");
|
plugin.getLog().info("Remember to follow the proxy guide to complete your setup");
|
||||||
@@ -134,13 +130,6 @@ public class BungeeManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean detectProxy() {
|
private boolean detectProxy() {
|
||||||
try {
|
|
||||||
ServerConfiguration.class.getDeclaredMethod("isProxyEnabled");
|
|
||||||
return Bukkit.getServerConfig().isProxyEnabled();
|
|
||||||
} catch (NoClassDefFoundError | NoSuchMethodException noSuchClassMethodEx) {
|
|
||||||
// Ignore continue below
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isProxySupported("org.spigotmc.SpigotConfig", "bungee")) {
|
if (isProxySupported("org.spigotmc.SpigotConfig", "bungee")) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,24 +25,33 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit;
|
||||||
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
|
||||||
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.command.DeleteCommand;
|
|
||||||
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
|
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.PaperCacheListener;
|
import com.github.games647.fastlogin.bukkit.listener.PaperCacheListener;
|
||||||
|
import com.github.games647.fastlogin.bukkit.listener.protocollib.ManualNameChange;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
|
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.SkinApplyListener;
|
import com.github.games647.fastlogin.bukkit.listener.protocollib.SkinApplyListener;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
|
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
|
||||||
import com.github.games647.fastlogin.bukkit.task.DelayedAuthHook;
|
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.antibot.AntiBotService;
|
|
||||||
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
||||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
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 io.papermc.lib.PaperLib;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
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;
|
||||||
@@ -50,28 +59,15 @@ import org.bukkit.plugin.PluginManager;
|
|||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This plugin checks if a player has a paid account and if so tries to skip offline mode authentication.
|
* This plugin checks if a player has a paid account and if so tries to skip offline mode authentication.
|
||||||
*/
|
*/
|
||||||
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(
|
private final ConcurrentMap<String, BukkitLoginSession> loginSession = CommonUtil.buildCache(1, -1);
|
||||||
Duration.ofMinutes(1), -1
|
|
||||||
);
|
|
||||||
|
|
||||||
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
|
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
@@ -117,14 +113,17 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AntiBotService antiBotService = core.getAntiBotService();
|
|
||||||
if (pluginManager.isPluginEnabled("ProtocolSupport")) {
|
if (pluginManager.isPluginEnabled("ProtocolSupport")) {
|
||||||
pluginManager.registerEvents(new ProtocolSupportListener(this, antiBotService), this);
|
pluginManager.registerEvents(new ProtocolSupportListener(this, core.getAntiBot()), this);
|
||||||
} else if (pluginManager.isPluginEnabled("ProtocolLib")) {
|
} else if (pluginManager.isPluginEnabled("ProtocolLib")) {
|
||||||
ProtocolLibListener.register(this, antiBotService, core.getConfig().getBoolean("verifyClientKeys"));
|
ProtocolLibListener.register(this, core.getAntiBot(), core.getConfig().getBoolean("verifyClientKeys"));
|
||||||
|
|
||||||
|
if (isPluginInstalled("floodgate")) {
|
||||||
|
printFloodgateWarning();
|
||||||
|
}
|
||||||
|
|
||||||
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
|
//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")) {
|
if (!PaperLib.isPaper() && getConfig().getBoolean("forwardSkin")) {
|
||||||
pluginManager.registerEvents(new SkinApplyListener(this), this);
|
pluginManager.registerEvents(new SkinApplyListener(this), this);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -140,23 +139,35 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
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
|
//if server is using paper - we need to add one more listener to correct the user cache usage
|
||||||
if (isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
pluginManager.registerEvents(new PaperCacheListener(this), this);
|
pluginManager.registerEvents(new PaperCacheListener(this), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)));
|
||||||
|
|
||||||
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
|
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
|
||||||
premiumPlaceholder = new PremiumPlaceholder(this);
|
premiumPlaceholder = new PremiumPlaceholder(this);
|
||||||
premiumPlaceholder.register();
|
premiumPlaceholder.register();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencyWarnings();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommands() {
|
private void printFloodgateWarning() {
|
||||||
//register commands using a unique name
|
if (getConfig().getBoolean("floodgatePrefixWorkaround")) {
|
||||||
Optional.ofNullable(getCommand("premium")).ifPresent(c -> c.setExecutor(new PremiumCommand(this)));
|
ManualNameChange.register(this, floodgateService);
|
||||||
Optional.ofNullable(getCommand("cracked")).ifPresent(c -> c.setExecutor(new CrackedCommand(this)));
|
logger.info("Floodgate prefix injection workaround has been enabled.");
|
||||||
Optional.ofNullable(getCommand("fldelete")).ifPresent(c -> c.setExecutor(new DeleteCommand(this)));
|
logger.info("If you have problems joining the server, try disabling it in the configuration.");
|
||||||
|
} else {
|
||||||
|
logger.warn("We have detected that you are running FastLogin alongside Floodgate and ProtocolLib.");
|
||||||
|
logger.warn("Currently there is an issue with FastLogin that prevents Floodgate name prefixes from "
|
||||||
|
+ "showing up when it is together used with ProtocolLib.");
|
||||||
|
logger.warn("If you would like to use Floodgate name prefixes, you can enable an experimental "
|
||||||
|
+ "workaround by changing the value 'floodgatePrefixWorkaround' to true in config.yml.");
|
||||||
|
logger.warn("For more information visit https://github.com/games647/FastLogin/issues/493");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean initializeFloodgate() {
|
private boolean initializeFloodgate() {
|
||||||
@@ -196,9 +207,9 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getServer().getPluginManager().isPluginEnabled("ProtocolLib")) {
|
// if (isPluginInstalled("ProtocolLib")) {
|
||||||
ProtocolLibrary.getProtocolManager().getAsynchronousManager().unregisterAsyncHandlers(this);
|
// ProtocolLibrary.getProtocolManager().getAsynchronousManager().unregisterAsyncHandlers(this);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public FastLoginCore<Player, CommandSender, FastLoginBukkit> getCore() {
|
public FastLoginCore<Player, CommandSender, FastLoginBukkit> getCore() {
|
||||||
@@ -240,28 +251,12 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the premium status of an online player.
|
* Fetches the premium status of an online player.
|
||||||
* {@snippet :
|
|
||||||
* // Bukkit's players object after successful authentication i.e. PlayerJoinEvent
|
|
||||||
* // except for proxies like BungeeCord and Velocity where the details are sent delayed (1-2 seconds)
|
|
||||||
* Player player;
|
|
||||||
* PremiumStatus status = JavaPlugin.getPlugin(FastLoginBukkit.class).getStatus(player.getUniqueId());
|
|
||||||
* switch (status) {
|
|
||||||
* case CRACKED:
|
|
||||||
* // player is offline
|
|
||||||
* break;
|
|
||||||
* case PREMIUM:
|
|
||||||
* // account is premium and player passed the verification
|
|
||||||
* break;
|
|
||||||
* case UNKNOWN:
|
|
||||||
* // no record about this player
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
*
|
||||||
* @param onlinePlayer player that is currently online player (play state)
|
* @param onlinePlayer player that is currently online player (play state)
|
||||||
* @return the online status or unknown if an error happened, the player isn't online or BungeeCord doesn't send
|
* @return the online status or unknown if an error happened, the player isn't online or BungeeCord doesn't send
|
||||||
* us the status message yet (This means you cannot check the login status on the PlayerJoinEvent).
|
* us the status message yet (This means you cannot check the login status on the PlayerJoinEvent).
|
||||||
*/
|
*/
|
||||||
public @NotNull PremiumStatus getStatus(@NotNull UUID onlinePlayer) {
|
public PremiumStatus getStatus(UUID onlinePlayer) {
|
||||||
return premiumPlayers.getOrDefault(onlinePlayer, PremiumStatus.UNKNOWN);
|
return premiumPlayers.getOrDefault(onlinePlayer, PremiumStatus.UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,16 +326,17 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
return geyserService;
|
return geyserService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPaper() {
|
/**
|
||||||
return isClassAvailable("com.destroystokyo.paper.PaperConfig").isPresent()
|
* Send warning messages to log if incompatible plugins are used
|
||||||
|| isClassAvailable("io.papermc.paper.configuration.Configuration").isPresent();
|
*/
|
||||||
}
|
private void dependencyWarnings() {
|
||||||
|
if (isPluginInstalled("floodgate-bukkit")) {
|
||||||
private Optional<Class<?>> isClassAvailable(String clazzName) {
|
logger.warn("We have detected that you are running Floodgate 1.0 which is not supported by the Bukkit "
|
||||||
try {
|
+ "version of FastLogin.");
|
||||||
return Optional.of(Class.forName(clazzName));
|
logger.warn("If you would like to use FastLogin with Floodgate, you can download development builds of "
|
||||||
} catch (ClassNotFoundException e) {
|
+ "Floodgate 2.0 from https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/dev%252F2.0/");
|
||||||
return Optional.empty();
|
logger.warn("Don't forget to update Geyser to a supported version as well from "
|
||||||
|
+ "https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/floodgate-2.0/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
|
|
||||||
public final class InetUtils {
|
|
||||||
|
|
||||||
private InetUtils() {
|
|
||||||
// Utility
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies if the given IP address is from the local network
|
|
||||||
*
|
|
||||||
* @param address IP address
|
|
||||||
* @return true if address is from local network or even from the device itself (loopback)
|
|
||||||
*/
|
|
||||||
public static boolean isLocalAddress(InetAddress address) {
|
|
||||||
// Loopback addresses like 127.0.* (IPv4) or [::1] (IPv6)
|
|
||||||
return address.isLoopbackAddress()
|
|
||||||
// Example: 10.0.0.0, 172.16.0.0, 192.168.0.0, fec0::/10 (deprecated)
|
|
||||||
// Ref: https://en.wikipedia.org/wiki/IP_address#Private_addresses
|
|
||||||
|| address.isSiteLocalAddress()
|
|
||||||
// Example: 169.254.0.0/16, fe80::/10
|
|
||||||
// Ref: https://en.wikipedia.org/wiki/IP_address#Address_autoconfiguration
|
|
||||||
|| address.isLinkLocalAddress()
|
|
||||||
// non deprecated unique site-local that java doesn't check yet -> fc00::/7
|
|
||||||
|| isIPv6UniqueSiteLocal(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isIPv6UniqueSiteLocal(InetAddress address) {
|
|
||||||
// ref: https://en.wikipedia.org/wiki/Unique_local_address
|
|
||||||
|
|
||||||
// currently undefined but could be used in the near future fc00::/8
|
|
||||||
return (address.getAddress()[0] & 0xFF) == 0xFC
|
|
||||||
// in use for unique site-local fd00::/8
|
|
||||||
|| (address.getAddress()[0] & 0xFF) == 0xFD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,13 +25,14 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit;
|
||||||
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
|
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class PremiumPlaceholder extends PlaceholderExpansion {
|
public class PremiumPlaceholder extends PlaceholderExpansion {
|
||||||
|
|
||||||
private static final String PLACEHOLDER_VARIABLE = "status";
|
private static final String PLACEHOLDER_VARIABLE = "status";
|
||||||
@@ -74,13 +75,11 @@ 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-19
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,10 +27,10 @@ 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.event.BukkitFastLoginPremiumToggleEvent;
|
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPremiumToggleEvent;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import static com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
|
import static com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
|
||||||
@@ -58,31 +58,21 @@ public class CrackedCommand extends ToggleCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Player player = (Player) sender;
|
|
||||||
if (forwardCrackedCommand(sender, sender.getName())) {
|
if (forwardCrackedCommand(sender, sender.getName())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.isOnlinemodePreferred()) {
|
if (profile.isPremium()) {
|
||||||
plugin.getCore().sendLocaleMessage("remove-premium", sender);
|
plugin.getCore().sendLocaleMessage("remove-premium", sender);
|
||||||
|
|
||||||
profile.setOnlinemodePreferred(false);
|
profile.setPremium(false);
|
||||||
profile.setId(null);
|
profile.setId(null);
|
||||||
plugin.getScheduler().runAsync(() -> {
|
plugin.getScheduler().runAsync(() -> {
|
||||||
plugin.getCore().getStorage().save(profile);
|
plugin.getCore().getStorage().save(profile);
|
||||||
plugin.getServer().getPluginManager().callEvent(
|
plugin.getServer().getPluginManager().callEvent(
|
||||||
new BukkitFastLoginPremiumToggleEvent(sender, profile, PremiumToggleReason.COMMAND_OTHER)
|
new BukkitFastLoginPremiumToggleEvent(profile, PremiumToggleReason.COMMAND_OTHER));
|
||||||
);
|
|
||||||
|
|
||||||
plugin.getScheduler().getSyncExecutor().execute(() -> {
|
|
||||||
if (plugin.getCore().getConfig().getBoolean("kick-toggle", true)) {
|
|
||||||
player.kickPlayer(plugin.getCore().getMessage("remove-premium"));
|
|
||||||
} else {
|
|
||||||
plugin.getCore().sendLocaleMessage("add-premium", sender);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
plugin.getCore().sendLocaleMessage("not-premium", sender);
|
plugin.getCore().sendLocaleMessage("not-premium", sender);
|
||||||
@@ -106,16 +96,16 @@ public class CrackedCommand extends ToggleCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//existing player is already cracked
|
//existing player is already cracked
|
||||||
if (profile.isExistingPlayer() && !profile.isOnlinemodePreferred()) {
|
if (profile.isSaved() && !profile.isPremium()) {
|
||||||
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.setOnlinemodePreferred(false);
|
profile.setPremium(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(
|
||||||
new BukkitFastLoginPremiumToggleEvent(sender, profile, PremiumToggleReason.COMMAND_OTHER));
|
new BukkitFastLoginPremiumToggleEvent(profile, PremiumToggleReason.COMMAND_OTHER));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.command;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.command.ConsoleCommandSender;
|
|
||||||
import org.bukkit.command.TabExecutor;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
|
||||||
|
|
||||||
public class DeleteCommand implements TabExecutor {
|
|
||||||
private final FastLoginBukkit plugin;
|
|
||||||
|
|
||||||
public DeleteCommand(FastLoginBukkit plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the command to delete profiles.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
|
||||||
|
|
||||||
if (!sender.hasPermission(command.getPermission())) {
|
|
||||||
plugin.getCore().sendLocaleMessage("no-permission", sender);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.getBungeeManager().isEnabled()) {
|
|
||||||
sender.sendMessage("Error: Cannot delete profile entries when using BungeeCord!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length < 1) {
|
|
||||||
sender.sendMessage("Error: Must supply username to delete!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
|
||||||
int count = plugin.getCore().getStorage().deleteProfile(args[0]);
|
|
||||||
if (!(sender instanceof ConsoleCommandSender)) {
|
|
||||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
|
||||||
if (count == 0) {
|
|
||||||
sender.sendMessage("Error: No profile entries found!");
|
|
||||||
} else {
|
|
||||||
sender.sendMessage("Deleted " + count + " matching profile entries");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
|
||||||
List<String> list = new ArrayList<>();
|
|
||||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
|
||||||
if (p.getName().toLowerCase().startsWith(args[0])) {
|
|
||||||
list.add(p.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+14
-22
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,15 +27,16 @@ 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.event.BukkitFastLoginPremiumToggleEvent;
|
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPremiumToggleEvent;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
|
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Let users activate fast login by command. This only be accessible if
|
* Let users activate fast login by command. This only be accessible if
|
||||||
* the user has access to its account. So we can make sure that not another
|
* the user has access to its account. So we can make sure that not another
|
||||||
@@ -68,8 +69,7 @@ public class PremiumCommand extends ToggleCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Player player = (Player) sender;
|
UUID id = ((Player) sender).getUniqueId();
|
||||||
UUID id = player.getUniqueId();
|
|
||||||
if (plugin.getConfig().getBoolean("premium-warning") && !plugin.getCore().getPendingConfirms().contains(id)) {
|
if (plugin.getConfig().getBoolean("premium-warning") && !plugin.getCore().getPendingConfirms().contains(id)) {
|
||||||
sender.sendMessage(plugin.getCore().getMessage("premium-warning"));
|
sender.sendMessage(plugin.getCore().getMessage("premium-warning"));
|
||||||
plugin.getCore().getPendingConfirms().add(id);
|
plugin.getCore().getPendingConfirms().add(id);
|
||||||
@@ -79,25 +79,18 @@ public class PremiumCommand extends ToggleCommand {
|
|||||||
plugin.getCore().getPendingConfirms().remove(id);
|
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.isOnlinemodePreferred()) {
|
if (profile.isPremium()) {
|
||||||
plugin.getCore().sendLocaleMessage("already-exists", sender);
|
plugin.getCore().sendLocaleMessage("already-exists", sender);
|
||||||
} else {
|
} else {
|
||||||
//todo: resolve uuid
|
//todo: resolve uuid
|
||||||
profile.setOnlinemodePreferred(true);
|
profile.setPremium(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(
|
||||||
new BukkitFastLoginPremiumToggleEvent(sender, profile, PremiumToggleReason.COMMAND_SELF)
|
new BukkitFastLoginPremiumToggleEvent(profile, PremiumToggleReason.COMMAND_SELF));
|
||||||
);
|
|
||||||
|
|
||||||
plugin.getScheduler().getSyncExecutor().execute(() -> {
|
|
||||||
if (plugin.getCore().getConfig().getBoolean("kick-toggle", true)) {
|
|
||||||
player.kickPlayer(plugin.getCore().getMessage("remove-premium"));
|
|
||||||
} else {
|
|
||||||
plugin.getCore().sendLocaleMessage("add-premium", sender);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
plugin.getCore().sendLocaleMessage("add-premium", sender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,16 +110,15 @@ public class PremiumCommand extends ToggleCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profile.isOnlinemodePreferred()) {
|
if (profile.isPremium()) {
|
||||||
plugin.getCore().sendLocaleMessage("already-exists-other", sender);
|
plugin.getCore().sendLocaleMessage("already-exists-other", sender);
|
||||||
} else {
|
} else {
|
||||||
//todo: resolve uuid
|
//todo: resolve uuid
|
||||||
profile.setOnlinemodePreferred(true);
|
profile.setPremium(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(
|
||||||
new BukkitFastLoginPremiumToggleEvent(sender, profile, PremiumToggleReason.COMMAND_OTHER)
|
new BukkitFastLoginPremiumToggleEvent(profile, PremiumToggleReason.COMMAND_OTHER));
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
plugin.getCore().sendLocaleMessage("add-premium-other", sender);
|
plugin.getCore().sendLocaleMessage("add-premium-other", sender);
|
||||||
|
|||||||
+4
-3
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,6 +28,9 @@ 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.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 java.util.Optional;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
@@ -35,8 +38,6 @@ import org.bukkit.command.CommandSender;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.messaging.PluginMessageRecipient;
|
import org.bukkit.plugin.messaging.PluginMessageRecipient;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public abstract class ToggleCommand implements CommandExecutor {
|
public abstract class ToggleCommand implements CommandExecutor {
|
||||||
|
|
||||||
protected final FastLoginBukkit plugin;
|
protected final FastLoginBukkit plugin;
|
||||||
|
|||||||
+3
-2
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,9 +25,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.event;
|
package com.github.games647.fastlogin.bukkit.event;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
import org.bukkit.event.Cancellable;
|
import org.bukkit.event.Cancellable;
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
|
|||||||
+3
-2
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,9 +25,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.event;
|
package com.github.games647.fastlogin.bukkit.event;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||||
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 org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|||||||
+4
-15
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,9 +25,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.event;
|
package com.github.games647.fastlogin.bukkit.event;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
|
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -35,15 +35,11 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
public class BukkitFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
|
public class BukkitFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
|
||||||
|
|
||||||
private static final HandlerList HANDLERS = new HandlerList();
|
private static final HandlerList HANDLERS = new HandlerList();
|
||||||
|
|
||||||
private final CommandSender invoker;
|
|
||||||
private final StoredProfile profile;
|
private final StoredProfile profile;
|
||||||
private final PremiumToggleReason reason;
|
private final PremiumToggleReason reason;
|
||||||
|
|
||||||
public BukkitFastLoginPremiumToggleEvent(CommandSender invoker, StoredProfile profile, PremiumToggleReason reason) {
|
public BukkitFastLoginPremiumToggleEvent(StoredProfile profile, PremiumToggleReason reason) {
|
||||||
super(true);
|
super(true);
|
||||||
|
|
||||||
this.invoker = invoker;
|
|
||||||
this.profile = profile;
|
this.profile = profile;
|
||||||
this.reason = reason;
|
this.reason = reason;
|
||||||
}
|
}
|
||||||
@@ -53,13 +49,6 @@ public class BukkitFastLoginPremiumToggleEvent extends Event implements FastLogi
|
|||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return who triggered this change. This could be a Player for itself or others (Admin) or the console.
|
|
||||||
*/
|
|
||||||
public CommandSender getInvoker() {
|
|
||||||
return invoker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PremiumToggleReason getReason() {
|
public PremiumToggleReason getReason() {
|
||||||
return reason;
|
return reason;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,26 +28,28 @@ package com.github.games647.fastlogin.bukkit.hook;
|
|||||||
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.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
|
|
||||||
import fr.xephi.authme.api.v3.AuthMeApi;
|
import fr.xephi.authme.api.v3.AuthMeApi;
|
||||||
import fr.xephi.authme.events.RestoreSessionEvent;
|
import fr.xephi.authme.events.RestoreSessionEvent;
|
||||||
import fr.xephi.authme.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
import fr.xephi.authme.process.register.executors.ApiPasswordRegisterParams;
|
import fr.xephi.authme.process.register.executors.ApiPasswordRegisterParams;
|
||||||
import fr.xephi.authme.process.register.executors.RegistrationMethod;
|
import fr.xephi.authme.process.register.executors.RegistrationMethod;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
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.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GitHub: <a href="https://github.com/Xephi/AuthMeReloaded/">...</a>
|
* GitHub: <a href="https://github.com/Xephi/AuthMeReloaded/">...</a>
|
||||||
* <p>
|
* <p>
|
||||||
* Project page:
|
* Project page:
|
||||||
* <p>
|
* <p>
|
||||||
* <a href="https://dev.bukkit.org/bukkit-plugins/authme-reloaded/">Bukkit</a>
|
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/authme-reloaded/">...</a>
|
||||||
* <p>
|
* <p>
|
||||||
* <a href="https://www.spigotmc.org/resources/authme-reloaded.6269/">Spigot</a>
|
* Spigot: <a href="https://www.spigotmc.org/resources/authme-reloaded.6269/">...</a>
|
||||||
*/
|
*/
|
||||||
public class AuthMeHook implements AuthPlugin<Player>, Listener {
|
public class AuthMeHook implements AuthPlugin<Player>, Listener {
|
||||||
|
|
||||||
@@ -60,7 +62,7 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
|
|||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.authmeAPI = AuthMeApi.getInstance();
|
this.authmeAPI = AuthMeApi.getInstance();
|
||||||
|
|
||||||
if (plugin.getCore().getConfig().getBoolean("respectIpLimit", false)) {
|
if (plugin.getConfig().getBoolean("respectIpLimit", false)) {
|
||||||
try {
|
try {
|
||||||
Field managementField = this.authmeAPI.getClass().getDeclaredField("management");
|
Field managementField = this.authmeAPI.getClass().getDeclaredField("management");
|
||||||
managementField.setAccessible(true);
|
managementField.setAccessible(true);
|
||||||
@@ -76,7 +78,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.isVerifiedPremium()) {
|
if (session != null && session.isVerified()) {
|
||||||
restoreSessionEvent.setCancelled(true);
|
restoreSessionEvent.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,24 +29,26 @@ import com.comphenix.protocol.reflect.accessors.Accessors;
|
|||||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
|
|
||||||
import de.st_ddt.crazylogin.CrazyLogin;
|
import de.st_ddt.crazylogin.CrazyLogin;
|
||||||
import de.st_ddt.crazylogin.data.LoginPlayerData;
|
import de.st_ddt.crazylogin.data.LoginPlayerData;
|
||||||
import de.st_ddt.crazylogin.databases.CrazyLoginDataDatabase;
|
import de.st_ddt.crazylogin.databases.CrazyLoginDataDatabase;
|
||||||
import de.st_ddt.crazylogin.listener.PlayerListener;
|
import de.st_ddt.crazylogin.listener.PlayerListener;
|
||||||
import de.st_ddt.crazylogin.metadata.Authenticated;
|
import de.st_ddt.crazylogin.metadata.Authenticated;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GitHub: <a href="https://github.com/ST-DDT/CrazyLogin">...</a>
|
* GitHub: <a href="https://github.com/ST-DDT/CrazyLogin">...</a>
|
||||||
* <p>
|
* <p>
|
||||||
* Project page:
|
* Project page:
|
||||||
* <p>
|
* <p>
|
||||||
* <a href="https://dev.bukkit.org/server-mods/crazylogin/">Bukkit</a>
|
* Bukkit: <a href="https://dev.bukkit.org/server-mods/crazylogin/">...</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-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,14 +27,16 @@ 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.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
|
|
||||||
import io.github.lucaseasedup.logit.CancelledState;
|
import io.github.lucaseasedup.logit.CancelledState;
|
||||||
import io.github.lucaseasedup.logit.LogItCore;
|
import io.github.lucaseasedup.logit.LogItCore;
|
||||||
import io.github.lucaseasedup.logit.account.Account;
|
import io.github.lucaseasedup.logit.account.Account;
|
||||||
import io.github.lucaseasedup.logit.session.SessionManager;
|
import io.github.lucaseasedup.logit.session.SessionManager;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GitHub: <a href="https://github.com/XziomekX/LogIt">...</a>
|
* GitHub: <a href="https://github.com/XziomekX/LogIt">...</a>
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
+4
-3
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,6 +32,7 @@ import com.lenis0012.bukkit.loginsecurity.session.AuthService;
|
|||||||
import com.lenis0012.bukkit.loginsecurity.session.PlayerSession;
|
import com.lenis0012.bukkit.loginsecurity.session.PlayerSession;
|
||||||
import com.lenis0012.bukkit.loginsecurity.session.action.LoginAction;
|
import com.lenis0012.bukkit.loginsecurity.session.action.LoginAction;
|
||||||
import com.lenis0012.bukkit.loginsecurity.session.action.RegisterAction;
|
import com.lenis0012.bukkit.loginsecurity.session.action.RegisterAction;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,9 +40,9 @@ import org.bukkit.entity.Player;
|
|||||||
* <p>
|
* <p>
|
||||||
* Project page:
|
* Project page:
|
||||||
* <p>
|
* <p>
|
||||||
* <a href="https://dev.bukkit.org/bukkit-plugins/loginsecurity/">Bukkit</a>
|
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/loginsecurity/">...</a>
|
||||||
* <p>
|
* <p>
|
||||||
* <a href="https://www.spigotmc.org/resources/loginsecurity.19362/">Spigot</a>
|
* Spigot: <a href="https://www.spigotmc.org/resources/loginsecurity.19362/">...</a>
|
||||||
*/
|
*/
|
||||||
public class LoginSecurityHook implements AuthPlugin<Player> {
|
public class LoginSecurityHook implements AuthPlugin<Player> {
|
||||||
|
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.hook;
|
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
|
||||||
import com.rabbitcomapny.api.Identifier;
|
|
||||||
import com.rabbitcomapny.api.LoginResult;
|
|
||||||
import com.rabbitcomapny.api.PasskyAPI;
|
|
||||||
import com.rabbitcomapny.api.RegisterResult;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class PasskyHook implements AuthPlugin<Player> {
|
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
|
||||||
|
|
||||||
public PasskyHook(FastLoginBukkit plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean forceLogin(Player player) {
|
|
||||||
LoginResult result = PasskyAPI.forceLogin(new Identifier(player), true);
|
|
||||||
if (!result.success) {
|
|
||||||
plugin.getLog().error("Failed to force login {} via Passky: {}", player.getName(), result.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean forceRegister(Player player, String password) {
|
|
||||||
RegisterResult result = PasskyAPI.forceRegister(new Identifier(player), password, true);
|
|
||||||
if (!result.success) {
|
|
||||||
plugin.getLog().error("Failed to register {} via Passky: {}", player.getName(), result.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRegistered(String playerName) {
|
|
||||||
return PasskyAPI.isRegistered(new Identifier(playerName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,20 +27,21 @@ 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.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import ultraauth.api.UltraAuthAPI;
|
import ultraauth.api.UltraAuthAPI;
|
||||||
import ultraauth.managers.PlayerManager;
|
import ultraauth.managers.PlayerManager;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project page:
|
* Project page:
|
||||||
* <p>
|
* <p>
|
||||||
* <a href="https://dev.bukkit.org/bukkit-plugins/ultraauth-aa/">Bukkit</a>
|
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/ultraauth-aa/">...</a>
|
||||||
* <p>
|
* <p>
|
||||||
* <a href="https://www.spigotmc.org/resources/ultraauth.17044/">Spigot</a>
|
* Spigot: <a href="https://www.spigotmc.org/resources/ultraauth.17044/">...</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-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,20 +27,22 @@ 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.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
|
|
||||||
import de.luricos.bukkit.xAuth.xAuth;
|
import de.luricos.bukkit.xAuth.xAuth;
|
||||||
import de.luricos.bukkit.xAuth.xAuthPlayer;
|
import de.luricos.bukkit.xAuth.xAuthPlayer;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GitHub: <a href="https://github.com/LycanDevelopment/xAuth/">...</a>
|
* GitHub: <a href="https://github.com/LycanDevelopment/xAuth/">...</a>
|
||||||
* <p>
|
* <p>
|
||||||
* Project page:
|
* Project page:
|
||||||
* <p>
|
* <p>
|
||||||
* <a href="https://dev.bukkit.org/bukkit-plugins/xauth/">Bukkit</a>
|
* Bukkit: <a href="https://dev.bukkit.org/bukkit-plugins/xauth/">...</a>
|
||||||
*/
|
*/
|
||||||
public class XAuthHook implements AuthPlugin<Player> {
|
public class XAuthHook implements AuthPlugin<Player> {
|
||||||
|
|
||||||
|
|||||||
+12
-9
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,16 +34,18 @@ import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
|||||||
import com.github.games647.fastlogin.core.message.LoginActionMessage.Type;
|
import com.github.games647.fastlogin.core.message.LoginActionMessage.Type;
|
||||||
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 java.net.InetSocketAddress;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for receiving messages from a BungeeCord instance.
|
* Responsible for receiving messages from a BungeeCord instance.
|
||||||
* <p>
|
*
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
@@ -91,23 +93,24 @@ public class BungeeListener implements PluginMessageListener {
|
|||||||
String playerName = message.getPlayerName();
|
String playerName = message.getPlayerName();
|
||||||
Type type = message.getType();
|
Type type = message.getType();
|
||||||
|
|
||||||
|
InetSocketAddress address = player.getAddress();
|
||||||
plugin.getLog().info("Player info {} command for {} from proxy", type, playerName);
|
plugin.getLog().info("Player info {} command for {} from proxy", type, playerName);
|
||||||
if (type == Type.LOGIN) {
|
if (type == Type.LOGIN) {
|
||||||
onLoginMessage(player, playerName);
|
onLoginMessage(player, playerName, address);
|
||||||
} else if (type == Type.REGISTER) {
|
} else if (type == Type.REGISTER) {
|
||||||
onRegisterMessage(player, playerName);
|
onRegisterMessage(player, playerName, address);
|
||||||
} else if (type == Type.CRACKED) {
|
} else if (type == Type.CRACKED) {
|
||||||
//we don't start a force login task here so update it manually
|
//we don't start a force login task here so update it manually
|
||||||
plugin.getPremiumPlayers().put(player.getUniqueId(), PremiumStatus.CRACKED);
|
plugin.getPremiumPlayers().put(player.getUniqueId(), PremiumStatus.CRACKED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onLoginMessage(Player player, String playerName) {
|
private void onLoginMessage(Player player, String playerName, InetSocketAddress address) {
|
||||||
BukkitLoginSession playerSession = new BukkitLoginSession(playerName, true);
|
BukkitLoginSession playerSession = new BukkitLoginSession(playerName, true);
|
||||||
startLoginTaskIfReady(player, playerSession);
|
startLoginTaskIfReady(player, playerSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onRegisterMessage(Player player, String playerName) {
|
private void onRegisterMessage(Player player, String playerName, InetSocketAddress address) {
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||||
AuthPlugin<Player> authPlugin = plugin.getCore().getAuthPluginHook();
|
AuthPlugin<Player> authPlugin = plugin.getCore().getAuthPluginHook();
|
||||||
try {
|
try {
|
||||||
@@ -123,7 +126,7 @@ public class BungeeListener implements PluginMessageListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startLoginTaskIfReady(Player player, BukkitLoginSession session) {
|
private void startLoginTaskIfReady(Player player, BukkitLoginSession session) {
|
||||||
session.setVerifiedPremium(true);
|
session.setVerified(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
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,6 +30,7 @@ import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
|||||||
import com.github.games647.fastlogin.bukkit.task.FloodgateAuthTask;
|
import com.github.games647.fastlogin.bukkit.task.FloodgateAuthTask;
|
||||||
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
|
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;
|
||||||
@@ -90,7 +91,6 @@ public class ConnectionListener implements Listener {
|
|||||||
if (floodgatePlayer != null) {
|
if (floodgatePlayer != null) {
|
||||||
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer);
|
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer);
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask);
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask);
|
||||||
plugin.getBungeeManager().markJoinEventFired(player);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,6 +29,7 @@ import com.destroystokyo.paper.profile.ProfileProperty;
|
|||||||
import com.github.games647.craftapi.model.skin.Textures;
|
import com.github.games647.craftapi.model.skin.Textures;
|
||||||
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 org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
|||||||
+22
-36
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,16 +32,8 @@ import com.google.common.hash.Hashing;
|
|||||||
import com.google.common.io.Resources;
|
import com.google.common.io.Resources;
|
||||||
import com.google.common.primitives.Longs;
|
import com.google.common.primitives.Longs;
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
|
||||||
import javax.crypto.Cipher;
|
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
@@ -53,14 +45,21 @@ import java.security.PublicKey;
|
|||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.security.spec.KeySpec;
|
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Base64.Encoder;
|
import java.util.Base64.Encoder;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.UUID;
|
|
||||||
|
import javax.crypto.BadPaddingException;
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encryption and decryption minecraft util for connection between servers
|
* Encryption and decryption minecraft util for connection between servers
|
||||||
@@ -71,15 +70,13 @@ final class EncryptionUtil {
|
|||||||
public static final int VERIFY_TOKEN_LENGTH = 4;
|
public static final int VERIFY_TOKEN_LENGTH = 4;
|
||||||
public static final String KEY_PAIR_ALGORITHM = "RSA";
|
public static final String KEY_PAIR_ALGORITHM = "RSA";
|
||||||
|
|
||||||
private static final int RSA_LENGTH = 2_048;
|
private static final int RSA_LENGTH = 1_024;
|
||||||
|
|
||||||
private static final PublicKey MOJANG_SESSION_KEY;
|
private static final PublicKey MOJANG_SESSION_KEY;
|
||||||
private static final int LINE_LENGTH = 76;
|
private static final int LINE_LENGTH = 76;
|
||||||
private static final Encoder KEY_ENCODER = Base64.getMimeEncoder(
|
private static final Encoder KEY_ENCODER = Base64.getMimeEncoder(
|
||||||
LINE_LENGTH, "\n".getBytes(StandardCharsets.UTF_8)
|
LINE_LENGTH, "\n".getBytes(StandardCharsets.UTF_8)
|
||||||
);
|
);
|
||||||
private static final int MILLISECOND_SIZE = 8;
|
|
||||||
private static final int UUID_SIZE = 2 * MILLISECOND_SIZE;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
@@ -149,7 +146,7 @@ final class EncryptionUtil {
|
|||||||
return new SecretKeySpec(decrypt(privateKey, sharedKey), "AES");
|
return new SecretKeySpec(decrypt(privateKey, sharedKey), "AES");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean verifyClientKey(ClientPublicKey clientKey, Instant verifyTimestamp, UUID premiumId)
|
public static boolean verifyClientKey(ClientPublicKey clientKey, Instant verifyTimestamp)
|
||||||
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
|
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
|
||||||
if (clientKey.isExpired(verifyTimestamp)) {
|
if (clientKey.isExpired(verifyTimestamp)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -158,27 +155,10 @@ final class EncryptionUtil {
|
|||||||
Signature verifier = Signature.getInstance("SHA1withRSA");
|
Signature verifier = Signature.getInstance("SHA1withRSA");
|
||||||
// key of the signer
|
// key of the signer
|
||||||
verifier.initVerify(MOJANG_SESSION_KEY);
|
verifier.initVerify(MOJANG_SESSION_KEY);
|
||||||
verifier.update(toSignable(clientKey, premiumId));
|
verifier.update(toSignable(clientKey).getBytes(StandardCharsets.US_ASCII));
|
||||||
return verifier.verify(clientKey.signature());
|
return verifier.verify(clientKey.signature());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] toSignable(ClientPublicKey clientPublicKey, UUID ownerPremiumId) {
|
|
||||||
if (ownerPremiumId == null) {
|
|
||||||
long expiry = clientPublicKey.expiry().toEpochMilli();
|
|
||||||
String encoded = KEY_ENCODER.encodeToString(clientPublicKey.key().getEncoded());
|
|
||||||
return (expiry + "-----BEGIN RSA PUBLIC KEY-----\n" + encoded + "\n-----END RSA PUBLIC KEY-----\n")
|
|
||||||
.getBytes(StandardCharsets.US_ASCII);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] keyData = clientPublicKey.key().getEncoded();
|
|
||||||
return ByteBuffer.allocate(keyData.length + UUID_SIZE + MILLISECOND_SIZE)
|
|
||||||
.putLong(ownerPremiumId.getMostSignificantBits())
|
|
||||||
.putLong(ownerPremiumId.getLeastSignificantBits())
|
|
||||||
.putLong(clientPublicKey.expiry().toEpochMilli())
|
|
||||||
.put(keyData)
|
|
||||||
.array();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean verifyNonce(byte[] expected, PrivateKey decryptionKey, byte[] encryptedNonce)
|
public static boolean verifyNonce(byte[] expected, PrivateKey decryptionKey, byte[] encryptedNonce)
|
||||||
throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException,
|
throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException,
|
||||||
BadPaddingException, InvalidKeyException {
|
BadPaddingException, InvalidKeyException {
|
||||||
@@ -199,13 +179,19 @@ final class EncryptionUtil {
|
|||||||
|
|
||||||
private static PublicKey loadMojangSessionKey()
|
private static PublicKey loadMojangSessionKey()
|
||||||
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
|
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
URL keyUrl = FastLoginBukkit.class.getClassLoader().getResource("yggdrasil_session_pubkey.der");
|
val keyUrl = FastLoginBukkit.class.getClassLoader().getResource("yggdrasil_session_pubkey.der");
|
||||||
byte[] keyData = Resources.toByteArray(keyUrl);
|
val keyData = Resources.toByteArray(keyUrl);
|
||||||
KeySpec keySpec = new X509EncodedKeySpec(keyData);
|
val keySpec = new X509EncodedKeySpec(keyData);
|
||||||
|
|
||||||
return KeyFactory.getInstance("RSA").generatePublic(keySpec);
|
return KeyFactory.getInstance("RSA").generatePublic(keySpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String toSignable(ClientPublicKey clientPublicKey) {
|
||||||
|
long expiry = clientPublicKey.expiry().toEpochMilli();
|
||||||
|
String encoded = KEY_ENCODER.encodeToString(clientPublicKey.key().getEncoded());
|
||||||
|
return expiry + "-----BEGIN RSA PUBLIC KEY-----\n" + encoded + "\n-----END RSA PUBLIC KEY-----\n";
|
||||||
|
}
|
||||||
|
|
||||||
private static byte[] decrypt(PrivateKey key, byte[] data)
|
private static byte[] decrypt(PrivateKey key, byte[] data)
|
||||||
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
|
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
|
||||||
IllegalBlockSizeException, BadPaddingException {
|
IllegalBlockSizeException, BadPaddingException {
|
||||||
|
|||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2022 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.protocollib;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.events.PacketAdapter;
|
||||||
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
|
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||||
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
|
|
||||||
|
import static com.comphenix.protocol.PacketType.Login.Client.START;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manually inject Floodgate player name prefixes.
|
||||||
|
* <br>
|
||||||
|
* This is used as a workaround, because Floodgate fails to inject
|
||||||
|
* the prefixes when it's used together with ProtocolLib and FastLogin.
|
||||||
|
* <br>
|
||||||
|
* For more information visit: <a href="https://github.com/games647/FastLogin/issues/493">...</a>
|
||||||
|
*/
|
||||||
|
public class ManualNameChange extends PacketAdapter {
|
||||||
|
|
||||||
|
private final FloodgateService floodgate;
|
||||||
|
|
||||||
|
public ManualNameChange(FastLoginBukkit plugin, FloodgateService floodgate) {
|
||||||
|
super(params()
|
||||||
|
.plugin(plugin)
|
||||||
|
.types(START));
|
||||||
|
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.floodgate = floodgate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(FastLoginBukkit plugin, FloodgateService floodgate) {
|
||||||
|
// they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
|
||||||
|
// ProtocolLibrary.getProtocolManager()
|
||||||
|
// .getAsynchronousManager()
|
||||||
|
// .registerAsyncHandler(new ManualNameChange(plugin, floodgate))
|
||||||
|
// .start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPacketReceiving(PacketEvent packetEvent) {
|
||||||
|
PacketContainer packet = packetEvent.getPacket();
|
||||||
|
String username = readUsername(packet);
|
||||||
|
|
||||||
|
if (floodgate.getBedrockPlayer(username) == null) {
|
||||||
|
//not a Floodgate player, no need to add a prefix
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet.setMeta("original_name", username);
|
||||||
|
String prefixedName = FloodgateApi.getInstance().getPlayerPrefix() + username;
|
||||||
|
setUsername(packet, prefixedName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUsername(PacketContainer packet, String name) {
|
||||||
|
if (packet.getGameProfiles().size() > 0) {
|
||||||
|
WrappedGameProfile updatedProfile = new WrappedGameProfile(UUID.randomUUID(), name);
|
||||||
|
packet.getGameProfiles().write(0, updatedProfile);
|
||||||
|
} else {
|
||||||
|
packet.getStrings().write(0, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readUsername(PacketContainer packet) {
|
||||||
|
if (packet.getGameProfiles().size() > 0) {
|
||||||
|
return packet.getGameProfiles().read(0).getName();
|
||||||
|
} else {
|
||||||
|
return packet.getStrings().read(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
-15
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,23 +25,23 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
||||||
|
|
||||||
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.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.bukkit.listener.protocollib.packet.ClientPublicKey;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
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 org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
public class NameCheckTask extends JoinManagement<Player, CommandSender, ProtocolLibLoginSource>
|
public class NameCheckTask extends JoinManagement<Player, CommandSender, ProtocolLibLoginSource>
|
||||||
implements Runnable {
|
implements Runnable {
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
private final FastLoginBukkit plugin;
|
||||||
private final PacketEvent packetEvent;
|
private final PacketEvent packetEvent;
|
||||||
@@ -69,11 +69,11 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
// try {
|
||||||
super.onLogin(username, new ProtocolLibLoginSource(player, random, serverKey, clientKey));
|
super.onLogin(username, new ProtocolLibLoginSource(player, random, serverKey, clientKey));
|
||||||
} finally {
|
// } finally {
|
||||||
ProtocolLibrary.getProtocolManager().getAsynchronousManager().signalPacketTransmission(packetEvent);
|
// ProtocolLibrary.getProtocolManager().getAsynchronousManager().signalPacketTransmission(packetEvent);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -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.addLoginAttempt(ip, username);
|
core.getPendingLogin().put(ip + username, new Object());
|
||||||
|
|
||||||
byte[] verify = source.getVerifyToken();
|
byte[] verify = source.getVerifyToken();
|
||||||
ClientPublicKey clientKey = source.getClientKey();
|
ClientPublicKey clientKey = source.getClientKey();
|
||||||
@@ -105,9 +105,9 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
|
|||||||
BukkitLoginSession playerSession = new BukkitLoginSession(username, verify, clientKey, registered, profile);
|
BukkitLoginSession playerSession = new BukkitLoginSession(username, verify, clientKey, registered, profile);
|
||||||
plugin.putSession(player.getAddress(), playerSession);
|
plugin.putSession(player.getAddress(), playerSession);
|
||||||
//cancel only if the player has a paid account otherwise login as normal offline player
|
//cancel only if the player has a paid account otherwise login as normal offline player
|
||||||
synchronized (packetEvent.getAsyncMarker().getProcessingLock()) {
|
// synchronized (packetEvent.getAsyncMarker().getProcessingLock()) {
|
||||||
packetEvent.setCancelled(true);
|
packetEvent.setCancelled(true);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+98
-160
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,14 +30,9 @@ import com.comphenix.protocol.ProtocolLibrary;
|
|||||||
import com.comphenix.protocol.events.PacketAdapter;
|
import com.comphenix.protocol.events.PacketAdapter;
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
import com.comphenix.protocol.injector.netty.channel.NettyChannelInjector;
|
|
||||||
import com.comphenix.protocol.injector.temporary.TemporaryPlayerFactory;
|
|
||||||
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.utility.MinecraftVersion;
|
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||||
import com.comphenix.protocol.wrappers.BukkitConverters;
|
import com.comphenix.protocol.wrappers.BukkitConverters;
|
||||||
import com.comphenix.protocol.wrappers.Converters;
|
|
||||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||||
import com.comphenix.protocol.wrappers.WrappedProfilePublicKey.WrappedProfileKeyData;
|
import com.comphenix.protocol.wrappers.WrappedProfilePublicKey.WrappedProfileKeyData;
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
@@ -46,16 +41,7 @@ import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPu
|
|||||||
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;
|
||||||
import io.netty.channel.Channel;
|
|
||||||
import io.netty.channel.ChannelHandler;
|
|
||||||
import io.netty.util.AttributeKey;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
@@ -64,15 +50,24 @@ import java.security.PublicKey;
|
|||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.function.Function;
|
import javax.crypto.BadPaddingException;
|
||||||
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
|
||||||
|
import lombok.var;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import static com.comphenix.protocol.PacketType.Login.Client.ENCRYPTION_BEGIN;
|
import static com.comphenix.protocol.PacketType.Login.Client.ENCRYPTION_BEGIN;
|
||||||
import static com.comphenix.protocol.PacketType.Login.Client.START;
|
import static com.comphenix.protocol.PacketType.Login.Client.START;
|
||||||
|
|
||||||
public class ProtocolLibListener extends PacketAdapter {
|
public class ProtocolLibListener extends PacketAdapter {
|
||||||
|
|
||||||
|
public static final String SOURCE_META_KEY = "source";
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
private final FastLoginBukkit plugin;
|
||||||
|
|
||||||
//just create a new once on plugin enable. This used for verify token generation
|
//just create a new once on plugin enable. This used for verify token generation
|
||||||
@@ -82,12 +77,14 @@ public class ProtocolLibListener extends PacketAdapter {
|
|||||||
|
|
||||||
private final boolean verifyClientKeys;
|
private final boolean verifyClientKeys;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private PacketContainer lastStartPacket;
|
||||||
|
|
||||||
public ProtocolLibListener(FastLoginBukkit plugin, AntiBotService antiBotService, boolean verifyClientKeys) {
|
public ProtocolLibListener(FastLoginBukkit plugin, AntiBotService antiBotService, boolean verifyClientKeys) {
|
||||||
//run async in order to not block the server, because we are making api calls to Mojang
|
//run async in order to not block the server, because we are making api calls to Mojang
|
||||||
super(params()
|
super(params()
|
||||||
.plugin(plugin)
|
.plugin(plugin)
|
||||||
.types(START, ENCRYPTION_BEGIN)
|
.types(START, ENCRYPTION_BEGIN));
|
||||||
.optionAsync());
|
|
||||||
|
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.antiBotService = antiBotService;
|
this.antiBotService = antiBotService;
|
||||||
@@ -98,77 +95,73 @@ public class ProtocolLibListener extends PacketAdapter {
|
|||||||
// they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
|
// they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
|
||||||
// TODO: make synchronous processing, but do web or database requests async
|
// TODO: make synchronous processing, but do web or database requests async
|
||||||
ProtocolLibrary.getProtocolManager()
|
ProtocolLibrary.getProtocolManager()
|
||||||
.getAsynchronousManager()
|
.addPacketListener(new ProtocolLibListener(plugin, antiBotService, verifyClientKeys));
|
||||||
.registerAsyncHandler(new ProtocolLibListener(plugin, antiBotService, verifyClientKeys))
|
|
||||||
.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPacketReceiving(PacketEvent packetEvent) {
|
public void onPacketReceiving(PacketEvent packetEvent) {
|
||||||
|
PacketContainer packet = packetEvent.getPacket();
|
||||||
|
plugin.getLog().info("New packet {} from {}; Cancellation: {}, Meta: {}",
|
||||||
|
packetEvent.getPacketType(), packetEvent.getPlayer(), packetEvent.isCancelled(),
|
||||||
|
packet.getMeta(SOURCE_META_KEY)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (packetEvent.getPacketType() == START) {
|
||||||
|
if (lastStartPacket != null) {
|
||||||
|
plugin.getLog().info("Start-packet equality (Last/New): {}/{}, {}",
|
||||||
|
lastStartPacket.getHandle().hashCode(), packet.getHandle().hashCode(),
|
||||||
|
Objects.equals(lastStartPacket.getHandle(), packet.getHandle())
|
||||||
|
);
|
||||||
|
|
||||||
|
plugin.getLog().info("Content: {}, {}", lastStartPacket.getHandle(), packet.getHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
lastStartPacket = packet;
|
||||||
|
}
|
||||||
|
|
||||||
if (packetEvent.isCancelled()
|
if (packetEvent.isCancelled()
|
||||||
|| plugin.getCore().getAuthPluginHook() == null
|
|| plugin.getCore().getAuthPluginHook() == null
|
||||||
|| !plugin.isServerFullyStarted()) {
|
|| !plugin.isServerFullyStarted()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isFastLoginPacket(packetEvent)) {
|
||||||
|
// this is our own packet
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Player sender = packetEvent.getPlayer();
|
Player sender = packetEvent.getPlayer();
|
||||||
PacketType packetType = getOverriddenType(packetEvent.getPacketType());
|
PacketType packetType = packetEvent.getPacketType();
|
||||||
|
if (packetType == START) {
|
||||||
|
// PacketContainer packet = packet;
|
||||||
|
|
||||||
plugin.getLog().info("New incoming packet {} from {}", packetType, sender.getName());
|
InetSocketAddress address = sender.getAddress();
|
||||||
try {
|
String username = getUsername(packet);
|
||||||
if (packetType == START) {
|
|
||||||
if (plugin.getFloodgateService() != null) {
|
|
||||||
boolean success = processFloodgateTasks(packetEvent);
|
|
||||||
if (!success) {
|
|
||||||
// don't continue execution if the player was kicked by Floodgate
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketContainer packet = packetEvent.getPacket();
|
Action action = antiBotService.onIncomingConnection(address, username);
|
||||||
|
switch (action) {
|
||||||
InetSocketAddress address = sender.getAddress();
|
case Ignore:
|
||||||
String username = getUsername(packet);
|
// just ignore
|
||||||
|
return;
|
||||||
Action action = antiBotService.onIncomingConnection(address, username);
|
case Block:
|
||||||
switch (action) {
|
String message = plugin.getCore().getMessage("kick-antibot");
|
||||||
case Ignore:
|
sender.kickPlayer(message);
|
||||||
// just ignore
|
break;
|
||||||
return;
|
case Continue:
|
||||||
case Block:
|
default:
|
||||||
String message = plugin.getCore().getMessage("kick-antibot");
|
//player.getName() won't work at this state
|
||||||
sender.kickPlayer(message);
|
onLoginStart(packetEvent, sender, username);
|
||||||
break;
|
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) {
|
} else {
|
||||||
plugin.getLog().error("Failed to parse packet {}", packetEvent.getPacketType(), fieldAccessEx);
|
onEncryptionBegin(packetEvent, sender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull PacketType getOverriddenType(PacketType packetType) {
|
private boolean isFastLoginPacket(PacketEvent packetEvent) {
|
||||||
if (packetType.isDynamic()) {
|
return packetEvent.getPacket().getMeta(SOURCE_META_KEY)
|
||||||
String vanillaName = packetType.getPacketClass().getName();
|
.map(val -> val.equals(plugin.getName()))
|
||||||
plugin.getLog().info("Overriding packet type for unregistered packet type to fix ProtocolLib bug");
|
.orElse(false);
|
||||||
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) {
|
||||||
@@ -181,12 +174,13 @@ public class ProtocolLibListener extends PacketAdapter {
|
|||||||
} else {
|
} else {
|
||||||
byte[] expectedVerifyToken = session.getVerifyToken();
|
byte[] expectedVerifyToken = session.getVerifyToken();
|
||||||
if (verifyNonce(sender, packetEvent.getPacket(), session.getClientPublicKey(), expectedVerifyToken)) {
|
if (verifyNonce(sender, packetEvent.getPacket(), session.getClientPublicKey(), expectedVerifyToken)) {
|
||||||
packetEvent.getAsyncMarker().incrementProcessingDelay();
|
// packetEvent.getAsyncMarker().incrementProcessingDelay();
|
||||||
|
|
||||||
Runnable verifyTask = new VerifyResponseTask(
|
Runnable verifyTask = new VerifyResponseTask(
|
||||||
plugin, packetEvent, sender, session, sharedSecret, keyPair
|
plugin, packetEvent, sender, session, sharedSecret, keyPair
|
||||||
);
|
);
|
||||||
plugin.getScheduler().runAsync(verifyTask);
|
verifyTask.run();
|
||||||
|
// plugin.getScheduler().runAsync(verifyTask);
|
||||||
} else {
|
} else {
|
||||||
sender.kickPlayer(plugin.getCore().getMessage("invalid-verify-token"));
|
sender.kickPlayer(plugin.getCore().getMessage("invalid-verify-token"));
|
||||||
}
|
}
|
||||||
@@ -196,8 +190,7 @@ public class ProtocolLibListener extends PacketAdapter {
|
|||||||
private boolean verifyNonce(Player sender, PacketContainer packet,
|
private boolean verifyNonce(Player sender, PacketContainer packet,
|
||||||
ClientPublicKey clientPublicKey, byte[] expectedToken) {
|
ClientPublicKey clientPublicKey, byte[] expectedToken) {
|
||||||
try {
|
try {
|
||||||
if (new MinecraftVersion(1, 19, 0).atOrAbove()
|
if (MinecraftVersion.atOrAbove(new MinecraftVersion(1, 19, 0))) {
|
||||||
&& !new MinecraftVersion(1, 19, 3).atOrAbove()) {
|
|
||||||
Either<byte[], ?> either = packet.getSpecificModifier(Either.class).read(0);
|
Either<byte[], ?> either = packet.getSpecificModifier(Either.class).read(0);
|
||||||
if (clientPublicKey == null) {
|
if (clientPublicKey == null) {
|
||||||
Optional<byte[]> left = either.left();
|
Optional<byte[]> left = either.left();
|
||||||
@@ -239,50 +232,48 @@ public class ProtocolLibListener extends PacketAdapter {
|
|||||||
//remove old data every time on a new login in order to keep the session only for one person
|
//remove old data every time on a new login in order to keep the session only for one person
|
||||||
plugin.removeSession(player.getAddress());
|
plugin.removeSession(player.getAddress());
|
||||||
|
|
||||||
|
if (packetEvent.getPacket().getMeta("original_name").isPresent()) {
|
||||||
|
//username has been injected by ManualNameChange.java
|
||||||
|
username = (String) packetEvent.getPacket().getMeta("original_name").get();
|
||||||
|
}
|
||||||
|
|
||||||
PacketContainer packet = packetEvent.getPacket();
|
PacketContainer packet = packetEvent.getPacket();
|
||||||
Optional<ClientPublicKey> clientKey;
|
var profileKey = packet.getOptionals(BukkitConverters.getWrappedPublicKeyDataConverter())
|
||||||
if (new MinecraftVersion(1, 19, 3).atOrAbove()) {
|
.optionRead(0);
|
||||||
// public key is sent separate
|
|
||||||
clientKey = Optional.empty();
|
|
||||||
} else {
|
|
||||||
Optional<Optional<WrappedProfileKeyData>> profileKey = packet.getOptionals(
|
|
||||||
BukkitConverters.getWrappedPublicKeyDataConverter()
|
|
||||||
).optionRead(0);
|
|
||||||
|
|
||||||
clientKey = profileKey.flatMap(Function.identity()).flatMap(data -> {
|
var clientKey = profileKey.flatMap(opt -> opt).flatMap(this::verifyPublicKey);
|
||||||
Instant expires = data.getExpireTime();
|
if (verifyClientKeys && !clientKey.isPresent()) {
|
||||||
PublicKey key = data.getKey();
|
// missing or incorrect
|
||||||
byte[] signature = data.getSignature();
|
// expired always not allowed
|
||||||
return Optional.of(ClientPublicKey.of(expires, key, signature));
|
player.kickPlayer(plugin.getCore().getMessage("invalid-public-key"));
|
||||||
});
|
plugin.getLog().warn("Invalid public key from player {}", username);
|
||||||
|
return;
|
||||||
// start reading from index 1, because 0 is already used by the public key
|
|
||||||
Optional<UUID> sessionUUID = packet.getOptionals(Converters.passthrough(UUID.class)).readSafely(1);
|
|
||||||
if (verifyClientKeys && sessionUUID.isPresent() && clientKey.isPresent()
|
|
||||||
&& verifyPublicKey(clientKey.get(), sessionUUID.get())) {
|
|
||||||
// missing or incorrect
|
|
||||||
// expired always not allowed
|
|
||||||
player.kickPlayer(plugin.getCore().getMessage("invalid-public-key"));
|
|
||||||
plugin.getLog().warn("Invalid public key from player {}", username);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getLog().trace("GameProfile {} with {} connecting", sessionKey, username);
|
plugin.getLog().trace("GameProfile {} with {} connecting", sessionKey, username);
|
||||||
|
|
||||||
packetEvent.getAsyncMarker().incrementProcessingDelay();
|
// packetEvent.getAsyncMarker().incrementProcessingDelay();
|
||||||
Runnable nameCheckTask = new NameCheckTask(
|
Runnable nameCheckTask = new NameCheckTask(
|
||||||
plugin, random, player, packetEvent, username, clientKey.orElse(null), keyPair.getPublic()
|
plugin, random, player, packetEvent, username, clientKey.orElse(null), keyPair.getPublic()
|
||||||
);
|
);
|
||||||
plugin.getScheduler().runAsync(nameCheckTask);
|
// plugin.getScheduler().runAsync(nameCheckTask);
|
||||||
|
nameCheckTask.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean verifyPublicKey(ClientPublicKey clientKey, UUID sessionPremiumUUID) {
|
private Optional<ClientPublicKey> verifyPublicKey(WrappedProfileKeyData profileKey) {
|
||||||
|
Instant expires = profileKey.getExpireTime();
|
||||||
|
PublicKey key = profileKey.getKey();
|
||||||
|
byte[] signature = profileKey.getSignature();
|
||||||
|
ClientPublicKey clientKey = ClientPublicKey.of(expires, key, signature);
|
||||||
try {
|
try {
|
||||||
return EncryptionUtil.verifyClientKey(clientKey, Instant.now(), sessionPremiumUUID);
|
if (EncryptionUtil.verifyClientKey(clientKey, Instant.now())) {
|
||||||
|
return Optional.of(clientKey);
|
||||||
|
}
|
||||||
} catch (SignatureException | InvalidKeyException | NoSuchAlgorithmException ex) {
|
} catch (SignatureException | InvalidKeyException | NoSuchAlgorithmException ex) {
|
||||||
return false;
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getUsername(PacketContainer packet) {
|
private String getUsername(PacketContainer packet) {
|
||||||
@@ -294,57 +285,4 @@ public class ProtocolLibListener extends PacketAdapter {
|
|||||||
//player.getName() won't work at this state
|
//player.getName() won't work at this state
|
||||||
return profile.getName();
|
return profile.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private FloodgatePlayer getFloodgatePlayer(Player player) {
|
|
||||||
Channel channel = getChannel(player);
|
|
||||||
AttributeKey<FloodgatePlayer> floodgateAttribute = AttributeKey.valueOf("floodgate-player");
|
|
||||||
return channel.attr(floodgateAttribute).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Channel getChannel(Player player) {
|
|
||||||
NettyChannelInjector injector = (NettyChannelInjector) Accessors.getMethodAccessorOrNull(
|
|
||||||
TemporaryPlayerFactory.class, "getInjectorFromPlayer", Player.class
|
|
||||||
).invoke(null, player);
|
|
||||||
return FuzzyReflection.getFieldValue(injector, Channel.class, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reimplementation of the tasks injected Floodgate in ProtocolLib that are not run due to a bug
|
|
||||||
* @see <a href="https://github.com/GeyserMC/Floodgate/issues/143">Issue Floodgate#143</a>
|
|
||||||
* @see <a href="https://github.com/GeyserMC/Floodgate/blob/5d5713ed9e9eeab0f4abdaa9cf5cd8619dc1909b/spigot/src/main/java/org/geysermc/floodgate/addon/data/SpigotDataHandler.java#L121-L175">Floodgate/SpigotDataHandler</a>
|
|
||||||
* @param packetEvent the PacketEvent that won't be processed by Floodgate
|
|
||||||
* @return false if the player was kicked
|
|
||||||
*/
|
|
||||||
private boolean processFloodgateTasks(PacketEvent packetEvent) {
|
|
||||||
PacketContainer packet = packetEvent.getPacket();
|
|
||||||
Player player = packetEvent.getPlayer();
|
|
||||||
FloodgatePlayer floodgatePlayer = getFloodgatePlayer(player);
|
|
||||||
if (floodgatePlayer == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// kick the player, if necessary
|
|
||||||
Channel channel = getChannel(packetEvent.getPlayer());
|
|
||||||
AttributeKey<String> kickMessageAttribute = AttributeKey.valueOf("floodgate-kick-message");
|
|
||||||
String kickMessage = channel.attr(kickMessageAttribute).get();
|
|
||||||
if (kickMessage != null) {
|
|
||||||
player.kickPlayer(kickMessage);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add prefix
|
|
||||||
String username = floodgatePlayer.getCorrectUsername();
|
|
||||||
if (packet.getGameProfiles().size() > 0) {
|
|
||||||
packet.getGameProfiles().write(0,
|
|
||||||
new WrappedGameProfile(floodgatePlayer.getCorrectUniqueId(), username));
|
|
||||||
} else {
|
|
||||||
packet.getStrings().write(0, username);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove real Floodgate data handler
|
|
||||||
ChannelHandler floodgateHandler = channel.pipeline().get("floodgate_data_handler");
|
|
||||||
channel.pipeline().remove(floodgateHandler);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-5
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,13 +32,14 @@ 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.listener.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 java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import static com.comphenix.protocol.PacketType.Login.Server.DISCONNECT;
|
import static com.comphenix.protocol.PacketType.Login.Server.DISCONNECT;
|
||||||
import static com.comphenix.protocol.PacketType.Login.Server.ENCRYPTION_BEGIN;
|
import static com.comphenix.protocol.PacketType.Login.Server.ENCRYPTION_BEGIN;
|
||||||
|
|
||||||
@@ -51,6 +52,7 @@ 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) {
|
||||||
@@ -71,7 +73,7 @@ class ProtocolLibLoginSource implements LoginSource {
|
|||||||
*/
|
*/
|
||||||
PacketContainer newPacket = new PacketContainer(ENCRYPTION_BEGIN);
|
PacketContainer newPacket = new PacketContainer(ENCRYPTION_BEGIN);
|
||||||
|
|
||||||
newPacket.getStrings().write(0, "");
|
newPacket.getStrings().write(0, serverId);
|
||||||
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()) {
|
||||||
@@ -83,8 +85,6 @@ 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);
|
||||||
@@ -116,6 +116,10 @@ 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();
|
||||||
}
|
}
|
||||||
@@ -125,6 +129,7 @@ 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)
|
||||||
+ '}';
|
+ '}';
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,6 +30,7 @@ import com.comphenix.protocol.wrappers.WrappedSignedProperty;
|
|||||||
import com.github.games647.craftapi.model.skin.Textures;
|
import com.github.games647.craftapi.model.skin.Textures;
|
||||||
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 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.EventPriority;
|
||||||
|
|||||||
+46
-78
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,18 +28,14 @@ package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
|||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
import com.comphenix.protocol.injector.netty.channel.NettyChannelInjector;
|
|
||||||
import com.comphenix.protocol.injector.packet.PacketRegistry;
|
|
||||||
import com.comphenix.protocol.injector.temporary.TemporaryPlayerFactory;
|
import com.comphenix.protocol.injector.temporary.TemporaryPlayerFactory;
|
||||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||||
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.ConstructorAccessor;
|
|
||||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||||
import com.comphenix.protocol.wrappers.BukkitConverters;
|
import com.comphenix.protocol.wrappers.BukkitConverters;
|
||||||
import com.comphenix.protocol.wrappers.Converters;
|
|
||||||
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||||
import com.comphenix.protocol.wrappers.WrappedProfilePublicKey.WrappedProfileKeyData;
|
import com.comphenix.protocol.wrappers.WrappedProfilePublicKey.WrappedProfileKeyData;
|
||||||
@@ -48,12 +44,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.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@@ -66,19 +58,25 @@ import java.util.Arrays;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import static com.comphenix.protocol.PacketType.Login.Client.START;
|
import static com.comphenix.protocol.PacketType.Login.Client.START;
|
||||||
import static com.comphenix.protocol.PacketType.Login.Server.DISCONNECT;
|
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 String ADDRESS_VERIFY_WARNING = "This indicates the use of reverse-proxy like HAProxy, "
|
private static final Class<?> ENCRYPTION_CLASS;
|
||||||
+ "TCPShield, BungeeCord, Velocity, etc. "
|
|
||||||
+ "By default (configurable in the config) this plugin requests Mojang to verify the connecting IP "
|
static {
|
||||||
+ "to this server with the one used to log into Minecraft to prevent MITM attacks. In "
|
ENCRYPTION_CLASS = MinecraftReflection.getMinecraftClass(
|
||||||
+ "order to work this security feature, the actual client IP needs to be forwarding "
|
"util." + ENCRYPTION_CLASS_NAME, ENCRYPTION_CLASS_NAME
|
||||||
+ "(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.";
|
}
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
private final FastLoginBukkit plugin;
|
||||||
private final PacketEvent packetEvent;
|
private final PacketEvent packetEvent;
|
||||||
@@ -91,8 +89,6 @@ 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,
|
||||||
@@ -112,11 +108,11 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
verifyResponse(session);
|
verifyResponse(session);
|
||||||
} finally {
|
} finally {
|
||||||
//this is a fake packet; it shouldn't be sent to the server
|
//this is a fake packet; it shouldn't be sent to the server
|
||||||
synchronized (packetEvent.getAsyncMarker().getProcessingLock()) {
|
// synchronized (packetEvent.getAsyncMarker().getProcessingLock()) {
|
||||||
packetEvent.setCancelled(true);
|
packetEvent.setCancelled(true);
|
||||||
}
|
// }
|
||||||
|
|
||||||
ProtocolLibrary.getProtocolManager().getAsynchronousManager().signalPacketTransmission(packetEvent);
|
// ProtocolLibrary.getProtocolManager().getAsynchronousManager().signalPacketTransmission(packetEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,26 +150,9 @@ 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 "
|
"GameProfile {} ({}) tried to log in with an invalid session. ServerId: {}",
|
||||||
+ "1) Client IP address contacting Mojang and server during server join were different "
|
session.getRequestUsername(), socketAddress, serverId
|
||||||
+ "(Do you use a reverse proxy? -> Enable IP forwarding, "
|
|
||||||
+ "or disable the feature in the config). "
|
|
||||||
+ "2) Player is offline, but tried to bypass the authentication "
|
|
||||||
+ "3) Client uses an outdated username for connecting (Fix: Restart client)",
|
|
||||||
requestedUsername, address
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (InetUtils.isLocalAddress(address)) {
|
|
||||||
plugin.getLog().warn(
|
|
||||||
"The incoming request for player {} uses a local IP address",
|
|
||||||
requestedUsername
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
@@ -195,10 +174,10 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
|
|
||||||
session.setVerifiedUsername(realUsername);
|
session.setVerifiedUsername(realUsername);
|
||||||
session.setUuid(verification.getId());
|
session.setUuid(verification.getId());
|
||||||
session.setVerifiedPremium(true);
|
session.setVerified(true);
|
||||||
|
|
||||||
setPremiumUUID(session.getUuid());
|
setPremiumUUID(session.getUuid());
|
||||||
receiveFakeStartPacket(realUsername, session.getClientPublicKey(), session.getUuid());
|
receiveFakeStartPacket(realUsername, session.getClientPublicKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPremiumUUID(UUID premiumUUID) {
|
private void setPremiumUUID(UUID premiumUUID) {
|
||||||
@@ -218,36 +197,34 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
|
|
||||||
//try to get the networkManager from ProtocolLib
|
//try to get the networkManager from ProtocolLib
|
||||||
private Object getNetworkManager() throws ClassNotFoundException {
|
private Object getNetworkManager() throws ClassNotFoundException {
|
||||||
NettyChannelInjector injectorContainer = (NettyChannelInjector) Accessors.getMethodAccessorOrNull(
|
Object injectorContainer = TemporaryPlayerFactory.getInjectorFromPlayer(player);
|
||||||
TemporaryPlayerFactory.class, "getInjectorFromPlayer", Player.class
|
|
||||||
).invoke(null, player);
|
|
||||||
|
|
||||||
FieldAccessor accessor = Accessors.getFieldAccessorOrNull(
|
// ChannelInjector
|
||||||
NettyChannelInjector.class, "networkManager", Object.class
|
Class<?> injectorClass = Class.forName("com.comphenix.protocol.injector.netty.Injector");
|
||||||
);
|
Object rawInjector = FuzzyReflection.getFieldValue(injectorContainer, injectorClass, true);
|
||||||
return accessor.get(injectorContainer);
|
|
||||||
|
Class<?> rawInjectorClass = rawInjector.getClass();
|
||||||
|
FieldAccessor accessor = Accessors.getFieldAccessorOrNull(rawInjectorClass, "networkManager", Object.class);
|
||||||
|
return accessor.get(rawInjector);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (encryptKeyMethod == null || encryptMethod == null) {
|
if (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
|
||||||
encryptKeyMethod = FuzzyReflection.fromClass(networkManagerClass)
|
encryptMethod = 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(encryptionClass)
|
cipherMethod = FuzzyReflection.fromClass(ENCRYPTION_CLASS)
|
||||||
.getMethodByParameters("a", int.class, Key.class);
|
.getMethodByParameters("a", int.class, Key.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,9 +233,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 (encryptKeyMethod != null) {
|
if (cipherMethod == null) {
|
||||||
// Encrypt/decrypt packet flow, this behaviour is expected by the client
|
// Encrypt/decrypt packet flow, this behaviour is expected by the client
|
||||||
encryptKeyMethod.invoke(networkManager, loginKey);
|
encryptMethod.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);
|
||||||
@@ -291,22 +268,15 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//fake a new login packet in order to let the server handle all the other stuff
|
//fake a new login packet in order to let the server handle all the other stuff
|
||||||
private void receiveFakeStartPacket(String username, ClientPublicKey clientKey, UUID uuid) {
|
private void receiveFakeStartPacket(String username, ClientPublicKey clientKey) {
|
||||||
PacketContainer startPacket;
|
//see StartPacketListener for packet information
|
||||||
if (new MinecraftVersion(1, 20, 2).atOrAbove()) {
|
PacketContainer startPacket = new PacketContainer(START);
|
||||||
startPacket = new PacketContainer(START);
|
|
||||||
startPacket.getStrings().write(0, username);
|
if (MinecraftVersion.atOrAbove(new MinecraftVersion(1, 19, 0))) {
|
||||||
startPacket.getUUIDs().write(0, uuid);
|
|
||||||
} else if (new MinecraftVersion(1, 19, 3).atOrAbove()) {
|
|
||||||
startPacket = new PacketContainer(START);
|
|
||||||
startPacket.getStrings().write(0, username);
|
|
||||||
startPacket.getOptionals(Converters.passthrough(UUID.class)).write(0, Optional.of(uuid));
|
|
||||||
} else if (new MinecraftVersion(1, 19, 0).atOrAbove()) {
|
|
||||||
startPacket = new PacketContainer(START);
|
|
||||||
startPacket.getStrings().write(0, username);
|
startPacket.getStrings().write(0, username);
|
||||||
|
|
||||||
EquivalentConverter<WrappedProfileKeyData> converter = BukkitConverters.getWrappedPublicKeyDataConverter();
|
EquivalentConverter<WrappedProfileKeyData> converter = BukkitConverters.getWrappedPublicKeyDataConverter();
|
||||||
Optional<WrappedProfileKeyData> wrappedKey = Optional.ofNullable(clientKey).map(key ->
|
val wrappedKey = Optional.ofNullable(clientKey).map(key ->
|
||||||
new WrappedProfileKeyData(clientKey.expiry(), clientKey.key(), clientKey.signature())
|
new WrappedProfileKeyData(clientKey.expiry(), clientKey.key(), clientKey.signature())
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -314,14 +284,12 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
} else {
|
} else {
|
||||||
//uuid is ignored by the packet definition
|
//uuid is ignored by the packet definition
|
||||||
WrappedGameProfile fakeProfile = new WrappedGameProfile(UUID.randomUUID(), username);
|
WrappedGameProfile fakeProfile = new WrappedGameProfile(UUID.randomUUID(), username);
|
||||||
|
startPacket.getGameProfiles().write(0, fakeProfile);
|
||||||
Class<?> profileHandleType = fakeProfile.getHandleType();
|
|
||||||
Class<?> packetHandleType = PacketRegistry.getPacketClassFromType(START);
|
|
||||||
ConstructorAccessor startCons = Accessors.getConstructorAccessorOrNull(packetHandleType, profileHandleType);
|
|
||||||
startPacket = new PacketContainer(START, startCons.invoke(fakeProfile.getHandle()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//we don't want to handle our own packets so ignore filters
|
//we don't want to handle our own packets so ignore filters
|
||||||
ProtocolLibrary.getProtocolManager().receiveClientPacket(player, startPacket, false);
|
startPacket.setMeta(ProtocolLibListener.SOURCE_META_KEY, plugin.getName());
|
||||||
|
ProtocolLibrary.getProtocolManager().receiveClientPacket(player, startPacket, true);
|
||||||
|
plugin.getLog().info("Sending new fake login start packet to {}-{}", player, username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-38
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,47 +27,18 @@ package com.github.games647.fastlogin.bukkit.listener.protocollib.packet;
|
|||||||
|
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.StringJoiner;
|
|
||||||
|
|
||||||
|
import lombok.Value;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Accessors(fluent = true)
|
||||||
|
@Value(staticConstructor = "of")
|
||||||
public class ClientPublicKey {
|
public class ClientPublicKey {
|
||||||
|
Instant expiry;
|
||||||
private final Instant expiry;
|
PublicKey key;
|
||||||
private final PublicKey key;
|
byte[] signature;
|
||||||
private final byte[] signature;
|
|
||||||
|
|
||||||
public Instant expiry() {
|
|
||||||
return expiry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PublicKey key() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] signature() {
|
|
||||||
return signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientPublicKey(Instant expiry, PublicKey key, byte[] signature) {
|
|
||||||
this.expiry = expiry;
|
|
||||||
this.key = key;
|
|
||||||
this.signature = signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ClientPublicKey of(Instant expiry, PublicKey key, byte[] signature) {
|
|
||||||
return new ClientPublicKey(expiry, key, signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExpired(Instant verifyTimestamp) {
|
public boolean isExpired(Instant verifyTimestamp) {
|
||||||
return !verifyTimestamp.isBefore(expiry);
|
return !verifyTimestamp.isBefore(expiry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return new StringJoiner(", ", ClientPublicKey.class.getSimpleName() + '[', "]")
|
|
||||||
.add("expiry=" + expiry)
|
|
||||||
.add("key=" + Base64.getEncoder().encodeToString(key.getEncoded()))
|
|
||||||
.add("signature=" + Base64.getEncoder().encodeToString(signature))
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,10 +26,11 @@
|
|||||||
package com.github.games647.fastlogin.bukkit.listener.protocolsupport;
|
package com.github.games647.fastlogin.bukkit.listener.protocolsupport;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||||
import protocolsupport.api.events.PlayerLoginStartEvent;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
import protocolsupport.api.events.PlayerLoginStartEvent;
|
||||||
|
|
||||||
public class ProtocolLoginSource implements LoginSource {
|
public class ProtocolLoginSource implements LoginSource {
|
||||||
|
|
||||||
private final PlayerLoginStartEvent loginStartEvent;
|
private final PlayerLoginStartEvent loginStartEvent;
|
||||||
|
|||||||
+8
-7
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,11 +29,15 @@ import com.github.games647.craftapi.UUIDAdapter;
|
|||||||
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.event.BukkitFastLoginPreLoginEvent;
|
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
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.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 java.net.InetSocketAddress;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@@ -42,9 +46,6 @@ import protocolsupport.api.events.ConnectionCloseEvent;
|
|||||||
import protocolsupport.api.events.PlayerLoginStartEvent;
|
import protocolsupport.api.events.PlayerLoginStartEvent;
|
||||||
import protocolsupport.api.events.PlayerProfileCompleteEvent;
|
import protocolsupport.api.events.PlayerProfileCompleteEvent;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class ProtocolSupportListener extends JoinManagement<Player, CommandSender, ProtocolLoginSource>
|
public class ProtocolSupportListener extends JoinManagement<Player, CommandSender, ProtocolLoginSource>
|
||||||
implements Listener {
|
implements Listener {
|
||||||
|
|
||||||
@@ -101,7 +102,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
|
|||||||
BukkitLoginSession session = plugin.getSession(address);
|
BukkitLoginSession session = plugin.getSession(address);
|
||||||
|
|
||||||
if (session != null && profileCompleteEvent.getConnection().getProfile().isOnlineMode()) {
|
if (session != null && profileCompleteEvent.getConnection().getProfile().isOnlineMode()) {
|
||||||
session.setVerifiedPremium(true);
|
session.setVerified(true);
|
||||||
|
|
||||||
if (!plugin.getConfig().getBoolean("premiumUuid")) {
|
if (!plugin.getConfig().getBoolean("premiumUuid")) {
|
||||||
String username = Optional.ofNullable(profileCompleteEvent.getForcedName())
|
String username = Optional.ofNullable(profileCompleteEvent.getForcedName())
|
||||||
@@ -125,7 +126,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
|
|||||||
source.enableOnlinemode();
|
source.enableOnlinemode();
|
||||||
|
|
||||||
String ip = source.getAddress().getAddress().getHostAddress();
|
String ip = source.getAddress().getAddress().getHostAddress();
|
||||||
plugin.getCore().addLoginAttempt(ip, username);
|
plugin.getCore().getPendingLogin().put(ip + username, new Object());
|
||||||
|
|
||||||
BukkitLoginSession playerSession = new BukkitLoginSession(username, registered, profile);
|
BukkitLoginSession playerSession = new BukkitLoginSession(username, registered, profile);
|
||||||
plugin.putSession(source.getAddress(), playerSession);
|
plugin.putSession(source.getAddress(), playerSession);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,16 +32,16 @@ import com.github.games647.fastlogin.bukkit.hook.LogItHook;
|
|||||||
import com.github.games647.fastlogin.bukkit.hook.LoginSecurityHook;
|
import com.github.games647.fastlogin.bukkit.hook.LoginSecurityHook;
|
||||||
import com.github.games647.fastlogin.bukkit.hook.UltraAuthHook;
|
import com.github.games647.fastlogin.bukkit.hook.UltraAuthHook;
|
||||||
import com.github.games647.fastlogin.bukkit.hook.XAuthHook;
|
import com.github.games647.fastlogin.bukkit.hook.XAuthHook;
|
||||||
import com.github.games647.fastlogin.bukkit.hook.PasskyHook;
|
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
public class DelayedAuthHook implements Runnable {
|
public class DelayedAuthHook implements Runnable {
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
private final FastLoginBukkit plugin;
|
||||||
@@ -95,7 +95,7 @@ public class DelayedAuthHook implements Runnable {
|
|||||||
try {
|
try {
|
||||||
List<Class<? extends AuthPlugin<Player>>> hooks = Arrays.asList(AuthMeHook.class,
|
List<Class<? extends AuthPlugin<Player>>> hooks = Arrays.asList(AuthMeHook.class,
|
||||||
CrazyLoginHook.class, LogItHook.class, LoginSecurityHook.class, UltraAuthHook.class,
|
CrazyLoginHook.class, LogItHook.class, LoginSecurityHook.class, UltraAuthHook.class,
|
||||||
XAuthHook.class, PasskyHook.class);
|
XAuthHook.class);
|
||||||
|
|
||||||
for (Class<? extends AuthPlugin<Player>> clazz : hooks) {
|
for (Class<? extends AuthPlugin<Player>> clazz : hooks) {
|
||||||
String pluginName = clazz.getSimpleName();
|
String pluginName = clazz.getSimpleName();
|
||||||
|
|||||||
+6
-5
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,14 +29,15 @@ 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.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.github.games647.fastlogin.core.shared.FloodgateManagement;
|
import com.github.games647.fastlogin.core.shared.FloodgateManagement;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
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;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class FloodgateAuthTask extends FloodgateManagement<Player, CommandSender, BukkitLoginSession, FastLoginBukkit> {
|
public class FloodgateAuthTask extends FloodgateManagement<Player, CommandSender, BukkitLoginSession, FastLoginBukkit> {
|
||||||
|
|
||||||
public FloodgateAuthTask(FastLoginCore<Player, CommandSender, FastLoginBukkit> core, Player player,
|
public FloodgateAuthTask(FastLoginCore<Player, CommandSender, FastLoginBukkit> core, Player player,
|
||||||
@@ -49,7 +50,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.setVerifiedPremium(isAutoAuthAllowed(autoLoginFloodgate));
|
session.setVerified(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-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,19 +29,20 @@ 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.event.BukkitFastLoginAutoLoginEvent;
|
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginAutoLoginEvent;
|
||||||
import com.github.games647.fastlogin.core.PremiumStatus;
|
import com.github.games647.fastlogin.core.PremiumStatus;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.message.SuccessMessage;
|
import com.github.games647.fastlogin.core.message.SuccessMessage;
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.github.games647.fastlogin.core.shared.ForceLoginManagement;
|
import com.github.games647.fastlogin.core.shared.ForceLoginManagement;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
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;
|
||||||
import org.bukkit.metadata.FixedMetadataValue;
|
import org.bukkit.metadata.FixedMetadataValue;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
|
|
||||||
public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender, BukkitLoginSession, FastLoginBukkit> {
|
public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender, BukkitLoginSession, FastLoginBukkit> {
|
||||||
|
|
||||||
public ForceLoginTask(FastLoginCore<Player, CommandSender, FastLoginBukkit> core, Player player,
|
public ForceLoginTask(FastLoginCore<Player, CommandSender, FastLoginBukkit> core, Player player,
|
||||||
@@ -103,6 +104,6 @@ public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOnlineMode() {
|
public boolean isOnlineMode() {
|
||||||
return session.isVerifiedPremium();
|
return session.isVerified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ softdepend:
|
|||||||
- floodgate
|
- floodgate
|
||||||
# Auth plugins
|
# Auth plugins
|
||||||
- AuthMe
|
- AuthMe
|
||||||
- CrazyLogin
|
|
||||||
- LoginSecurity
|
- LoginSecurity
|
||||||
|
- SodionAuth
|
||||||
|
- xAuth
|
||||||
- LogIt
|
- LogIt
|
||||||
- UltraAuth
|
- UltraAuth
|
||||||
- xAuth
|
- CrazyLogin
|
||||||
- Passky
|
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
${project.parent.name}:
|
${project.parent.name}:
|
||||||
@@ -45,11 +45,6 @@ commands:
|
|||||||
usage: /<command> [player]
|
usage: /<command> [player]
|
||||||
permission: ${project.artifactId}.command.cracked
|
permission: ${project.artifactId}.command.cracked
|
||||||
|
|
||||||
fldelete:
|
|
||||||
description: 'Delete player profile data'
|
|
||||||
usage: /<command> [player]
|
|
||||||
permission: ${project.artifactId}.command.delete
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
${project.artifactId}.command.premium:
|
${project.artifactId}.command.premium:
|
||||||
description: 'Label themselves as premium'
|
description: 'Label themselves as premium'
|
||||||
@@ -68,7 +63,3 @@ permissions:
|
|||||||
description: 'Label others as cracked'
|
description: 'Label others as cracked'
|
||||||
children:
|
children:
|
||||||
${project.artifactId}.command.cracked: true
|
${project.artifactId}.command.cracked: true
|
||||||
|
|
||||||
${project.artifactId}.command.delete:
|
|
||||||
description: 'Delete other players profile data'
|
|
||||||
default: op
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,9 +26,11 @@
|
|||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.CommonUtil;
|
import com.github.games647.fastlogin.core.CommonUtil;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.chat.ComponentSerializer;
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
@@ -37,14 +39,12 @@ class FastLoginBukkitTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testRGB() {
|
void testRGB() {
|
||||||
String message = "&x00002a00002b&lText";
|
val message = "&x00002a00002b&lText";
|
||||||
String msg = CommonUtil.translateColorCodes(message);
|
val msg = CommonUtil.translateColorCodes(message);
|
||||||
assertEquals(msg, "§x00002a00002b§lText");
|
assertEquals(msg, "§x00002a00002b§lText");
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
val components = TextComponent.fromLegacyText(msg);
|
||||||
BaseComponent[] components = TextComponent.fromLegacyText(msg);
|
val expected = "{\"bold\":true,\"color\":\"#00a00b\",\"text\":\"Text\"}";
|
||||||
String 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-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,8 +27,10 @@ package com.github.games647.fastlogin.bukkit;
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
import fr.xephi.authme.api.v3.AuthMeApi;
|
import fr.xephi.authme.api.v3.AuthMeApi;
|
||||||
import fr.xephi.authme.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|||||||
+3
-1
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,8 +27,10 @@ package com.github.games647.fastlogin.bukkit.hook;
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
import de.st_ddt.crazylogin.CrazyLogin;
|
import de.st_ddt.crazylogin.CrazyLogin;
|
||||||
import de.st_ddt.crazylogin.listener.PlayerListener;
|
import de.st_ddt.crazylogin.listener.PlayerListener;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|||||||
+4
-2
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,11 +32,13 @@ import com.google.gson.stream.JsonWriter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
|
|
||||||
public class Base64Adapter extends TypeAdapter<byte[]> {
|
public class Base64Adapter extends TypeAdapter<byte[]> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(JsonWriter out, byte[] value) throws IOException {
|
public void write(JsonWriter out, byte[] value) throws IOException {
|
||||||
String encoded = Base64.getEncoder().encodeToString(value);
|
val encoded = Base64.getEncoder().encodeToString(value);
|
||||||
out.value(encoded);
|
out.value(encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+43
-62
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,18 +27,8 @@ package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
|||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.SignatureTestData.SignatureData;
|
import com.github.games647.fastlogin.bukkit.listener.protocollib.SignatureTestData.SignatureData;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
||||||
import com.google.common.hash.Hasher;
|
|
||||||
import com.google.common.hash.Hashing;
|
import com.google.common.hash.Hashing;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
|
||||||
import javax.crypto.Cipher;
|
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
@@ -51,17 +41,27 @@ import java.security.SignatureException;
|
|||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
import javax.crypto.BadPaddingException;
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
class EncryptionUtilTest {
|
class EncryptionUtilTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testVerifyToken() {
|
void testVerifyToken() {
|
||||||
Random random = ThreadLocalRandom.current();
|
val random = ThreadLocalRandom.current();
|
||||||
byte[] token = EncryptionUtil.generateVerifyToken(random);
|
byte[] token = EncryptionUtil.generateVerifyToken(random);
|
||||||
|
|
||||||
assertAll(
|
assertAll(
|
||||||
@@ -89,11 +89,11 @@ class EncryptionUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testExpiredClientKey() throws Exception {
|
void testExpiredClientKey() throws Exception {
|
||||||
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
val clientKey = 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
|
||||||
Instant expiredTimestamp = clientKey.expiry();
|
val expiredTimestamp = clientKey.expiry();
|
||||||
assertFalse(EncryptionUtil.verifyClientKey(clientKey, expiredTimestamp, null));
|
assertFalse(EncryptionUtil.verifyClientKey(clientKey, expiredTimestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@@ -106,42 +106,24 @@ 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 {
|
||||||
ClientPublicKey clientKey = ResourceLoader.loadClientKey(clientKeySource);
|
val clientKey = 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testValidClientKey() throws Exception {
|
void testValidClientKey() throws Exception {
|
||||||
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
||||||
Instant 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));
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testValid191ClientKey() throws Exception {
|
|
||||||
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
|
|
||||||
Instant verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
|
||||||
|
|
||||||
UUID ownerPremiumId = UUID.fromString("0aaa2c13-922a-411b-b655-9b8c08404695");
|
|
||||||
assertTrue(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp, ownerPremiumId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testIncorrect191ClientOwner() throws Exception {
|
|
||||||
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key_19_1.json");
|
|
||||||
Instant verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
|
||||||
|
|
||||||
UUID ownerPremiumId = UUID.fromString("61699b2e-d327-4a01-9f1e-0ea8c3f06bc6");
|
|
||||||
assertFalse(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp, ownerPremiumId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testDecryptSharedSecret() throws Exception {
|
void testDecryptSharedSecret() throws Exception {
|
||||||
KeyPair serverPair = EncryptionUtil.generateKeyPair();
|
KeyPair serverPair = EncryptionUtil.generateKeyPair();
|
||||||
PublicKey serverPK = serverPair.getPublic();
|
val serverPK = serverPair.getPublic();
|
||||||
|
|
||||||
SecretKey secretKey = generateSharedKey();
|
SecretKey secretKey = generateSharedKey();
|
||||||
byte[] encryptedSecret = encrypt(serverPK, secretKey.getEncoded());
|
byte[] encryptedSecret = encrypt(serverPK, secretKey.getEncoded());
|
||||||
@@ -153,7 +135,7 @@ class EncryptionUtilTest {
|
|||||||
private static byte[] encrypt(PublicKey receiverKey, byte... message)
|
private static byte[] encrypt(PublicKey receiverKey, byte... message)
|
||||||
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
|
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
|
||||||
IllegalBlockSizeException, BadPaddingException {
|
IllegalBlockSizeException, BadPaddingException {
|
||||||
Cipher encryptCipher = Cipher.getInstance(receiverKey.getAlgorithm());
|
val encryptCipher = Cipher.getInstance(receiverKey.getAlgorithm());
|
||||||
encryptCipher.init(Cipher.ENCRYPT_MODE, receiverKey);
|
encryptCipher.init(Cipher.ENCRYPT_MODE, receiverKey);
|
||||||
return encryptCipher.doFinal(message);
|
return encryptCipher.doFinal(message);
|
||||||
}
|
}
|
||||||
@@ -169,16 +151,15 @@ class EncryptionUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testServerIdHash() throws Exception {
|
void testServerIdHash() throws Exception {
|
||||||
String serverId = "";
|
val serverId = "";
|
||||||
SecretKeySpec sharedSecret = generateSharedKey();
|
val sharedSecret = generateSharedKey();
|
||||||
PublicKey serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
|
val serverPK = 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getServerHash(@SuppressWarnings("SameParameterValue") CharSequence serverId,
|
private static String getServerHash(CharSequence serverId, SecretKey sharedSecret, PublicKey serverPK) {
|
||||||
SecretKey sharedSecret, PublicKey serverPK) {
|
|
||||||
// https://wiki.vg/Protocol_Encryption#Client
|
// https://wiki.vg/Protocol_Encryption#Client
|
||||||
// sha1 := Sha1()
|
// sha1 := Sha1()
|
||||||
// sha1.update(ASCII encoding of the server id string from Encryption Request)
|
// sha1.update(ASCII encoding of the server id string from Encryption Request)
|
||||||
@@ -186,7 +167,7 @@ class EncryptionUtilTest {
|
|||||||
// sha1.update(server's encoded public key from Encryption Request)
|
// sha1.update(server's encoded public key from Encryption Request)
|
||||||
// hash := sha1.hexdigest() # String of hex characters
|
// hash := sha1.hexdigest() # String of hex characters
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
Hasher hasher = Hashing.sha1().newHasher();
|
val hasher = Hashing.sha1().newHasher();
|
||||||
hasher.putString(serverId, StandardCharsets.US_ASCII);
|
hasher.putString(serverId, StandardCharsets.US_ASCII);
|
||||||
hasher.putBytes(sharedSecret.getEncoded());
|
hasher.putBytes(sharedSecret.getEncoded());
|
||||||
hasher.putBytes(serverPK.getEncoded());
|
hasher.putBytes(serverPK.getEncoded());
|
||||||
@@ -199,9 +180,9 @@ class EncryptionUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testServerIdHashWrongSecret() throws Exception {
|
void testServerIdHashWrongSecret() throws Exception {
|
||||||
String serverId = "";
|
val serverId = "";
|
||||||
SecretKeySpec sharedSecret = generateSharedKey();
|
val sharedSecret = generateSharedKey();
|
||||||
PublicKey serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
|
val serverPK = 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);
|
||||||
@@ -209,12 +190,12 @@ class EncryptionUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testServerIdHashWrongServerKey() {
|
void testServerIdHashWrongServerKey() {
|
||||||
String serverId = "";
|
val serverId = "";
|
||||||
SecretKeySpec sharedSecret = generateSharedKey();
|
val sharedSecret = generateSharedKey();
|
||||||
PublicKey serverPK = EncryptionUtil.generateKeyPair().getPublic();
|
val serverPK = EncryptionUtil.generateKeyPair().getPublic();
|
||||||
|
|
||||||
String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
|
String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
|
||||||
PublicKey wrongPK = EncryptionUtil.generateKeyPair().getPublic();
|
val wrongPK = EncryptionUtil.generateKeyPair().getPublic();
|
||||||
assertNotEquals(EncryptionUtil.getServerIdHashString("", sharedSecret, wrongPK), sessionHash);
|
assertNotEquals(EncryptionUtil.getServerIdHashString("", sharedSecret, wrongPK), sessionHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,8 +239,8 @@ class EncryptionUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
void testNonce() throws Exception {
|
void testNonce() throws Exception {
|
||||||
byte[] expected = {1, 2, 3, 4};
|
byte[] expected = {1, 2, 3, 4};
|
||||||
KeyPair serverKey = EncryptionUtil.generateKeyPair();
|
val serverKey = EncryptionUtil.generateKeyPair();
|
||||||
byte[] encryptedNonce = encrypt(serverKey.getPublic(), expected);
|
val encryptedNonce = encrypt(serverKey.getPublic(), expected);
|
||||||
|
|
||||||
assertTrue(EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce));
|
assertTrue(EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce));
|
||||||
}
|
}
|
||||||
@@ -267,19 +248,19 @@ class EncryptionUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
void testNonceIncorrect() throws Exception {
|
void testNonceIncorrect() throws Exception {
|
||||||
byte[] expected = {1, 2, 3, 4};
|
byte[] expected = {1, 2, 3, 4};
|
||||||
KeyPair serverKey = EncryptionUtil.generateKeyPair();
|
val serverKey = EncryptionUtil.generateKeyPair();
|
||||||
|
|
||||||
// flipped first character
|
// flipped first character
|
||||||
byte[] encryptedNonce = encrypt(serverKey.getPublic(), new byte[]{0, 2, 3, 4});
|
val encryptedNonce = encrypt(serverKey.getPublic(), new byte[]{0, 2, 3, 4});
|
||||||
assertFalse(EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce));
|
assertFalse(EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testNonceFailedDecryption() throws Exception {
|
void testNonceFailedDecryption() throws Exception {
|
||||||
byte[] expected = {1, 2, 3, 4};
|
byte[] expected = {1, 2, 3, 4};
|
||||||
KeyPair serverKey = EncryptionUtil.generateKeyPair();
|
val serverKey = EncryptionUtil.generateKeyPair();
|
||||||
// generate a new keypair that is different
|
// generate a new keypair that is different
|
||||||
byte[] encryptedNonce = encrypt(EncryptionUtil.generateKeyPair().getPublic(), expected);
|
val encryptedNonce = encrypt(EncryptionUtil.generateKeyPair().getPublic(), expected);
|
||||||
|
|
||||||
assertThrows(GeneralSecurityException.class,
|
assertThrows(GeneralSecurityException.class,
|
||||||
() -> EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce)
|
() -> EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce)
|
||||||
@@ -289,7 +270,7 @@ class EncryptionUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
void testNonceIncorrectEmpty() {
|
void testNonceIncorrectEmpty() {
|
||||||
byte[] expected = {1, 2, 3, 4};
|
byte[] expected = {1, 2, 3, 4};
|
||||||
KeyPair serverKey = EncryptionUtil.generateKeyPair();
|
val serverKey = EncryptionUtil.generateKeyPair();
|
||||||
byte[] encryptedNonce = {};
|
byte[] encryptedNonce = {};
|
||||||
|
|
||||||
assertThrows(GeneralSecurityException.class,
|
assertThrows(GeneralSecurityException.class,
|
||||||
|
|||||||
+6
-6
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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.fastlogin.bukkit.listener.protocollib.packet.ClientPu
|
|||||||
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;
|
||||||
import org.bouncycastle.util.io.pem.PemObject;
|
|
||||||
import org.bouncycastle.util.io.pem.PemReader;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
@@ -42,12 +40,14 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
import java.security.interfaces.RSAPrivateKey;
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.security.spec.KeySpec;
|
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
|
import org.bouncycastle.util.io.pem.PemObject;
|
||||||
|
import org.bouncycastle.util.io.pem.PemReader;
|
||||||
|
|
||||||
public class ResourceLoader {
|
public class ResourceLoader {
|
||||||
|
|
||||||
public static RSAPrivateKey parsePrivateKey(String keySpec)
|
public static RSAPrivateKey parsePrivateKey(String keySpec)
|
||||||
@@ -58,7 +58,7 @@ public class ResourceLoader {
|
|||||||
) {
|
) {
|
||||||
PemObject pemObject = pemReader.readPemObject();
|
PemObject pemObject = pemReader.readPemObject();
|
||||||
byte[] content = pemObject.getContent();
|
byte[] content = pemObject.getContent();
|
||||||
KeySpec privateKeySpec = new PKCS8EncodedKeySpec(content);
|
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(content);
|
||||||
|
|
||||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||||
return (RSAPrivateKey) factory.generatePrivate(privateKeySpec);
|
return (RSAPrivateKey) factory.generatePrivate(privateKeySpec);
|
||||||
@@ -88,7 +88,7 @@ public class ResourceLoader {
|
|||||||
) {
|
) {
|
||||||
PemObject pemObject = pemReader.readPemObject();
|
PemObject pemObject = pemReader.readPemObject();
|
||||||
byte[] content = pemObject.getContent();
|
byte[] content = pemObject.getContent();
|
||||||
KeySpec pubKeySpec = new X509EncodedKeySpec(content);
|
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
|
||||||
|
|
||||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||||
return (RSAPublicKey) factory.generatePublic(pubKeySpec);
|
return (RSAPublicKey) factory.generatePublic(pubKeySpec);
|
||||||
|
|||||||
+5
-4
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,14 +30,15 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.annotations.JsonAdapter;
|
import com.google.gson.annotations.JsonAdapter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
|
|
||||||
public class SignatureTestData {
|
public class SignatureTestData {
|
||||||
|
|
||||||
public static SignatureTestData fromResource(String resourceName) throws IOException {
|
public static SignatureTestData fromResource(String resourceName) throws IOException {
|
||||||
URL keyUrl = Resources.getResource(resourceName);
|
val keyUrl = Resources.getResource(resourceName);
|
||||||
String encodedSignature = Resources.toString(keyUrl, StandardCharsets.US_ASCII);
|
val encodedSignature = Resources.toString(keyUrl, StandardCharsets.US_ASCII);
|
||||||
|
|
||||||
return new Gson().fromJson(encodedSignature, SignatureTestData.class);
|
return new Gson().fromJson(encodedSignature, SignatureTestData.class);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,14 +29,16 @@ import com.comphenix.protocol.injector.packet.PacketRegistry;
|
|||||||
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;
|
||||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.MockedStatic;
|
import org.mockito.MockedStatic;
|
||||||
|
|
||||||
import java.util.Optional;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.Mockito.mockStatic;
|
import static org.mockito.Mockito.mockStatic;
|
||||||
|
|
||||||
class VerifyResponseTaskTest {
|
class VerifyResponseTaskTest {
|
||||||
|
|||||||
+4
-2
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,8 @@
|
|||||||
package com.github.games647.fastlogin.bukkit.task;
|
package com.github.games647.fastlogin.bukkit.task;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -35,7 +37,7 @@ class DelayedAuthHookTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void createNewReflectiveInstance() throws ReflectiveOperationException {
|
void createNewReflectiveInstance() throws ReflectiveOperationException {
|
||||||
DelayedAuthHook authHook = new DelayedAuthHook(null);
|
val authHook = new DelayedAuthHook(null);
|
||||||
assertNotNull(authHook.newInstance(DummyHook.class));
|
assertNotNull(authHook.newInstance(DummyHook.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"expires_at": "2022-07-29T12:57:39.011Z",
|
|
||||||
"key": "-----BEGIN RSA PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtYOUXdid0c09/eYoseLf8qG9fKQ/G2DY9wlSyEZaFMflwZ8ZpLFYigxzfaimpT3A5cbFIdIH2W2sYl5PwsKSs128GBh/rxXUEZlLkIkS+EfxyuMp9ITclxAjCqvFgfJbZHugtB9Ofi6knCEEgjFwMDh2efdpOXkCxtHuPFfnVzDJBbHWdlCCtJesMAnA2jCT7CqCwsi7sW2QxuTarqHP/cHKiBeBIu/SngGUB6eWmvAwERW5x2D+O26w8Z5sQCND3xQ4D868RALiPNG94TyKoJV+jKi0tTUmjGGs/1ksbSGDQb5xqIH0NYKZhoZrczYPNmJX4k7g5BA5RHX8AGORaQIDAQAB\n-----END RSA PUBLIC KEY-----\n",
|
|
||||||
"signature": "Fto/GDqEMTWpNrktWSi3tnP3ZZlo8r4Jled/5PKYRvaL/zksfjB2RK2O8pZL+w5mI2VAViTVAQmSJEF2o/BCb2L0zXp3/hC9VhZj5NTVi4KbHfnfMorj7/WJP2vvMgVxIxgLb3EEQXGS2Mmo0w2ikUVauwXgLWECvVt10KAZnTAWNIvpM8NUoZ2oCCxVimYHBtlwWQ7WvowAatP4ypa7fo3xhQg8Im1hvQDsFTNp58pgnd7l3l99xLj1uYOUJM06HGZJ/Xd0kzzJz44Csh4m50Q0RP4Nq5L+fYPeUx990Z1r1lw0sSayk+vA2Qnxgbs/z6KgkxfhBg7oOlp4ykl9cLC2kA/LdV6igqsdr/KoP4GWxwTA7RgQbhMkDFdmIg1W+gh3XqwASFQK2BAN/eAfmDTf8u9BtOEF7Ehn9uPOaiFiGztyaHxXNIkVSPTG2GXMFSijnd3Ms28jHYVY/67INTnDRmN0//KzBAoTRMe1S5idai19kug4EUVIRKDziipowzCPdbD18trdQGpK0dYOrw9XQiQd4N4V3eItpyAULGiZd8KcjgKo4orqgsUfNyhLI1keig7TyJUE3FkBOfX4hlZBm7Q/Wq4hwarlc5yZIjhsuivKV/q4tcnYYPwjP7kNMRsIApWG+yHmSIo8QfZhBiPxvtWSSLZgoFgnlxfaEko="
|
|
||||||
}
|
|
||||||
+40
-52
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015-2024 games647 and contributors
|
Copyright (c) 2015-2022 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 @@
|
|||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -40,10 +40,6 @@
|
|||||||
<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>
|
||||||
|
|
||||||
@@ -51,12 +47,20 @@
|
|||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.6.0</version>
|
<version>3.3.0</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>
|
||||||
@@ -70,15 +74,13 @@
|
|||||||
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
|
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
|
||||||
<!-- Located in META-INF/services -->
|
<!-- Located in META-INF/services -->
|
||||||
<transformers>
|
<transformers>
|
||||||
<transformer
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||||
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
|
||||||
</transformers>
|
</transformers>
|
||||||
<filters>
|
<filters>
|
||||||
<filter>
|
<filter>
|
||||||
<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>
|
||||||
@@ -102,6 +104,11 @@
|
|||||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
|
||||||
|
<repository>
|
||||||
|
<id>spigotplugins-repo</id>
|
||||||
|
<url>https://maven.gamestrike.de/mvn/</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
<repository>
|
<repository>
|
||||||
<id>jitpack.io</id>
|
<id>jitpack.io</id>
|
||||||
<url>https://jitpack.io</url>
|
<url>https://jitpack.io</url>
|
||||||
@@ -117,33 +124,13 @@
|
|||||||
<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.20-R0.2-SNAPSHOT</version>
|
<version>1.19-R0.1-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<!-- Use our own newer api version -->
|
<!-- Use our own newer api version -->
|
||||||
<exclusions>
|
<exclusions>
|
||||||
@@ -152,14 +139,13 @@
|
|||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>com.mysql</groupId>
|
<groupId>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>
|
||||||
@@ -168,11 +154,6 @@
|
|||||||
<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>
|
||||||
@@ -181,10 +162,6 @@
|
|||||||
<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>
|
||||||
|
|
||||||
@@ -196,7 +173,11 @@
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>*</groupId>
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.geysermc.cumulus</groupId>
|
||||||
<artifactId>*</artifactId>
|
<artifactId>*</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
@@ -204,7 +185,7 @@
|
|||||||
|
|
||||||
<!-- Bedrock player bridge -->
|
<!-- Bedrock player bridge -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.geysermc.geyser</groupId>
|
<groupId>org.geysermc</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>${geyser.version}</version>
|
<version>${geyser.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
@@ -218,16 +199,10 @@
|
|||||||
|
|
||||||
<!-- We need the API, but it was excluded above -->
|
<!-- We need the API, but it was excluded above -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.geysermc.geyser</groupId>
|
<groupId>org.geysermc</groupId>
|
||||||
<artifactId>api</artifactId>
|
<artifactId>geyser-api</artifactId>
|
||||||
<version>${geyser.version}</version>
|
<version>${geyser.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>*</groupId>
|
|
||||||
<artifactId>*</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--Login plugin-->
|
<!--Login plugin-->
|
||||||
@@ -238,5 +213,18 @@
|
|||||||
<scope>system</scope>
|
<scope>system</scope>
|
||||||
<systemPath>${project.basedir}/lib/BungeeAuth-1.4.jar</systemPath>
|
<systemPath>${project.basedir}/lib/BungeeAuth-1.4.jar</systemPath>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.xxschrandxx.bca</groupId>
|
||||||
|
<artifactId>BungeeCordAuthenticator</artifactId>
|
||||||
|
<version>0.0.3</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>*</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,8 +25,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bungee;
|
package com.github.games647.fastlogin.bungee;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
|
|
||||||
public class BungeeLoginSession extends LoginSession {
|
public class BungeeLoginSession extends LoginSession {
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,14 +26,15 @@
|
|||||||
package com.github.games647.fastlogin.bungee;
|
package com.github.games647.fastlogin.bungee;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
import net.md_5.bungee.api.ChatColor;
|
import net.md_5.bungee.api.ChatColor;
|
||||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
import net.md_5.bungee.api.event.PreLoginEvent;
|
import net.md_5.bungee.api.event.PreLoginEvent;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
|
|
||||||
public class BungeeLoginSource implements LoginSource {
|
public class BungeeLoginSource implements LoginSource {
|
||||||
|
|
||||||
private final PendingConnection connection;
|
private final PendingConnection connection;
|
||||||
@@ -54,15 +55,9 @@ public class BungeeLoginSource implements LoginSource {
|
|||||||
preLoginEvent.setCancelled(true);
|
preLoginEvent.setCancelled(true);
|
||||||
|
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
preLoginEvent.setReason(
|
preLoginEvent.setCancelReason(new ComponentBuilder("Kicked").color(ChatColor.WHITE).create());
|
||||||
TextComponent.fromArray(
|
|
||||||
new ComponentBuilder("Kicked").color(ChatColor.WHITE).create()
|
|
||||||
));
|
|
||||||
} else {
|
} else {
|
||||||
preLoginEvent.setReason(
|
preLoginEvent.setCancelReason(TextComponent.fromLegacyText(message));
|
||||||
TextComponent.fromArray(
|
|
||||||
TextComponent.fromLegacyText(message)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +73,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-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,8 +26,10 @@
|
|||||||
package com.github.games647.fastlogin.bungee;
|
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.hook.BungeeCordAuthenticatorBungeeHook;
|
||||||
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;
|
||||||
@@ -37,13 +39,19 @@ 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;
|
||||||
import com.google.common.io.ByteArrayDataOutput;
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
|
||||||
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.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
@@ -53,16 +61,11 @@ import net.md_5.bungee.api.plugin.Listener;
|
|||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import net.md_5.bungee.api.plugin.PluginManager;
|
import net.md_5.bungee.api.plugin.PluginManager;
|
||||||
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
|
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
|
||||||
|
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.concurrent.ThreadFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BungeeCord version of FastLogin. This plugin keeps track on online mode connections.
|
* BungeeCord version of FastLogin. This plugin keeps track on online mode connections.
|
||||||
*/
|
*/
|
||||||
@@ -98,7 +101,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.getAntiBotService());
|
Listener connectListener = new ConnectListener(this, core.getAntiBot());
|
||||||
pluginManager.registerListener(this, connectListener);
|
pluginManager.registerListener(this, connectListener);
|
||||||
pluginManager.registerListener(this, new PluginMessageListener(this));
|
pluginManager.registerListener(this, new PluginMessageListener(this));
|
||||||
|
|
||||||
@@ -126,9 +129,8 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
|||||||
|
|
||||||
private void registerHook() {
|
private void registerHook() {
|
||||||
try {
|
try {
|
||||||
List<Class<? extends AuthPlugin<ProxiedPlayer>>> hooks = Collections.singletonList(
|
List<Class<? extends AuthPlugin<ProxiedPlayer>>> hooks = Arrays.asList(
|
||||||
BungeeAuthHook.class
|
BungeeAuthHook.class, BungeeCordAuthenticatorBungeeHook.class);
|
||||||
);
|
|
||||||
|
|
||||||
for (Class<? extends AuthPlugin<ProxiedPlayer>> clazz : hooks) {
|
for (Class<? extends AuthPlugin<ProxiedPlayer>> clazz : hooks) {
|
||||||
String pluginName = clazz.getSimpleName();
|
String pluginName = clazz.getSimpleName();
|
||||||
|
|||||||
+3
-2
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,9 +25,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bungee.event;
|
package com.github.games647.fastlogin.bungee.event;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
import net.md_5.bungee.api.plugin.Cancellable;
|
import net.md_5.bungee.api.plugin.Cancellable;
|
||||||
import net.md_5.bungee.api.plugin.Event;
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,9 +25,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bungee.event;
|
package com.github.games647.fastlogin.bungee.event;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||||
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 net.md_5.bungee.api.plugin.Event;
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
public class BungeeFastLoginPreLoginEvent extends Event implements FastLoginPreLoginEvent {
|
public class BungeeFastLoginPreLoginEvent extends Event implements FastLoginPreLoginEvent {
|
||||||
|
|||||||
+3
-2
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,8 +25,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bungee.event;
|
package com.github.games647.fastlogin.bungee.event;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
|
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
import net.md_5.bungee.api.plugin.Event;
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
public class BungeeFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
|
public class BungeeFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,16 +27,18 @@ package com.github.games647.fastlogin.bungee.hook;
|
|||||||
|
|
||||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
|
|
||||||
import me.vik1395.BungeeAuth.Main;
|
import me.vik1395.BungeeAuth.Main;
|
||||||
import me.vik1395.BungeeAuthAPI.RequestHandler;
|
import me.vik1395.BungeeAuthAPI.RequestHandler;
|
||||||
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GitHub:
|
* GitHub:
|
||||||
* <a href="https://github.com/vik1395/BungeeAuth-Minecraft">...</a>
|
* <a href="https://github.com/vik1395/BungeeAuth-Minecraft">...</a>
|
||||||
* <p>
|
*
|
||||||
* Project page:
|
* Project page:
|
||||||
* <p>
|
*
|
||||||
* Spigot:
|
* Spigot:
|
||||||
* <a href="https://www.spigotmc.org/resources/bungeeauth.493/">...</a>
|
* <a href="https://www.spigotmc.org/resources/bungeeauth.493/">...</a>
|
||||||
*/
|
*/
|
||||||
|
|||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2022 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.bungee.hook;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||||
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
|
|
||||||
|
import de.xxschrandxx.bca.bungee.BungeeCordAuthenticatorBungee;
|
||||||
|
import de.xxschrandxx.bca.bungee.api.BungeeCordAuthenticatorBungeeAPI;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GitHub:
|
||||||
|
* <a href="https://github.com/xXSchrandXx/SpigotPlugins/tree/master/BungeeCordAuthenticator">...</a>
|
||||||
|
* <p>
|
||||||
|
* Project page:
|
||||||
|
* <p>
|
||||||
|
* Spigot: <a href="https://www.spigotmc.org/resources/bungeecordauthenticator.87669/">...</a>
|
||||||
|
*/
|
||||||
|
public class BungeeCordAuthenticatorBungeeHook implements AuthPlugin<ProxiedPlayer> {
|
||||||
|
|
||||||
|
public final BungeeCordAuthenticatorBungeeAPI api;
|
||||||
|
|
||||||
|
public BungeeCordAuthenticatorBungeeHook(FastLoginBungee plugin) {
|
||||||
|
api = ((BungeeCordAuthenticatorBungee) plugin.getProxy().getPluginManager()
|
||||||
|
.getPlugin("BungeeCordAuthenticatorBungee")).getAPI();
|
||||||
|
plugin.getLog().info("BungeeCordAuthenticatorHook | Hooked successful!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean forceLogin(ProxiedPlayer player) {
|
||||||
|
if (api.isAuthenticated(player)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
api.setAuthenticated(player);
|
||||||
|
} catch (SQLException sqlEx) {
|
||||||
|
api.getLogger().log(Level.WARNING, "Failed to force login", sqlEx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRegistered(String playerName) {
|
||||||
|
try {
|
||||||
|
return api.getSQL().checkPlayerEntry(playerName);
|
||||||
|
} catch (SQLException sqlEx) {
|
||||||
|
api.getLogger().log(Level.WARNING, "Failed to check registration", sqlEx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean forceRegister(ProxiedPlayer player, String password) {
|
||||||
|
try {
|
||||||
|
return api.createPlayerEntry(player, password);
|
||||||
|
} catch (SQLException sqlEx) {
|
||||||
|
api.getLogger().log(Level.WARNING, "Failed to force register", sqlEx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
-41
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -31,12 +31,20 @@ import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
|||||||
import com.github.games647.fastlogin.bungee.task.AsyncPremiumCheck;
|
import com.github.games647.fastlogin.bungee.task.AsyncPremiumCheck;
|
||||||
import com.github.games647.fastlogin.bungee.task.FloodgateAuthTask;
|
import com.github.games647.fastlogin.bungee.task.FloodgateAuthTask;
|
||||||
import com.github.games647.fastlogin.bungee.task.ForceLoginTask;
|
import com.github.games647.fastlogin.bungee.task.ForceLoginTask;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
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.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||||
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.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodHandles.Lookup;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
@@ -51,17 +59,11 @@ import net.md_5.bungee.connection.LoginResult;
|
|||||||
import net.md_5.bungee.event.EventHandler;
|
import net.md_5.bungee.event.EventHandler;
|
||||||
import net.md_5.bungee.event.EventPriority;
|
import net.md_5.bungee.event.EventPriority;
|
||||||
import net.md_5.bungee.protocol.Property;
|
import net.md_5.bungee.protocol.Property;
|
||||||
|
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.invoke.MethodHandles.Lookup;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables online mode logins for specified users and sends plugin message to the Bukkit version of this plugin in
|
* Enables online mode logins for specified users and sends plugin message to the Bukkit version of this plugin in
|
||||||
* order to clear that the connection is online mode.
|
* order to clear that the connection is online mode.
|
||||||
@@ -71,43 +73,25 @@ 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 uniqueIdHandle = null;
|
MethodHandle setHandle = 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);
|
|
||||||
try {
|
Field uuidField = InitialHandler.class.getDeclaredField(UUID_FIELD_NAME);
|
||||||
rewriterHandle = getHandlerSetter(lookup, REWRITE_ID_NAME);
|
uuidField.setAccessible(true);
|
||||||
} catch (NoSuchFieldException noSuchFieldEx) {
|
setHandle = lookup.unreflectSetter(uuidField);
|
||||||
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 UUID field implementation; Disabling premium UUID and skin won't work.",
|
"Cannot find Bungee initial handler; Disabling premium UUID and skin won't work.",
|
||||||
reflectiveOperationException
|
reflectiveOperationException
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIQUE_ID_SETTER = uniqueIdHandle;
|
UNIQUE_ID_SETTER = setHandle;
|
||||||
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;
|
||||||
@@ -197,12 +181,6 @@ 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) {
|
||||||
@@ -235,7 +213,7 @@ public class ConnectListener implements Listener {
|
|||||||
|
|
||||||
// delay sending force command, because Paper will process the login event asynchronously
|
// 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
|
// 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
|
// 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);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,14 +28,17 @@ package com.github.games647.fastlogin.bungee.listener;
|
|||||||
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
|
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
|
||||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||||
import com.github.games647.fastlogin.bungee.task.AsyncToggleMessage;
|
import com.github.games647.fastlogin.bungee.task.AsyncToggleMessage;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||||
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
|
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
|
||||||
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.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
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 java.util.Arrays;
|
||||||
|
|
||||||
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.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
@@ -44,8 +47,6 @@ import net.md_5.bungee.api.event.PluginMessageEvent;
|
|||||||
import net.md_5.bungee.api.plugin.Listener;
|
import net.md_5.bungee.api.plugin.Listener;
|
||||||
import net.md_5.bungee.event.EventHandler;
|
import net.md_5.bungee.event.EventHandler;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class PluginMessageListener implements Listener {
|
public class PluginMessageListener implements Listener {
|
||||||
|
|
||||||
private final FastLoginBungee plugin;
|
private final FastLoginBungee plugin;
|
||||||
@@ -131,7 +132,7 @@ public class PluginMessageListener implements Listener {
|
|||||||
loginSession.setRegistered(true);
|
loginSession.setRegistered(true);
|
||||||
|
|
||||||
if (!loginSession.isAlreadySaved()) {
|
if (!loginSession.isAlreadySaved()) {
|
||||||
playerProfile.setOnlinemodePreferred(true);
|
playerProfile.setPremium(true);
|
||||||
plugin.getCore().getStorage().save(playerProfile);
|
plugin.getCore().getStorage().save(playerProfile);
|
||||||
loginSession.setAlreadySaved(true);
|
loginSession.setAlreadySaved(true);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,10 @@ import com.github.games647.fastlogin.bungee.BungeeLoginSession;
|
|||||||
import com.github.games647.fastlogin.bungee.BungeeLoginSource;
|
import com.github.games647.fastlogin.bungee.BungeeLoginSource;
|
||||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||||
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginPreLoginEvent;
|
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginPreLoginEvent;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.JoinManagement;
|
import com.github.games647.fastlogin.core.shared.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 net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
@@ -81,7 +82,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().addLoginAttempt(ip, username);
|
plugin.getCore().getPendingLogin().put(ip + username, new Object());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+8
-12
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,9 +27,10 @@ package com.github.games647.fastlogin.bungee.task;
|
|||||||
|
|
||||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||||
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginPremiumToggleEvent;
|
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginPremiumToggleEvent;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
|
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
@@ -64,34 +65,29 @@ 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.isExistingPlayer() && !playerProfile.isOnlinemodePreferred()) {
|
if (playerProfile.isSaved() && !playerProfile.isPremium()) {
|
||||||
sendMessage("not-premium");
|
sendMessage("not-premium");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerProfile.setOnlinemodePreferred(false);
|
playerProfile.setPremium(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()))
|
||||||
? PremiumToggleReason.COMMAND_OTHER : PremiumToggleReason.COMMAND_SELF;
|
? PremiumToggleReason.COMMAND_OTHER : PremiumToggleReason.COMMAND_SELF;
|
||||||
core.getPlugin().getProxy().getPluginManager().callEvent(
|
core.getPlugin().getProxy().getPluginManager().callEvent(
|
||||||
new BungeeFastLoginPremiumToggleEvent(playerProfile, reason));
|
new BungeeFastLoginPremiumToggleEvent(playerProfile, reason));
|
||||||
|
sendMessage("remove-premium");
|
||||||
if (isPlayerSender && core.getConfig().getBoolean("kick-toggle", true)) {
|
|
||||||
sender.disconnect(TextComponent.fromLegacyText(core.getMessage("remove-premium")));
|
|
||||||
} else {
|
|
||||||
sendMessage("remove-premium");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void activatePremium() {
|
private void activatePremium() {
|
||||||
StoredProfile playerProfile = core.getStorage().loadProfile(targetPlayer);
|
StoredProfile playerProfile = core.getStorage().loadProfile(targetPlayer);
|
||||||
if (playerProfile.isOnlinemodePreferred()) {
|
if (playerProfile.isPremium()) {
|
||||||
sendMessage("already-exists");
|
sendMessage("already-exists");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerProfile.setOnlinemodePreferred(true);
|
playerProfile.setPremium(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;
|
||||||
|
|||||||
+7
-5
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,14 +29,16 @@ import com.github.games647.fastlogin.bungee.BungeeLoginSession;
|
|||||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.github.games647.fastlogin.core.shared.FloodgateManagement;
|
import com.github.games647.fastlogin.core.shared.FloodgateManagement;
|
||||||
import net.md_5.bungee.api.CommandSender;
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|
||||||
import net.md_5.bungee.api.connection.Server;
|
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.CommandSender;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
import net.md_5.bungee.api.connection.Server;
|
||||||
|
|
||||||
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
|
||||||
public class FloodgateAuthTask
|
public class FloodgateAuthTask
|
||||||
extends FloodgateManagement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> {
|
extends FloodgateManagement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> {
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,6 +28,7 @@ package com.github.games647.fastlogin.bungee.task;
|
|||||||
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
|
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
|
||||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||||
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginAutoLoginEvent;
|
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginAutoLoginEvent;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
||||||
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
||||||
import com.github.games647.fastlogin.core.message.LoginActionMessage.Type;
|
import com.github.games647.fastlogin.core.message.LoginActionMessage.Type;
|
||||||
@@ -35,14 +36,14 @@ import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
|||||||
import com.github.games647.fastlogin.core.shared.ForceLoginManagement;
|
import com.github.games647.fastlogin.core.shared.ForceLoginManagement;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
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 java.util.UUID;
|
|
||||||
|
|
||||||
public class ForceLoginTask
|
public class ForceLoginTask
|
||||||
extends ForceLoginManagement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> {
|
extends ForceLoginManagement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> {
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ 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
|
||||||
|
|||||||
+5
-4
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,13 +25,14 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bungee.listener;
|
package com.github.games647.fastlogin.bungee.listener;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import net.md_5.bungee.BungeeCord;
|
import net.md_5.bungee.BungeeCord;
|
||||||
import net.md_5.bungee.conf.Configuration;
|
import net.md_5.bungee.conf.Configuration;
|
||||||
import net.md_5.bungee.connection.InitialHandler;
|
import net.md_5.bungee.connection.InitialHandler;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import org.junit.jupiter.api.Test;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|||||||
+31
-9
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015-2024 games647 and contributors
|
Copyright (c) 2015-2022 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,6 +29,35 @@
|
|||||||
<!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
|
||||||
@@ -72,7 +101,6 @@
|
|||||||
<module name="LineLength">
|
<module name="LineLength">
|
||||||
<property name="max" value="120"/>
|
<property name="max" value="120"/>
|
||||||
<property name="fileExtensions" value="java"/>
|
<property name="fileExtensions" value="java"/>
|
||||||
<property name="ignorePattern" value="^ *\* *@see.+$"/>
|
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
<!-- Checks for whitespace -->
|
<!-- Checks for whitespace -->
|
||||||
@@ -191,12 +219,6 @@
|
|||||||
<property name="optional" value="true"/>
|
<property name="optional" value="true"/>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
<!-- Suppress filters via comments -->
|
|
||||||
<!-- https://stackoverflow.com/a/4023351/9767089 -->
|
|
||||||
<module name="SuppressionCommentFilter">
|
|
||||||
<property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>
|
|
||||||
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
|
|
||||||
<property name="checkFormat" value="$1"/>
|
|
||||||
</module>
|
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
</module>
|
</module>
|
||||||
|
|||||||
+56
-85
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015-2024 games647 and contributors
|
Copyright (c) 2015-2022 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 @@
|
|||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -39,17 +39,12 @@
|
|||||||
<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>
|
||||||
<repository>
|
<repository>
|
||||||
<id>luck-repo</id>
|
<id>luck-repo</id>
|
||||||
<url>https://ci.lucko.me/plugin/repository/everything/</url>
|
<url>https://ci.lucko.me/plugin/repository/everything</url>
|
||||||
<snapshots>
|
<snapshots>
|
||||||
<enabled>false</enabled>
|
<enabled>false</enabled>
|
||||||
</snapshots>
|
</snapshots>
|
||||||
@@ -60,7 +55,7 @@
|
|||||||
</repository>
|
</repository>
|
||||||
<!-- Floodgate -->
|
<!-- Floodgate -->
|
||||||
<repository>
|
<repository>
|
||||||
<id>opencollab</id>
|
<id>opencollab-snapshot</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,56 +63,6 @@
|
|||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<version>3.4.2</version>
|
|
||||||
<configuration>
|
|
||||||
<archive>
|
|
||||||
<manifestEntries>
|
|
||||||
<Automatic-Module-Name>com.github.games647.fastlogin.core</Automatic-Module-Name>
|
|
||||||
</manifestEntries>
|
|
||||||
</archive>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</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 -->
|
||||||
|
|
||||||
@@ -140,21 +85,20 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-jdk14</artifactId>
|
<artifactId>slf4j-jdk14</artifactId>
|
||||||
<version>2.0.17</version>
|
<version>2.0.0-alpha7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- snakeyaml is present in Bungee, Spigot, so we could use this independent implementation -->
|
<!-- snakeyaml is present in Bungee, Spigot, Cauldron, 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.20-R0.2</version>
|
<version>1.19-R0.1-20220702.004052-16</version>
|
||||||
</dependency>
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
<!-- This is optional in BungeeCord-config, so we include it here manually -->
|
<groupId>*</groupId>
|
||||||
<dependency>
|
<artifactId>*</artifactId>
|
||||||
<groupId>org.yaml</groupId>
|
</exclusion>
|
||||||
<artifactId>snakeyaml</artifactId>
|
</exclusions>
|
||||||
<version>2.4</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--Floodgate for Xbox Live Authentication-->
|
<!--Floodgate for Xbox Live Authentication-->
|
||||||
@@ -165,7 +109,11 @@
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>*</groupId>
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.geysermc.cumulus</groupId>
|
||||||
<artifactId>*</artifactId>
|
<artifactId>*</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
@@ -173,7 +121,7 @@
|
|||||||
|
|
||||||
<!-- Bedrock player bridge -->
|
<!-- Bedrock player bridge -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.geysermc.geyser</groupId>
|
<groupId>org.geysermc</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>${geyser.version}</version>
|
<version>${geyser.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
@@ -187,31 +135,54 @@
|
|||||||
|
|
||||||
<!-- We need the API, but it was excluded above -->
|
<!-- We need the API, but it was excluded above -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.geysermc.geyser</groupId>
|
<groupId>org.geysermc</groupId>
|
||||||
<artifactId>api</artifactId>
|
<artifactId>geyser-api</artifactId>
|
||||||
<version>${geyser.version}</version>
|
<version>${geyser.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>*</groupId>
|
|
||||||
<artifactId>*</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--Common component for contacting the Mojang API-->
|
<!--Common component for contacting the Mojang API-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.games647</groupId>
|
<groupId>com.github.games647</groupId>
|
||||||
<artifactId>craftapi</artifactId>
|
<artifactId>craftapi</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>0.5.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Database driver included in Spigot -->
|
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee, Velocity) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.xerial</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
<artifactId>sqlite-jdbc</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>[3.36,)</version>
|
<!-- Old version for velocity -->
|
||||||
<scope>provided</scope>
|
<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.9.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
+25
-29
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,22 +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.core.scheduler;
|
package com.github.games647.fastlogin.core;
|
||||||
|
|
||||||
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;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public abstract class AbstractAsyncScheduler {
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
protected final Logger logger;
|
/**
|
||||||
protected final Executor processingPool;
|
* This limits the number of threads that are used at maximum. Thread creation can be very heavy for the CPU and
|
||||||
protected final AtomicInteger currentlyRunning = new AtomicInteger();
|
* context switching between threads too. However, we need many threads for blocking HTTP and database calls.
|
||||||
|
* Nevertheless, this number can be further limited, because the number of actually working database threads
|
||||||
|
* is limited by the size of our database pool. The goal is to separate concerns into processing and blocking only
|
||||||
|
* threads.
|
||||||
|
*/
|
||||||
|
public class AsyncScheduler {
|
||||||
|
|
||||||
public AbstractAsyncScheduler(Logger logger, Executor processingPool) {
|
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) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.processingPool = processingPool;
|
this.processingPool = processingPool;
|
||||||
}
|
}
|
||||||
@@ -50,25 +64,7 @@ public abstract class AbstractAsyncScheduler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> runAsyncDelayed(Runnable task, Duration delay) {
|
private void process(Runnable task) {
|
||||||
return CompletableFuture.runAsync(() -> {
|
|
||||||
currentlyRunning.incrementAndGet();
|
|
||||||
try {
|
|
||||||
Thread.sleep(delay.toMillis());
|
|
||||||
task.run();
|
|
||||||
} 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;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void process(Runnable task) {
|
|
||||||
currentlyRunning.incrementAndGet();
|
currentlyRunning.incrementAndGet();
|
||||||
try {
|
try {
|
||||||
task.run();
|
task.run();
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,26 +26,27 @@
|
|||||||
package com.github.games647.fastlogin.core;
|
package com.github.games647.fastlogin.core;
|
||||||
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
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;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.slf4j.jul.JDK14LoggerAdapter;
|
||||||
|
|
||||||
public final class CommonUtil {
|
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(Duration expireAfterWrite, int maxSize) {
|
public static <K, V> ConcurrentMap<K, V> buildCache(int expireAfterWrite, int maxSize) {
|
||||||
CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
|
CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
|
||||||
|
|
||||||
if (expireAfterWrite != null) {
|
if (expireAfterWrite > 0) {
|
||||||
builder.expireAfterWrite(expireAfterWrite);
|
builder.expireAfterWrite(expireAfterWrite, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxSize > 0) {
|
if (maxSize > 0) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
-62
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,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.core.storage;
|
package com.github.games647.fastlogin.core;
|
||||||
|
|
||||||
import com.github.games647.craftapi.model.Profile;
|
import com.github.games647.craftapi.model.Profile;
|
||||||
import com.github.games647.fastlogin.core.shared.FloodgateState;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -40,35 +39,27 @@ public class StoredProfile extends Profile {
|
|||||||
private final ReentrantLock saveLock = new ReentrantLock();
|
private final ReentrantLock saveLock = new ReentrantLock();
|
||||||
|
|
||||||
private boolean premium;
|
private boolean premium;
|
||||||
private FloodgateState floodgate;
|
|
||||||
private String lastIp;
|
private String lastIp;
|
||||||
private Instant lastLogin;
|
private Instant lastLogin;
|
||||||
|
|
||||||
public StoredProfile(long rowId, UUID uuid, String playerName, boolean premium, FloodgateState floodgate,
|
public StoredProfile(long rowId, UUID uuid, String playerName, boolean premium, String lastIp, Instant lastLogin) {
|
||||||
String lastIp, Instant lastLogin) {
|
|
||||||
super(uuid, playerName);
|
super(uuid, playerName);
|
||||||
|
|
||||||
this.rowId = rowId;
|
this.rowId = rowId;
|
||||||
this.premium = premium;
|
this.premium = premium;
|
||||||
this.floodgate = floodgate;
|
|
||||||
this.lastIp = lastIp;
|
this.lastIp = lastIp;
|
||||||
this.lastLogin = lastLogin;
|
this.lastLogin = lastLogin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StoredProfile(UUID uuid, String playerName, boolean premium, FloodgateState isFloodgate, String lastIp) {
|
|
||||||
this(-1, uuid, playerName, premium, isFloodgate, lastIp, Instant.now());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public StoredProfile(UUID uuid, String playerName, boolean premium, String lastIp) {
|
public StoredProfile(UUID uuid, String playerName, boolean premium, String lastIp) {
|
||||||
this(-1, uuid, playerName, premium, FloodgateState.FALSE, lastIp, Instant.now());
|
this(-1, uuid, playerName, premium, lastIp, Instant.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReentrantLock getSaveLock() {
|
public ReentrantLock getSaveLock() {
|
||||||
return saveLock;
|
return saveLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean isExistingPlayer() {
|
public synchronized boolean isSaved() {
|
||||||
return rowId >= 0;
|
return rowId >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,55 +88,14 @@ public class StoredProfile extends Profile {
|
|||||||
this.id = uniqueId;
|
this.id = uniqueId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return whether the online mode should be enabled for this player
|
|
||||||
* @deprecated {@link #isOnlinemodePreferred()} is recommended, because the name represents more its
|
|
||||||
* meaning
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public synchronized boolean isPremium() {
|
public synchronized boolean isPremium() {
|
||||||
return premium;
|
return premium;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the online mode preference for this player.
|
|
||||||
* <p>
|
|
||||||
* <b>
|
|
||||||
* Note: {@code false} doesn't represent that the player is offline. It could also mean that the player is premium,
|
|
||||||
* but didn't activated the premium login mode yet.
|
|
||||||
* </b>
|
|
||||||
*
|
|
||||||
* @return whether the online mode should be enabled for this player
|
|
||||||
*/
|
|
||||||
public synchronized boolean isOnlinemodePreferred() {
|
|
||||||
return premium;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param premium whether online mode is preferred
|
|
||||||
* @deprecated {@link #setOnlinemodePreferred(boolean)} is recommended, because of the better method name
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public synchronized void setPremium(boolean premium) {
|
public synchronized void setPremium(boolean premium) {
|
||||||
this.premium = premium;
|
this.premium = premium;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setOnlinemodePreferred(boolean premium) {
|
|
||||||
this.premium = premium;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized FloodgateState getFloodgate() {
|
|
||||||
return floodgate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized boolean isFloodgateMigrated() {
|
|
||||||
return floodgate != FloodgateState.NOT_MIGRATED;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void setFloodgate(FloodgateState floodgate) {
|
|
||||||
this.floodgate = floodgate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized String getLastIp() {
|
public synchronized String getLastIp() {
|
||||||
return lastIp;
|
return lastIp;
|
||||||
}
|
}
|
||||||
@@ -178,7 +128,7 @@ public class StoredProfile extends Profile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return rowId == that.rowId && premium == that.premium
|
return rowId == that.rowId && premium == that.premium
|
||||||
&& Objects.equals(lastIp, that.lastIp) && lastLogin.equals(that.lastLogin);
|
&& Objects.equals(lastIp, that.lastIp) && lastLogin.equals(that.lastLogin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -189,11 +139,10 @@ public class StoredProfile extends Profile {
|
|||||||
@Override
|
@Override
|
||||||
public synchronized String toString() {
|
public synchronized String toString() {
|
||||||
return this.getClass().getSimpleName() + '{'
|
return this.getClass().getSimpleName() + '{'
|
||||||
+ "rowId=" + rowId
|
+ "rowId=" + rowId
|
||||||
+ ", premium=" + premium
|
+ ", premium=" + premium
|
||||||
+ ", floodgate=" + floodgate
|
+ ", lastIp='" + lastIp + '\''
|
||||||
+ ", lastIp='" + lastIp + '\''
|
+ ", lastLogin=" + lastLogin
|
||||||
+ ", lastLogin=" + lastLogin
|
+ "} " + super.toString();
|
||||||
+ "} " + super.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,10 +25,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.core.antibot;
|
package com.github.games647.fastlogin.core.antibot;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
public class AntiBotService {
|
public class AntiBotService {
|
||||||
|
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
@@ -57,6 +57,6 @@ public class AntiBotService {
|
|||||||
|
|
||||||
Block,
|
Block,
|
||||||
|
|
||||||
Continue
|
Continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-7
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,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.core;
|
package com.github.games647.fastlogin.core.mojang;
|
||||||
|
|
||||||
import com.github.games647.craftapi.model.auth.Verification;
|
import com.github.games647.craftapi.model.auth.Verification;
|
||||||
import com.github.games647.craftapi.resolver.MojangResolver;
|
import com.github.games647.craftapi.resolver.MojangResolver;
|
||||||
import com.github.games647.craftapi.resolver.Options;
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@@ -43,12 +44,38 @@ import java.util.Optional;
|
|||||||
*/
|
*/
|
||||||
public class ProxyAgnosticMojangResolver extends MojangResolver {
|
public class ProxyAgnosticMojangResolver extends MojangResolver {
|
||||||
|
|
||||||
public ProxyAgnosticMojangResolver(Options options) {
|
private static final String HOST = "sessionserver.mojang.com";
|
||||||
super(options);
|
|
||||||
}
|
/**
|
||||||
|
* 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 {
|
||||||
return super.hasJoined(username, serverHash, null);
|
String url = String.format(ENDPOINT, username, serverHash);
|
||||||
|
|
||||||
|
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-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
|
|||||||
+4
-9
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -107,7 +107,7 @@ public class TickingRateLimiter implements RateLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TimeRecord implements Comparable<TimeRecord> {
|
private static class TimeRecord implements Comparable<Long> {
|
||||||
|
|
||||||
private final long firstMinuteRecord;
|
private final long firstMinuteRecord;
|
||||||
private final long expireTime;
|
private final long expireTime;
|
||||||
@@ -131,9 +131,9 @@ public class TickingRateLimiter implements RateLimiter {
|
|||||||
return firstMinuteRecord + expireTime <= now;
|
return firstMinuteRecord + expireTime <= now;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(long other) {
|
@Override
|
||||||
|
public int compareTo(Long other) {
|
||||||
if (other < firstMinuteRecord) {
|
if (other < firstMinuteRecord) {
|
||||||
// other is earlier
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,10 +143,5 @@ public class TickingRateLimiter implements RateLimiter {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(TimeRecord other) {
|
|
||||||
return compareTo(other.firstMinuteRecord);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,7 @@ public interface AuthPlugin<P> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Login the premium (paid account) player after the player joined successfully the server.
|
* Login the premium (paid account) player after the player joined successfully the server.
|
||||||
* <p>
|
*
|
||||||
* <strong>This operation will be performed async while the player successfully
|
* <strong>This operation will be performed async while the player successfully
|
||||||
* joined the server.</strong>
|
* joined the server.</strong>
|
||||||
*
|
*
|
||||||
@@ -48,17 +48,17 @@ public interface AuthPlugin<P> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces a register in order to protect the paid account.
|
* Forces a register in order to protect the paid account.
|
||||||
* <p>
|
*
|
||||||
* <strong>This operation will be performed async while the player successfully
|
* <strong>This operation will be performed async while the player successfully
|
||||||
* joined the server.</strong>
|
* joined the server.</strong>
|
||||||
* <p>
|
*
|
||||||
* After a successful registration the player should be logged
|
* After a successful registration the player should be logged
|
||||||
* in too.
|
* in too.
|
||||||
* <p>
|
*
|
||||||
* The method will be called only for premium accounts.
|
* The method will be called only for premium accounts.
|
||||||
* So it's recommended to set additionally premium property
|
* So it's recommended to set additionally premium property
|
||||||
* if possible.
|
* if possible.
|
||||||
* <p>
|
*
|
||||||
* Background: If we don't register an account, cracked players
|
* Background: If we don't register an account, cracked players
|
||||||
* could steal the unregistered account from the paid
|
* could steal the unregistered account from the paid
|
||||||
* player account
|
* player account
|
||||||
@@ -71,11 +71,11 @@ public interface AuthPlugin<P> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether an account exists for this player name.
|
* Checks whether an account exists for this player name.
|
||||||
* <p>
|
*
|
||||||
* This check should check if a cracked player account exists,
|
* This check should check if a cracked player account exists,
|
||||||
* so we can be sure the premium player doesn't steal the account
|
* so we can be sure the premium player doesn't steal the account
|
||||||
* of that player.
|
* of that player.
|
||||||
* <p>
|
*
|
||||||
* This operation will be performed async while the player is
|
* This operation will be performed async while the player is
|
||||||
* connecting.
|
* connecting.
|
||||||
*
|
*
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,17 +25,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.core.hooks;
|
package com.github.games647.fastlogin.core.hooks;
|
||||||
|
|
||||||
/**
|
|
||||||
* Password generator for your auth plugin.
|
|
||||||
* @param <P> platform dependent player class
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface PasswordGenerator<P> {
|
public interface PasswordGenerator<P> {
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a password for a non-registered player
|
|
||||||
* @param player player representation
|
|
||||||
* @return generated password
|
|
||||||
*/
|
|
||||||
String getRandomPassword(P player);
|
String getRandomPassword(P player);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,9 +27,9 @@ package com.github.games647.fastlogin.core.hooks.bedrock;
|
|||||||
|
|
||||||
import com.github.games647.craftapi.model.Profile;
|
import com.github.games647.craftapi.model.Profile;
|
||||||
import com.github.games647.craftapi.resolver.RateLimitException;
|
import com.github.games647.craftapi.resolver.RateLimitException;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|||||||
+17
-4
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,16 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.core.hooks.bedrock;
|
package com.github.games647.fastlogin.core.hooks.bedrock;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
|
||||||
public class FloodgateService extends BedrockService<FloodgatePlayer> {
|
public class FloodgateService extends BedrockService<FloodgatePlayer> {
|
||||||
|
|
||||||
private final FloodgateApi floodgate;
|
private final FloodgateApi floodgate;
|
||||||
@@ -98,11 +99,23 @@ public class FloodgateService extends BedrockService<FloodgatePlayer> {
|
|||||||
* The FloodgateApi does not support querying players by name, so this function
|
* The FloodgateApi does not support querying players by name, so this function
|
||||||
* iterates over every online FloodgatePlayer and checks if the requested
|
* iterates over every online FloodgatePlayer and checks if the requested
|
||||||
* username can be found
|
* username can be found
|
||||||
|
* <br>
|
||||||
|
* <i>Falls back to non-prefixed name checks, if ProtocolLib is installed</i>
|
||||||
*
|
*
|
||||||
* @param prefixedUsername the name of the player with the prefix appended
|
* @param prefixedUsername the name of the player with the prefix appended
|
||||||
* @return FloodgatePlayer if found, null otherwise
|
* @return FloodgatePlayer if found, null otherwise
|
||||||
*/
|
*/
|
||||||
public FloodgatePlayer getBedrockPlayer(String prefixedUsername) {
|
public FloodgatePlayer getBedrockPlayer(String prefixedUsername) {
|
||||||
|
//prefixes are broken with ProtocolLib, so fall back to name checks without prefixes
|
||||||
|
//this should be removed if #493 gets fixed
|
||||||
|
if (core.getPlugin().isPluginInstalled("ProtocolLib")) {
|
||||||
|
for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) {
|
||||||
|
if (floodgatePlayer.getUsername().equals(prefixedUsername)) {
|
||||||
|
return floodgatePlayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) {
|
for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) {
|
||||||
if (floodgatePlayer.getCorrectUsername().equals(prefixedUsername)) {
|
if (floodgatePlayer.getCorrectUsername().equals(prefixedUsername)) {
|
||||||
return floodgatePlayer;
|
return floodgatePlayer;
|
||||||
|
|||||||
+7
-11
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
@@ -27,12 +27,13 @@ package com.github.games647.fastlogin.core.hooks.bedrock;
|
|||||||
|
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
|
||||||
import org.geysermc.geyser.api.network.AuthType;
|
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
import org.geysermc.geyser.session.auth.AuthType;
|
||||||
|
|
||||||
public class GeyserService extends BedrockService<GeyserSession> {
|
public class GeyserService extends BedrockService<GeyserSession> {
|
||||||
|
|
||||||
private final GeyserImpl geyser;
|
private final GeyserImpl geyser;
|
||||||
@@ -43,7 +44,7 @@ public class GeyserService extends BedrockService<GeyserSession> {
|
|||||||
super(core);
|
super(core);
|
||||||
this.geyser = geyser;
|
this.geyser = geyser;
|
||||||
this.core = core;
|
this.core = core;
|
||||||
this.authType = GeyserImpl.getInstance().getConfig().getRemote().authType();
|
this.authType = GeyserImpl.getInstance().getConfig().getRemote().getAuthType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -64,12 +65,7 @@ public class GeyserService extends BedrockService<GeyserSession> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GeyserSession getBedrockPlayer(String username) {
|
public GeyserSession getBedrockPlayer(String username) {
|
||||||
for (GeyserSession gSess : geyser.getSessionManager().getAllSessions()) {
|
return geyser.connectionByName(username);
|
||||||
if (username.equals(gSess.getClientData().getUsername())) {
|
|
||||||
return gSess;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
-3
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,7 +63,7 @@ public class LoginActionMessage implements ChannelMessage {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readFrom(ByteArrayDataInput input) {
|
public void readFrom(ByteArrayDataInput input) {
|
||||||
this.type = Type.values()[input.readByte()];
|
this.type = Type.values()[input.readInt()];
|
||||||
|
|
||||||
this.playerName = input.readUTF();
|
this.playerName = input.readUTF();
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ public class LoginActionMessage implements ChannelMessage {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(ByteArrayDataOutput output) {
|
public void writeTo(ByteArrayDataOutput output) {
|
||||||
output.writeByte(type.ordinal());
|
output.writeInt(type.ordinal());
|
||||||
|
|
||||||
//Data is sent through a random player. We have to tell the Bukkit version of this plugin the target
|
//Data is sent through a random player. We have to tell the Bukkit version of this plugin the target
|
||||||
output.writeUTF(playerName);
|
output.writeUTF(playerName);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,12 +48,4 @@ public class NamespaceKey {
|
|||||||
public static String getCombined(String namespace, String key) {
|
public static String getCombined(String namespace, String key) {
|
||||||
return new NamespaceKey(namespace, key).combined;
|
return new NamespaceKey(namespace, key).combined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNamespace() {
|
|
||||||
return namespace;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.core.scheduler;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This limits the number of threads that are used at maximum. Thread creation can be very heavy for the CPU and
|
|
||||||
* context switching between threads too. However, we need many threads for blocking HTTP and database calls.
|
|
||||||
* Nevertheless, this number can be further limited, because the number of actually working database threads
|
|
||||||
* is limited by the size of our database pool. The goal is to separate concerns into processing and blocking only
|
|
||||||
* threads.
|
|
||||||
*/
|
|
||||||
public class AsyncScheduler extends AbstractAsyncScheduler {
|
|
||||||
|
|
||||||
public AsyncScheduler(Logger logger, Executor processingPool) {
|
|
||||||
super(logger, processingPool);
|
|
||||||
logger.info("Using legacy platform scheduler for using an older Java version. "
|
|
||||||
+ "Upgrade Java to 21+ for improved performance");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
* Copyright (c) 2015-2022 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,10 +26,8 @@
|
|||||||
package com.github.games647.fastlogin.core.shared;
|
package com.github.games647.fastlogin.core.shared;
|
||||||
|
|
||||||
import com.github.games647.craftapi.resolver.MojangResolver;
|
import com.github.games647.craftapi.resolver.MojangResolver;
|
||||||
import com.github.games647.craftapi.resolver.Options;
|
|
||||||
import com.github.games647.craftapi.resolver.http.RotatingProxySelector;
|
import com.github.games647.craftapi.resolver.http.RotatingProxySelector;
|
||||||
import com.github.games647.fastlogin.core.CommonUtil;
|
import com.github.games647.fastlogin.core.CommonUtil;
|
||||||
import com.github.games647.fastlogin.core.ProxyAgnosticMojangResolver;
|
|
||||||
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.github.games647.fastlogin.core.antibot.RateLimiter;
|
import com.github.games647.fastlogin.core.antibot.RateLimiter;
|
||||||
@@ -37,24 +35,24 @@ import com.github.games647.fastlogin.core.antibot.TickingRateLimiter;
|
|||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
import com.github.games647.fastlogin.core.hooks.DefaultPasswordGenerator;
|
import com.github.games647.fastlogin.core.hooks.DefaultPasswordGenerator;
|
||||||
import com.github.games647.fastlogin.core.hooks.PasswordGenerator;
|
import com.github.games647.fastlogin.core.hooks.PasswordGenerator;
|
||||||
|
import com.github.games647.fastlogin.core.mojang.ProxyAgnosticMojangResolver;
|
||||||
import com.github.games647.fastlogin.core.storage.MySQLStorage;
|
import com.github.games647.fastlogin.core.storage.MySQLStorage;
|
||||||
import com.github.games647.fastlogin.core.storage.SQLStorage;
|
import com.github.games647.fastlogin.core.storage.SQLStorage;
|
||||||
import com.github.games647.fastlogin.core.storage.SQLiteStorage;
|
import com.github.games647.fastlogin.core.storage.SQLiteStorage;
|
||||||
import com.google.common.base.Ticker;
|
import com.google.common.base.Ticker;
|
||||||
|
import com.google.common.net.HostAndPort;
|
||||||
import com.zaxxer.hikari.HikariConfig;
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
import net.md_5.bungee.config.Configuration;
|
|
||||||
import net.md_5.bungee.config.ConfigurationProvider;
|
|
||||||
import net.md_5.bungee.config.YamlConfiguration;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.Proxy.Type;
|
import java.net.Proxy.Type;
|
||||||
|
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;
|
||||||
@@ -64,6 +62,12 @@ import java.util.UUID;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import net.md_5.bungee.config.Configuration;
|
||||||
|
import net.md_5.bungee.config.ConfigurationProvider;
|
||||||
|
import net.md_5.bungee.config.YamlConfiguration;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import static java.util.function.Function.identity;
|
import static java.util.function.Function.identity;
|
||||||
import static java.util.stream.Collectors.toMap;
|
import static java.util.stream.Collectors.toMap;
|
||||||
import static java.util.stream.Collectors.toSet;
|
import static java.util.stream.Collectors.toSet;
|
||||||
@@ -78,10 +82,7 @@ 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(
|
private final ConcurrentMap<String, Object> pendingLogin = CommonUtil.buildCache(5, -1);
|
||||||
Duration.ofMinutes(5), -1
|
|
||||||
);
|
|
||||||
|
|
||||||
private final Collection<UUID> pendingConfirms = new HashSet<>();
|
private final Collection<UUID> pendingConfirms = new HashSet<>();
|
||||||
private final T plugin;
|
private final T plugin;
|
||||||
|
|
||||||
@@ -120,35 +121,30 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Options resolverOptions = new Options();
|
|
||||||
resolverOptions.setMaxNameRequests(config.getInt("mojang-request-limit", 600));
|
|
||||||
|
|
||||||
Set<Proxy> proxies = config.getStringList("proxies")
|
|
||||||
.stream()
|
|
||||||
.map(proxy -> proxy.split(":"))
|
|
||||||
.map(proxy -> new InetSocketAddress(proxy[0], Integer.parseInt(proxy[1])))
|
|
||||||
.map(sa -> new Proxy(Type.HTTP, sa))
|
|
||||||
.collect(toSet());
|
|
||||||
if (!proxies.isEmpty()) {
|
|
||||||
resolverOptions.setProxySelector(new RotatingProxySelector(proxies));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Not available currently in craftapi?
|
|
||||||
// Collection<InetAddress> addresses = new HashSet<>();
|
|
||||||
// for (String localAddress : config.getStringList("ip-addresses")) {
|
|
||||||
// try {
|
|
||||||
// addresses.add(InetAddress.getByName(localAddress.replace('-', '.')));
|
|
||||||
// } catch (UnknownHostException ex) {
|
|
||||||
// plugin.getLog().error("IP-Address is unknown to us", ex);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// resolver.setOutgoingAddresses(addresses);
|
|
||||||
|
|
||||||
// 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(resolverOptions) : new MojangResolver(resolverOptions);
|
? new ProxyAgnosticMojangResolver() : new MojangResolver();
|
||||||
|
|
||||||
antiBot = createAntiBotService(config.getSection("anti-bot"));
|
antiBot = createAntiBotService(config.getSection("anti-bot"));
|
||||||
|
Set<Proxy> proxies = config.getStringList("proxies")
|
||||||
|
.stream()
|
||||||
|
.map(HostAndPort::fromString)
|
||||||
|
.map(proxy -> new InetSocketAddress(proxy.getHost(), proxy.getPort()))
|
||||||
|
.map(sa -> new Proxy(Type.HTTP, sa))
|
||||||
|
.collect(toSet());
|
||||||
|
|
||||||
|
Collection<InetAddress> addresses = new HashSet<>();
|
||||||
|
for (String localAddress : config.getStringList("ip-addresses")) {
|
||||||
|
try {
|
||||||
|
addresses.add(InetAddress.getByName(localAddress.replace('-', '.')));
|
||||||
|
} catch (UnknownHostException ex) {
|
||||||
|
plugin.getLog().error("IP-Address is unknown to us", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolver.setMaxNameRequests(config.getInt("mojang-request-limit"));
|
||||||
|
resolver.setProxySelector(new RotatingProxySelector(proxies));
|
||||||
|
resolver.setOutgoingAddresses(addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AntiBotService createAntiBotService(Configuration botSection) {
|
private AntiBotService createAntiBotService(Configuration botSection) {
|
||||||
@@ -228,16 +224,21 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean setupDatabase() {
|
public boolean setupDatabase() {
|
||||||
String type = config.getString("driver");
|
String driver = config.getString("driver");
|
||||||
|
if (!checkDriver(driver)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
HikariConfig databaseConfig = new HikariConfig();
|
HikariConfig databaseConfig = new HikariConfig();
|
||||||
|
databaseConfig.setDriverClassName(driver);
|
||||||
|
|
||||||
String database = config.getString("database");
|
String database = config.getString("database");
|
||||||
|
|
||||||
databaseConfig.setConnectionTimeout(config.getInt("timeout", 30) * 1_000L);
|
databaseConfig.setConnectionTimeout(config.getInt("timeout", 30) * 1_000L);
|
||||||
databaseConfig.setMaxLifetime(config.getInt("lifetime", 30) * 1_000L);
|
databaseConfig.setMaxLifetime(config.getInt("lifetime", 30) * 1_000L);
|
||||||
|
|
||||||
if (type.contains("sqlite")) {
|
if (driver.contains("sqlite")) {
|
||||||
storage = new SQLiteStorage(plugin, database, databaseConfig);
|
storage = new SQLiteStorage(this, database, databaseConfig);
|
||||||
} else {
|
} else {
|
||||||
String host = config.get("host", "");
|
String host = config.get("host", "");
|
||||||
int port = config.get("port", 3306);
|
int port = config.get("port", 3306);
|
||||||
@@ -255,7 +256,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
|
|
||||||
databaseConfig.setUsername(config.get("username", ""));
|
databaseConfig.setUsername(config.get("username", ""));
|
||||||
databaseConfig.setPassword(config.getString("password"));
|
databaseConfig.setPassword(config.getString("password"));
|
||||||
storage = new MySQLStorage(plugin, type, host, port, database, databaseConfig, useSSL);
|
storage = new MySQLStorage(this, driver, host, port, database, databaseConfig, useSSL);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -267,6 +268,20 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkDriver(String className) {
|
||||||
|
try {
|
||||||
|
Class.forName(className);
|
||||||
|
return true;
|
||||||
|
} catch (ClassNotFoundException notFoundEx) {
|
||||||
|
Logger log = plugin.getLog();
|
||||||
|
log.warn("This driver {} is not supported on this platform", className);
|
||||||
|
log.warn("Please choose either MySQL (Spigot, BungeeCord), SQLite (Spigot, Sponge) or "
|
||||||
|
+ "MariaDB (Sponge, Velocity)", notFoundEx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public Configuration getConfig() {
|
public Configuration getConfig() {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@@ -275,21 +290,12 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
return passwordGenerator;
|
return passwordGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public void setPasswordGenerator(PasswordGenerator<P> passwordGenerator) {
|
public void setPasswordGenerator(PasswordGenerator<P> passwordGenerator) {
|
||||||
this.passwordGenerator = passwordGenerator;
|
this.passwordGenerator = passwordGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLoginAttempt(String ip, String username) {
|
public ConcurrentMap<String, Object> getPendingLogin() {
|
||||||
pendingLogin.put(ip + username, new Object());
|
return pendingLogin;
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasFailedLogin(String ip, String username) {
|
|
||||||
if (!config.get("secondAttemptCracked", false)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pendingLogin.remove(ip + username) != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<UUID> getPendingConfirms() {
|
public Collection<UUID> getPendingConfirms() {
|
||||||
@@ -300,7 +306,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
return authPlugin;
|
return authPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AntiBotService getAntiBotService() {
|
public AntiBotService getAntiBot() {
|
||||||
return antiBot;
|
return antiBot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user