Compare commits

...

201 Commits

Author SHA1 Message Date
games647
a9e4c90970 Merge pull request #799 from games647/dependabot/maven/org.mariadb.jdbc-mariadb-java-client-3.0.5
Bump mariadb-java-client from 3.0.4 to 3.0.5
2022-06-15 13:15:15 +02:00
games647
0af22d9927 Merge pull request #811 from Enginecrafter77/main
Support for transparent proxies / DNAT
2022-06-11 08:40:48 +02:00
Enginecrafter77
5abd864fa5 fix: Typo in config.yml comment about useProxyAgnosticResolver 2022-06-10 11:55:31 +02:00
Enginecrafter77
d7d0caf6e7 style: Re-phrasing of config.yml comment for useProxyAgnosticResolver
The comment for useProxyAgnosticResolver in config.yml was re-phrased and supplied with additional information regarding its effective context and its relation to the prevent-proxy setting in server.properties.
2022-06-10 11:40:21 +02:00
Enginecrafter77
edd82f7978 style: ProxyAgnosticMojangResolver: Extracted the URL into a constant
The URL of the mojang session server call in ProxyAgnosticMojangResolver was extracted into a constant in order to mitigate the "magic constants" problem.

Additionally, the 204 in the response code check was replaced by a constant from HttpURLConnection, again, in order to not use any magic numbers.
2022-06-10 11:38:22 +02:00
Enginecrafter77
6413ca4d10 fix: Reverted the invalid session log entry modification
The initial debug-entry modification regarding the invalid session message was reverted. Now the logging and parameter expansion is done solely by the SLF4J library.
2022-06-10 11:14:10 +02:00
Enginecrafter77
5f494e5a04 feat: Config option to enable ProxyAgnosticMojangResolver
A config option was added to allow users to use the ProxyAgnosticMojangResolver if they feel the need to do so. This setting won't affect existing users since it's disabled by default.
2022-06-09 19:24:53 +02:00
Enginecrafter77
5d4483224d refactor: ProxyAgnosticMojangResolver
ProxyAgnosticMojangResolver serves as a cleaner implementation of the hasJoined static method from previous commit. All the reflection involved was removed due to no longer being necessary. This way, a lot cleaner code could be made. All the inner workings remained the same. For more information on how it works, check out ProxyAgnosticMojangResolver.java.
2022-06-09 19:04:49 +02:00
Enginecrafter77
61b86fba52 fix: Initial addressing of #810
This commit contains a crude but functional fix for problem described by issue #810. It works by reimplementing the MojangResolver#hasJoined method using reflection to access the inaccessible fields. The significant difference is that unlike in the CraftAPI implementation, which sends the "ip" parameter when the hostIp parameter is an IPv4 address, but skips it for IPv6, this implementation ommits the "ip" parameter also for IPv4, effectively enabling transparent proxies to work.

WARNING: This commit contains only a proof-of-concept code with crude hacks to make it work with the least amount of code edits. Improvements upon the code will be included in following commits. The code is at the moment really ineffective, and therefore SHOULD NOT BE USED IN PRODUCTION! You have been warned.
2022-06-09 18:41:03 +02:00
games647
6665c0359b Note latest proxy version 2022-06-08 10:20:15 +02:00
games647
896291be53 Bump BungeeCord required version
Fixes #808
2022-06-08 10:08:15 +02:00
games647
5828e1abde Remove last sodion reference 2022-06-07 18:51:22 +02:00
games647
8d50a14371 Drop SodionAuth plugin, because it's no longer reachable in Maven 2022-06-07 18:26:24 +02:00
games647
0ae18f3ac6 Always log invalid state messages
Related #803
Related #806
2022-06-07 18:24:27 +02:00
games647
82d8b4d2be Fix typo in messages for invalid-request 2022-06-07 18:18:28 +02:00
dependabot[bot]
41890679ed Bump mariadb-java-client from 3.0.4 to 3.0.5
Bumps [mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) from 3.0.4 to 3.0.5.
- [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.0.4...3.0.5)

---
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>
2022-05-30 07:03:27 +00:00
games647
fc50c997ba Dump craftapi for updated GSON version and allow . in legit usernames 2022-05-21 14:02:37 +02:00
games647
b04b8f5806 Merge pull request #790 from games647/dependabot/github_actions/github/codeql-action-2
Bump github/codeql-action from 1 to 2
2022-05-20 12:34:03 +02:00
games647
16f8a49b4c Inform users about the delayed session start for proxies 2022-05-20 12:32:58 +02:00
dependabot[bot]
830d6b1e35 Bump github/codeql-action from 1 to 2
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 2.
- [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/v1...v2)

