Compare commits

...

84 Commits

Author SHA1 Message Date
31d9f3cb4a Fix parsing of illegal uuids with spaces 2024-04-04 21:46:58 +02:00
56e43fb146 Add support for postgresql 2024-04-04 17:43:23 +02:00
a65a5f3020 Make ignore states more verbose in Velocity 2024-02-13 16:54:23 +01:00
8a729e069d Use current link for hastebin 2024-02-13 16:54:22 +01:00
d89d332273 Minor code recommendations 2024-02-13 16:54:22 +01:00
cd3cfef6d4 Do not encapsulate the task twice in Velocity 2024-02-13 16:54:22 +01:00
6ec6e4844d Bump dependencies 2024-02-13 16:54:22 +01:00
60a65377b8 Hint proxy setup guide and out of date versions 2024-02-13 16:54:22 +01:00
ffbf0ae3f4 Merge pull request #1151 from games647/dependabot/github_actions/advanced-security/maven-dependency-submission-action-4.0.0
Bump advanced-security/maven-dependency-submission-action from 3.0.2 to 4.0.0
2024-02-01 11:38:47 +01:00
4cf65cf7e5 Bump advanced-security/maven-dependency-submission-action
Bumps [advanced-security/maven-dependency-submission-action](https://github.com/advanced-security/maven-dependency-submission-action) from 3.0.2 to 4.0.0.
- [Release notes](https://github.com/advanced-security/maven-dependency-submission-action/releases)
- [Commits](https://github.com/advanced-security/maven-dependency-submission-action/compare/v3.0.2...v4.0.0)

---
updated-dependencies:
- dependency-name: advanced-security/maven-dependency-submission-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-01 07:45:51 +00:00
dbf5ae2fae [Velocity] Fix plugin resuming event processing if login is not handled
This causes login timeouts if this plugin doesn't handle the login for
cases like:

* Anti-Bot is triggered
* Another plugin already denied the login

Fixes #1146
2024-01-23 13:59:49 +01:00
707572a007 Add core module name 2024-01-16 14:08:47 +01:00
108f5ad324 Transform velocity MariaDB transformers too
Otherwise, authentication plugin drivers couldn't be found.
2024-01-15 17:01:02 +01:00
2112d06162 Increase encryption key size for Spigot protocol
1024 bits are very weak keys. This size equals vanillas implementation.
Therefore, 2048 goes out of spec, but works and requires only minimal
additional performance for improved security.

The consequence will be during the login and playing in onlinemode.
First for authenticating and second for the encryption of all following
packets.
2024-01-15 16:37:48 +01:00
aece7f855d Update Java CI version 2024-01-15 16:29:26 +01:00
33b4ac8494 [ci-skip] Fully qualify dependabot versions 2024-01-15 16:29:16 +01:00
09161b86dd Merge pull request #1142 from games647/dependabot/maven/production-dependencies-eb968b0e20
Bump the production-dependencies group with 5 updates
2024-01-15 16:25:55 +01:00
57833bb40b Merge pull request #1133 from games647/dependabot/github_actions/github/codeql-action-3
Bump github/codeql-action from 2 to 3
2024-01-15 16:23:45 +01:00
a1414a38ff Merge pull request #1141 from games647/dependabot/maven/development-dependencies-ca802ab3b6
Bump the development-dependencies group with 1 update
2024-01-15 16:23:24 +01:00
0021bc476d Merge pull request #709 from Smart123s/feature/floodgate/newdb
Differentiate Floodgate players in database
2024-01-15 16:22:34 +01:00
4b1e08a2f8 Bump the production-dependencies group with 5 updates
Bumps the production-dependencies group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `10.12.5` | `10.12.7` |
| [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) | `3.2.2` | `3.2.5` |
| org.slf4j:slf4j-jdk14 | `2.0.9` | `2.0.11` |
| com.lenis0012.bukkit:loginsecurity | `3.2.1` | `3.3.0` |
| [org.mariadb.jdbc:mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) | `3.3.1` | `3.3.2` |


Updates `com.puppycrawl.tools:checkstyle` from 10.12.5 to 10.12.7
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.5...checkstyle-10.12.7)

Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.2.2 to 3.2.5
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.2...surefire-3.2.5)

Updates `org.slf4j:slf4j-jdk14` from 2.0.9 to 2.0.11

Updates `com.lenis0012.bukkit:loginsecurity` from 3.2.1 to 3.3.0

Updates `org.mariadb.jdbc:mariadb-java-client` from 3.3.1 to 3.3.2
- [Release notes](https://github.com/mariadb-corporation/mariadb-connector-j/releases)
- [Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.3.1...3.3.2)

---
updated-dependencies:
- dependency-name: com.puppycrawl.tools:checkstyle
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.slf4j:slf4j-jdk14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: com.lenis0012.bukkit:loginsecurity
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.mariadb.jdbc:mariadb-java-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 07:40:02 +00:00
dbf5b8907e Bump the development-dependencies group with 1 update
Bumps the development-dependencies group with 1 update: [org.mockito:mockito-core](https://github.com/mockito/mockito).


Updates `org.mockito:mockito-core` from 5.8.0 to 5.9.0
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v5.8.0...v5.9.0)

---
updated-dependencies:
- dependency-name: org.mockito:mockito-core
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 07:38:05 +00:00
e6dfa97e70 Bump github/codeql-action from 2 to 3
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-01 07:12:00 +00:00
434a276d30 Invert if and document migration flow for better readability 2023-12-11 16:16:16 +01:00
485af5e044 Document states 2023-12-11 16:16:16 +01:00
e566740dde Differentiate Floodgate players during login 2023-12-11 16:16:15 +01:00
db5b818a80 Add Floodgate variable to StoredProfile/Database 2023-12-11 16:16:15 +01:00
b0b998d1aa Use columnName instead of columnIndex
It's safer to rely on names instead of indexes.
It's also easier to add new columns at the end of the table.
2023-12-11 16:16:15 +01:00
62ca46fe6a Add checksytle suppression via comments 2023-12-11 16:16:15 +01:00
cd67797b5b Merge pull request #1122 from games647/dependabot/maven/development-dependencies-a116437099
Bump the development-dependencies group with 3 updates
2023-12-06 16:19:28 +01:00
48e8b45f1e Merge pull request #1123 from games647/dependabot/maven/production-dependencies-d650319dc7
Bump the production-dependencies group with 6 updates
2023-12-06 16:19:09 +01:00
1c9b8cb971 Merge pull request #1120 from games647/dependabot/github_actions/actions/setup-java-4
Bump actions/setup-java from 3 to 4
2023-12-06 16:18:34 +01:00
dcb9540a2f Bump the production-dependencies group with 6 updates
Bumps the production-dependencies group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `10.12.4` | `10.12.5` |
| [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) | `3.3.0` | `3.3.1` |
| [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) | `3.1.2` | `3.2.2` |
| me.clip:placeholderapi | `2.11.4` | `2.11.5` |
| [org.mariadb.jdbc:mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) | `3.2.0` | `3.3.1` |
| [org.codehaus.mojo:templating-maven-plugin](https://github.com/mojohaus/templating-maven-plugin) | `1.0.0` | `3.0.0` |


Updates `com.puppycrawl.tools:checkstyle` from 10.12.4 to 10.12.5
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.4...checkstyle-10.12.5)

Updates `org.apache.maven.plugins:maven-checkstyle-plugin` from 3.3.0 to 3.3.1
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.0...maven-checkstyle-plugin-3.3.1)

Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.1.2 to 3.2.2
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.2.2)

Updates `me.clip:placeholderapi` from 2.11.4 to 2.11.5