---
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>
2022-05-01 07:04:13 +00:00
games647
a32791687c Merge pull request #774 from games647/dependabot/github_actions/actions/checkout-3
Bump actions/checkout from 2 to 3
2022-04-01 13:21:52 +02:00
games647
5d63d304e6 Merge pull request #775 from games647/dependabot/github_actions/actions/cache-3.0.1
Bump actions/cache from 2.1.4 to 3.0.1
2022-04-01 13:21:29 +02:00
dependabot[bot]
f25d8b3a99 Bump actions/cache from 2.1.4 to 3.0.1
Bumps [actions/cache](https://github.com/actions/cache) from 2.1.4 to 3.0.1.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v2.1.4...v3.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-01 07:02:15 +00:00
dependabot[bot]
cac96408a0 Bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [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/v2...v3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-01 07:02:13 +00:00
games647
0bdcc935ad Merge pull request #771 from games647/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.3.0
Bump maven-shade-plugin from 3.2.4 to 3.3.0
2022-03-30 17:34:12 +02:00
dependabot[bot]
07dea4ac0f Bump maven-shade-plugin from 3.2.4 to 3.3.0
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.2.4 to 3.3.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.2.4...maven-shade-plugin-3.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-30 14:04:11 +00:00
games647
f4a3fed017 Highlight build definition 2022-03-30 16:02:52 +02:00
games647
0105c29710 Reduce memory consumption of anti bot feature 2022-03-30 16:02:52 +02:00
games647
d11cd4f9a1 Ignore META-Info in shading 2022-03-30 16:02:52 +02:00
games647
6c0baea278 Make questions section more specific 2022-03-30 16:02:52 +02:00
games647
55270702a5 Document event behavior that is platform specific 2022-03-30 16:02:52 +02:00
games647
9d2c346235 Use platform scheduler to reuse threads between plugins
The platforms usually use a caching thread executor. It makes to use
this executor to reuse threads as they are expensive to create.
2022-03-30 16:02:51 +02:00
games647
1d3fcb9929 Use custom repository settings for faster fetching
Order of repository seems to indicate maven priority fetching
2022-03-30 16:02:51 +02:00
games647
35b044651c Update dependencies
diff --git a/bukkit/pom.xml b/bukkit/pom.xml
index e57b9d2..939697a 100644
--- a/bukkit/pom.xml
+++ b/bukkit/pom.xml
@@ -272,7 +272,7 @@
         <dependency>
             <groupId>com.lenis0012.bukkit</groupId>
             <artifactId>loginsecurity</artifactId>
-            <version>3.0.2</version>
+            <version>3.1</version>
             <scope>provided</scope>
             <optional>true</optional>
             <exclusions>
diff --git a/core/pom.xml b/core/pom.xml
index 15a1eb7..3738e9d 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -179,7 +179,7 @@
         <dependency>
             <groupId>com.google.code.gson</groupId>
             <artifactId>gson</artifactId>
-            <version>2.8.9</version>
+            <version>2.9.0</version>
         </dependency>
     </dependencies>
 </project>
2022-03-30 16:02:51 +02:00
dependabot[bot]
666fabd76c Bump mariadb-java-client from 3.0.3 to 3.0.4
Bumps [mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) from 3.0.3 to 3.0.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/compare/3.0.3...3.0.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>
2022-03-28 13:17:13 +02:00
dependabot[bot]
5d49c497b5 Bump slf4j-jdk14 from 2.0.0-alpha6 to 2.0.0-alpha7 (#756)
Bumps [slf4j-jdk14](https://github.com/qos-ch/slf4j) from 2.0.0-alpha6 to 2.0.0-alpha7.
- [Release notes](https://github.com/qos-ch/slf4j/releases)
- [Commits](https://github.com/qos-ch/slf4j/compare/v_2.0.0-alpha6...v_2.0.0-alpha7)

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-jdk14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-28 13:16:30 +02:00
games647
812cf21ad0 Merge pull request #750 from Smart123s/license/autoheader
Fix License header
2022-03-14 14:54:17 +01:00
Smart123s
e7a915a6cd Check license headers before building
If a header is missing, then the build should fail. If someone commits
a new file, WITHOUT building it beforehnd, than that header won't be
added. The CI will build the plugin, but changes made by the CI are not
retained in the source tree.
2022-03-13 10:41:33 +01:00
Smart123s
a856356c49 Update license headers to 02db104
Done using `mvn license:format`
2022-03-13 10:08:57 +01:00
Smart123s
e9ea930be7 Update copyright year in LICENSE 2022-03-13 10:06:17 +01:00
games647
59eb9ced8b Merge pull request #741 from games647/dependabot/github_actions/actions/setup-java-3
Bump actions/setup-java from 2.3.0 to 3
2022-03-01 08:32:54 +01:00
dependabot[bot]
60d414eacb Bump actions/setup-java from 2.3.0 to 3
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 2.3.0 to 3.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/v2.3.0...v3)

---
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>
2022-03-01 07:02:58 +00:00
games647
ae93b3215a Merge pull request #737 from Smart123s/fix/736
Fix 'no-conflict' option of 'autoLoginFloodgate' in config
2022-02-26 17:37:37 +01:00
Smart123s
7e9bd1639b Move similar config checks to a common function
'autoRegisterFloodgate' and 'autoLoginFloodgate' have the same possible
options, and they are checked against the player in the exact same way.
For example, if either one of them is set to isLinked, linked status is
checked in the same way, regardless of wether it's checked for login or
for registering.
2022-02-25 18:14:25 +01:00
Smart123s
817eedd4ac Move autoLoginFloodgate check to a common function
Reduces duplicate code.
Added missing check for "no-conflict".
2022-02-25 18:13:44 +01:00
games647
033fdd55ae [ci-skip] Update proxy setup guide 2022-02-15 12:01:13 +01:00
games647
d581b34005 Use mariadb protocol if using its connector
MariaDB enforces this to ensure the selection of the correct driver.

Fixes #724
2022-02-09 12:57:14 +01:00
games647
3665e15920 Add velocity driver hint
Related #723
2022-02-09 12:57:14 +01:00
games647
6f16700cdf Merge pull request #717 from games647/dependabot/maven/org.mariadb.jdbc-mariadb-java-client-3.0.3
Bump mariadb-java-client from 2.7.5 to 3.0.3
2022-02-07 18:07:34 +01:00
Smart123s
8e6221d846 Fix delayed force login for Floodgate players
Login checks are done by bungee, so Bukkit doesn't have to do anything.
The session is set for them by the plugin messages, however, force login
may be delayed. In that case, the player should be logged in at
the onPlayerJoin event.
However, FloodgateAuthTask was run at onPlayerJoin, even if the player
allready had a valid login session. And FloodgateAuthTask always deffers
force login if bungee is present.
As a result, the Floodgate player will never get logged in, if the force
login was delayed by the plugin message.

Co-authored-by: BOT-Neil <neilbooth125@gmail.com>
2022-02-07 17:30:51 +01:00
games647
7a049b98a6 Update distribution 2022-02-07 17:18:10 +01:00
games647
8de1546e7b Update craftapi to fix broken prevent-proxy api
Related #718
2022-02-04 16:37:13 +01:00
dependabot[bot]
7cce0f6e4a Bump mariadb-java-client from 2.7.5 to 3.0.3
Bumps [mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) from 2.7.5 to 3.0.3.
- [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/2.7.5...3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-31 07:02:36 +00:00
games647
999738ef3e Merge pull request #715 from Smart123s/fix/bukkit/noplibload
Fix plugin start without ProtocolLib installed
2022-01-29 11:55:55 +01:00
Smart123s
7951c4c893 Fix plugin startup without ProtocolLib installed
Referencing `ProtocolLibrary` in FastLoginBukkit (even in an unreachable
code block) causes Bukkit servers to throw a NoClassDefFoundError on
startup.
Fix based on commit 0082cc6536
2022-01-29 10:48:27 +01:00
games647
9b04ea5c89 Merge pull request #707 from games647/dependabot/maven/org.mariadb.jdbc-mariadb-java-client-2.7.5
Bump mariadb-java-client from 2.7.4 to 2.7.5
2022-01-25 20:27:13 +01:00
dependabot[bot]
ac66cefd33 Bump mariadb-java-client from 2.7.4 to 2.7.5
Bumps [mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) from 2.7.4 to 2.7.5.
- [Release notes](https://github.com/mariadb-corporation/mariadb-connector-j/releases)
- [Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/blob/2.7.5/CHANGELOG.md)
- [Commits](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.4...2.7.5)

---
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>
2022-01-20 10:51:24 +00:00
games647
8a01ddc231 Do not shade the MultiMap class
This class is used by ProtocolLib. Calling it, means we use its signature. With relocating this would also update the method
call signature to `.WrappedGameProfile.getProperties()Lfastlogin/guava/collect/Multimap;`, which obviously not present.
2022-01-20 11:50:32 +01:00
games647
3bcc6c2e94 Differentiate between rate limit and IOExceptions
(Related #698)
2022-01-14 14:22:11 +01:00
games647
b351338e0b Allow disabling anti bot completely 2022-01-14 14:13:43 +01:00
games647
36c9ae2465 Fix rate limiter
Time reported by nanoTime is arbitrarily and could include negative numbers
2022-01-14 14:03:14 +01:00
games647
e0f823cbe4 Fix rate limiter blocking the first requests
If the server just started, expireTime can become negative. Therefore, the first uninitialized values will not be made available.
2022-01-14 13:20:44 +01:00
games647
17234a791b Update logging dependency 2022-01-14 12:56:22 +01:00
games647
0e935e3ad0 Fail safe if command is not specified in plugin.yml 2022-01-14 12:53:51 +01:00
games647
52d778afb1 Clean up 2022-01-14 12:52:46 +01:00
games647
e6eb4939b4 Document generics 2022-01-14 12:50:53 +01:00
games647
36337f7feb Fix potential thread-safety issues in storing the profile 2022-01-14 12:50:07 +01:00
games647
aa51e98fe2 Declare nullable variants using jetbrains annotations 2022-01-14 12:16:30 +01:00
games647
a5c7e7371d Try out to minimize unnecessary classes from big dependencies 2022-01-14 12:14:22 +01:00
games647
35b493a708 Typo fixes 2022-01-14 12:12:47 +01:00
games647
b02a1a54d9 Add velocity platform to support tickets 2022-01-14 12:02:19 +01:00
games647
253da03f9c Add missing descriptions 2022-01-14 12:01:25 +01:00
games647
4a5516c9f9 Merge pull request #566 from Smart123s/fg-plib-fix
Workaround for Floodgate prefixes with ProtocolLlib
2021-12-23 12:28:15 +01:00
games647
3ca8ae694d Merge pull request #682 from games647/dependabot/maven/me.clip-placeholderapi-2.11.0
Bump placeholderapi from 2.10.10 to 2.11.0
2021-12-21 19:19:47 +01:00
dependabot[bot]
1d7c2aed61 Bump placeholderapi from 2.10.10 to 2.11.0
Bumps placeholderapi from 2.10.10 to 2.11.0.

---
updated-dependencies:
- dependency-name: me.clip:placeholderapi
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-20 07:01:45 +00:00
Smart123s
03850ae4f2 Only add Floodgate prefixes if they are needed
Without this patch, Java players would also get a prefix.
2021-12-09 19:40:46 +01:00
Smart123s
b92911bf26 Made floodgatePrefixWorkaround configurable 2021-12-09 18:03:29 +01:00
Smart123s
8859ebb454 Manually append Floodgate Prefixes
This can be used as a workaround for #493
This will leave
821be02bdb/spigot/src/main/java/org/geysermc/floodgate/addon/data/SpigotDataHandler.java
in a limbo state, but it shouldn't have a noticable impact on neither
performance nor stability.
This commit will try append prefixes to every player, even if it's not
needed of if Floodgate isn't installed.
2021-12-09 18:01:58 +01:00
games647
06a8d6c625 Merge pull request #674 from Smart123s/fix/geyser/mc-1.18
Update to Geyser 2.0 API (fix 1.18)
2021-12-07 19:24:24 +01:00
Smart123s
8c33813e45 Update to Geyser 2.0 API 2021-12-06 19:22:54 +01:00
games647
95251b611a Initialize logger factory by doing a first call to it
Related #670
2021-12-03 10:22:33 +01:00
games647
6c47abc76d Update dependencies 2021-12-03 09:46:26 +01:00
games647
9c2068032f Remove duplicate dependency 2021-12-03 09:46:26 +01:00
games647
2110e93bd6 Override slf4j transitive dependency from paper
Fixes #670
2021-12-03 09:46:25 +01:00
games647
7439a95e16 Reduce the amount of necessary dependencies by dropping transitive ones 2021-12-02 14:40:29 +01:00
games647
e1c1da199e Search SL4J JDK provider in our own classpath
Using the previous behavior it would look for the service file and provider
in the server jar. First it requires relocating the service file to our JDK
provider and let the service only be queryable from our plugin jar.

Fixes #668

Search SL4J JDK provider in our own classpath

Using the previous behavior it would look for the service file and provider
in the server jar. First it requires relocating the service file to our JDK
provider and let the service only be queryable from our plugin jar.

Fixes #668
2021-12-02 14:40:26 +01:00
games647
829ba79400 Merge pull request #659 from AlbeMiglio/main
Added latest Guava and SLF4J compatibility
2021-12-01 16:34:14 +01:00
games647
1dd27ff529 Restore 1.8 compatibility by shading guava in Spigot versions 2021-12-01 16:29:37 +01:00
Alberto Migliorato
2cdfdcb5c5 Added latest Guava and SLF4J compatibility
(1.18+ breaks support to older guava methods)
2021-12-01 01:12:38 +01:00
Oldřich Jedlička
15fee92937 Detect enabled Velocity support in server 2021-11-29 13:12:19 +01:00
games647
cb29c5e226 Merge pull request #655 from games647/dependabot/maven/com.velocitypowered-velocity-api-3.1.0
Bump velocity-api from 3.0.1 to 3.1.0
2021-11-28 14:04:50 +01:00
games647
d8cd39a974 Merge pull request #654 from games647/dependabot/maven/io.papermc-paperlib-1.0.7
Bump paperlib from 1.0.6 to 1.0.7
2021-11-28 14:04:44 +01:00
dependabot[bot]
9a2bc14b72 Bump velocity-api from 3.0.1 to 3.1.0
Bumps velocity-api from 3.0.1 to 3.1.0.

---
updated-dependencies:
- dependency-name: com.velocitypowered:velocity-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-28 12:48:34 +00:00
dependabot[bot]
f5a60ca0b3 Bump paperlib from 1.0.6 to 1.0.7
Bumps [paperlib](https://github.com/PaperMC/PaperLib) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/PaperMC/PaperLib/releases)
- [Changelog](https://github.com/PaperMC/PaperLib/blob/master/CHANGELOG.md)
- [Commits](https://github.com/PaperMC/PaperLib/compare/1.0.6...v1.0.7)

---
updated-dependencies:
- dependency-name: io.papermc:paperlib
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-28 12:46:15 +00:00
games647
10a7b01bc7 Merge branch 'Smart123s-feature/geyser/allowOfflineNameConflict' 2021-11-28 13:45:33 +01:00
Smart123s
909f263189 Update GH Actions to build with Java 16 2021-11-28 13:45:25 +01:00
Smart123s
2f61a8f8ad Add packet level checks for Geyser
If AuthType == ONLINE, players will be treated as if they were Java
players
If AuthType == OFFLINE, name conflicts will be checked the same way it's
done with Floodgate
Updated config.yml to infrom about the changes.
2021-11-28 13:45:23 +01:00
Smart123s
d0a7832929 Remove unused Floodgate 1.0 dependency 2021-11-28 13:44:57 +01:00
Smart123s
2ac638f3f9 Merge bedrock packet checks into a single function
Floodgate and Geyser specific checks can now be modified without
changing JoinManagement.
Added the ability to resume Java specific checks for Bedrock players.
This will be neccessary for Geyser `auth-type=online` players
2021-11-28 13:44:57 +01:00
Smart123s
af0bc34255 Use local Floodgate instance
Shortens code and fixes an unused warning
2021-11-28 13:44:57 +01:00
Smart123s
fcd2aa95f0 Use BedrockService in JoinManagement
Since the code only needs to interact with Geyser, if Floodgate is not
installed, and perform similar things with both, it's reasonable, to
merge their code.
This commit breaks premium checking with `auth-type=online` in Geyser
2021-11-28 13:44:57 +01:00
Smart123s
f76c7bd62f Create generalized BedrockService class 2021-11-28 13:44:57 +01:00
Smart123s
f570474fa3 Detect Geyser connections at packet level
It is possible to use Geyser without Floodgate by configuring Geyser to
use auth-type= 'online' or 'offline'. In that scenario, floodgateService
will be either unavailable or empty.
2021-11-28 13:44:57 +01:00
Smart123s
3ee6cb2ada Create stub GeyserService
The FloodgateService and GeyserService classes are not merged,
because Geyser can work without Floodgate.
Added Geyser as 'softdepends' in plugin.yml and bungee.yml
to make it load before FastLogin.
Also made Floodgate a soft dependency in bungee.yml.
2021-11-28 13:44:56 +01:00
games647
5612ca744b Fix relocating mariadb driver in Velocity
Fixes #643
2021-11-04 10:29:57 +01:00
games647
d2c94af4a7 Merge pull request #636 from Smart123s/fix/floodgate/pluginmessage
Fix "No Session" in plugin messaging
2021-10-24 20:23:53 +02:00
Smart123s
4c514c269b Fix "No Session" in plugin messaging
After Bungee recieved a plugin message from Bukkit, that it has
completed login/register for a Floodgate player, bungee would throw a
NullPointerException: Cannot invoke "BungeeLoginSession.getProfile()"
because "loginSession" is null
2021-10-24 18:24:50 +02:00
games647
40b4eae756 Merge pull request #635 from Smart123s/fix/floodgate/prefix-detect
Fix Floodgate player detection (caused by prefixes)
2021-10-23 17:38:14 +02:00
Smart123s
9978fe69d5 Fix Floodgate detection for buggy ProtocolLib 2021-10-23 15:56:16 +02:00
Smart123s
94299d2547 Prefixed names for packet level Floodgate checks 2021-10-23 13:24:40 +02:00
games647
ef6f0fc436 Fix detecting floodgate on plugin name
Floodgate's name is lowercase
Related #630
2021-10-11 16:09:24 +02:00
games647
1f83a656cc Merge pull request #629 from Krakenied/main
Fix #627 - skip Floodgate config validation if there's no Floodgate installed
2021-10-10 13:38:29 +02:00
Krakenied
d7e0a4469f Fix #627 - skip Floodgate config validation if there's no Floodgate installed
Fix BungeeManager NPE
2021-10-09 19:52:26 +02:00
games647
28480a0f01 Add floodgate service to Bungee 2021-10-05 15:42:40 +02:00
games647
a3bf875976 Encapsulate floodgate hooks
Related #619
Related #620
2021-10-05 15:35:43 +02:00
games647
11c91e6428 Merge pull request #622 from BOT-Neil/main
Update JoinManagement.java Dont Check empty for empty prefix
2021-10-05 14:39:36 +02:00
BOT-Neil
8490ff628c Update JoinManagement.java 2021-10-01 17:15:05 +02:00
BOT-Neil
0d7b8e237d Update JoinManagement.java
dont check for empty prefixes
2021-10-01 13:29:02 +02:00
games647
8b4d4586a7 Fix compiling 2021-09-23 14:56:30 +02:00
games647
cd55441e4e Allow configuring SSL requirements for MySQL instances
Fixes #433
2021-09-23 14:55:23 +02:00
games647
17ecb186a5 Require full verification if SSL is enabled in MySQL 2021-09-23 14:43:24 +02:00
games647
aaff7710e0 Merge pull request #612 from juanmuscaria/main
Velocity support
2021-09-22 12:47:21 +02:00
games647
37ac04c8ed Reformat 2021-09-22 12:13:33 +02:00
games647
c2ec8c93b0 Use the MariaDB driver for a smaller footprint 2021-09-22 12:03:44 +02:00
games647
665881d19a Exclude gson already present in velocity 2021-09-22 12:01:08 +02:00
games647
5192b98d78 Use java runner for cache 2021-09-22 11:48:59 +02:00
juanmuscaria
709edc6c0a Added comment to the config to notify about the different driver name 2021-09-17 10:04:05 -03:00
juanmuscaria
c458bd383a Only remove the texture property from the player profile if forwardSkin is disabled 2021-09-17 10:00:45 -03:00
juanmuscaria
64fbbf759f Actually handle proxy shutdown this time 2021-09-17 09:45:09 -03:00
juanmuscaria
20379d13b2 Commented why org.slf4j is excluded from the final jar 2021-09-17 09:40:12 -03:00
juanmuscaria
310ef4068c Make PROXY_ID_fILE static 2021-09-17 09:37:50 -03:00
juanmuscaria
bc4d9857b4 Ops, printing exception directly 2021-09-17 09:36:51 -03:00
juanmuscaria
d0491d44ec Remove left over assertion 2021-09-17 09:35:07 -03:00
juanmuscaria
7ade127888 Relocate the MySql Driver 2021-09-16 13:42:36 -03:00
juanmuscaria
68a783bd40 Use path directly for loading the proxy uuid 2021-09-16 13:25:35 -03:00
juanmuscaria
352702eae4 Some code formatting and cleanup 2021-09-15 20:08:03 -03:00
juanmuscaria
b6dfa4802a Removed old FIXME and added a new TODO 2021-09-15 19:58:29 -03:00
juanmuscaria
fc226e1010 Moved LoginEvent logic to GameProfileRequestEvent. Allow overwriting online mode uuid and support for forwardSkin. Added one second delay for login command. 2021-09-15 19:58:29 -03:00
juanmuscaria
4befb35af9 Added a way to generate or use a predefined proxy uuid. 2021-09-15 19:58:29 -03:00
juanmuscaria
01632ec125 Cleanup unused imports 2021-09-15 15:44:51 -03:00
juanmuscaria
268c70bc51 Use org.slf4j.Logger directly 2021-09-15 13:54:28 -03:00
Enrique García
ec7c421f83 [Security] Check if cracked user have the Floodgate prefix (#614) 2021-09-15 16:50:55 +02:00
juanmuscaria
f82c85d3eb Ops, seems like velocity repo already mirrors the latest driver. 2021-09-14 12:29:49 -03:00
juanmuscaria
6e318ba9bb Use logger for exceptions 2021-09-14 12:26:52 -03:00
juanmuscaria
89d03bcc6b I missed that there was an alternative for bungee in the documentation 2021-09-14 12:22:22 -03:00
juanmuscaria
502b16a0e7 Fill all plugin metadata properly. 2021-09-14 12:12:04 -03:00
juanmuscaria
de0655cba2 Changed the database driver to mysql 2021-09-14 11:59:22 -03:00
juanmuscaria
0e7d8a595d Added missing license header for some classes. 2021-09-14 11:36:26 -03:00
juanmuscaria
7178ea4587 Seems like this is generated automatically. 2021-09-13 21:29:56 -03:00
juanmuscaria
e639e29dee Partial velocity support. 2021-09-13 21:24:46 -03:00
games647
d8021931b6 Merge pull request #606 from Smart123s/fg-nostorage-fix
Don't crash if no storage is loaded
2021-08-29 20:48:47 +02:00
games647
47ee2cf458 [ci skip] Merge pull request #609 from cmod31/patch-1
BungeeCord/Waterfall section
2021-08-29 10:56:32 +02:00
cmod31
d564d74443 BungeeCord/Waterfall section
Added some detail.
issue #607
2021-08-29 10:47:05 +02:00
Smart123s
586b357be8 Don't crash if no storage is loaded
If the pluign is running on Bukkit, and it's connected to Bungee
then core.getStorage() will be null.
If that's the case, players will be logged in via a plugin messages.
2021-08-26 13:40:41 +02:00
games647
172efafc2b Merge pull request #602 from Smart123s/fg-bungee-handshake
Fix plugin messages for Floodgate players
2021-08-23 17:17:56 +02:00
Smart123s
056b8a7af7 Recieve success message for Floodgate
Floodgate players are offline players, so a special check needs to be
done to save Floodgate players as if they were online players.
2021-08-22 13:33:20 +02:00
Smart123s
198e8f9ea2 Fix Floodgate without auth plugin
If no auth plugin is installed, rely on StoredProfile
This fixes #594
2021-08-22 13:33:16 +02:00
Smart123s
f39c3a1ea6 Update Floodgate repository 2021-08-20 11:49:54 +02:00
games647
7dd0aa5bca Limit parallelism to one thread for SQLite
Fixes #596
2021-08-14 17:54:57 +02:00
games647
f8fe3d7d71 Do not silence exceptions for Floodgate 2021-08-12 20:39:14 +02:00
games647
4d4ecf3da7 Merge pull request #583 from games647/dependabot/maven/org.slf4j-slf4j-jdk14-1.7.32
Bump slf4j-jdk14 from 1.7.31 to 1.7.32
2021-07-26 10:06:59 +02:00
dependabot[bot]
f80059987b Bump slf4j-jdk14 from 1.7.31 to 1.7.32
Bumps [slf4j-jdk14](https://github.com/qos-ch/slf4j) from 1.7.31 to 1.7.32.
- [Release notes](https://github.com/qos-ch/slf4j/releases)
- [Commits](https://github.com/qos-ch/slf4j/commits)

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-jdk14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-26 07:02:17 +00:00
games647
6e0272d92c Fix receiving login packet twice with ProtocolLib
Fixes #578
Commit that introduces the bug:
1f4757669c
2021-07-16 14:24:17 +02:00
games647
758ccb9bf2 Clean up 2021-07-14 16:33:31 +02:00
games647
0515ac193d Extract protocollib method detection 2021-07-14 16:33:18 +02:00
games647
864e551a88 Disable verbose verification output
NameChange fix is resolved
2021-07-14 16:32:32 +02:00
games647
0a24d36ef8 [ci skip] Rephrase development build section
Fixes #576
2021-07-12 17:25:52 +02:00
games647
8a535e1ad9 [ci skip] Merge pull request #574 from MAX-XiaoKui/patch-1
Update plugin SodionAuth's link. Its URL has changed.
2021-07-10 17:18:08 +02:00
MAX_小葵
ae66f1ab35 Update plugin SodionAuth's link 2021-07-10 22:04:54 +08:00
games647
ed725d991e [ci skip] Show user clickable links 2021-07-06 11:25:52 +02:00
games647
e45d4b3482 [ci skip] Require what happened form 2021-07-06 11:20:36 +02:00
games647
b5b5faaefb [ci skip] Add feedback message to forms 2021-06-30 17:23:54 +02:00
games647
51a28ae93f [CI-SKIP] Fix issue template syntax 2021-06-30 17:04:16 +02:00
games647
d2fcdade0b [CI-SKIP] Try out issue forms 2021-06-30 17:02:19 +02:00
games647
cde045d6fd Only build for main branches to fix duplicate actions with dependabot 2021-06-29 12:55:37 +02:00
games647
ccdc455ce9 Clarify naming and structure 2021-06-22 14:07:47 +02:00
games647
4e1f5e9401 Add icons to issue templates 2021-06-22 13:25:57 +02:00
games647
2e64b52261 Migrate questions to discussions 2021-06-22 13:25:41 +02:00
games647
1f4757669c Allow packet modifications by other plugins
If we disable filters, other plugins are advised to only monitor
packets. Potential modifications can be allowed by enabling the filtering again, but adding our meta data to prevent duplicate
processing.
2021-06-22 11:15:21 +02:00
games647
496817afca Increase the rate limit for bigger servers
Related #406
2021-06-21 18:00:45 +02:00
games647
daf6f06a00 Name anti-bot feature explicitly for own rate limiting 2021-06-21 17:33:38 +02:00
games647
4be0e1333d [CI-SKIP] Add issue template descriptions 2021-06-21 17:08:20 +02:00
games647
58cee1e26e Exclude more transitive dependencies
This could reduce the number of required
downloads as well as to prevent download
from legacy HTTP non secure (not HTTPS)
sources.
2021-06-21 17:08:20 +02:00
games647
9f89756820 Disable plugin if dependencies not available
Related #554
2021-06-21 17:08:20 +02:00
games647
d1daec436c Merge pull request #559 from Smart123s/fg2-ln-autoreg
Add 'linked' option to 'autoRegisterFloodgate'
2021-06-21 16:31:25 +02:00
Smart123s
2626c21bc8 Add 'linked' option to 'autoRegisterFloodgate'
This makes sense with Floodgate 2.0's Global Link API
2021-06-21 15:15:18 +02:00
games647
5607a19312 Merge pull request #560 from Smart123s/fg-player-to-account
Update messages
2021-06-21 14:30:46 +02:00
games647
1f950397a4 Merge pull request #561 from games647/dependabot/maven/org.slf4j-slf4j-jdk14-1.7.31
Bump slf4j-jdk14 from 1.7.30 to 1.7.31
2021-06-21 12:07:45 +02:00
dependabot[bot]
08e26dd60f Bump slf4j-jdk14 from 1.7.30 to 1.7.31
Bumps [slf4j-jdk14](https://github.com/qos-ch/slf4j) from 1.7.30 to 1.7.31.
- [Release notes](https://github.com/qos-ch/slf4j/releases)
- [Commits](https://github.com/qos-ch/slf4j/commits)

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-jdk14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 07:03:13 +00:00
Smart123s
2ffe7e0daf Replace word 'Player' with 'Account' in messages.
Technically speaking, one player can own both the Java and the Bedrock
account with the same name, so it's more appropriate to say account
instead of player.
2021-06-20 17:44:46 +02:00
Smart123s
33261b9ea6 Floodgate 2.0 is no longer in a seperate branch 2021-06-20 17:37:18 +02:00
games647
5442f773ae Merge pull request #558 from Smart123s/fg-sharedtask
Add Floodgate config options for BungeeCord
2021-06-20 14:03:45 +02:00
Smart123s
fd3da28bec Use Override for non core code in FloodgateAuthTas 2021-06-20 13:35:31 +02:00
Smart123s
9350f52916 Create a seperate function for isNameCheckRequired 2021-06-20 13:23:51 +02:00
Smart123s
7c2bb9c9a4 Don't spam log when with unregistered floodgate 2021-06-20 13:05:04 +02:00
Smart123s
0b307a95a3 Add further documentation to config.yml
Floodgate options are no longer Bukkit only
autoRegister/LoginFloodgate needs normal (Java) autoRegister/Login
to be set to ture
2021-06-20 11:26:15 +02:00
Smart123s
ed627ce438 Add autoLogin and register for Floodgate Bungee 2021-06-20 11:26:14 +02:00
Smart123s
af83604c94 Remove existing Floodgate integration from Bungee 2021-06-20 11:26:13 +02:00
Smart123s
8f43cc0978 Partially move FloodgateAuthTask to Core
The moved code can be used in a BungeeCord implementation
2021-06-20 11:26:13 +02:00
games647
578028719f Merge pull request #556 from Smart123s/patch-5
FloodgateNameConflict no longer needs autoLogin
2021-06-19 10:43:09 +02:00
Péter Tombor
b87b59be12 FloodgateNameConflict no longer needs autoLogin
The removed line is not valid after 1f3cd5fa5b
2021-06-18 23:25:46 +02:00
120 changed files with 3725 additions and 1224 deletions

View File

@@ -1,41 +0,0 @@
---
name: Bug report
about: Something isn't working
title: ''
labels: 'bug'
assignees: ''
---
[//]: # (Lines in this format are considered as comments and will not be displayed.)
[//]: # (Before reporting make sure you're running the **latest build** of the plugin and checked for existing issues!)
### What behaviour is observed:
[//]: # (What happened?)
### What behaviour is expected:
[//]: # (What did you expect?)
### Steps/models to reproduce:
[//]: # (The actions that cause the issue. Please explain it in detail)
### Screenshots (if applicable)
[//]: # (You can drop the files here directly)
### Plugin list:
[//]: # (This can be found by running `/pl`)
### Environment description
[//]: # (Server software with exact version number, Minecraft version, SQLite/MySQL/MariaDB, ...)
### Plugin version or build number (don't write latest):
[//]: # (This can be found by running `/version plugin-name`.)
### Server Log:
[//]: # (No images please - only the textual representation)
[Hastebin](https://hastebin.com/) / [Gist](https://gist.github.com/) link of the error, stacktrace or the complete log (if any)
### Configuration:
[//]: # (No images please - only the textual representation)
[//]: # (remember to delete any sensitive data)
[Hastebin](https://hastebin.com/) / [Gist](https://gist.github.com/) link of your config.yml file

68
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View File

@@ -0,0 +1,68 @@
name: 🐞 Bug Report
description: Something isn't working, broken, not expected behavior
labels: [bug]
body:
- type: markdown
attributes:
value: |
This ticket is about bugs, so broken, not expected behavior. Feedback about this form is appreciated.
- type: textarea
attributes:
label: What happened?
description: What behavior is observed?
validations:
required: true
- type: textarea
attributes:
label: What did you expect?
description: What behavior is expected?
- type: textarea
attributes:
label: Steps to reproduce
description: The actions that cause the issues. Please explain it in detail.
- type: input
attributes:
label: Plugin list
description: This can be found by running `/pl`
placeholder: AuthMe, ProtocolLib, ...
- type: input
attributes:
label: Configuration file
description: |
Link to the contents of your config.yml file.
You can use [GitHub](https://gist.github.com/), [Hastebin](https://hastebin.com) or similar for that.
placeholder: https://gist.github.com/games647/88c4439e1cd7810f21318b1b24a04ee0
- type: textarea
attributes:
label: Server log
description: The error, stacktrace or link the complete log. You can use the links above for long versions.
render: shell
placeholder: https://hastebin.com/ / https://gist.github.com/
- type: input
attributes:
label: Plugin version
description: Plugin version or build number. This can be found by running `/version plugin-name`
placeholder: v3.1-SNAPSHOT-570b321
validations:
required: true
- type: dropdown
attributes:
label: Platform
description: Server software - choose your proxy software if you have multiple servers
options:
- Spigot
- BungeeCord
- Velocity
validations:
required: true
- type: checkboxes
attributes:
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)
required: true
- label: |
I checked for existing tickets -
If there are, please vote them with a thumps reaction and not create new ones
required: true

12
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# General configuration for issue templates
# Allow issues without a template
#blank_issues_enabled: false
# Extra section on creating issues to redirect to another site
contact_links:
- name: 📌 Questions
url: https://github.com/games647/FastLogin/discussions
about:
You want to ask something - general questions. Example includes how to set it up or how it is working internally

View File

@@ -1,5 +1,5 @@
---
name: Enhancement request
name: 💡 Enhancement request
about: New feature or change request
title: ''
labels: 'enhancement'
@@ -8,6 +8,9 @@ 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 [...])

View File

@@ -1,10 +0,0 @@
---
name: Question
about: You want to ask something
title: ''
labels: 'question'
assignees: ''
---

View File

@@ -1,6 +1,6 @@
# GitHub automatic code security scanning using CodeQL
# Human readable name in the actions tab
# Human-readable name in the actions tab
name: "CodeQL"
on:
@@ -33,26 +33,35 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v3
with:
distribution: 'adopt'
# Use Java 16, because it's minimum required version by Geyser
java-version: 16
cache: 'maven'
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# Cache build process too like in the maven config
- uses: actions/cache@v2.1.4
- uses: actions/cache@v3.0.1
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# 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@v1
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2

View File

@@ -1,50 +1,43 @@
# Automatically build, run unit and integration tests to detect errors early (CI provided by GitHub)
# including making pull requests review easier
# Human readable name in the actions tab
# Human-readable name in the actions tab
name: Java CI
# Build on every push and pull request regardless of the branch
# Build on every pull request regardless of the branch
# Wiki: https://help.github.com/en/actions/reference/events-that-trigger-workflows
on:
- push
- pull_request
push:
branches:
- main
pull_request:
branches:
- main
jobs:
# job id
build_and_test:
# Environment image - always newest OS
# Environment image - always use the newest OS
runs-on: ubuntu-latest
# Run steps
steps:
# Pull changes
- uses: actions/checkout@v2.3.4
# Pull changes
- uses: actions/checkout@v3
# Cache artifacts - however this has the downside that we don't get notified of
# artifact resolution failures like invalid repository
# Nevertheless the repositories should be more stable and it makes no sense to pull
# a same version every time
# A dry run would make more sense
- uses: actions/cache@v2.1.4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v3
with:
distribution: 'temurin'
# Use Java 16, because it's minimum required version by Geyser
java-version: 16
cache: 'maven'
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v2.1.0
with:
distribution: 'adopt'
# Use Java 11, because it's minimum required version
java-version: 11
# Build and test (included in package)
- name: Build with Maven and test
# Run non-interactive, package (with compile+test),
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums to validate
# possible errors in dependencies
run: mvn test --batch-mode --no-snapshot-updates --strict-checksums --file pom.xml
# Build and test (included in package)
- name: Build with Maven and test
# Run non-interactive, package (with compile+test),
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums to validate
# possible errors in dependencies
run: mvn test --batch-mode --no-snapshot-updates --strict-checksums --file pom.xml

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015-2021 games647 and contributors
Copyright (c) 2015-2022 games647 and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -12,7 +12,7 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
* Forge/Sponge message support
* Premium UUID support
* Forward skins
* Detect user name changed and will update the existing database record
* Detect username changed and will update the existing database record
* BungeeCord support
* Auto register new premium players
* Plugin: ProtocolSupport is supported and can be used as an alternative to ProtocolLib
@@ -23,21 +23,17 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
## Issues
Please use issues for bug reports, suggestions, questions and more. Please check for existing issues. Existing issues
Please use issues for bug reports, suggestions, questions and more. Please check for existing issues. Existing issues
can be voted up by adding up vote to the original post. Closing issues means that they are marked as resolved. Comments
are still allowed and it could be re-opened.
## Development builds
Development builds of this project can be acquired at the provided CI (continuous integration) server. It contains the
latest changes from the Source-Code in preparation for the following release. This means they could contain new
features, bug fixes and other changes since the last release.
Development builds contain the latest changes from the Source-Code. They are bleeding edge and could introduce new bugs,
but also include features, enhancements and bug fixes that are not yet in a released version. If you click on the left
side on `Changes`, you can see iterative change sets leading to a specific build.
They **could** contain new bugs and are likely to be less stable than released versions.
Specific builds can be grabbed by clicking on the build number on the left side or by clicking on status to retrieve the
latest build.
https://ci.codemc.org/job/Games647/job/FastLogin/changes
You can download them from here: https://ci.codemc.org/job/Games647/job/FastLogin/
***
@@ -55,21 +51,22 @@ https://ci.codemc.org/job/Games647/job/FastLogin/changes
## Placeholder
This plugin supports `PlaceholderAPI` on `Spigot`. It exports the following variable
`%fastlogin_status%`. In BungeeCord environments, the status of a player will be delivered with a delay after the player
This plugin supports `PlaceholderAPI` on `Spigot`. It exports the following variable
`%fastlogin_status%`. In BungeeCord environments, the status of a player will be delivered with a delay after the player
already successful joined the server. This takes about a couple of milliseconds. In this case the value
will be `Unknown`.
will be `Unknown`.
Possible values: `Premium`, `Cracked`, `Unknown`
Possible values: `Premium`, `Cracked`, `Unknown`
## Requirements
* Plugin:
* [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
* [Spigot](https://www.spigotmc.org) 1.8.8+
* Java 8+
* Run Spigot (or a fork e.g. Paper) and/or BungeeCord (or a fork e.g. Waterfall) in offline mode
* Server software in offlinemode:
* Spigot (or a fork e.g. Paper) 1.8.8+
* Protocol plugin:
* [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
* Latest BungeeCord (or a fork e.g. Waterfall)
* An auth plugin.
### Supported auth plugins
@@ -81,7 +78,7 @@ Possible values: `Premium`, `Cracked`, `Unknown`
* [CrazyLogin](https://dev.bukkit.org/bukkit-plugins/crazylogin/)
* [LoginSecurity](https://dev.bukkit.org/bukkit-plugins/loginsecurity/)
* [LogIt](https://github.com/games647/LogIt)
* [SodionAuth (2.0+)](https://github.com/Mohist-Community/SodionAuth)
* [SodionAuth (2.0+)](https://github.com/MohistMC/SodionAuth)
* [UltraAuth](https://dev.bukkit.org/bukkit-plugins/ultraauth-aa/)
* [UserLogin](https://www.spigotmc.org/resources/userlogin.80669/)
* [xAuth](https://dev.bukkit.org/bukkit-plugins/xauth/)
@@ -90,7 +87,7 @@ Possible values: `Premium`, `Cracked`, `Unknown`
* [BungeeAuth](https://www.spigotmc.org/resources/bungeeauth.493/)
* [BungeeAuthenticator](https://www.spigotmc.org/resources/bungeecordauthenticator.87669/)
* [SodionAuth (2.0+)](https://github.com/Mohist-Community/SodionAuth)
* [SodionAuth (2.0+)](https://github.com/MohistMC/SodionAuth)
## Network requests
@@ -106,20 +103,28 @@ This plugin performs network requests to:
### Spigot/Paper
1. Download and install ProtocolLib/ProtocolSupport
2. Download and install FastLogin (or FastLoginBukkit for newer versions)
3. Set your server in offline mode by setting the value onlinemode in your server.properties to false
2. Download and install FastLogin (or `FastLoginBukkit` for newer versions)
3. Set your server in offline mode by setting the value `onlinemode` in your server.properties to false
### BungeeCord/Waterfall
### BungeeCord/Waterfall or Velocity
1. Activate BungeeCord in the Spigot configuration
2. Restart your server
3. Now there is `allowed-proxies.txt` file in the FastLogin folder
Put your stats id from the BungeeCord config into this file
4. Activate ipForward in your BungeeCord config
5. Download and Install FastLogin (or FastLoginBungee in newer versions) on BungeeCord AND Spigot
(on the servers where your login plugin is or where player should be able to execute the commands of FastLogin)
6. Check your database settings in the config of FastLogin on BungeeCord
7. Set proxy and Spigot in offline mode by setting the value onlinemode in your config.yml to false
8. You should *always* firewall your Spigot server that it's only accessible through BungeeCord
* https://www.spigotmc.org/wiki/bungeecord-installation/#post-installation
* BungeeCord doesn't support SQLite per default, so you should change the configuration to MySQL or MariaDB
Install the plugin on both platforms, that is proxy (BungeeCord or Velocity) and backend server (Spigot).
1. Activate proxy support in the server configuration
* This is often found in `spigot.yml` or `paper.yml`
2. Restart the backend server
3. Now there is `allowed-proxies.txt` file in the FastLogin folder of the restarted server
* BungeeCord: Put your `stats-id` from the BungeeCord config into this file
* Velocity: On plugin startup the plugin generates a `proxyId.txt` inside the plugins folder of the proxy
4. Activate ip forwarding in your proxy config
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
* 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
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* firewall your Spigot server that it's only accessible through your proxy
* This is also the case without this plugin
* https://www.spigotmc.org/wiki/bungeecord-installation/#post-installation

View File

@@ -4,7 +4,7 @@
The MIT License (MIT)
Copyright (c) 2015-2021 <Your name and contributors>
Copyright (c) 2015-2022 games647 and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -36,7 +36,7 @@
<relativePath>../pom.xml</relativePath>
</parent>
<!--This have to be in lowercase because it's used by plugin.yml-->
<!--This has to be in lowercase because it's used by plugin.yml-->
<artifactId>fastlogin.bukkit</artifactId>
<packaging>jar</packaging>
@@ -47,7 +47,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<version>3.3.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>false</shadedArtifactAttached>
@@ -68,11 +68,33 @@
<pattern>com.google.gson</pattern>
<shadedPattern>fastlogin.gson</shadedPattern>
</relocation>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>fastlogin.guava</shadedPattern>
<excludes>
<exclude>com.google.common.collect.Multimap</exclude>
</excludes>
</relocation>
<relocation>
<pattern>io.papermc.lib</pattern>
<shadedPattern>fastlogin.paperlib</shadedPattern>
</relocation>
</relocations>
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
<!-- Located in META-INF/services -->
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
<minimizeJar>true</minimizeJar>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/MANIFEST.MF</exclude>
<exclude>**/module-info.class</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
@@ -106,12 +128,6 @@
<repository>
<id>codemc-releases</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
</repository>
<!-- GitHub automatic maven builds -->
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
@@ -126,10 +142,13 @@
</snapshots>
</repository>
<!-- Floodgate -->
<!-- GitHub automatic maven builds -->
<repository>
<id>nukkitx-snapshot</id>
<url>https://repo.nukkitx.com/maven-snapshots/</url>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
@@ -141,28 +160,40 @@
<version>${project.version}</version>
</dependency>
<!-- PaperSpigot API for correcting usercache usage -->
<!-- PaperSpigot API for correcting user cache usage -->
<dependency>
<groupId>com.destroystokyo.paper</groupId>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.15.2-R0.1-SNAPSHOT</version>
<version>1.18-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<!-- Use our own newer api version -->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- PaperLib for checking if server uses PaperSpigot -->
<dependency>
<groupId>io.papermc</groupId>
<artifactId>paperlib</artifactId>
<version>1.0.6</version>
<scope>compile</scope>
<version>1.0.7</version>
</dependency>
<!--Library for listening and sending Minecraft packets-->
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.6.0</version>
<version>4.8.0</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Changing onlinemode on login process-->
@@ -172,15 +203,6 @@
<!--4.29.dev after commit about API improvements-->
<version>3a80c661fe</version>
<scope>provided</scope>
</dependency>
<!--Provide premium placeholders-->
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.10.8</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>*</groupId>
@@ -195,6 +217,53 @@
<artifactId>api</artifactId>
<version>2.0-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.geysermc.cumulus</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Bedrock player bridge -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>core</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- We need the API, but it was excluded above -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>geyser-api</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
</dependency>
<!--Provide premium placeholders-->
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.1</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Login Plugins-->
@@ -215,7 +284,7 @@
<dependency>
<groupId>com.lenis0012.bukkit</groupId>
<artifactId>loginsecurity</artifactId>
<version>3.0.2</version>
<version>3.1</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
@@ -282,19 +351,5 @@
<scope>system</scope>
<systemPath>${project.basedir}/lib/UltraAuth v2.1.2.jar</systemPath>
</dependency>
<dependency>
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
<artifactId>SodionAuth-Bukkit</artifactId>
<version>2bdfdc854b</version>
<exclusions>
<exclusion>
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
<artifactId>SodionAuth-Libs</artifactId>
</exclusion>
</exclusions>
<optional>true</optional>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -69,11 +69,11 @@ public class BukkitLoginSession extends LoginSession {
}
/**
* Gets the verify token the server sent to the client.
* Gets the verify-token the server sent to the client.
*
* Empty if it's a BungeeCord connection
*
* @return the verify token from the server
* @return verify token from the server
*/
public synchronized byte[] getVerifyToken() {
return verifyToken.clone();

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,7 +28,6 @@ package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.core.AsyncScheduler;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
@@ -38,8 +37,8 @@ public class BukkitScheduler extends AsyncScheduler {
private final Executor syncExecutor;
public BukkitScheduler(Plugin plugin, Logger logger, ThreadFactory threadFactory) {
super(logger, threadFactory);
public BukkitScheduler(Plugin plugin, Logger logger) {
super(logger, command -> Bukkit.getScheduler().runTaskAsynchronously(plugin, command));
syncExecutor = r -> Bukkit.getScheduler().runTask(plugin, r);
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -88,9 +88,9 @@ public class BungeeManager {
public void initialize() {
try {
enabled = detectBungeeCord();
enabled = detectProxy();
} catch (Exception ex) {
plugin.getLog().warn("Cannot check bungeecord support. Fallback to non-bungee mode", ex);
plugin.getLog().warn("Cannot check proxy support. Fallback to non-proxy mode", ex);
}
if (enabled) {
@@ -99,16 +99,21 @@ public class BungeeManager {
}
}
private boolean detectBungeeCord() throws Exception {
private boolean isProxySupported(String className, String fieldName) {
try {
enabled = Class.forName("org.spigotmc.SpigotConfig").getDeclaredField("bungee").getBoolean(null);
return enabled;
return Class.forName(className).getDeclaredField(fieldName).getBoolean(null);
} catch (ClassNotFoundException notFoundEx) {
//ignore server has no bungee support
return false;
} catch (Exception ex) {
throw ex;
//ignore server has no proxy support
} catch (NoSuchFieldException | IllegalAccessException noSuchFieldException) {
plugin.getLog().warn("Cannot access proxy field", noSuchFieldException);
}
return false;
}
private boolean detectProxy() {
return isProxySupported("org.spigotmc.SpigotConfig", "bungee")
|| isProxySupported("com.destroystokyo.paper.PaperConfig", "velocitySupport");
}
private void registerPluginChannels() {
@@ -162,7 +167,7 @@ public class BungeeManager {
/**
* Mark the event to be fired including the task delay.
*
* @param player
* @param player joining player
*/
public synchronized void markJoinEventFired(Player player) {
firedJoinEvents.add(player.getUniqueId());
@@ -176,7 +181,7 @@ public class BungeeManager {
* session. If not fired, we can start a new force login task. This will still match the requirement that we wait
* a certain time after the player join event fired.
*
* @param player
* @param player joining player
* @return event fired including delay
*/
public synchronized boolean didJoinEventFired(Player player) {
@@ -186,7 +191,7 @@ public class BungeeManager {
/**
* Player quit clean up
*
* @param player
* @param player joining player
*/
public synchronized void cleanup(Player player) {
firedJoinEvents.remove(player.getUniqueId());

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,13 +28,17 @@ package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
import com.github.games647.fastlogin.bukkit.listener.PaperPreLoginListener;
import com.github.games647.fastlogin.bukkit.listener.PaperCacheListener;
import com.github.games647.fastlogin.bukkit.listener.protocollib.ManualNameChange;
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
import com.github.games647.fastlogin.bukkit.listener.protocollib.SkinApplyListener;
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
import com.github.games647.fastlogin.bukkit.task.DelayedAuthHook;
import com.github.games647.fastlogin.core.CommonUtil;
import com.github.games647.fastlogin.core.PremiumStatus;
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.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
@@ -43,6 +47,7 @@ import io.papermc.lib.PaperLib;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -52,6 +57,8 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.geyser.GeyserImpl;
import org.slf4j.Logger;
/**
@@ -68,12 +75,14 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
private BungeeManager bungeeManager;
private final BukkitScheduler scheduler;
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
private FloodgateService floodgateService;
private GeyserService geyserService;
private PremiumPlaceholder premiumPlaceholder;
public FastLoginBukkit() {
this.logger = CommonUtil.createLoggerFromJDK(getLogger());
this.scheduler = new BukkitScheduler(this, logger, getThreadFactory());
this.logger = CommonUtil.initializeLoggerService(getLogger());
this.scheduler = new BukkitScheduler(this, logger);
}
@Override
@@ -82,22 +91,19 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
core.load();
if (getServer().getOnlineMode()) {
//we need to require offline to prevent a loginSession request for a offline player
//we need to require offline to prevent a loginSession request for an offline player
logger.error("Server has to be in offline mode");
setEnabled(false);
return;
}
// Check Floodgate config values
if (!isValidFloodgateConfigString("autoLoginFloodgate")
|| !isValidFloodgateConfigString("allowFloodgateNameConflict")) {
setEnabled(false);
return;
}
if (!initializeFloodgate()) {
setEnabled(false);
}
bungeeManager = new BungeeManager(this);
bungeeManager.initialize();
PluginManager pluginManager = getServer().getPluginManager();
if (bungeeManager.isEnabled()) {
markInitialized();
@@ -112,12 +118,29 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
} else if (pluginManager.isPluginEnabled("ProtocolLib")) {
ProtocolLibListener.register(this, core.getRateLimiter());
if (isPluginInstalled("floodgate")) {
if (getConfig().getBoolean("floodgatePrefixWorkaround")){
ManualNameChange.register(this, floodgateService);
logger.info("Floodgate prefix injection workaround has been enabled.");
logger.info("If you have problems joining the server, try disabling it in the configuration.");
} else {
logger.warn("We have detected that you are runnging FastLogin alongside Floodgate and ProtocolLib.");
logger.warn("Currently there is an issue with FastLogin that prevents Floodgate name prefixes from showing up "
+ "when it is together used with ProtocolLib.");
logger.warn("If you would like to use Floodgate name prefixes, you can enable an experimental workaround by changing "
+ "the value 'floodgatePrefixWorkaround' to true in config.yml.");
logger.warn("For more information visit https://github.com/games647/FastLogin/issues/493");
}
}
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
if (!PaperLib.isPaper() && getConfig().getBoolean("forwardSkin")) {
pluginManager.registerEvents(new SkinApplyListener(this), this);
}
} else {
logger.warn("Either ProtocolLib or ProtocolSupport have to be installed if you don't use BungeeCord");
setEnabled(false);
return;
}
}
@@ -126,14 +149,14 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
pluginManager.registerEvents(new ConnectionListener(this), this);
//if server is using paper - we need to add one more listener to correct the usercache usage
//if server is using paper - we need to add one more listener to correct the user cache usage
if (PaperLib.isPaper()) {
pluginManager.registerEvents(new PaperPreLoginListener(this), this);
pluginManager.registerEvents(new PaperCacheListener(this), this);
}
//register commands using a unique name
getCommand("premium").setExecutor(new PremiumCommand(this));
getCommand("cracked").setExecutor(new CrackedCommand(this));
Optional.ofNullable(getCommand("premium")).ifPresent(c -> c.setExecutor(new PremiumCommand(this)));
Optional.ofNullable(getCommand("cracked")).ifPresent(c -> c.setExecutor(new CrackedCommand(this)));
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
premiumPlaceholder = new PremiumPlaceholder(this);
@@ -143,6 +166,22 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
dependencyWarnings();
}
private boolean initializeFloodgate() {
if (getServer().getPluginManager().getPlugin("Geyser-Spigot") != null) {
geyserService = new GeyserService(GeyserImpl.getInstance(), core);
}
if (getServer().getPluginManager().getPlugin("floodgate") != null) {
floodgateService = new FloodgateService(FloodgateApi.getInstance(), core);
// Check Floodgate config values and return
return floodgateService.isValidFloodgateConfigString("autoLoginFloodgate")
&& floodgateService.isValidFloodgateConfigString("allowFloodgateNameConflict");
}
return true;
}
@Override
public void onDisable() {
loginSession.clear();
@@ -152,7 +191,10 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
core.close();
}
bungeeManager.cleanup();
if (bungeeManager != null) {
bungeeManager.cleanup();
}
if (premiumPlaceholder != null && getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
try {
premiumPlaceholder.unregister();
@@ -176,22 +218,22 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
return loginSession;
}
public BukkitLoginSession getSession(InetSocketAddress addr) {
String id = getSessionId(addr);
public BukkitLoginSession getSession(InetSocketAddress address) {
String id = getSessionId(address);
return loginSession.get(id);
}
public String getSessionId(InetSocketAddress addr) {
return addr.getAddress().getHostAddress() + ':' + addr.getPort();
public String getSessionId(InetSocketAddress address) {
return address.getAddress().getHostAddress() + ':' + address.getPort();
}
public void putSession(InetSocketAddress addr, BukkitLoginSession session) {
String id = getSessionId(addr);
public void putSession(InetSocketAddress address, BukkitLoginSession session) {
String id = getSessionId(address);
loginSession.put(id, session);
}
public void removeSession(InetSocketAddress addr) {
String id = getSessionId(addr);
public void removeSession(InetSocketAddress address) {
String id = getSessionId(address);
loginSession.remove(id);
}
@@ -202,7 +244,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
/**
* Fetches the premium status of an online player.
*
* @param onlinePlayer
* @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
* us the status message yet (This means you cannot check the login status on the PlayerJoinEvent).
*/
@@ -247,60 +289,45 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
public void sendMessage(CommandSender receiver, String message) {
receiver.sendMessage(message);
}
/**
* Checks if a config entry (related to Floodgate) is valid. <br>
* Writes to Log if the value is invalid.
* <p>
* This should be used for:
* <ul>
* <li>allowFloodgateNameConflict
* <li>autoLoginFloodgate
* <li>autoRegisterFloodgate
* </ul>
* </p>
*
* @param key the key of the entry in config.yml
* @return <b>true</b> if the entry's value is "true", "false", or "linked"
*/
private boolean isValidFloodgateConfigString(String key) {
String value = core.getConfig().get(key).toString().toLowerCase();
if (!value.equals("true") && !value.equals("linked") && !value.equals("false") && !value.equals("no-conflict")) {
logger.error("Invalid value detected for {} in FastLogin/config.yml.", key);
return false;
}
return true;
}
/**
* Checks if a plugin is installed on the server
* @param name the name of the plugin
* @return true if the plugin is installed
*/
@Override
public boolean isPluginInstalled(String name) {
//the plugin may be enabled after FastLogin, so isPluginEnabled()
//won't work here
// the plugin may be enabled after FastLogin, so isPluginEnabled() won't work here
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
}
public FloodgateService getFloodgateService() {
return floodgateService;
}
public GeyserService getGeyserService() {
return geyserService;
}
@Override
public BedrockService<?> getBedrockService() {
if (floodgateService != null) {
return floodgateService;
}
return geyserService;
}
/**
* Send warning messages to log if incompatible plugins are used
* Send warning messages to log if incompatible plugins are used
*/
private void dependencyWarnings() {
if (isPluginInstalled("floodgate-bukkit")) {
logger.warn("We have detected that you are runnging Floodgate 1.0 which is not supported by the Bukkit "
logger.warn("We have detected that you are running Floodgate 1.0 which is not supported by the Bukkit "
+ "version of FastLogin.");
logger.warn("If you would like to use FastLogin with Floodgate, you can download developement builds of "
logger.warn("If you would like to use FastLogin with Floodgate, you can download development builds of "
+ "Floodgate 2.0 from https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/dev%252F2.0/");
logger.warn("Don't forget to update Geyser to a supported version as well from "
+ "https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/floodgate-2.0/");
} else if (isPluginInstalled("floodgate") && isPluginInstalled("ProtocolLib")) {
logger.warn("We have detected that you are runnging FastLogin alongside Floodgate and ProtocolLib.");
logger.warn("Currently there is an issue with FastLogin that prevents Floodgate name prefixes from showing up "
+ "when it is together used with ProtocolLib.");
logger.warn("If you would like to use Floodgate name prefixes, you can replace ProtocolLib with ProtocolSupport "
+ "which does not have this issue.");
logger.warn("For more information visit https://github.com/games647/FastLogin/issues/493");
}
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,6 +28,7 @@ package com.github.games647.fastlogin.bukkit;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
public class PremiumPlaceholder extends PlaceholderExpansion {
@@ -40,7 +41,7 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
}
@Override
public String onRequest(OfflinePlayer player, String identifier) {
public String onRequest(OfflinePlayer player, @NotNull String identifier) {
// player is null if offline
if (player != null && PLACEHOLDER_VARIABLE.equals(identifier)) {
return plugin.getStatus(player.getUniqueId()).getReadableName();
@@ -50,7 +51,7 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
}
@Override
public String getIdentifier() {
public @NotNull String getIdentifier() {
return plugin.getName();
}
@@ -60,12 +61,12 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
}
@Override
public String getAuthor() {
public @NotNull String getAuthor() {
return String.join(", ", plugin.getDescription().getAuthors());
}
@Override
public String getVersion() {
public @NotNull String getVersion() {
return plugin.getDescription().getVersion();
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -31,6 +31,7 @@ import com.github.games647.fastlogin.core.StoredProfile;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import static com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
@@ -41,7 +42,7 @@ public class CrackedCommand extends ToggleCommand {
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
if (args.length == 0) {
onCrackedSelf(sender, command, args);
} else {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,17 +28,18 @@ package com.github.games647.fastlogin.bukkit.command;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPremiumToggleEvent;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
import java.util.UUID;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Let users activate fast login by command. This only be accessible if
* the user has access to it's account. So we can make sure that not another
* the user has access to its account. So we can make sure that not another
* person with a paid account and the same username can steal their account.
*/
public class PremiumCommand extends ToggleCommand {
@@ -48,7 +49,7 @@ public class PremiumCommand extends ToggleCommand {
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
if (args.length == 0) {
onPremiumSelf(sender, command, args);
} else {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -47,12 +47,12 @@ public abstract class ToggleCommand implements CommandExecutor {
}
protected boolean hasOtherPermission(CommandSender sender, Command cmd) {
if (!sender.hasPermission(cmd.getPermission() + ".other")) {
plugin.getCore().sendLocaleMessage("no-permission", sender);
return false;
if (sender.hasPermission(cmd.getPermission() + ".other")) {
return true;
}
return true;
plugin.getCore().sendLocaleMessage("no-permission", sender);
return false;
}
protected boolean forwardBungeeCommand(CommandSender sender, String target, boolean activate) {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -31,6 +31,7 @@ import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class BukkitFastLoginAutoLoginEvent extends Event implements FastLoginAutoLoginEvent, Cancellable {
@@ -67,7 +68,7 @@ public class BukkitFastLoginAutoLoginEvent extends Event implements FastLoginAut
}
@Override
public HandlerList getHandlers() {
public @NotNull HandlerList getHandlers() {
return handlers;
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,6 +30,7 @@ import com.github.games647.fastlogin.core.shared.LoginSource;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class BukkitFastLoginPreLoginEvent extends Event implements FastLoginPreLoginEvent {
@@ -62,7 +63,7 @@ public class BukkitFastLoginPreLoginEvent extends Event implements FastLoginPreL
}
@Override
public HandlerList getHandlers() {
public @NotNull HandlerList getHandlers() {
return handlers;
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,6 +29,7 @@ import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class BukkitFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
@@ -53,7 +54,7 @@ public class BukkitFastLoginPremiumToggleEvent extends Event implements FastLogi
}
@Override
public HandlerList getHandlers() {
public @NotNull HandlerList getHandlers() {
return handlers;
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -121,11 +121,11 @@ public class CrazyLoginHook implements AuthPlugin<Player> {
public boolean forceRegister(Player player, String password) {
CrazyLoginDataDatabase crazyDatabase = crazyLoginPlugin.getCrazyDatabase();
//this executes a sql query and accesses only thread safe collections so we can run it async
//this executes a sql query and accesses only thread safe collections, so we can run it async
LoginPlayerData playerData = crazyLoginPlugin.getPlayerData(player.getName());
if (playerData == null) {
//create a fake account - this will be saved to the database with the password=FAILEDLOADING
//user cannot login with that password unless the admin uses plain text
//user cannot log in with that password unless the admin uses plain text
//this automatically marks the player as logged in
crazyDatabase.save(new LoginPlayerData(player));
return forceLogin(player);

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,78 +0,0 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import org.bukkit.entity.Player;
import red.mohist.sodionauth.bukkit.implementation.BukkitPlayer;
import red.mohist.sodionauth.core.SodionAuthApi;
import red.mohist.sodionauth.core.exception.AuthenticatedException;
/**
* GitHub: https://github.com/Mohist-Community/SodionAuth
* <p>
* Project page: https://gitea.e-loli.com/SodionAuth/SodionAuth
* <p>
* Bukkit: Unknown
* <p>
* Spigot: https://www.spigotmc.org/resources/sodionauth.76944/
*/
public class SodionAuthHook implements AuthPlugin<Player> {
private final FastLoginBukkit plugin;
public SodionAuthHook(FastLoginBukkit plugin) {
this.plugin = plugin;
}
@Override
public boolean forceLogin(Player player) {
try {
SodionAuthApi.login(new BukkitPlayer(player));
} catch (AuthenticatedException e) {
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
return false;
}
return true;
}
@Override
public boolean forceRegister(Player player, String password) {
try{
return SodionAuthApi.register(new BukkitPlayer(player), password);
} catch (UnsupportedOperationException e){
plugin.getLog().warn("Currently SodionAuth is not accepting forceRegister, " +
"It may be caused by unsupported AuthBackend");
return false;
}
}
@Override
public boolean isRegistered(String playerName) {
return SodionAuthApi.isRegistered(playerName);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -41,6 +41,7 @@ import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
import org.jetbrains.annotations.NotNull;
/**
* Responsible for receiving messages from a BungeeCord instance.
@@ -57,7 +58,7 @@ public class BungeeListener implements PluginMessageListener {
}
@Override
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
public void onPluginMessageReceived(@NotNull String channel, Player player, byte[] message) {
ByteArrayDataInput dataInput = ByteStreams.newDataInput(message);
LoginActionMessage loginMessage = new LoginActionMessage();
@@ -67,7 +68,7 @@ public class BungeeListener implements PluginMessageListener {
Player targetPlayer = player;
if (!loginMessage.getPlayerName().equals(player.getName())) {
targetPlayer = Bukkit.getPlayerExact(loginMessage.getPlayerName());;
targetPlayer = Bukkit.getPlayerExact(loginMessage.getPlayerName());
}
if (targetPlayer == null) {
@@ -128,7 +129,7 @@ public class BungeeListener implements PluginMessageListener {
session.setVerified(true);
plugin.putSession(player.getAddress(), session);
// only start a new login task if the join event fired earlier. This event then didn
// only start a new login task if the join event fired earlier. This event then didn't
boolean result = plugin.getBungeeManager().didJoinEventFired(player);
plugin.getLog().info("Delaying force login until join event fired?: {}", result);
if (result) {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,6 +29,7 @@ import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.task.FloodgateAuthTask;
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -38,12 +39,12 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.metadata.Metadatable;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
/**
* This listener tells authentication plugins if the player has a premium account and we checked it successfully. So the
* This listener tells authentication plugins weather the player has a premium account. So the
* plugin can skip authentication.
*/
public class ConnectionListener implements Listener {
@@ -69,37 +70,43 @@ public class ConnectionListener implements Listener {
Player player = joinEvent.getPlayer();
Bukkit.getScheduler().runTaskLater(plugin, () -> {
// session exists so the player is ready for force login
// cases: Paper (firing BungeeCord message before PlayerJoinEvent) or not running BungeeCord and already
// having the login session from the login process
BukkitLoginSession session = plugin.getSession(player.getAddress());
boolean isFloodgateLogin = false;
if (Bukkit.getServer().getPluginManager().isPluginEnabled("floodgate")) {
FloodgatePlayer floodgatePlayer = FloodgateApi.getInstance().getPlayer(player.getUniqueId());
if (floodgatePlayer != null) {
isFloodgateLogin = true;
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin, player, floodgatePlayer);
Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask);
}
}
if (!isFloodgateLogin) {
if (session == null) {
String sessionId = plugin.getSessionId(player.getAddress());
plugin.getLog().info("No on-going login session for player: {} with ID {}", player, sessionId);
} else {
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
}
}
plugin.getBungeeManager().markJoinEventFired(player);
delayForceLogin(player);
// delay the login process to let auth plugins initialize the player
// Magic number however as there is no direct event from those plugins
}, DELAY_LOGIN);
}
private void delayForceLogin(Player player) {
// session exists so the player is ready for force login
// cases: Paper (firing BungeeCord message before PlayerJoinEvent) or not running BungeeCord and already
// having the login session from the login process
BukkitLoginSession session = plugin.getSession(player.getAddress());
if (session == null) {
// Floodgate players usually don't have a session at this point
// exception: if force login by bungee message had been delayed
FloodgateService floodgateService = plugin.getFloodgateService();
if (floodgateService != null) {
FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(player.getUniqueId());
if (floodgatePlayer != null) {
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer);
Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask);
return;
}
}
String sessionId = plugin.getSessionId(player.getAddress());
plugin.getLog().info("No on-going login session for player: {} with ID {}. ", player, sessionId);
plugin.getLog().info("Setups using Minecraft proxies will start delayed " +
"when the command from the proxy is received");
} else {
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
}
plugin.getBungeeManager().markJoinEventFired(player);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
Player player = quitEvent.getPlayer();
@@ -110,7 +117,7 @@ public class ConnectionListener implements Listener {
plugin.getBungeeManager().cleanup(player);
}
private void removeBlockedStatus(Player player) {
private void removeBlockedStatus(Metadatable player) {
player.removeMetadata(plugin.getName(), plugin);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -35,17 +35,17 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
public class PaperPreLoginListener implements Listener {
public class PaperCacheListener implements Listener {
private final FastLoginBukkit plugin;
public PaperPreLoginListener(final FastLoginBukkit plugin) {
public PaperCacheListener(final FastLoginBukkit plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.HIGHEST)
//if paper is used - player skin must be set at pre login, otherwise usercache is used
//using usercache makes premium name change basically impossible
//if paper is used - player skin must be set at pre login, otherwise user cache is used
// user cache makes premium name change basically impossible
public void onAsyncPlayerPreLogin(AsyncPlayerPreLoginEvent event) {
if (event.getLoginResult() != Result.ALLOWED) {
return;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -35,6 +35,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
@@ -55,7 +56,7 @@ public class EncryptionUtil {
}
/**
* Generate a RSA key pair
* Generate an RSA key pair
*
* @return The RSA key pair.
*/

View File

@@ -0,0 +1,85 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import org.geysermc.floodgate.api.FloodgateApi;
import static com.comphenix.protocol.PacketType.Login.Client.START;
import com.comphenix.protocol.ProtocolLibrary;
/**
* Manually inject Floodgate player name prefixes.
* <br>
* This is used as a workaround, because Floodgate fails to inject
* the prefixes when it's used together with ProtocolLib and FastLogin.
* <br>
* For more information visit: https://github.com/games647/FastLogin/issues/493
*/
public class ManualNameChange extends PacketAdapter {
private final FloodgateService floodgate;
public ManualNameChange(FastLoginBukkit plugin, FloodgateService floodgate) {
super(params()
.plugin(plugin)
.types(START));
this.plugin = plugin;
this.floodgate = floodgate;
}
public static void register(FastLoginBukkit plugin, FloodgateService floodgate) {
// they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
ProtocolLibrary.getProtocolManager()
.getAsynchronousManager()
.registerAsyncHandler(new ManualNameChange(plugin, floodgate))
.start();
}
@Override
public void onPacketReceiving(PacketEvent packetEvent) {
PacketContainer packet = packetEvent.getPacket();
WrappedGameProfile originalProfile = packet.getGameProfiles().read(0);
if (floodgate.getBedrockPlayer(originalProfile.getName()) == null) {
//not a Floodgate player, no need to add a prefix
return;
}
packet.setMeta("original_name", originalProfile.getName());
String prefixedName = FloodgateApi.getInstance().getPlayerPrefix() + originalProfile.getName();
WrappedGameProfile updatedProfile = originalProfile.withName(prefixedName);
packet.getGameProfiles().write(0, updatedProfile);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -52,10 +52,9 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
private final Player player;
private final String username;
public NameCheckTask(FastLoginBukkit plugin, PacketEvent packetEvent, Random random,
Player player, String username, PublicKey publicKey) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
public NameCheckTask(FastLoginBukkit plugin, Random random, Player player, PacketEvent packetEvent,
String username, PublicKey publicKey) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
this.plugin = plugin;
this.packetEvent = packetEvent;
@@ -68,14 +67,15 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
@Override
public void run() {
try {
super.onLogin(username, new ProtocolLibLoginSource(packetEvent, player, random, publicKey));
super.onLogin(username, new ProtocolLibLoginSource(player, random, publicKey));
} finally {
ProtocolLibrary.getProtocolManager().getAsynchronousManager().signalPacketTransmission(packetEvent);
}
}
@Override
public FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, ProtocolLibLoginSource source, StoredProfile profile) {
public FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, ProtocolLibLoginSource source,
StoredProfile profile) {
BukkitFastLoginPreLoginEvent event = new BukkitFastLoginPreLoginEvent(username, source, profile);
plugin.getServer().getPluginManager().callEvent(event);
return event;
@@ -87,7 +87,7 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
public void requestPremiumLogin(ProtocolLibLoginSource source, StoredProfile profile
, String username, boolean registered) {
try {
source.setOnlineMode();
source.enableOnlinemode();
} catch (Exception ex) {
plugin.getLog().error("Cannot send encryption packet. Falling back to cracked login for: {}", profile, ex);
return;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -43,6 +43,8 @@ import static com.comphenix.protocol.PacketType.Login.Client.START;
public class ProtocolLibListener extends PacketAdapter {
public static final String SOURCE_META_KEY = "source";
private final FastLoginBukkit plugin;
//just create a new once on plugin enable. This used for verify token generation
@@ -62,7 +64,8 @@ public class ProtocolLibListener extends PacketAdapter {
}
public static void register(FastLoginBukkit plugin, RateLimiter rateLimiter) {
//they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
// they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
// TODO: make synchronous processing, but do web or database requests async
ProtocolLibrary.getProtocolManager()
.getAsynchronousManager()
.registerAsyncHandler(new ProtocolLibListener(plugin, rateLimiter))
@@ -72,16 +75,21 @@ public class ProtocolLibListener extends PacketAdapter {
@Override
public void onPacketReceiving(PacketEvent packetEvent) {
if (packetEvent.isCancelled()
|| plugin.getCore().getAuthPluginHook()== null
|| plugin.getCore().getAuthPluginHook() == null
|| !plugin.isServerFullyStarted()) {
return;
}
if (isFastLoginPacket(packetEvent)) {
// this is our own packet
return;
}
Player sender = packetEvent.getPlayer();
PacketType packetType = packetEvent.getPacketType();
if (packetType == START) {
if (!rateLimiter.tryAcquire()) {
plugin.getLog().warn("Join limit hit - Ignoring player {}", sender);
plugin.getLog().warn("Simple Anti-Bot join limit - Ignoring {}", sender);
return;
}
@@ -91,6 +99,12 @@ public class ProtocolLibListener extends PacketAdapter {
}
}
private Boolean isFastLoginPacket(PacketEvent packetEvent) {
return packetEvent.getPacket().getMeta(SOURCE_META_KEY)
.map(val -> val.equals(plugin.getName()))
.orElse(false);
}
private void onEncryptionBegin(PacketEvent packetEvent, Player sender) {
byte[] sharedSecret = packetEvent.getPacket().getByteArrays().read(0);
@@ -110,10 +124,16 @@ public class ProtocolLibListener extends PacketAdapter {
PacketContainer packet = packetEvent.getPacket();
String username = packet.getGameProfiles().read(0).getName();
if (packetEvent.getPacket().getMeta("original_name").isPresent()) {
//username has been injected by ManualNameChange.java
username = (String) packetEvent.getPacket().getMeta("original_name").get();
}
plugin.getLog().trace("GameProfile {} with {} connecting", sessionKey, username);
packetEvent.getAsyncMarker().incrementProcessingDelay();
Runnable nameCheckTask = new NameCheckTask(plugin, packetEvent, random, player, username, keyPair.getPublic());
Runnable nameCheckTask = new NameCheckTask(plugin, random, player, packetEvent, username, keyPair.getPublic());
plugin.getScheduler().runAsync(nameCheckTask);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,7 +28,6 @@ package com.github.games647.fastlogin.bukkit.listener.protocollib;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.github.games647.fastlogin.core.shared.LoginSource;
@@ -46,7 +45,6 @@ import static com.comphenix.protocol.PacketType.Login.Server.ENCRYPTION_BEGIN;
class ProtocolLibLoginSource implements LoginSource {
private final PacketEvent packetEvent;
private final Player player;
private final Random random;
@@ -55,15 +53,14 @@ class ProtocolLibLoginSource implements LoginSource {
private final String serverId = "";
private byte[] verifyToken;
public ProtocolLibLoginSource(PacketEvent packetEvent, Player player, Random random, PublicKey publicKey) {
this.packetEvent = packetEvent;
public ProtocolLibLoginSource(Player player, Random random, PublicKey publicKey) {
this.player = player;
this.random = random;
this.publicKey = publicKey;
}
@Override
public void setOnlineMode() throws Exception {
public void enableOnlinemode() throws InvocationTargetException {
verifyToken = EncryptionUtil.generateVerifyToken(random);
/*
@@ -86,7 +83,7 @@ class ProtocolLibLoginSource implements LoginSource {
newPacket.getByteArrays().write(verifyField, verifyToken);
//serverId is a empty string
//serverId is an empty string
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket);
}
@@ -109,7 +106,7 @@ class ProtocolLibLoginSource implements LoginSource {
@Override
public InetSocketAddress getAddress() {
return packetEvent.getPlayer().getAddress();
return player.getAddress();
}
public String getServerId() {
@@ -123,8 +120,7 @@ class ProtocolLibLoginSource implements LoginSource {
@Override
public String toString() {
return this.getClass().getSimpleName() + '{' +
"packetEvent=" + packetEvent +
", player=" + player +
"player=" + player +
", random=" + random +
", serverId='" + serverId + '\'' +
", verifyToken=" + Arrays.toString(verifyToken) +

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -36,15 +36,18 @@ import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.github.games647.craftapi.model.auth.Verification;
import com.github.games647.craftapi.model.skin.SkinProperty;
import com.github.games647.craftapi.resolver.AbstractResolver;
import com.github.games647.craftapi.resolver.MojangResolver;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyPair;
@@ -95,13 +98,14 @@ public class VerifyResponseTask implements Runnable {
try {
BukkitLoginSession session = plugin.getSession(player.getAddress());
if (session == null) {
disconnect("invalid-request", true
, "GameProfile {0} tried to send encryption response at invalid state", player.getAddress());
disconnect("invalid-request",
"GameProfile {0} tried to send encryption response at invalid state",
player.getAddress());
} else {
verifyResponse(session);
}
} finally {
//this is a fake packet; it shouldn't be send to the server
//this is a fake packet; it shouldn't be sent to the server
synchronized (packetEvent.getAsyncMarker().getProcessingLock()) {
packetEvent.setCancelled(true);
}
@@ -117,7 +121,7 @@ public class VerifyResponseTask implements Runnable {
try {
loginKey = EncryptionUtil.decryptSharedKey(privateKey, sharedSecret);
} catch (GeneralSecurityException securityEx) {
disconnect("error-kick", false, "Cannot decrypt received contents", securityEx);
disconnect("error-kick", "Cannot decrypt received contents", securityEx);
return;
}
@@ -126,7 +130,7 @@ public class VerifyResponseTask implements Runnable {
return;
}
} catch (Exception ex) {
disconnect("error-kick", false, "Cannot decrypt received contents", ex);
disconnect("error-kick", "Cannot decrypt received contents", ex);
return;
}
@@ -140,10 +144,10 @@ public class VerifyResponseTask implements Runnable {
Optional<Verification> response = resolver.hasJoined(requestedUsername, serverId, address);
if (response.isPresent()) {
Verification verification = response.get();
plugin.getLog().info("Profile {} has a verified premium account: {}", requestedUsername, verification);
plugin.getLog().info("Profile {} has a verified premium account", requestedUsername);
String realUsername = verification.getName();
if (realUsername == null) {
disconnect("invalid-session", true, "Username field null for {}", requestedUsername);
disconnect("invalid-session", "Username field null for {}", requestedUsername);
return;
}
@@ -159,13 +163,11 @@ public class VerifyResponseTask implements Runnable {
setPremiumUUID(session.getUuid());
receiveFakeStartPacket(realUsername);
} else {
//user tried to fake a authentication
disconnect("invalid-session", true
, "GameProfile {0} ({1}) tried to log in with an invalid session ServerId: {2}"
, session.getRequestUsername(), socketAddress, serverId);
//user tried to fake an authentication
disconnect("invalid-session", "GameProfile {} ({}) tried to log in with an invalid session. ServerId: {}", session.getRequestUsername(), socketAddress, serverId);
}
} catch (IOException ioEx) {
disconnect("error-kick", false, "Failed to connect to session server", ioEx);
disconnect("error-kick", "Failed to connect to session server", ioEx);
}
}
@@ -188,10 +190,10 @@ public class VerifyResponseTask implements Runnable {
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L182
if (!Arrays.equals(requestVerify, EncryptionUtil.decrypt(serverKey.getPrivate(), responseVerify))) {
//check if the verify token are equal to the server sent one
disconnect("invalid-verify-token", true
, "GameProfile {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}"
, session.getRequestUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
//check if the verify-token are equal to the server sent one
disconnect("invalid-verify-token",
"GameProfile {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}",
session.getRequestUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
return false;
}
@@ -202,13 +204,14 @@ public class VerifyResponseTask implements Runnable {
private Object getNetworkManager() throws IllegalAccessException, ClassNotFoundException {
Object injectorContainer = TemporaryPlayerFactory.getInjectorFromPlayer(player);
//ChannelInjector
// ChannelInjector
Class<?> injectorClass = Class.forName("com.comphenix.protocol.injector.netty.Injector");
Object rawInjector = FuzzyReflection.getFieldValue(injectorContainer, injectorClass, true);
return FieldUtils.readField(rawInjector, "networkManager", true);
}
private boolean enableEncryption(SecretKey loginKey) throws IllegalArgumentException {
plugin.getLog().info("Enabling onlinemode encryption for {}", player.getName());
// Initialize method reflections
if (encryptMethod == null) {
Class<?> networkManagerClass = MinecraftReflection.getNetworkManagerClass();
@@ -216,15 +219,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);
}
}
@@ -244,20 +247,15 @@ public class VerifyResponseTask implements Runnable {
encryptMethod.invoke(networkManager, decryptionCipher, encryptionCipher);
}
} catch (Exception ex) {
disconnect("error-kick", false, "Couldn't enable encryption", ex);
disconnect("error-kick", "Couldn't enable encryption", ex);
return false;
}
return true;
}
private void disconnect(String reasonKey, boolean debug, String logMessage, Object... arguments) {
if (debug) {
plugin.getLog().debug(logMessage, arguments);
} else {
plugin.getLog().error(logMessage, arguments);
}
private void disconnect(String reasonKey, String logMessage, Object... arguments) {
plugin.getLog().error(logMessage, arguments);
kickPlayer(plugin.getCore().getMessage(reasonKey));
}
@@ -285,7 +283,8 @@ public class VerifyResponseTask implements Runnable {
startPacket.getGameProfiles().write(0, fakeProfile);
try {
//we don't want to handle our own packets so ignore filters
ProtocolLibrary.getProtocolManager().recieveClientPacket(player, startPacket, false);
startPacket.setMeta(ProtocolLibListener.SOURCE_META_KEY, plugin.getName());
ProtocolLibrary.getProtocolManager().recieveClientPacket(player, startPacket, true);
} catch (InvocationTargetException | IllegalAccessException ex) {
plugin.getLog().warn("Failed to fake a new start packet for: {}", username, ex);
//cancel the event in order to prevent the server receiving an invalid packet

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -40,7 +40,7 @@ public class ProtocolLoginSource implements LoginSource {
}
@Override
public void setOnlineMode() {
public void enableOnlinemode() {
loginStartEvent.setOnlineMode(true);
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -41,7 +41,6 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import protocolsupport.api.events.ConnectionCloseEvent;
import protocolsupport.api.events.PlayerLoginStartEvent;
import protocolsupport.api.events.PlayerProfileCompleteEvent;
@@ -53,7 +52,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
private final RateLimiter rateLimiter;
public ProtocolSupportListener(FastLoginBukkit plugin, RateLimiter rateLimiter) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
this.plugin = plugin;
this.rateLimiter = rateLimiter;
@@ -66,7 +65,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
}
if (!rateLimiter.tryAcquire()) {
plugin.getLog().warn("Join limit hit - Ignoring player {}", loginStartEvent.getConnection());
plugin.getLog().warn("Simple Anti-Bot join limit - Ignoring {}", loginStartEvent.getConnection());
return;
}
@@ -112,7 +111,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
@Override
public void requestPremiumLogin(ProtocolLoginSource source, StoredProfile profile, String username
, boolean registered) {
source.setOnlineMode();
source.enableOnlinemode();
String ip = source.getAddress().getAddress().getHostAddress();
plugin.getCore().getPendingLogin().put(ip + username, new Object());

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,7 +32,6 @@ import com.github.games647.fastlogin.bukkit.hook.LogItHook;
import com.github.games647.fastlogin.bukkit.hook.LoginSecurityHook;
import com.github.games647.fastlogin.bukkit.hook.UltraAuthHook;
import com.github.games647.fastlogin.bukkit.hook.xAuthHook;
import com.github.games647.fastlogin.bukkit.hook.SodionAuthHook;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import java.lang.reflect.Constructor;
@@ -95,8 +94,8 @@ public class DelayedAuthHook implements Runnable {
private AuthPlugin<Player> getAuthHook() {
try {
List<Class<? extends AuthPlugin<Player>>> hooks = Arrays.asList(AuthMeHook.class,
CrazyLoginHook.class, LogItHook.class, LoginSecurityHook.class,
SodionAuthHook.class, UltraAuthHook.class, xAuthHook.class);
CrazyLoginHook.class, LogItHook.class, LoginSecurityHook.class, UltraAuthHook.class,
xAuthHook.class);
for (Class<? extends AuthPlugin<Player>> clazz : hooks) {
String pluginName = clazz.getSimpleName();

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,103 +25,47 @@
*/
package com.github.games647.fastlogin.bukkit.task;
import java.io.IOException;
import java.util.Optional;
import java.net.InetSocketAddress;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.FloodgateManagement;
public class FloodgateAuthTask implements Runnable {
public class FloodgateAuthTask extends FloodgateManagement<Player, CommandSender, BukkitLoginSession, FastLoginBukkit> {
private final FastLoginBukkit plugin;
private final Player player;
private final FloodgatePlayer floodgatePlayer;
public FloodgateAuthTask(FastLoginBukkit plugin, Player player, FloodgatePlayer floodgatePlayer) {
this.plugin = plugin;
this.player = player;
this.floodgatePlayer = floodgatePlayer;
public FloodgateAuthTask(FastLoginCore<Player, CommandSender, FastLoginBukkit> core, Player player, FloodgatePlayer floodgatePlayer) {
super(core, player, floodgatePlayer);
}
@Override
public void run() {
plugin.getLog().info(
"Player {} is connecting through Geyser Floodgate.",
player.getName());
// check if the Bedrock player is linked to a Java account
boolean isLinked = floodgatePlayer.getLinkedPlayer() != null;
AuthPlugin<Player> authPlugin = plugin.getCore().getAuthPluginHook();
String autoLoginFloodgate = plugin.getCore().getConfig().get("autoLoginFloodgate").toString().toLowerCase();
String autoRegisterFloodgate = plugin.getCore().getConfig().get("autoRegisterFloodgate").toString().toLowerCase();
String allowNameConflict = plugin.getCore().getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
boolean isRegistered;
try {
isRegistered = authPlugin.isRegistered(player.getName());
} catch (Exception e) {
plugin.getLog().error(
"An error has occured while checking if player {} is registered",
player.getName());
return;
}
//decide if checks should be made for conflicting Java player names
if (!isLinked //linked players have the same name as their Java profile
// if allowNameConflict is 'false' or 'linked' and the player had a conflicting
// name, than they would have been kicked in FloodgateHook#checkNameConflict
&& allowNameConflict.equals("true") &&
(
autoLoginFloodgate.equals("no-conflict")
|| !isRegistered && autoRegisterFloodgate.equals("no-conflict"))
) {
// check for conflicting Premium Java name
Optional<Profile> premiumUUID = Optional.empty();
try {
premiumUUID = plugin.getCore().getResolver().findProfile(player.getName());
} catch (IOException | RateLimitException e) {
plugin.getLog().error(
"Could not check wether Floodgate Player {}'s name conflits a premium Java player's name.",
player.getName());
return;
}
//stop execution if player's name is conflicting
if (premiumUUID.isPresent()) {
return;
}
}
if (!isRegistered && autoRegisterFloodgate.equals("false")) {
plugin.getLog().info(
"Auto registration is disabled for Floodgate players in config.yml");
return;
}
// logging in from bedrock for a second time threw an error with UUID
StoredProfile profile = plugin.getCore().getStorage().loadProfile(player.getName());
if (profile == null) {
profile = new StoredProfile(player.getUniqueId(), player.getName(), true, player.getAddress().toString());
}
protected void startLogin() {
BukkitLoginSession session = new BukkitLoginSession(player.getName(), isRegistered, profile);
// enable auto login based on the value of 'autoLoginFloodgate' in config.yml
session.setVerified(autoLoginFloodgate.equals("true")
|| (autoLoginFloodgate.equals("linked") && isLinked));
session.setVerified(isAutoAuthAllowed(autoLoginFloodgate));
// run login task
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, session);
Bukkit.getScheduler().runTaskAsynchronously(core.getPlugin(), forceLoginTask);
}
protected String getName(Player player) {
return player.getName();
}
protected UUID getUUID(Player player) {
return player.getUniqueId();
}
protected InetSocketAddress getAddress(Player player) {
return player.getAddress();
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,4 +1,4 @@
# project data for Bukkit in order to register our plugin with all it components
# project data for Bukkit in order to register our plugin with all it's components
# ${-} are variables from Maven (pom.xml) which will be replaced after the build
name: ${project.parent.name}
version: ${project.version}-${git.commit.id.abbrev}
@@ -11,15 +11,17 @@ description: |
website: ${project.url}
dev-url: ${project.url}
# This plugin don't have to be transformed for compatibility with Minecraft >= 1.13
# This plugin doesn't have to be transformed for compatibility with Minecraft >= 1.13
api-version: '1.13'
softdepend:
# We depend either ProtocolLib or ProtocolSupport
# We depend on either ProtocolLib or ProtocolSupport
- ProtocolSupport
- ProtocolLib
# Premium variable
- PlaceholderAPI
# Bedrock Player Bridge
- Geyser-Spigot
- floodgate
# Auth plugins
- AuthMe

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -36,31 +36,11 @@ import static org.hamcrest.MatcherAssert.assertThat;
public class EncryptionUtilTest {
@Test
public void testVerifyToken() throws Exception {
public void testVerifyToken() {
SecureRandom random = new SecureRandom();
byte[] token = EncryptionUtil.generateVerifyToken(random);
assertThat(token, notNullValue());
assertThat(token.length, is(4));
}
// @Test
// public void testDecryptSharedSecret() throws Exception {
//
// }
//
// @Test
// public void testDecryptData() throws Exception {
//
// }
// private static SecretKey createNewSharedKey() {
// try {
// KeyGenerator keygenerator = KeyGenerator.getInstance("AES");
// keygenerator.init(128);
// return keygenerator.generateKey();
// } catch (NoSuchAlgorithmException nosuchalgorithmexception) {
// throw new Error(nosuchalgorithmexception);
// }
// }
}

View File

@@ -4,7 +4,7 @@
The MIT License (MIT)
Copyright (c) 2015-2021 <Your name and contributors>
Copyright (c) 2015-2022 games647 and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -36,7 +36,7 @@
<relativePath>../pom.xml</relativePath>
</parent>
<!--This have to be in lowercase because it's used by plugin.yml-->
<!--This has to be in lowercase because it's used by plugin.yml-->
<artifactId>fastlogin.bungee</artifactId>
<packaging>jar</packaging>
@@ -48,7 +48,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<version>3.3.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>false</shadedArtifactAttached>
@@ -57,6 +57,7 @@
<!--Those classes are already present in BungeeCord version-->
<exclude>net.md-5:bungeecord-config</exclude>
<exclude>com.google.code.gson:gson</exclude>
<exclude>com.google.guava:guava</exclude>
</excludes>
</artifactSet>
<relocations>
@@ -69,6 +70,20 @@
<shadedPattern>fastlogin.slf4j</shadedPattern>
</relocation>
</relocations>
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
<!-- Located in META-INF/services -->
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/MANIFEST.MF</exclude>
<exclude>**/module-info.class</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
@@ -88,11 +103,6 @@
<url>https://repo.codemc.io/repository/maven-public/</url>
</repository>
<repository>
<id>nukkitx-repo</id>
<url>https://repo.nukkitx.com/maven-snapshots/</url>
</repository>
<repository>
<id>spigotplugins-repo</id>
<url>https://maven.gamestrike.de/mvn/</url>
@@ -119,25 +129,54 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>1.16-R0.5-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<!-- Use our own newer api version -->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Bedrock player bridge -->
<!-- Should be removed one Floodgate 2.0 gets a stable release -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>floodgate-bungee</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Bedrock player bridge -->
<!-- Version 2.0 -->
<!--Floodgate for Xbox Live Authentication-->
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>2.0-SNAPSHOT</version>
<version>${floodgate.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.geysermc.cumulus</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Bedrock player bridge -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>core</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- We need the API, but it was excluded above -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>geyser-api</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
</dependency>
@@ -155,20 +194,12 @@
<artifactId>BungeeCordAuthenticator</artifactId>
<version>0.0.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
<artifactId>SodionAuth-Bungee</artifactId>
<version>2bdfdc854b</version>
<exclusions>
<exclusion>
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
<artifactId>SodionAuth-Libs</artifactId>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
<optional>true</optional>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -46,7 +46,7 @@ public class BungeeLoginSource implements LoginSource {
}
@Override
public void setOnlineMode() {
public void enableOnlinemode() {
connection.setOnlineMode(true);
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -27,12 +27,14 @@ package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.bungee.hook.BungeeAuthHook;
import com.github.games647.fastlogin.bungee.hook.BungeeCordAuthenticatorBungeeHook;
import com.github.games647.fastlogin.bungee.hook.SodionAuthHook;
import com.github.games647.fastlogin.bungee.listener.ConnectListener;
import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
import com.github.games647.fastlogin.core.AsyncScheduler;
import com.github.games647.fastlogin.core.CommonUtil;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
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.NamespaceKey;
@@ -59,6 +61,8 @@ import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager;
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.geyser.GeyserImpl;
import org.slf4j.Logger;
/**
@@ -70,12 +74,14 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
private FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core;
private AsyncScheduler scheduler;
private FloodgateService floodgateService;
private GeyserService geyserService;
private Logger logger;
@Override
public void onEnable() {
logger = CommonUtil.createLoggerFromJDK(getLogger());
scheduler = new AsyncScheduler(logger, getThreadFactory());
logger = CommonUtil.initializeLoggerService(getLogger());
scheduler = new AsyncScheduler(logger, task -> getProxy().getScheduler().runAsync(this, task));
core = new FastLoginCore<>(this);
core.load();
@@ -83,18 +89,18 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
return;
}
if (isPluginInstalled("floodgate")) {
floodgateService = new FloodgateService(FloodgateApi.getInstance(), core);
}
if (isPluginInstalled("Geyser-BungeeCord")) {
geyserService = new GeyserService(GeyserImpl.getInstance(), core);
}
//events
PluginManager pluginManager = getProxy().getPluginManager();
//check Floodgate version
String floodgateVersion = "0";
Plugin floodgatePlugin = pluginManager.getPlugin("floodgate");
if (floodgatePlugin != null) {
floodgateVersion = floodgatePlugin.getDescription().getVersion();
}
ConnectListener connectListener = new ConnectListener(this, core.getRateLimiter(), floodgateVersion);
ConnectListener connectListener = new ConnectListener(this, core.getRateLimiter());
pluginManager.registerListener(this, connectListener);
pluginManager.registerListener(this, new PluginMessageListener(this));
@@ -123,7 +129,7 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
private void registerHook() {
try {
List<Class<? extends AuthPlugin<ProxiedPlayer>>> hooks = Arrays.asList(
BungeeAuthHook.class, BungeeCordAuthenticatorBungeeHook.class, SodionAuthHook.class);
BungeeAuthHook.class, BungeeCordAuthenticatorBungeeHook.class);
for (Class<? extends AuthPlugin<ProxiedPlayer>> clazz : hooks) {
String pluginName = clazz.getSimpleName();
@@ -192,4 +198,20 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
public boolean isPluginInstalled(String name) {
return getProxy().getPluginManager().getPlugin(name) != null;
}
public FloodgateService getFloodgateService() {
return floodgateService;
}
public GeyserService getGeyserService() {
return geyserService;
}
@Override
public BedrockService<?> getBedrockService() {
if (floodgateService != null) {
return floodgateService;
}
return geyserService;
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -27,6 +27,7 @@ package com.github.games647.fastlogin.bungee.event;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
import net.md_5.bungee.api.plugin.Event;
public class BungeeFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
@@ -45,7 +46,7 @@ public class BungeeFastLoginPremiumToggleEvent extends Event implements FastLogi
}
@Override
public FastLoginPremiumToggleEvent.PremiumToggleReason getReason() {
public PremiumToggleReason getReason() {
return reason;
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,22 +25,23 @@
*/
package com.github.games647.fastlogin.bungee.hook;
import java.sql.SQLException;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import de.xxschrandxx.bca.bungee.BungeeCordAuthenticatorBungee;
import de.xxschrandxx.bca.bungee.api.BungeeCordAuthenticatorBungeeAPI;
import java.sql.SQLException;
import java.util.logging.Level;
import net.md_5.bungee.api.connection.ProxiedPlayer;
/**
* GitHub:
* https://github.com/xXSchrandXx/SpigotPlugins/tree/master/BungeeCordAuthenticator
*
* <p>
* Project page:
*
* <p>
* Spigot: https://www.spigotmc.org/resources/bungeecordauthenticator.87669/
*/
public class BungeeCordAuthenticatorBungeeHook implements AuthPlugin<ProxiedPlayer> {
@@ -49,7 +50,7 @@ public class BungeeCordAuthenticatorBungeeHook implements AuthPlugin<ProxiedPlay
public BungeeCordAuthenticatorBungeeHook(FastLoginBungee plugin) {
api = ((BungeeCordAuthenticatorBungee) plugin.getProxy().getPluginManager()
.getPlugin("BungeeCordAuthenticatorBungee")).getAPI();
.getPlugin("BungeeCordAuthenticatorBungee")).getAPI();
plugin.getLog().info("BungeeCordAuthenticatorHook | Hooked successful!");
}
@@ -57,25 +58,24 @@ public class BungeeCordAuthenticatorBungeeHook implements AuthPlugin<ProxiedPlay
public boolean forceLogin(ProxiedPlayer player) {
if (api.isAuthenticated(player)) {
return true;
} else {
try {
api.setAuthenticated(player);
}
catch (SQLException e) {
e.printStackTrace();
return false;
}
return true;
}
try {
api.setAuthenticated(player);
} catch (SQLException sqlEx) {
api.getLogger().log(Level.WARNING, "Failed to force login", sqlEx);
return false;
}
return true;
}
@Override
public boolean isRegistered(String playerName) {
try {
return api.getSQL().checkPlayerEntry(playerName);
}
catch (SQLException e) {
e.printStackTrace();
} catch (SQLException sqlEx) {
api.getLogger().log(Level.WARNING, "Failed to check registration", sqlEx);
return false;
}
}
@@ -84,9 +84,8 @@ public class BungeeCordAuthenticatorBungeeHook implements AuthPlugin<ProxiedPlay
public boolean forceRegister(ProxiedPlayer player, String password) {
try {
return api.createPlayerEntry(player, password);
}
catch (SQLException e) {
e.printStackTrace();
} catch (SQLException sqlEx) {
api.getLogger().log(Level.WARNING, "Failed to force register", sqlEx);
return false;
}
}

View File

@@ -1,78 +0,0 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.hook;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import red.mohist.sodionauth.bungee.implementation.BungeePlayer;
import red.mohist.sodionauth.core.SodionAuthApi;
import red.mohist.sodionauth.core.exception.AuthenticatedException;
/**
* GitHub: https://github.com/Mohist-Community/SodionAuth
* <p>
* Project page: https://gitea.e-loli.com/SodionAuth/SodionAuth
* <p>
* Bukkit: Unknown
* <p>
* Spigot: https://www.spigotmc.org/resources/sodionauth.76944/
*/
public class SodionAuthHook implements AuthPlugin<ProxiedPlayer> {
private final FastLoginBungee plugin;
public SodionAuthHook(FastLoginBungee plugin) {
this.plugin = plugin;
}
@Override
public boolean forceLogin(ProxiedPlayer player) {
try {
SodionAuthApi.login(new BungeePlayer(player));
} catch (AuthenticatedException e) {
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
return false;
}
return true;
}
@Override
public boolean forceRegister(ProxiedPlayer player, String password) {
try{
return SodionAuthApi.register(new BungeePlayer(player), password);
} catch (UnsupportedOperationException e){
plugin.getLog().warn("Currently SodionAuth is not accepting forceRegister, " +
"It may be caused by unsupported AuthBackend");
return false;
}
}
@Override
public boolean isRegistered(String playerName) {
return SodionAuthApi.isRegistered(playerName);
}
}

View File

@@ -1,9 +0,0 @@
package com.github.games647.fastlogin.bungee.hook.floodgate;
import java.util.UUID;
public interface FloodgateHook {
boolean isBedrockPlayer(UUID uuid);
}

View File

@@ -1,14 +0,0 @@
package com.github.games647.fastlogin.bungee.hook.floodgate;
import org.geysermc.floodgate.FloodgateAPI;
import java.util.UUID;
public class FloodgateV1Hook implements FloodgateHook {
@Override
public boolean isBedrockPlayer(UUID uuid) {
return FloodgateAPI.isBedrockPlayer(uuid);
}
}

View File

@@ -1,21 +0,0 @@
package com.github.games647.fastlogin.bungee.hook.floodgate;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.InstanceHolder;
import java.util.UUID;
public class FloodgateV2Hook implements FloodgateHook {
private FloodgateApi floodgateApi;
public FloodgateV2Hook() {
this.floodgateApi = InstanceHolder.getApi();
}
@Override
public boolean isBedrockPlayer(UUID uuid) {
return floodgateApi.isFloodgatePlayer(uuid);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,13 +28,12 @@ package com.github.games647.fastlogin.bungee.listener;
import com.github.games647.craftapi.UUIDAdapter;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.bungee.hook.floodgate.FloodgateHook;
import com.github.games647.fastlogin.bungee.hook.floodgate.FloodgateV1Hook;
import com.github.games647.fastlogin.bungee.hook.floodgate.FloodgateV2Hook;
import com.github.games647.fastlogin.bungee.task.AsyncPremiumCheck;
import com.github.games647.fastlogin.bungee.task.FloodgateAuthTask;
import com.github.games647.fastlogin.bungee.task.ForceLoginTask;
import com.github.games647.fastlogin.core.RateLimiter;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.google.common.base.Throwables;
@@ -54,10 +53,11 @@ import net.md_5.bungee.api.event.ServerConnectedEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.connection.LoginResult;
import net.md_5.bungee.connection.LoginResult.Property;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import net.md_5.bungee.protocol.Property;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -80,14 +80,12 @@ public class ConnectListener implements Listener {
Field uuidField = InitialHandler.class.getDeclaredField(UUID_FIELD_NAME);
uuidField.setAccessible(true);
setHandle = lookup.unreflectSetter(uuidField);
} catch (ClassNotFoundException classNotFoundException) {
} catch (ReflectiveOperationException reflectiveOperationException) {
Logger logger = LoggerFactory.getLogger(ConnectListener.class);
logger.error(
"Cannot find Bungee initial handler; Disabling premium UUID and skin won't work.",
classNotFoundException
reflectiveOperationException
);
} catch (ReflectiveOperationException reflectiveOperationException) {
reflectiveOperationException.printStackTrace();
}
uniqueIdSetter = setHandle;
@@ -96,31 +94,21 @@ public class ConnectListener implements Listener {
private final FastLoginBungee plugin;
private final RateLimiter rateLimiter;
private final Property[] emptyProperties = {};
private final FloodgateHook floodgateHook;
public ConnectListener(FastLoginBungee plugin, RateLimiter rateLimiter, String floodgateVersion) {
public ConnectListener(FastLoginBungee plugin, RateLimiter rateLimiter) {
this.plugin = plugin;
this.rateLimiter = rateLimiter;
// Get the appropriate floodgate api hook based on the version
if (floodgateVersion.startsWith("1")) {
this.floodgateHook = new FloodgateV1Hook();
} else if (floodgateVersion.startsWith("2")) {
this.floodgateHook = new FloodgateV2Hook();
} else {
this.floodgateHook = null;
}
}
@EventHandler
public void onPreLogin(PreLoginEvent preLoginEvent) {
PendingConnection connection = preLoginEvent.getConnection();
if (preLoginEvent.isCancelled() || isBedrockPlayer(connection.getUniqueId())) {
if (preLoginEvent.isCancelled()) {
return;
}
if (!rateLimiter.tryAcquire()) {
plugin.getLog().warn("Join limit hit - Ignoring player {}", connection);
plugin.getLog().warn("Simple Anti-Bot join limit - Ignoring {}", connection);
return;
}
@@ -171,8 +159,8 @@ public class ConnectListener implements Listener {
private void setOfflineId(InitialHandler connection, String username) {
try {
final UUID oldPremiumId = connection.getUniqueId();
final UUID offlineUUID = UUIDAdapter.generateOfflineId(username);
UUID oldPremiumId = connection.getUniqueId();
UUID offlineUUID = UUIDAdapter.generateOfflineId(username);
// BungeeCord only allows setting the UUID in PreLogin events and before requesting online mode
// However if online mode is requested, it will override previous values
@@ -184,7 +172,7 @@ public class ConnectListener implements Listener {
} catch (Exception ex) {
plugin.getLog().error("Failed to set offline uuid of {}", username, ex);
} catch (Throwable throwable) {
// throw remaining exceptions like outofmemory that we shouldn't handle ourself
// throw remaining exceptions like out of memory that we shouldn't handle ourselves
Throwables.throwIfUnchecked(throwable);
}
}
@@ -194,6 +182,16 @@ public class ConnectListener implements Listener {
ProxiedPlayer player = serverConnectedEvent.getPlayer();
Server server = serverConnectedEvent.getServer();
FloodgateService floodgateService = plugin.getFloodgateService();
if (floodgateService != null) {
FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(player.getUniqueId());
if (floodgatePlayer != null) {
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer, server);
plugin.getScheduler().runAsync(floodgateAuthTask);
return;
}
}
BungeeLoginSession session = plugin.getSession().get(player.getPendingConnection());
if (session == null) {
return;
@@ -212,16 +210,4 @@ public class ConnectListener implements Listener {
plugin.getSession().remove(player.getPendingConnection());
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
}
private boolean isBedrockPlayer(UUID correctedUUID) {
// Floodgate will set a correct UUID at the beginning of the PreLoginEvent
// and will cancel the online mode login for those players
// Therefore we just ignore those
if (floodgateHook == null || correctedUUID == null) {
// Also ignore if not set by floodgate or any other plugin
return false;
}
return this.floodgateHook.isBedrockPlayer(correctedUUID);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,6 +29,7 @@ import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.bungee.task.AsyncToggleMessage;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
import com.github.games647.fastlogin.core.message.NamespaceKey;
import com.github.games647.fastlogin.core.message.SuccessMessage;
@@ -68,7 +69,7 @@ public class PluginMessageListener implements Listener {
}
//the client shouldn't be able to read the messages in order to know something about server internal states
//moreover the client shouldn't be able fake a running premium check by sending the result message
//moreover the client shouldn't be able to fake a running premium check by sending the result message
pluginMessageEvent.setCancelled(true);
if (!(pluginMessageEvent.getSender() instanceof Server)) {
@@ -115,7 +116,15 @@ public class PluginMessageListener implements Listener {
}
private void onSuccessMessage(ProxiedPlayer forPlayer) {
if (forPlayer.getPendingConnection().isOnlineMode()) {
boolean shouldPersist = forPlayer.getPendingConnection().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
BungeeLoginSession loginSession = plugin.getSession().get(forPlayer.getPendingConnection());

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -49,7 +49,7 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
public AsyncPremiumCheck(FastLoginBungee plugin, PreLoginEvent preLoginEvent, PendingConnection connection,
String username) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
this.plugin = plugin;
this.preLoginEvent = preLoginEvent;
@@ -78,7 +78,7 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
@Override
public void requestPremiumLogin(BungeeLoginSource source, StoredProfile profile,
String username, boolean registered) {
source.setOnlineMode();
source.enableOnlinemode();
plugin.getSession().put(source.getConnection(), new BungeeLoginSession(username, registered, profile));
String ip = source.getAddress().getAddress().getHostAddress();

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -0,0 +1,79 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.task;
import java.net.InetSocketAddress;
import java.util.UUID;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.FloodgateManagement;
public class FloodgateAuthTask
extends FloodgateManagement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> {
private final Server server;
public FloodgateAuthTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core, ProxiedPlayer player,
FloodgatePlayer floodgatePlayer, Server server) {
super(core, player, floodgatePlayer);
this.server = server;
}
@Override
protected void startLogin() {
BungeeLoginSession session = new BungeeLoginSession(player.getName(), isRegistered, profile);
core.getPlugin().getSession().put(player.getPendingConnection(), session);
// run login task
Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, server, session,
isAutoAuthAllowed(autoLoginFloodgate));
core.getPlugin().getScheduler().runAsync(forceLoginTask);
}
@Override
protected String getName(ProxiedPlayer player) {
return player.getName();
}
@Override
protected UUID getUUID(ProxiedPlayer player) {
return player.getUniqueId();
}
@Override
protected InetSocketAddress getAddress(ProxiedPlayer player) {
return player.getAddress();
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -49,11 +49,21 @@ public class ForceLoginTask
private final Server server;
//treat player as if they had a premium account, even when they don't
//use for Floodgate auto login/register
private final boolean forcedOnlineMode;
public ForceLoginTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core,
ProxiedPlayer player, Server server, BungeeLoginSession session) {
ProxiedPlayer player, Server server, BungeeLoginSession session, boolean forcedOnlineMode) {
super(core, player, session);
this.server = server;
this.forcedOnlineMode = forcedOnlineMode;
}
public ForceLoginTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core, ProxiedPlayer player,
Server server, BungeeLoginSession session) {
this(core, player, server, session, false);
}
@Override
@@ -116,6 +126,6 @@ public class ForceLoginTask
@Override
public boolean isOnlineMode() {
return player.getPendingConnection().isOnlineMode();
return forcedOnlineMode || player.getPendingConnection().isOnlineMode();
}
}

View File

@@ -13,6 +13,9 @@ softDepends:
- BungeeAuth
- BungeeCordAuthenticatorBungee
- SodionAuth
# Bedrock Player Bridge
- Geyser-BungeeCord
- floodgate
description: |
${project.description}

View File

@@ -4,7 +4,7 @@
The MIT License (MIT)
Copyright (c) 2015-2021 <Your name and contributors>
Copyright (c) 2015-2022 games647 and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -52,11 +52,17 @@
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<!-- Floodgate -->
<repository>
<id>nukkitx-snapshot</id>
<url>https://repo.nukkitx.com/maven-snapshots/</url>
<id>opencollab-snapshot</id>
<url>https://repo.opencollab.dev/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
@@ -67,21 +73,29 @@
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.1</version>
<version>4.0.3</version>
<exclusions>
<!-- HikariCP uses an old version of this API that has a typo in the service interface -->
<!-- We will use the api provided by the jdk14 dependency -->
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Logging framework implements slf4j which is required by hikari-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.30</version>
<version>2.0.0-alpha7</version>
</dependency>
<!-- snakeyaml is present in Bungee, Spigot, Cauldron and so we could use this independent implementation -->
<!-- snakeyaml is present in Bungee, Spigot, Cauldron, so we could use this independent implementation -->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
<version>1.12-SNAPSHOT</version>
<version>1.16-R0.4</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
@@ -94,7 +108,39 @@
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>2.0-SNAPSHOT</version>
<version>${floodgate.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.geysermc.cumulus</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Bedrock player bridge -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>core</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- We need the API, but it was excluded above -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>geyser-api</artifactId>
<version>${geyser.version}</version>
<scope>provided</scope>
</dependency>
@@ -102,21 +148,44 @@
<dependency>
<groupId>com.github.games647</groupId>
<artifactId>craftapi</artifactId>
<version>0.4</version>
<version>0.5.3</version>
</dependency>
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee) -->
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee, Velocity) -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>17.0</version>
<scope>provided</scope>
<!-- Old version for velocity -->
<version>25.1-jre</version>
<!-- Exclude compile time dependencies not marked as such on upstream -->
<exclusions>
<exclusion>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.j2objc</groupId>
<artifactId>j2objc-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
<version>2.9.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,21 +25,16 @@
*/
package com.github.games647.fastlogin.core;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
/**
* This limits the number of threads that are used at maximum. Thread creation can be very heavy for the CPU and
* context switching between threads too. However we need many threads for blocking HTTP and database calls.
* Nevertheless this number can be further limited, because the number of actually working database threads
* context switching between threads too. However, we need many threads for blocking HTTP and database calls.
* Nevertheless, this number can be further limited, because the number of actually working database threads
* is limited by the size of our database pool. The goal is to separate concerns into processing and blocking only
* threads.
*/
@@ -53,7 +48,9 @@ public class AsyncScheduler {
// 30 threads are still too many - the optimal solution is to separate into processing and blocking threads
// where processing threads could only be max number of cores while blocking threads could be minimized using
// non-blocking I/O and a single event executor
private final ExecutorService processingPool;
private final Executor processingPool;
private final AtomicInteger currentlyRunning = new AtomicInteger();
/*
private final ExecutorService databaseExecutor = new ThreadPoolExecutor(1, 10,
@@ -61,34 +58,27 @@ public class AsyncScheduler {
new LinkedBlockingQueue<>(MAX_CAPACITY));
*/
public AsyncScheduler(Logger logger, ThreadFactory threadFactory) {
public AsyncScheduler(Logger logger, Executor processingPool) {
this.logger = logger;
processingPool = new ThreadPoolExecutor(6, 32,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(MAX_CAPACITY), threadFactory);
this.processingPool = processingPool;
}
/*
public <R> CompletableFuture<R> runDatabaseTask(Supplier<R> databaseTask) {
return CompletableFuture.supplyAsync(databaseTask, databaseExecutor)
.exceptionally(error -> {
logger.warn("Error occurred on thread pool", error);
return null;
})
// change context to the processing pool
.thenApplyAsync(r -> r, processingPool);
}
*/
public CompletableFuture<Void> runAsync(Runnable task) {
return CompletableFuture.runAsync(task, processingPool).exceptionally(error -> {
return CompletableFuture.runAsync(() -> {
currentlyRunning.incrementAndGet();
try {
task.run();
} finally {
currentlyRunning.getAndDecrement();
}
}, processingPool).exceptionally(error -> {
logger.warn("Error occurred on thread pool", error);
return null;
});
}
public void shutdown() {
MoreExecutors.shutdownAndAwaitTermination(processingPool, 1, TimeUnit.MINUTES);
// MoreExecutors.shutdownAndAwaitTermination(processingPool, 1, TimeUnit.MINUTES);
//MoreExecutors.shutdownAndAwaitTermination(databaseExecutor, 1, TimeUnit.MINUTES);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -35,7 +35,7 @@ import java.util.logging.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.impl.JDK14LoggerAdapter;
import org.slf4j.jul.JDK14LoggerAdapter;
public class CommonUtil {
@@ -70,7 +70,27 @@ public class CommonUtil {
return new String(chars);
}
public static Logger createLoggerFromJDK(java.util.logging.Logger parent) {
/**
* This creates a SLF4J logger. In the process it initializes the SLF4J service provider. This method looks
* for the provider in the plugin jar instead of in the server jar when creating a Logger. The provider is only
* initialized once, so this method should be called early.
*
* The provider is bound to the service class `SLF4JServiceProvider`. Relocating this class makes it available
* for exclusive own usage. Other dependencies will use the relocated service too, and therefore will find the
* initialized provider.
*
* @param parent JDK logger
* @return slf4j logger
*/
public static Logger initializeLoggerService(java.util.logging.Logger parent) {
// set the class loader to the plugin one to find our own SLF4J provider in the plugin jar and not in the global
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
ClassLoader pluginLoader = CommonUtil.class.getClassLoader();
Thread.currentThread().setContextClassLoader(pluginLoader);
// Trigger provider search
LoggerFactory.getLogger(parent.getName()).info("Initialize logging service");
try {
parent.setLevel(Level.ALL);
@@ -82,6 +102,9 @@ public class CommonUtil {
parent.log(Level.WARNING, "Cannot create slf4j logging adapter", reflectEx);
parent.log(Level.WARNING, "Creating logger instance manually...");
return LoggerFactory.getLogger(parent.getName());
} finally {
// restore previous class loader
Thread.currentThread().setContextClassLoader(oldLoader);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,42 +25,8 @@
*/
package com.github.games647.fastlogin.core;
/**
* Limit the number of requests with a maximum size. Each requests expires after the specified time making it available
* for another request.
*/
public class RateLimiter {
@FunctionalInterface
public interface RateLimiter {
private final long[] requests;
private final long expireTime;
private int position;
public RateLimiter(int maxLimit, long expireTime) {
this.requests = new long[maxLimit];
this.expireTime = expireTime;
}
/**
* Ask if access is allowed. If so register the request.
*
* @return true if allowed - false otherwise without any side effects
*/
public boolean tryAcquire() {
// current time millis is not monotonic - it can jump back depending on user choice or NTP
long now = System.nanoTime() / 1_000_000;
// after this the request should be expired
long toBeExpired = now - expireTime;
synchronized (this) {
// having synchronized will limit the amount of concurrency a lot
long oldest = requests[position];
if (oldest < toBeExpired) {
requests[position] = now;
position = (position + 1) % requests.length;
return true;
}
return false;
}
}
boolean tryAcquire();
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -113,7 +113,7 @@ public class StoredProfile extends Profile {
}
@Override
public boolean equals(Object o) {
public synchronized boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof StoredProfile)) return false;
if (!super.equals(o)) return false;
@@ -123,7 +123,7 @@ public class StoredProfile extends Profile {
}
@Override
public int hashCode() {
public synchronized int hashCode() {
return Objects.hash(super.hashCode(), rowId, premium, lastIp, lastLogin);
}

View File

@@ -0,0 +1,147 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core;
import com.google.common.base.Ticker;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
/**
* Limit the number of requests with a maximum size. Each requests expire after the specified time making it available
* for another request.
*/
public class TickingRateLimiter implements RateLimiter {
private final Ticker ticker;
// amount of milliseconds to expire
private final long expireTime;
// total request limit
private final int requestLimit;
private final Deque<TimeRecord> records;
private int totalRequests;
public TickingRateLimiter(Ticker ticker, int maxLimit, long expireTime) {
this.ticker = ticker;
this.requestLimit = maxLimit;
this.expireTime = expireTime;
records = new ArrayDeque<>(10);
}
/**
* Ask if access is allowed. If so register the request.
*
* @return true if allowed - false otherwise without any side effects
*/
@Override
public boolean tryAcquire() {
// current time millis is not monotonic - it can jump back depending on user choice or NTP
long nowMilli = ticker.read() / 1_000_000;
synchronized (this) {
// having synchronized will limit the amount of concurrency a lot
TimeRecord oldest = records.peekFirst();
if (oldest != null && oldest.hasExpired(nowMilli)) {
records.pop();
totalRequests -= oldest.getRequestCount();
}
// total requests reached block any further requests
if (totalRequests >= requestLimit) {
return false;
}
TimeRecord latest = records.peekLast();
if (latest == null) {
// empty list - add new record
records.add(new TimeRecord(nowMilli, expireTime));
totalRequests++;
return true;
}
int res = latest.compareTo(nowMilli);
if (res < 0) {
// now is before than the record means time jumps
throw new IllegalStateException("Time jumped back");
}
if (res == 0) {
// same minute record
latest.hit();
totalRequests++;
return true;
}
// now is one minute newer
records.add(new TimeRecord(nowMilli, expireTime));
totalRequests++;
return true;
}
}
private static class TimeRecord implements Comparable<Long> {
private final long firstMinuteRecord;
private final long expireTime;
private int count;
public TimeRecord(long firstMinuteRecord, long expireTime) {
this.firstMinuteRecord = firstMinuteRecord;
this.expireTime = expireTime;
this.count = 1;
}
public void hit() {
count++;
}
public int getRequestCount() {
return count;
}
public boolean hasExpired(long now) {
return firstMinuteRecord + expireTime <= now;
}
@Override
public int compareTo(Long other) {
if (other < firstMinuteRecord) {
return -1;
}
if (other > firstMinuteRecord + TimeUnit.MINUTES.toMillis(1)) {
return +1;
}
return 0;
}
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -72,7 +72,7 @@ public interface AuthPlugin<P> {
/**
* Checks whether an account exists for this player name.
*
* This check should check if a cracked player account exists
* This check should check if a cracked player account exists,
* so we can be sure the premium player doesn't steal the account
* of that player.
*

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,111 +0,0 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name 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.hooks;
import java.io.IOException;
import java.util.Optional;
import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSource;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
public class FloodgateHook<P extends C, C, S extends LoginSource> {
private final FastLoginCore<P, C, ?> core;
public FloodgateHook(FastLoginCore<P, C, ?> core) {
this.core = core;
}
/**
* Check if the player's name conflicts an existing Java player's name, and
* kick them if it does
*
* @param username the name of the player
* @param source an instance of LoginSource
*/
public void checkFloodgateNameConflict(String username, LoginSource source, FloodgatePlayer floodgatePlayer) {
String allowConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
// check if the Bedrock player is linked to a Java account
boolean isLinked = ((FloodgatePlayer) floodgatePlayer).getLinkedPlayer() != null;
if (allowConflict.equals("false")
|| allowConflict.equals("linked") && !isLinked) {
// check for conflicting Premium Java name
Optional<Profile> premiumUUID = Optional.empty();
try {
premiumUUID = core.getResolver().findProfile(username);
} catch (IOException | RateLimitException e) {
core.getPlugin().getLog().error(
"Could not check wether Floodgate Player {}'s name conflicts a premium Java player's name.",
username);
try {
source.kick("Could not check if your name conflicts an existing Java Premium Player's name");
} catch (Exception e1) {
core.getPlugin().getLog().error("Could not kick Player {}", username);
}
}
if (premiumUUID.isPresent()) {
core.getPlugin().getLog().info("Bedrock Player {}'s name conflicts an existing Java Premium Player's name",
username);
try {
source.kick("Your name conflicts an existing Java Premium Player's name");
} catch (Exception e) {
core.getPlugin().getLog().error("Could not kick Player {}", username);
}
}
} else {
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
}
}
/**
* The FloodgateApi does not support querying players by name, so this function
* iterates over every online FloodgatePlayer and checks if the requested
* username can be found
*
* @param username the name of the player
* @return FloodgatePlayer if found, null otherwise
*/
public FloodgatePlayer getFloodgatePlayer(String username) {
if (core.getPlugin().isPluginInstalled("floodgate")) {
for (FloodgatePlayer floodgatePlayer : FloodgateApi.getInstance().getPlayers()) {
if (floodgatePlayer.getUsername().equals(username)) {
return floodgatePlayer;
}
}
}
return null;
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -0,0 +1,135 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.hooks.bedrock;
import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSource;
import java.io.IOException;
import java.util.Optional;
import java.util.UUID;
/**
* @param <B> is an instance of either FloodgatePlayer or GeyserSession
*/
public abstract class BedrockService<B> {
protected final FastLoginCore<?, ?, ?> core;
protected final String allowConflict;
public BedrockService(FastLoginCore<?, ?, ?> core) {
this.core = core;
this.allowConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
}
/**
* Perform every packet level check needed on a Bedrock player.
*
* @param username the name of the player
* @param source an instance of LoginSource
* @return true if Java specific checks can be skipped
*/
public abstract boolean performChecks(String username, LoginSource source);
/**
* Check if the player's name conflicts an existing Java player's name, and kick
* them if it does
*
* @param username the name of the player
* @param source an instance of LoginSource
*/
protected void checkNameConflict(String username, LoginSource source) {
// check for conflicting Premium Java name
Optional<Profile> premiumUUID = Optional.empty();
try {
premiumUUID = core.getResolver().findProfile(username);
} catch (IOException ioEx) {
core.getPlugin().getLog().error(
"Could not check whether Bedrock Player {}'s name conflicts a premium Java player's name.",
username);
kickPlayer(source, username, "Could not check if your name conflicts an existing " +
"premium Java account's name. This is usually a serverside error.");
} catch (RateLimitException rateLimitException) {
core.getPlugin().getLog().warn("Mojang API rate limit hit");
kickPlayer(source, username, "Could not check if your name conflicts an existing premium " +
"Java account's name. Try again in a few minutes");
}
if (premiumUUID.isPresent()) {
core.getPlugin().getLog().info("Bedrock Player {}'s name conflicts an existing premium Java account's name",
username);
kickPlayer(source, username, "Your name conflicts an existing premium Java account's name");
}
}
private void kickPlayer(LoginSource source, String username, String message) {
try {
source.kick(message);
} catch (Exception ex) {
core.getPlugin().getLog().error("Could not kick Player {}", username, ex);
}
}
/**
* The Floodgate / Geyser API does not support querying players by name, so this function
* iterates over every online Bedrock Player and checks if the requested
* username can be found
* <br>
* <i>Falls back to non-prefixed name checks, if ProtocolLib is installed</i>
*
* @param prefixedUsername the name of the player with the prefix appended
* @return Bedrock Player if found, null otherwise
*/
public B getBedrockPlayer(String prefixedUsername) {
return null;
}
public B getBedrockPlayer(UUID uuid) {
return null;
}
public boolean isBedrockPlayer(UUID uuid) {
return getBedrockPlayer(uuid) != null;
}
public boolean isBedrockConnection(String username) {
return getBedrockPlayer(username) != null;
}
/**
* Checks if a profile's name starts with the Floodgate prefix, if it's available
* @param profile profile of the connecting player
* @return true if the username is forbidden
*/
public boolean isUsernameForbidden(StoredProfile profile) {
return false;
}
}

View File

@@ -0,0 +1,136 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.hooks.bedrock;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSource;
import java.util.Locale;
import java.util.UUID;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
public class FloodgateService extends BedrockService<FloodgatePlayer> {
private final FloodgateApi floodgate;
public FloodgateService(FloodgateApi floodgate, FastLoginCore<?, ?, ?> core) {
super(core);
this.floodgate = floodgate;
}
/**
* Checks if a config entry (related to Floodgate) is valid. <br>
* Writes to Log if the value is invalid.
* <p>
* This should be used for:
* <ul>
* <li>allowFloodgateNameConflict
* <li>autoLoginFloodgate
* <li>autoRegisterFloodgate
* </ul>
* </p>
*
* @param key the key of the entry in config.yml
* @return <b>true</b> if the entry's value is "true", "false", or "linked"
*/
public boolean isValidFloodgateConfigString(String key) {
String value = core.getConfig().get(key).toString().toLowerCase(Locale.ENGLISH);
if (!value.equals("true") && !value.equals("linked") && !value.equals("false") && !value.equals("no-conflict")) {
core.getPlugin().getLog().error("Invalid value detected for {} in FastLogin/config.yml.", key);
return false;
}
return true;
}
@Override
public boolean isUsernameForbidden(StoredProfile profile) {
String playerPrefix = floodgate.getPlayerPrefix();
return profile.getName().startsWith(playerPrefix) && !playerPrefix.isEmpty();
}
@Override
public boolean performChecks(String username, LoginSource source) {
// check if the Bedrock player is linked to a Java account
FloodgatePlayer floodgatePlayer = getBedrockPlayer(username);
boolean isLinked = floodgatePlayer.getLinkedPlayer() != null;
if ("false".equals(allowConflict)
|| "linked".equals(allowConflict) && !isLinked) {
super.checkNameConflict(username, source);
} else {
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
}
//Floodgate users don't need Java specific checks
return true;
}
/**
* The FloodgateApi does not support querying players by name, so this function
* iterates over every online FloodgatePlayer and checks if the requested
* username can be found
* <br>
* <i>Falls back to non-prefixed name checks, if ProtocolLib is installed</i>
*
* @param prefixedUsername the name of the player with the prefix appended
* @return FloodgatePlayer if found, null otherwise
*/
public FloodgatePlayer getBedrockPlayer(String prefixedUsername) {
//prefixes are broken with ProtocolLib, so fall back to name checks without prefixes
//this should be removed if #493 gets fixed
if (core.getPlugin().isPluginInstalled("ProtocolLib")) {
for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) {
if (floodgatePlayer.getUsername().equals(prefixedUsername)) {
return floodgatePlayer;
}
}
return null;
}
for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) {
if (floodgatePlayer.getCorrectUsername().equals(prefixedUsername)) {
return floodgatePlayer;
}
}
return null;
}
public FloodgatePlayer getBedrockPlayer(UUID uuid) {
return floodgate.getPlayer(uuid);
}
public boolean isBedrockPlayer(UUID uuid) {
return getBedrockPlayer(uuid) != null;
}
public boolean isBedrockConnection(String username) {
return getBedrockPlayer(username) != null;
}
}

View File

@@ -0,0 +1,75 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.hooks.bedrock;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSource;
import java.util.UUID;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.auth.AuthType;
public class GeyserService extends BedrockService<GeyserSession> {
private final GeyserImpl geyser;
private final FastLoginCore<?, ?, ?> core;
private final AuthType authType;
public GeyserService(GeyserImpl geyser, FastLoginCore<?, ?, ?> core) {
super(core);
this.geyser = geyser;
this.core = core;
this.authType = GeyserImpl.getInstance().getConfig().getRemote().getAuthType();
}
@Override
public boolean performChecks(String username, LoginSource source) {
// AuthType.FLOODGATE will be handled by FloodgateService
if (authType == AuthType.ONLINE) {
// authenticate everyone, as if they were Java players, since they have signed
// in through Mojang
return false;
}
if ("true".equals(allowConflict)) {
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
} else {
super.checkNameConflict(username, source);
}
return true;
}
@Override
public GeyserSession getBedrockPlayer(String username) {
return geyser.connectionByName(username);
}
@Override
public GeyserSession getBedrockPlayer(UUID uuid) {
return geyser.connectionByUuid(uuid);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -0,0 +1,77 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.mojang;
import com.github.games647.craftapi.model.auth.Verification;
import com.github.games647.craftapi.resolver.MojangResolver;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.util.Optional;
/**
* An extension to {@link MojangResolver} which allows connection using transparent reverse proxies.
* The significant difference is that unlike MojangResolver from the CraftAPI implementation, which sends the "ip" parameter
* when the hostIp parameter is an IPv4 address, but skips it for IPv6, this implementation leaves out the "ip" parameter
* also for IPv4, effectively enabling transparent proxies to work.
* @author games647, Enginecrafter77
*/
public class ProxyAgnosticMojangResolver extends MojangResolver {
/**
* A formatting string containing an URL used to call the {@code hasJoined} method on mojang session servers.
*
* Formatting parameters:
* 1. The username of the player in question
* 2. The serverId of this server
*/
public static final String MOJANG_SESSIONSERVER_HASJOINED_CALL_URLFMT = "https://sessionserver.mojang.com/session/minecraft/hasJoined?username=%s&serverId=%s";
@Override
public Optional<Verification> hasJoined(String username, String serverHash, InetAddress hostIp) throws IOException
{
String url = String.format(MOJANG_SESSIONSERVER_HASJOINED_CALL_URLFMT, username, serverHash);
HttpURLConnection conn = this.getConnection(url);
int responseCode = conn.getResponseCode();
Verification verification = null;
// Mojang session servers send HTTP 204 (NO CONTENT) when the authentication seems invalid
// If that's not our case, the authentication is valid, and so we can parse the response.
if(responseCode != HttpURLConnection.HTTP_NO_CONTENT)
verification = this.parseRequest(conn, this::parseVerification);
return Optional.ofNullable(verification);
}
// Functional implementation of InputStreamAction, used in hasJoined method in parseRequest call
protected Verification parseVerification(InputStream input) throws IOException
{
return this.readJson(input, Verification.class);
}
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -27,12 +27,17 @@ package com.github.games647.fastlogin.core.shared;
import com.github.games647.craftapi.resolver.MojangResolver;
import com.github.games647.craftapi.resolver.http.RotatingProxySelector;
import com.github.games647.fastlogin.core.AuthStorage;
import com.github.games647.fastlogin.core.CommonUtil;
import com.github.games647.fastlogin.core.RateLimiter;
import com.github.games647.fastlogin.core.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.mojang.ProxyAgnosticMojangResolver;
import com.github.games647.fastlogin.core.storage.MySQLStorage;
import com.github.games647.fastlogin.core.storage.SQLStorage;
import com.github.games647.fastlogin.core.storage.SQLiteStorage;
import com.google.common.base.Ticker;
import com.google.common.net.HostAndPort;
import com.zaxxer.hikari.HikariConfig;
@@ -79,10 +84,10 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
private final Collection<UUID> pendingConfirms = new HashSet<>();
private final T plugin;
private final MojangResolver resolver = new MojangResolver();
private MojangResolver resolver;
private Configuration config;
private AuthStorage storage;
private SQLStorage storage;
private RateLimiter rateLimiter;
private PasswordGenerator<P> passwordGenerator = new DefaultPasswordGenerator<>();
private AuthPlugin<P> authPlugin;
@@ -114,17 +119,14 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
return;
}
int maxCon = config.getInt("anti-bot.connections", 200);
long expireTime = config.getLong("anti-bot.expire", 5) * 60 * 1_000L;
if (expireTime > MAX_EXPIRE_RATE) {
expireTime = MAX_EXPIRE_RATE;
}
// Initialize the resolver based on the config parameter
this.resolver = this.config.getBoolean("useProxyAgnosticResolver", false) ? new ProxyAgnosticMojangResolver() : new MojangResolver();
rateLimiter = new RateLimiter(maxCon, expireTime);
rateLimiter = createRateLimiter(config.getSection("anti-bot"));
Set<Proxy> proxies = config.getStringList("proxies")
.stream()
.map(HostAndPort::fromString)
.map(proxy -> new InetSocketAddress(proxy.getHostText(), proxy.getPort()))
.map(proxy -> new InetSocketAddress(proxy.getHost(), proxy.getPort()))
.map(sa -> new Proxy(Type.HTTP, sa))
.collect(toSet());
@@ -142,6 +144,22 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
resolver.setOutgoingAddresses(addresses);
}
private RateLimiter createRateLimiter(Configuration botSection) {
boolean enabled = botSection.getBoolean("enabled", true);
if (!enabled) {
// no-op rate limiter
return () -> true;
}
int maxCon = botSection.getInt("anti-bot.connections", 200);
long expireTime = botSection.getLong("anti-bot.expire", 5) * 60 * 1_000L;
if (expireTime > MAX_EXPIRE_RATE) {
expireTime = MAX_EXPIRE_RATE;
}
return new TickingRateLimiter(Ticker.systemTicker(), maxCon, expireTime);
}
private Configuration loadFile(String fileName) throws IOException {
ConfigurationProvider configProvider = ConfigurationProvider.getProvider(YamlConfiguration.class);
@@ -169,7 +187,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
return resolver;
}
public AuthStorage getStorage() {
public SQLStorage getStorage() {
return storage;
}
@@ -189,26 +207,37 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
}
public boolean setupDatabase() {
if (!checkDriver(config.getString("driver"))) {
String driver = config.getString("driver");
if (!checkDriver(driver)) {
return false;
}
HikariConfig databaseConfig = new HikariConfig();
databaseConfig.setDriverClassName(config.getString("driver"));
databaseConfig.setDriverClassName(driver);
String host = config.get("host", "");
int port = config.get("port", 3306);
String database = config.getString("database");
boolean useSSL = config.get("useSSL", false);
databaseConfig.setUsername(config.get("username", ""));
databaseConfig.setPassword(config.getString("password"));
databaseConfig.setConnectionTimeout(config.getInt("timeout", 30) * 1_000L);
databaseConfig.setMaxLifetime(config.getInt("lifetime", 30) * 1_000L);
storage = new AuthStorage(this, host, port, database, databaseConfig, useSSL);
if (driver.contains("sqlite")) {
storage = new SQLiteStorage(this, database, databaseConfig);
} else {
String host = config.get("host", "");
int port = config.get("port", 3306);
boolean useSSL = config.get("useSSL", false);
if (useSSL) {
databaseConfig.addDataSourceProperty("allowPublicKeyRetrieval", config.getBoolean("allowPublicKeyRetrieval", false));
databaseConfig.addDataSourceProperty("serverRSAPublicKeyFile", config.getString("ServerRSAPublicKeyFile"));
databaseConfig.addDataSourceProperty("sslMode", config.getString("sslMode", "Required"));
}
databaseConfig.setUsername(config.get("username", ""));
databaseConfig.setPassword(config.getString("password"));
storage = new MySQLStorage(this, driver, host, port, database, databaseConfig, useSSL);
}
try {
storage.createTables();
return true;
@@ -225,7 +254,8 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
} catch (ClassNotFoundException notFoundEx) {
Logger log = plugin.getLog();
log.warn("This driver {} is not supported on this platform", className);
log.warn("Please choose MySQL (Spigot+BungeeCord), SQLite (Spigot+Sponge) or MariaDB (Sponge)", notFoundEx);
log.warn("Please choose either MySQL (Spigot, BungeeCord), SQLite (Spigot, Sponge) or " +
"MariaDB (Sponge, Velocity)", notFoundEx);
}
return false;

View File

@@ -0,0 +1,178 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.shared;
import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Optional;
import java.util.UUID;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
public abstract class FloodgateManagement<P extends C, C, L extends LoginSession, T extends PlatformPlugin<C>>
implements Runnable {
protected final FastLoginCore<P, C, T> core;
protected final P player;
private final FloodgatePlayer floodgatePlayer;
private final String username;
//config.yml values that might be accessed by multiple methods
protected final String autoLoginFloodgate;
protected final String autoRegisterFloodgate;
protected final String allowNameConflict;
//variables initialized through run() and accesses by subclasss
protected boolean isRegistered;
protected StoredProfile profile;
protected boolean isLinked;
public FloodgateManagement(FastLoginCore<P, C, T> core, P player, FloodgatePlayer floodgatePlayer) {
this.core = core;
this.player = player;
this.floodgatePlayer = floodgatePlayer;
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();
}
@Override
public void run() {
core.getPlugin().getLog().info("Player {} is connecting through Geyser Floodgate.", username);
// check if the Bedrock player is linked to a Java account
isLinked = floodgatePlayer.getLinkedPlayer() != null;
//this happens on Bukkit if it's connected to Bungee
//if that's the case, players will be logged in via plugin messages
if (core.getStorage() == null) {
return;
}
profile = core.getStorage().loadProfile(username);
AuthPlugin<P> authPlugin = core.getAuthPluginHook();
try {
//maybe Bungee without auth plugin
if (authPlugin == null) {
if (profile != null) {
isRegistered = profile.isPremium();
} else {
isRegistered = false;
}
} else {
isRegistered = authPlugin.isRegistered(username);
}
} catch (Exception ex) {
core.getPlugin().getLog().error(
"An error has occured while checking if player {} is registered",
username, ex);
return;
}
//decide if checks should be made for conflicting Java player names
if (isNameCheckRequired()) {
// check for conflicting Premium Java name
Optional<Profile> premiumUUID = Optional.empty();
try {
premiumUUID = core.getResolver().findProfile(username);
} catch (IOException | RateLimitException e) {
core.getPlugin().getLog().error(
"Could not check whether Floodgate Player {}'s name conflicts a premium Java account's name.",
username, e);
return;
}
//stop execution if player's name is conflicting
if (premiumUUID.isPresent()) {
return;
}
}
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());
}
//start Bukkit/Bungee specific tasks
startLogin();
}
/**
* Decide if the player can be automatically registered or logged in.<br>
* The config option 'non-conflicting' is ignored by this function, as name
* conflicts are checked by a different part of the code.
*
* @param configValue the value of either 'autoLoginFloodgate' or
* 'autoRegisterFloodgate' from config.yml
* @return true if the Player can be registered automatically
*/
protected boolean isAutoAuthAllowed(String configValue) {
return "true".equals(configValue)
|| "no-conflict".equals(configValue) // this was checked before
|| ("linked".equals(configValue) && isLinked);
}
/**
* Decides wether checks for conflicting Java names should be made
* @return ture if an API call to Mojang is needed
*/
private boolean isNameCheckRequired() {
//linked players have the same name as their Java profile
//OR
//if allowNameConflict is 'false' or 'linked' and the player had a conflicting
//name, than they would have been kicked in FloodgateHook#checkNameConflict
if (isLinked || !"true".equals(allowNameConflict)) {
return false;
}
//autoRegisterFloodgate should only be checked if then player is not yet registered
if (!isRegistered && "no-conflict".equals(autoRegisterFloodgate)) {
return true;
}
return "no-conflict".equals(autoLoginFloodgate);
}
protected abstract void startLogin();
protected abstract String getName(P player);
protected abstract UUID getUUID(P player);
protected abstract InetSocketAddress getAddress(P player);
}

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,7 +25,7 @@
*/
package com.github.games647.fastlogin.core.shared;
import com.github.games647.fastlogin.core.AuthStorage;
import com.github.games647.fastlogin.core.storage.SQLStorage;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
@@ -55,7 +55,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
return;
}
AuthStorage storage = core.getStorage();
SQLStorage storage = core.getStorage();
StoredProfile playerProfile = session.getProfile();
try {
if (isOnlineMode()) {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,25 +29,23 @@ import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.hooks.FloodgateHook;
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import java.util.Optional;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import net.md_5.bungee.config.Configuration;
public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
protected final FastLoginCore<P, C, ?> core;
protected final AuthPlugin<P> authHook;
private final FloodgateHook<P, C, ?> floodgateHook;
private final BedrockService<?> bedrockService;
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook) {
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook, BedrockService<?> bedrockService) {
this.core = core;
this.authHook = authHook;
this.floodgateHook = new FloodgateHook<>(core);
this.bedrockService = bedrockService;
}
public void onLogin(String username, S source) {
@@ -57,13 +55,14 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
return;
}
//check if the player is connecting through Floodgate
FloodgatePlayer floodgatePlayer = floodgateHook.getFloodgatePlayer(username);
if (floodgatePlayer != null) {
floodgateHook.checkFloodgateNameConflict(username, source, floodgatePlayer);
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)) {
return;
}
}
callFastLoginPreLoginEvent(username, source, profile);
Configuration config = core.getConfig();
@@ -76,7 +75,9 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
core.getPlugin().getLog().info("Requesting premium login for registered player: {}", username);
requestPremiumLogin(source, profile, username, true);
} else {
startCrackedSession(source, profile, username);
if (isValidUsername(source, profile)) {
startCrackedSession(source, profile, username);
}
}
} else {
if (core.getPendingLogin().remove(ip + username) != null && config.get("secondAttemptCracked", false)) {
@@ -114,6 +115,16 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
}
}
protected boolean isValidUsername(LoginSource source, StoredProfile profile) throws Exception {
if (bedrockService != null && bedrockService.isUsernameForbidden(profile)) {
core.getPlugin().getLog().info("Floodgate Prefix detected on cracked player");
source.kick("Your username contains illegal characters");
return false;
}
return true;
}
private boolean checkPremiumName(S source, String username, StoredProfile profile) throws Exception {
core.getPlugin().getLog().info("GameProfile {} uses a premium username", username);
if (core.getConfig().get("autoRegister", false) && (authHook == null || !authHook.isRegistered(username))) {

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,6 +26,7 @@
package com.github.games647.fastlogin.core.shared;
import com.github.games647.fastlogin.core.StoredProfile;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import java.util.UUID;
@@ -91,7 +92,7 @@ public abstract class LoginSession {
@Override
public synchronized String toString() {
return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("profile", profile)
.add("requestUsername", requestUsername)
.add("username", username)

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +29,7 @@ import java.net.InetSocketAddress;
public interface LoginSource {
void setOnlineMode() throws Exception;
void enableOnlinemode() throws Exception;
void kick(String message) throws Exception;

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,6 +26,7 @@
package com.github.games647.fastlogin.core.shared;
import com.github.games647.fastlogin.core.AsyncScheduler;
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.nio.file.Path;
@@ -53,6 +54,8 @@ public interface PlatformPlugin<C> {
}
}
BedrockService<?> getBedrockService();
default ThreadFactory getThreadFactory() {
return new ThreadFactoryBuilder()
.setNameFormat(getName() + " Pool Thread #%1$d")

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,6 +28,9 @@ package com.github.games647.fastlogin.core.shared.event;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.LoginSession;
/**
* This event fires if the plugin performs an auto login on the platform where the login plugin is.
*/
public interface FastLoginAutoLoginEvent extends FastLoginCancellableEvent {
LoginSession getSession();
StoredProfile getProfile();

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,6 +28,9 @@ package com.github.games647.fastlogin.core.shared.event;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.LoginSource;
/**
* This action represents the login attempt of a player before the plugin makes any online mode actions.
*/
public interface FastLoginPreLoginEvent {
String getUsername();

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -27,6 +27,9 @@ package com.github.games647.fastlogin.core.shared.event;
import com.github.games647.fastlogin.core.StoredProfile;
/**
* This even represents the opt-in premium status change by request.
*/
public interface FastLoginPremiumToggleEvent {
StoredProfile getProfile();

View File

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

View File

@@ -0,0 +1,94 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 games647 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.storage;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.zaxxer.hikari.HikariConfig;
public class MySQLStorage extends SQLStorage {
public MySQLStorage(FastLoginCore<?, ?, ?> core, String driver, String host, int port, String database,
HikariConfig config,boolean useSSL) {
super(core,
buildJDBCUrl(driver, host, port, database),
setParams(config, useSSL));
}
private static String buildJDBCUrl(String driver, String host, int port, String database) {
String protocol = "mysql";
if (driver.contains("mariadb")) {
protocol = "mariadb";
}
return protocol + "://" + host + ':' + port + '/' + database;
}
private static HikariConfig setParams(HikariConfig config, 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);
// enable MySQL specific optimizations
addPerformanceProperties(config);
return config;
}
private static void addPerformanceProperties(HikariConfig config) {
// disabled by default - will return the same prepared statement instance
config.addDataSourceProperty("cachePrepStmts", true);
// default prepStmtCacheSize 25 - amount of cached statements
config.addDataSourceProperty("prepStmtCacheSize", 250);
// default prepStmtCacheSqlLimit 256 - length of SQL
config.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
// default false - available in newer versions caches the statements server-side
config.addDataSourceProperty("useServerPrepStmts", true);
// default false - prefer use of local values for autocommit and
// transaction isolation (alwaysSendSetIsolation) should only be enabled if always use the set* methods
// instead of raw SQL
// https://forums.mysql.com/read.php?39,626495,626512
config.addDataSourceProperty("useLocalSessionState", true);
// rewrite batched statements to a single statement, adding them behind each other
// only useful for addBatch statements and inserts
config.addDataSourceProperty("rewriteBatchedStatements", true);
// cache result metadata
config.addDataSourceProperty("cacheResultSetMetadata", true);
// cache results of show variables and collation per URL
config.addDataSourceProperty("cacheServerConfiguration", true);
// default false - set auto commit only if not matching
config.addDataSourceProperty("elideSetAutoCommits", true);
// default true - internal timers for idle calculation -> removes System.getCurrentTimeMillis call per query
// Some platforms are slow on this and it could affect the throughput about 3% according to MySQL
// performance gems presentation
// In our case it can be useful to see the time in error messages
// config.addDataSourceProperty("maintainTimeStats", false);
}
}

Some files were not shown because too many files have changed in this diff Show More