Updates `org.mariadb.jdbc:mariadb-java-client` from 3.2.0 to 3.3.1
- [Release notes](https://github.com/mariadb-corporation/mariadb-connector-j/releases)
- [Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.2.0...3.3.1)

Updates `org.codehaus.mojo:templating-maven-plugin` from 1.0.0 to 3.0.0
- [Release notes](https://github.com/mojohaus/templating-maven-plugin/releases)
- [Commits](https://github.com/mojohaus/templating-maven-plugin/compare/templating-maven-plugin-1.0.0...3.0.0)

---
updated-dependencies:
- dependency-name: com.puppycrawl.tools:checkstyle
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: me.clip:placeholderapi
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.mariadb.jdbc:mariadb-java-client
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.codehaus.mojo:templating-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 07:49:44 +00:00
cacf3c23f1 Bump the development-dependencies group with 3 updates
Bumps the development-dependencies group with 3 updates: [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5), [org.mockito:mockito-core](https://github.com/mockito/mockito) and [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java).


Updates `org.junit.jupiter:junit-jupiter` from 5.10.0 to 5.10.1
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.10.0...r5.10.1)

Updates `org.mockito:mockito-core` from 5.6.0 to 5.8.0
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v5.6.0...v5.8.0)

Updates `org.bouncycastle:bcprov-jdk18on` from 1.76 to 1.77
- [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: org.mockito:mockito-core
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: org.bouncycastle:bcprov-jdk18on
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 07:48:07 +00:00
67f170694f Bump actions/setup-java from 3 to 4
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-01 07:49:23 +00:00
e15ea9ce85 Restore support for fully qualified storage drivers
Related #1100
2023-10-12 10:47:14 +02:00
70960661b4 [ci-skip] Fix typo in issue templates 2023-10-11 13:42:17 +02:00
ec657faaff Force lowercase SQL driver name to improve type checks 2023-10-11 13:40:57 +02:00
51898b4b34 Migrate enhancement requests to newer issue templates 2023-10-11 13:28:12 +02:00
e30de1b700 Include CI server in issue template 2023-10-11 13:28:11 +02:00
ce17441edb Merge pull request #1097 from games647/dependabot/maven/production-dependencies-84d7f6773a
Bump the production-dependencies group with 6 updates
2023-10-11 12:39:04 +02:00
3244b7a87a Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-11 12:38:02 +02:00
ecacd2a715 Update toolchain for Java 21 compiling 2023-10-11 12:37:07 +02:00
ea6d4cf2f6 Add proper support for 1.19.3-1.20.1 2023-10-11 12:37:07 +02:00
91b05289ad Add 1.20.2 support 2023-10-11 12:37:07 +02:00
4e0f8cfb65 Bump the production-dependencies group with 6 updates
Bumps the production-dependencies group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `10.12.3` | `10.12.4` |
| [org.projectlombok:lombok](https://github.com/projectlombok/lombok) | `1.18.28` | `1.18.30` |
| com.mycila:license-maven-plugin | `4.2` | `4.3` |
| org.slf4j:slf4j-jdk14 | `2.0.7` | `2.0.9` |
| me.clip:placeholderapi | `2.11.3` | `2.11.4` |
| [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) | `3.5.0` | `3.5.1` |


Updates `com.puppycrawl.tools:checkstyle` from 10.12.3 to 10.12.4
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.3...checkstyle-10.12.4)

Updates `org.projectlombok:lombok` from 1.18.28 to 1.18.30
- [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown)
- [Commits](https://github.com/projectlombok/lombok/compare/v1.18.28...v1.18.30)

Updates `com.mycila:license-maven-plugin` from 4.2 to 4.3

Updates `org.slf4j:slf4j-jdk14` from 2.0.7 to 2.0.9

Updates `me.clip:placeholderapi` from 2.11.3 to 2.11.4

Updates `org.apache.maven.plugins:maven-shade-plugin` from 3.5.0 to 3.5.1
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.0...maven-shade-plugin-3.5.1)

---
updated-dependencies:
- dependency-name: com.puppycrawl.tools:checkstyle
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.projectlombok:lombok
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: com.mycila:license-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.slf4j:slf4j-jdk14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: me.clip:placeholderapi
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-02 07:56:41 +00:00
d76690dcbe Merge pull request #1087 from games647/dependabot/maven/production-dependencies-ce791421b1
Bump the production-dependencies group with 7 updates
2023-08-31 15:23:30 +02:00
3559d067ad Bump the production-dependencies group with 7 updates
Bumps the production-dependencies group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) | `10.9.3` | `10.12.3` |
| [org.projectlombok:lombok](https://github.com/projectlombok/lombok) | `1.18.26` | `1.18.28` |
| [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) | `2.22.2` | `3.1.2` |
| [com.google.code.gson:gson](https://github.com/google/gson) | `2.10` | `2.10.1` |
| com.lenis0012.bukkit:loginsecurity | `3.1.1` | `3.2.1` |
| [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) | `3.4.1` | `3.5.0` |
| [org.mariadb.jdbc:mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) | `3.1.4` | `3.2.0` |


Updates `com.puppycrawl.tools:checkstyle` from 10.9.3 to 10.12.3
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.9.3...checkstyle-10.12.3)

Updates `org.projectlombok:lombok` from 1.18.26 to 1.18.28
- [Release notes](https://github.com/projectlombok/lombok/releases)
- [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown)
- [Commits](https://github.com/projectlombok/lombok/compare/v1.18.26...v1.18.28)

Updates `org.apache.maven.plugins:maven-surefire-plugin` from 2.22.2 to 3.1.2
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-2.22.2...surefire-3.1.2)

Updates `com.google.code.gson:gson` from 2.10 to 2.10.1
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.10...gson-parent-2.10.1)

Updates `com.lenis0012.bukkit:loginsecurity` from 3.1.1 to 3.2.1

Updates `org.apache.maven.plugins:maven-shade-plugin` from 3.4.1 to 3.5.0
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.4.1...maven-shade-plugin-3.5.0)

Updates `org.mariadb.jdbc:mariadb-java-client` from 3.1.4 to 3.2.0
- [Release notes](https://github.com/mariadb-corporation/mariadb-connector-j/releases)
- [Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.4...3.2.0)

---
updated-dependencies:
- dependency-name: com.puppycrawl.tools:checkstyle
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.projectlombok:lombok
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: production-dependencies
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: com.lenis0012.bukkit:loginsecurity
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: org.mariadb.jdbc:mariadb-java-client
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-31 11:53:12 +00:00
48a92ed35e Use wildcard exclude patterns 2023-08-31 13:51:42 +02:00
a4eec19f53 [ci-skip] Fix dependency name 2023-08-31 13:19:17 +02:00
32eda941ee Ignore Hikari and SnakeYAML in dependency updates 2023-08-31 12:42:32 +02:00
92d88caf0a Merge pull request #1085 from games647/dependabot/maven/development-dependencies-424a594065
Bump the development-dependencies group with 2 updates
2023-08-31 12:28:11 +02:00
d2202d7a12 Bump the development-dependencies group with 2 updates
Bumps the development-dependencies group with 2 updates: [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) and [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java).


Updates `org.junit.jupiter:junit-jupiter` from 5.9.1 to 5.10.0
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.9.1...r5.10.0)

Updates `org.bouncycastle:bcprov-jdk18on` from 1.75 to 1.76
- [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: org.bouncycastle:bcprov-jdk18on
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-31 10:21:23 +00:00
6a68e04c87 Fix grouping for maven packages 2023-08-31 12:18:10 +02:00
b702f48907 Add version number back 2023-08-31 12:14:06 +02:00
159a6ed37c Add JavaDoc snippets and tiny reformats 2023-08-31 12:08:40 +02:00
b48dfed709 Add NPE check on velocity for logins 2023-08-31 12:08:40 +02:00
2db327ccc4 Group dependency updates together 2023-08-31 12:08:39 +02:00
9d907983a6 Only run CodeQL if successful 2023-08-31 12:08:39 +02:00
4a3d7f448f Merge pull request #1071 from xrh0905/floodgate_enabled
Floodgate enabled
2023-08-31 12:07:53 +02:00
31cbb2ff11 Add floodgate support
Based on: https://github.com/games647/FastLogin/pull/649

Solve hooks not found

Add defination of floodgateservice

Geyser API
2023-08-31 12:04:23 +02:00
1715c08ee6 Merge pull request #1041 from games647/dependabot/maven/org.apache.maven.plugins-maven-checkstyle-plugin-3.3.0
Bump maven-checkstyle-plugin from 3.1.2 to 3.3.0
2023-07-20 12:02:43 +02:00
5682df9ad5 Merge pull request #1048 from games647/dependabot/maven/org.bouncycastle-bcprov-jdk18on-1.75
Bump bcprov-jdk18on from 1.72 to 1.75
2023-07-20 12:01:27 +02:00
132b560130 Merge pull request #1036 from games647/dependabot/maven/org.mariadb.jdbc-mariadb-java-client-3.1.4
Bump mariadb-java-client from 3.1.0 to 3.1.4
2023-07-20 12:01:13 +02:00
e204c9c579 Merge pull request #1021 from games647/dependabot/maven/com.mycila-license-maven-plugin-4.2
Bump license-maven-plugin from 4.1 to 4.2
2023-07-20 12:00:56 +02:00
f92863e53a Merge branch 'main' into dependabot/maven/org.apache.maven.plugins-maven-checkstyle-plugin-3.3.0 2023-07-20 12:00:33 +02:00
23fec56ecd Merge branch 'main' into dependabot/maven/org.bouncycastle-bcprov-jdk18on-1.75 2023-07-20 11:57:50 +02:00
5cd10fd795 Run CodeQL after main build to leverage caching 2023-07-17 17:04:28 +02:00
ecbf07c0b2 Manually start build process in CodeQL 2023-07-17 16:26:52 +02:00
053b51e96b Relax java build version requirement
GitHub action seems to always download Java 19 even though it is
already downloaded and installed. This could also help with running
the CodeQL action.
2023-07-17 16:17:57 +02:00
44d365b15d Use java dot file to help autobuild select the correct version 2023-07-17 15:52:54 +02:00
610c49d62c Enable write for dependency graph 2023-07-17 15:49:36 +02:00
dbd12742fa Only upload dependency graph on push 2023-07-17 15:47:02 +02:00
f2fd51d4e2 Use suggestion dependency version 2023-07-17 15:17:29 +02:00
f9ca318775 Apply Java version selection after CodeQL init 2023-07-17 15:13:40 +02:00
f06ace2f5b Add dependency graph to help GitHub find dependencies 2023-07-17 15:09:16 +02:00
ee465e381c Rephrase invalid session warning to make it more clear 2023-07-17 10:10:03 +02:00
6ab81b1a2f Fix formatting errors 2023-07-17 09:55:24 +02:00
36ee52aa6e Print out a warning if we detect local IP addresses during connections
Reference #1055
2023-07-10 15:52:34 +02:00
e5c70d8597 Bump bcprov-jdk18on from 1.72 to 1.75
Bumps [bcprov-jdk18on](https://github.com/bcgit/bc-java) from 1.72 to 1.75.
- [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)

---
updated-dependencies:
- dependency-name: org.bouncycastle:bcprov-jdk18on
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 07:58:13 +00:00
8b1485f0b1 Bump maven-checkstyle-plugin from 3.1.2 to 3.3.0
Bumps [maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) from 3.1.2 to 3.3.0.
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.1.2...maven-checkstyle-plugin-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 07:57:19 +00:00
c106089a72 Include updated yaml for older Spigot platforms
Fixes #1031
2023-05-22 15:16:42 +02:00
5fc27f6c4a Bump mariadb-java-client from 3.1.0 to 3.1.4
Bumps [mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) from 3.1.0 to 3.1.4.
- [Release notes](https://github.com/mariadb-corporation/mariadb-connector-j/releases)
- [Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mariadb-corporation/mariadb-connector-j/commits/3.1.4)

---
updated-dependencies:
- dependency-name: org.mariadb.jdbc:mariadb-java-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 07:57:09 +00:00
73720277b3 Bump license-maven-plugin from 4.1 to 4.2
Bumps license-maven-plugin from 4.1 to 4.2.

---
updated-dependencies:
- dependency-name: com.mycila:license-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 07:58:12 +00:00
46 changed files with 976 additions and 188 deletions

View File

@ -36,7 +36,7 @@ body:
attributes:
label: Server log
description: The error, stacktrace or link the complete log. You can use the links above for long versions.
placeholder: https://hastebin.com/ / https://gist.github.com/
placeholder: https://www.toptal.com/developers/hastebin / https://gist.github.com/
- type: input
attributes:
label: Plugin version
@ -59,9 +59,11 @@ body:
label: Relevance
description: Check list for previous tickets
options:
- label: I tried the latest build (build refers to development builds not necessary a release version)
- label: |
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
- label: |
I checked for existing tickets -
If there are, please vote them with a thumps reaction and not create new ones
If there are, please vote them with a thumbs reaction and not create new ones
required: true

View File

@ -1,30 +0,0 @@
---
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.)

View File

@ -0,0 +1,43 @@
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

View File

@ -14,3 +14,22 @@ updates:
directory: "/"
schedule:
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"]
# SnakeYAML has breaking changes with 2.0
- dependency-name: "org.yaml:snakeyaml"
update-types: ["version-update:semver-major"]

View File

@ -4,11 +4,11 @@
name: "CodeQL"
on:
# Scan only for push on the primary branch for now
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_run:
workflows: ["Maven Build"]
branches: [main]
types:
- completed
jobs:
# job i
@ -20,6 +20,10 @@ jobs:
# Environment
runs-on: ubuntu-latest
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
if: ${{ github.event.workflow_run.conclusion == 'success' }}
permissions:
actions: read
contents: read
@ -33,28 +37,29 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 19
cache: 'maven'
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# Auto build attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version-file: '.java-version'
cache: 'maven'
# Manually start the autobuild process, because autobuild always selects Java 8 as build toolchain, but
# we are doing cross-crompiling from a newer Java version
- 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@v2
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@ -21,19 +21,19 @@ jobs:
# Environment image - always use the newest OS
runs-on: ubuntu-latest
permissions:
contents: read
contents: write
# Run steps
steps:
# Pull changes
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 19
java-version-file: '.java-version'
cache: 'maven'
# Build and test (included in package)
@ -41,3 +41,7 @@ jobs:
# Run non-interactive, package (with compile+test),
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums
run: mvn test --batch-mode --threads 2.0C --no-snapshot-updates --strict-checksums --file pom.xml
- name: Update dependency graph
if: ${{ github.event_name == 'push' }}
uses: advanced-security/maven-dependency-submission-action@v4.0.0

2
.java-version Normal file
View File

@ -0,0 +1,2 @@
# Latest GitHub Action java release that is installed on the runners
21

View File

@ -60,13 +60,13 @@ Possible values: `Premium`, `Cracked`, `Unknown`
## Requirements
* Java 17+
* Java 17+ (Recommended)
* Server software in offlinemode:
* Spigot (or a fork e.g. Paper) 1.8.8+
* Protocol plugin:
* [ProtocolLib 5.0+](https://www.spigotmc.org/resources/protocollib.1997/) or
* [ProtocolLib 5.1+](https://www.spigotmc.org/resources/protocollib.1997/) or
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
* Latest BungeeCord (or a fork e.g. Waterfall)
* Latest BungeeCord (or a fork e.g. Waterfall) or Velocity
* An auth plugin.
### Supported auth plugins
@ -117,10 +117,10 @@ Install the plugin on both platforms, that is proxy (BungeeCord or Velocity) and
4. Activate ip forwarding in your proxy config
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:
* BungeeCord: `com.mysql.jdbc.Driver` for MySQL/MariaDB
* Velocity: `fastlogin.mariadb.jdbc.Driver` for MySQL/MariaDB
* BungeeCord: `com.mysql.jdbc.Driver` for MySQL/MariaDB/PostgreSQL
* Velocity: `fastlogin.mariadb.jdbc.Driver` for MySQL/MariaDB/PostgreSQL
* 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/PostgreSQL requires an external database server running. Check your server provider if there is one available
or install one.
6. Set proxy and Spigot in offline mode by setting the value `onlinemode` in your `config.yml` to false
7. You should *always* configure the firewall for your Spigot server so that it's only accessible through your proxy

View File

@ -50,11 +50,15 @@
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<version>3.5.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>false</shadedArtifactAttached>
<relocations>
<relocation>
<pattern>org.yaml.snakeyaml</pattern>
<shadedPattern>fastlogin.yaml</shadedPattern>
</relocation>
<relocation>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>fastlogin.hikari</shadedPattern>
@ -123,6 +127,9 @@
<repository>
<id>dmulloy2-repo</id>
<url>https://repo.dmulloy2.net/repository/public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<!-- AuthMe Reloaded, xAuth and LoginSecurity -->
@ -161,6 +168,13 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
<scope>compile</scope>
</dependency>
<!-- PaperSpigot API for correcting user cache usage -->
<dependency>
<groupId>io.papermc.paper</groupId>
@ -193,7 +207,7 @@
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>5.0.0</version>
<version>5.1.0</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@ -264,7 +278,7 @@
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.3</version>
<version>2.11.5</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
@ -293,7 +307,7 @@
<dependency>
<groupId>com.lenis0012.bukkit</groupId>
<artifactId>loginsecurity</artifactId>
<version>3.1.1</version>
<version>3.3.0</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
@ -364,7 +378,7 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.72</version>
<version>1.77</version>
<scope>test</scope>
</dependency>

View File

@ -39,7 +39,7 @@ public class BukkitScheduler extends AsyncScheduler {
public BukkitScheduler(Plugin plugin, Logger logger) {
super(logger, command -> Bukkit.getScheduler().runTaskAsynchronously(plugin, command));
syncExecutor = r -> Bukkit.getScheduler().runTask(plugin, r);
syncExecutor = task -> Bukkit.getScheduler().runTask(plugin, task);
}
public Executor getSyncExecutor() {

View File

@ -228,6 +228,22 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
/**
* 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)
* @return the online status or unknown if an error happened, the player isn't online or BungeeCord doesn't send

View File

@ -0,0 +1,63 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit;
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;
}
}

View File

@ -70,7 +70,7 @@ final class EncryptionUtil {
public static final int VERIFY_TOKEN_LENGTH = 4;
public static final String KEY_PAIR_ALGORITHM = "RSA";
private static final int RSA_LENGTH = 1_024;
private static final int RSA_LENGTH = 2_048;
private static final PublicKey MOJANG_SESSION_KEY;
private static final int LINE_LENGTH = 76;

View File

@ -177,7 +177,7 @@ public class ProtocolLibListener extends PacketAdapter {
ClientPublicKey clientPublicKey, byte[] expectedToken) {
try {
if (new MinecraftVersion(1, 19, 0).atOrAbove()
&& !(new MinecraftVersion(1, 19, 3).atOrAbove())) {
&& !new MinecraftVersion(1, 19, 3).atOrAbove()) {
Either<byte[], ?> either = packet.getSpecificModifier(Either.class).read(0);
if (clientPublicKey == null) {
Optional<byte[]> left = either.left();

View File

@ -38,6 +38,7 @@ import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.utility.MinecraftVersion;
import com.comphenix.protocol.wrappers.BukkitConverters;
import com.comphenix.protocol.wrappers.Converters;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedProfilePublicKey.WrappedProfileKeyData;
@ -46,6 +47,7 @@ import com.github.games647.craftapi.model.skin.SkinProperty;
import com.github.games647.craftapi.resolver.MojangResolver;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
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 lombok.val;
import org.bukkit.entity.Player;
@ -71,10 +73,17 @@ public class VerifyResponseTask implements Runnable {
private static final String ENCRYPTION_CLASS_NAME = "MinecraftEncryption";
private static final Class<?> ENCRYPTION_CLASS;
private static final String ADDRESS_VERIFY_WARNING = "This indicates the use of reverse-proxy like HAProxy, "
+ "TCPShield, BungeeCord, Velocity, etc. "
+ "By default (configurable in the config) this plugin requests Mojang to verify the connecting IP "
+ "to this server with the one used to log into Minecraft to prevent MITM attacks. In "
+ "order to work this security feature, the actual client IP needs to be forwarding "
+ "(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.";
static {
ENCRYPTION_CLASS = MinecraftReflection.getMinecraftClass(
"util." + ENCRYPTION_CLASS_NAME, ENCRYPTION_CLASS_NAME
"util." + ENCRYPTION_CLASS_NAME, ENCRYPTION_CLASS_NAME
);
}
@ -149,10 +158,27 @@ public class VerifyResponseTask implements Runnable {
} else {
//user tried to fake an authentication
disconnect(
"invalid-session",
"GameProfile {} ({}) tried to log in with an invalid session. ServerId: {}",
session.getRequestUsername(), socketAddress, serverId
"invalid-session",
"Session server rejected incoming connection for GameProfile {} ({}). Possible reasons are"
+ "1) Client IP address contacting Mojang and server during server join were different "
+ "(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
);
plugin.getLog().warn(ADDRESS_VERIFY_WARNING);
} 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) {
disconnect("error-kick", "Failed to connect to session server", ioEx);
@ -177,7 +203,7 @@ public class VerifyResponseTask implements Runnable {
session.setVerified(true);
setPremiumUUID(session.getUuid());
receiveFakeStartPacket(realUsername, session.getClientPublicKey());
receiveFakeStartPacket(realUsername, session.getClientPublicKey(), session.getUuid());
}
private void setPremiumUUID(UUID premiumUUID) {
@ -217,15 +243,15 @@ public class VerifyResponseTask implements Runnable {
try {
// Try to get the old (pre MC 1.16.4) encryption method
encryptMethod = FuzzyReflection.fromClass(networkManagerClass)
.getMethodByParameters("a", SecretKey.class);
.getMethodByParameters("a", SecretKey.class);
} catch (IllegalArgumentException exception) {
// Get the new encryption method
encryptMethod = FuzzyReflection.fromClass(networkManagerClass)
.getMethodByParameters("a", Cipher.class, Cipher.class);
.getMethodByParameters("a", Cipher.class, Cipher.class);
// Get the needed Cipher helper method (used to generate ciphers from login key)
cipherMethod = FuzzyReflection.fromClass(ENCRYPTION_CLASS)
.getMethodByParameters("a", int.class, Key.class);
.getMethodByParameters("a", int.class, Key.class);
}
}
@ -268,15 +294,23 @@ public class VerifyResponseTask implements Runnable {
}
//fake a new login packet in order to let the server handle all the other stuff
private void receiveFakeStartPacket(String username, ClientPublicKey clientKey) {
private void receiveFakeStartPacket(String username, ClientPublicKey clientKey, UUID uuid) {
PacketContainer startPacket;
if (new MinecraftVersion(1, 19, 0).atOrAbove()) {
if (new MinecraftVersion(1, 20, 2).atOrAbove()) {
startPacket = new PacketContainer(START);
startPacket.getStrings().write(0, username);
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);
EquivalentConverter<WrappedProfileKeyData> converter = BukkitConverters.getWrappedPublicKeyDataConverter();
val wrappedKey = Optional.ofNullable(clientKey).map(key ->
new WrappedProfileKeyData(clientKey.expiry(), clientKey.key(), clientKey.signature())
new WrappedProfileKeyData(clientKey.expiry(), clientKey.key(), clientKey.signature())
);
startPacket.getOptionals(converter).write(0, wrappedKey);

View File

@ -47,7 +47,7 @@
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<version>3.5.1</version>
<configuration>
<minimizeJar>true</minimizeJar>

View File

@ -220,6 +220,14 @@
<property name="optional" value="true"/>
</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>

View File

@ -63,6 +63,23 @@
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>com.github.games647.fastlogin.core</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Libraries that we shade into the project -->
@ -85,7 +102,7 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>2.0.7</version>
<version>2.0.11</version>
</dependency>
<!-- snakeyaml is present in Bungee, Spigot, Cauldron, so we could use this independent implementation -->
@ -93,12 +110,6 @@
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Floodgate for Xbox Live Authentication-->
@ -184,7 +195,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10</version>
<version>2.10.1</version>
</dependency>
<dependency>

View File

@ -107,7 +107,7 @@ public class TickingRateLimiter implements RateLimiter {
}
}
private static class TimeRecord implements Comparable<Long> {
private static class TimeRecord implements Comparable<TimeRecord> {
private final long firstMinuteRecord;
private final long expireTime;
@ -131,9 +131,9 @@ public class TickingRateLimiter implements RateLimiter {
return firstMinuteRecord + expireTime <= now;
}
@Override
public int compareTo(Long other) {
public int compareTo(long other) {
if (other < firstMinuteRecord) {
// other is earlier
return -1;
}
@ -143,5 +143,10 @@ public class TickingRateLimiter implements RateLimiter {
return 0;
}
@Override
public int compareTo(TimeRecord other) {
return compareTo(other.firstMinuteRecord);
}
}
}

View File

@ -25,8 +25,17 @@
*/
package com.github.games647.fastlogin.core.hooks;
/**
* Password generator for your auth plugin.
* @param <P> platform dependent player class
*/
@FunctionalInterface
public interface PasswordGenerator<P> {
/**
* Generate a password for a non-registered player
* @param player
* @return daw
*/
String getRandomPassword(P player);
}

View File

@ -36,6 +36,7 @@ import com.github.games647.fastlogin.core.antibot.TickingRateLimiter;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.hooks.DefaultPasswordGenerator;
import com.github.games647.fastlogin.core.hooks.PasswordGenerator;
import com.github.games647.fastlogin.core.storage.PostgreSQLStorage;
import com.github.games647.fastlogin.core.storage.MySQLStorage;
import com.github.games647.fastlogin.core.storage.SQLStorage;
import com.github.games647.fastlogin.core.storage.SQLiteStorage;
@ -230,6 +231,24 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
if (type.contains("sqlite")) {
storage = new SQLiteStorage(plugin, database, databaseConfig);
} else if (type.contains("postgresql")) {
String host = config.get("host", "");
int port = config.get("port", 3306);
boolean useSSL = config.get("useSSL", false);
if (useSSL) {
boolean publicKeyRetrieval = config.getBoolean("allowPublicKeyRetrieval", false);
String rsaPublicKeyFile = config.getString("ServerRSAPublicKeyFile");
String sslMode = config.getString("sslMode", "Required");
databaseConfig.addDataSourceProperty("allowPublicKeyRetrieval", publicKeyRetrieval);
databaseConfig.addDataSourceProperty("serverRSAPublicKeyFile", rsaPublicKeyFile);
databaseConfig.addDataSourceProperty("sslMode", sslMode);
}
databaseConfig.setUsername(config.get("username", ""));
databaseConfig.setPassword(config.getString("password"));
storage = new PostgreSQLStorage(plugin, type, host, port, database, databaseConfig, useSSL);
} else {
String host = config.get("host", "");
int port = config.get("port", 3306);

View File

@ -33,6 +33,7 @@ import org.geysermc.floodgate.api.player.FloodgatePlayer;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Locale;
import java.util.Optional;
import java.util.UUID;
@ -61,9 +62,9 @@ public abstract class FloodgateManagement<P extends C, C, L extends LoginSession
this.username = getName(player);
//load values from config.yml
autoLoginFloodgate = core.getConfig().get("autoLoginFloodgate").toString().toLowerCase();
autoRegisterFloodgate = core.getConfig().get("autoRegisterFloodgate").toString().toLowerCase();
allowNameConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
autoLoginFloodgate = core.getConfig().getString("autoLoginFloodgate").toLowerCase(Locale.ROOT);
autoRegisterFloodgate = core.getConfig().getString("autoRegisterFloodgate").toLowerCase(Locale.ROOT);
allowNameConflict = core.getConfig().getString("allowFloodgateNameConflict").toLowerCase(Locale.ROOT);
}
@Override
@ -80,6 +81,40 @@ public abstract class FloodgateManagement<P extends C, C, L extends LoginSession
}
profile = core.getStorage().loadProfile(username);
if (profile.isSaved()) {
if (profile.isFloodgateMigrated()) {
if (profile.getFloodgate() == FloodgateState.TRUE && isLinked) {
core.getPlugin().getLog()
.info("Player {} is already stored by FastLogin as a non-linked Bedrock Edition player",
username);
return;
} else if (profile.getFloodgate() == FloodgateState.FALSE && isLinked) {
profile.setFloodgate(FloodgateState.LINKED);
core.getPlugin().getLog().info(
"Player {} will be changed from a Java player to a linked Floodgate player",
username);
}
} else {
if (isLinked) {
profile.setFloodgate(FloodgateState.LINKED);
core.getPlugin().getLog().info(
"Player {} will be migrated to the v2 database schema as a linked Floodgate user",
username);
} else {
profile.setFloodgate(FloodgateState.TRUE);
core.getPlugin().getLog().info(
"Player {} will be migrated to the v2 database schema as a Floodgate user", username);
}
}
} else {
if (isLinked) {
profile.setFloodgate(FloodgateState.LINKED);
} else {
profile.setFloodgate(FloodgateState.TRUE);
}
}
AuthPlugin<P> authPlugin = core.getAuthPluginHook();
try {
@ -119,13 +154,17 @@ public abstract class FloodgateManagement<P extends C, C, L extends LoginSession
}
}
// defer auto registration, if it's not enabled in the config
if (!isRegistered && !isAutoAuthAllowed(autoRegisterFloodgate)) {
return;
}
//logging in from bedrock for a second time threw an error with UUID
if (profile == null) {
profile = new StoredProfile(getUUID(player), username, true, getAddress(player).toString());
// stop the auto login procedure, if the current connection's parameters don't match the one stored in our
// database
// ex. we stored a LINKED account, but the current connection is not linked
if ((profile.getFloodgate() == FloodgateState.LINKED && !isLinked)
|| (profile.getFloodgate() == FloodgateState.TRUE && isLinked)) {
return;
}
//start Bukkit/Bungee specific tasks

View File

@ -0,0 +1,86 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.shared;
public enum FloodgateState {
/**
* Purely Java profile
*/
FALSE(0),
/**
* Purely Bedrock profile
*/
TRUE(1),
/**
* Bedrock profile is bidirectional associated with the Java Mojang profile.
*/
LINKED(2),
/**
* Data before floodgate database migration. Floodgate state is unknown.
*/
NOT_MIGRATED(3);
private int value;
FloodgateState(int value) {
this.value = value;
}
public int getValue() {
return value;
}
/**
* Convert a number to FloodgateState
* <ol start="0">
* <li>False</li>
* <li>True</li>
* <li>Linked</li>
* <li>Not Migrated</li>
* </ol>
* @param num the number, most likely loaded from the database
* @return FloodgateStatus on success, null otherwise
*/
public static FloodgateState fromInt(int num) {
// using Enum.values()[i] is expensive as per https://stackoverflow.com/a/8762387/9767089
switch (num) {
case 0:
return FloodgateState.FALSE;
case 1:
return FloodgateState.TRUE;
case 2:
return FloodgateState.LINKED;
case 3:
return FloodgateState.NOT_MIGRATED;
default:
return null;
}
}
}

View File

@ -62,7 +62,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
//premium player
AuthPlugin<P> authPlugin = core.getAuthPluginHook();
if (authPlugin == null) {
//maybe only bungeecord plugin
// maybe only bungeecord plugin
onForceActionSuccess(session);
} else {
boolean success = true;

View File

@ -49,17 +49,32 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
public void onLogin(String username, S source) {
core.getPlugin().getLog().info("Handling player {}", username);
//check if the player is connecting through Bedrock Edition
if (bedrockService != null && bedrockService.isBedrockConnection(username)) {
//perform Bedrock specific checks and skip Java checks if no longer needed
if (bedrockService.performChecks(username, source)) {
return;
}
}
StoredProfile profile = core.getStorage().loadProfile(username);
//can't be a premium Java player, if it's not saved in the database
if (profile == null) {
return;
}
//check if the player is connecting through Bedrock Edition
if (bedrockService != null && bedrockService.isBedrockConnection(username)) {
//perform Bedrock specific checks and skip Java checks, if they are not needed
if (bedrockService.performChecks(username, source)) {
if (profile.isFloodgateMigrated()) {
if (profile.getFloodgate() == FloodgateState.TRUE) {
// migrated and enabled floodgate player, however the above bedrocks fails, so the current connection
// isn't premium
return;
}
} else {
profile.setFloodgate(FloodgateState.FALSE);
core.getPlugin().getLog().info(
"Player {} will be migrated to the v2 database schema as a JAVA user", username);
}
callFastLoginPreLoginEvent(username, source, profile);
@ -139,6 +154,12 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
if (core.getConfig().get("nameChangeCheck", false)) {
StoredProfile storedProfile = core.getStorage().loadProfile(profile.getId());
if (storedProfile != null) {
if (storedProfile.getFloodgate() == FloodgateState.TRUE) {
core.getPlugin().getLog()
.info("Player {} is already stored by FastLogin as a Bedrock Edition player.", username);
return false;
}
//uuid exists in the database
core.getPlugin().getLog().info("GameProfile {} changed it's username", profile);

View File

@ -61,6 +61,7 @@ public abstract class LoginSession {
}
/**
* Check if user needs registration once login is successful
* @return This value is always false if we authenticate the player with a cracked authentication
*/
public synchronized boolean needsRegistration() {

View File

@ -29,9 +29,20 @@ import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.storage.StoredProfile;
/**
* This event fires if the plugin performs an auto login on the platform where the login plugin is.
* This event fires if the plugin performs an auto login on the platform where the login plugin is
*
* {@snippet :
* @EventHandler()
* public void onPlayerLogin(FastLoginAutoLoginEvent loginEvent) {
* StoredProfile profile = loginEvent.getProfile();
* LoginSession session = loginEvent.getSession();
*
* System.out.println("Player: " + session.getUsername() + " is about to be force logged in");
* }
* }
*/
public interface FastLoginAutoLoginEvent extends FastLoginCancellableEvent {
LoginSession getSession();
StoredProfile getProfile();
}

View File

@ -28,5 +28,6 @@ package com.github.games647.fastlogin.core.shared.event;
public interface FastLoginCancellableEvent {
boolean isCancelled();
void setCancelled(boolean cancelled);
}

View File

@ -34,6 +34,8 @@ import com.github.games647.fastlogin.core.storage.StoredProfile;
public interface FastLoginPreLoginEvent {
String getUsername();
LoginSource getSource();
StoredProfile getProfile();
}

View File

@ -33,6 +33,7 @@ import com.github.games647.fastlogin.core.storage.StoredProfile;
public interface FastLoginPremiumToggleEvent {
StoredProfile getProfile();
PremiumToggleReason getReason();
enum PremiumToggleReason {

View File

@ -28,6 +28,8 @@ package com.github.games647.fastlogin.core.storage;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import com.zaxxer.hikari.HikariConfig;
import java.util.Locale;
public class MySQLStorage extends SQLStorage {
private static final String JDBC_PROTOCOL = "jdbc:";
@ -68,12 +70,12 @@ public class MySQLStorage extends SQLStorage {
}
private static String buildJDBCUrl(String driver, String host, int port, String database) {
String protocol = "mysql";
if (driver.contains("mariadb")) {
protocol = "mariadb";
MySQLVariant variant = MySQLVariant.fromDriver(driver);
if (variant == null) {
throw new IllegalArgumentException("Unknown storage driver");
}
return protocol + "://" + host + ':' + port + '/' + database;
return variant.getJdbcPrefix() + "://" + host + ':' + port + '/' + database;
}
private static void addPerformanceProperties(HikariConfig config) {
@ -106,4 +108,32 @@ public class MySQLStorage extends SQLStorage {
// In our case it can be useful to see the time in error messages
// config.addDataSourceProperty("maintainTimeStats", false);
}
enum MySQLVariant {
MYSQL("mysql"),
MARIADB("mariadb");
private final String jdbcPrefix;
public static MySQLVariant fromDriver(String driver) {
String normalizedDriver = driver.toLowerCase(Locale.ENGLISH);
if (normalizedDriver.contains("mysql")) {
return MYSQL;
} else if (normalizedDriver.contains("mariadb")) {
return MARIADB;
}
return null;
}
MySQLVariant(String jdbcPrefix) {
this.jdbcPrefix = jdbcPrefix;
}
public String getJdbcPrefix() {
return jdbcPrefix;
}
}
}

View File

@ -0,0 +1,101 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.storage;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import com.zaxxer.hikari.HikariConfig;
public class PostgreSQLStorage extends SQLStorage {
private static final String JDBC_PROTOCOL = "jdbc:";
public PostgreSQLStorage(PlatformPlugin<?> plugin, String driver, String host, int port, String database,
HikariConfig config, boolean useSSL) {
super(plugin.getLog(), plugin.getName(), plugin.getThreadFactory(),
setParams(config, driver, host, port, database, useSSL));
}
private static HikariConfig setParams(HikariConfig config,
String driver, String host, int port, String database,
boolean useSSL) {
// Require SSL on the server if requested in config - this will also verify certificate
// Those values are deprecated in favor of sslMode
config.addDataSourceProperty("useSSL", useSSL);
config.addDataSourceProperty("requireSSL", useSSL);
// adding paranoid, hides hostname, username, version and so
// could be useful for hiding server details
config.addDataSourceProperty("paranoid", true);
config.setJdbcUrl(JDBC_PROTOCOL + buildJDBCUrl(driver, host, port, database));
return config;
}
private static String buildJDBCUrl(String driver, String host, int port, String database) {
return "postgresql://" + host + ':' + port + '/' + database;
}
@Override
protected String getCreateTableStmt() {
// PostgreSQL has a different syntax for id column
return CREATE_TABLE_STMT
.replace("`", "\"")
.replace("INTEGER PRIMARY KEY AUTO_INCREMENT", "SERIAL PRIMARY KEY");
}
@Override
protected String getAddFloodgateColumnStmt() {
// PostgreSQL has a different syntax
return ADD_FLOODGATE_COLUMN_STMT
.replace("`", "\"")
.replace("INTEGER(3)", "INTEGER");
}
@Override
protected String getLoadByNameStmt() {
return LOAD_BY_NAME_STMT
.replace("`", "\"");
}
@Override
protected String getLoadByUuidStmt() {
return LOAD_BY_UUID_STMT
.replace("`", "\"");
}
@Override
protected String getInsertProfileStmt() {
return INSERT_PROFILE_STMT
.replace("`", "\"");
}
@Override
protected String getUpdateProfileStmt() {
return UPDATE_PROFILE_STMT
.replace("`", "\"");
}
}

View File

@ -26,11 +26,13 @@
package com.github.games647.fastlogin.core.storage;
import com.github.games647.craftapi.UUIDAdapter;
import com.github.games647.fastlogin.core.shared.FloodgateState;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@ -56,13 +58,19 @@ public abstract class SQLStorage implements AuthStorage {
+ "UNIQUE (`Name`) "
+ ')';
protected static final String LOAD_BY_NAME = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `Name`=? LIMIT 1";
protected static final String LOAD_BY_UUID = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `UUID`=? LIMIT 1";
protected static final String INSERT_PROFILE = "INSERT INTO `" + PREMIUM_TABLE
+ "` (`UUID`, `Name`, `Premium`, `LastIp`) " + "VALUES (?, ?, ?, ?) ";
protected static final String ADD_FLOODGATE_COLUMN_STMT = "ALTER TABLE `" + PREMIUM_TABLE
+ "` ADD COLUMN `Floodgate` INTEGER(3)";
protected static final String LOAD_BY_NAME_STMT = "SELECT * FROM `" + PREMIUM_TABLE
+ "` WHERE `Name`=? LIMIT 1";
protected static final String LOAD_BY_UUID_STMT = "SELECT * FROM `" + PREMIUM_TABLE
+ "` WHERE `UUID`=? LIMIT 1";
protected static final String INSERT_PROFILE_STMT = "INSERT INTO `" + PREMIUM_TABLE
+ "` (`UUID`, `Name`, `Premium`, `Floodgate`, `LastIp`) " + "VALUES (?, ?, ?, ?, ?) ";
// limit not necessary here, because it's unique
protected static final String UPDATE_PROFILE = "UPDATE `" + PREMIUM_TABLE
+ "` SET `UUID`=?, `Name`=?, `Premium`=?, `LastIp`=?, `LastLogin`=CURRENT_TIMESTAMP WHERE `UserID`=?";
protected static final String UPDATE_PROFILE_STMT = "UPDATE `" + PREMIUM_TABLE
+ "` SET `UUID`=?, `Name`=?, `Premium`=?, `Floodgate`=?, `LastIp`=?, "
+ "`LastLogin`=CURRENT_TIMESTAMP WHERE `UserID`=?";
protected final Logger log;
protected final HikariDataSource dataSource;
@ -81,23 +89,36 @@ public abstract class SQLStorage implements AuthStorage {
// choose surrogate PK(ID), because UUID can be null for offline players
// if UUID is always Premium UUID we would have to update offline player entries on insert
// name cannot be PK, because it can be changed for premium players
//todo: add unique uuid index usage
try (Connection con = dataSource.getConnection();
Statement createStmt = con.createStatement()) {
createStmt.executeUpdate(CREATE_TABLE_STMT);
Statement stmt = con.createStatement()) {
stmt.executeUpdate(getCreateTableStmt());
// add Floodgate column
DatabaseMetaData md = con.getMetaData();
if (isColumnMissing(md, "Floodgate")) {
stmt.executeUpdate(getAddFloodgateColumnStmt());
}
}
}
private boolean isColumnMissing(DatabaseMetaData metaData, String columnName) throws SQLException {
try (ResultSet rs = metaData.getColumns(null, null, PREMIUM_TABLE, columnName)) {
return !rs.next();
}
}
@Override
public StoredProfile loadProfile(String name) {
try (Connection con = dataSource.getConnection();
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_NAME)
PreparedStatement loadStmt = con.prepareStatement(getLoadByNameStmt())
) {
loadStmt.setString(1, name);
try (ResultSet resultSet = loadStmt.executeQuery()) {
return parseResult(resultSet).orElseGet(() -> new StoredProfile(null, name, false, ""));
return parseResult(resultSet).orElseGet(() -> new StoredProfile(null, name, false,
FloodgateState.FALSE, ""));
}
} catch (SQLException sqlEx) {
log.error("Failed to query profile: {}", name, sqlEx);
@ -109,7 +130,7 @@ public abstract class SQLStorage implements AuthStorage {
@Override
public StoredProfile loadProfile(UUID uuid) {
try (Connection con = dataSource.getConnection();
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_UUID)) {
PreparedStatement loadStmt = con.prepareStatement(getLoadByUuidStmt())) {
loadStmt.setString(1, UUIDAdapter.toMojangId(uuid));
try (ResultSet resultSet = loadStmt.executeQuery()) {
@ -124,15 +145,28 @@ public abstract class SQLStorage implements AuthStorage {
private Optional<StoredProfile> parseResult(ResultSet resultSet) throws SQLException {
if (resultSet.next()) {
long userId = resultSet.getInt(1);
long userId = resultSet.getInt("UserID");
UUID uuid = Optional.ofNullable(resultSet.getString(2)).map(UUIDAdapter::parseId).orElse(null);
UUID uuid = Optional.ofNullable(resultSet.getString("UUID"))
.map(String::trim)
.map(UUIDAdapter::parseId)
.orElse(null);
String name = resultSet.getString(3);
boolean premium = resultSet.getBoolean(4);
String lastIp = resultSet.getString(5);
Instant lastLogin = resultSet.getTimestamp(6).toInstant();
return Optional.of(new StoredProfile(userId, uuid, name, premium, lastIp, lastLogin));
String name = resultSet.getString("Name");
boolean premium = resultSet.getBoolean("Premium");
int floodgateNum = resultSet.getInt("Floodgate");
FloodgateState floodgate;
// if the player wasn't migrated to the new database format
if (resultSet.wasNull()) {
floodgate = FloodgateState.NOT_MIGRATED;
} else {
floodgate = FloodgateState.fromInt(floodgateNum);
}
String lastIp = resultSet.getString("LastIp");
Instant lastLogin = resultSet.getTimestamp("LastLogin").toInstant();
return Optional.of(new StoredProfile(userId, uuid, name, premium, floodgate, lastIp, lastLogin));
}
return Optional.empty();
@ -146,22 +180,26 @@ public abstract class SQLStorage implements AuthStorage {
playerProfile.getSaveLock().lock();
try {
if (playerProfile.isSaved()) {
try (PreparedStatement saveStmt = con.prepareStatement(UPDATE_PROFILE)) {
try (PreparedStatement saveStmt = con.prepareStatement(getUpdateProfileStmt())) {
saveStmt.setString(1, uuid);
saveStmt.setString(2, playerProfile.getName());
saveStmt.setBoolean(3, playerProfile.isPremium());
saveStmt.setString(4, playerProfile.getLastIp());
saveStmt.setInt(4, playerProfile.getFloodgate().getValue());
saveStmt.setString(5, playerProfile.getLastIp());
saveStmt.setLong(5, playerProfile.getRowId());
saveStmt.setLong(6, playerProfile.getRowId());
saveStmt.execute();
}
} else {
try (PreparedStatement saveStmt = con.prepareStatement(INSERT_PROFILE, RETURN_GENERATED_KEYS)) {
try (PreparedStatement saveStmt = con.prepareStatement(getInsertProfileStmt(),
RETURN_GENERATED_KEYS)) {
saveStmt.setString(1, uuid);
saveStmt.setString(2, playerProfile.getName());
saveStmt.setBoolean(3, playerProfile.isPremium());
saveStmt.setString(4, playerProfile.getLastIp());
saveStmt.setBoolean(3, playerProfile.isPremium());
saveStmt.setInt(4, playerProfile.getFloodgate().getValue());
saveStmt.setString(5, playerProfile.getLastIp());
saveStmt.execute();
try (ResultSet generatedKeys = saveStmt.getGeneratedKeys()) {
@ -179,6 +217,38 @@ public abstract class SQLStorage implements AuthStorage {
}
}
/**
* SQLite and PostgreSQL have a slightly different syntax, so this will be overridden by SQLiteStorage and so on...
* @return An SQL Statement to create the `premium` table
*/
protected String getCreateTableStmt() {
return CREATE_TABLE_STMT;
}
/**
* PostgreSQL has a slightly different syntax, so this will be overridden by PostgreSQLStorage
* @return An SQL Statement to create the `premium` table
*/
protected String getAddFloodgateColumnStmt() {
return ADD_FLOODGATE_COLUMN_STMT;
}
protected String getLoadByNameStmt() {
return LOAD_BY_NAME_STMT;
}
protected String getLoadByUuidStmt() {
return LOAD_BY_UUID_STMT;
}
protected String getInsertProfileStmt() {
return INSERT_PROFILE_STMT;
}
protected String getUpdateProfileStmt() {
return UPDATE_PROFILE_STMT;
}
@Override
public void close() {
dataSource.close();

View File

@ -31,15 +31,23 @@ import org.sqlite.JDBC;
import org.sqlite.SQLiteConfig;
import java.nio.file.Path;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SQLiteStorage extends SQLStorage {
protected static final String CREATE_TABLE_STMT = "CREATE TABLE IF NOT EXISTS `" + PREMIUM_TABLE + "` ("
+ "`UserID` INTEGER PRIMARY KEY AUTO_INCREMENT, "
+ "`UUID` CHAR(36), "
+ "`Name` VARCHAR(16) NOT NULL, "
+ "`Premium` BOOLEAN NOT NULL, "
+ "`LastIp` VARCHAR(255) NOT NULL, "
+ "`LastLogin` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "
//the premium shouldn't steal the cracked account by changing the name
+ "UNIQUE (`Name`) "
+ ')';
private static final String SQLITE_DRIVER = "org.sqlite.SQLiteDataSource";
private final Lock lock = new ReentrantLock();
@ -103,12 +111,9 @@ public class SQLiteStorage extends SQLStorage {
}
@Override
public void createTables() throws SQLException {
try (Connection con = dataSource.getConnection();
Statement createStmt = con.createStatement()) {
// SQLite has a different syntax for auto increment
createStmt.executeUpdate(CREATE_TABLE_STMT.replace("AUTO_INCREMENT", "AUTOINCREMENT"));
}
protected String getCreateTableStmt() {
// SQLite has a different syntax for auto increment
return CREATE_TABLE_STMT.replace("AUTO_INCREMENT", "AUTOINCREMENT");
}
private static String replacePathVariables(Path dataFolder, String input) {

View File

@ -26,6 +26,7 @@
package com.github.games647.fastlogin.core.storage;
import com.github.games647.craftapi.model.Profile;
import com.github.games647.fastlogin.core.shared.FloodgateState;
import java.time.Instant;
import java.util.Objects;
@ -39,20 +40,28 @@ public class StoredProfile extends Profile {
private final ReentrantLock saveLock = new ReentrantLock();
private boolean premium;
private FloodgateState floodgate;
private String lastIp;
private Instant lastLogin;
public StoredProfile(long rowId, UUID uuid, String playerName, boolean premium, String lastIp, Instant lastLogin) {
public StoredProfile(long rowId, UUID uuid, String playerName, boolean premium, FloodgateState floodgate,
String lastIp, Instant lastLogin) {
super(uuid, playerName);
this.rowId = rowId;
this.premium = premium;
this.floodgate = floodgate;
this.lastIp = lastIp;
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) {
this(-1, uuid, playerName, premium, lastIp, Instant.now());
this(-1, uuid, playerName, premium, FloodgateState.FALSE, lastIp, Instant.now());
}
public ReentrantLock getSaveLock() {
@ -96,6 +105,18 @@ public class StoredProfile extends Profile {
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() {
return lastIp;
}
@ -128,7 +149,7 @@ public class StoredProfile extends Profile {
}
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
@ -141,6 +162,7 @@ public class StoredProfile extends Profile {
return this.getClass().getSimpleName() + '{'
+ "rowId=" + rowId
+ ", premium=" + premium
+ ", floodgate=" + floodgate
+ ", lastIp='" + lastIp + '\''
+ ", lastLogin=" + lastLogin
+ "} " + super.toString();

View File

@ -289,6 +289,15 @@ database: '{pluginDir}/FastLogin.db'
#username: 'myUser'
#password: 'myPassword'
# PostgreSQL
# If you want to enable it, uncomment only the lines below; this not this line.
#driver: 'postgresql'
#host: '127.0.0.1'
#port: 5432
#database: 'fastlogin'
#username: 'myUser'
#password: 'myPassword'
# Advanced Connection Pool settings in seconds
#timeout: 30
#lifetime: 30

View File

@ -70,7 +70,7 @@ no-console: '&4You are not a player. You cannot toggle the premium state for YOU
# The user wants to toggle premium state, but BungeeCord support is enabled. This means the server have to communicate
# with the BungeeCord first which will establish a connection with the database server.
wait-on-proxy: '&6Sending request... (Do not forget to follow the BungeeCord setup guide)'
wait-on-proxy: '&6Sending request... (Do not forget to follow the BungeeCord setup guide referenced on the plugin page)'
# When ProtocolLib is enabled and the plugin is unable to continue handling a login request after a requested premium
# authentication. In this state the client expects a success packet with an encrypted connection or disconnect packet.
@ -100,5 +100,3 @@ Type &a/premium&6 again to confirm'
invalid-public-key: '&cInvalid client public key. Please try to restart your game.'
# ========= Bungee/Waterfall only ================================

17
pom.xml
View File

@ -103,7 +103,7 @@
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>4.1</version>
<version>4.3</version>
<configuration>
<licenseSets>
<licenseSet>
@ -115,6 +115,7 @@
<excludes>
<exclude>src/test/resources/**</exclude>
<exclude>src/main/resources/**</exclude>
<exclude>.java-version</exclude>
</excludes>
</licenseSet>
</licenseSets>
@ -130,7 +131,7 @@
</plugin>
<plugin>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.2</version>
<version>3.3.1</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
<consoleOutput>true</consoleOutput>
@ -141,7 +142,7 @@
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>10.9.3</version>
<version>10.12.7</version>
</dependency>
</dependencies>
<executions>
@ -158,7 +159,7 @@
<!-- Require newer versions for Junit5 support -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<version>3.2.5</version>
</plugin>
</plugins>
@ -187,22 +188,22 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.1</version>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
<!-- Require inline to support static mocks -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>5.2.0</version>
<artifactId>mockito-core</artifactId>
<version>5.9.0</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -55,7 +55,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>templating-maven-plugin</artifactId>
<version>1.0.0</version>
<version>3.0.0</version>
<executions>
<execution>
<id>filter-src</id>
@ -67,7 +67,7 @@
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<version>3.5.1</version>
<configuration>
<minimizeJar>true</minimizeJar>
@ -97,6 +97,10 @@
<exclude>com.google.guava:guava</exclude>
</excludes>
</artifactSet>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
@ -129,6 +133,10 @@
<id>velocity</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>opencollab-snapshot</id>
<url>https://repo.opencollab.dev/main/</url>
</repository>
</repositories>
<dependencies>
@ -143,7 +151,7 @@
<dependency>
<groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId>
<version>3.1.1</version>
<version>3.3.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@ -151,7 +159,29 @@
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.1.0</version>
<version>3.3.2</version>
</dependency>
<!-- Bedrock player bridge -->
<dependency>
<groupId>org.geysermc.geyser</groupId>
<artifactId>core</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Floodgate -->
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>${floodgate.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -27,6 +27,8 @@ package com.github.games647.fastlogin.velocity;
import com.github.games647.fastlogin.core.AsyncScheduler;
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.GeyserService;
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
import com.github.games647.fastlogin.core.message.ChannelMessage;
import com.github.games647.fastlogin.core.message.SuccessMessage;
@ -50,6 +52,8 @@ import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
import com.velocitypowered.api.proxy.messages.ChannelRegistrar;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.geyser.GeyserImpl;
import org.slf4j.Logger;
import java.io.IOException;
@ -76,6 +80,8 @@ public class FastLoginVelocity implements PlatformPlugin<CommandSource> {
private FastLoginCore<Player, CommandSource, FastLoginVelocity> core;
private AsyncScheduler scheduler;
private FloodgateService floodgateService;
private GeyserService geyserService;
private UUID proxyId;
@Inject
@ -95,6 +101,14 @@ public class FastLoginVelocity implements PlatformPlugin<CommandSource> {
return;
}
if (isPluginInstalled("floodgate")) {
floodgateService = new FloodgateService(FloodgateApi.getInstance(), core);
}
if (isPluginInstalled("Geyser-Velocity")) {
geyserService = new GeyserService(GeyserImpl.getInstance(), core);
}
server.getEventManager().register(this, new ConnectListener(this, core.getAntiBot()));
server.getEventManager().register(this, new PluginMessageListener(this));
@ -140,9 +154,21 @@ public class FastLoginVelocity implements PlatformPlugin<CommandSource> {
return server.getPluginManager().isLoaded(name);
}
public FloodgateService getFloodgateService() {
return floodgateService;
}
public GeyserService getGeyserService() {
return geyserService;
}
@Override
public BedrockService<?> getBedrockService() {
return null;
if (floodgateService != null) {
return floodgateService;
}
return geyserService;
}
public FastLoginCore<Player, CommandSource, FastLoginVelocity> getCore() {

View File

@ -53,10 +53,12 @@ public class VelocityLoginSource implements LoginSource {
public void kick(String message) {
if (message == null) {
preLoginEvent.setResult(PreLoginEvent.PreLoginComponentResult.denied(
Component.text("Kicked").color(NamedTextColor.WHITE)));
Component.text("Kicked").color(NamedTextColor.WHITE))
);
} else {
preLoginEvent.setResult(PreLoginEvent.PreLoginComponentResult.denied(
LegacyComponentSerializer.legacyAmpersand().deserialize(message)));
LegacyComponentSerializer.legacyAmpersand().deserialize(message))
);
}
}

View File

@ -28,13 +28,15 @@ package com.github.games647.fastlogin.velocity.listener;
import com.github.games647.craftapi.UUIDAdapter;
import com.github.games647.fastlogin.core.antibot.AntiBotService;
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.velocity.FastLoginVelocity;
import com.github.games647.fastlogin.velocity.VelocityLoginSession;
import com.github.games647.fastlogin.velocity.task.AsyncPremiumCheck;
import com.github.games647.fastlogin.velocity.task.FloodgateAuthTask;
import com.github.games647.fastlogin.velocity.task.ForceLoginTask;
import com.velocitypowered.api.event.Continuation;
import com.velocitypowered.api.event.EventTask;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.connection.PreLoginEvent;
@ -48,6 +50,7 @@ import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.api.util.GameProfile.Property;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import java.net.InetSocketAddress;
import java.util.ArrayList;
@ -67,9 +70,9 @@ public class ConnectListener {
}
@Subscribe
public void onPreLogin(PreLoginEvent preLoginEvent, Continuation continuation) {
public EventTask onPreLogin(PreLoginEvent preLoginEvent) {
if (!preLoginEvent.getResult().isAllowed()) {
return;
return null;
}
InboundConnection connection = preLoginEvent.getConnection();
@ -81,28 +84,30 @@ public class ConnectListener {
switch (action) {
case Ignore:
// just ignore
return;
return null;
case Block:
String message = plugin.getCore().getMessage("kick-antibot");
TextComponent messageParsed = LegacyComponentSerializer.legacyAmpersand().deserialize(message);
PreLoginComponentResult reason = PreLoginComponentResult.denied(messageParsed);
preLoginEvent.setResult(reason);
break;
return null;
case Continue:
default:
Runnable asyncPremiumCheck = new AsyncPremiumCheck(
plugin, connection, username, continuation, preLoginEvent
return EventTask.async(
new AsyncPremiumCheck(plugin, connection, username, preLoginEvent)
);
plugin.getScheduler().runAsync(asyncPremiumCheck);
break;
}
}
@Subscribe
public void onGameprofileRequest(GameProfileRequestEvent event) {
public void onGameProfileRequest(GameProfileRequestEvent event) {
if (event.isOnlineMode()) {
LoginSession session = plugin.getSession().get(event.getConnection().getRemoteAddress());
if (session == null) {
plugin.getLog().warn("No active login session found for player {}", event.getUsername());
return;
}
UUID verifiedUUID = event.getGameProfile().getId();
String verifiedUsername = event.getUsername();
@ -141,8 +146,20 @@ public class ConnectListener {
Player player = serverConnectedEvent.getPlayer();
RegisteredServer server = serverConnectedEvent.getServer();
FloodgateService floodgateService = plugin.getFloodgateService();
if (floodgateService != null) {
FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(player.getUniqueId());
if (floodgatePlayer != null) {
plugin.getLog().info("Running floodgate handling for {}", player);
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer, server);
plugin.getScheduler().runAsync(floodgateAuthTask);
return;
}
}
VelocityLoginSession session = plugin.getSession().get(player.getRemoteAddress());
if (session == null) {
plugin.getLog().info("No active login session found on server connect for {}", player);
return;
}
@ -151,7 +168,7 @@ public class ConnectListener {
// player is still in the login phase and reported to be offline.
Runnable loginTask = new ForceLoginTask(plugin.getCore(), player, server, session);
plugin.getProxy().getScheduler()
.buildTask(plugin, () -> plugin.getScheduler().runAsync(loginTask))
.buildTask(plugin, loginTask)
.delay(1L, TimeUnit.SECONDS) // Delay at least one second, otherwise the login command can be missed
.schedule();
}

View File

@ -29,6 +29,7 @@ import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
import com.github.games647.fastlogin.core.message.SuccessMessage;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.storage.StoredProfile;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.velocity.FastLoginVelocity;
import com.github.games647.fastlogin.velocity.VelocityLoginSession;
import com.github.games647.fastlogin.velocity.task.AsyncToggleMessage;
@ -115,7 +116,15 @@ public class PluginMessageListener {
}
private void onSuccessMessage(Player forPlayer) {
if (forPlayer.isOnlineMode()) {
boolean shouldPersist = forPlayer.isOnlineMode();
FloodgateService floodgateService = plugin.getFloodgateService();
if (!shouldPersist && floodgateService != null) {
// always save floodgate players to lock this username
shouldPersist = floodgateService.isBedrockPlayer(forPlayer.getUniqueId());
}
if (shouldPersist) {
//bukkit module successfully received and force logged in the user
//update only on success to prevent corrupt data
VelocityLoginSession loginSession = plugin.getSession().get(forPlayer.getRemoteAddress());

View File

@ -33,7 +33,6 @@ import com.github.games647.fastlogin.velocity.VelocityLoginSession;
import com.github.games647.fastlogin.velocity.VelocityLoginSource;
import com.github.games647.fastlogin.velocity.event.VelocityFastLoginPreLoginEvent;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.event.Continuation;
import com.velocitypowered.api.event.connection.PreLoginEvent;
import com.velocitypowered.api.proxy.InboundConnection;
import com.velocitypowered.api.proxy.Player;
@ -45,28 +44,22 @@ public class AsyncPremiumCheck extends JoinManagement<Player, CommandSource, Vel
private final FastLoginVelocity plugin;
private final String username;
private final Continuation continuation;
private final PreLoginEvent preLoginEvent;
private final InboundConnection connection;
public AsyncPremiumCheck(FastLoginVelocity plugin, InboundConnection connection, String username,
Continuation continuation, PreLoginEvent preLoginEvent) {
PreLoginEvent preLoginEvent) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
this.plugin = plugin;
this.connection = connection;
this.username = username;
this.continuation = continuation;
this.preLoginEvent = preLoginEvent;
}
@Override
public void run() {
plugin.getSession().remove(connection.getRemoteAddress());
try {
super.onLogin(username, new VelocityLoginSource(connection, preLoginEvent));
} finally {
continuation.resume();
}
super.onLogin(username, new VelocityLoginSource(connection, preLoginEvent));
}
@Override

View File

@ -0,0 +1,85 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.velocity.task;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.FloodgateManagement;
import com.github.games647.fastlogin.velocity.FastLoginVelocity;
import com.github.games647.fastlogin.velocity.VelocityLoginSession;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import java.net.InetSocketAddress;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class FloodgateAuthTask
extends FloodgateManagement<Player, CommandSource, VelocityLoginSession, FastLoginVelocity> {
private final RegisteredServer server;
public FloodgateAuthTask(FastLoginCore<Player, CommandSource, FastLoginVelocity> core, Player player,
FloodgatePlayer floodgatePlayer, RegisteredServer server) {
super(core, player, floodgatePlayer);
this.server = server;
}
@Override
protected void startLogin() {
VelocityLoginSession session = new VelocityLoginSession(player.getUsername(), isRegistered, profile);
core.getPlugin().getSession().put(player.getRemoteAddress(), session);
// enable auto login based on the value of 'autoLoginFloodgate' in config.yml
boolean forcedOnlineMode = autoLoginFloodgate.equals("true")
|| (autoLoginFloodgate.equals("linked") && isLinked);
// delay sending force command, because Paper will process the login event asynchronously
// In this case it means that the force command (plugin message) is already received and processed while
// player is still in the login phase and reported to be offline.
Runnable loginTask = new ForceLoginTask(core.getPlugin().getCore(), player, server, session, forcedOnlineMode);
core.getPlugin().getProxy().getScheduler()
.buildTask(core.getPlugin(), () -> core.getPlugin().getScheduler().runAsync(loginTask))
.delay(1L, TimeUnit.SECONDS) // Delay at least one second, otherwise the login command can be missed
.schedule();
}
@Override
protected String getName(Player player) {
return player.getUsername();
}
@Override
protected UUID getUUID(Player player) {
return player.getUniqueId();
}
@Override
protected InetSocketAddress getAddress(Player player) {
return player.getRemoteAddress();
}
}

View File

@ -68,6 +68,7 @@ public class ForceLoginTask
@Override
public void run() {
if (session == null) {
core.getPlugin().getLog().info("No active login session on force handling for {}", player);
return;
}
@ -80,6 +81,7 @@ public class ForceLoginTask
@Override
public boolean forceLogin(Player player) {
if (session.isAlreadyLogged()) {
core.getPlugin().getLog().info("Ignoring second force login attempt for {}", player);
return true;
}
@ -92,11 +94,11 @@ public class ForceLoginTask
VelocityFastLoginAutoLoginEvent event = new VelocityFastLoginAutoLoginEvent(session, profile);
try {
return core.getPlugin().getProxy().getEventManager().fire(event).get();
} catch (InterruptedException e) {
} catch (InterruptedException interruptedEx) {
Thread.currentThread().interrupt(); // Set the interrupt flag again
return event;
} catch (ExecutionException e) {
core.getPlugin().getLog().error("Error firing event", e);
} catch (ExecutionException executionEx) {
core.getPlugin().getLog().error("Error firing event", executionEx);
return event;
}
}
@ -114,6 +116,8 @@ public class ForceLoginTask
type = Type.REGISTER;
}
core.getPlugin().getLog().info("Sending force {} for {} towards server {}", type, player.getUsername(), server);
UUID proxyId = core.getPlugin().getProxyId();
ChannelMessage loginMessage = new LoginActionMessage(type, player.getUsername(), proxyId);
core.getPlugin().sendPluginMessage(server, loginMessage);